]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ppc-dis.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
82704155 2 Copyright (C) 1994-2019 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;
b240011a 43} private;
fa452fa6
PB
44
45#define POWERPC_DIALECT(INFO) \
46 (((struct dis_private *) ((INFO)->private_data))->dialect)
418c1742 47
69fe9ce5 48struct ppc_mopt {
9b753937 49 /* Option string, without -m or -M prefix. */
69fe9ce5 50 const char *opt;
9b753937 51 /* CPU option flags. */
69fe9ce5 52 ppc_cpu_t cpu;
9b753937
AM
53 /* Flags that should stay on, even when combined with another cpu
54 option. This should only be used for generic options like
55 "-many" or "-maltivec" where it is reasonable to add some
56 capability to another cpu selection. The added flags are sticky
57 so that, for example, "-many -me500" and "-me500 -many" result in
58 the same assembler or disassembler behaviour. Do not use
59 "sticky" for specific cpus, as this will prevent that cpu's flags
60 from overriding the defaults set in powerpc_init_dialect or a
61 prior -m option. */
69fe9ce5
AM
62 ppc_cpu_t sticky;
63};
64
65struct ppc_mopt ppc_opts[] = {
14b57c7c 66 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403,
69fe9ce5 67 0 },
14b57c7c 68 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
69fe9ce5 69 0 },
bdc70b4a
AM
70 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
71 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 72 0 },
bdc70b4a
AM
73 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
74 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
69fe9ce5 75 0 },
62adc510
AM
76 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
77 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
9fe54b1c 78 0 },
14b57c7c 79 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601,
69fe9ce5 80 0 },
14b57c7c 81 { "603", PPC_OPCODE_PPC,
69fe9ce5 82 0 },
14b57c7c 83 { "604", PPC_OPCODE_PPC,
69fe9ce5 84 0 },
14b57c7c 85 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 86 0 },
14b57c7c 87 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 88 0 },
14b57c7c 89 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 90 0 },
14b57c7c 91 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
69fe9ce5 92 0 },
14b57c7c 93 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
69fe9ce5 94 0 },
14b57c7c 95 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
69fe9ce5 96 , 0 },
fa758a70
AC
97 { "gekko", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
98 , 0 },
99 { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
100 , 0 },
14b57c7c 101 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 102 0 },
14b57c7c 103 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 104 0 },
14b57c7c 105 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860,
ef5a96d5 106 0 },
bdc70b4a
AM
107 { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
108 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
109 | PPC_OPCODE_A2),
cdc51b07 110 0 },
14b57c7c 111 { "altivec", PPC_OPCODE_PPC,
4b8b687e 112 PPC_OPCODE_ALTIVEC },
52be03fd 113 { "any", PPC_OPCODE_PPC,
69fe9ce5 114 PPC_OPCODE_ANY },
14b57c7c 115 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 116 0 },
14b57c7c 117 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
69fe9ce5 118 0 },
bdc70b4a
AM
119 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
120 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
69fe9ce5 121 0 },
14b57c7c 122 { "com", PPC_OPCODE_COMMON,
69fe9ce5 123 0 },
dfdaec14
AJ
124 { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
125 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
126 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948
AF
127 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
128 | PPC_OPCODE_EFS2 | PPC_OPCODE_LSP),
9b753937 129 0 },
14b57c7c 130 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
69fe9ce5
AM
131 0 },
132 { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
133 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
134 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
e01d869a 135 | PPC_OPCODE_E500),
69fe9ce5
AM
136 0 },
137 { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
138 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
139 | PPC_OPCODE_E500MC),
140 0 },
0dc93057
AM
141 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
142 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
63d0fa4e
AM
143 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
144 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
0dc93057 145 0 },
aea77599
AM
146 { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
147 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
148 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
c03dc33b 149 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
aea77599
AM
150 0 },
151 { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
152 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
153 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
c03dc33b 154 | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
aea77599
AM
155 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
156 0 },
69fe9ce5
AM
157 { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
158 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
159 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
e01d869a 160 | PPC_OPCODE_E500),
69fe9ce5 161 0 },
14b57c7c 162 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 163 0 },
74081948
AF
164 { "efs2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
165 0 },
14b57c7c 166 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
69fe9ce5 167 0 },
bdc70b4a
AM
168 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
169 | PPC_OPCODE_POWER5),
69fe9ce5 170 0 },
bdc70b4a
AM
171 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
172 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
69fe9ce5 173 0 },
bdc70b4a
AM
174 { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
175 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
176 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
69fe9ce5 177 0 },
5817ffd1
PB
178 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
179 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 180 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 181 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 182 0 },
a680de9a
PB
183 { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
184 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
185 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
ef85eab0 186 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 187 0 },
14b57c7c 188 { "ppc", PPC_OPCODE_PPC,
69fe9ce5 189 0 },
14b57c7c 190 { "ppc32", PPC_OPCODE_PPC,
69fe9ce5 191 0 },
65b48a81
PB
192 { "32", PPC_OPCODE_PPC,
193 0 },
14b57c7c 194 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 195 0 },
65b48a81
PB
196 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
197 0 },
14b57c7c 198 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
69fe9ce5 199 0 },
14b57c7c 200 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
69fe9ce5 201 0 },
14b57c7c 202 { "pwr", PPC_OPCODE_POWER,
69fe9ce5 203 0 },
14b57c7c 204 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
cdc51b07 205 0 },
14b57c7c 206 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
cdc51b07 207 0 },
bdc70b4a
AM
208 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
209 | PPC_OPCODE_POWER5),
cdc51b07 210 0 },
bdc70b4a
AM
211 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
212 | PPC_OPCODE_POWER5),
cdc51b07 213 0 },
bdc70b4a
AM
214 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
215 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
cdc51b07 216 0 },
bdc70b4a
AM
217 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
218 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
219 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
69fe9ce5 220 0 },
5817ffd1
PB
221 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
222 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 223 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 224 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 225 0 },
a680de9a
PB
226 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
227 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
228 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
ef85eab0 229 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 230 0 },
14b57c7c 231 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
69fe9ce5 232 0 },
52be03fd
AM
233 { "raw", PPC_OPCODE_PPC,
234 PPC_OPCODE_RAW },
14b57c7c 235 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 236 PPC_OPCODE_SPE },
74081948
AF
237 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
238 PPC_OPCODE_SPE2 },
bdc70b4a
AM
239 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
240 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
ce3d2015 241 0 },
14b57c7c
AM
242 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
243 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
244 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948 245 | PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
b9c361e0 246 PPC_OPCODE_VLE },
14b57c7c 247 { "vsx", PPC_OPCODE_PPC,
4b8b687e 248 PPC_OPCODE_VSX },
69fe9ce5
AM
249};
250
b9c361e0
JL
251/* Switch between Booke and VLE dialects for interlinked dumps. */
252static ppc_cpu_t
253get_powerpc_dialect (struct disassemble_info *info)
254{
255 ppc_cpu_t dialect = 0;
256
257 dialect = POWERPC_DIALECT (info);
258
259 /* Disassemble according to the section headers flags for VLE-mode. */
260 if (dialect & PPC_OPCODE_VLE
3a2488dd 261 && info->section != NULL && info->section->owner != NULL
94caa966
AM
262 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
263 && elf_object_id (info->section->owner) == PPC32_ELF_DATA
264 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
b9c361e0
JL
265 return dialect;
266 else
267 return dialect & ~ PPC_OPCODE_VLE;
268}
269
69fe9ce5
AM
270/* Handle -m and -M options that set cpu type, and .machine arg. */
271
272ppc_cpu_t
776fc418 273ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
69fe9ce5 274{
69fe9ce5
AM
275 unsigned int i;
276
65b48a81
PB
277 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
278 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
69fe9ce5
AM
279 {
280 if (ppc_opts[i].sticky)
281 {
776fc418
AM
282 *sticky |= ppc_opts[i].sticky;
283 if ((ppc_cpu & ~*sticky) != 0)
69fe9ce5
AM
284 break;
285 }
286 ppc_cpu = ppc_opts[i].cpu;
287 break;
288 }
65b48a81 289 if (i >= ARRAY_SIZE (ppc_opts))
69fe9ce5
AM
290 return 0;
291
776fc418 292 ppc_cpu |= *sticky;
69fe9ce5
AM
293 return ppc_cpu;
294}
295
296/* Determine which set of machines to disassemble for. */
418c1742 297
b240011a 298static void
fa452fa6 299powerpc_init_dialect (struct disassemble_info *info)
418c1742 300{
69fe9ce5 301 ppc_cpu_t dialect = 0;
776fc418 302 ppc_cpu_t sticky = 0;
fa452fa6
PB
303 struct dis_private *priv = calloc (sizeof (*priv), 1);
304
305 if (priv == NULL)
b240011a 306 priv = &private;
418c1742 307
776fc418
AM
308 switch (info->mach)
309 {
310 case bfd_mach_ppc_403:
311 case bfd_mach_ppc_403gc:
4f6ffcd3 312 dialect = ppc_parse_cpu (dialect, &sticky, "403");
776fc418
AM
313 break;
314 case bfd_mach_ppc_405:
4f6ffcd3 315 dialect = ppc_parse_cpu (dialect, &sticky, "405");
776fc418
AM
316 break;
317 case bfd_mach_ppc_601:
4f6ffcd3 318 dialect = ppc_parse_cpu (dialect, &sticky, "601");
776fc418 319 break;
fa758a70
AC
320 case bfd_mach_ppc_750:
321 dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
322 break;
776fc418
AM
323 case bfd_mach_ppc_a35:
324 case bfd_mach_ppc_rs64ii:
325 case bfd_mach_ppc_rs64iii:
4f6ffcd3 326 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
776fc418
AM
327 break;
328 case bfd_mach_ppc_e500:
4f6ffcd3 329 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
776fc418
AM
330 break;
331 case bfd_mach_ppc_e500mc:
4f6ffcd3 332 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
776fc418
AM
333 break;
334 case bfd_mach_ppc_e500mc64:
4f6ffcd3 335 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
776fc418
AM
336 break;
337 case bfd_mach_ppc_e5500:
4f6ffcd3 338 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
776fc418
AM
339 break;
340 case bfd_mach_ppc_e6500:
4f6ffcd3 341 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
776fc418
AM
342 break;
343 case bfd_mach_ppc_titan:
4f6ffcd3 344 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
776fc418
AM
345 break;
346 case bfd_mach_ppc_vle:
4f6ffcd3 347 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
776fc418
AM
348 break;
349 default:
52fe4420
AM
350 if (info->arch == bfd_arch_powerpc)
351 dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY;
352 else
353 dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
65b48a81 354 break;
776fc418
AM
355 }
356
f995bbe8 357 const char *opt;
65b48a81 358 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
69fe9ce5
AM
359 {
360 ppc_cpu_t new_cpu = 0;
9b4e5766 361
65b48a81 362 if (disassembler_options_cmp (opt, "32") == 0)
7102e95e 363 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
65b48a81 364 else if (disassembler_options_cmp (opt, "64") == 0)
bdc70b4a 365 dialect |= PPC_OPCODE_64;
65b48a81
PB
366 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
367 dialect = new_cpu;
69fe9ce5 368 else
a6743a54
AM
369 /* xgettext: c-format */
370 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
69fe9ce5 371 }
661bd698 372
fa452fa6
PB
373 info->private_data = priv;
374 POWERPC_DIALECT(info) = dialect;
b240011a
AM
375}
376
f413a913
AM
377#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
378static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
379#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
380static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
381#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
382static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
b240011a
AM
383
384/* Calculate opcode table indices to speed up disassembly,
385 and init dialect. */
386
387void
388disassemble_init_powerpc (struct disassemble_info *info)
389{
27c49e9a 390 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 391 {
2ceb7719 392 unsigned seg, idx, op;
27c49e9a 393
2ceb7719
PB
394 /* PPC opcodes */
395 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 396 {
2ceb7719
PB
397 powerpc_opcd_indices[seg] = idx;
398 for (; idx < powerpc_num_opcodes; idx++)
399 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
400 break;
0f873fd5 401 }
27c49e9a 402
2ceb7719
PB
403 /* VLE opcodes */
404 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 405 {
2ceb7719
PB
406 vle_opcd_indices[seg] = idx;
407 for (; idx < vle_num_opcodes; idx++)
408 {
409 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
410 if (seg < VLE_OP_TO_SEG (op))
411 break;
412 }
0f873fd5 413 }
27c49e9a 414
2ceb7719
PB
415 /* SPE2 opcodes */
416 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 417 {
2ceb7719
PB
418 spe2_opcd_indices[seg] = idx;
419 for (; idx < spe2_num_opcodes; idx++)
420 {
421 op = SPE2_XOP (spe2_opcodes[idx].opcode);
422 if (seg < SPE2_XOP_TO_SEG (op))
423 break;
424 }
0f873fd5 425 }
b9c361e0
JL
426 }
427
52fe4420 428 powerpc_init_dialect (info);
418c1742
MG
429}
430
431/* Print a big endian PowerPC instruction. */
252b5132
RH
432
433int
823bbe9d 434print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 435{
b9c361e0 436 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
437}
438
418c1742 439/* Print a little endian PowerPC instruction. */
252b5132
RH
440
441int
823bbe9d 442print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 443{
b9c361e0 444 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
445}
446
ea192fa3
PB
447/* Extract the operand value from the PowerPC or POWER instruction. */
448
0f873fd5 449static int64_t
ea192fa3 450operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 451 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 452{
0f873fd5 453 int64_t value;
9cf7e568 454 int invalid = 0;
ea192fa3
PB
455 /* Extract the value from the instruction. */
456 if (operand->extract)
457 value = (*operand->extract) (insn, dialect, &invalid);
458 else
459 {
b9c361e0
JL
460 if (operand->shift >= 0)
461 value = (insn >> operand->shift) & operand->bitm;
462 else
463 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
464 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
465 {
466 /* BITM is always some number of zeros followed by some
b9c361e0 467 number of ones, followed by some number of zeros. */
0f873fd5 468 uint64_t top = operand->bitm;
ea192fa3
PB
469 /* top & -top gives the rightmost 1 bit, so this
470 fills in any trailing zeros. */
471 top |= (top & -top) - 1;
472 top &= ~(top >> 1);
473 value = (value ^ top) - top;
474 }
475 }
476
477 return value;
478}
479
480/* Determine whether the optional operand(s) should be printed. */
481
bda678b9 482static bfd_boolean
ea192fa3 483skip_optional_operands (const unsigned char *opindex,
0f873fd5 484 uint64_t insn, ppc_cpu_t dialect)
ea192fa3
PB
485{
486 const struct powerpc_operand *operand;
9cf7e568 487 int num_optional;
ea192fa3 488
9cf7e568 489 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
490 {
491 operand = &powerpc_operands[*opindex];
9cf7e568 492 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
bda678b9 493 return FALSE;
9cf7e568
AM
494 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
495 {
496 /* Negative count is used as a flag to extract function. */
497 --num_optional;
498 if (operand_value_powerpc (operand, insn, dialect)
499 != ppc_optional_operand_value (operand, insn, dialect,
500 num_optional))
bda678b9 501 return FALSE;
9cf7e568 502 }
ea192fa3
PB
503 }
504
bda678b9 505 return TRUE;
ea192fa3
PB
506}
507
52be03fd 508/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 509
d6688282 510static const struct powerpc_opcode *
0f873fd5 511lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 512{
52be03fd 513 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
514 unsigned long op;
515
516 /* Get the major opcode of the instruction. */
517 op = PPC_OP (insn);
518
519 /* Find the first match in the opcode table for this major opcode. */
520 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 521 last = NULL;
d6688282
AM
522 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
523 opcode < opcode_end;
524 ++opcode)
525 {
526 const unsigned char *opindex;
527 const struct powerpc_operand *operand;
528 int invalid;
529
530 if ((insn & opcode->mask) != opcode->opcode
52be03fd 531 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
532 && ((opcode->flags & dialect) == 0
533 || (opcode->deprecated & dialect) != 0)))
534 continue;
535
536 /* Check validity of operands. */
537 invalid = 0;
538 for (opindex = opcode->operands; *opindex != 0; opindex++)
539 {
540 operand = powerpc_operands + *opindex;
541 if (operand->extract)
542 (*operand->extract) (insn, dialect, &invalid);
543 }
544 if (invalid)
545 continue;
546
52be03fd
AM
547 if ((dialect & PPC_OPCODE_RAW) == 0)
548 return opcode;
549
550 /* The raw machine insn is one that is not a specialization. */
551 if (last == NULL
552 || (last->mask & ~opcode->mask) != 0)
553 last = opcode;
d6688282
AM
554 }
555
52be03fd 556 return last;
d6688282
AM
557}
558
b9c361e0
JL
559/* Find a match for INSN in the VLE opcode table. */
560
561static const struct powerpc_opcode *
0f873fd5 562lookup_vle (uint64_t insn)
b9c361e0
JL
563{
564 const struct powerpc_opcode *opcode;
565 const struct powerpc_opcode *opcode_end;
566 unsigned op, seg;
567
568 op = PPC_OP (insn);
569 if (op >= 0x20 && op <= 0x37)
570 {
571 /* This insn has a 4-bit opcode. */
572 op &= 0x3c;
573 }
574 seg = VLE_OP_TO_SEG (op);
575
576 /* Find the first match in the opcode table for this major opcode. */
577 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
578 for (opcode = vle_opcodes + vle_opcd_indices[seg];
579 opcode < opcode_end;
580 ++opcode)
581 {
0f873fd5
PB
582 uint64_t table_opcd = opcode->opcode;
583 uint64_t table_mask = opcode->mask;
b9c361e0 584 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 585 uint64_t insn2;
b9c361e0
JL
586 const unsigned char *opindex;
587 const struct powerpc_operand *operand;
588 int invalid;
589
590 insn2 = insn;
591 if (table_op_is_short)
592 insn2 >>= 16;
593 if ((insn2 & table_mask) != table_opcd)
594 continue;
595
596 /* Check validity of operands. */
597 invalid = 0;
598 for (opindex = opcode->operands; *opindex != 0; ++opindex)
599 {
600 operand = powerpc_operands + *opindex;
601 if (operand->extract)
602 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
603 }
604 if (invalid)
605 continue;
606
607 return opcode;
608 }
609
610 return NULL;
611}
612
74081948
AF
613/* Find a match for INSN in the SPE2 opcode table. */
614
615static const struct powerpc_opcode *
0f873fd5 616lookup_spe2 (uint64_t insn)
74081948
AF
617{
618 const struct powerpc_opcode *opcode, *opcode_end;
619 unsigned op, xop, seg;
620
621 op = PPC_OP (insn);
622 if (op != 0x4)
623 {
624 /* This is not SPE2 insn.
625 * All SPE2 instructions have OP=4 and differs by XOP */
626 return NULL;
627 }
628 xop = SPE2_XOP (insn);
629 seg = SPE2_XOP_TO_SEG (xop);
630
631 /* Find the first match in the opcode table for this major opcode. */
632 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
633 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
634 opcode < opcode_end;
635 ++opcode)
636 {
0f873fd5
PB
637 uint64_t table_opcd = opcode->opcode;
638 uint64_t table_mask = opcode->mask;
639 uint64_t insn2;
74081948
AF
640 const unsigned char *opindex;
641 const struct powerpc_operand *operand;
642 int invalid;
643
644 insn2 = insn;
645 if ((insn2 & table_mask) != table_opcd)
646 continue;
647
648 /* Check validity of operands. */
649 invalid = 0;
650 for (opindex = opcode->operands; *opindex != 0; ++opindex)
651 {
652 operand = powerpc_operands + *opindex;
653 if (operand->extract)
654 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
655 }
656 if (invalid)
657 continue;
658
659 return opcode;
660 }
661
662 return NULL;
663}
664
252b5132
RH
665/* Print a PowerPC or POWER instruction. */
666
667static int
823bbe9d
AM
668print_insn_powerpc (bfd_vma memaddr,
669 struct disassemble_info *info,
670 int bigendian,
fa452fa6 671 ppc_cpu_t dialect)
252b5132
RH
672{
673 bfd_byte buffer[4];
674 int status;
0f873fd5 675 uint64_t insn;
252b5132 676 const struct powerpc_opcode *opcode;
a87a6478 677 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
678
679 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
680
681 /* The final instruction may be a 2-byte VLE insn. */
682 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
683 {
684 /* Clear buffer so unused bytes will not have garbage in them. */
685 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
686 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
687 }
688
252b5132
RH
689 if (status != 0)
690 {
a87a6478
PB
691 (*info->memory_error_func) (status, memaddr, info);
692 return -1;
252b5132
RH
693 }
694
695 if (bigendian)
696 insn = bfd_getb32 (buffer);
697 else
698 insn = bfd_getl32 (buffer);
699
b9c361e0
JL
700 /* Get the major opcode of the insn. */
701 opcode = NULL;
b9c361e0
JL
702 if ((dialect & PPC_OPCODE_VLE) != 0)
703 {
704 opcode = lookup_vle (insn);
a87a6478
PB
705 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
706 {
707 /* The operands will be fetched out of the 16-bit instruction. */
708 insn >>= 16;
709 insn_length = 2;
710 }
b9c361e0 711 }
74081948
AF
712 if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
713 opcode = lookup_spe2 (insn);
b9c361e0 714 if (opcode == NULL)
52be03fd 715 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
d6688282 716 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
52be03fd 717 opcode = lookup_powerpc (insn, dialect);
252b5132 718
d6688282 719 if (opcode != NULL)
252b5132 720 {
252b5132
RH
721 const unsigned char *opindex;
722 const struct powerpc_operand *operand;
e392bad3
AM
723 enum {
724 need_comma = 0,
725 need_1space = 1,
726 need_2spaces = 2,
727 need_3spaces = 3,
728 need_4spaces = 4,
729 need_5spaces = 5,
730 need_6spaces = 6,
731 need_7spaces = 7,
732 need_paren
733 } op_separator;
bda678b9 734 bfd_boolean skip_optional;
c2b1c275 735 int spaces;
252b5132 736
c2b1c275
AM
737 (*info->fprintf_func) (info->stream, "%s", opcode->name);
738 /* gdb fprintf_func doesn't return count printed. */
739 spaces = 8 - strlen (opcode->name);
740 if (spaces <= 0)
741 spaces = 1;
252b5132
RH
742
743 /* Now extract and print the operands. */
e392bad3 744 op_separator = spaces;
bda678b9 745 skip_optional = FALSE;
252b5132
RH
746 for (opindex = opcode->operands; *opindex != 0; opindex++)
747 {
0f873fd5 748 int64_t value;
252b5132
RH
749
750 operand = powerpc_operands + *opindex;
751
0067be51
AM
752 /* If all of the optional operands past this one have their
753 default value, then don't print any of them. Except in
754 raw mode, print them all. */
755 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
756 && (dialect & PPC_OPCODE_RAW) == 0)
65b650b4 757 {
bda678b9
PB
758 if (!skip_optional)
759 skip_optional = skip_optional_operands (opindex, insn, dialect);
65b650b4
AM
760 if (skip_optional)
761 continue;
762 }
252b5132 763
ea192fa3
PB
764 value = operand_value_powerpc (operand, insn, dialect);
765
e392bad3
AM
766 if (op_separator == need_comma)
767 (*info->fprintf_func) (info->stream, ",");
768 else if (op_separator == need_paren)
769 (*info->fprintf_func) (info->stream, "(");
770 else
771 (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
252b5132
RH
772
773 /* Print the operand as directed by the flags. */
fdd12ef3
AM
774 if ((operand->flags & PPC_OPERAND_GPR) != 0
775 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 776 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 777 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 778 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 779 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 780 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 781 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 782 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
252b5132
RH
783 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
784 (*info->print_address_func) (memaddr + value, info);
785 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
786 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 787 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 788 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 789 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 790 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 791 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 792 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 793 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 794 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
795 && (((dialect & PPC_OPCODE_PPC) != 0)
796 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 797 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
798 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
799 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
800 && (((dialect & PPC_OPCODE_PPC) != 0)
801 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 802 {
b9c361e0
JL
803 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
804 int cr;
805 int cc;
806
807 cr = value >> 2;
808 if (cr != 0)
809 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
810 cc = value & 3;
811 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 812 }
70dc4e32 813 else
d1a3c973 814 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 815
e392bad3
AM
816 if (op_separator == need_paren)
817 (*info->fprintf_func) (info->stream, ")");
252b5132 818
e392bad3
AM
819 op_separator = need_comma;
820 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
821 op_separator = need_paren;
252b5132
RH
822 }
823
a87a6478
PB
824 /* We have found and printed an instruction. */
825 return insn_length;
252b5132
RH
826 }
827
828 /* We could not find a match. */
d1a3c973 829 (*info->fprintf_func) (info->stream, ".long 0x%" PRIx64, insn);
252b5132
RH
830
831 return 4;
832}
07dd56a9 833
471b9d15 834const disasm_options_and_args_t *
65b48a81
PB
835disassembler_options_powerpc (void)
836{
471b9d15 837 static disasm_options_and_args_t *opts_and_args;
65b48a81 838
471b9d15 839 if (opts_and_args == NULL)
65b48a81
PB
840 {
841 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
842 disasm_options_t *opts;
843
844 opts_and_args = XNEW (disasm_options_and_args_t);
845 opts_and_args->args = NULL;
846
847 opts = &opts_and_args->options;
65b48a81 848 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
849 opts->description = NULL;
850 opts->arg = NULL;
65b48a81
PB
851 for (i = 0; i < num_options; i++)
852 opts->name[i] = ppc_opts[i].opt;
853 /* The array we return must be NULL terminated. */
854 opts->name[i] = NULL;
65b48a81
PB
855 }
856
471b9d15 857 return opts_and_args;
65b48a81
PB
858}
859
07dd56a9 860void
823bbe9d 861print_ppc_disassembler_options (FILE *stream)
07dd56a9 862{
69fe9ce5
AM
863 unsigned int i, col;
864
865 fprintf (stream, _("\n\
07dd56a9 866The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
867the -M switch:\n"));
868
65b48a81 869 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
870 {
871 col += fprintf (stream, " %s,", ppc_opts[i].opt);
872 if (col > 66)
873 {
874 fprintf (stream, "\n");
875 col = 0;
876 }
877 }
65b48a81 878 fprintf (stream, "\n");
07dd56a9 879}