1 /* ppc-dis.c -- Disassemble PowerPC instructions
2    Copyright (C) 1994-2021 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   { "e200z4",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
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 | PPC_OPCODE_LSP),
139     0 },
140   { "e300",    PPC_OPCODE_PPC | PPC_OPCODE_E300,
141     0 },
142   { "e500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
143 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
144 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
145 		| PPC_OPCODE_E500),
146     0 },
147   { "e500mc",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
148 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
149 		| PPC_OPCODE_E500MC),
150     0 },
151   { "e500mc64",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
152 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
153 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
154 		| PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
155     0 },
156   { "e5500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
157 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
158 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
159 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
160     0 },
161   { "e6500",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
162 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
163 		| PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
164 		| PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
165 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
166     0 },
167   { "e500x2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
168 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
169 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
170 		| PPC_OPCODE_E500),
171     0 },
172   { "efs",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
173     0 },
174   { "efs2",    PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
175     0 },
176   { "power4",  PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
177     0 },
178   { "power5",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
179 		| PPC_OPCODE_POWER5),
180     0 },
181   { "power6",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
182 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
183     0 },
184   { "power7",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
185 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
186 		| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
187     0 },
188   { "power8",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
189 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
190 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
191 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
192     0 },
193   { "power9",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
194 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
195 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
196 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
197     0 },
198   { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
199 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
200 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
201 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
202     0 },
203   { "future",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
204 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
205 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
206 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
207     0 },
208   { "ppc",     PPC_OPCODE_PPC,
209     0 },
210   { "ppc32",   PPC_OPCODE_PPC,
211     0 },
212   { "32",      PPC_OPCODE_PPC,
213     0 },
214   { "ppc64",   PPC_OPCODE_PPC | PPC_OPCODE_64,
215     0 },
216   { "64",      PPC_OPCODE_PPC | PPC_OPCODE_64,
217     0 },
218   { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
219     0 },
220   { "ppcps",   PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
221     0 },
222   { "pwr",     PPC_OPCODE_POWER,
223     0 },
224   { "pwr2",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
225     0 },
226   { "pwr4",    PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
227     0 },
228   { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
229 		| PPC_OPCODE_POWER5),
230     0 },
231   { "pwr5x",   (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
232 		| PPC_OPCODE_POWER5),
233     0 },
234   { "pwr6",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
235 		| PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
236     0 },
237   { "pwr7",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
238 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
239 		| PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
240     0 },
241   { "pwr8",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
242 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
243 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
244 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
245     0 },
246   { "pwr9",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
247 		| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
248 		| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
249 		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
250     0 },
251   { "pwr10",   (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_POWER8 | PPC_OPCODE_POWER9
254 		| PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
255     0 },
256   { "pwrx",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
257     0 },
258   { "raw",     PPC_OPCODE_PPC,
259     PPC_OPCODE_RAW },
260   { "spe",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
261     PPC_OPCODE_SPE },
262   { "spe2",     PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
263     PPC_OPCODE_SPE2 },
264   { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
265 		| PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
266     0 },
267   { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
268 		| PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
269 		| PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
270 		| PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
271     PPC_OPCODE_VLE },
272   { "vsx",     PPC_OPCODE_PPC,
273     PPC_OPCODE_VSX },
274 };
275 
276 /* Switch between Booke and VLE dialects for interlinked dumps.  */
277 static ppc_cpu_t
get_powerpc_dialect(struct disassemble_info * info)278 get_powerpc_dialect (struct disassemble_info *info)
279 {
280   ppc_cpu_t dialect = 0;
281 
282   if (info->private_data)
283     dialect = private_data (info)->dialect;
284 
285   /* Disassemble according to the section headers flags for VLE-mode.  */
286   if (dialect & PPC_OPCODE_VLE
287       && info->section != NULL && info->section->owner != NULL
288       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
289       && elf_object_id (info->section->owner) == PPC32_ELF_DATA
290       && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
291     return dialect;
292   else
293     return dialect & ~ PPC_OPCODE_VLE;
294 }
295 
296 /* Handle -m and -M options that set cpu type, and .machine arg.  */
297 
298 ppc_cpu_t
ppc_parse_cpu(ppc_cpu_t ppc_cpu,ppc_cpu_t * sticky,const char * arg)299 ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
300 {
301   unsigned int i;
302 
303   for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
304     if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
305       {
306 	if (ppc_opts[i].sticky)
307 	  {
308 	    *sticky |= ppc_opts[i].sticky;
309 	    if ((ppc_cpu & ~*sticky) != 0)
310 	      break;
311 	  }
312 	ppc_cpu = ppc_opts[i].cpu;
313 	break;
314       }
315   if (i >= ARRAY_SIZE (ppc_opts))
316     return 0;
317 
318   ppc_cpu |= *sticky;
319   return ppc_cpu;
320 }
321 
322 /* Determine which set of machines to disassemble for.  */
323 
324 static void
powerpc_init_dialect(struct disassemble_info * info)325 powerpc_init_dialect (struct disassemble_info *info)
326 {
327   ppc_cpu_t dialect = 0;
328   ppc_cpu_t sticky = 0;
329   struct dis_private *priv = calloc (sizeof (*priv), 1);
330 
331   if (priv == NULL)
332     return;
333 
334   switch (info->mach)
335     {
336     case bfd_mach_ppc_403:
337     case bfd_mach_ppc_403gc:
338       dialect = ppc_parse_cpu (dialect, &sticky, "403");
339       break;
340     case bfd_mach_ppc_405:
341       dialect = ppc_parse_cpu (dialect, &sticky, "405");
342       break;
343     case bfd_mach_ppc_601:
344       dialect = ppc_parse_cpu (dialect, &sticky, "601");
345       break;
346     case bfd_mach_ppc_750:
347       dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
348       break;
349     case bfd_mach_ppc_a35:
350     case bfd_mach_ppc_rs64ii:
351     case bfd_mach_ppc_rs64iii:
352       dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
353       break;
354     case bfd_mach_ppc_e500:
355       dialect = ppc_parse_cpu (dialect, &sticky, "e500");
356       break;
357     case bfd_mach_ppc_e500mc:
358       dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
359       break;
360     case bfd_mach_ppc_e500mc64:
361       dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
362       break;
363     case bfd_mach_ppc_e5500:
364       dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
365       break;
366     case bfd_mach_ppc_e6500:
367       dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
368       break;
369     case bfd_mach_ppc_titan:
370       dialect = ppc_parse_cpu (dialect, &sticky, "titan");
371       break;
372     case bfd_mach_ppc_vle:
373       dialect = ppc_parse_cpu (dialect, &sticky, "vle");
374       break;
375     default:
376       if (info->arch == bfd_arch_powerpc)
377 	dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
378       else
379 	dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
380       break;
381     }
382 
383   const char *opt;
384   FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
385     {
386       ppc_cpu_t new_cpu = 0;
387 
388       if (disassembler_options_cmp (opt, "32") == 0)
389 	dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
390       else if (disassembler_options_cmp (opt, "64") == 0)
391 	dialect |= PPC_OPCODE_64;
392       else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
393 	dialect = new_cpu;
394       else
395 	/* xgettext: c-format */
396 	opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
397     }
398 
399   info->private_data = priv;
400   private_data (info)->dialect = dialect;
401 }
402 
403 #define PPC_OPCD_SEGS (1 + PPC_OP (-1))
404 static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
405 #define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
406 static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
407 #define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
408 static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
409 #define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
410 static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
411 
412 static bool
ppc_symbol_is_valid(asymbol * sym,struct disassemble_info * info ATTRIBUTE_UNUSED)413 ppc_symbol_is_valid (asymbol *sym,
414 		     struct disassemble_info *info ATTRIBUTE_UNUSED)
415 {
416   elf_symbol_type * est;
417 
418   if (sym == NULL)
419     return false;
420 
421   est = elf_symbol_from (sym);
422 
423   /* Ignore ELF hidden, local, no-type symbols.
424      These are generated by annobin.  */
425   if (est != NULL
426       && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN
427       && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL
428       && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE)
429     return false;
430 
431   return true;
432 }
433 
434 /* Calculate opcode table indices to speed up disassembly,
435    and init dialect.  */
436 
437 void
disassemble_init_powerpc(struct disassemble_info * info)438 disassemble_init_powerpc (struct disassemble_info *info)
439 {
440   info->symbol_is_valid = ppc_symbol_is_valid;
441 
442   if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
443     {
444       unsigned seg, idx, op;
445 
446       /* PPC opcodes */
447       for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
448 	{
449 	  powerpc_opcd_indices[seg] = idx;
450 	  for (; idx < powerpc_num_opcodes; idx++)
451 	    if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
452 	      break;
453 	}
454 
455       /* 64-bit prefix opcodes */
456       for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
457 	{
458 	  prefix_opcd_indices[seg] = idx;
459 	  for (; idx < prefix_num_opcodes; idx++)
460 	    if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
461 	      break;
462 	}
463 
464       /* VLE opcodes */
465       for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
466 	{
467 	  vle_opcd_indices[seg] = idx;
468 	  for (; idx < vle_num_opcodes; idx++)
469 	    {
470 	      op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
471 	      if (seg < VLE_OP_TO_SEG (op))
472 		break;
473 	    }
474 	}
475 
476       /* SPE2 opcodes */
477       for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
478 	{
479 	  spe2_opcd_indices[seg] = idx;
480 	  for (; idx < spe2_num_opcodes; idx++)
481 	    {
482 	      op = SPE2_XOP (spe2_opcodes[idx].opcode);
483 	      if (seg < SPE2_XOP_TO_SEG (op))
484 		break;
485 	    }
486 	}
487     }
488 
489   powerpc_init_dialect (info);
490   if (info->private_data != NULL)
491     {
492       private_data (info)->special[0].name = ".got";
493       private_data (info)->special[1].name = ".plt";
494     }
495 }
496 
497 /* Print a big endian PowerPC instruction.  */
498 
499 int
print_insn_big_powerpc(bfd_vma memaddr,struct disassemble_info * info)500 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
501 {
502   return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
503 }
504 
505 /* Print a little endian PowerPC instruction.  */
506 
507 int
print_insn_little_powerpc(bfd_vma memaddr,struct disassemble_info * info)508 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
509 {
510   return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
511 }
512 
513 /* Extract the operand value from the PowerPC or POWER instruction.  */
514 
515 static int64_t
operand_value_powerpc(const struct powerpc_operand * operand,uint64_t insn,ppc_cpu_t dialect)516 operand_value_powerpc (const struct powerpc_operand *operand,
517 		       uint64_t insn, ppc_cpu_t dialect)
518 {
519   int64_t value;
520   int invalid = 0;
521   /* Extract the value from the instruction.  */
522   if (operand->extract)
523     value = (*operand->extract) (insn, dialect, &invalid);
524   else
525     {
526       if (operand->shift >= 0)
527 	value = (insn >> operand->shift) & operand->bitm;
528       else
529 	value = (insn << -operand->shift) & operand->bitm;
530       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
531 	{
532 	  /* BITM is always some number of zeros followed by some
533 	     number of ones, followed by some number of zeros.  */
534 	  uint64_t top = operand->bitm;
535 	  /* top & -top gives the rightmost 1 bit, so this
536 	     fills in any trailing zeros.  */
537 	  top |= (top & -top) - 1;
538 	  top &= ~(top >> 1);
539 	  value = (value ^ top) - top;
540 	}
541     }
542 
543   return value;
544 }
545 
546 /* Determine whether the optional operand(s) should be printed.  */
547 
548 static bool
skip_optional_operands(const unsigned char * opindex,uint64_t insn,ppc_cpu_t dialect,bool * is_pcrel)549 skip_optional_operands (const unsigned char *opindex,
550 			uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
551 {
552   const struct powerpc_operand *operand;
553   int num_optional;
554 
555   for (num_optional = 0; *opindex != 0; opindex++)
556     {
557       operand = &powerpc_operands[*opindex];
558       if ((operand->flags & PPC_OPERAND_NEXT) != 0)
559 	return false;
560       if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
561 	{
562 	  int64_t value = operand_value_powerpc (operand, insn, dialect);
563 
564 	  if (operand->shift == 52)
565 	    *is_pcrel = value != 0;
566 
567 	  /* Negative count is used as a flag to extract function.  */
568 	  --num_optional;
569 	  if (value != ppc_optional_operand_value (operand, insn, dialect,
570 						   num_optional))
571 	    return false;
572 	}
573     }
574 
575   return true;
576 }
577 
578 /* Find a match for INSN in the opcode table, given machine DIALECT.  */
579 
580 static const struct powerpc_opcode *
lookup_powerpc(uint64_t insn,ppc_cpu_t dialect)581 lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
582 {
583   const struct powerpc_opcode *opcode, *opcode_end;
584   unsigned long op;
585 
586   /* Get the major opcode of the instruction.  */
587   op = PPC_OP (insn);
588 
589   /* Find the first match in the opcode table for this major opcode.  */
590   opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
591   for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
592        opcode < opcode_end;
593        ++opcode)
594     {
595       const unsigned char *opindex;
596       const struct powerpc_operand *operand;
597       int invalid;
598 
599       if ((insn & opcode->mask) != opcode->opcode
600 	  || ((dialect & PPC_OPCODE_ANY) == 0
601 	      && (opcode->flags & dialect) == 0)
602 	  || (opcode->deprecated & dialect) != 0)
603 	continue;
604 
605       /* Check validity of operands.  */
606       invalid = 0;
607       for (opindex = opcode->operands; *opindex != 0; opindex++)
608 	{
609 	  operand = powerpc_operands + *opindex;
610 	  if (operand->extract)
611 	    (*operand->extract) (insn, dialect, &invalid);
612 	}
613       if (invalid)
614 	continue;
615 
616       return opcode;
617     }
618 
619   return NULL;
620 }
621 
622 /* Find a match for INSN in the PREFIX opcode table.  */
623 
624 static const struct powerpc_opcode *
lookup_prefix(uint64_t insn,ppc_cpu_t dialect)625 lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
626 {
627   const struct powerpc_opcode *opcode, *opcode_end;
628   unsigned long seg;
629 
630   /* Get the opcode segment of the instruction.  */
631   seg = PPC_PREFIX_SEG (insn);
632 
633   /* Find the first match in the opcode table for this major opcode.  */
634   opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
635   for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
636        opcode < opcode_end;
637        ++opcode)
638     {
639       const unsigned char *opindex;
640       const struct powerpc_operand *operand;
641       int invalid;
642 
643       if ((insn & opcode->mask) != opcode->opcode
644 	  || ((dialect & PPC_OPCODE_ANY) == 0
645 	      && (opcode->flags & dialect) == 0)
646 	  || (opcode->deprecated & dialect) != 0)
647 	continue;
648 
649       /* Check validity of operands.  */
650       invalid = 0;
651       for (opindex = opcode->operands; *opindex != 0; opindex++)
652 	{
653 	  operand = powerpc_operands + *opindex;
654 	  if (operand->extract)
655 	    (*operand->extract) (insn, dialect, &invalid);
656 	}
657       if (invalid)
658 	continue;
659 
660       return opcode;
661     }
662 
663   return NULL;
664 }
665 
666 /* Find a match for INSN in the VLE opcode table.  */
667 
668 static const struct powerpc_opcode *
lookup_vle(uint64_t insn,ppc_cpu_t dialect)669 lookup_vle (uint64_t insn, ppc_cpu_t dialect)
670 {
671   const struct powerpc_opcode *opcode;
672   const struct powerpc_opcode *opcode_end;
673   unsigned op, seg;
674 
675   op = PPC_OP (insn);
676   if (op >= 0x20 && op <= 0x37)
677     {
678       /* This insn has a 4-bit opcode.  */
679       op &= 0x3c;
680     }
681   seg = VLE_OP_TO_SEG (op);
682 
683   /* Find the first match in the opcode table for this major opcode.  */
684   opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
685   for (opcode = vle_opcodes + vle_opcd_indices[seg];
686        opcode < opcode_end;
687        ++opcode)
688     {
689       uint64_t table_opcd = opcode->opcode;
690       uint64_t table_mask = opcode->mask;
691       bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
692       uint64_t insn2;
693       const unsigned char *opindex;
694       const struct powerpc_operand *operand;
695       int invalid;
696 
697       insn2 = insn;
698       if (table_op_is_short)
699 	insn2 >>= 16;
700       if ((insn2 & table_mask) != table_opcd
701 	  || (opcode->deprecated & dialect) != 0)
702 	continue;
703 
704       /* Check validity of operands.  */
705       invalid = 0;
706       for (opindex = opcode->operands; *opindex != 0; ++opindex)
707 	{
708 	  operand = powerpc_operands + *opindex;
709 	  if (operand->extract)
710 	    (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
711 	}
712       if (invalid)
713 	continue;
714 
715       return opcode;
716     }
717 
718   return NULL;
719 }
720 
721 /* Find a match for INSN in the SPE2 opcode table.  */
722 
723 static const struct powerpc_opcode *
lookup_spe2(uint64_t insn,ppc_cpu_t dialect)724 lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
725 {
726   const struct powerpc_opcode *opcode, *opcode_end;
727   unsigned op, xop, seg;
728 
729   op = PPC_OP (insn);
730   if (op != 0x4)
731     {
732       /* This is not SPE2 insn.
733        * All SPE2 instructions have OP=4 and differs by XOP  */
734       return NULL;
735     }
736   xop = SPE2_XOP (insn);
737   seg = SPE2_XOP_TO_SEG (xop);
738 
739   /* Find the first match in the opcode table for this major opcode.  */
740   opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
741   for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
742        opcode < opcode_end;
743        ++opcode)
744     {
745       uint64_t table_opcd = opcode->opcode;
746       uint64_t table_mask = opcode->mask;
747       uint64_t insn2;
748       const unsigned char *opindex;
749       const struct powerpc_operand *operand;
750       int invalid;
751 
752       insn2 = insn;
753       if ((insn2 & table_mask) != table_opcd
754 	  || (opcode->deprecated & dialect) != 0)
755 	continue;
756 
757       /* Check validity of operands.  */
758       invalid = 0;
759       for (opindex = opcode->operands; *opindex != 0; ++opindex)
760 	{
761 	  operand = powerpc_operands + *opindex;
762 	  if (operand->extract)
763 	    (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
764 	}
765       if (invalid)
766 	continue;
767 
768       return opcode;
769     }
770 
771   return NULL;
772 }
773 
774 static arelent *
bsearch_reloc(arelent ** lo,arelent ** hi,bfd_vma vma)775 bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
776 {
777   while (lo < hi)
778     {
779       arelent **mid = lo + (hi - lo) / 2;
780       arelent *rel = *mid;
781 
782       if (vma < rel->address)
783 	hi = mid;
784       else if (vma > rel->address)
785 	lo = mid + 1;
786       else
787 	return rel;
788     }
789   return NULL;
790 }
791 
792 static bool
print_got_plt(struct sec_buf * sb,uint64_t vma,struct disassemble_info * info)793 print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
794 {
795   if (sb->name != NULL)
796     {
797       asection *s = sb->sec;
798       if (s == NULL)
799 	{
800 	  s = bfd_get_section_by_name (info->section->owner, sb->name);
801 	  sb->sec = s;
802 	  if (s == NULL)
803 	    sb->name = NULL;
804 	}
805       if (s != NULL
806 	  && vma >= s->vma
807 	  && vma < s->vma + s->size)
808 	{
809 	  asymbol *sym = NULL;
810 	  uint64_t ent = 0;
811 	  if (info->dynrelcount > 0)
812 	    {
813 	      arelent **lo = info->dynrelbuf;
814 	      arelent **hi = lo + info->dynrelcount;
815 	      arelent *rel = bsearch_reloc (lo, hi, vma);
816 	      if (rel != NULL && rel->sym_ptr_ptr != NULL)
817 		sym = *rel->sym_ptr_ptr;
818 	    }
819 	  if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
820 	    {
821 	      if (sb->buf == NULL
822 		  && !bfd_malloc_and_get_section (s->owner, s, &sb->buf))
823 		sb->name = NULL;
824 	      if (sb->buf != NULL)
825 		{
826 		  ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma));
827 		  if (ent != 0)
828 		    sym = (*info->symbol_at_address_func) (ent, info);
829 		}
830 	    }
831 	  if (sym != NULL)
832 	    (*info->fprintf_func) (info->stream, " [%s@%s]",
833 				   bfd_asymbol_name (sym), sb->name + 1);
834 	  else
835 	    (*info->fprintf_func) (info->stream, " [%" PRIx64 "@%s]",
836 				   ent, sb->name + 1);
837 	  return true;
838 	}
839     }
840   return false;
841 }
842 
843 /* Print a PowerPC or POWER instruction.  */
844 
845 static int
print_insn_powerpc(bfd_vma memaddr,struct disassemble_info * info,int bigendian,ppc_cpu_t dialect)846 print_insn_powerpc (bfd_vma memaddr,
847 		    struct disassemble_info *info,
848 		    int bigendian,
849 		    ppc_cpu_t dialect)
850 {
851   bfd_byte buffer[4];
852   int status;
853   uint64_t insn;
854   const struct powerpc_opcode *opcode;
855   int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
856 
857   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
858 
859   /* The final instruction may be a 2-byte VLE insn.  */
860   if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
861     {
862       /* Clear buffer so unused bytes will not have garbage in them.  */
863       buffer[2] = buffer[3] = 0;
864       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
865       insn_length = 2;
866     }
867 
868   if (status != 0)
869     {
870       (*info->memory_error_func) (status, memaddr, info);
871       return -1;
872     }
873 
874   if (bigendian)
875     insn = bfd_getb32 (buffer);
876   else
877     insn = bfd_getl32 (buffer);
878 
879   /* Get the major opcode of the insn.  */
880   opcode = NULL;
881   if ((dialect & PPC_OPCODE_POWER10) != 0
882       && PPC_OP (insn) == 0x1)
883     {
884       uint64_t temp_insn, suffix;
885       status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
886       if (status == 0)
887 	{
888 	  if (bigendian)
889 	    suffix = bfd_getb32 (buffer);
890 	  else
891 	    suffix = bfd_getl32 (buffer);
892 	  temp_insn = (insn << 32) | suffix;
893 	  opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
894 	  if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
895 	    opcode = lookup_prefix (temp_insn, dialect);
896 	  if (opcode != NULL)
897 	    {
898 	      insn = temp_insn;
899 	      insn_length = 8;
900 	      if ((info->flags & WIDE_OUTPUT) != 0)
901 		info->bytes_per_line = 8;
902 	    }
903 	}
904     }
905   if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
906     {
907       opcode = lookup_vle (insn, dialect);
908       if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
909 	{
910 	  /* The operands will be fetched out of the 16-bit instruction.  */
911 	  insn >>= 16;
912 	  insn_length = 2;
913 	}
914     }
915   if (opcode == NULL && insn_length == 4)
916     {
917       if ((dialect & PPC_OPCODE_SPE2) != 0)
918 	opcode = lookup_spe2 (insn, dialect);
919       if (opcode == NULL)
920 	opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
921       if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
922 	opcode = lookup_powerpc (insn, dialect);
923     }
924 
925   if (opcode != NULL)
926     {
927       const unsigned char *opindex;
928       const struct powerpc_operand *operand;
929       enum {
930 	need_comma = 0,
931 	need_1space = 1,
932 	need_2spaces = 2,
933 	need_3spaces = 3,
934 	need_4spaces = 4,
935 	need_5spaces = 5,
936 	need_6spaces = 6,
937 	need_7spaces = 7,
938 	need_paren
939       } op_separator;
940       bool skip_optional;
941       bool is_pcrel;
942       uint64_t d34;
943       int blanks;
944 
945       (*info->fprintf_func) (info->stream, "%s", opcode->name);
946       /* gdb fprintf_func doesn't return count printed.  */
947       blanks = 8 - strlen (opcode->name);
948       if (blanks <= 0)
949 	blanks = 1;
950 
951       /* Now extract and print the operands.  */
952       op_separator = blanks;
953       skip_optional = false;
954       is_pcrel = false;
955       d34 = 0;
956       for (opindex = opcode->operands; *opindex != 0; opindex++)
957 	{
958 	  int64_t value;
959 
960 	  operand = powerpc_operands + *opindex;
961 
962 	  /* If all of the optional operands past this one have their
963 	     default value, then don't print any of them.  Except in
964 	     raw mode, print them all.  */
965 	  if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
966 	      && (dialect & PPC_OPCODE_RAW) == 0)
967 	    {
968 	      if (!skip_optional)
969 		skip_optional = skip_optional_operands (opindex, insn,
970 							dialect, &is_pcrel);
971 	      if (skip_optional)
972 		continue;
973 	    }
974 
975 	  value = operand_value_powerpc (operand, insn, dialect);
976 
977 	  if (op_separator == need_comma)
978 	    (*info->fprintf_func) (info->stream, ",");
979 	  else if (op_separator == need_paren)
980 	    (*info->fprintf_func) (info->stream, "(");
981 	  else
982 	    (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
983 
984 	  /* Print the operand as directed by the flags.  */
985 	  if ((operand->flags & PPC_OPERAND_GPR) != 0
986 	      || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
987 	    (*info->fprintf_func) (info->stream, "r%" PRId64, value);
988 	  else if ((operand->flags & PPC_OPERAND_FPR) != 0)
989 	    (*info->fprintf_func) (info->stream, "f%" PRId64, value);
990 	  else if ((operand->flags & PPC_OPERAND_VR) != 0)
991 	    (*info->fprintf_func) (info->stream, "v%" PRId64, value);
992 	  else if ((operand->flags & PPC_OPERAND_VSR) != 0)
993 	    (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
994 	  else if ((operand->flags & PPC_OPERAND_ACC) != 0)
995 	    (*info->fprintf_func) (info->stream, "a%" PRId64, value);
996 	  else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
997 	    (*info->print_address_func) (memaddr + value, info);
998 	  else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
999 	    (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
1000 	  else if ((operand->flags & PPC_OPERAND_FSL) != 0)
1001 	    (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
1002 	  else if ((operand->flags & PPC_OPERAND_FCR) != 0)
1003 	    (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
1004 	  else if ((operand->flags & PPC_OPERAND_UDI) != 0)
1005 	    (*info->fprintf_func) (info->stream, "%" PRId64, value);
1006 	  else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
1007 		   && (operand->flags & PPC_OPERAND_CR_BIT) == 0
1008 		   && (((dialect & PPC_OPCODE_PPC) != 0)
1009 		       || ((dialect & PPC_OPCODE_VLE) != 0)))
1010 	    (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
1011 	  else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1012 		   && (operand->flags & PPC_OPERAND_CR_REG) == 0
1013 		   && (((dialect & PPC_OPCODE_PPC) != 0)
1014 		       || ((dialect & PPC_OPCODE_VLE) != 0)))
1015 	    {
1016 	      static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1017 	      int cr;
1018 	      int cc;
1019 
1020 	      cr = value >> 2;
1021 	      if (cr != 0)
1022 		(*info->fprintf_func) (info->stream, "4*cr%d+", cr);
1023 	      cc = value & 3;
1024 	      (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
1025 	    }
1026 	  else
1027 	    (*info->fprintf_func) (info->stream, "%" PRId64, value);
1028 
1029 	  if (operand->shift == 52)
1030 	    is_pcrel = value != 0;
1031 	  else if (operand->bitm == UINT64_C (0x3ffffffff))
1032 	    d34 = value;
1033 
1034 	  if (op_separator == need_paren)
1035 	    (*info->fprintf_func) (info->stream, ")");
1036 
1037 	  op_separator = need_comma;
1038 	  if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1039 	    op_separator = need_paren;
1040 	}
1041 
1042       if (is_pcrel)
1043 	{
1044 	  d34 += memaddr;
1045 	  (*info->fprintf_func) (info->stream, "\t# %" PRIx64, d34);
1046 	  asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1047 	  if (sym)
1048 	    (*info->fprintf_func) (info->stream, " <%s>",
1049 				   bfd_asymbol_name (sym));
1050 
1051 	  if (info->private_data != NULL
1052 	      && info->section != NULL
1053 	      && info->section->owner != NULL
1054 	      && (bfd_get_file_flags (info->section->owner)
1055 		  & (EXEC_P | DYNAMIC)) != 0
1056 	      && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
1057 		  == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
1058 	    {
1059 	      for (int i = 0; i < 2; i++)
1060 		if (print_got_plt (private_data (info)->special + i, d34, info))
1061 		  break;
1062 	    }
1063 	}
1064 
1065       /* We have found and printed an instruction.  */
1066       return insn_length;
1067     }
1068 
1069   /* We could not find a match.  */
1070   if (insn_length == 4)
1071     (*info->fprintf_func) (info->stream, ".long 0x%x",
1072 			   (unsigned int) insn);
1073   else
1074     (*info->fprintf_func) (info->stream, ".word 0x%x",
1075 			   (unsigned int) insn >> 16);
1076   return insn_length;
1077 }
1078 
1079 const disasm_options_and_args_t *
disassembler_options_powerpc(void)1080 disassembler_options_powerpc (void)
1081 {
1082   static disasm_options_and_args_t *opts_and_args;
1083 
1084   if (opts_and_args == NULL)
1085     {
1086       size_t i, num_options = ARRAY_SIZE (ppc_opts);
1087       disasm_options_t *opts;
1088 
1089       opts_and_args = XNEW (disasm_options_and_args_t);
1090       opts_and_args->args = NULL;
1091 
1092       opts = &opts_and_args->options;
1093       opts->name = XNEWVEC (const char *, num_options + 1);
1094       opts->description = NULL;
1095       opts->arg = NULL;
1096       for (i = 0; i < num_options; i++)
1097 	opts->name[i] = ppc_opts[i].opt;
1098       /* The array we return must be NULL terminated.  */
1099       opts->name[i] = NULL;
1100     }
1101 
1102   return opts_and_args;
1103 }
1104 
1105 void
print_ppc_disassembler_options(FILE * stream)1106 print_ppc_disassembler_options (FILE *stream)
1107 {
1108   unsigned int i, col;
1109 
1110   fprintf (stream, _("\n\
1111 The following PPC specific disassembler options are supported for use with\n\
1112 the -M switch:\n"));
1113 
1114   for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
1115     {
1116       col += fprintf (stream, " %s,", ppc_opts[i].opt);
1117       if (col > 66)
1118 	{
1119 	  fprintf (stream, "\n");
1120 	  col = 0;
1121 	}
1122     }
1123   fprintf (stream, "\n");
1124 }
1125