Automatic date update in version.in
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
250d07de 2 Copyright (C) 1994-2021 Free Software Foundation, Inc.
252b5132
RH
3 Written by Ian Lance Taylor, Cygnus Support
4
9b201bb5
NC
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. */
252b5132 21
252b5132 22#include "sysdep.h"
df7b86aa 23#include <stdio.h>
88c1242d 24#include "disassemble.h"
b9c361e0 25#include "elf-bfd.h"
94caa966 26#include "elf/ppc.h"
69fe9ce5 27#include "opintl.h"
252b5132 28#include "opcode/ppc.h"
65b48a81 29#include "libiberty.h"
252b5132
RH
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. */
fa452fa6
PB
36static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
37 ppc_cpu_t);
252b5132 38
fa452fa6
PB
39struct dis_private
40{
41 /* Stash the result of parsing disassembler_options here. */
42 ppc_cpu_t dialect;
c3f72de4
AM
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];
6f0e0752 50};
fa452fa6 51
c3f72de4
AM
52static inline struct dis_private *
53private_data (struct disassemble_info *info)
54{
55 return (struct dis_private *) info->private_data;
56}
418c1742 57
69fe9ce5 58struct ppc_mopt {
9b753937 59 /* Option string, without -m or -M prefix. */
69fe9ce5 60 const char *opt;
9b753937 61 /* CPU option flags. */
69fe9ce5 62 ppc_cpu_t cpu;
9b753937
AM
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. */
69fe9ce5
AM
72 ppc_cpu_t sticky;
73};
74
75struct ppc_mopt ppc_opts[] = {
14b57c7c 76 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403,
69fe9ce5 77 0 },
14b57c7c 78 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
69fe9ce5 79 0 },
bdc70b4a
AM
80 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
81 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 82 0 },
bdc70b4a
AM
83 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
84 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 85 0 },
62adc510
AM
86 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
87 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
9fe54b1c 88 0 },
14b57c7c 89 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601,
69fe9ce5 90 0 },
14b57c7c 91 { "603", PPC_OPCODE_PPC,
69fe9ce5 92 0 },
14b57c7c 93 { "604", PPC_OPCODE_PPC,
69fe9ce5 94 0 },
14b57c7c 95 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 96 0 },
14b57c7c 97 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 98 0 },
14b57c7c 99 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 100 0 },
14b57c7c 101 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
69fe9ce5 102 0 },
14b57c7c 103 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 104 0 },
14b57c7c 105 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
69fe9ce5 106 , 0 },
fa758a70
AC
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 },
14b57c7c 111 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 112 0 },
14b57c7c 113 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 114 0 },
14b57c7c 115 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 116 0 },
bdc70b4a
AM
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),
cdc51b07 120 0 },
14b57c7c 121 { "altivec", PPC_OPCODE_PPC,
4b8b687e 122 PPC_OPCODE_ALTIVEC },
52be03fd 123 { "any", PPC_OPCODE_PPC,
69fe9ce5 124 PPC_OPCODE_ANY },
14b57c7c 125 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 126 0 },
14b57c7c 127 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 128 0 },
bdc70b4a
AM
129 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
130 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
69fe9ce5 131 0 },
14b57c7c 132 { "com", PPC_OPCODE_COMMON,
69fe9ce5 133 0 },
dfdaec14
AJ
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
74081948
AF
137 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
138 | PPC_OPCODE_EFS2 | PPC_OPCODE_LSP),
9b753937 139 0 },
14b57c7c 140 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
69fe9ce5
AM
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
e01d869a 145 | PPC_OPCODE_E500),
69fe9ce5
AM
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 },
0dc93057
AM
151 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
152 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
63d0fa4e
AM
153 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
154 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0dc93057 155 0 },
aea77599
AM
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
c03dc33b 159 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
aea77599
AM
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
c03dc33b 164 | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
aea77599
AM
165 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
166 0 },
69fe9ce5
AM
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
e01d869a 170 | PPC_OPCODE_E500),
69fe9ce5 171 0 },
14b57c7c 172 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 173 0 },
74081948
AF
174 { "efs2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
175 0 },
14b57c7c 176 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
69fe9ce5 177 0 },
bdc70b4a
AM
178 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
179 | PPC_OPCODE_POWER5),
69fe9ce5 180 0 },
bdc70b4a
AM
181 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
182 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
69fe9ce5 183 0 },
bdc70b4a
AM
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),
69fe9ce5 187 0 },
5817ffd1
PB
188 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
189 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 190 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 191 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 192 0 },
a680de9a
PB
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
ef85eab0 196 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 197 0 },
7c1f4227
AM
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 },
dd7efa79
PB
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
7c1f4227 206 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
dd7efa79 207 0 },
14b57c7c 208 { "ppc", PPC_OPCODE_PPC,
69fe9ce5 209 0 },
14b57c7c 210 { "ppc32", PPC_OPCODE_PPC,
69fe9ce5 211 0 },
65b48a81
PB
212 { "32", PPC_OPCODE_PPC,
213 0 },
14b57c7c 214 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 215 0 },
65b48a81
PB
216 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
217 0 },
14b57c7c 218 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
69fe9ce5 219 0 },
14b57c7c 220 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
69fe9ce5 221 0 },
14b57c7c 222 { "pwr", PPC_OPCODE_POWER,
69fe9ce5 223 0 },
14b57c7c 224 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
cdc51b07 225 0 },
14b57c7c 226 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
cdc51b07 227 0 },
bdc70b4a
AM
228 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
229 | PPC_OPCODE_POWER5),
cdc51b07 230 0 },
bdc70b4a
AM
231 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
232 | PPC_OPCODE_POWER5),
cdc51b07 233 0 },
bdc70b4a
AM
234 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
235 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
cdc51b07 236 0 },
bdc70b4a
AM
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),
69fe9ce5 240 0 },
5817ffd1
PB
241 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
242 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 243 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 244 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 245 0 },
a680de9a
PB
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
ef85eab0 249 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 250 0 },
1424c35d
AM
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 },
14b57c7c 256 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
69fe9ce5 257 0 },
52be03fd
AM
258 { "raw", PPC_OPCODE_PPC,
259 PPC_OPCODE_RAW },
14b57c7c 260 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 261 PPC_OPCODE_SPE },
74081948
AF
262 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
263 PPC_OPCODE_SPE2 },
bdc70b4a
AM
264 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
265 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
ce3d2015 266 0 },
14b57c7c
AM
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
74081948 270 | PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
b9c361e0 271 PPC_OPCODE_VLE },
14b57c7c 272 { "vsx", PPC_OPCODE_PPC,
4b8b687e 273 PPC_OPCODE_VSX },
69fe9ce5
AM
274};
275
b9c361e0
JL
276/* Switch between Booke and VLE dialects for interlinked dumps. */
277static ppc_cpu_t
278get_powerpc_dialect (struct disassemble_info *info)
279{
280 ppc_cpu_t dialect = 0;
281
6f0e0752 282 if (info->private_data)
c3f72de4 283 dialect = private_data (info)->dialect;
b9c361e0
JL
284
285 /* Disassemble according to the section headers flags for VLE-mode. */
286 if (dialect & PPC_OPCODE_VLE
3a2488dd 287 && info->section != NULL && info->section->owner != NULL
94caa966
AM
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)
b9c361e0
JL
291 return dialect;
292 else
293 return dialect & ~ PPC_OPCODE_VLE;
294}
295
69fe9ce5
AM
296/* Handle -m and -M options that set cpu type, and .machine arg. */
297
298ppc_cpu_t
776fc418 299ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
69fe9ce5 300{
69fe9ce5
AM
301 unsigned int i;
302
65b48a81
PB
303 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
304 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
69fe9ce5
AM
305 {
306 if (ppc_opts[i].sticky)
307 {
776fc418
AM
308 *sticky |= ppc_opts[i].sticky;
309 if ((ppc_cpu & ~*sticky) != 0)
69fe9ce5
AM
310 break;
311 }
312 ppc_cpu = ppc_opts[i].cpu;
313 break;
314 }
65b48a81 315 if (i >= ARRAY_SIZE (ppc_opts))
69fe9ce5
AM
316 return 0;
317
776fc418 318 ppc_cpu |= *sticky;
69fe9ce5
AM
319 return ppc_cpu;
320}
321
322/* Determine which set of machines to disassemble for. */
418c1742 323
b240011a 324static void
fa452fa6 325powerpc_init_dialect (struct disassemble_info *info)
418c1742 326{
69fe9ce5 327 ppc_cpu_t dialect = 0;
776fc418 328 ppc_cpu_t sticky = 0;
fa452fa6
PB
329 struct dis_private *priv = calloc (sizeof (*priv), 1);
330
331 if (priv == NULL)
6f0e0752 332 return;
418c1742 333
776fc418
AM
334 switch (info->mach)
335 {
336 case bfd_mach_ppc_403:
337 case bfd_mach_ppc_403gc:
4f6ffcd3 338 dialect = ppc_parse_cpu (dialect, &sticky, "403");
776fc418
AM
339 break;
340 case bfd_mach_ppc_405:
4f6ffcd3 341 dialect = ppc_parse_cpu (dialect, &sticky, "405");
776fc418
AM
342 break;
343 case bfd_mach_ppc_601:
4f6ffcd3 344 dialect = ppc_parse_cpu (dialect, &sticky, "601");
776fc418 345 break;
fa758a70
AC
346 case bfd_mach_ppc_750:
347 dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
348 break;
776fc418
AM
349 case bfd_mach_ppc_a35:
350 case bfd_mach_ppc_rs64ii:
351 case bfd_mach_ppc_rs64iii:
4f6ffcd3 352 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
776fc418
AM
353 break;
354 case bfd_mach_ppc_e500:
4f6ffcd3 355 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
776fc418
AM
356 break;
357 case bfd_mach_ppc_e500mc:
4f6ffcd3 358 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
776fc418
AM
359 break;
360 case bfd_mach_ppc_e500mc64:
4f6ffcd3 361 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
776fc418
AM
362 break;
363 case bfd_mach_ppc_e5500:
4f6ffcd3 364 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
776fc418
AM
365 break;
366 case bfd_mach_ppc_e6500:
4f6ffcd3 367 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
776fc418
AM
368 break;
369 case bfd_mach_ppc_titan:
4f6ffcd3 370 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
776fc418
AM
371 break;
372 case bfd_mach_ppc_vle:
4f6ffcd3 373 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
776fc418
AM
374 break;
375 default:
52fe4420 376 if (info->arch == bfd_arch_powerpc)
6bbb0c05 377 dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
52fe4420
AM
378 else
379 dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
65b48a81 380 break;
776fc418
AM
381 }
382
f995bbe8 383 const char *opt;
65b48a81 384 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
69fe9ce5
AM
385 {
386 ppc_cpu_t new_cpu = 0;
9b4e5766 387
65b48a81 388 if (disassembler_options_cmp (opt, "32") == 0)
7102e95e 389 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
65b48a81 390 else if (disassembler_options_cmp (opt, "64") == 0)
bdc70b4a 391 dialect |= PPC_OPCODE_64;
65b48a81
PB
392 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
393 dialect = new_cpu;
69fe9ce5 394 else
a6743a54
AM
395 /* xgettext: c-format */
396 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
69fe9ce5 397 }
661bd698 398
fa452fa6 399 info->private_data = priv;
c3f72de4 400 private_data (info)->dialect = dialect;
b240011a
AM
401}
402
f413a913
AM
403#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
404static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
dd7efa79 405#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
4f6d070a 406static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
f413a913
AM
407#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
408static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
409#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
410static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
b240011a 411
78933a4a 412static bool
7ad57880
NC
413ppc_symbol_is_valid (asymbol *sym,
414 struct disassemble_info *info ATTRIBUTE_UNUSED)
415{
416 elf_symbol_type * est;
417
418 if (sym == NULL)
78933a4a 419 return false;
7ad57880 420
c1229f84 421 est = elf_symbol_from (sym);
c3f72de4 422
7ad57880
NC
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)
78933a4a 429 return false;
7ad57880 430
78933a4a 431 return true;
7ad57880
NC
432}
433
b240011a
AM
434/* Calculate opcode table indices to speed up disassembly,
435 and init dialect. */
436
437void
438disassemble_init_powerpc (struct disassemble_info *info)
439{
7ad57880
NC
440 info->symbol_is_valid = ppc_symbol_is_valid;
441
27c49e9a 442 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 443 {
2ceb7719 444 unsigned seg, idx, op;
27c49e9a 445
2ceb7719
PB
446 /* PPC opcodes */
447 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 448 {
2ceb7719
PB
449 powerpc_opcd_indices[seg] = idx;
450 for (; idx < powerpc_num_opcodes; idx++)
451 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
452 break;
0f873fd5 453 }
27c49e9a 454
dd7efa79
PB
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
2ceb7719
PB
464 /* VLE opcodes */
465 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 466 {
2ceb7719
PB
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 }
0f873fd5 474 }
27c49e9a 475
2ceb7719
PB
476 /* SPE2 opcodes */
477 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 478 {
2ceb7719
PB
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 }
0f873fd5 486 }
b9c361e0
JL
487 }
488
52fe4420 489 powerpc_init_dialect (info);
c3f72de4
AM
490 if (info->private_data != NULL)
491 {
492 private_data (info)->special[0].name = ".got";
493 private_data (info)->special[1].name = ".plt";
494 }
418c1742
MG
495}
496
497/* Print a big endian PowerPC instruction. */
252b5132
RH
498
499int
823bbe9d 500print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 501{
b9c361e0 502 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
503}
504
418c1742 505/* Print a little endian PowerPC instruction. */
252b5132
RH
506
507int
823bbe9d 508print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 509{
b9c361e0 510 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
511}
512
ea192fa3
PB
513/* Extract the operand value from the PowerPC or POWER instruction. */
514
0f873fd5 515static int64_t
ea192fa3 516operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 517 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 518{
0f873fd5 519 int64_t value;
9cf7e568 520 int invalid = 0;
ea192fa3
PB
521 /* Extract the value from the instruction. */
522 if (operand->extract)
523 value = (*operand->extract) (insn, dialect, &invalid);
524 else
525 {
b9c361e0
JL
526 if (operand->shift >= 0)
527 value = (insn >> operand->shift) & operand->bitm;
528 else
529 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
530 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
531 {
532 /* BITM is always some number of zeros followed by some
b9c361e0 533 number of ones, followed by some number of zeros. */
0f873fd5 534 uint64_t top = operand->bitm;
ea192fa3
PB
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
78933a4a 548static bool
ea192fa3 549skip_optional_operands (const unsigned char *opindex,
c3f72de4 550 uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
ea192fa3
PB
551{
552 const struct powerpc_operand *operand;
9cf7e568 553 int num_optional;
ea192fa3 554
9cf7e568 555 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
556 {
557 operand = &powerpc_operands[*opindex];
9cf7e568 558 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
78933a4a 559 return false;
9cf7e568
AM
560 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
561 {
c3f72de4
AM
562 int64_t value = operand_value_powerpc (operand, insn, dialect);
563
564 if (operand->shift == 52)
565 *is_pcrel = value != 0;
566
9cf7e568
AM
567 /* Negative count is used as a flag to extract function. */
568 --num_optional;
c3f72de4
AM
569 if (value != ppc_optional_operand_value (operand, insn, dialect,
570 num_optional))
78933a4a 571 return false;
9cf7e568 572 }
ea192fa3
PB
573 }
574
78933a4a 575 return true;
ea192fa3
PB
576}
577
52be03fd 578/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 579
d6688282 580static const struct powerpc_opcode *
0f873fd5 581lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 582{
1ff6a3b8 583 const struct powerpc_opcode *opcode, *opcode_end;
d6688282
AM
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
52be03fd 600 || ((dialect & PPC_OPCODE_ANY) == 0
1ff6a3b8
AM
601 && (opcode->flags & dialect) == 0)
602 || (opcode->deprecated & dialect) != 0)
d6688282
AM
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
1ff6a3b8 616 return opcode;
d6688282
AM
617 }
618
1ff6a3b8 619 return NULL;
d6688282
AM
620}
621
dd7efa79
PB
622/* Find a match for INSN in the PREFIX opcode table. */
623
624static const struct powerpc_opcode *
625lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
626{
1ff6a3b8 627 const struct powerpc_opcode *opcode, *opcode_end;
dd7efa79
PB
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];
dd7efa79
PB
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
1ff6a3b8
AM
645 && (opcode->flags & dialect) == 0)
646 || (opcode->deprecated & dialect) != 0)
dd7efa79
PB
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
1ff6a3b8 660 return opcode;
dd7efa79
PB
661 }
662
1ff6a3b8 663 return NULL;
dd7efa79
PB
664}
665
b9c361e0
JL
666/* Find a match for INSN in the VLE opcode table. */
667
668static const struct powerpc_opcode *
1ff6a3b8 669lookup_vle (uint64_t insn, ppc_cpu_t dialect)
b9c361e0
JL
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 {
0f873fd5
PB
689 uint64_t table_opcd = opcode->opcode;
690 uint64_t table_mask = opcode->mask;
78933a4a 691 bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 692 uint64_t insn2;
b9c361e0
JL
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;
1ff6a3b8
AM
700 if ((insn2 & table_mask) != table_opcd
701 || (opcode->deprecated & dialect) != 0)
b9c361e0
JL
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
74081948
AF
721/* Find a match for INSN in the SPE2 opcode table. */
722
723static const struct powerpc_opcode *
1ff6a3b8 724lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
74081948
AF
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 {
0f873fd5
PB
745 uint64_t table_opcd = opcode->opcode;
746 uint64_t table_mask = opcode->mask;
747 uint64_t insn2;
74081948
AF
748 const unsigned char *opindex;
749 const struct powerpc_operand *operand;
750 int invalid;
751
752 insn2 = insn;
1ff6a3b8
AM
753 if ((insn2 & table_mask) != table_opcd
754 || (opcode->deprecated & dialect) != 0)
74081948
AF
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
c3f72de4
AM
774static arelent *
775bsearch_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
792static bool
793print_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
252b5132
RH
843/* Print a PowerPC or POWER instruction. */
844
845static int
823bbe9d
AM
846print_insn_powerpc (bfd_vma memaddr,
847 struct disassemble_info *info,
848 int bigendian,
fa452fa6 849 ppc_cpu_t dialect)
252b5132
RH
850{
851 bfd_byte buffer[4];
852 int status;
0f873fd5 853 uint64_t insn;
252b5132 854 const struct powerpc_opcode *opcode;
a87a6478 855 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
856
857 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
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. */
833d919c 863 buffer[2] = buffer[3] = 0;
a87a6478 864 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
833d919c 865 insn_length = 2;
a87a6478
PB
866 }
867
252b5132
RH
868 if (status != 0)
869 {
a87a6478
PB
870 (*info->memory_error_func) (status, memaddr, info);
871 return -1;
252b5132
RH
872 }
873
874 if (bigendian)
875 insn = bfd_getb32 (buffer);
876 else
877 insn = bfd_getl32 (buffer);
878
b9c361e0
JL
879 /* Get the major opcode of the insn. */
880 opcode = NULL;
7c1f4227 881 if ((dialect & PPC_OPCODE_POWER10) != 0
dd7efa79
PB
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)
b9c361e0 906 {
1ff6a3b8 907 opcode = lookup_vle (insn, dialect);
a87a6478
PB
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 }
b9c361e0 914 }
833d919c
AM
915 if (opcode == NULL && insn_length == 4)
916 {
917 if ((dialect & PPC_OPCODE_SPE2) != 0)
1ff6a3b8 918 opcode = lookup_spe2 (insn, dialect);
833d919c
AM
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 }
252b5132 924
d6688282 925 if (opcode != NULL)
252b5132 926 {
252b5132
RH
927 const unsigned char *opindex;
928 const struct powerpc_operand *operand;
e392bad3
AM
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;
78933a4a 940 bool skip_optional;
c3f72de4
AM
941 bool is_pcrel;
942 uint64_t d34;
0e62b37a 943 int blanks;
252b5132 944
c2b1c275
AM
945 (*info->fprintf_func) (info->stream, "%s", opcode->name);
946 /* gdb fprintf_func doesn't return count printed. */
0e62b37a
JB
947 blanks = 8 - strlen (opcode->name);
948 if (blanks <= 0)
949 blanks = 1;
252b5132
RH
950
951 /* Now extract and print the operands. */
0e62b37a 952 op_separator = blanks;
78933a4a 953 skip_optional = false;
c3f72de4
AM
954 is_pcrel = false;
955 d34 = 0;
252b5132
RH
956 for (opindex = opcode->operands; *opindex != 0; opindex++)
957 {
0f873fd5 958 int64_t value;
252b5132
RH
959
960 operand = powerpc_operands + *opindex;
961
0067be51
AM
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)
65b650b4 967 {
bda678b9 968 if (!skip_optional)
c3f72de4
AM
969 skip_optional = skip_optional_operands (opindex, insn,
970 dialect, &is_pcrel);
65b650b4
AM
971 if (skip_optional)
972 continue;
973 }
252b5132 974
ea192fa3
PB
975 value = operand_value_powerpc (operand, insn, dialect);
976
e392bad3
AM
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, " ");
252b5132
RH
983
984 /* Print the operand as directed by the flags. */
fdd12ef3
AM
985 if ((operand->flags & PPC_OPERAND_GPR) != 0
986 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 987 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 988 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 989 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 990 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 991 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 992 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 993 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
aa3c112f
AM
994 else if ((operand->flags & PPC_OPERAND_ACC) != 0)
995 (*info->fprintf_func) (info->stream, "a%" PRId64, value);
252b5132
RH
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);
43e65147 1000 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 1001 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 1002 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 1003 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 1004 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 1005 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 1006 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 1007 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
1008 && (((dialect & PPC_OPCODE_PPC) != 0)
1009 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 1010 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
1011 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1012 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
1013 && (((dialect & PPC_OPCODE_PPC) != 0)
1014 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 1015 {
b9c361e0
JL
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]);
252b5132 1025 }
70dc4e32 1026 else
d1a3c973 1027 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 1028
c3f72de4
AM
1029 if (operand->shift == 52)
1030 is_pcrel = value != 0;
1031 else if (operand->bitm == UINT64_C (0x3ffffffff))
1032 d34 = value;
1033
e392bad3
AM
1034 if (op_separator == need_paren)
1035 (*info->fprintf_func) (info->stream, ")");
252b5132 1036
e392bad3
AM
1037 op_separator = need_comma;
1038 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1039 op_separator = need_paren;
252b5132
RH
1040 }
1041
c3f72de4
AM
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
a87a6478
PB
1065 /* We have found and printed an instruction. */
1066 return insn_length;
252b5132
RH
1067 }
1068
1069 /* We could not find a match. */
833d919c
AM
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;
252b5132 1077}
07dd56a9 1078
471b9d15 1079const disasm_options_and_args_t *
65b48a81
PB
1080disassembler_options_powerpc (void)
1081{
471b9d15 1082 static disasm_options_and_args_t *opts_and_args;
65b48a81 1083
471b9d15 1084 if (opts_and_args == NULL)
65b48a81
PB
1085 {
1086 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
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;
65b48a81 1093 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
1094 opts->description = NULL;
1095 opts->arg = NULL;
65b48a81
PB
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;
65b48a81
PB
1100 }
1101
471b9d15 1102 return opts_and_args;
65b48a81
PB
1103}
1104
07dd56a9 1105void
823bbe9d 1106print_ppc_disassembler_options (FILE *stream)
07dd56a9 1107{
69fe9ce5
AM
1108 unsigned int i, col;
1109
1110 fprintf (stream, _("\n\
07dd56a9 1111The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
1112the -M switch:\n"));
1113
65b48a81 1114 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
1115 {
1116 col += fprintf (stream, " %s,", ppc_opts[i].opt);
1117 if (col > 66)
1118 {
1119 fprintf (stream, "\n");
1120 col = 0;
1121 }
1122 }
65b48a81 1123 fprintf (stream, "\n");
07dd56a9 1124}
This page took 1.043508 seconds and 4 git commands to generate.