Bug 23142, SIGSEGV in is_strip_section
[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{
383 int i;
d6688282 384 unsigned short last;
fa452fa6 385
27c49e9a 386 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 387 {
27c49e9a
AB
388 i = powerpc_num_opcodes;
389 while (--i >= 0)
0f873fd5
PB
390 {
391 unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
392 powerpc_opcd_indices[op] = i;
393 }
27c49e9a
AB
394
395 last = powerpc_num_opcodes;
396 for (i = PPC_OPCD_SEGS; i > 0; --i)
0f873fd5
PB
397 {
398 if (powerpc_opcd_indices[i] == 0)
27c49e9a 399 powerpc_opcd_indices[i] = last;
0f873fd5
PB
400 last = powerpc_opcd_indices[i];
401 }
27c49e9a
AB
402
403 i = vle_num_opcodes;
404 while (--i >= 0)
0f873fd5
PB
405 {
406 unsigned op = VLE_OP (vle_opcodes[i].opcode, vle_opcodes[i].mask);
407 unsigned seg = VLE_OP_TO_SEG (op);
408 vle_opcd_indices[seg] = i;
409 }
27c49e9a
AB
410
411 last = vle_num_opcodes;
412 for (i = VLE_OPCD_SEGS; i > 0; --i)
0f873fd5
PB
413 {
414 if (vle_opcd_indices[i] == 0)
27c49e9a 415 vle_opcd_indices[i] = last;
0f873fd5
PB
416 last = vle_opcd_indices[i];
417 }
b9c361e0
JL
418 }
419
74081948
AF
420 /* SPE2 opcodes */
421 i = spe2_num_opcodes;
422 while (--i >= 0)
423 {
424 unsigned xop = SPE2_XOP (spe2_opcodes[i].opcode);
425 unsigned seg = SPE2_XOP_TO_SEG (xop);
74081948
AF
426 spe2_opcd_indices[seg] = i;
427 }
428
429 last = spe2_num_opcodes;
430 for (i = SPE2_OPCD_SEGS; i > 1; --i)
431 {
432 if (spe2_opcd_indices[i] == 0)
433 spe2_opcd_indices[i] = last;
434 last = spe2_opcd_indices[i];
435 }
436
52fe4420 437 powerpc_init_dialect (info);
418c1742
MG
438}
439
440/* Print a big endian PowerPC instruction. */
252b5132
RH
441
442int
823bbe9d 443print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 444{
b9c361e0 445 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
446}
447
418c1742 448/* Print a little endian PowerPC instruction. */
252b5132
RH
449
450int
823bbe9d 451print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 452{
b9c361e0 453 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
454}
455
ea192fa3
PB
456/* Extract the operand value from the PowerPC or POWER instruction. */
457
0f873fd5 458static int64_t
ea192fa3 459operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 460 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 461{
0f873fd5 462 int64_t value;
ea192fa3
PB
463 int invalid;
464 /* Extract the value from the instruction. */
465 if (operand->extract)
466 value = (*operand->extract) (insn, dialect, &invalid);
467 else
468 {
b9c361e0
JL
469 if (operand->shift >= 0)
470 value = (insn >> operand->shift) & operand->bitm;
471 else
472 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
473 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
474 {
475 /* BITM is always some number of zeros followed by some
b9c361e0 476 number of ones, followed by some number of zeros. */
0f873fd5 477 uint64_t top = operand->bitm;
ea192fa3
PB
478 /* top & -top gives the rightmost 1 bit, so this
479 fills in any trailing zeros. */
480 top |= (top & -top) - 1;
481 top &= ~(top >> 1);
482 value = (value ^ top) - top;
483 }
484 }
485
486 return value;
487}
488
489/* Determine whether the optional operand(s) should be printed. */
490
491static int
492skip_optional_operands (const unsigned char *opindex,
0f873fd5 493 uint64_t insn, ppc_cpu_t dialect)
ea192fa3
PB
494{
495 const struct powerpc_operand *operand;
496
497 for (; *opindex != 0; opindex++)
498 {
499 operand = &powerpc_operands[*opindex];
500 if ((operand->flags & PPC_OPERAND_NEXT) != 0
501 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
11a0cf2e
PB
502 && operand_value_powerpc (operand, insn, dialect) !=
503 ppc_optional_operand_value (operand)))
ea192fa3
PB
504 return 0;
505 }
506
507 return 1;
508}
509
52be03fd 510/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 511
d6688282 512static const struct powerpc_opcode *
0f873fd5 513lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 514{
52be03fd 515 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
516 unsigned long op;
517
518 /* Get the major opcode of the instruction. */
519 op = PPC_OP (insn);
520
521 /* Find the first match in the opcode table for this major opcode. */
522 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 523 last = NULL;
d6688282
AM
524 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
525 opcode < opcode_end;
526 ++opcode)
527 {
528 const unsigned char *opindex;
529 const struct powerpc_operand *operand;
530 int invalid;
531
532 if ((insn & opcode->mask) != opcode->opcode
52be03fd 533 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
534 && ((opcode->flags & dialect) == 0
535 || (opcode->deprecated & dialect) != 0)))
536 continue;
537
538 /* Check validity of operands. */
539 invalid = 0;
540 for (opindex = opcode->operands; *opindex != 0; opindex++)
541 {
542 operand = powerpc_operands + *opindex;
543 if (operand->extract)
544 (*operand->extract) (insn, dialect, &invalid);
545 }
546 if (invalid)
547 continue;
548
52be03fd
AM
549 if ((dialect & PPC_OPCODE_RAW) == 0)
550 return opcode;
551
552 /* The raw machine insn is one that is not a specialization. */
553 if (last == NULL
554 || (last->mask & ~opcode->mask) != 0)
555 last = opcode;
d6688282
AM
556 }
557
52be03fd 558 return last;
d6688282
AM
559}
560
b9c361e0
JL
561/* Find a match for INSN in the VLE opcode table. */
562
563static const struct powerpc_opcode *
0f873fd5 564lookup_vle (uint64_t insn)
b9c361e0
JL
565{
566 const struct powerpc_opcode *opcode;
567 const struct powerpc_opcode *opcode_end;
568 unsigned op, seg;
569
570 op = PPC_OP (insn);
571 if (op >= 0x20 && op <= 0x37)
572 {
573 /* This insn has a 4-bit opcode. */
574 op &= 0x3c;
575 }
576 seg = VLE_OP_TO_SEG (op);
577
578 /* Find the first match in the opcode table for this major opcode. */
579 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
580 for (opcode = vle_opcodes + vle_opcd_indices[seg];
581 opcode < opcode_end;
582 ++opcode)
583 {
0f873fd5
PB
584 uint64_t table_opcd = opcode->opcode;
585 uint64_t table_mask = opcode->mask;
b9c361e0 586 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 587 uint64_t insn2;
b9c361e0
JL
588 const unsigned char *opindex;
589 const struct powerpc_operand *operand;
590 int invalid;
591
592 insn2 = insn;
593 if (table_op_is_short)
594 insn2 >>= 16;
595 if ((insn2 & table_mask) != table_opcd)
596 continue;
597
598 /* Check validity of operands. */
599 invalid = 0;
600 for (opindex = opcode->operands; *opindex != 0; ++opindex)
601 {
602 operand = powerpc_operands + *opindex;
603 if (operand->extract)
604 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
605 }
606 if (invalid)
607 continue;
608
609 return opcode;
610 }
611
612 return NULL;
613}
614
74081948
AF
615/* Find a match for INSN in the SPE2 opcode table. */
616
617static const struct powerpc_opcode *
0f873fd5 618lookup_spe2 (uint64_t insn)
74081948
AF
619{
620 const struct powerpc_opcode *opcode, *opcode_end;
621 unsigned op, xop, seg;
622
623 op = PPC_OP (insn);
624 if (op != 0x4)
625 {
626 /* This is not SPE2 insn.
627 * All SPE2 instructions have OP=4 and differs by XOP */
628 return NULL;
629 }
630 xop = SPE2_XOP (insn);
631 seg = SPE2_XOP_TO_SEG (xop);
632
633 /* Find the first match in the opcode table for this major opcode. */
634 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
635 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
636 opcode < opcode_end;
637 ++opcode)
638 {
0f873fd5
PB
639 uint64_t table_opcd = opcode->opcode;
640 uint64_t table_mask = opcode->mask;
641 uint64_t insn2;
74081948
AF
642 const unsigned char *opindex;
643 const struct powerpc_operand *operand;
644 int invalid;
645
646 insn2 = insn;
647 if ((insn2 & table_mask) != table_opcd)
648 continue;
649
650 /* Check validity of operands. */
651 invalid = 0;
652 for (opindex = opcode->operands; *opindex != 0; ++opindex)
653 {
654 operand = powerpc_operands + *opindex;
655 if (operand->extract)
656 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
657 }
658 if (invalid)
659 continue;
660
661 return opcode;
662 }
663
664 return NULL;
665}
666
252b5132
RH
667/* Print a PowerPC or POWER instruction. */
668
669static int
823bbe9d
AM
670print_insn_powerpc (bfd_vma memaddr,
671 struct disassemble_info *info,
672 int bigendian,
fa452fa6 673 ppc_cpu_t dialect)
252b5132
RH
674{
675 bfd_byte buffer[4];
676 int status;
0f873fd5 677 uint64_t insn;
252b5132 678 const struct powerpc_opcode *opcode;
b9c361e0 679 bfd_boolean insn_is_short;
252b5132
RH
680
681 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
682 if (status != 0)
683 {
b9c361e0
JL
684 /* The final instruction may be a 2-byte VLE insn. */
685 if ((dialect & PPC_OPCODE_VLE) != 0)
686 {
687 /* Clear buffer so unused bytes will not have garbage in them. */
688 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
689 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
690 if (status != 0)
691 {
692 (*info->memory_error_func) (status, memaddr, info);
693 return -1;
694 }
695 }
696 else
697 {
698 (*info->memory_error_func) (status, memaddr, info);
699 return -1;
700 }
252b5132
RH
701 }
702
703 if (bigendian)
704 insn = bfd_getb32 (buffer);
705 else
706 insn = bfd_getl32 (buffer);
707
b9c361e0
JL
708 /* Get the major opcode of the insn. */
709 opcode = NULL;
710 insn_is_short = FALSE;
711 if ((dialect & PPC_OPCODE_VLE) != 0)
712 {
713 opcode = lookup_vle (insn);
714 if (opcode != NULL)
715 insn_is_short = PPC_OP_SE_VLE(opcode->mask);
716 }
74081948
AF
717 if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
718 opcode = lookup_spe2 (insn);
b9c361e0 719 if (opcode == NULL)
52be03fd 720 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
d6688282 721 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
52be03fd 722 opcode = lookup_powerpc (insn, dialect);
252b5132 723
d6688282 724 if (opcode != NULL)
252b5132 725 {
252b5132
RH
726 const unsigned char *opindex;
727 const struct powerpc_operand *operand;
252b5132
RH
728 int need_comma;
729 int need_paren;
ea192fa3 730 int skip_optional;
252b5132 731
252b5132 732 if (opcode->operands[0] != 0)
fdd12ef3
AM
733 (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
734 else
735 (*info->fprintf_func) (info->stream, "%s", opcode->name);
252b5132 736
b9c361e0
JL
737 if (insn_is_short)
738 /* The operands will be fetched out of the 16-bit instruction. */
739 insn >>= 16;
740
252b5132
RH
741 /* Now extract and print the operands. */
742 need_comma = 0;
743 need_paren = 0;
ea192fa3 744 skip_optional = -1;
252b5132
RH
745 for (opindex = opcode->operands; *opindex != 0; opindex++)
746 {
0f873fd5 747 int64_t value;
252b5132
RH
748
749 operand = powerpc_operands + *opindex;
750
751 /* Operands that are marked FAKE are simply ignored. We
752 already made sure that the extract function considered
753 the instruction to be valid. */
754 if ((operand->flags & PPC_OPERAND_FAKE) != 0)
755 continue;
756
ea192fa3
PB
757 /* If all of the optional operands have the value zero,
758 then don't print any of them. */
65b650b4
AM
759 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
760 {
761 if (skip_optional < 0)
762 skip_optional = skip_optional_operands (opindex, insn,
763 dialect);
764 if (skip_optional)
765 continue;
766 }
252b5132 767
ea192fa3
PB
768 value = operand_value_powerpc (operand, insn, dialect);
769
252b5132
RH
770 if (need_comma)
771 {
772 (*info->fprintf_func) (info->stream, ",");
773 need_comma = 0;
774 }
775
776 /* Print the operand as directed by the flags. */
fdd12ef3
AM
777 if ((operand->flags & PPC_OPERAND_GPR) != 0
778 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
0f873fd5 779 (*info->fprintf_func) (info->stream, "r%" PPC_INT_FMT "d", value);
252b5132 780 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
0f873fd5 781 (*info->fprintf_func) (info->stream, "f%" PPC_INT_FMT "d", value);
786e2c0f 782 else if ((operand->flags & PPC_OPERAND_VR) != 0)
0f873fd5 783 (*info->fprintf_func) (info->stream, "v%" PPC_INT_FMT "d", value);
9b4e5766 784 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
0f873fd5 785 (*info->fprintf_func) (info->stream, "vs%" PPC_INT_FMT "d", value);
252b5132
RH
786 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
787 (*info->print_address_func) (memaddr + value, info);
788 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
789 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 790 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
0f873fd5 791 (*info->fprintf_func) (info->stream, "fsl%" PPC_INT_FMT "d", value);
081ba1b3 792 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
0f873fd5 793 (*info->fprintf_func) (info->stream, "fcr%" PPC_INT_FMT "d", value);
081ba1b3 794 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
0f873fd5 795 (*info->fprintf_func) (info->stream, "%" PPC_INT_FMT "d", value);
b9c361e0
JL
796 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
797 && (((dialect & PPC_OPCODE_PPC) != 0)
798 || ((dialect & PPC_OPCODE_VLE) != 0)))
0f873fd5 799 (*info->fprintf_func) (info->stream, "cr%" PPC_INT_FMT "d", value);
b9c361e0
JL
800 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
801 && (((dialect & PPC_OPCODE_PPC) != 0)
802 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 803 {
b9c361e0
JL
804 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
805 int cr;
806 int cc;
807
808 cr = value >> 2;
809 if (cr != 0)
810 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
811 cc = value & 3;
812 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 813 }
70dc4e32 814 else
0f873fd5 815 (*info->fprintf_func) (info->stream, "%" PPC_INT_FMT "d", value);
252b5132
RH
816
817 if (need_paren)
818 {
819 (*info->fprintf_func) (info->stream, ")");
820 need_paren = 0;
821 }
822
823 if ((operand->flags & PPC_OPERAND_PARENS) == 0)
824 need_comma = 1;
825 else
826 {
827 (*info->fprintf_func) (info->stream, "(");
828 need_paren = 1;
829 }
830 }
831
b9c361e0
JL
832 /* We have found and printed an instruction.
833 If it was a short VLE instruction we have more to do. */
834 if (insn_is_short)
835 {
836 memaddr += 2;
837 return 2;
838 }
839 else
840 /* Otherwise, return. */
841 return 4;
252b5132
RH
842 }
843
844 /* We could not find a match. */
0f873fd5 845 (*info->fprintf_func) (info->stream, ".long 0x%" PPC_INT_FMT "x", insn);
252b5132
RH
846
847 return 4;
848}
07dd56a9 849
65b48a81
PB
850const disasm_options_t *
851disassembler_options_powerpc (void)
852{
853 static disasm_options_t *opts = NULL;
854
855 if (opts == NULL)
856 {
857 size_t i, num_options = ARRAY_SIZE (ppc_opts);
858 opts = XNEW (disasm_options_t);
859 opts->name = XNEWVEC (const char *, num_options + 1);
860 for (i = 0; i < num_options; i++)
861 opts->name[i] = ppc_opts[i].opt;
862 /* The array we return must be NULL terminated. */
863 opts->name[i] = NULL;
864 opts->description = NULL;
865 }
866
867 return opts;
868}
869
07dd56a9 870void
823bbe9d 871print_ppc_disassembler_options (FILE *stream)
07dd56a9 872{
69fe9ce5
AM
873 unsigned int i, col;
874
875 fprintf (stream, _("\n\
07dd56a9 876The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
877the -M switch:\n"));
878
65b48a81 879 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
880 {
881 col += fprintf (stream, " %s,", ppc_opts[i].opt);
882 if (col > 66)
883 {
884 fprintf (stream, "\n");
885 col = 0;
886 }
887 }
65b48a81 888 fprintf (stream, "\n");
07dd56a9 889}
This page took 0.956732 seconds and 4 git commands to generate.