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