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