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