Make find_thread_ptid lookup thread map instead of iterate
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
82704155 2 Copyright (C) 1994-2019 Free Software Foundation, Inc.
252b5132
RH
3 Written by Ian Lance Taylor, Cygnus Support
4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "sysdep.h"
df7b86aa 23#include <stdio.h>
88c1242d 24#include "disassemble.h"
b9c361e0 25#include "elf-bfd.h"
94caa966 26#include "elf/ppc.h"
69fe9ce5 27#include "opintl.h"
252b5132 28#include "opcode/ppc.h"
65b48a81 29#include "libiberty.h"
252b5132
RH
30
31/* This file provides several disassembler functions, all of which use
32 the disassembler interface defined in dis-asm.h. Several functions
33 are provided because this file handles disassembly for the PowerPC
34 in both big and little endian mode and also for the POWER (RS/6000)
35 chip. */
fa452fa6
PB
36static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
37 ppc_cpu_t);
252b5132 38
fa452fa6
PB
39struct dis_private
40{
41 /* Stash the result of parsing disassembler_options here. */
42 ppc_cpu_t dialect;
6f0e0752 43};
fa452fa6
PB
44
45#define POWERPC_DIALECT(INFO) \
46 (((struct dis_private *) ((INFO)->private_data))->dialect)
418c1742 47
69fe9ce5 48struct ppc_mopt {
9b753937 49 /* Option string, without -m or -M prefix. */
69fe9ce5 50 const char *opt;
9b753937 51 /* CPU option flags. */
69fe9ce5 52 ppc_cpu_t cpu;
9b753937
AM
53 /* Flags that should stay on, even when combined with another cpu
54 option. This should only be used for generic options like
55 "-many" or "-maltivec" where it is reasonable to add some
56 capability to another cpu selection. The added flags are sticky
57 so that, for example, "-many -me500" and "-me500 -many" result in
58 the same assembler or disassembler behaviour. Do not use
59 "sticky" for specific cpus, as this will prevent that cpu's flags
60 from overriding the defaults set in powerpc_init_dialect or a
61 prior -m option. */
69fe9ce5
AM
62 ppc_cpu_t sticky;
63};
64
65struct ppc_mopt ppc_opts[] = {
14b57c7c 66 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403,
69fe9ce5 67 0 },
14b57c7c 68 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
69fe9ce5 69 0 },
bdc70b4a
AM
70 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
71 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 72 0 },
bdc70b4a
AM
73 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
74 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 75 0 },
62adc510
AM
76 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
77 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
9fe54b1c 78 0 },
14b57c7c 79 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601,
69fe9ce5 80 0 },
14b57c7c 81 { "603", PPC_OPCODE_PPC,
69fe9ce5 82 0 },
14b57c7c 83 { "604", PPC_OPCODE_PPC,
69fe9ce5 84 0 },
14b57c7c 85 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 86 0 },
14b57c7c 87 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 88 0 },
14b57c7c 89 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 90 0 },
14b57c7c 91 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
69fe9ce5 92 0 },
14b57c7c 93 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 94 0 },
14b57c7c 95 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
69fe9ce5 96 , 0 },
fa758a70
AC
97 { "gekko", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
98 , 0 },
99 { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
100 , 0 },
14b57c7c 101 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 102 0 },
14b57c7c 103 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 104 0 },
14b57c7c 105 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 106 0 },
bdc70b4a
AM
107 { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
108 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
109 | PPC_OPCODE_A2),
cdc51b07 110 0 },
14b57c7c 111 { "altivec", PPC_OPCODE_PPC,
4b8b687e 112 PPC_OPCODE_ALTIVEC },
52be03fd 113 { "any", PPC_OPCODE_PPC,
69fe9ce5 114 PPC_OPCODE_ANY },
14b57c7c 115 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 116 0 },
14b57c7c 117 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 118 0 },
bdc70b4a
AM
119 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
120 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
69fe9ce5 121 0 },
14b57c7c 122 { "com", PPC_OPCODE_COMMON,
69fe9ce5 123 0 },
dfdaec14
AJ
124 { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
125 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
126 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948
AF
127 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
128 | PPC_OPCODE_EFS2 | PPC_OPCODE_LSP),
9b753937 129 0 },
14b57c7c 130 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
69fe9ce5
AM
131 0 },
132 { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
133 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
134 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
e01d869a 135 | PPC_OPCODE_E500),
69fe9ce5
AM
136 0 },
137 { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
138 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
139 | PPC_OPCODE_E500MC),
140 0 },
0dc93057
AM
141 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
142 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
63d0fa4e
AM
143 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
144 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0dc93057 145 0 },
aea77599
AM
146 { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
147 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
148 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
c03dc33b 149 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
aea77599
AM
150 0 },
151 { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
152 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
153 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
c03dc33b 154 | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
aea77599
AM
155 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
156 0 },
69fe9ce5
AM
157 { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
158 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
159 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
e01d869a 160 | PPC_OPCODE_E500),
69fe9ce5 161 0 },
14b57c7c 162 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 163 0 },
74081948
AF
164 { "efs2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
165 0 },
14b57c7c 166 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
69fe9ce5 167 0 },
bdc70b4a
AM
168 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
169 | PPC_OPCODE_POWER5),
69fe9ce5 170 0 },
bdc70b4a
AM
171 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
172 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
69fe9ce5 173 0 },
bdc70b4a
AM
174 { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
175 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
176 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
69fe9ce5 177 0 },
5817ffd1
PB
178 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
179 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 180 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 181 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 182 0 },
a680de9a
PB
183 { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
184 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
185 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
ef85eab0 186 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 187 0 },
dd7efa79
PB
188 { "future", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
189 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
190 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
191 | PPC_OPCODE_POWERXX | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
192 0 },
14b57c7c 193 { "ppc", PPC_OPCODE_PPC,
69fe9ce5 194 0 },
14b57c7c 195 { "ppc32", PPC_OPCODE_PPC,
69fe9ce5 196 0 },
65b48a81
PB
197 { "32", PPC_OPCODE_PPC,
198 0 },
14b57c7c 199 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 200 0 },
65b48a81
PB
201 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
202 0 },
14b57c7c 203 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
69fe9ce5 204 0 },
14b57c7c 205 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
69fe9ce5 206 0 },
14b57c7c 207 { "pwr", PPC_OPCODE_POWER,
69fe9ce5 208 0 },
14b57c7c 209 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
cdc51b07 210 0 },
14b57c7c 211 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
cdc51b07 212 0 },
bdc70b4a
AM
213 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
214 | PPC_OPCODE_POWER5),
cdc51b07 215 0 },
bdc70b4a
AM
216 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
217 | PPC_OPCODE_POWER5),
cdc51b07 218 0 },
bdc70b4a
AM
219 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
220 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
cdc51b07 221 0 },
bdc70b4a
AM
222 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
223 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
224 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
69fe9ce5 225 0 },
5817ffd1
PB
226 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
227 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 228 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 229 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 230 0 },
a680de9a
PB
231 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
232 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
233 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
ef85eab0 234 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 235 0 },
14b57c7c 236 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
69fe9ce5 237 0 },
52be03fd
AM
238 { "raw", PPC_OPCODE_PPC,
239 PPC_OPCODE_RAW },
14b57c7c 240 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 241 PPC_OPCODE_SPE },
74081948
AF
242 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
243 PPC_OPCODE_SPE2 },
bdc70b4a
AM
244 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
245 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
ce3d2015 246 0 },
14b57c7c
AM
247 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
248 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
249 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948 250 | PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
b9c361e0 251 PPC_OPCODE_VLE },
14b57c7c 252 { "vsx", PPC_OPCODE_PPC,
4b8b687e 253 PPC_OPCODE_VSX },
69fe9ce5
AM
254};
255
b9c361e0
JL
256/* Switch between Booke and VLE dialects for interlinked dumps. */
257static ppc_cpu_t
258get_powerpc_dialect (struct disassemble_info *info)
259{
260 ppc_cpu_t dialect = 0;
261
6f0e0752
AM
262 if (info->private_data)
263 dialect = POWERPC_DIALECT (info);
b9c361e0
JL
264
265 /* Disassemble according to the section headers flags for VLE-mode. */
266 if (dialect & PPC_OPCODE_VLE
3a2488dd 267 && info->section != NULL && info->section->owner != NULL
94caa966
AM
268 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
269 && elf_object_id (info->section->owner) == PPC32_ELF_DATA
270 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
b9c361e0
JL
271 return dialect;
272 else
273 return dialect & ~ PPC_OPCODE_VLE;
274}
275
69fe9ce5
AM
276/* Handle -m and -M options that set cpu type, and .machine arg. */
277
278ppc_cpu_t
776fc418 279ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
69fe9ce5 280{
69fe9ce5
AM
281 unsigned int i;
282
65b48a81
PB
283 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
284 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
69fe9ce5
AM
285 {
286 if (ppc_opts[i].sticky)
287 {
776fc418
AM
288 *sticky |= ppc_opts[i].sticky;
289 if ((ppc_cpu & ~*sticky) != 0)
69fe9ce5
AM
290 break;
291 }
292 ppc_cpu = ppc_opts[i].cpu;
293 break;
294 }
65b48a81 295 if (i >= ARRAY_SIZE (ppc_opts))
69fe9ce5
AM
296 return 0;
297
776fc418 298 ppc_cpu |= *sticky;
69fe9ce5
AM
299 return ppc_cpu;
300}
301
302/* Determine which set of machines to disassemble for. */
418c1742 303
b240011a 304static void
fa452fa6 305powerpc_init_dialect (struct disassemble_info *info)
418c1742 306{
69fe9ce5 307 ppc_cpu_t dialect = 0;
776fc418 308 ppc_cpu_t sticky = 0;
fa452fa6
PB
309 struct dis_private *priv = calloc (sizeof (*priv), 1);
310
311 if (priv == NULL)
6f0e0752 312 return;
418c1742 313
776fc418
AM
314 switch (info->mach)
315 {
316 case bfd_mach_ppc_403:
317 case bfd_mach_ppc_403gc:
4f6ffcd3 318 dialect = ppc_parse_cpu (dialect, &sticky, "403");
776fc418
AM
319 break;
320 case bfd_mach_ppc_405:
4f6ffcd3 321 dialect = ppc_parse_cpu (dialect, &sticky, "405");
776fc418
AM
322 break;
323 case bfd_mach_ppc_601:
4f6ffcd3 324 dialect = ppc_parse_cpu (dialect, &sticky, "601");
776fc418 325 break;
fa758a70
AC
326 case bfd_mach_ppc_750:
327 dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
328 break;
776fc418
AM
329 case bfd_mach_ppc_a35:
330 case bfd_mach_ppc_rs64ii:
331 case bfd_mach_ppc_rs64iii:
4f6ffcd3 332 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
776fc418
AM
333 break;
334 case bfd_mach_ppc_e500:
4f6ffcd3 335 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
776fc418
AM
336 break;
337 case bfd_mach_ppc_e500mc:
4f6ffcd3 338 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
776fc418
AM
339 break;
340 case bfd_mach_ppc_e500mc64:
4f6ffcd3 341 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
776fc418
AM
342 break;
343 case bfd_mach_ppc_e5500:
4f6ffcd3 344 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
776fc418
AM
345 break;
346 case bfd_mach_ppc_e6500:
4f6ffcd3 347 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
776fc418
AM
348 break;
349 case bfd_mach_ppc_titan:
4f6ffcd3 350 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
776fc418
AM
351 break;
352 case bfd_mach_ppc_vle:
4f6ffcd3 353 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
776fc418
AM
354 break;
355 default:
52fe4420
AM
356 if (info->arch == bfd_arch_powerpc)
357 dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY;
358 else
359 dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
65b48a81 360 break;
776fc418
AM
361 }
362
f995bbe8 363 const char *opt;
65b48a81 364 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
69fe9ce5
AM
365 {
366 ppc_cpu_t new_cpu = 0;
9b4e5766 367
65b48a81 368 if (disassembler_options_cmp (opt, "32") == 0)
7102e95e 369 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
65b48a81 370 else if (disassembler_options_cmp (opt, "64") == 0)
bdc70b4a 371 dialect |= PPC_OPCODE_64;
65b48a81
PB
372 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
373 dialect = new_cpu;
69fe9ce5 374 else
a6743a54
AM
375 /* xgettext: c-format */
376 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
69fe9ce5 377 }
661bd698 378
fa452fa6
PB
379 info->private_data = priv;
380 POWERPC_DIALECT(info) = dialect;
b240011a
AM
381}
382
f413a913
AM
383#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
384static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
dd7efa79 385#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
4f6d070a 386static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
f413a913
AM
387#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
388static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
389#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
390static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
b240011a
AM
391
392/* Calculate opcode table indices to speed up disassembly,
393 and init dialect. */
394
395void
396disassemble_init_powerpc (struct disassemble_info *info)
397{
27c49e9a 398 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 399 {
2ceb7719 400 unsigned seg, idx, op;
27c49e9a 401
2ceb7719
PB
402 /* PPC opcodes */
403 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 404 {
2ceb7719
PB
405 powerpc_opcd_indices[seg] = idx;
406 for (; idx < powerpc_num_opcodes; idx++)
407 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
408 break;
0f873fd5 409 }
27c49e9a 410
dd7efa79
PB
411 /* 64-bit prefix opcodes */
412 for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
413 {
414 prefix_opcd_indices[seg] = idx;
415 for (; idx < prefix_num_opcodes; idx++)
416 if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
417 break;
418 }
419
2ceb7719
PB
420 /* VLE opcodes */
421 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 422 {
2ceb7719
PB
423 vle_opcd_indices[seg] = idx;
424 for (; idx < vle_num_opcodes; idx++)
425 {
426 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
427 if (seg < VLE_OP_TO_SEG (op))
428 break;
429 }
0f873fd5 430 }
27c49e9a 431
2ceb7719
PB
432 /* SPE2 opcodes */
433 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 434 {
2ceb7719
PB
435 spe2_opcd_indices[seg] = idx;
436 for (; idx < spe2_num_opcodes; idx++)
437 {
438 op = SPE2_XOP (spe2_opcodes[idx].opcode);
439 if (seg < SPE2_XOP_TO_SEG (op))
440 break;
441 }
0f873fd5 442 }
b9c361e0
JL
443 }
444
52fe4420 445 powerpc_init_dialect (info);
418c1742
MG
446}
447
448/* Print a big endian PowerPC instruction. */
252b5132
RH
449
450int
823bbe9d 451print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 452{
b9c361e0 453 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
454}
455
418c1742 456/* Print a little endian PowerPC instruction. */
252b5132
RH
457
458int
823bbe9d 459print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 460{
b9c361e0 461 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
462}
463
ea192fa3
PB
464/* Extract the operand value from the PowerPC or POWER instruction. */
465
0f873fd5 466static int64_t
ea192fa3 467operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 468 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 469{
0f873fd5 470 int64_t value;
9cf7e568 471 int invalid = 0;
ea192fa3
PB
472 /* Extract the value from the instruction. */
473 if (operand->extract)
474 value = (*operand->extract) (insn, dialect, &invalid);
475 else
476 {
b9c361e0
JL
477 if (operand->shift >= 0)
478 value = (insn >> operand->shift) & operand->bitm;
479 else
480 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
481 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
482 {
483 /* BITM is always some number of zeros followed by some
b9c361e0 484 number of ones, followed by some number of zeros. */
0f873fd5 485 uint64_t top = operand->bitm;
ea192fa3
PB
486 /* top & -top gives the rightmost 1 bit, so this
487 fills in any trailing zeros. */
488 top |= (top & -top) - 1;
489 top &= ~(top >> 1);
490 value = (value ^ top) - top;
491 }
492 }
493
494 return value;
495}
496
497/* Determine whether the optional operand(s) should be printed. */
498
bda678b9 499static bfd_boolean
ea192fa3 500skip_optional_operands (const unsigned char *opindex,
0f873fd5 501 uint64_t insn, ppc_cpu_t dialect)
ea192fa3
PB
502{
503 const struct powerpc_operand *operand;
9cf7e568 504 int num_optional;
ea192fa3 505
9cf7e568 506 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
507 {
508 operand = &powerpc_operands[*opindex];
9cf7e568 509 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
bda678b9 510 return FALSE;
9cf7e568
AM
511 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
512 {
513 /* Negative count is used as a flag to extract function. */
514 --num_optional;
515 if (operand_value_powerpc (operand, insn, dialect)
516 != ppc_optional_operand_value (operand, insn, dialect,
517 num_optional))
bda678b9 518 return FALSE;
9cf7e568 519 }
ea192fa3
PB
520 }
521
bda678b9 522 return TRUE;
ea192fa3
PB
523}
524
52be03fd 525/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 526
d6688282 527static const struct powerpc_opcode *
0f873fd5 528lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 529{
52be03fd 530 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
531 unsigned long op;
532
533 /* Get the major opcode of the instruction. */
534 op = PPC_OP (insn);
535
536 /* Find the first match in the opcode table for this major opcode. */
537 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 538 last = NULL;
d6688282
AM
539 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
540 opcode < opcode_end;
541 ++opcode)
542 {
543 const unsigned char *opindex;
544 const struct powerpc_operand *operand;
545 int invalid;
546
547 if ((insn & opcode->mask) != opcode->opcode
52be03fd 548 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
549 && ((opcode->flags & dialect) == 0
550 || (opcode->deprecated & dialect) != 0)))
551 continue;
552
553 /* Check validity of operands. */
554 invalid = 0;
555 for (opindex = opcode->operands; *opindex != 0; opindex++)
556 {
557 operand = powerpc_operands + *opindex;
558 if (operand->extract)
559 (*operand->extract) (insn, dialect, &invalid);
560 }
561 if (invalid)
562 continue;
563
52be03fd
AM
564 if ((dialect & PPC_OPCODE_RAW) == 0)
565 return opcode;
566
567 /* The raw machine insn is one that is not a specialization. */
568 if (last == NULL
569 || (last->mask & ~opcode->mask) != 0)
570 last = opcode;
d6688282
AM
571 }
572
52be03fd 573 return last;
d6688282
AM
574}
575
dd7efa79
PB
576/* Find a match for INSN in the PREFIX opcode table. */
577
578static const struct powerpc_opcode *
579lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
580{
581 const struct powerpc_opcode *opcode, *opcode_end, *last;
582 unsigned long seg;
583
584 /* Get the opcode segment of the instruction. */
585 seg = PPC_PREFIX_SEG (insn);
586
587 /* Find the first match in the opcode table for this major opcode. */
588 opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
589 last = NULL;
590 for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
591 opcode < opcode_end;
592 ++opcode)
593 {
594 const unsigned char *opindex;
595 const struct powerpc_operand *operand;
596 int invalid;
597
598 if ((insn & opcode->mask) != opcode->opcode
599 || ((dialect & PPC_OPCODE_ANY) == 0
600 && ((opcode->flags & dialect) == 0
601 || (opcode->deprecated & dialect) != 0)))
602 continue;
603
604 /* Check validity of operands. */
605 invalid = 0;
606 for (opindex = opcode->operands; *opindex != 0; opindex++)
607 {
608 operand = powerpc_operands + *opindex;
609 if (operand->extract)
610 (*operand->extract) (insn, dialect, &invalid);
611 }
612 if (invalid)
613 continue;
614
615 if ((dialect & PPC_OPCODE_RAW) == 0)
616 return opcode;
617
618 /* The raw machine insn is one that is not a specialization. */
619 if (last == NULL
620 || (last->mask & ~opcode->mask) != 0)
621 last = opcode;
622 }
623
624 return last;
625}
626
b9c361e0
JL
627/* Find a match for INSN in the VLE opcode table. */
628
629static const struct powerpc_opcode *
0f873fd5 630lookup_vle (uint64_t insn)
b9c361e0
JL
631{
632 const struct powerpc_opcode *opcode;
633 const struct powerpc_opcode *opcode_end;
634 unsigned op, seg;
635
636 op = PPC_OP (insn);
637 if (op >= 0x20 && op <= 0x37)
638 {
639 /* This insn has a 4-bit opcode. */
640 op &= 0x3c;
641 }
642 seg = VLE_OP_TO_SEG (op);
643
644 /* Find the first match in the opcode table for this major opcode. */
645 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
646 for (opcode = vle_opcodes + vle_opcd_indices[seg];
647 opcode < opcode_end;
648 ++opcode)
649 {
0f873fd5
PB
650 uint64_t table_opcd = opcode->opcode;
651 uint64_t table_mask = opcode->mask;
b9c361e0 652 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 653 uint64_t insn2;
b9c361e0
JL
654 const unsigned char *opindex;
655 const struct powerpc_operand *operand;
656 int invalid;
657
658 insn2 = insn;
659 if (table_op_is_short)
660 insn2 >>= 16;
661 if ((insn2 & table_mask) != table_opcd)
662 continue;
663
664 /* Check validity of operands. */
665 invalid = 0;
666 for (opindex = opcode->operands; *opindex != 0; ++opindex)
667 {
668 operand = powerpc_operands + *opindex;
669 if (operand->extract)
670 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
671 }
672 if (invalid)
673 continue;
674
675 return opcode;
676 }
677
678 return NULL;
679}
680
74081948
AF
681/* Find a match for INSN in the SPE2 opcode table. */
682
683static const struct powerpc_opcode *
0f873fd5 684lookup_spe2 (uint64_t insn)
74081948
AF
685{
686 const struct powerpc_opcode *opcode, *opcode_end;
687 unsigned op, xop, seg;
688
689 op = PPC_OP (insn);
690 if (op != 0x4)
691 {
692 /* This is not SPE2 insn.
693 * All SPE2 instructions have OP=4 and differs by XOP */
694 return NULL;
695 }
696 xop = SPE2_XOP (insn);
697 seg = SPE2_XOP_TO_SEG (xop);
698
699 /* Find the first match in the opcode table for this major opcode. */
700 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
701 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
702 opcode < opcode_end;
703 ++opcode)
704 {
0f873fd5
PB
705 uint64_t table_opcd = opcode->opcode;
706 uint64_t table_mask = opcode->mask;
707 uint64_t insn2;
74081948
AF
708 const unsigned char *opindex;
709 const struct powerpc_operand *operand;
710 int invalid;
711
712 insn2 = insn;
713 if ((insn2 & table_mask) != table_opcd)
714 continue;
715
716 /* Check validity of operands. */
717 invalid = 0;
718 for (opindex = opcode->operands; *opindex != 0; ++opindex)
719 {
720 operand = powerpc_operands + *opindex;
721 if (operand->extract)
722 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
723 }
724 if (invalid)
725 continue;
726
727 return opcode;
728 }
729
730 return NULL;
731}
732
252b5132
RH
733/* Print a PowerPC or POWER instruction. */
734
735static int
823bbe9d
AM
736print_insn_powerpc (bfd_vma memaddr,
737 struct disassemble_info *info,
738 int bigendian,
fa452fa6 739 ppc_cpu_t dialect)
252b5132
RH
740{
741 bfd_byte buffer[4];
742 int status;
0f873fd5 743 uint64_t insn;
252b5132 744 const struct powerpc_opcode *opcode;
a87a6478 745 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
746
747 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
748
749 /* The final instruction may be a 2-byte VLE insn. */
750 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
751 {
752 /* Clear buffer so unused bytes will not have garbage in them. */
753 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
754 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
755 }
756
252b5132
RH
757 if (status != 0)
758 {
a87a6478
PB
759 (*info->memory_error_func) (status, memaddr, info);
760 return -1;
252b5132
RH
761 }
762
763 if (bigendian)
764 insn = bfd_getb32 (buffer);
765 else
766 insn = bfd_getl32 (buffer);
767
b9c361e0
JL
768 /* Get the major opcode of the insn. */
769 opcode = NULL;
dd7efa79
PB
770 if ((dialect & PPC_OPCODE_POWERXX) != 0
771 && PPC_OP (insn) == 0x1)
772 {
773 uint64_t temp_insn, suffix;
774 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
775 if (status == 0)
776 {
777 if (bigendian)
778 suffix = bfd_getb32 (buffer);
779 else
780 suffix = bfd_getl32 (buffer);
781 temp_insn = (insn << 32) | suffix;
782 opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
783 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
784 opcode = lookup_prefix (temp_insn, dialect);
785 if (opcode != NULL)
786 {
787 insn = temp_insn;
788 insn_length = 8;
789 if ((info->flags & WIDE_OUTPUT) != 0)
790 info->bytes_per_line = 8;
791 }
792 }
793 }
794 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
b9c361e0
JL
795 {
796 opcode = lookup_vle (insn);
a87a6478
PB
797 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
798 {
799 /* The operands will be fetched out of the 16-bit instruction. */
800 insn >>= 16;
801 insn_length = 2;
802 }
b9c361e0 803 }
74081948
AF
804 if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
805 opcode = lookup_spe2 (insn);
b9c361e0 806 if (opcode == NULL)
52be03fd 807 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
d6688282 808 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
52be03fd 809 opcode = lookup_powerpc (insn, dialect);
252b5132 810
d6688282 811 if (opcode != NULL)
252b5132 812 {
252b5132
RH
813 const unsigned char *opindex;
814 const struct powerpc_operand *operand;
e392bad3
AM
815 enum {
816 need_comma = 0,
817 need_1space = 1,
818 need_2spaces = 2,
819 need_3spaces = 3,
820 need_4spaces = 4,
821 need_5spaces = 5,
822 need_6spaces = 6,
823 need_7spaces = 7,
824 need_paren
825 } op_separator;
bda678b9 826 bfd_boolean skip_optional;
c2b1c275 827 int spaces;
252b5132 828
c2b1c275
AM
829 (*info->fprintf_func) (info->stream, "%s", opcode->name);
830 /* gdb fprintf_func doesn't return count printed. */
831 spaces = 8 - strlen (opcode->name);
832 if (spaces <= 0)
833 spaces = 1;
252b5132
RH
834
835 /* Now extract and print the operands. */
e392bad3 836 op_separator = spaces;
bda678b9 837 skip_optional = FALSE;
252b5132
RH
838 for (opindex = opcode->operands; *opindex != 0; opindex++)
839 {
0f873fd5 840 int64_t value;
252b5132
RH
841
842 operand = powerpc_operands + *opindex;
843
0067be51
AM
844 /* If all of the optional operands past this one have their
845 default value, then don't print any of them. Except in
846 raw mode, print them all. */
847 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
848 && (dialect & PPC_OPCODE_RAW) == 0)
65b650b4 849 {
bda678b9
PB
850 if (!skip_optional)
851 skip_optional = skip_optional_operands (opindex, insn, dialect);
65b650b4
AM
852 if (skip_optional)
853 continue;
854 }
252b5132 855
ea192fa3
PB
856 value = operand_value_powerpc (operand, insn, dialect);
857
e392bad3
AM
858 if (op_separator == need_comma)
859 (*info->fprintf_func) (info->stream, ",");
860 else if (op_separator == need_paren)
861 (*info->fprintf_func) (info->stream, "(");
862 else
863 (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
252b5132
RH
864
865 /* Print the operand as directed by the flags. */
fdd12ef3
AM
866 if ((operand->flags & PPC_OPERAND_GPR) != 0
867 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 868 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 869 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 870 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 871 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 872 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 873 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 874 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
252b5132
RH
875 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
876 (*info->print_address_func) (memaddr + value, info);
877 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
878 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 879 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 880 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 881 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 882 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 883 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 884 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 885 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 886 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
887 && (((dialect & PPC_OPCODE_PPC) != 0)
888 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 889 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
890 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
891 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
892 && (((dialect & PPC_OPCODE_PPC) != 0)
893 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 894 {
b9c361e0
JL
895 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
896 int cr;
897 int cc;
898
899 cr = value >> 2;
900 if (cr != 0)
901 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
902 cc = value & 3;
903 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 904 }
70dc4e32 905 else
d1a3c973 906 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 907
e392bad3
AM
908 if (op_separator == need_paren)
909 (*info->fprintf_func) (info->stream, ")");
252b5132 910
e392bad3
AM
911 op_separator = need_comma;
912 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
913 op_separator = need_paren;
252b5132
RH
914 }
915
a87a6478
PB
916 /* We have found and printed an instruction. */
917 return insn_length;
252b5132
RH
918 }
919
920 /* We could not find a match. */
d1a3c973 921 (*info->fprintf_func) (info->stream, ".long 0x%" PRIx64, insn);
252b5132
RH
922
923 return 4;
924}
07dd56a9 925
471b9d15 926const disasm_options_and_args_t *
65b48a81
PB
927disassembler_options_powerpc (void)
928{
471b9d15 929 static disasm_options_and_args_t *opts_and_args;
65b48a81 930
471b9d15 931 if (opts_and_args == NULL)
65b48a81
PB
932 {
933 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
934 disasm_options_t *opts;
935
936 opts_and_args = XNEW (disasm_options_and_args_t);
937 opts_and_args->args = NULL;
938
939 opts = &opts_and_args->options;
65b48a81 940 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
941 opts->description = NULL;
942 opts->arg = NULL;
65b48a81
PB
943 for (i = 0; i < num_options; i++)
944 opts->name[i] = ppc_opts[i].opt;
945 /* The array we return must be NULL terminated. */
946 opts->name[i] = NULL;
65b48a81
PB
947 }
948
471b9d15 949 return opts_and_args;
65b48a81
PB
950}
951
07dd56a9 952void
823bbe9d 953print_ppc_disassembler_options (FILE *stream)
07dd56a9 954{
69fe9ce5
AM
955 unsigned int i, col;
956
957 fprintf (stream, _("\n\
07dd56a9 958The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
959the -M switch:\n"));
960
65b48a81 961 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
962 {
963 col += fprintf (stream, " %s,", ppc_opts[i].opt);
964 if (col > 66)
965 {
966 fprintf (stream, "\n");
967 col = 0;
968 }
969 }
65b48a81 970 fprintf (stream, "\n");
07dd56a9 971}
This page took 0.919685 seconds and 4 git commands to generate.