PowerPC HOWTOs
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
219d1afa 2 Copyright (C) 1994-2018 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;
ea192fa3
PB
454 int invalid;
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
482static int
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;
487
488 for (; *opindex != 0; opindex++)
489 {
490 operand = &powerpc_operands[*opindex];
491 if ((operand->flags & PPC_OPERAND_NEXT) != 0
492 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
11a0cf2e
PB
493 && operand_value_powerpc (operand, insn, dialect) !=
494 ppc_optional_operand_value (operand)))
ea192fa3
PB
495 return 0;
496 }
497
498 return 1;
499}
500
52be03fd 501/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 502
d6688282 503static const struct powerpc_opcode *
0f873fd5 504lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 505{
52be03fd 506 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
507 unsigned long op;
508
509 /* Get the major opcode of the instruction. */
510 op = PPC_OP (insn);
511
512 /* Find the first match in the opcode table for this major opcode. */
513 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 514 last = NULL;
d6688282
AM
515 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
516 opcode < opcode_end;
517 ++opcode)
518 {
519 const unsigned char *opindex;
520 const struct powerpc_operand *operand;
521 int invalid;
522
523 if ((insn & opcode->mask) != opcode->opcode
52be03fd 524 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
525 && ((opcode->flags & dialect) == 0
526 || (opcode->deprecated & dialect) != 0)))
527 continue;
528
529 /* Check validity of operands. */
530 invalid = 0;
531 for (opindex = opcode->operands; *opindex != 0; opindex++)
532 {
533 operand = powerpc_operands + *opindex;
534 if (operand->extract)
535 (*operand->extract) (insn, dialect, &invalid);
536 }
537 if (invalid)
538 continue;
539
52be03fd
AM
540 if ((dialect & PPC_OPCODE_RAW) == 0)
541 return opcode;
542
543 /* The raw machine insn is one that is not a specialization. */
544 if (last == NULL
545 || (last->mask & ~opcode->mask) != 0)
546 last = opcode;
d6688282
AM
547 }
548
52be03fd 549 return last;
d6688282
AM
550}
551
b9c361e0
JL
552/* Find a match for INSN in the VLE opcode table. */
553
554static const struct powerpc_opcode *
0f873fd5 555lookup_vle (uint64_t insn)
b9c361e0
JL
556{
557 const struct powerpc_opcode *opcode;
558 const struct powerpc_opcode *opcode_end;
559 unsigned op, seg;
560
561 op = PPC_OP (insn);
562 if (op >= 0x20 && op <= 0x37)
563 {
564 /* This insn has a 4-bit opcode. */
565 op &= 0x3c;
566 }
567 seg = VLE_OP_TO_SEG (op);
568
569 /* Find the first match in the opcode table for this major opcode. */
570 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
571 for (opcode = vle_opcodes + vle_opcd_indices[seg];
572 opcode < opcode_end;
573 ++opcode)
574 {
0f873fd5
PB
575 uint64_t table_opcd = opcode->opcode;
576 uint64_t table_mask = opcode->mask;
b9c361e0 577 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 578 uint64_t insn2;
b9c361e0
JL
579 const unsigned char *opindex;
580 const struct powerpc_operand *operand;
581 int invalid;
582
583 insn2 = insn;
584 if (table_op_is_short)
585 insn2 >>= 16;
586 if ((insn2 & table_mask) != table_opcd)
587 continue;
588
589 /* Check validity of operands. */
590 invalid = 0;
591 for (opindex = opcode->operands; *opindex != 0; ++opindex)
592 {
593 operand = powerpc_operands + *opindex;
594 if (operand->extract)
595 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
596 }
597 if (invalid)
598 continue;
599
600 return opcode;
601 }
602
603 return NULL;
604}
605
74081948
AF
606/* Find a match for INSN in the SPE2 opcode table. */
607
608static const struct powerpc_opcode *
0f873fd5 609lookup_spe2 (uint64_t insn)
74081948
AF
610{
611 const struct powerpc_opcode *opcode, *opcode_end;
612 unsigned op, xop, seg;
613
614 op = PPC_OP (insn);
615 if (op != 0x4)
616 {
617 /* This is not SPE2 insn.
618 * All SPE2 instructions have OP=4 and differs by XOP */
619 return NULL;
620 }
621 xop = SPE2_XOP (insn);
622 seg = SPE2_XOP_TO_SEG (xop);
623
624 /* Find the first match in the opcode table for this major opcode. */
625 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
626 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
627 opcode < opcode_end;
628 ++opcode)
629 {
0f873fd5
PB
630 uint64_t table_opcd = opcode->opcode;
631 uint64_t table_mask = opcode->mask;
632 uint64_t insn2;
74081948
AF
633 const unsigned char *opindex;
634 const struct powerpc_operand *operand;
635 int invalid;
636
637 insn2 = insn;
638 if ((insn2 & table_mask) != table_opcd)
639 continue;
640
641 /* Check validity of operands. */
642 invalid = 0;
643 for (opindex = opcode->operands; *opindex != 0; ++opindex)
644 {
645 operand = powerpc_operands + *opindex;
646 if (operand->extract)
647 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
648 }
649 if (invalid)
650 continue;
651
652 return opcode;
653 }
654
655 return NULL;
656}
657
252b5132
RH
658/* Print a PowerPC or POWER instruction. */
659
660static int
823bbe9d
AM
661print_insn_powerpc (bfd_vma memaddr,
662 struct disassemble_info *info,
663 int bigendian,
fa452fa6 664 ppc_cpu_t dialect)
252b5132
RH
665{
666 bfd_byte buffer[4];
667 int status;
0f873fd5 668 uint64_t insn;
252b5132 669 const struct powerpc_opcode *opcode;
a87a6478 670 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
671
672 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
673
674 /* The final instruction may be a 2-byte VLE insn. */
675 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
676 {
677 /* Clear buffer so unused bytes will not have garbage in them. */
678 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
679 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
680 }
681
252b5132
RH
682 if (status != 0)
683 {
a87a6478
PB
684 (*info->memory_error_func) (status, memaddr, info);
685 return -1;
252b5132
RH
686 }
687
688 if (bigendian)
689 insn = bfd_getb32 (buffer);
690 else
691 insn = bfd_getl32 (buffer);
692
b9c361e0
JL
693 /* Get the major opcode of the insn. */
694 opcode = NULL;
b9c361e0
JL
695 if ((dialect & PPC_OPCODE_VLE) != 0)
696 {
697 opcode = lookup_vle (insn);
a87a6478
PB
698 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
699 {
700 /* The operands will be fetched out of the 16-bit instruction. */
701 insn >>= 16;
702 insn_length = 2;
703 }
b9c361e0 704 }
74081948
AF
705 if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
706 opcode = lookup_spe2 (insn);
b9c361e0 707 if (opcode == NULL)
52be03fd 708 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
d6688282 709 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
52be03fd 710 opcode = lookup_powerpc (insn, dialect);
252b5132 711
d6688282 712 if (opcode != NULL)
252b5132 713 {
252b5132
RH
714 const unsigned char *opindex;
715 const struct powerpc_operand *operand;
252b5132
RH
716 int need_comma;
717 int need_paren;
ea192fa3 718 int skip_optional;
252b5132 719
252b5132 720 if (opcode->operands[0] != 0)
fdd12ef3
AM
721 (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
722 else
723 (*info->fprintf_func) (info->stream, "%s", opcode->name);
252b5132
RH
724
725 /* Now extract and print the operands. */
726 need_comma = 0;
727 need_paren = 0;
ea192fa3 728 skip_optional = -1;
252b5132
RH
729 for (opindex = opcode->operands; *opindex != 0; opindex++)
730 {
0f873fd5 731 int64_t value;
252b5132
RH
732
733 operand = powerpc_operands + *opindex;
734
ea192fa3
PB
735 /* If all of the optional operands have the value zero,
736 then don't print any of them. */
65b650b4
AM
737 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
738 {
739 if (skip_optional < 0)
740 skip_optional = skip_optional_operands (opindex, insn,
741 dialect);
742 if (skip_optional)
743 continue;
744 }
252b5132 745
ea192fa3
PB
746 value = operand_value_powerpc (operand, insn, dialect);
747
252b5132
RH
748 if (need_comma)
749 {
750 (*info->fprintf_func) (info->stream, ",");
751 need_comma = 0;
752 }
753
754 /* Print the operand as directed by the flags. */
fdd12ef3
AM
755 if ((operand->flags & PPC_OPERAND_GPR) != 0
756 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
0f873fd5 757 (*info->fprintf_func) (info->stream, "r%" PPC_INT_FMT "d", value);
252b5132 758 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
0f873fd5 759 (*info->fprintf_func) (info->stream, "f%" PPC_INT_FMT "d", value);
786e2c0f 760 else if ((operand->flags & PPC_OPERAND_VR) != 0)
0f873fd5 761 (*info->fprintf_func) (info->stream, "v%" PPC_INT_FMT "d", value);
9b4e5766 762 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
0f873fd5 763 (*info->fprintf_func) (info->stream, "vs%" PPC_INT_FMT "d", value);
252b5132
RH
764 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
765 (*info->print_address_func) (memaddr + value, info);
766 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
767 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 768 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
0f873fd5 769 (*info->fprintf_func) (info->stream, "fsl%" PPC_INT_FMT "d", value);
081ba1b3 770 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
0f873fd5 771 (*info->fprintf_func) (info->stream, "fcr%" PPC_INT_FMT "d", value);
081ba1b3 772 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
0f873fd5 773 (*info->fprintf_func) (info->stream, "%" PPC_INT_FMT "d", value);
b9c361e0
JL
774 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
775 && (((dialect & PPC_OPCODE_PPC) != 0)
776 || ((dialect & PPC_OPCODE_VLE) != 0)))
0f873fd5 777 (*info->fprintf_func) (info->stream, "cr%" PPC_INT_FMT "d", value);
b9c361e0
JL
778 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
779 && (((dialect & PPC_OPCODE_PPC) != 0)
780 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 781 {
b9c361e0
JL
782 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
783 int cr;
784 int cc;
785
786 cr = value >> 2;
787 if (cr != 0)
788 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
789 cc = value & 3;
790 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 791 }
70dc4e32 792 else
0f873fd5 793 (*info->fprintf_func) (info->stream, "%" PPC_INT_FMT "d", value);
252b5132
RH
794
795 if (need_paren)
796 {
797 (*info->fprintf_func) (info->stream, ")");
798 need_paren = 0;
799 }
800
801 if ((operand->flags & PPC_OPERAND_PARENS) == 0)
802 need_comma = 1;
803 else
804 {
805 (*info->fprintf_func) (info->stream, "(");
806 need_paren = 1;
807 }
808 }
809
a87a6478
PB
810 /* We have found and printed an instruction. */
811 return insn_length;
252b5132
RH
812 }
813
814 /* We could not find a match. */
0f873fd5 815 (*info->fprintf_func) (info->stream, ".long 0x%" PPC_INT_FMT "x", insn);
252b5132
RH
816
817 return 4;
818}
07dd56a9 819
471b9d15 820const disasm_options_and_args_t *
65b48a81
PB
821disassembler_options_powerpc (void)
822{
471b9d15 823 static disasm_options_and_args_t *opts_and_args;
65b48a81 824
471b9d15 825 if (opts_and_args == NULL)
65b48a81
PB
826 {
827 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
828 disasm_options_t *opts;
829
830 opts_and_args = XNEW (disasm_options_and_args_t);
831 opts_and_args->args = NULL;
832
833 opts = &opts_and_args->options;
65b48a81 834 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
835 opts->description = NULL;
836 opts->arg = NULL;
65b48a81
PB
837 for (i = 0; i < num_options; i++)
838 opts->name[i] = ppc_opts[i].opt;
839 /* The array we return must be NULL terminated. */
840 opts->name[i] = NULL;
65b48a81
PB
841 }
842
471b9d15 843 return opts_and_args;
65b48a81
PB
844}
845
07dd56a9 846void
823bbe9d 847print_ppc_disassembler_options (FILE *stream)
07dd56a9 848{
69fe9ce5
AM
849 unsigned int i, col;
850
851 fprintf (stream, _("\n\
07dd56a9 852The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
853the -M switch:\n"));
854
65b48a81 855 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
856 {
857 col += fprintf (stream, " %s,", ppc_opts[i].opt);
858 if (col > 66)
859 {
860 fprintf (stream, "\n");
861 col = 0;
862 }
863 }
65b48a81 864 fprintf (stream, "\n");
07dd56a9 865}
This page took 0.902838 seconds and 4 git commands to generate.