]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ppc-dis.c
PowerPC disassembly of pcrel references
[thirdparty/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{
52be03fd 583 const struct powerpc_opcode *opcode, *opcode_end, *last;
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];
52be03fd 591 last = NULL;
d6688282
AM
592 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
593 opcode < opcode_end;
594 ++opcode)
595 {
596 const unsigned char *opindex;
597 const struct powerpc_operand *operand;
598 int invalid;
599
600 if ((insn & opcode->mask) != opcode->opcode
52be03fd 601 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
602 && ((opcode->flags & dialect) == 0
603 || (opcode->deprecated & dialect) != 0)))
604 continue;
605
606 /* Check validity of operands. */
607 invalid = 0;
608 for (opindex = opcode->operands; *opindex != 0; opindex++)
609 {
610 operand = powerpc_operands + *opindex;
611 if (operand->extract)
612 (*operand->extract) (insn, dialect, &invalid);
613 }
614 if (invalid)
615 continue;
616
52be03fd
AM
617 if ((dialect & PPC_OPCODE_RAW) == 0)
618 return opcode;
619
620 /* The raw machine insn is one that is not a specialization. */
621 if (last == NULL
622 || (last->mask & ~opcode->mask) != 0)
623 last = opcode;
d6688282
AM
624 }
625
52be03fd 626 return last;
d6688282
AM
627}
628
dd7efa79
PB
629/* Find a match for INSN in the PREFIX opcode table. */
630
631static const struct powerpc_opcode *
632lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
633{
634 const struct powerpc_opcode *opcode, *opcode_end, *last;
635 unsigned long seg;
636
637 /* Get the opcode segment of the instruction. */
638 seg = PPC_PREFIX_SEG (insn);
639
640 /* Find the first match in the opcode table for this major opcode. */
641 opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
642 last = NULL;
643 for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
644 opcode < opcode_end;
645 ++opcode)
646 {
647 const unsigned char *opindex;
648 const struct powerpc_operand *operand;
649 int invalid;
650
651 if ((insn & opcode->mask) != opcode->opcode
652 || ((dialect & PPC_OPCODE_ANY) == 0
653 && ((opcode->flags & dialect) == 0
654 || (opcode->deprecated & dialect) != 0)))
655 continue;
656
657 /* Check validity of operands. */
658 invalid = 0;
659 for (opindex = opcode->operands; *opindex != 0; opindex++)
660 {
661 operand = powerpc_operands + *opindex;
662 if (operand->extract)
663 (*operand->extract) (insn, dialect, &invalid);
664 }
665 if (invalid)
666 continue;
667
668 if ((dialect & PPC_OPCODE_RAW) == 0)
669 return opcode;
670
671 /* The raw machine insn is one that is not a specialization. */
672 if (last == NULL
673 || (last->mask & ~opcode->mask) != 0)
674 last = opcode;
675 }
676
677 return last;
678}
679
b9c361e0
JL
680/* Find a match for INSN in the VLE opcode table. */
681
682static const struct powerpc_opcode *
0f873fd5 683lookup_vle (uint64_t insn)
b9c361e0
JL
684{
685 const struct powerpc_opcode *opcode;
686 const struct powerpc_opcode *opcode_end;
687 unsigned op, seg;
688
689 op = PPC_OP (insn);
690 if (op >= 0x20 && op <= 0x37)
691 {
692 /* This insn has a 4-bit opcode. */
693 op &= 0x3c;
694 }
695 seg = VLE_OP_TO_SEG (op);
696
697 /* Find the first match in the opcode table for this major opcode. */
698 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
699 for (opcode = vle_opcodes + vle_opcd_indices[seg];
700 opcode < opcode_end;
701 ++opcode)
702 {
0f873fd5
PB
703 uint64_t table_opcd = opcode->opcode;
704 uint64_t table_mask = opcode->mask;
78933a4a 705 bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 706 uint64_t insn2;
b9c361e0
JL
707 const unsigned char *opindex;
708 const struct powerpc_operand *operand;
709 int invalid;
710
711 insn2 = insn;
712 if (table_op_is_short)
713 insn2 >>= 16;
714 if ((insn2 & table_mask) != table_opcd)
715 continue;
716
717 /* Check validity of operands. */
718 invalid = 0;
719 for (opindex = opcode->operands; *opindex != 0; ++opindex)
720 {
721 operand = powerpc_operands + *opindex;
722 if (operand->extract)
723 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
724 }
725 if (invalid)
726 continue;
727
728 return opcode;
729 }
730
731 return NULL;
732}
733
74081948
AF
734/* Find a match for INSN in the SPE2 opcode table. */
735
736static const struct powerpc_opcode *
0f873fd5 737lookup_spe2 (uint64_t insn)
74081948
AF
738{
739 const struct powerpc_opcode *opcode, *opcode_end;
740 unsigned op, xop, seg;
741
742 op = PPC_OP (insn);
743 if (op != 0x4)
744 {
745 /* This is not SPE2 insn.
746 * All SPE2 instructions have OP=4 and differs by XOP */
747 return NULL;
748 }
749 xop = SPE2_XOP (insn);
750 seg = SPE2_XOP_TO_SEG (xop);
751
752 /* Find the first match in the opcode table for this major opcode. */
753 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
754 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
755 opcode < opcode_end;
756 ++opcode)
757 {
0f873fd5
PB
758 uint64_t table_opcd = opcode->opcode;
759 uint64_t table_mask = opcode->mask;
760 uint64_t insn2;
74081948
AF
761 const unsigned char *opindex;
762 const struct powerpc_operand *operand;
763 int invalid;
764
765 insn2 = insn;
766 if ((insn2 & table_mask) != table_opcd)
767 continue;
768
769 /* Check validity of operands. */
770 invalid = 0;
771 for (opindex = opcode->operands; *opindex != 0; ++opindex)
772 {
773 operand = powerpc_operands + *opindex;
774 if (operand->extract)
775 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
776 }
777 if (invalid)
778 continue;
779
780 return opcode;
781 }
782
783 return NULL;
784}
785
c3f72de4
AM
786static arelent *
787bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
788{
789 while (lo < hi)
790 {
791 arelent **mid = lo + (hi - lo) / 2;
792 arelent *rel = *mid;
793
794 if (vma < rel->address)
795 hi = mid;
796 else if (vma > rel->address)
797 lo = mid + 1;
798 else
799 return rel;
800 }
801 return NULL;
802}
803
804static bool
805print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
806{
807 if (sb->name != NULL)
808 {
809 asection *s = sb->sec;
810 if (s == NULL)
811 {
812 s = bfd_get_section_by_name (info->section->owner, sb->name);
813 sb->sec = s;
814 if (s == NULL)
815 sb->name = NULL;
816 }
817 if (s != NULL
818 && vma >= s->vma
819 && vma < s->vma + s->size)
820 {
821 asymbol *sym = NULL;
822 uint64_t ent = 0;
823 if (info->dynrelcount > 0)
824 {
825 arelent **lo = info->dynrelbuf;
826 arelent **hi = lo + info->dynrelcount;
827 arelent *rel = bsearch_reloc (lo, hi, vma);
828 if (rel != NULL && rel->sym_ptr_ptr != NULL)
829 sym = *rel->sym_ptr_ptr;
830 }
831 if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
832 {
833 if (sb->buf == NULL
834 && !bfd_malloc_and_get_section (s->owner, s, &sb->buf))
835 sb->name = NULL;
836 if (sb->buf != NULL)
837 {
838 ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma));
839 if (ent != 0)
840 sym = (*info->symbol_at_address_func) (ent, info);
841 }
842 }
843 if (sym != NULL)
844 (*info->fprintf_func) (info->stream, " [%s@%s]",
845 bfd_asymbol_name (sym), sb->name + 1);
846 else
847 (*info->fprintf_func) (info->stream, " [%" PRIx64 "@%s]",
848 ent, sb->name + 1);
849 return true;
850 }
851 }
852 return false;
853}
854
252b5132
RH
855/* Print a PowerPC or POWER instruction. */
856
857static int
823bbe9d
AM
858print_insn_powerpc (bfd_vma memaddr,
859 struct disassemble_info *info,
860 int bigendian,
fa452fa6 861 ppc_cpu_t dialect)
252b5132
RH
862{
863 bfd_byte buffer[4];
864 int status;
0f873fd5 865 uint64_t insn;
252b5132 866 const struct powerpc_opcode *opcode;
a87a6478 867 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
868
869 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
870
871 /* The final instruction may be a 2-byte VLE insn. */
872 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
873 {
874 /* Clear buffer so unused bytes will not have garbage in them. */
833d919c 875 buffer[2] = buffer[3] = 0;
a87a6478 876 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
833d919c 877 insn_length = 2;
a87a6478
PB
878 }
879
252b5132
RH
880 if (status != 0)
881 {
a87a6478
PB
882 (*info->memory_error_func) (status, memaddr, info);
883 return -1;
252b5132
RH
884 }
885
886 if (bigendian)
887 insn = bfd_getb32 (buffer);
888 else
889 insn = bfd_getl32 (buffer);
890
b9c361e0
JL
891 /* Get the major opcode of the insn. */
892 opcode = NULL;
7c1f4227 893 if ((dialect & PPC_OPCODE_POWER10) != 0
dd7efa79
PB
894 && PPC_OP (insn) == 0x1)
895 {
896 uint64_t temp_insn, suffix;
897 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
898 if (status == 0)
899 {
900 if (bigendian)
901 suffix = bfd_getb32 (buffer);
902 else
903 suffix = bfd_getl32 (buffer);
904 temp_insn = (insn << 32) | suffix;
905 opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
906 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
907 opcode = lookup_prefix (temp_insn, dialect);
908 if (opcode != NULL)
909 {
910 insn = temp_insn;
911 insn_length = 8;
912 if ((info->flags & WIDE_OUTPUT) != 0)
913 info->bytes_per_line = 8;
914 }
915 }
916 }
917 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
b9c361e0
JL
918 {
919 opcode = lookup_vle (insn);
a87a6478
PB
920 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
921 {
922 /* The operands will be fetched out of the 16-bit instruction. */
923 insn >>= 16;
924 insn_length = 2;
925 }
b9c361e0 926 }
833d919c
AM
927 if (opcode == NULL && insn_length == 4)
928 {
929 if ((dialect & PPC_OPCODE_SPE2) != 0)
930 opcode = lookup_spe2 (insn);
931 if (opcode == NULL)
932 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
933 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
934 opcode = lookup_powerpc (insn, dialect);
935 }
252b5132 936
d6688282 937 if (opcode != NULL)
252b5132 938 {
252b5132
RH
939 const unsigned char *opindex;
940 const struct powerpc_operand *operand;
e392bad3
AM
941 enum {
942 need_comma = 0,
943 need_1space = 1,
944 need_2spaces = 2,
945 need_3spaces = 3,
946 need_4spaces = 4,
947 need_5spaces = 5,
948 need_6spaces = 6,
949 need_7spaces = 7,
950 need_paren
951 } op_separator;
78933a4a 952 bool skip_optional;
c3f72de4
AM
953 bool is_pcrel;
954 uint64_t d34;
0e62b37a 955 int blanks;
252b5132 956
c2b1c275
AM
957 (*info->fprintf_func) (info->stream, "%s", opcode->name);
958 /* gdb fprintf_func doesn't return count printed. */
0e62b37a
JB
959 blanks = 8 - strlen (opcode->name);
960 if (blanks <= 0)
961 blanks = 1;
252b5132
RH
962
963 /* Now extract and print the operands. */
0e62b37a 964 op_separator = blanks;
78933a4a 965 skip_optional = false;
c3f72de4
AM
966 is_pcrel = false;
967 d34 = 0;
252b5132
RH
968 for (opindex = opcode->operands; *opindex != 0; opindex++)
969 {
0f873fd5 970 int64_t value;
252b5132
RH
971
972 operand = powerpc_operands + *opindex;
973
0067be51
AM
974 /* If all of the optional operands past this one have their
975 default value, then don't print any of them. Except in
976 raw mode, print them all. */
977 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
978 && (dialect & PPC_OPCODE_RAW) == 0)
65b650b4 979 {
bda678b9 980 if (!skip_optional)
c3f72de4
AM
981 skip_optional = skip_optional_operands (opindex, insn,
982 dialect, &is_pcrel);
65b650b4
AM
983 if (skip_optional)
984 continue;
985 }
252b5132 986
ea192fa3
PB
987 value = operand_value_powerpc (operand, insn, dialect);
988
e392bad3
AM
989 if (op_separator == need_comma)
990 (*info->fprintf_func) (info->stream, ",");
991 else if (op_separator == need_paren)
992 (*info->fprintf_func) (info->stream, "(");
993 else
994 (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
252b5132
RH
995
996 /* Print the operand as directed by the flags. */
fdd12ef3
AM
997 if ((operand->flags & PPC_OPERAND_GPR) != 0
998 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 999 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 1000 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 1001 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 1002 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 1003 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 1004 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 1005 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
aa3c112f
AM
1006 else if ((operand->flags & PPC_OPERAND_ACC) != 0)
1007 (*info->fprintf_func) (info->stream, "a%" PRId64, value);
252b5132
RH
1008 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
1009 (*info->print_address_func) (memaddr + value, info);
1010 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
1011 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 1012 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 1013 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 1014 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 1015 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 1016 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 1017 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 1018 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 1019 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
1020 && (((dialect & PPC_OPCODE_PPC) != 0)
1021 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 1022 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
1023 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1024 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
1025 && (((dialect & PPC_OPCODE_PPC) != 0)
1026 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 1027 {
b9c361e0
JL
1028 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1029 int cr;
1030 int cc;
1031
1032 cr = value >> 2;
1033 if (cr != 0)
1034 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
1035 cc = value & 3;
1036 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 1037 }
70dc4e32 1038 else
d1a3c973 1039 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 1040
c3f72de4
AM
1041 if (operand->shift == 52)
1042 is_pcrel = value != 0;
1043 else if (operand->bitm == UINT64_C (0x3ffffffff))
1044 d34 = value;
1045
e392bad3
AM
1046 if (op_separator == need_paren)
1047 (*info->fprintf_func) (info->stream, ")");
252b5132 1048
e392bad3
AM
1049 op_separator = need_comma;
1050 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1051 op_separator = need_paren;
252b5132
RH
1052 }
1053
c3f72de4
AM
1054 if (is_pcrel)
1055 {
1056 d34 += memaddr;
1057 (*info->fprintf_func) (info->stream, "\t# %" PRIx64, d34);
1058 asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1059 if (sym)
1060 (*info->fprintf_func) (info->stream, " <%s>",
1061 bfd_asymbol_name (sym));
1062
1063 if (info->private_data != NULL
1064 && info->section != NULL
1065 && info->section->owner != NULL
1066 && (bfd_get_file_flags (info->section->owner)
1067 & (EXEC_P | DYNAMIC)) != 0
1068 && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
1069 == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
1070 {
1071 for (int i = 0; i < 2; i++)
1072 if (print_got_plt (private_data (info)->special + i, d34, info))
1073 break;
1074 }
1075 }
1076
a87a6478
PB
1077 /* We have found and printed an instruction. */
1078 return insn_length;
252b5132
RH
1079 }
1080
1081 /* We could not find a match. */
833d919c
AM
1082 if (insn_length == 4)
1083 (*info->fprintf_func) (info->stream, ".long 0x%x",
1084 (unsigned int) insn);
1085 else
1086 (*info->fprintf_func) (info->stream, ".word 0x%x",
1087 (unsigned int) insn >> 16);
1088 return insn_length;
252b5132 1089}
07dd56a9 1090
471b9d15 1091const disasm_options_and_args_t *
65b48a81
PB
1092disassembler_options_powerpc (void)
1093{
471b9d15 1094 static disasm_options_and_args_t *opts_and_args;
65b48a81 1095
471b9d15 1096 if (opts_and_args == NULL)
65b48a81
PB
1097 {
1098 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
1099 disasm_options_t *opts;
1100
1101 opts_and_args = XNEW (disasm_options_and_args_t);
1102 opts_and_args->args = NULL;
1103
1104 opts = &opts_and_args->options;
65b48a81 1105 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
1106 opts->description = NULL;
1107 opts->arg = NULL;
65b48a81
PB
1108 for (i = 0; i < num_options; i++)
1109 opts->name[i] = ppc_opts[i].opt;
1110 /* The array we return must be NULL terminated. */
1111 opts->name[i] = NULL;
65b48a81
PB
1112 }
1113
471b9d15 1114 return opts_and_args;
65b48a81
PB
1115}
1116
07dd56a9 1117void
823bbe9d 1118print_ppc_disassembler_options (FILE *stream)
07dd56a9 1119{
69fe9ce5
AM
1120 unsigned int i, col;
1121
1122 fprintf (stream, _("\n\
07dd56a9 1123The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
1124the -M switch:\n"));
1125
65b48a81 1126 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
1127 {
1128 col += fprintf (stream, " %s,", ppc_opts[i].opt);
1129 if (col > 66)
1130 {
1131 fprintf (stream, "\n");
1132 col = 0;
1133 }
1134 }
65b48a81 1135 fprintf (stream, "\n");
07dd56a9 1136}