Home | History | Annotate | Line # | Download | only in opcodes
      1   1.1     skrll /* ppc-dis.c -- Disassemble PowerPC instructions
      2  1.13  christos    Copyright (C) 1994-2026 Free Software Foundation, Inc.
      3   1.1     skrll    Written by Ian Lance Taylor, Cygnus Support
      4   1.1     skrll 
      5   1.1     skrll    This file is part of the GNU opcodes library.
      6   1.1     skrll 
      7   1.1     skrll    This library is free software; you can redistribute it and/or modify
      8   1.1     skrll    it under the terms of the GNU General Public License as published by
      9   1.1     skrll    the Free Software Foundation; either version 3, or (at your option)
     10   1.1     skrll    any later version.
     11   1.1     skrll 
     12   1.1     skrll    It is distributed in the hope that it will be useful, but WITHOUT
     13   1.1     skrll    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14   1.1     skrll    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15   1.1     skrll    License for more details.
     16   1.1     skrll 
     17   1.1     skrll    You should have received a copy of the GNU General Public License
     18   1.1     skrll    along with this file; see the file COPYING.  If not, write to the
     19   1.1     skrll    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     20   1.1     skrll    MA 02110-1301, USA.  */
     21   1.1     skrll 
     22   1.4  christos #include "sysdep.h"
     23   1.1     skrll #include <stdio.h>
     24   1.7  christos #include "disassemble.h"
     25   1.4  christos #include "elf-bfd.h"
     26   1.4  christos #include "elf/ppc.h"
     27   1.3  christos #include "opintl.h"
     28   1.1     skrll #include "opcode/ppc.h"
     29   1.7  christos #include "libiberty.h"
     30   1.1     skrll 
     31   1.1     skrll /* This file provides several disassembler functions, all of which use
     32   1.1     skrll    the disassembler interface defined in dis-asm.h.  Several functions
     33   1.1     skrll    are provided because this file handles disassembly for the PowerPC
     34   1.1     skrll    in both big and little endian mode and also for the POWER (RS/6000)
     35   1.1     skrll    chip.  */
     36   1.1     skrll static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
     37   1.1     skrll 			       ppc_cpu_t);
     38   1.1     skrll 
     39   1.1     skrll struct dis_private
     40   1.1     skrll {
     41   1.1     skrll   /* Stash the result of parsing disassembler_options here.  */
     42   1.1     skrll   ppc_cpu_t dialect;
     43  1.10  christos 
     44  1.10  christos   /* .got and .plt sections.  NAME is set to NULL if not present.  */
     45  1.10  christos   struct sec_buf {
     46  1.10  christos     asection *sec;
     47  1.10  christos     bfd_byte *buf;
     48  1.10  christos     const char *name;
     49  1.10  christos   } special[2];
     50   1.9  christos };
     51   1.1     skrll 
     52  1.10  christos static inline struct dis_private *
     53  1.10  christos private_data (struct disassemble_info *info)
     54  1.10  christos {
     55  1.10  christos   return (struct dis_private *) info->private_data;
     56  1.10  christos }
     57   1.1     skrll 
     58   1.3  christos struct ppc_mopt {
     59   1.7  christos   /* Option string, without -m or -M prefix.  */
     60   1.3  christos   const char *opt;
     61   1.7  christos   /* CPU option flags.  */
     62   1.3  christos   ppc_cpu_t cpu;
     63   1.7  christos   /* Flags that should stay on, even when combined with another cpu
     64   1.7  christos      option.  This should only be used for generic options like
     65   1.7  christos      "-many" or "-maltivec" where it is reasonable to add some
     66   1.7  christos      capability to another cpu selection.  The added flags are sticky
     67   1.7  christos      so that, for example, "-many -me500" and "-me500 -many" result in
     68   1.7  christos      the same assembler or disassembler behaviour.  Do not use
     69   1.7  christos      "sticky" for specific cpus, as this will prevent that cpu's flags
     70   1.7  christos      from overriding the defaults set in powerpc_init_dialect or a
     71   1.7  christos      prior -m option.  */
     72   1.3  christos   ppc_cpu_t sticky;
     73   1.3  christos };
     74   1.3  christos 
     75  1.13  christos static const struct ppc_mopt ppc_opts[] = {
     76   1.6  christos   { "403",     PPC_OPCODE_PPC | PPC_OPCODE_403,
     77   1.3  christos     0 },
     78   1.6  christos   { "405",     PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
     79   1.3  christos     0 },
     80   1.3  christos   { "440",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
     81   1.3  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
     82   1.3  christos     0 },
     83   1.3  christos   { "464",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
     84   1.3  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
     85   1.3  christos     0 },
     86   1.7  christos   { "476",     (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
     87   1.7  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
     88   1.3  christos     0 },
     89   1.6  christos   { "601",     PPC_OPCODE_PPC | PPC_OPCODE_601,
     90   1.3  christos     0 },
     91   1.6  christos   { "603",     PPC_OPCODE_PPC,
     92   1.3  christos     0 },
     93   1.6  christos   { "604",     PPC_OPCODE_PPC,
     94   1.3  christos     0 },
     95   1.6  christos   { "620",     PPC_OPCODE_PPC | PPC_OPCODE_64,
     96   1.3  christos     0 },
     97   1.6  christos   { "7400",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
     98   1.3  christos     0 },
     99   1.6  christos   { "7410",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
    100   1.3  christos     0 },
    101   1.6  christos   { "7450",    PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
    102   1.3  christos     0 },
    103   1.6  christos   { "7455",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
    104   1.3  christos     0 },
    105   1.6  christos   { "750cl",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
    106   1.3  christos     , 0 },
    107   1.9  christos   { "gekko",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
    108   1.9  christos     , 0 },
    109   1.9  christos   { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
    110   1.9  christos     , 0 },
    111   1.6  christos   { "821",     PPC_OPCODE_PPC | PPC_OPCODE_860,
    112   1.5  christos     0 },
    113   1.6  christos   { "850",     PPC_OPCODE_PPC | PPC_OPCODE_860,
    114   1.5  christos     0 },
    115   1.6  christos   { "860",     PPC_OPCODE_PPC | PPC_OPCODE_860,
    116   1.5  christos     0 },
    117   1.3  christos   { "a2",      (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
    118   1.3  christos 		| PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
    119   1.3  christos 		| PPC_OPCODE_A2),
    120   1.3  christos     0 },
    121   1.6  christos   { "altivec", PPC_OPCODE_PPC,
    122   1.7  christos     PPC_OPCODE_ALTIVEC },
    123   1.7  christos   { "any",     PPC_OPCODE_PPC,
    124   1.3  christos     PPC_OPCODE_ANY },
    125   1.6  christos   { "booke",   PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
    126   1.3  christos     0 },
    127   1.6  christos   { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
    128   1.3  christos     0 },
    129   1.3  christos   { "cell",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    130   1.3  christos 		| PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
    131   1.3  christos     0 },
    132   1.6  christos   { "com",     PPC_OPCODE_COMMON,
    133   1.3  christos     0 },
    134  1.11  christos   { "e200z2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_LSP
    135   1.7  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
    136   1.7  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    137   1.7  christos 		| PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
    138  1.11  christos 		| PPC_OPCODE_EFS2),
    139  1.11  christos     0 },
    140  1.11  christos   { "e200z4",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
    141  1.11  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
    142  1.11  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    143  1.11  christos 		| PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
    144  1.11  christos 		| PPC_OPCODE_EFS2),
    145   1.7  christos     0 },
    146   1.6  christos   { "e300",    PPC_OPCODE_PPC | PPC_OPCODE_E300,
    147   1.3  christos     0 },
    148   1.3  christos   { "e500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
    149   1.3  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
    150   1.3  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    151   1.3  christos 		| PPC_OPCODE_E500),
    152   1.3  christos     0 },
    153   1.3  christos   { "e500mc",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
    154   1.3  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    155   1.3  christos 		| PPC_OPCODE_E500MC),
    156   1.3  christos     0 },
    157   1.3  christos   { "e500mc64",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
    158   1.3  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    159   1.3  christos 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
    160   1.3  christos 		| PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
    161   1.3  christos     0 },
    162   1.4  christos   { "e5500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
    163   1.4  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    164   1.4  christos 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    165   1.7  christos 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
    166   1.4  christos     0 },
    167   1.4  christos   { "e6500",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
    168   1.4  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    169   1.4  christos 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
    170   1.7  christos 		| PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
    171   1.4  christos 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
    172   1.4  christos     0 },
    173   1.3  christos   { "e500x2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
    174   1.3  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
    175   1.3  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    176   1.3  christos 		| PPC_OPCODE_E500),
    177   1.3  christos     0 },
    178   1.6  christos   { "efs",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
    179   1.3  christos     0 },
    180   1.7  christos   { "efs2",    PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
    181   1.7  christos     0 },
    182  1.11  christos   { "lsp",     PPC_OPCODE_PPC,
    183  1.11  christos     PPC_OPCODE_LSP },
    184   1.6  christos   { "power4",  PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
    185   1.3  christos     0 },
    186   1.3  christos   { "power5",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    187   1.3  christos 		| PPC_OPCODE_POWER5),
    188   1.3  christos     0 },
    189   1.3  christos   { "power6",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    190   1.3  christos 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
    191   1.3  christos     0 },
    192   1.3  christos   { "power7",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    193   1.3  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    194   1.3  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    195   1.3  christos     0 },
    196   1.5  christos   { "power8",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    197   1.5  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    198   1.7  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
    199   1.7  christos 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    200   1.5  christos     0 },
    201   1.5  christos   { "power9",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    202   1.5  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    203   1.5  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    204   1.7  christos 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    205   1.5  christos     0 },
    206  1.10  christos   { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    207  1.10  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    208  1.10  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    209  1.10  christos 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    210  1.10  christos     0 },
    211  1.12  christos   { "power11", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    212  1.12  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    213  1.12  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    214  1.12  christos 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    215  1.12  christos     0 },
    216  1.11  christos   { "libresoc",(PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    217  1.11  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    218  1.11  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    219  1.11  christos 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX | PPC_OPCODE_SVP64),
    220  1.11  christos     0 },
    221   1.9  christos   { "future",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    222   1.9  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    223   1.9  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    224  1.11  christos 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
    225  1.11  christos 		| PPC_OPCODE_FUTURE),
    226   1.9  christos     0 },
    227   1.6  christos   { "ppc",     PPC_OPCODE_PPC,
    228   1.3  christos     0 },
    229   1.6  christos   { "ppc32",   PPC_OPCODE_PPC,
    230   1.3  christos     0 },
    231   1.7  christos   { "32",      PPC_OPCODE_PPC,
    232   1.7  christos     0 },
    233   1.6  christos   { "ppc64",   PPC_OPCODE_PPC | PPC_OPCODE_64,
    234   1.3  christos     0 },
    235   1.7  christos   { "64",      PPC_OPCODE_PPC | PPC_OPCODE_64,
    236   1.7  christos     0 },
    237   1.6  christos   { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
    238   1.3  christos     0 },
    239   1.6  christos   { "ppcps",   PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
    240   1.3  christos     0 },
    241   1.6  christos   { "pwr",     PPC_OPCODE_POWER,
    242   1.3  christos     0 },
    243   1.6  christos   { "pwr2",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
    244   1.3  christos     0 },
    245   1.6  christos   { "pwr4",    PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
    246   1.3  christos     0 },
    247   1.3  christos   { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    248   1.3  christos 		| PPC_OPCODE_POWER5),
    249   1.3  christos     0 },
    250   1.3  christos   { "pwr5x",   (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    251   1.3  christos 		| PPC_OPCODE_POWER5),
    252   1.3  christos     0 },
    253   1.3  christos   { "pwr6",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
    254   1.3  christos 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
    255   1.3  christos     0 },
    256   1.3  christos   { "pwr7",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    257   1.3  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    258   1.3  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    259   1.3  christos     0 },
    260   1.5  christos   { "pwr8",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    261   1.5  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    262   1.7  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
    263   1.7  christos 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    264   1.5  christos     0 },
    265   1.5  christos   { "pwr9",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    266   1.5  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    267   1.5  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    268   1.7  christos 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    269   1.5  christos     0 },
    270  1.10  christos   { "pwr10",   (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    271  1.10  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    272  1.10  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    273  1.10  christos 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    274  1.10  christos     0 },
    275  1.12  christos   { "pwr11",   (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
    276  1.12  christos 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
    277  1.12  christos 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
    278  1.12  christos 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
    279  1.12  christos     0 },
    280   1.6  christos   { "pwrx",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
    281   1.3  christos     0 },
    282   1.7  christos   { "raw",     PPC_OPCODE_PPC,
    283   1.7  christos     PPC_OPCODE_RAW },
    284   1.6  christos   { "spe",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
    285   1.3  christos     PPC_OPCODE_SPE },
    286   1.7  christos   { "spe2",     PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
    287   1.7  christos     PPC_OPCODE_SPE2 },
    288   1.3  christos   { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
    289   1.3  christos 		| PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
    290   1.3  christos     0 },
    291  1.11  christos   { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
    292   1.6  christos 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
    293   1.6  christos 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
    294  1.11  christos 		| PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
    295   1.4  christos     PPC_OPCODE_VLE },
    296   1.6  christos   { "vsx",     PPC_OPCODE_PPC,
    297   1.7  christos     PPC_OPCODE_VSX },
    298   1.3  christos };
    299   1.3  christos 
    300   1.4  christos /* Switch between Booke and VLE dialects for interlinked dumps.  */
    301   1.4  christos static ppc_cpu_t
    302   1.4  christos get_powerpc_dialect (struct disassemble_info *info)
    303   1.4  christos {
    304   1.4  christos   ppc_cpu_t dialect = 0;
    305   1.4  christos 
    306   1.9  christos   if (info->private_data)
    307  1.10  christos     dialect = private_data (info)->dialect;
    308   1.4  christos 
    309   1.4  christos   /* Disassemble according to the section headers flags for VLE-mode.  */
    310   1.4  christos   if (dialect & PPC_OPCODE_VLE
    311   1.7  christos       && info->section != NULL && info->section->owner != NULL
    312   1.4  christos       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
    313   1.4  christos       && elf_object_id (info->section->owner) == PPC32_ELF_DATA
    314   1.4  christos       && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
    315   1.4  christos     return dialect;
    316   1.4  christos   else
    317   1.4  christos     return dialect & ~ PPC_OPCODE_VLE;
    318   1.4  christos }
    319   1.4  christos 
    320   1.3  christos /* Handle -m and -M options that set cpu type, and .machine arg.  */
    321   1.3  christos 
    322   1.3  christos ppc_cpu_t
    323   1.4  christos ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
    324   1.3  christos {
    325   1.3  christos   unsigned int i;
    326   1.3  christos 
    327   1.7  christos   for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
    328  1.13  christos     if (strcmp (ppc_opts[i].opt, arg) == 0)
    329   1.3  christos       {
    330   1.3  christos 	if (ppc_opts[i].sticky)
    331   1.3  christos 	  {
    332   1.4  christos 	    *sticky |= ppc_opts[i].sticky;
    333   1.4  christos 	    if ((ppc_cpu & ~*sticky) != 0)
    334   1.3  christos 	      break;
    335   1.3  christos 	  }
    336   1.3  christos 	ppc_cpu = ppc_opts[i].cpu;
    337   1.3  christos 	break;
    338   1.3  christos       }
    339   1.7  christos   if (i >= ARRAY_SIZE (ppc_opts))
    340   1.3  christos     return 0;
    341   1.3  christos 
    342  1.11  christos   /* SPE and LSP are mutually exclusive, don't allow them both in
    343  1.11  christos      sticky options.  However do allow them both in ppc_cpu, so that
    344  1.11  christos      for example, -mvle -mlsp enables both SPE and LSP for assembly.  */
    345  1.11  christos   if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0)
    346  1.11  christos     *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2);
    347  1.11  christos   else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0)
    348  1.11  christos     *sticky &= ~PPC_OPCODE_LSP;
    349   1.4  christos   ppc_cpu |= *sticky;
    350  1.11  christos 
    351   1.3  christos   return ppc_cpu;
    352   1.3  christos }
    353   1.3  christos 
    354  1.13  christos struct ppc_parse_data
    355  1.13  christos {
    356  1.13  christos   ppc_cpu_t dialect;
    357  1.13  christos   ppc_cpu_t sticky;
    358  1.13  christos };
    359  1.13  christos 
    360  1.13  christos static bool
    361  1.13  christos ppc_parse_option (const char *opt, void *data)
    362  1.13  christos {
    363  1.13  christos   struct ppc_parse_data *res = data;
    364  1.13  christos   ppc_cpu_t new_cpu;
    365  1.13  christos 
    366  1.13  christos   if (strcmp (opt, "32") == 0)
    367  1.13  christos     res->dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
    368  1.13  christos   else if (strcmp (opt, "64") == 0)
    369  1.13  christos     res->dialect |= PPC_OPCODE_64;
    370  1.13  christos   else if ((new_cpu = ppc_parse_cpu (res->dialect, &res->sticky, opt)) != 0)
    371  1.13  christos     res->dialect = new_cpu;
    372  1.13  christos   else
    373  1.13  christos     /* xgettext: c-format */
    374  1.13  christos     opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
    375  1.13  christos   return true;
    376  1.13  christos }
    377  1.13  christos 
    378   1.3  christos /* Determine which set of machines to disassemble for.  */
    379   1.1     skrll 
    380   1.4  christos static void
    381   1.1     skrll powerpc_init_dialect (struct disassemble_info *info)
    382   1.1     skrll {
    383  1.13  christos   struct ppc_parse_data out = { 0, 0 };
    384  1.11  christos   struct dis_private *priv = calloc (1, sizeof (*priv));
    385   1.1     skrll 
    386   1.1     skrll   if (priv == NULL)
    387   1.9  christos     return;
    388   1.4  christos 
    389   1.4  christos   switch (info->mach)
    390   1.4  christos     {
    391   1.4  christos     case bfd_mach_ppc_403:
    392   1.4  christos     case bfd_mach_ppc_403gc:
    393  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "403");
    394   1.4  christos       break;
    395   1.4  christos     case bfd_mach_ppc_405:
    396  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "405");
    397   1.4  christos       break;
    398   1.4  christos     case bfd_mach_ppc_601:
    399  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "601");
    400   1.4  christos       break;
    401   1.9  christos     case bfd_mach_ppc_750:
    402  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "750cl");
    403   1.9  christos       break;
    404   1.4  christos     case bfd_mach_ppc_a35:
    405   1.4  christos     case bfd_mach_ppc_rs64ii:
    406   1.4  christos     case bfd_mach_ppc_rs64iii:
    407  1.13  christos       out.dialect = (ppc_parse_cpu (out.dialect, &out.sticky, "pwr2")
    408  1.13  christos 		     | PPC_OPCODE_64);
    409   1.4  christos       break;
    410   1.4  christos     case bfd_mach_ppc_e500:
    411  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e500");
    412   1.4  christos       break;
    413   1.4  christos     case bfd_mach_ppc_e500mc:
    414  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e500mc");
    415   1.4  christos       break;
    416   1.4  christos     case bfd_mach_ppc_e500mc64:
    417  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e500mc64");
    418   1.4  christos       break;
    419   1.4  christos     case bfd_mach_ppc_e5500:
    420  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e5500");
    421   1.4  christos       break;
    422   1.4  christos     case bfd_mach_ppc_e6500:
    423  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e6500");
    424   1.4  christos       break;
    425   1.4  christos     case bfd_mach_ppc_titan:
    426  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "titan");
    427   1.4  christos       break;
    428   1.4  christos     case bfd_mach_ppc_vle:
    429  1.13  christos       out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "vle");
    430   1.4  christos       break;
    431   1.4  christos     default:
    432   1.8  christos       if (info->arch == bfd_arch_powerpc)
    433  1.13  christos 	out.dialect = (ppc_parse_cpu (out.dialect, &out.sticky, "power11")
    434  1.13  christos 		       | PPC_OPCODE_ANY);
    435   1.8  christos       else
    436  1.13  christos 	out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "pwr");
    437   1.7  christos       break;
    438   1.4  christos     }
    439   1.1     skrll 
    440  1.13  christos   for_each_disassembler_option (info, ppc_parse_option, &out);
    441   1.1     skrll 
    442   1.4  christos   info->private_data = priv;
    443  1.13  christos   private_data (info)->dialect = out.dialect;
    444   1.4  christos }
    445   1.4  christos 
    446   1.8  christos #define PPC_OPCD_SEGS (1 + PPC_OP (-1))
    447   1.8  christos static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
    448   1.9  christos #define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
    449   1.9  christos static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
    450   1.8  christos #define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
    451   1.8  christos static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
    452  1.11  christos #define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1))
    453  1.11  christos static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1];
    454   1.8  christos #define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
    455   1.8  christos static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
    456   1.4  christos 
    457  1.10  christos static bool
    458  1.10  christos ppc_symbol_is_valid (asymbol *sym,
    459  1.10  christos 		     struct disassemble_info *info ATTRIBUTE_UNUSED)
    460  1.10  christos {
    461  1.10  christos   elf_symbol_type * est;
    462  1.10  christos 
    463  1.10  christos   if (sym == NULL)
    464  1.10  christos     return false;
    465  1.10  christos 
    466  1.10  christos   est = elf_symbol_from (sym);
    467  1.10  christos 
    468  1.10  christos   /* Ignore ELF hidden, local, no-type symbols.
    469  1.10  christos      These are generated by annobin.  */
    470  1.10  christos   if (est != NULL
    471  1.10  christos       && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN
    472  1.10  christos       && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL
    473  1.10  christos       && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE)
    474  1.10  christos     return false;
    475  1.10  christos 
    476  1.10  christos   return true;
    477  1.10  christos }
    478  1.10  christos 
    479   1.4  christos /* Calculate opcode table indices to speed up disassembly,
    480   1.4  christos    and init dialect.  */
    481   1.4  christos 
    482   1.4  christos void
    483   1.4  christos disassemble_init_powerpc (struct disassemble_info *info)
    484   1.4  christos {
    485  1.10  christos   info->symbol_is_valid = ppc_symbol_is_valid;
    486  1.10  christos 
    487   1.5  christos   if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
    488   1.4  christos     {
    489   1.8  christos       unsigned seg, idx, op;
    490   1.4  christos 
    491   1.8  christos       /* PPC opcodes */
    492   1.8  christos       for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
    493   1.7  christos 	{
    494   1.8  christos 	  powerpc_opcd_indices[seg] = idx;
    495   1.8  christos 	  for (; idx < powerpc_num_opcodes; idx++)
    496   1.8  christos 	    if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
    497   1.8  christos 	      break;
    498   1.7  christos 	}
    499   1.4  christos 
    500   1.9  christos       /* 64-bit prefix opcodes */
    501   1.9  christos       for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
    502   1.9  christos 	{
    503   1.9  christos 	  prefix_opcd_indices[seg] = idx;
    504   1.9  christos 	  for (; idx < prefix_num_opcodes; idx++)
    505   1.9  christos 	    if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
    506   1.9  christos 	      break;
    507   1.9  christos 	}
    508   1.9  christos 
    509   1.8  christos       /* VLE opcodes */
    510   1.8  christos       for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
    511   1.7  christos 	{
    512   1.8  christos 	  vle_opcd_indices[seg] = idx;
    513   1.8  christos 	  for (; idx < vle_num_opcodes; idx++)
    514   1.8  christos 	    {
    515   1.8  christos 	      op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
    516   1.8  christos 	      if (seg < VLE_OP_TO_SEG (op))
    517   1.8  christos 		break;
    518   1.8  christos 	    }
    519   1.7  christos 	}
    520   1.1     skrll 
    521  1.11  christos       /* LSP opcodes */
    522  1.11  christos       for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++)
    523  1.11  christos 	{
    524  1.11  christos 	  lsp_opcd_indices[seg] = idx;
    525  1.11  christos 	  for (; idx < lsp_num_opcodes; idx++)
    526  1.11  christos 	    if (seg < LSP_OP_TO_SEG (lsp_opcodes[idx].opcode))
    527  1.11  christos 	      break;
    528  1.11  christos 	}
    529  1.11  christos 
    530   1.8  christos       /* SPE2 opcodes */
    531   1.8  christos       for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
    532   1.7  christos 	{
    533   1.8  christos 	  spe2_opcd_indices[seg] = idx;
    534   1.8  christos 	  for (; idx < spe2_num_opcodes; idx++)
    535   1.8  christos 	    {
    536   1.8  christos 	      op = SPE2_XOP (spe2_opcodes[idx].opcode);
    537   1.8  christos 	      if (seg < SPE2_XOP_TO_SEG (op))
    538   1.8  christos 		break;
    539   1.8  christos 	    }
    540   1.7  christos 	}
    541   1.7  christos     }
    542   1.7  christos 
    543   1.8  christos   powerpc_init_dialect (info);
    544  1.10  christos   if (info->private_data != NULL)
    545  1.10  christos     {
    546  1.10  christos       private_data (info)->special[0].name = ".got";
    547  1.10  christos       private_data (info)->special[1].name = ".plt";
    548  1.10  christos     }
    549   1.1     skrll }
    550   1.1     skrll 
    551  1.12  christos void
    552  1.12  christos disassemble_free_powerpc (struct disassemble_info *info)
    553  1.12  christos {
    554  1.12  christos   if (info->private_data != NULL)
    555  1.12  christos     {
    556  1.12  christos       free (private_data (info)->special[0].buf);
    557  1.12  christos       free (private_data (info)->special[1].buf);
    558  1.12  christos     }
    559  1.12  christos }
    560  1.12  christos 
    561   1.1     skrll /* Print a big endian PowerPC instruction.  */
    562   1.1     skrll 
    563   1.1     skrll int
    564   1.1     skrll print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
    565   1.1     skrll {
    566   1.4  christos   return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
    567   1.1     skrll }
    568   1.1     skrll 
    569   1.1     skrll /* Print a little endian PowerPC instruction.  */
    570   1.1     skrll 
    571   1.1     skrll int
    572   1.1     skrll print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
    573   1.1     skrll {
    574   1.4  christos   return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
    575   1.1     skrll }
    576   1.1     skrll 
    577   1.1     skrll /* Extract the operand value from the PowerPC or POWER instruction.  */
    578   1.1     skrll 
    579   1.7  christos static int64_t
    580   1.1     skrll operand_value_powerpc (const struct powerpc_operand *operand,
    581   1.7  christos 		       uint64_t insn, ppc_cpu_t dialect)
    582   1.1     skrll {
    583   1.7  christos   int64_t value;
    584   1.9  christos   int invalid = 0;
    585   1.1     skrll   /* Extract the value from the instruction.  */
    586   1.1     skrll   if (operand->extract)
    587   1.1     skrll     value = (*operand->extract) (insn, dialect, &invalid);
    588   1.1     skrll   else
    589   1.1     skrll     {
    590   1.4  christos       if (operand->shift >= 0)
    591   1.4  christos 	value = (insn >> operand->shift) & operand->bitm;
    592   1.4  christos       else
    593   1.4  christos 	value = (insn << -operand->shift) & operand->bitm;
    594   1.1     skrll       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
    595   1.1     skrll 	{
    596   1.1     skrll 	  /* BITM is always some number of zeros followed by some
    597   1.4  christos 	     number of ones, followed by some number of zeros.  */
    598   1.7  christos 	  uint64_t top = operand->bitm;
    599   1.1     skrll 	  /* top & -top gives the rightmost 1 bit, so this
    600   1.1     skrll 	     fills in any trailing zeros.  */
    601   1.1     skrll 	  top |= (top & -top) - 1;
    602   1.1     skrll 	  top &= ~(top >> 1);
    603   1.1     skrll 	  value = (value ^ top) - top;
    604   1.1     skrll 	}
    605   1.1     skrll     }
    606   1.1     skrll 
    607  1.11  christos   if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
    608  1.11  christos     ++value;
    609  1.11  christos 
    610   1.1     skrll   return value;
    611   1.1     skrll }
    612   1.1     skrll 
    613   1.1     skrll /* Determine whether the optional operand(s) should be printed.  */
    614   1.1     skrll 
    615  1.10  christos static bool
    616  1.10  christos skip_optional_operands (const ppc_opindex_t *opindex,
    617  1.10  christos 			uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
    618   1.1     skrll {
    619   1.1     skrll   const struct powerpc_operand *operand;
    620   1.9  christos   int num_optional;
    621   1.1     skrll 
    622   1.9  christos   for (num_optional = 0; *opindex != 0; opindex++)
    623   1.1     skrll     {
    624   1.1     skrll       operand = &powerpc_operands[*opindex];
    625   1.9  christos       if ((operand->flags & PPC_OPERAND_NEXT) != 0)
    626  1.10  christos 	return false;
    627   1.9  christos       if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
    628   1.9  christos 	{
    629  1.10  christos 	  int64_t value = operand_value_powerpc (operand, insn, dialect);
    630  1.10  christos 
    631  1.10  christos 	  if (operand->shift == 52)
    632  1.10  christos 	    *is_pcrel = value != 0;
    633  1.10  christos 
    634   1.9  christos 	  /* Negative count is used as a flag to extract function.  */
    635   1.9  christos 	  --num_optional;
    636  1.10  christos 	  if (value != ppc_optional_operand_value (operand, insn, dialect,
    637  1.10  christos 						   num_optional))
    638  1.10  christos 	    return false;
    639   1.9  christos 	}
    640   1.1     skrll     }
    641   1.1     skrll 
    642  1.10  christos   return true;
    643   1.1     skrll }
    644   1.1     skrll 
    645   1.7  christos /* Find a match for INSN in the opcode table, given machine DIALECT.  */
    646   1.4  christos 
    647   1.4  christos static const struct powerpc_opcode *
    648   1.7  christos lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
    649   1.4  christos {
    650  1.10  christos   const struct powerpc_opcode *opcode, *opcode_end;
    651   1.4  christos   unsigned long op;
    652   1.4  christos 
    653   1.4  christos   /* Get the major opcode of the instruction.  */
    654   1.4  christos   op = PPC_OP (insn);
    655   1.4  christos 
    656   1.4  christos   /* Find the first match in the opcode table for this major opcode.  */
    657   1.4  christos   opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
    658   1.4  christos   for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
    659   1.4  christos        opcode < opcode_end;
    660   1.4  christos        ++opcode)
    661   1.4  christos     {
    662  1.10  christos       const ppc_opindex_t *opindex;
    663   1.4  christos       const struct powerpc_operand *operand;
    664   1.4  christos       int invalid;
    665   1.4  christos 
    666   1.4  christos       if ((insn & opcode->mask) != opcode->opcode
    667   1.7  christos 	  || ((dialect & PPC_OPCODE_ANY) == 0
    668   1.4  christos 	      && ((opcode->flags & dialect) == 0
    669  1.10  christos 		  || (opcode->deprecated & dialect) != 0))
    670  1.10  christos 	  || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
    671   1.4  christos 	continue;
    672   1.4  christos 
    673   1.4  christos       /* Check validity of operands.  */
    674   1.4  christos       invalid = 0;
    675   1.4  christos       for (opindex = opcode->operands; *opindex != 0; opindex++)
    676   1.4  christos 	{
    677   1.4  christos 	  operand = powerpc_operands + *opindex;
    678   1.4  christos 	  if (operand->extract)
    679   1.4  christos 	    (*operand->extract) (insn, dialect, &invalid);
    680   1.4  christos 	}
    681   1.4  christos       if (invalid)
    682   1.4  christos 	continue;
    683   1.4  christos 
    684  1.10  christos       return opcode;
    685   1.4  christos     }
    686   1.4  christos 
    687  1.10  christos   return NULL;
    688   1.4  christos }
    689   1.4  christos 
    690   1.9  christos /* Find a match for INSN in the PREFIX opcode table.  */
    691   1.9  christos 
    692   1.9  christos static const struct powerpc_opcode *
    693   1.9  christos lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
    694   1.9  christos {
    695  1.10  christos   const struct powerpc_opcode *opcode, *opcode_end;
    696   1.9  christos   unsigned long seg;
    697   1.9  christos 
    698   1.9  christos   /* Get the opcode segment of the instruction.  */
    699   1.9  christos   seg = PPC_PREFIX_SEG (insn);
    700   1.9  christos 
    701   1.9  christos   /* Find the first match in the opcode table for this major opcode.  */
    702   1.9  christos   opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
    703   1.9  christos   for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
    704   1.9  christos        opcode < opcode_end;
    705   1.9  christos        ++opcode)
    706   1.9  christos     {
    707  1.10  christos       const ppc_opindex_t *opindex;
    708   1.9  christos       const struct powerpc_operand *operand;
    709   1.9  christos       int invalid;
    710   1.9  christos 
    711   1.9  christos       if ((insn & opcode->mask) != opcode->opcode
    712   1.9  christos 	  || ((dialect & PPC_OPCODE_ANY) == 0
    713  1.10  christos 	      && (opcode->flags & dialect) == 0)
    714  1.10  christos 	  || (opcode->deprecated & dialect) != 0)
    715   1.9  christos 	continue;
    716   1.9  christos 
    717   1.9  christos       /* Check validity of operands.  */
    718   1.9  christos       invalid = 0;
    719   1.9  christos       for (opindex = opcode->operands; *opindex != 0; opindex++)
    720   1.9  christos 	{
    721   1.9  christos 	  operand = powerpc_operands + *opindex;
    722   1.9  christos 	  if (operand->extract)
    723   1.9  christos 	    (*operand->extract) (insn, dialect, &invalid);
    724   1.9  christos 	}
    725   1.9  christos       if (invalid)
    726   1.9  christos 	continue;
    727   1.9  christos 
    728  1.10  christos       return opcode;
    729   1.9  christos     }
    730   1.9  christos 
    731  1.10  christos   return NULL;
    732   1.9  christos }
    733   1.9  christos 
    734   1.4  christos /* Find a match for INSN in the VLE opcode table.  */
    735   1.4  christos 
    736   1.4  christos static const struct powerpc_opcode *
    737  1.10  christos lookup_vle (uint64_t insn, ppc_cpu_t dialect)
    738   1.4  christos {
    739   1.4  christos   const struct powerpc_opcode *opcode;
    740   1.4  christos   const struct powerpc_opcode *opcode_end;
    741   1.4  christos   unsigned op, seg;
    742   1.4  christos 
    743   1.4  christos   op = PPC_OP (insn);
    744   1.4  christos   if (op >= 0x20 && op <= 0x37)
    745   1.4  christos     {
    746   1.4  christos       /* This insn has a 4-bit opcode.  */
    747   1.4  christos       op &= 0x3c;
    748   1.4  christos     }
    749   1.4  christos   seg = VLE_OP_TO_SEG (op);
    750   1.4  christos 
    751   1.4  christos   /* Find the first match in the opcode table for this major opcode.  */
    752   1.4  christos   opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
    753   1.4  christos   for (opcode = vle_opcodes + vle_opcd_indices[seg];
    754   1.4  christos        opcode < opcode_end;
    755   1.4  christos        ++opcode)
    756   1.4  christos     {
    757   1.7  christos       uint64_t table_opcd = opcode->opcode;
    758   1.7  christos       uint64_t table_mask = opcode->mask;
    759  1.10  christos       bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
    760   1.7  christos       uint64_t insn2;
    761  1.10  christos       const ppc_opindex_t *opindex;
    762   1.4  christos       const struct powerpc_operand *operand;
    763   1.4  christos       int invalid;
    764   1.4  christos 
    765   1.4  christos       insn2 = insn;
    766   1.4  christos       if (table_op_is_short)
    767   1.4  christos 	insn2 >>= 16;
    768  1.10  christos       if ((insn2 & table_mask) != table_opcd
    769  1.10  christos 	  || (opcode->deprecated & dialect) != 0)
    770   1.4  christos 	continue;
    771   1.4  christos 
    772   1.4  christos       /* Check validity of operands.  */
    773   1.4  christos       invalid = 0;
    774   1.4  christos       for (opindex = opcode->operands; *opindex != 0; ++opindex)
    775   1.4  christos 	{
    776   1.4  christos 	  operand = powerpc_operands + *opindex;
    777   1.4  christos 	  if (operand->extract)
    778   1.4  christos 	    (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
    779   1.4  christos 	}
    780   1.4  christos       if (invalid)
    781   1.4  christos 	continue;
    782   1.4  christos 
    783   1.4  christos       return opcode;
    784   1.4  christos     }
    785   1.4  christos 
    786   1.4  christos   return NULL;
    787   1.4  christos }
    788   1.4  christos 
    789  1.11  christos /* Find a match for INSN in the LSP opcode table.  */
    790  1.11  christos 
    791  1.11  christos static const struct powerpc_opcode *
    792  1.11  christos lookup_lsp (uint64_t insn, ppc_cpu_t dialect)
    793  1.11  christos {
    794  1.11  christos   const struct powerpc_opcode *opcode, *opcode_end;
    795  1.11  christos   unsigned op, seg;
    796  1.11  christos 
    797  1.11  christos   op = PPC_OP (insn);
    798  1.11  christos   if (op != 0x4)
    799  1.11  christos     return NULL;
    800  1.11  christos 
    801  1.11  christos   seg = LSP_OP_TO_SEG (insn);
    802  1.11  christos 
    803  1.11  christos   /* Find the first match in the opcode table for this opcode.  */
    804  1.11  christos   opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1];
    805  1.11  christos   for (opcode = lsp_opcodes + lsp_opcd_indices[seg];
    806  1.11  christos        opcode < opcode_end;
    807  1.11  christos        ++opcode)
    808  1.11  christos     {
    809  1.11  christos       const ppc_opindex_t *opindex;
    810  1.11  christos       const struct powerpc_operand *operand;
    811  1.11  christos       int invalid;
    812  1.11  christos 
    813  1.11  christos       if ((insn & opcode->mask) != opcode->opcode
    814  1.11  christos 	  || (opcode->deprecated & dialect) != 0)
    815  1.11  christos 	continue;
    816  1.11  christos 
    817  1.11  christos       /* Check validity of operands.  */
    818  1.11  christos       invalid = 0;
    819  1.11  christos       for (opindex = opcode->operands; *opindex != 0; ++opindex)
    820  1.11  christos 	{
    821  1.11  christos 	  operand = powerpc_operands + *opindex;
    822  1.11  christos 	  if (operand->extract)
    823  1.11  christos 	    (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
    824  1.11  christos 	}
    825  1.11  christos       if (invalid)
    826  1.11  christos 	continue;
    827  1.11  christos 
    828  1.11  christos       return opcode;
    829  1.11  christos     }
    830  1.11  christos 
    831  1.11  christos   return NULL;
    832  1.11  christos }
    833  1.11  christos 
    834   1.7  christos /* Find a match for INSN in the SPE2 opcode table.  */
    835   1.7  christos 
    836   1.7  christos static const struct powerpc_opcode *
    837  1.10  christos lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
    838   1.7  christos {
    839   1.7  christos   const struct powerpc_opcode *opcode, *opcode_end;
    840   1.7  christos   unsigned op, xop, seg;
    841   1.7  christos 
    842   1.7  christos   op = PPC_OP (insn);
    843   1.7  christos   if (op != 0x4)
    844   1.7  christos     {
    845   1.7  christos       /* This is not SPE2 insn.
    846   1.7  christos        * All SPE2 instructions have OP=4 and differs by XOP  */
    847   1.7  christos       return NULL;
    848   1.7  christos     }
    849   1.7  christos   xop = SPE2_XOP (insn);
    850   1.7  christos   seg = SPE2_XOP_TO_SEG (xop);
    851   1.7  christos 
    852  1.11  christos   /* Find the first match in the opcode table for this opcode.  */
    853   1.7  christos   opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
    854   1.7  christos   for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
    855   1.7  christos        opcode < opcode_end;
    856   1.7  christos        ++opcode)
    857   1.7  christos     {
    858   1.7  christos       uint64_t table_opcd = opcode->opcode;
    859   1.7  christos       uint64_t table_mask = opcode->mask;
    860   1.7  christos       uint64_t insn2;
    861  1.10  christos       const ppc_opindex_t *opindex;
    862   1.7  christos       const struct powerpc_operand *operand;
    863   1.7  christos       int invalid;
    864   1.7  christos 
    865   1.7  christos       insn2 = insn;
    866  1.10  christos       if ((insn2 & table_mask) != table_opcd
    867  1.10  christos 	  || (opcode->deprecated & dialect) != 0)
    868   1.7  christos 	continue;
    869   1.7  christos 
    870   1.7  christos       /* Check validity of operands.  */
    871   1.7  christos       invalid = 0;
    872   1.7  christos       for (opindex = opcode->operands; *opindex != 0; ++opindex)
    873   1.7  christos 	{
    874   1.7  christos 	  operand = powerpc_operands + *opindex;
    875   1.7  christos 	  if (operand->extract)
    876   1.7  christos 	    (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
    877   1.7  christos 	}
    878   1.7  christos       if (invalid)
    879   1.7  christos 	continue;
    880   1.7  christos 
    881   1.7  christos       return opcode;
    882   1.7  christos     }
    883   1.7  christos 
    884   1.7  christos   return NULL;
    885   1.7  christos }
    886   1.7  christos 
    887  1.10  christos static arelent *
    888  1.10  christos bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
    889  1.10  christos {
    890  1.10  christos   while (lo < hi)
    891  1.10  christos     {
    892  1.10  christos       arelent **mid = lo + (hi - lo) / 2;
    893  1.10  christos       arelent *rel = *mid;
    894  1.10  christos 
    895  1.10  christos       if (vma < rel->address)
    896  1.10  christos 	hi = mid;
    897  1.10  christos       else if (vma > rel->address)
    898  1.10  christos 	lo = mid + 1;
    899  1.10  christos       else
    900  1.10  christos 	return rel;
    901  1.10  christos     }
    902  1.10  christos   return NULL;
    903  1.10  christos }
    904  1.10  christos 
    905  1.10  christos static bool
    906  1.10  christos print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
    907  1.10  christos {
    908  1.10  christos   if (sb->name != NULL)
    909  1.10  christos     {
    910  1.10  christos       asection *s = sb->sec;
    911  1.10  christos       if (s == NULL)
    912  1.10  christos 	{
    913  1.10  christos 	  s = bfd_get_section_by_name (info->section->owner, sb->name);
    914  1.10  christos 	  sb->sec = s;
    915  1.10  christos 	  if (s == NULL)
    916  1.10  christos 	    sb->name = NULL;
    917  1.10  christos 	}
    918  1.10  christos       if (s != NULL
    919  1.10  christos 	  && vma >= s->vma
    920  1.10  christos 	  && vma < s->vma + s->size)
    921  1.10  christos 	{
    922  1.10  christos 	  asymbol *sym = NULL;
    923  1.10  christos 	  uint64_t ent = 0;
    924  1.10  christos 	  if (info->dynrelcount > 0)
    925  1.10  christos 	    {
    926  1.10  christos 	      arelent **lo = info->dynrelbuf;
    927  1.10  christos 	      arelent **hi = lo + info->dynrelcount;
    928  1.10  christos 	      arelent *rel = bsearch_reloc (lo, hi, vma);
    929  1.10  christos 	      if (rel != NULL && rel->sym_ptr_ptr != NULL)
    930  1.10  christos 		sym = *rel->sym_ptr_ptr;
    931  1.10  christos 	    }
    932  1.10  christos 	  if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
    933  1.10  christos 	    {
    934  1.10  christos 	      if (sb->buf == NULL
    935  1.10  christos 		  && !bfd_malloc_and_get_section (s->owner, s, &sb->buf))
    936  1.10  christos 		sb->name = NULL;
    937  1.10  christos 	      if (sb->buf != NULL)
    938  1.10  christos 		{
    939  1.10  christos 		  ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma));
    940  1.10  christos 		  if (ent != 0)
    941  1.10  christos 		    sym = (*info->symbol_at_address_func) (ent, info);
    942  1.10  christos 		}
    943  1.10  christos 	    }
    944  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
    945  1.10  christos 	  if (sym != NULL)
    946  1.11  christos 	    {
    947  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
    948  1.11  christos 					    "%s", bfd_asymbol_name (sym));
    949  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
    950  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
    951  1.11  christos 					    "%s", sb->name + 1);
    952  1.11  christos 	    }
    953  1.10  christos 	  else
    954  1.11  christos 	    {
    955  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_address,
    956  1.11  christos 					    "%" PRIx64, ent);
    957  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
    958  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
    959  1.11  christos 					    "%s", sb->name + 1);
    960  1.11  christos 	    }
    961  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
    962  1.10  christos 	  return true;
    963  1.10  christos 	}
    964  1.10  christos     }
    965  1.10  christos   return false;
    966  1.10  christos }
    967  1.10  christos 
    968   1.1     skrll /* Print a PowerPC or POWER instruction.  */
    969   1.1     skrll 
    970   1.1     skrll static int
    971   1.1     skrll print_insn_powerpc (bfd_vma memaddr,
    972   1.1     skrll 		    struct disassemble_info *info,
    973   1.1     skrll 		    int bigendian,
    974   1.1     skrll 		    ppc_cpu_t dialect)
    975   1.1     skrll {
    976   1.1     skrll   bfd_byte buffer[4];
    977   1.1     skrll   int status;
    978   1.7  christos   uint64_t insn;
    979   1.1     skrll   const struct powerpc_opcode *opcode;
    980   1.8  christos   int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
    981   1.1     skrll 
    982   1.1     skrll   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    983   1.8  christos 
    984   1.8  christos   /* The final instruction may be a 2-byte VLE insn.  */
    985   1.8  christos   if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
    986   1.8  christos     {
    987   1.8  christos       /* Clear buffer so unused bytes will not have garbage in them.  */
    988  1.10  christos       buffer[2] = buffer[3] = 0;
    989   1.8  christos       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
    990  1.10  christos       insn_length = 2;
    991   1.8  christos     }
    992   1.8  christos 
    993   1.1     skrll   if (status != 0)
    994   1.1     skrll     {
    995   1.8  christos       (*info->memory_error_func) (status, memaddr, info);
    996   1.8  christos       return -1;
    997   1.1     skrll     }
    998   1.1     skrll 
    999   1.1     skrll   if (bigendian)
   1000   1.1     skrll     insn = bfd_getb32 (buffer);
   1001   1.1     skrll   else
   1002   1.1     skrll     insn = bfd_getl32 (buffer);
   1003   1.1     skrll 
   1004   1.4  christos   /* Get the major opcode of the insn.  */
   1005   1.4  christos   opcode = NULL;
   1006  1.10  christos   if ((dialect & PPC_OPCODE_POWER10) != 0
   1007   1.9  christos       && PPC_OP (insn) == 0x1)
   1008   1.9  christos     {
   1009   1.9  christos       uint64_t temp_insn, suffix;
   1010   1.9  christos       status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
   1011   1.9  christos       if (status == 0)
   1012   1.9  christos 	{
   1013   1.9  christos 	  if (bigendian)
   1014   1.9  christos 	    suffix = bfd_getb32 (buffer);
   1015   1.9  christos 	  else
   1016   1.9  christos 	    suffix = bfd_getl32 (buffer);
   1017   1.9  christos 	  temp_insn = (insn << 32) | suffix;
   1018   1.9  christos 	  opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
   1019   1.9  christos 	  if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
   1020   1.9  christos 	    opcode = lookup_prefix (temp_insn, dialect);
   1021   1.9  christos 	  if (opcode != NULL)
   1022   1.9  christos 	    {
   1023   1.9  christos 	      insn = temp_insn;
   1024   1.9  christos 	      insn_length = 8;
   1025   1.9  christos 	      if ((info->flags & WIDE_OUTPUT) != 0)
   1026   1.9  christos 		info->bytes_per_line = 8;
   1027   1.9  christos 	    }
   1028   1.9  christos 	}
   1029   1.9  christos     }
   1030   1.9  christos   if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
   1031   1.4  christos     {
   1032  1.10  christos       opcode = lookup_vle (insn, dialect);
   1033   1.8  christos       if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
   1034   1.8  christos 	{
   1035   1.8  christos 	  /* The operands will be fetched out of the 16-bit instruction.  */
   1036   1.8  christos 	  insn >>= 16;
   1037   1.8  christos 	  insn_length = 2;
   1038   1.8  christos 	}
   1039   1.4  christos     }
   1040  1.10  christos   if (opcode == NULL && insn_length == 4)
   1041  1.10  christos     {
   1042  1.11  christos       if ((dialect & PPC_OPCODE_LSP) != 0)
   1043  1.11  christos 	opcode = lookup_lsp (insn, dialect);
   1044  1.10  christos       if ((dialect & PPC_OPCODE_SPE2) != 0)
   1045  1.10  christos 	opcode = lookup_spe2 (insn, dialect);
   1046  1.10  christos       if (opcode == NULL)
   1047  1.10  christos 	opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
   1048  1.10  christos       if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
   1049  1.10  christos 	opcode = lookup_powerpc (insn, dialect);
   1050  1.11  christos       if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
   1051  1.11  christos 	opcode = lookup_spe2 (insn, dialect);
   1052  1.11  christos       if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
   1053  1.11  christos 	opcode = lookup_lsp (insn, dialect);
   1054  1.10  christos     }
   1055   1.1     skrll 
   1056   1.4  christos   if (opcode != NULL)
   1057   1.1     skrll     {
   1058  1.10  christos       const ppc_opindex_t *opindex;
   1059   1.1     skrll       const struct powerpc_operand *operand;
   1060   1.9  christos       enum {
   1061   1.9  christos 	need_comma = 0,
   1062   1.9  christos 	need_1space = 1,
   1063   1.9  christos 	need_2spaces = 2,
   1064   1.9  christos 	need_3spaces = 3,
   1065   1.9  christos 	need_4spaces = 4,
   1066   1.9  christos 	need_5spaces = 5,
   1067   1.9  christos 	need_6spaces = 6,
   1068   1.9  christos 	need_7spaces = 7,
   1069   1.9  christos 	need_paren
   1070   1.9  christos       } op_separator;
   1071  1.10  christos       bool skip_optional;
   1072  1.10  christos       bool is_pcrel;
   1073  1.10  christos       uint64_t d34;
   1074   1.9  christos       int blanks;
   1075   1.9  christos 
   1076  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
   1077  1.11  christos 				    "%s", opcode->name);
   1078  1.11  christos       /* gdb fprintf_styled_func doesn't return count printed.  */
   1079   1.9  christos       blanks = 8 - strlen (opcode->name);
   1080   1.9  christos       if (blanks <= 0)
   1081   1.9  christos 	blanks = 1;
   1082   1.1     skrll 
   1083   1.1     skrll       /* Now extract and print the operands.  */
   1084   1.9  christos       op_separator = blanks;
   1085  1.10  christos       skip_optional = false;
   1086  1.10  christos       is_pcrel = false;
   1087  1.10  christos       d34 = 0;
   1088   1.1     skrll       for (opindex = opcode->operands; *opindex != 0; opindex++)
   1089   1.1     skrll 	{
   1090   1.7  christos 	  int64_t value;
   1091   1.1     skrll 
   1092   1.1     skrll 	  operand = powerpc_operands + *opindex;
   1093   1.1     skrll 
   1094   1.9  christos 	  /* If all of the optional operands past this one have their
   1095   1.9  christos 	     default value, then don't print any of them.  Except in
   1096   1.9  christos 	     raw mode, print them all.  */
   1097   1.9  christos 	  if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
   1098   1.9  christos 	      && (dialect & PPC_OPCODE_RAW) == 0)
   1099   1.1     skrll 	    {
   1100   1.9  christos 	      if (!skip_optional)
   1101  1.10  christos 		skip_optional = skip_optional_operands (opindex, insn,
   1102  1.10  christos 							dialect, &is_pcrel);
   1103   1.1     skrll 	      if (skip_optional)
   1104   1.1     skrll 		continue;
   1105   1.1     skrll 	    }
   1106   1.1     skrll 
   1107   1.1     skrll 	  value = operand_value_powerpc (operand, insn, dialect);
   1108   1.1     skrll 
   1109   1.9  christos 	  if (op_separator == need_comma)
   1110  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
   1111   1.9  christos 	  else if (op_separator == need_paren)
   1112  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
   1113   1.9  christos 	  else
   1114  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
   1115  1.11  christos 					  op_separator, " ");
   1116   1.1     skrll 
   1117   1.1     skrll 	  /* Print the operand as directed by the flags.  */
   1118   1.1     skrll 	  if ((operand->flags & PPC_OPERAND_GPR) != 0
   1119   1.1     skrll 	      || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
   1120  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1121  1.11  christos 					  "r%" PRId64, value);
   1122   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_FPR) != 0)
   1123  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1124  1.11  christos 					  "f%" PRId64, value);
   1125   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_VR) != 0)
   1126  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1127  1.11  christos 					  "v%" PRId64, value);
   1128   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_VSR) != 0)
   1129  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1130  1.11  christos 					  "vs%" PRId64, value);
   1131  1.11  christos 	  else if ((operand->flags & PPC_OPERAND_DMR) != 0)
   1132  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1133  1.11  christos 					  "dm%" PRId64, value);
   1134  1.10  christos 	  else if ((operand->flags & PPC_OPERAND_ACC) != 0)
   1135  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1136  1.11  christos 					  "a%" PRId64, value);
   1137   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
   1138   1.1     skrll 	    (*info->print_address_func) (memaddr + value, info);
   1139   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
   1140   1.1     skrll 	    (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
   1141   1.5  christos 	  else if ((operand->flags & PPC_OPERAND_FSL) != 0)
   1142  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1143  1.11  christos 					  "fsl%" PRId64, value);
   1144   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_FCR) != 0)
   1145  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1146  1.11  christos 					  "fcr%" PRId64, value);
   1147   1.1     skrll 	  else if ((operand->flags & PPC_OPERAND_UDI) != 0)
   1148  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1149  1.11  christos 					  "%" PRId64, value);
   1150   1.4  christos 	  else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
   1151   1.9  christos 		   && (operand->flags & PPC_OPERAND_CR_BIT) == 0
   1152   1.4  christos 		   && (((dialect & PPC_OPCODE_PPC) != 0)
   1153   1.4  christos 		       || ((dialect & PPC_OPCODE_VLE) != 0)))
   1154  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1155  1.11  christos 					  "cr%" PRId64, value);
   1156   1.9  christos 	  else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
   1157   1.9  christos 		   && (operand->flags & PPC_OPERAND_CR_REG) == 0
   1158   1.4  christos 		   && (((dialect & PPC_OPCODE_PPC) != 0)
   1159   1.4  christos 		       || ((dialect & PPC_OPCODE_VLE) != 0)))
   1160   1.1     skrll 	    {
   1161   1.4  christos 	      static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
   1162   1.4  christos 	      int cr;
   1163   1.4  christos 	      int cc;
   1164   1.4  christos 
   1165   1.4  christos 	      cr = value >> 2;
   1166  1.11  christos 	      cc = value & 3;
   1167   1.4  christos 	      if (cr != 0)
   1168  1.11  christos 		{
   1169  1.11  christos 		  (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1170  1.11  christos 						"4*");
   1171  1.11  christos 		  (*info->fprintf_styled_func) (info->stream,
   1172  1.11  christos 						dis_style_register,
   1173  1.11  christos 						"cr%d", cr);
   1174  1.11  christos 		  (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1175  1.11  christos 						"+");
   1176  1.11  christos 		}
   1177  1.11  christos 
   1178  1.11  christos 	      (*info->fprintf_styled_func) (info->stream,
   1179  1.11  christos 					    dis_style_sub_mnemonic,
   1180  1.11  christos 					    "%s", cbnames[cc]);
   1181   1.1     skrll 	    }
   1182   1.3  christos 	  else
   1183  1.11  christos 	    {
   1184  1.11  christos 	      /* An immediate, but what style?  */
   1185  1.11  christos 	      enum disassembler_style style;
   1186  1.11  christos 
   1187  1.11  christos 	      if ((operand->flags & PPC_OPERAND_PARENS) != 0)
   1188  1.11  christos 		style = dis_style_address_offset;
   1189  1.11  christos 	      else
   1190  1.11  christos 		style = dis_style_immediate;
   1191  1.11  christos 
   1192  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, style,
   1193  1.11  christos 					    "%" PRId64, value);
   1194  1.11  christos 	    }
   1195   1.1     skrll 
   1196  1.10  christos 	  if (operand->shift == 52)
   1197  1.10  christos 	    is_pcrel = value != 0;
   1198  1.10  christos 	  else if (operand->bitm == UINT64_C (0x3ffffffff))
   1199  1.10  christos 	    d34 = value;
   1200  1.10  christos 
   1201   1.9  christos 	  if (op_separator == need_paren)
   1202  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
   1203   1.1     skrll 
   1204   1.9  christos 	  op_separator = need_comma;
   1205   1.9  christos 	  if ((operand->flags & PPC_OPERAND_PARENS) != 0)
   1206   1.9  christos 	    op_separator = need_paren;
   1207   1.1     skrll 	}
   1208   1.1     skrll 
   1209  1.10  christos       if (is_pcrel)
   1210  1.10  christos 	{
   1211  1.10  christos 	  d34 += memaddr;
   1212  1.11  christos 	  (*info->fprintf_styled_func) (info->stream,
   1213  1.11  christos 					dis_style_comment_start,
   1214  1.11  christos 					"\t# %" PRIx64, d34);
   1215  1.10  christos 	  asymbol *sym = (*info->symbol_at_address_func) (d34, info);
   1216  1.10  christos 	  if (sym)
   1217  1.11  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1218  1.11  christos 					  " <%s>", bfd_asymbol_name (sym));
   1219  1.10  christos 
   1220  1.10  christos 	  if (info->private_data != NULL
   1221  1.10  christos 	      && info->section != NULL
   1222  1.10  christos 	      && info->section->owner != NULL
   1223  1.10  christos 	      && (bfd_get_file_flags (info->section->owner)
   1224  1.10  christos 		  & (EXEC_P | DYNAMIC)) != 0
   1225  1.10  christos 	      && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
   1226  1.10  christos 		  == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
   1227  1.10  christos 	    {
   1228  1.10  christos 	      for (int i = 0; i < 2; i++)
   1229  1.10  christos 		if (print_got_plt (private_data (info)->special + i, d34, info))
   1230  1.10  christos 		  break;
   1231  1.10  christos 	    }
   1232  1.10  christos 	}
   1233  1.10  christos 
   1234   1.8  christos       /* We have found and printed an instruction.  */
   1235   1.8  christos       return insn_length;
   1236   1.1     skrll     }
   1237   1.1     skrll 
   1238   1.1     skrll   /* We could not find a match.  */
   1239  1.10  christos   if (insn_length == 4)
   1240  1.11  christos     (*info->fprintf_styled_func) (info->stream,
   1241  1.11  christos 				  dis_style_assembler_directive, ".long");
   1242  1.10  christos   else
   1243  1.11  christos     {
   1244  1.11  christos       (*info->fprintf_styled_func) (info->stream,
   1245  1.11  christos 				    dis_style_assembler_directive, ".word");
   1246  1.11  christos       insn >>= 16;
   1247  1.11  christos     }
   1248  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
   1249  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
   1250  1.11  christos 				(unsigned int) insn);
   1251  1.11  christos 
   1252  1.11  christos 
   1253  1.10  christos   return insn_length;
   1254   1.1     skrll }
   1255   1.1     skrll 
   1256   1.9  christos const disasm_options_and_args_t *
   1257   1.7  christos disassembler_options_powerpc (void)
   1258   1.7  christos {
   1259   1.9  christos   static disasm_options_and_args_t *opts_and_args;
   1260   1.7  christos 
   1261   1.9  christos   if (opts_and_args == NULL)
   1262   1.7  christos     {
   1263   1.7  christos       size_t i, num_options = ARRAY_SIZE (ppc_opts);
   1264   1.9  christos       disasm_options_t *opts;
   1265   1.9  christos 
   1266   1.9  christos       opts_and_args = XNEW (disasm_options_and_args_t);
   1267   1.9  christos       opts_and_args->args = NULL;
   1268   1.9  christos 
   1269   1.9  christos       opts = &opts_and_args->options;
   1270   1.7  christos       opts->name = XNEWVEC (const char *, num_options + 1);
   1271   1.9  christos       opts->description = NULL;
   1272   1.9  christos       opts->arg = NULL;
   1273   1.7  christos       for (i = 0; i < num_options; i++)
   1274   1.7  christos 	opts->name[i] = ppc_opts[i].opt;
   1275   1.7  christos       /* The array we return must be NULL terminated.  */
   1276   1.7  christos       opts->name[i] = NULL;
   1277   1.7  christos     }
   1278   1.7  christos 
   1279   1.9  christos   return opts_and_args;
   1280   1.7  christos }
   1281   1.7  christos 
   1282   1.1     skrll void
   1283   1.1     skrll print_ppc_disassembler_options (FILE *stream)
   1284   1.1     skrll {
   1285   1.3  christos   unsigned int i, col;
   1286   1.3  christos 
   1287   1.3  christos   fprintf (stream, _("\n\
   1288   1.1     skrll The following PPC specific disassembler options are supported for use with\n\
   1289   1.3  christos the -M switch:\n"));
   1290   1.1     skrll 
   1291   1.7  christos   for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
   1292   1.3  christos     {
   1293   1.3  christos       col += fprintf (stream, " %s,", ppc_opts[i].opt);
   1294   1.3  christos       if (col > 66)
   1295   1.3  christos 	{
   1296   1.3  christos 	  fprintf (stream, "\n");
   1297   1.3  christos 	  col = 0;
   1298   1.3  christos 	}
   1299   1.3  christos     }
   1300   1.7  christos   fprintf (stream, "\n");
   1301   1.1     skrll }
   1302