xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/ppc-dis.c (revision dd7241df2fae9da4ea2bd20a68f001fa86ecf909)
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