]> Git Repo - binutils.git/blame - opcodes/ppc-dis.c
Automatic date update in version.in
[binutils.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
a2c58332 2 Copyright (C) 1994-2022 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 },
61a457e5 134 { "e200z2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_LSP
dfdaec14
AJ
135 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
136 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948 137 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
61a457e5
AM
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),
9b753937 145 0 },
14b57c7c 146 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
69fe9ce5
AM
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
e01d869a 151 | PPC_OPCODE_E500),
69fe9ce5
AM
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 },
0dc93057
AM
157 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
158 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
63d0fa4e
AM
159 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
160 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0dc93057 161 0 },
aea77599
AM
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
c03dc33b 165 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
aea77599
AM
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
c03dc33b 170 | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
aea77599
AM
171 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
172 0 },
69fe9ce5
AM
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
e01d869a 176 | PPC_OPCODE_E500),
69fe9ce5 177 0 },
14b57c7c 178 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 179 0 },
74081948
AF
180 { "efs2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
181 0 },
61a457e5
AM
182 { "lsp", PPC_OPCODE_PPC,
183 PPC_OPCODE_LSP },
14b57c7c 184 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
69fe9ce5 185 0 },
bdc70b4a
AM
186 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
187 | PPC_OPCODE_POWER5),
69fe9ce5 188 0 },
bdc70b4a
AM
189 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
190 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
69fe9ce5 191 0 },
bdc70b4a
AM
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),
69fe9ce5 195 0 },
5817ffd1
PB
196 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
197 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 198 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 199 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 200 0 },
a680de9a
PB
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
ef85eab0 204 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 205 0 },
7c1f4227
AM
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 },
33ae8a3a
DS
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 },
dd7efa79
PB
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
29a6701e
PB
219 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
220 | PPC_OPCODE_FUTURE),
dd7efa79 221 0 },
14b57c7c 222 { "ppc", PPC_OPCODE_PPC,
69fe9ce5 223 0 },
14b57c7c 224 { "ppc32", PPC_OPCODE_PPC,
69fe9ce5 225 0 },
65b48a81
PB
226 { "32", PPC_OPCODE_PPC,
227 0 },
14b57c7c 228 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 229 0 },
65b48a81
PB
230 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
231 0 },
14b57c7c 232 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
69fe9ce5 233 0 },
14b57c7c 234 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
69fe9ce5 235 0 },
14b57c7c 236 { "pwr", PPC_OPCODE_POWER,
69fe9ce5 237 0 },
14b57c7c 238 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
cdc51b07 239 0 },
14b57c7c 240 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
cdc51b07 241 0 },
bdc70b4a
AM
242 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
243 | PPC_OPCODE_POWER5),
cdc51b07 244 0 },
bdc70b4a
AM
245 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
246 | PPC_OPCODE_POWER5),
cdc51b07 247 0 },
bdc70b4a
AM
248 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
249 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
cdc51b07 250 0 },
bdc70b4a
AM
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),
69fe9ce5 254 0 },
5817ffd1
PB
255 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
256 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 257 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 258 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 259 0 },
a680de9a
PB
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
ef85eab0 263 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 264 0 },
1424c35d
AM
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 },
14b57c7c 270 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
69fe9ce5 271 0 },
52be03fd
AM
272 { "raw", PPC_OPCODE_PPC,
273 PPC_OPCODE_RAW },
14b57c7c 274 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 275 PPC_OPCODE_SPE },
74081948
AF
276 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
277 PPC_OPCODE_SPE2 },
bdc70b4a
AM
278 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
279 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
ce3d2015 280 0 },
61a457e5 281 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
14b57c7c
AM
282 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
283 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
61a457e5 284 | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
b9c361e0 285 PPC_OPCODE_VLE },
14b57c7c 286 { "vsx", PPC_OPCODE_PPC,
4b8b687e 287 PPC_OPCODE_VSX },
69fe9ce5
AM
288};
289
b9c361e0
JL
290/* Switch between Booke and VLE dialects for interlinked dumps. */
291static ppc_cpu_t
292get_powerpc_dialect (struct disassemble_info *info)
293{
294 ppc_cpu_t dialect = 0;
295
6f0e0752 296 if (info->private_data)
c3f72de4 297 dialect = private_data (info)->dialect;
b9c361e0
JL
298
299 /* Disassemble according to the section headers flags for VLE-mode. */
300 if (dialect & PPC_OPCODE_VLE
3a2488dd 301 && info->section != NULL && info->section->owner != NULL
94caa966
AM
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)
b9c361e0
JL
305 return dialect;
306 else
307 return dialect & ~ PPC_OPCODE_VLE;
308}
309
69fe9ce5
AM
310/* Handle -m and -M options that set cpu type, and .machine arg. */
311
312ppc_cpu_t
776fc418 313ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
69fe9ce5 314{
69fe9ce5
AM
315 unsigned int i;
316
65b48a81
PB
317 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
318 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
69fe9ce5
AM
319 {
320 if (ppc_opts[i].sticky)
321 {
776fc418
AM
322 *sticky |= ppc_opts[i].sticky;
323 if ((ppc_cpu & ~*sticky) != 0)
69fe9ce5
AM
324 break;
325 }
326 ppc_cpu = ppc_opts[i].cpu;
327 break;
328 }
65b48a81 329 if (i >= ARRAY_SIZE (ppc_opts))
69fe9ce5
AM
330 return 0;
331
61a457e5
AM
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;
776fc418 339 ppc_cpu |= *sticky;
61a457e5 340
69fe9ce5
AM
341 return ppc_cpu;
342}
343
344/* Determine which set of machines to disassemble for. */
418c1742 345
b240011a 346static void
fa452fa6 347powerpc_init_dialect (struct disassemble_info *info)
418c1742 348{
69fe9ce5 349 ppc_cpu_t dialect = 0;
776fc418 350 ppc_cpu_t sticky = 0;
fa452fa6
PB
351 struct dis_private *priv = calloc (sizeof (*priv), 1);
352
353 if (priv == NULL)
6f0e0752 354 return;
418c1742 355
776fc418
AM
356 switch (info->mach)
357 {
358 case bfd_mach_ppc_403:
359 case bfd_mach_ppc_403gc:
4f6ffcd3 360 dialect = ppc_parse_cpu (dialect, &sticky, "403");
776fc418
AM
361 break;
362 case bfd_mach_ppc_405:
4f6ffcd3 363 dialect = ppc_parse_cpu (dialect, &sticky, "405");
776fc418
AM
364 break;
365 case bfd_mach_ppc_601:
4f6ffcd3 366 dialect = ppc_parse_cpu (dialect, &sticky, "601");
776fc418 367 break;
fa758a70
AC
368 case bfd_mach_ppc_750:
369 dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
370 break;
776fc418
AM
371 case bfd_mach_ppc_a35:
372 case bfd_mach_ppc_rs64ii:
373 case bfd_mach_ppc_rs64iii:
4f6ffcd3 374 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
776fc418
AM
375 break;
376 case bfd_mach_ppc_e500:
4f6ffcd3 377 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
776fc418
AM
378 break;
379 case bfd_mach_ppc_e500mc:
4f6ffcd3 380 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
776fc418
AM
381 break;
382 case bfd_mach_ppc_e500mc64:
4f6ffcd3 383 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
776fc418
AM
384 break;
385 case bfd_mach_ppc_e5500:
4f6ffcd3 386 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
776fc418
AM
387 break;
388 case bfd_mach_ppc_e6500:
4f6ffcd3 389 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
776fc418
AM
390 break;
391 case bfd_mach_ppc_titan:
4f6ffcd3 392 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
776fc418
AM
393 break;
394 case bfd_mach_ppc_vle:
4f6ffcd3 395 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
776fc418
AM
396 break;
397 default:
52fe4420 398 if (info->arch == bfd_arch_powerpc)
6bbb0c05 399 dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
52fe4420
AM
400 else
401 dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
65b48a81 402 break;
776fc418
AM
403 }
404
f995bbe8 405 const char *opt;
65b48a81 406 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
69fe9ce5
AM
407 {
408 ppc_cpu_t new_cpu = 0;
9b4e5766 409
65b48a81 410 if (disassembler_options_cmp (opt, "32") == 0)
7102e95e 411 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
65b48a81 412 else if (disassembler_options_cmp (opt, "64") == 0)
bdc70b4a 413 dialect |= PPC_OPCODE_64;
65b48a81
PB
414 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
415 dialect = new_cpu;
69fe9ce5 416 else
a6743a54
AM
417 /* xgettext: c-format */
418 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
69fe9ce5 419 }
661bd698 420
fa452fa6 421 info->private_data = priv;
c3f72de4 422 private_data (info)->dialect = dialect;
b240011a
AM
423}
424
f413a913
AM
425#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
426static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
dd7efa79 427#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
4f6d070a 428static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
f413a913
AM
429#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
430static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
61a457e5
AM
431#define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1))
432static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1];
f413a913
AM
433#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
434static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
b240011a 435
78933a4a 436static bool
7ad57880
NC
437ppc_symbol_is_valid (asymbol *sym,
438 struct disassemble_info *info ATTRIBUTE_UNUSED)
439{
440 elf_symbol_type * est;
441
442 if (sym == NULL)
78933a4a 443 return false;
7ad57880 444
c1229f84 445 est = elf_symbol_from (sym);
c3f72de4 446
7ad57880
NC
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)
78933a4a 453 return false;
7ad57880 454
78933a4a 455 return true;
7ad57880
NC
456}
457
b240011a
AM
458/* Calculate opcode table indices to speed up disassembly,
459 and init dialect. */
460
461void
462disassemble_init_powerpc (struct disassemble_info *info)
463{
7ad57880
NC
464 info->symbol_is_valid = ppc_symbol_is_valid;
465
27c49e9a 466 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 467 {
2ceb7719 468 unsigned seg, idx, op;
27c49e9a 469
2ceb7719
PB
470 /* PPC opcodes */
471 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 472 {
2ceb7719
PB
473 powerpc_opcd_indices[seg] = idx;
474 for (; idx < powerpc_num_opcodes; idx++)
475 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
476 break;
0f873fd5 477 }
27c49e9a 478
dd7efa79
PB
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
2ceb7719
PB
488 /* VLE opcodes */
489 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 490 {
2ceb7719
PB
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 }
0f873fd5 498 }
27c49e9a 499
61a457e5
AM
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
2ceb7719
PB
509 /* SPE2 opcodes */
510 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 511 {
2ceb7719
PB
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 }
0f873fd5 519 }
b9c361e0
JL
520 }
521
52fe4420 522 powerpc_init_dialect (info);
c3f72de4
AM
523 if (info->private_data != NULL)
524 {
525 private_data (info)->special[0].name = ".got";
526 private_data (info)->special[1].name = ".plt";
527 }
418c1742
MG
528}
529
530/* Print a big endian PowerPC instruction. */
252b5132
RH
531
532int
823bbe9d 533print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 534{
b9c361e0 535 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
536}
537
418c1742 538/* Print a little endian PowerPC instruction. */
252b5132
RH
539
540int
823bbe9d 541print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 542{
b9c361e0 543 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
544}
545
ea192fa3
PB
546/* Extract the operand value from the PowerPC or POWER instruction. */
547
0f873fd5 548static int64_t
ea192fa3 549operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 550 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 551{
0f873fd5 552 int64_t value;
9cf7e568 553 int invalid = 0;
ea192fa3
PB
554 /* Extract the value from the instruction. */
555 if (operand->extract)
556 value = (*operand->extract) (insn, dialect, &invalid);
557 else
558 {
b9c361e0
JL
559 if (operand->shift >= 0)
560 value = (insn >> operand->shift) & operand->bitm;
561 else
562 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
563 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
564 {
565 /* BITM is always some number of zeros followed by some
b9c361e0 566 number of ones, followed by some number of zeros. */
0f873fd5 567 uint64_t top = operand->bitm;
ea192fa3
PB
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
59f08271
DS
576 if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
577 ++value;
578
ea192fa3
PB
579 return value;
580}
581
582/* Determine whether the optional operand(s) should be printed. */
583
78933a4a 584static bool
8e5eb8e1 585skip_optional_operands (const ppc_opindex_t *opindex,
c3f72de4 586 uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
ea192fa3
PB
587{
588 const struct powerpc_operand *operand;
9cf7e568 589 int num_optional;
ea192fa3 590
9cf7e568 591 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
592 {
593 operand = &powerpc_operands[*opindex];
9cf7e568 594 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
78933a4a 595 return false;
9cf7e568
AM
596 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
597 {
c3f72de4
AM
598 int64_t value = operand_value_powerpc (operand, insn, dialect);
599
600 if (operand->shift == 52)
601 *is_pcrel = value != 0;
602
9cf7e568
AM
603 /* Negative count is used as a flag to extract function. */
604 --num_optional;
c3f72de4
AM
605 if (value != ppc_optional_operand_value (operand, insn, dialect,
606 num_optional))
78933a4a 607 return false;
9cf7e568 608 }
ea192fa3
PB
609 }
610
78933a4a 611 return true;
ea192fa3
PB
612}
613
52be03fd 614/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 615
d6688282 616static const struct powerpc_opcode *
0f873fd5 617lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 618{
1ff6a3b8 619 const struct powerpc_opcode *opcode, *opcode_end;
d6688282
AM
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 {
8e5eb8e1 631 const ppc_opindex_t *opindex;
d6688282
AM
632 const struct powerpc_operand *operand;
633 int invalid;
634
635 if ((insn & opcode->mask) != opcode->opcode
52be03fd 636 || ((dialect & PPC_OPCODE_ANY) == 0
b508e46b
AM
637 && ((opcode->flags & dialect) == 0
638 || (opcode->deprecated & dialect) != 0))
639 || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
d6688282
AM
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
1ff6a3b8 653 return opcode;
d6688282
AM
654 }
655
1ff6a3b8 656 return NULL;
d6688282
AM
657}
658
dd7efa79
PB
659/* Find a match for INSN in the PREFIX opcode table. */
660
661static const struct powerpc_opcode *
662lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
663{
1ff6a3b8 664 const struct powerpc_opcode *opcode, *opcode_end;
dd7efa79
PB
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];
dd7efa79
PB
672 for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
673 opcode < opcode_end;
674 ++opcode)
675 {
8e5eb8e1 676 const ppc_opindex_t *opindex;
dd7efa79
PB
677 const struct powerpc_operand *operand;
678 int invalid;
679
680 if ((insn & opcode->mask) != opcode->opcode
681 || ((dialect & PPC_OPCODE_ANY) == 0
1ff6a3b8
AM
682 && (opcode->flags & dialect) == 0)
683 || (opcode->deprecated & dialect) != 0)
dd7efa79
PB
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
1ff6a3b8 697 return opcode;
dd7efa79
PB
698 }
699
1ff6a3b8 700 return NULL;
dd7efa79
PB
701}
702
b9c361e0
JL
703/* Find a match for INSN in the VLE opcode table. */
704
705static const struct powerpc_opcode *
1ff6a3b8 706lookup_vle (uint64_t insn, ppc_cpu_t dialect)
b9c361e0
JL
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 {
0f873fd5
PB
726 uint64_t table_opcd = opcode->opcode;
727 uint64_t table_mask = opcode->mask;
78933a4a 728 bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 729 uint64_t insn2;
8e5eb8e1 730 const ppc_opindex_t *opindex;
b9c361e0
JL
731 const struct powerpc_operand *operand;
732 int invalid;
733
734 insn2 = insn;
735 if (table_op_is_short)
736 insn2 >>= 16;
1ff6a3b8
AM
737 if ((insn2 & table_mask) != table_opcd
738 || (opcode->deprecated & dialect) != 0)
b9c361e0
JL
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
61a457e5
AM
758/* Find a match for INSN in the LSP opcode table. */
759
760static const struct powerpc_opcode *
761lookup_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
74081948
AF
803/* Find a match for INSN in the SPE2 opcode table. */
804
805static const struct powerpc_opcode *
1ff6a3b8 806lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
74081948
AF
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
61a457e5 821 /* Find the first match in the opcode table for this opcode. */
74081948
AF
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 {
0f873fd5
PB
827 uint64_t table_opcd = opcode->opcode;
828 uint64_t table_mask = opcode->mask;
829 uint64_t insn2;
8e5eb8e1 830 const ppc_opindex_t *opindex;
74081948
AF
831 const struct powerpc_operand *operand;
832 int invalid;
833
834 insn2 = insn;
1ff6a3b8
AM
835 if ((insn2 & table_mask) != table_opcd
836 || (opcode->deprecated & dialect) != 0)
74081948
AF
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
c3f72de4
AM
856static arelent *
857bsearch_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
874static bool
875print_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 }
36d94bd4 913 (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
c3f72de4 914 if (sym != NULL)
36d94bd4
AB
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 }
c3f72de4 922 else
36d94bd4
AB
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, "]");
c3f72de4
AM
931 return true;
932 }
933 }
934 return false;
935}
936
252b5132
RH
937/* Print a PowerPC or POWER instruction. */
938
939static int
823bbe9d
AM
940print_insn_powerpc (bfd_vma memaddr,
941 struct disassemble_info *info,
942 int bigendian,
fa452fa6 943 ppc_cpu_t dialect)
252b5132
RH
944{
945 bfd_byte buffer[4];
946 int status;
0f873fd5 947 uint64_t insn;
252b5132 948 const struct powerpc_opcode *opcode;
a87a6478 949 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
950
951 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
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. */
833d919c 957 buffer[2] = buffer[3] = 0;
a87a6478 958 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
833d919c 959 insn_length = 2;
a87a6478
PB
960 }
961
252b5132
RH
962 if (status != 0)
963 {
a87a6478
PB
964 (*info->memory_error_func) (status, memaddr, info);
965 return -1;
252b5132
RH
966 }
967
968 if (bigendian)
969 insn = bfd_getb32 (buffer);
970 else
971 insn = bfd_getl32 (buffer);
972
b9c361e0
JL
973 /* Get the major opcode of the insn. */
974 opcode = NULL;
7c1f4227 975 if ((dialect & PPC_OPCODE_POWER10) != 0
dd7efa79
PB
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)
b9c361e0 1000 {
1ff6a3b8 1001 opcode = lookup_vle (insn, dialect);
a87a6478
PB
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 }
b9c361e0 1008 }
833d919c
AM
1009 if (opcode == NULL && insn_length == 4)
1010 {
61a457e5
AM
1011 if ((dialect & PPC_OPCODE_LSP) != 0)
1012 opcode = lookup_lsp (insn, dialect);
833d919c 1013 if ((dialect & PPC_OPCODE_SPE2) != 0)
1ff6a3b8 1014 opcode = lookup_spe2 (insn, dialect);
833d919c
AM
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);
45685a2f
AM
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);
833d919c 1023 }
252b5132 1024
d6688282 1025 if (opcode != NULL)
252b5132 1026 {
8e5eb8e1 1027 const ppc_opindex_t *opindex;
252b5132 1028 const struct powerpc_operand *operand;
e392bad3
AM
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;
78933a4a 1040 bool skip_optional;
c3f72de4
AM
1041 bool is_pcrel;
1042 uint64_t d34;
0e62b37a 1043 int blanks;
252b5132 1044
36d94bd4
AB
1045 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1046 "%s", opcode->name);
1047 /* gdb fprintf_styled_func doesn't return count printed. */
0e62b37a
JB
1048 blanks = 8 - strlen (opcode->name);
1049 if (blanks <= 0)
1050 blanks = 1;
252b5132
RH
1051
1052 /* Now extract and print the operands. */
0e62b37a 1053 op_separator = blanks;
78933a4a 1054 skip_optional = false;
c3f72de4
AM
1055 is_pcrel = false;
1056 d34 = 0;
252b5132
RH
1057 for (opindex = opcode->operands; *opindex != 0; opindex++)
1058 {
0f873fd5 1059 int64_t value;
252b5132
RH
1060
1061 operand = powerpc_operands + *opindex;
1062
0067be51
AM
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)
65b650b4 1068 {
bda678b9 1069 if (!skip_optional)
c3f72de4
AM
1070 skip_optional = skip_optional_operands (opindex, insn,
1071 dialect, &is_pcrel);
65b650b4
AM
1072 if (skip_optional)
1073 continue;
1074 }
252b5132 1075
ea192fa3
PB
1076 value = operand_value_powerpc (operand, insn, dialect);
1077
e392bad3 1078 if (op_separator == need_comma)
36d94bd4 1079 (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
e392bad3 1080 else if (op_separator == need_paren)
36d94bd4 1081 (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
e392bad3 1082 else
36d94bd4
AB
1083 (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
1084 op_separator, " ");
252b5132
RH
1085
1086 /* Print the operand as directed by the flags. */
fdd12ef3
AM
1087 if ((operand->flags & PPC_OPERAND_GPR) != 0
1088 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
36d94bd4
AB
1089 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1090 "r%" PRId64, value);
252b5132 1091 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
36d94bd4
AB
1092 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1093 "f%" PRId64, value);
786e2c0f 1094 else if ((operand->flags & PPC_OPERAND_VR) != 0)
36d94bd4
AB
1095 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1096 "v%" PRId64, value);
9b4e5766 1097 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
36d94bd4
AB
1098 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1099 "vs%" PRId64, value);
79e24d0a
PB
1100 else if ((operand->flags & PPC_OPERAND_DMR) != 0)
1101 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1102 "dm%" PRId64, value);
aa3c112f 1103 else if ((operand->flags & PPC_OPERAND_ACC) != 0)
36d94bd4
AB
1104 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1105 "a%" PRId64, value);
252b5132
RH
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);
43e65147 1110 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
36d94bd4
AB
1111 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1112 "fsl%" PRId64, value);
081ba1b3 1113 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
36d94bd4
AB
1114 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1115 "fcr%" PRId64, value);
081ba1b3 1116 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
36d94bd4
AB
1117 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1118 "%" PRId64, value);
b9c361e0 1119 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 1120 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
1121 && (((dialect & PPC_OPCODE_PPC) != 0)
1122 || ((dialect & PPC_OPCODE_VLE) != 0)))
36d94bd4
AB
1123 (*info->fprintf_styled_func) (info->stream, dis_style_register,
1124 "cr%" PRId64, value);
96a86c01
AM
1125 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1126 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
1127 && (((dialect & PPC_OPCODE_PPC) != 0)
1128 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 1129 {
b9c361e0
JL
1130 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1131 int cr;
1132 int cc;
1133
1134 cr = value >> 2;
b9c361e0 1135 cc = value & 3;
36d94bd4
AB
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]);
252b5132 1150 }
70dc4e32 1151 else
36d94bd4
AB
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 }
252b5132 1164
c3f72de4
AM
1165 if (operand->shift == 52)
1166 is_pcrel = value != 0;
1167 else if (operand->bitm == UINT64_C (0x3ffffffff))
1168 d34 = value;
1169
e392bad3 1170 if (op_separator == need_paren)
36d94bd4 1171 (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
252b5132 1172
e392bad3
AM
1173 op_separator = need_comma;
1174 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1175 op_separator = need_paren;
252b5132
RH
1176 }
1177
c3f72de4
AM
1178 if (is_pcrel)
1179 {
1180 d34 += memaddr;
36d94bd4
AB
1181 (*info->fprintf_styled_func) (info->stream,
1182 dis_style_comment_start,
1183 "\t# %" PRIx64, d34);
c3f72de4
AM
1184 asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1185 if (sym)
36d94bd4
AB
1186 (*info->fprintf_styled_func) (info->stream, dis_style_text,
1187 " <%s>", bfd_asymbol_name (sym));
c3f72de4
AM
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
a87a6478
PB
1203 /* We have found and printed an instruction. */
1204 return insn_length;
252b5132
RH
1205 }
1206
1207 /* We could not find a match. */
833d919c 1208 if (insn_length == 4)
36d94bd4
AB
1209 (*info->fprintf_styled_func) (info->stream,
1210 dis_style_assembler_directive, ".long");
833d919c 1211 else
36d94bd4
AB
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
833d919c 1222 return insn_length;
252b5132 1223}
07dd56a9 1224
471b9d15 1225const disasm_options_and_args_t *
65b48a81
PB
1226disassembler_options_powerpc (void)
1227{
471b9d15 1228 static disasm_options_and_args_t *opts_and_args;
65b48a81 1229
471b9d15 1230 if (opts_and_args == NULL)
65b48a81
PB
1231 {
1232 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
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;
65b48a81 1239 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
1240 opts->description = NULL;
1241 opts->arg = NULL;
65b48a81
PB
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;
65b48a81
PB
1246 }
1247
471b9d15 1248 return opts_and_args;
65b48a81
PB
1249}
1250
07dd56a9 1251void
823bbe9d 1252print_ppc_disassembler_options (FILE *stream)
07dd56a9 1253{
69fe9ce5
AM
1254 unsigned int i, col;
1255
1256 fprintf (stream, _("\n\
07dd56a9 1257The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
1258the -M switch:\n"));
1259
65b48a81 1260 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
1261 {
1262 col += fprintf (stream, " %s,", ppc_opts[i].opt);
1263 if (col > 66)
1264 {
1265 fprintf (stream, "\n");
1266 col = 0;
1267 }
1268 }
65b48a81 1269 fprintf (stream, "\n");
07dd56a9 1270}
This page took 2.332462 seconds and 5 git commands to generate.