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