]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/ppc-dis.c
New Romanian translation for ld
[thirdparty/binutils-gdb.git] / opcodes / ppc-dis.c
1 /* ppc-dis.c -- Disassemble PowerPC instructions
2 Copyright (C) 1994-2023 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 *
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
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
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
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
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
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
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
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
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
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 *
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 *
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 *
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 *
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 *
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 *
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
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
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 *
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
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 }