]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/ppc-dis.c
GDB: Add support for the new set/show disassembler-options commands.
[thirdparty/binutils-gdb.git] / opcodes / ppc-dis.c
1 /* ppc-dis.c -- Disassemble PowerPC instructions
2 Copyright (C) 1994-2017 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support
4
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. */
21
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include "dis-asm.h"
25 #include "elf-bfd.h"
26 #include "elf/ppc.h"
27 #include "opintl.h"
28 #include "opcode/ppc.h"
29 #include "libiberty.h"
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. */
36 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
37 ppc_cpu_t);
38
39 struct dis_private
40 {
41 /* Stash the result of parsing disassembler_options here. */
42 ppc_cpu_t dialect;
43 } private;
44
45 #define POWERPC_DIALECT(INFO) \
46 (((struct dis_private *) ((INFO)->private_data))->dialect)
47
48 struct ppc_mopt {
49 const char *opt;
50 ppc_cpu_t cpu;
51 ppc_cpu_t sticky;
52 };
53
54 struct ppc_mopt ppc_opts[] = {
55 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403,
56 0 },
57 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
58 0 },
59 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
60 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
61 0 },
62 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
63 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
64 0 },
65 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_440
66 | PPC_OPCODE_476 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
67 0 },
68 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601,
69 0 },
70 { "603", PPC_OPCODE_PPC,
71 0 },
72 { "604", PPC_OPCODE_PPC,
73 0 },
74 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64,
75 0 },
76 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
77 0 },
78 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
79 0 },
80 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
81 0 },
82 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
83 0 },
84 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
85 , 0 },
86 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
87 0 },
88 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
89 0 },
90 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860,
91 0 },
92 { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
93 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
94 | PPC_OPCODE_A2),
95 0 },
96 { "altivec", PPC_OPCODE_PPC,
97 PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 },
98 { "any", 0,
99 PPC_OPCODE_ANY },
100 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
101 0 },
102 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
103 0 },
104 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
105 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
106 0 },
107 { "com", PPC_OPCODE_COMMON,
108 0 },
109 { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
110 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
111 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
112 | PPC_OPCODE_E500 | PPC_OPCODE_E200Z4),
113 PPC_OPCODE_VLE },
114 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
115 0 },
116 { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
117 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
118 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
119 | PPC_OPCODE_E500),
120 0 },
121 { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
122 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
123 | PPC_OPCODE_E500MC),
124 0 },
125 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
126 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
127 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
128 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
129 0 },
130 { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
131 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
132 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
133 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
134 | PPC_OPCODE_POWER7),
135 0 },
136 { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
137 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
138 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
139 | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4
140 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
141 0 },
142 { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
143 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
144 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
145 | PPC_OPCODE_E500),
146 0 },
147 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
148 0 },
149 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
150 0 },
151 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
152 | PPC_OPCODE_POWER5),
153 0 },
154 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
155 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
156 0 },
157 { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
158 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
159 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
160 0 },
161 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
162 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
163 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
164 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
165 0 },
166 { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
167 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
168 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
169 | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
170 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ),
171 0 },
172 { "ppc", PPC_OPCODE_PPC,
173 0 },
174 { "ppc32", PPC_OPCODE_PPC,
175 0 },
176 { "32", PPC_OPCODE_PPC,
177 0 },
178 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
179 0 },
180 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
181 0 },
182 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
183 0 },
184 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
185 0 },
186 { "pwr", PPC_OPCODE_POWER,
187 0 },
188 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
189 0 },
190 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
191 0 },
192 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
193 | PPC_OPCODE_POWER5),
194 0 },
195 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
196 | PPC_OPCODE_POWER5),
197 0 },
198 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
199 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
200 0 },
201 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
202 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
203 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
204 0 },
205 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
206 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
207 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
208 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
209 0 },
210 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
211 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
212 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
213 | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
214 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ),
215 0 },
216 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
217 0 },
218 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
219 PPC_OPCODE_SPE },
220 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
221 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
222 0 },
223 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
224 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
225 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
226 | PPC_OPCODE_E500),
227 PPC_OPCODE_VLE },
228 { "vsx", PPC_OPCODE_PPC,
229 PPC_OPCODE_VSX | PPC_OPCODE_VSX3 },
230 { "htm", PPC_OPCODE_PPC,
231 PPC_OPCODE_HTM },
232 };
233
234 /* Switch between Booke and VLE dialects for interlinked dumps. */
235 static ppc_cpu_t
236 get_powerpc_dialect (struct disassemble_info *info)
237 {
238 ppc_cpu_t dialect = 0;
239
240 dialect = POWERPC_DIALECT (info);
241
242 /* Disassemble according to the section headers flags for VLE-mode. */
243 if (dialect & PPC_OPCODE_VLE
244 && info->section != NULL && info->section->owner != NULL
245 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
246 && elf_object_id (info->section->owner) == PPC32_ELF_DATA
247 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
248 return dialect;
249 else
250 return dialect & ~ PPC_OPCODE_VLE;
251 }
252
253 /* Handle -m and -M options that set cpu type, and .machine arg. */
254
255 ppc_cpu_t
256 ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
257 {
258 unsigned int i;
259
260 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
261 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
262 {
263 if (ppc_opts[i].sticky)
264 {
265 *sticky |= ppc_opts[i].sticky;
266 if ((ppc_cpu & ~*sticky) != 0)
267 break;
268 }
269 ppc_cpu = ppc_opts[i].cpu;
270 break;
271 }
272 if (i >= ARRAY_SIZE (ppc_opts))
273 return 0;
274
275 ppc_cpu |= *sticky;
276 return ppc_cpu;
277 }
278
279 /* Determine which set of machines to disassemble for. */
280
281 static void
282 powerpc_init_dialect (struct disassemble_info *info)
283 {
284 ppc_cpu_t dialect = 0;
285 ppc_cpu_t sticky = 0;
286 struct dis_private *priv = calloc (sizeof (*priv), 1);
287
288 if (priv == NULL)
289 priv = &private;
290
291 switch (info->mach)
292 {
293 case bfd_mach_ppc_403:
294 case bfd_mach_ppc_403gc:
295 dialect = ppc_parse_cpu (dialect, &sticky, "403");
296 break;
297 case bfd_mach_ppc_405:
298 dialect = ppc_parse_cpu (dialect, &sticky, "405");
299 break;
300 case bfd_mach_ppc_601:
301 dialect = ppc_parse_cpu (dialect, &sticky, "601");
302 break;
303 case bfd_mach_ppc_a35:
304 case bfd_mach_ppc_rs64ii:
305 case bfd_mach_ppc_rs64iii:
306 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
307 break;
308 case bfd_mach_ppc_e500:
309 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
310 break;
311 case bfd_mach_ppc_e500mc:
312 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
313 break;
314 case bfd_mach_ppc_e500mc64:
315 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
316 break;
317 case bfd_mach_ppc_e5500:
318 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
319 break;
320 case bfd_mach_ppc_e6500:
321 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
322 break;
323 case bfd_mach_ppc_titan:
324 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
325 break;
326 case bfd_mach_ppc_vle:
327 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
328 break;
329 default:
330 dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY;
331 break;
332 }
333
334 char *opt;
335 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
336 {
337 ppc_cpu_t new_cpu = 0;
338
339 if (disassembler_options_cmp (opt, "32") == 0)
340 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
341 else if (disassembler_options_cmp (opt, "64") == 0)
342 dialect |= PPC_OPCODE_64;
343 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
344 dialect = new_cpu;
345 else
346 fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), opt);
347 }
348
349 info->private_data = priv;
350 POWERPC_DIALECT(info) = dialect;
351 }
352
353 #define PPC_OPCD_SEGS 64
354 static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS+1];
355 #define VLE_OPCD_SEGS 32
356 static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1];
357
358 /* Calculate opcode table indices to speed up disassembly,
359 and init dialect. */
360
361 void
362 disassemble_init_powerpc (struct disassemble_info *info)
363 {
364 int i;
365 unsigned short last;
366
367 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
368 {
369
370 i = powerpc_num_opcodes;
371 while (--i >= 0)
372 {
373 unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
374
375 powerpc_opcd_indices[op] = i;
376 }
377
378 last = powerpc_num_opcodes;
379 for (i = PPC_OPCD_SEGS; i > 0; --i)
380 {
381 if (powerpc_opcd_indices[i] == 0)
382 powerpc_opcd_indices[i] = last;
383 last = powerpc_opcd_indices[i];
384 }
385
386 i = vle_num_opcodes;
387 while (--i >= 0)
388 {
389 unsigned op = VLE_OP (vle_opcodes[i].opcode, vle_opcodes[i].mask);
390 unsigned seg = VLE_OP_TO_SEG (op);
391
392 vle_opcd_indices[seg] = i;
393 }
394
395 last = vle_num_opcodes;
396 for (i = VLE_OPCD_SEGS; i > 0; --i)
397 {
398 if (vle_opcd_indices[i] == 0)
399 vle_opcd_indices[i] = last;
400 last = vle_opcd_indices[i];
401 }
402 }
403
404 if (info->arch == bfd_arch_powerpc)
405 powerpc_init_dialect (info);
406 }
407
408 /* Print a big endian PowerPC instruction. */
409
410 int
411 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
412 {
413 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
414 }
415
416 /* Print a little endian PowerPC instruction. */
417
418 int
419 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
420 {
421 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
422 }
423
424 /* Print a POWER (RS/6000) instruction. */
425
426 int
427 print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
428 {
429 return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
430 }
431
432 /* Extract the operand value from the PowerPC or POWER instruction. */
433
434 static long
435 operand_value_powerpc (const struct powerpc_operand *operand,
436 unsigned long insn, ppc_cpu_t dialect)
437 {
438 long value;
439 int invalid;
440 /* Extract the value from the instruction. */
441 if (operand->extract)
442 value = (*operand->extract) (insn, dialect, &invalid);
443 else
444 {
445 if (operand->shift >= 0)
446 value = (insn >> operand->shift) & operand->bitm;
447 else
448 value = (insn << -operand->shift) & operand->bitm;
449 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
450 {
451 /* BITM is always some number of zeros followed by some
452 number of ones, followed by some number of zeros. */
453 unsigned long top = operand->bitm;
454 /* top & -top gives the rightmost 1 bit, so this
455 fills in any trailing zeros. */
456 top |= (top & -top) - 1;
457 top &= ~(top >> 1);
458 value = (value ^ top) - top;
459 }
460 }
461
462 return value;
463 }
464
465 /* Determine whether the optional operand(s) should be printed. */
466
467 static int
468 skip_optional_operands (const unsigned char *opindex,
469 unsigned long insn, ppc_cpu_t dialect)
470 {
471 const struct powerpc_operand *operand;
472
473 for (; *opindex != 0; opindex++)
474 {
475 operand = &powerpc_operands[*opindex];
476 if ((operand->flags & PPC_OPERAND_NEXT) != 0
477 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
478 && operand_value_powerpc (operand, insn, dialect) !=
479 ppc_optional_operand_value (operand)))
480 return 0;
481 }
482
483 return 1;
484 }
485
486 /* Find a match for INSN in the opcode table, given machine DIALECT.
487 A DIALECT of -1 is special, matching all machine opcode variations. */
488
489 static const struct powerpc_opcode *
490 lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
491 {
492 const struct powerpc_opcode *opcode;
493 const struct powerpc_opcode *opcode_end;
494 unsigned long op;
495
496 /* Get the major opcode of the instruction. */
497 op = PPC_OP (insn);
498
499 /* Find the first match in the opcode table for this major opcode. */
500 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
501 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
502 opcode < opcode_end;
503 ++opcode)
504 {
505 const unsigned char *opindex;
506 const struct powerpc_operand *operand;
507 int invalid;
508
509 if ((insn & opcode->mask) != opcode->opcode
510 || (dialect != (ppc_cpu_t) -1
511 && ((opcode->flags & dialect) == 0
512 || (opcode->deprecated & dialect) != 0)))
513 continue;
514
515 /* Check validity of operands. */
516 invalid = 0;
517 for (opindex = opcode->operands; *opindex != 0; opindex++)
518 {
519 operand = powerpc_operands + *opindex;
520 if (operand->extract)
521 (*operand->extract) (insn, dialect, &invalid);
522 }
523 if (invalid)
524 continue;
525
526 return opcode;
527 }
528
529 return NULL;
530 }
531
532 /* Find a match for INSN in the VLE opcode table. */
533
534 static const struct powerpc_opcode *
535 lookup_vle (unsigned long insn)
536 {
537 const struct powerpc_opcode *opcode;
538 const struct powerpc_opcode *opcode_end;
539 unsigned op, seg;
540
541 op = PPC_OP (insn);
542 if (op >= 0x20 && op <= 0x37)
543 {
544 /* This insn has a 4-bit opcode. */
545 op &= 0x3c;
546 }
547 seg = VLE_OP_TO_SEG (op);
548
549 /* Find the first match in the opcode table for this major opcode. */
550 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
551 for (opcode = vle_opcodes + vle_opcd_indices[seg];
552 opcode < opcode_end;
553 ++opcode)
554 {
555 unsigned long table_opcd = opcode->opcode;
556 unsigned long table_mask = opcode->mask;
557 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
558 unsigned long insn2;
559 const unsigned char *opindex;
560 const struct powerpc_operand *operand;
561 int invalid;
562
563 insn2 = insn;
564 if (table_op_is_short)
565 insn2 >>= 16;
566 if ((insn2 & table_mask) != table_opcd)
567 continue;
568
569 /* Check validity of operands. */
570 invalid = 0;
571 for (opindex = opcode->operands; *opindex != 0; ++opindex)
572 {
573 operand = powerpc_operands + *opindex;
574 if (operand->extract)
575 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
576 }
577 if (invalid)
578 continue;
579
580 return opcode;
581 }
582
583 return NULL;
584 }
585
586 /* Print a PowerPC or POWER instruction. */
587
588 static int
589 print_insn_powerpc (bfd_vma memaddr,
590 struct disassemble_info *info,
591 int bigendian,
592 ppc_cpu_t dialect)
593 {
594 bfd_byte buffer[4];
595 int status;
596 unsigned long insn;
597 const struct powerpc_opcode *opcode;
598 bfd_boolean insn_is_short;
599
600 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
601 if (status != 0)
602 {
603 /* The final instruction may be a 2-byte VLE insn. */
604 if ((dialect & PPC_OPCODE_VLE) != 0)
605 {
606 /* Clear buffer so unused bytes will not have garbage in them. */
607 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
608 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
609 if (status != 0)
610 {
611 (*info->memory_error_func) (status, memaddr, info);
612 return -1;
613 }
614 }
615 else
616 {
617 (*info->memory_error_func) (status, memaddr, info);
618 return -1;
619 }
620 }
621
622 if (bigendian)
623 insn = bfd_getb32 (buffer);
624 else
625 insn = bfd_getl32 (buffer);
626
627 /* Get the major opcode of the insn. */
628 opcode = NULL;
629 insn_is_short = FALSE;
630 if ((dialect & PPC_OPCODE_VLE) != 0)
631 {
632 opcode = lookup_vle (insn);
633 if (opcode != NULL)
634 insn_is_short = PPC_OP_SE_VLE(opcode->mask);
635 }
636 if (opcode == NULL)
637 opcode = lookup_powerpc (insn, dialect);
638 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
639 opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
640
641 if (opcode != NULL)
642 {
643 const unsigned char *opindex;
644 const struct powerpc_operand *operand;
645 int need_comma;
646 int need_paren;
647 int skip_optional;
648
649 if (opcode->operands[0] != 0)
650 (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
651 else
652 (*info->fprintf_func) (info->stream, "%s", opcode->name);
653
654 if (insn_is_short)
655 /* The operands will be fetched out of the 16-bit instruction. */
656 insn >>= 16;
657
658 /* Now extract and print the operands. */
659 need_comma = 0;
660 need_paren = 0;
661 skip_optional = -1;
662 for (opindex = opcode->operands; *opindex != 0; opindex++)
663 {
664 long value;
665
666 operand = powerpc_operands + *opindex;
667
668 /* Operands that are marked FAKE are simply ignored. We
669 already made sure that the extract function considered
670 the instruction to be valid. */
671 if ((operand->flags & PPC_OPERAND_FAKE) != 0)
672 continue;
673
674 /* If all of the optional operands have the value zero,
675 then don't print any of them. */
676 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
677 {
678 if (skip_optional < 0)
679 skip_optional = skip_optional_operands (opindex, insn,
680 dialect);
681 if (skip_optional)
682 continue;
683 }
684
685 value = operand_value_powerpc (operand, insn, dialect);
686
687 if (need_comma)
688 {
689 (*info->fprintf_func) (info->stream, ",");
690 need_comma = 0;
691 }
692
693 /* Print the operand as directed by the flags. */
694 if ((operand->flags & PPC_OPERAND_GPR) != 0
695 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
696 (*info->fprintf_func) (info->stream, "r%ld", value);
697 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
698 (*info->fprintf_func) (info->stream, "f%ld", value);
699 else if ((operand->flags & PPC_OPERAND_VR) != 0)
700 (*info->fprintf_func) (info->stream, "v%ld", value);
701 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
702 (*info->fprintf_func) (info->stream, "vs%ld", value);
703 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
704 (*info->print_address_func) (memaddr + value, info);
705 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
706 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
707 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
708 (*info->fprintf_func) (info->stream, "fsl%ld", value);
709 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
710 (*info->fprintf_func) (info->stream, "fcr%ld", value);
711 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
712 (*info->fprintf_func) (info->stream, "%ld", value);
713 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
714 && (((dialect & PPC_OPCODE_PPC) != 0)
715 || ((dialect & PPC_OPCODE_VLE) != 0)))
716 (*info->fprintf_func) (info->stream, "cr%ld", value);
717 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
718 && (((dialect & PPC_OPCODE_PPC) != 0)
719 || ((dialect & PPC_OPCODE_VLE) != 0)))
720 {
721 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
722 int cr;
723 int cc;
724
725 cr = value >> 2;
726 if (cr != 0)
727 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
728 cc = value & 3;
729 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
730 }
731 else
732 (*info->fprintf_func) (info->stream, "%d", (int) value);
733
734 if (need_paren)
735 {
736 (*info->fprintf_func) (info->stream, ")");
737 need_paren = 0;
738 }
739
740 if ((operand->flags & PPC_OPERAND_PARENS) == 0)
741 need_comma = 1;
742 else
743 {
744 (*info->fprintf_func) (info->stream, "(");
745 need_paren = 1;
746 }
747 }
748
749 /* We have found and printed an instruction.
750 If it was a short VLE instruction we have more to do. */
751 if (insn_is_short)
752 {
753 memaddr += 2;
754 return 2;
755 }
756 else
757 /* Otherwise, return. */
758 return 4;
759 }
760
761 /* We could not find a match. */
762 (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
763
764 return 4;
765 }
766
767 const disasm_options_t *
768 disassembler_options_powerpc (void)
769 {
770 static disasm_options_t *opts = NULL;
771
772 if (opts == NULL)
773 {
774 size_t i, num_options = ARRAY_SIZE (ppc_opts);
775 opts = XNEW (disasm_options_t);
776 opts->name = XNEWVEC (const char *, num_options + 1);
777 for (i = 0; i < num_options; i++)
778 opts->name[i] = ppc_opts[i].opt;
779 /* The array we return must be NULL terminated. */
780 opts->name[i] = NULL;
781 opts->description = NULL;
782 }
783
784 return opts;
785 }
786
787 void
788 print_ppc_disassembler_options (FILE *stream)
789 {
790 unsigned int i, col;
791
792 fprintf (stream, _("\n\
793 The following PPC specific disassembler options are supported for use with\n\
794 the -M switch:\n"));
795
796 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
797 {
798 col += fprintf (stream, " %s,", ppc_opts[i].opt);
799 if (col > 66)
800 {
801 fprintf (stream, "\n");
802 col = 0;
803 }
804 }
805 fprintf (stream, "\n");
806 }