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