Fix: A potential null_pointer_deference bug
[binutils-gdb.git] / opcodes / ppc-dis.c
blobd97137d8b71837b74875e44dc935753092838dbc
1 /* ppc-dis.c -- Disassemble PowerPC instructions
2 Copyright (C) 1994-2023 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support
5 This file is part of the GNU opcodes library.
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.
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.
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. */
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"
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);
39 struct dis_private
41 /* Stash the result of parsing disassembler_options here. */
42 ppc_cpu_t dialect;
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];
52 static inline struct dis_private *
53 private_data (struct disassemble_info *info)
55 return (struct dis_private *) info->private_data;
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;
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 },
290 /* Switch between Booke and VLE dialects for interlinked dumps. */
291 static ppc_cpu_t
292 get_powerpc_dialect (struct disassemble_info *info)
294 ppc_cpu_t dialect = 0;
296 if (info->private_data)
297 dialect = private_data (info)->dialect;
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;
310 /* Handle -m and -M options that set cpu type, and .machine arg. */
312 ppc_cpu_t
313 ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
315 unsigned int i;
317 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
318 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
320 if (ppc_opts[i].sticky)
322 *sticky |= ppc_opts[i].sticky;
323 if ((ppc_cpu & ~*sticky) != 0)
324 break;
326 ppc_cpu = ppc_opts[i].cpu;
327 break;
329 if (i >= ARRAY_SIZE (ppc_opts))
330 return 0;
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;
341 return ppc_cpu;
344 /* Determine which set of machines to disassemble for. */
346 static void
347 powerpc_init_dialect (struct disassemble_info *info)
349 ppc_cpu_t dialect = 0;
350 ppc_cpu_t sticky = 0;
351 struct dis_private *priv = calloc (sizeof (*priv), 1);
353 if (priv == NULL)
354 return;
356 switch (info->mach)
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;
405 const char *opt;
406 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
408 ppc_cpu_t new_cpu = 0;
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);
421 info->private_data = priv;
422 private_data (info)->dialect = dialect;
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];
436 static bool
437 ppc_symbol_is_valid (asymbol *sym,
438 struct disassemble_info *info ATTRIBUTE_UNUSED)
440 elf_symbol_type * est;
442 if (sym == NULL)
443 return false;
445 est = elf_symbol_from (sym);
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;
455 return true;
458 /* Calculate opcode table indices to speed up disassembly,
459 and init dialect. */
461 void
462 disassemble_init_powerpc (struct disassemble_info *info)
464 info->symbol_is_valid = ppc_symbol_is_valid;
466 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
468 unsigned seg, idx, op;
470 /* PPC opcodes */
471 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
473 powerpc_opcd_indices[seg] = idx;
474 for (; idx < powerpc_num_opcodes; idx++)
475 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
476 break;
479 /* 64-bit prefix opcodes */
480 for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
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;
488 /* VLE opcodes */
489 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
491 vle_opcd_indices[seg] = idx;
492 for (; idx < vle_num_opcodes; idx++)
494 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
495 if (seg < VLE_OP_TO_SEG (op))
496 break;
500 /* LSP opcodes */
501 for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++)
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;
509 /* SPE2 opcodes */
510 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
512 spe2_opcd_indices[seg] = idx;
513 for (; idx < spe2_num_opcodes; idx++)
515 op = SPE2_XOP (spe2_opcodes[idx].opcode);
516 if (seg < SPE2_XOP_TO_SEG (op))
517 break;
522 powerpc_init_dialect (info);
523 if (info->private_data != NULL)
525 private_data (info)->special[0].name = ".got";
526 private_data (info)->special[1].name = ".plt";
530 /* Print a big endian PowerPC instruction. */
533 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
535 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
538 /* Print a little endian PowerPC instruction. */
541 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
543 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
546 /* Extract the operand value from the PowerPC or POWER instruction. */
548 static int64_t
549 operand_value_powerpc (const struct powerpc_operand *operand,
550 uint64_t insn, ppc_cpu_t dialect)
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
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)
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;
576 if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
577 ++value;
579 return value;
582 /* Determine whether the optional operand(s) should be printed. */
584 static bool
585 skip_optional_operands (const ppc_opindex_t *opindex,
586 uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
588 const struct powerpc_operand *operand;
589 int num_optional;
591 for (num_optional = 0; *opindex != 0; opindex++)
593 operand = &powerpc_operands[*opindex];
594 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
595 return false;
596 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
598 int64_t value = operand_value_powerpc (operand, insn, dialect);
600 if (operand->shift == 52)
601 *is_pcrel = value != 0;
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;
611 return true;
614 /* Find a match for INSN in the opcode table, given machine DIALECT. */
616 static const struct powerpc_opcode *
617 lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
619 const struct powerpc_opcode *opcode, *opcode_end;
620 unsigned long op;
622 /* Get the major opcode of the instruction. */
623 op = PPC_OP (insn);
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)
631 const ppc_opindex_t *opindex;
632 const struct powerpc_operand *operand;
633 int invalid;
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;
642 /* Check validity of operands. */
643 invalid = 0;
644 for (opindex = opcode->operands; *opindex != 0; opindex++)
646 operand = powerpc_operands + *opindex;
647 if (operand->extract)
648 (*operand->extract) (insn, dialect, &invalid);
650 if (invalid)
651 continue;
653 return opcode;
656 return NULL;
659 /* Find a match for INSN in the PREFIX opcode table. */
661 static const struct powerpc_opcode *
662 lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
664 const struct powerpc_opcode *opcode, *opcode_end;
665 unsigned long seg;
667 /* Get the opcode segment of the instruction. */
668 seg = PPC_PREFIX_SEG (insn);
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)
676 const ppc_opindex_t *opindex;
677 const struct powerpc_operand *operand;
678 int invalid;
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;
686 /* Check validity of operands. */
687 invalid = 0;
688 for (opindex = opcode->operands; *opindex != 0; opindex++)
690 operand = powerpc_operands + *opindex;
691 if (operand->extract)
692 (*operand->extract) (insn, dialect, &invalid);
694 if (invalid)
695 continue;
697 return opcode;
700 return NULL;
703 /* Find a match for INSN in the VLE opcode table. */
705 static const struct powerpc_opcode *
706 lookup_vle (uint64_t insn, ppc_cpu_t dialect)
708 const struct powerpc_opcode *opcode;
709 const struct powerpc_opcode *opcode_end;
710 unsigned op, seg;
712 op = PPC_OP (insn);
713 if (op >= 0x20 && op <= 0x37)
715 /* This insn has a 4-bit opcode. */
716 op &= 0x3c;
718 seg = VLE_OP_TO_SEG (op);
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)
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;
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;
741 /* Check validity of operands. */
742 invalid = 0;
743 for (opindex = opcode->operands; *opindex != 0; ++opindex)
745 operand = powerpc_operands + *opindex;
746 if (operand->extract)
747 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
749 if (invalid)
750 continue;
752 return opcode;
755 return NULL;
758 /* Find a match for INSN in the LSP opcode table. */
760 static const struct powerpc_opcode *
761 lookup_lsp (uint64_t insn, ppc_cpu_t dialect)
763 const struct powerpc_opcode *opcode, *opcode_end;
764 unsigned op, seg;
766 op = PPC_OP (insn);
767 if (op != 0x4)
768 return NULL;
770 seg = LSP_OP_TO_SEG (insn);
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)
778 const ppc_opindex_t *opindex;
779 const struct powerpc_operand *operand;
780 int invalid;
782 if ((insn & opcode->mask) != opcode->opcode
783 || (opcode->deprecated & dialect) != 0)
784 continue;
786 /* Check validity of operands. */
787 invalid = 0;
788 for (opindex = opcode->operands; *opindex != 0; ++opindex)
790 operand = powerpc_operands + *opindex;
791 if (operand->extract)
792 (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
794 if (invalid)
795 continue;
797 return opcode;
800 return NULL;
803 /* Find a match for INSN in the SPE2 opcode table. */
805 static const struct powerpc_opcode *
806 lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
808 const struct powerpc_opcode *opcode, *opcode_end;
809 unsigned op, xop, seg;
811 op = PPC_OP (insn);
812 if (op != 0x4)
814 /* This is not SPE2 insn.
815 * All SPE2 instructions have OP=4 and differs by XOP */
816 return NULL;
818 xop = SPE2_XOP (insn);
819 seg = SPE2_XOP_TO_SEG (xop);
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)
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;
834 insn2 = insn;
835 if ((insn2 & table_mask) != table_opcd
836 || (opcode->deprecated & dialect) != 0)
837 continue;
839 /* Check validity of operands. */
840 invalid = 0;
841 for (opindex = opcode->operands; *opindex != 0; ++opindex)
843 operand = powerpc_operands + *opindex;
844 if (operand->extract)
845 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
847 if (invalid)
848 continue;
850 return opcode;
853 return NULL;
856 static arelent *
857 bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
859 while (lo < hi)
861 arelent **mid = lo + (hi - lo) / 2;
862 arelent *rel = *mid;
864 if (vma < rel->address)
865 hi = mid;
866 else if (vma > rel->address)
867 lo = mid + 1;
868 else
869 return rel;
871 return NULL;
874 static bool
875 print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
877 if (sb->name != NULL)
879 asection *s = sb->sec;
880 if (s == NULL)
882 s = bfd_get_section_by_name (info->section->owner, sb->name);
883 sb->sec = s;
884 if (s == NULL)
885 sb->name = NULL;
887 if (s != NULL
888 && vma >= s->vma
889 && vma < s->vma + s->size)
891 asymbol *sym = NULL;
892 uint64_t ent = 0;
893 if (info->dynrelcount > 0)
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;
901 if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
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)
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);
913 (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
914 if (sym != NULL)
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);
922 else
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);
930 (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
931 return true;
934 return false;
937 /* Print a PowerPC or POWER instruction. */
939 static int
940 print_insn_powerpc (bfd_vma memaddr,
941 struct disassemble_info *info,
942 int bigendian,
943 ppc_cpu_t dialect)
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. */
951 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
953 /* The final instruction may be a 2-byte VLE insn. */
954 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
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;
962 if (status != 0)
964 (*info->memory_error_func) (status, memaddr, info);
965 return -1;
968 if (bigendian)
969 insn = bfd_getb32 (buffer);
970 else
971 insn = bfd_getl32 (buffer);
973 /* Get the major opcode of the insn. */
974 opcode = NULL;
975 if ((dialect & PPC_OPCODE_POWER10) != 0
976 && PPC_OP (insn) == 0x1)
978 uint64_t temp_insn, suffix;
979 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
980 if (status == 0)
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)
992 insn = temp_insn;
993 insn_length = 8;
994 if ((info->flags & WIDE_OUTPUT) != 0)
995 info->bytes_per_line = 8;
999 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
1001 opcode = lookup_vle (insn, dialect);
1002 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
1004 /* The operands will be fetched out of the 16-bit instruction. */
1005 insn >>= 16;
1006 insn_length = 2;
1009 if (opcode == NULL && insn_length == 4)
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);
1025 if (opcode != NULL)
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;
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;
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++)
1059 int64_t value;
1061 operand = powerpc_operands + *opindex;
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)
1069 if (!skip_optional)
1070 skip_optional = skip_optional_operands (opindex, insn,
1071 dialect, &is_pcrel);
1072 if (skip_optional)
1073 continue;
1076 value = operand_value_powerpc (operand, insn, dialect);
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, " ");
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)))
1130 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1131 int cr;
1132 int cc;
1134 cr = value >> 2;
1135 cc = value & 3;
1136 if (cr != 0)
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 "+");
1147 (*info->fprintf_styled_func) (info->stream,
1148 dis_style_sub_mnemonic,
1149 "%s", cbnames[cc]);
1151 else
1153 /* An immediate, but what style? */
1154 enum disassembler_style style;
1156 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1157 style = dis_style_address_offset;
1158 else
1159 style = dis_style_immediate;
1161 (*info->fprintf_styled_func) (info->stream, style,
1162 "%" PRId64, value);
1165 if (operand->shift == 52)
1166 is_pcrel = value != 0;
1167 else if (operand->bitm == UINT64_C (0x3ffffffff))
1168 d34 = value;
1170 if (op_separator == need_paren)
1171 (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1173 op_separator = need_comma;
1174 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1175 op_separator = need_paren;
1178 if (is_pcrel)
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));
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 */))
1197 for (int i = 0; i < 2; i++)
1198 if (print_got_plt (private_data (info)->special + i, d34, info))
1199 break;
1203 /* We have found and printed an instruction. */
1204 return insn_length;
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
1213 (*info->fprintf_styled_func) (info->stream,
1214 dis_style_assembler_directive, ".word");
1215 insn >>= 16;
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);
1222 return insn_length;
1225 const disasm_options_and_args_t *
1226 disassembler_options_powerpc (void)
1228 static disasm_options_and_args_t *opts_and_args;
1230 if (opts_and_args == NULL)
1232 size_t i, num_options = ARRAY_SIZE (ppc_opts);
1233 disasm_options_t *opts;
1235 opts_and_args = XNEW (disasm_options_and_args_t);
1236 opts_and_args->args = NULL;
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;
1248 return opts_and_args;
1251 void
1252 print_ppc_disassembler_options (FILE *stream)
1254 unsigned int i, col;
1256 fprintf (stream, _("\n\
1257 The following PPC specific disassembler options are supported for use with\n\
1258 the -M switch:\n"));
1260 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
1262 col += fprintf (stream, " %s,", ppc_opts[i].opt);
1263 if (col > 66)
1265 fprintf (stream, "\n");
1266 col = 0;
1269 fprintf (stream, "\n");