sim/ppc: Fix linker error with -fno-common
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
b3adc24a 2 Copyright (C) 1994-2020 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;
6f0e0752 43};
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 },
7c1f4227
AM
188 { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
189 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
190 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
191 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
192 0 },
dd7efa79
PB
193 { "future", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
194 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
195 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
7c1f4227 196 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
dd7efa79 197 0 },
14b57c7c 198 { "ppc", PPC_OPCODE_PPC,
69fe9ce5 199 0 },
14b57c7c 200 { "ppc32", PPC_OPCODE_PPC,
69fe9ce5 201 0 },
65b48a81
PB
202 { "32", PPC_OPCODE_PPC,
203 0 },
14b57c7c 204 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
69fe9ce5 205 0 },
65b48a81
PB
206 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
207 0 },
14b57c7c 208 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
69fe9ce5 209 0 },
14b57c7c 210 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
69fe9ce5 211 0 },
14b57c7c 212 { "pwr", PPC_OPCODE_POWER,
69fe9ce5 213 0 },
14b57c7c 214 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
cdc51b07 215 0 },
14b57c7c 216 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
cdc51b07 217 0 },
bdc70b4a
AM
218 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
219 | PPC_OPCODE_POWER5),
cdc51b07 220 0 },
bdc70b4a
AM
221 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
222 | PPC_OPCODE_POWER5),
cdc51b07 223 0 },
bdc70b4a
AM
224 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
225 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
cdc51b07 226 0 },
bdc70b4a
AM
227 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
228 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
229 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
69fe9ce5 230 0 },
5817ffd1
PB
231 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
232 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
ef85eab0 233 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
9a85b496 234 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
5817ffd1 235 0 },
a680de9a
PB
236 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
237 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
238 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
ef85eab0 239 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
a680de9a 240 0 },
1424c35d
AM
241 { "pwr10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
242 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
243 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
244 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
245 0 },
14b57c7c 246 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
69fe9ce5 247 0 },
52be03fd
AM
248 { "raw", PPC_OPCODE_PPC,
249 PPC_OPCODE_RAW },
14b57c7c 250 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
69fe9ce5 251 PPC_OPCODE_SPE },
74081948
AF
252 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
253 PPC_OPCODE_SPE2 },
bdc70b4a
AM
254 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
255 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
ce3d2015 256 0 },
14b57c7c
AM
257 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
258 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
259 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
74081948 260 | PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
b9c361e0 261 PPC_OPCODE_VLE },
14b57c7c 262 { "vsx", PPC_OPCODE_PPC,
4b8b687e 263 PPC_OPCODE_VSX },
69fe9ce5
AM
264};
265
b9c361e0
JL
266/* Switch between Booke and VLE dialects for interlinked dumps. */
267static ppc_cpu_t
268get_powerpc_dialect (struct disassemble_info *info)
269{
270 ppc_cpu_t dialect = 0;
271
6f0e0752
AM
272 if (info->private_data)
273 dialect = POWERPC_DIALECT (info);
b9c361e0
JL
274
275 /* Disassemble according to the section headers flags for VLE-mode. */
276 if (dialect & PPC_OPCODE_VLE
3a2488dd 277 && info->section != NULL && info->section->owner != NULL
94caa966
AM
278 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
279 && elf_object_id (info->section->owner) == PPC32_ELF_DATA
280 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
b9c361e0
JL
281 return dialect;
282 else
283 return dialect & ~ PPC_OPCODE_VLE;
284}
285
69fe9ce5
AM
286/* Handle -m and -M options that set cpu type, and .machine arg. */
287
288ppc_cpu_t
776fc418 289ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
69fe9ce5 290{
69fe9ce5
AM
291 unsigned int i;
292
65b48a81
PB
293 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
294 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
69fe9ce5
AM
295 {
296 if (ppc_opts[i].sticky)
297 {
776fc418
AM
298 *sticky |= ppc_opts[i].sticky;
299 if ((ppc_cpu & ~*sticky) != 0)
69fe9ce5
AM
300 break;
301 }
302 ppc_cpu = ppc_opts[i].cpu;
303 break;
304 }
65b48a81 305 if (i >= ARRAY_SIZE (ppc_opts))
69fe9ce5
AM
306 return 0;
307
776fc418 308 ppc_cpu |= *sticky;
69fe9ce5
AM
309 return ppc_cpu;
310}
311
312/* Determine which set of machines to disassemble for. */
418c1742 313
b240011a 314static void
fa452fa6 315powerpc_init_dialect (struct disassemble_info *info)
418c1742 316{
69fe9ce5 317 ppc_cpu_t dialect = 0;
776fc418 318 ppc_cpu_t sticky = 0;
fa452fa6
PB
319 struct dis_private *priv = calloc (sizeof (*priv), 1);
320
321 if (priv == NULL)
6f0e0752 322 return;
418c1742 323
776fc418
AM
324 switch (info->mach)
325 {
326 case bfd_mach_ppc_403:
327 case bfd_mach_ppc_403gc:
4f6ffcd3 328 dialect = ppc_parse_cpu (dialect, &sticky, "403");
776fc418
AM
329 break;
330 case bfd_mach_ppc_405:
4f6ffcd3 331 dialect = ppc_parse_cpu (dialect, &sticky, "405");
776fc418
AM
332 break;
333 case bfd_mach_ppc_601:
4f6ffcd3 334 dialect = ppc_parse_cpu (dialect, &sticky, "601");
776fc418 335 break;
fa758a70
AC
336 case bfd_mach_ppc_750:
337 dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
338 break;
776fc418
AM
339 case bfd_mach_ppc_a35:
340 case bfd_mach_ppc_rs64ii:
341 case bfd_mach_ppc_rs64iii:
4f6ffcd3 342 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
776fc418
AM
343 break;
344 case bfd_mach_ppc_e500:
4f6ffcd3 345 dialect = ppc_parse_cpu (dialect, &sticky, "e500");
776fc418
AM
346 break;
347 case bfd_mach_ppc_e500mc:
4f6ffcd3 348 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
776fc418
AM
349 break;
350 case bfd_mach_ppc_e500mc64:
4f6ffcd3 351 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
776fc418
AM
352 break;
353 case bfd_mach_ppc_e5500:
4f6ffcd3 354 dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
776fc418
AM
355 break;
356 case bfd_mach_ppc_e6500:
4f6ffcd3 357 dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
776fc418
AM
358 break;
359 case bfd_mach_ppc_titan:
4f6ffcd3 360 dialect = ppc_parse_cpu (dialect, &sticky, "titan");
776fc418
AM
361 break;
362 case bfd_mach_ppc_vle:
4f6ffcd3 363 dialect = ppc_parse_cpu (dialect, &sticky, "vle");
776fc418
AM
364 break;
365 default:
52fe4420 366 if (info->arch == bfd_arch_powerpc)
6bbb0c05 367 dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
52fe4420
AM
368 else
369 dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
65b48a81 370 break;
776fc418
AM
371 }
372
f995bbe8 373 const char *opt;
65b48a81 374 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
69fe9ce5
AM
375 {
376 ppc_cpu_t new_cpu = 0;
9b4e5766 377
65b48a81 378 if (disassembler_options_cmp (opt, "32") == 0)
7102e95e 379 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
65b48a81 380 else if (disassembler_options_cmp (opt, "64") == 0)
bdc70b4a 381 dialect |= PPC_OPCODE_64;
65b48a81
PB
382 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
383 dialect = new_cpu;
69fe9ce5 384 else
a6743a54
AM
385 /* xgettext: c-format */
386 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
69fe9ce5 387 }
661bd698 388
fa452fa6
PB
389 info->private_data = priv;
390 POWERPC_DIALECT(info) = dialect;
b240011a
AM
391}
392
f413a913
AM
393#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
394static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
dd7efa79 395#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
4f6d070a 396static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
f413a913
AM
397#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
398static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
399#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
400static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
b240011a
AM
401
402/* Calculate opcode table indices to speed up disassembly,
403 and init dialect. */
404
405void
406disassemble_init_powerpc (struct disassemble_info *info)
407{
27c49e9a 408 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 409 {
2ceb7719 410 unsigned seg, idx, op;
27c49e9a 411
2ceb7719
PB
412 /* PPC opcodes */
413 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 414 {
2ceb7719
PB
415 powerpc_opcd_indices[seg] = idx;
416 for (; idx < powerpc_num_opcodes; idx++)
417 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
418 break;
0f873fd5 419 }
27c49e9a 420
dd7efa79
PB
421 /* 64-bit prefix opcodes */
422 for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
423 {
424 prefix_opcd_indices[seg] = idx;
425 for (; idx < prefix_num_opcodes; idx++)
426 if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
427 break;
428 }
429
2ceb7719
PB
430 /* VLE opcodes */
431 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 432 {
2ceb7719
PB
433 vle_opcd_indices[seg] = idx;
434 for (; idx < vle_num_opcodes; idx++)
435 {
436 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
437 if (seg < VLE_OP_TO_SEG (op))
438 break;
439 }
0f873fd5 440 }
27c49e9a 441
2ceb7719
PB
442 /* SPE2 opcodes */
443 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 444 {
2ceb7719
PB
445 spe2_opcd_indices[seg] = idx;
446 for (; idx < spe2_num_opcodes; idx++)
447 {
448 op = SPE2_XOP (spe2_opcodes[idx].opcode);
449 if (seg < SPE2_XOP_TO_SEG (op))
450 break;
451 }
0f873fd5 452 }
b9c361e0
JL
453 }
454
52fe4420 455 powerpc_init_dialect (info);
418c1742
MG
456}
457
458/* Print a big endian PowerPC instruction. */
252b5132
RH
459
460int
823bbe9d 461print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 462{
b9c361e0 463 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
464}
465
418c1742 466/* Print a little endian PowerPC instruction. */
252b5132
RH
467
468int
823bbe9d 469print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 470{
b9c361e0 471 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
472}
473
ea192fa3
PB
474/* Extract the operand value from the PowerPC or POWER instruction. */
475
0f873fd5 476static int64_t
ea192fa3 477operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 478 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 479{
0f873fd5 480 int64_t value;
9cf7e568 481 int invalid = 0;
ea192fa3
PB
482 /* Extract the value from the instruction. */
483 if (operand->extract)
484 value = (*operand->extract) (insn, dialect, &invalid);
485 else
486 {
b9c361e0
JL
487 if (operand->shift >= 0)
488 value = (insn >> operand->shift) & operand->bitm;
489 else
490 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
491 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
492 {
493 /* BITM is always some number of zeros followed by some
b9c361e0 494 number of ones, followed by some number of zeros. */
0f873fd5 495 uint64_t top = operand->bitm;
ea192fa3
PB
496 /* top & -top gives the rightmost 1 bit, so this
497 fills in any trailing zeros. */
498 top |= (top & -top) - 1;
499 top &= ~(top >> 1);
500 value = (value ^ top) - top;
501 }
502 }
503
504 return value;
505}
506
507/* Determine whether the optional operand(s) should be printed. */
508
bda678b9 509static bfd_boolean
ea192fa3 510skip_optional_operands (const unsigned char *opindex,
0f873fd5 511 uint64_t insn, ppc_cpu_t dialect)
ea192fa3
PB
512{
513 const struct powerpc_operand *operand;
9cf7e568 514 int num_optional;
ea192fa3 515
9cf7e568 516 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
517 {
518 operand = &powerpc_operands[*opindex];
9cf7e568 519 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
bda678b9 520 return FALSE;
9cf7e568
AM
521 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
522 {
523 /* Negative count is used as a flag to extract function. */
524 --num_optional;
525 if (operand_value_powerpc (operand, insn, dialect)
526 != ppc_optional_operand_value (operand, insn, dialect,
527 num_optional))
bda678b9 528 return FALSE;
9cf7e568 529 }
ea192fa3
PB
530 }
531
bda678b9 532 return TRUE;
ea192fa3
PB
533}
534
52be03fd 535/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 536
d6688282 537static const struct powerpc_opcode *
0f873fd5 538lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 539{
52be03fd 540 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
541 unsigned long op;
542
543 /* Get the major opcode of the instruction. */
544 op = PPC_OP (insn);
545
546 /* Find the first match in the opcode table for this major opcode. */
547 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 548 last = NULL;
d6688282
AM
549 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
550 opcode < opcode_end;
551 ++opcode)
552 {
553 const unsigned char *opindex;
554 const struct powerpc_operand *operand;
555 int invalid;
556
557 if ((insn & opcode->mask) != opcode->opcode
52be03fd 558 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
559 && ((opcode->flags & dialect) == 0
560 || (opcode->deprecated & dialect) != 0)))
561 continue;
562
563 /* Check validity of operands. */
564 invalid = 0;
565 for (opindex = opcode->operands; *opindex != 0; opindex++)
566 {
567 operand = powerpc_operands + *opindex;
568 if (operand->extract)
569 (*operand->extract) (insn, dialect, &invalid);
570 }
571 if (invalid)
572 continue;
573
52be03fd
AM
574 if ((dialect & PPC_OPCODE_RAW) == 0)
575 return opcode;
576
577 /* The raw machine insn is one that is not a specialization. */
578 if (last == NULL
579 || (last->mask & ~opcode->mask) != 0)
580 last = opcode;
d6688282
AM
581 }
582
52be03fd 583 return last;
d6688282
AM
584}
585
dd7efa79
PB
586/* Find a match for INSN in the PREFIX opcode table. */
587
588static const struct powerpc_opcode *
589lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
590{
591 const struct powerpc_opcode *opcode, *opcode_end, *last;
592 unsigned long seg;
593
594 /* Get the opcode segment of the instruction. */
595 seg = PPC_PREFIX_SEG (insn);
596
597 /* Find the first match in the opcode table for this major opcode. */
598 opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
599 last = NULL;
600 for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
601 opcode < opcode_end;
602 ++opcode)
603 {
604 const unsigned char *opindex;
605 const struct powerpc_operand *operand;
606 int invalid;
607
608 if ((insn & opcode->mask) != opcode->opcode
609 || ((dialect & PPC_OPCODE_ANY) == 0
610 && ((opcode->flags & dialect) == 0
611 || (opcode->deprecated & dialect) != 0)))
612 continue;
613
614 /* Check validity of operands. */
615 invalid = 0;
616 for (opindex = opcode->operands; *opindex != 0; opindex++)
617 {
618 operand = powerpc_operands + *opindex;
619 if (operand->extract)
620 (*operand->extract) (insn, dialect, &invalid);
621 }
622 if (invalid)
623 continue;
624
625 if ((dialect & PPC_OPCODE_RAW) == 0)
626 return opcode;
627
628 /* The raw machine insn is one that is not a specialization. */
629 if (last == NULL
630 || (last->mask & ~opcode->mask) != 0)
631 last = opcode;
632 }
633
634 return last;
635}
636
b9c361e0
JL
637/* Find a match for INSN in the VLE opcode table. */
638
639static const struct powerpc_opcode *
0f873fd5 640lookup_vle (uint64_t insn)
b9c361e0
JL
641{
642 const struct powerpc_opcode *opcode;
643 const struct powerpc_opcode *opcode_end;
644 unsigned op, seg;
645
646 op = PPC_OP (insn);
647 if (op >= 0x20 && op <= 0x37)
648 {
649 /* This insn has a 4-bit opcode. */
650 op &= 0x3c;
651 }
652 seg = VLE_OP_TO_SEG (op);
653
654 /* Find the first match in the opcode table for this major opcode. */
655 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
656 for (opcode = vle_opcodes + vle_opcd_indices[seg];
657 opcode < opcode_end;
658 ++opcode)
659 {
0f873fd5
PB
660 uint64_t table_opcd = opcode->opcode;
661 uint64_t table_mask = opcode->mask;
b9c361e0 662 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 663 uint64_t insn2;
b9c361e0
JL
664 const unsigned char *opindex;
665 const struct powerpc_operand *operand;
666 int invalid;
667
668 insn2 = insn;
669 if (table_op_is_short)
670 insn2 >>= 16;
671 if ((insn2 & table_mask) != table_opcd)
672 continue;
673
674 /* Check validity of operands. */
675 invalid = 0;
676 for (opindex = opcode->operands; *opindex != 0; ++opindex)
677 {
678 operand = powerpc_operands + *opindex;
679 if (operand->extract)
680 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
681 }
682 if (invalid)
683 continue;
684
685 return opcode;
686 }
687
688 return NULL;
689}
690
74081948
AF
691/* Find a match for INSN in the SPE2 opcode table. */
692
693static const struct powerpc_opcode *
0f873fd5 694lookup_spe2 (uint64_t insn)
74081948
AF
695{
696 const struct powerpc_opcode *opcode, *opcode_end;
697 unsigned op, xop, seg;
698
699 op = PPC_OP (insn);
700 if (op != 0x4)
701 {
702 /* This is not SPE2 insn.
703 * All SPE2 instructions have OP=4 and differs by XOP */
704 return NULL;
705 }
706 xop = SPE2_XOP (insn);
707 seg = SPE2_XOP_TO_SEG (xop);
708
709 /* Find the first match in the opcode table for this major opcode. */
710 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
711 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
712 opcode < opcode_end;
713 ++opcode)
714 {
0f873fd5
PB
715 uint64_t table_opcd = opcode->opcode;
716 uint64_t table_mask = opcode->mask;
717 uint64_t insn2;
74081948
AF
718 const unsigned char *opindex;
719 const struct powerpc_operand *operand;
720 int invalid;
721
722 insn2 = insn;
723 if ((insn2 & table_mask) != table_opcd)
724 continue;
725
726 /* Check validity of operands. */
727 invalid = 0;
728 for (opindex = opcode->operands; *opindex != 0; ++opindex)
729 {
730 operand = powerpc_operands + *opindex;
731 if (operand->extract)
732 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
733 }
734 if (invalid)
735 continue;
736
737 return opcode;
738 }
739
740 return NULL;
741}
742
252b5132
RH
743/* Print a PowerPC or POWER instruction. */
744
745static int
823bbe9d
AM
746print_insn_powerpc (bfd_vma memaddr,
747 struct disassemble_info *info,
748 int bigendian,
fa452fa6 749 ppc_cpu_t dialect)
252b5132
RH
750{
751 bfd_byte buffer[4];
752 int status;
0f873fd5 753 uint64_t insn;
252b5132 754 const struct powerpc_opcode *opcode;
a87a6478 755 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
756
757 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
758
759 /* The final instruction may be a 2-byte VLE insn. */
760 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
761 {
762 /* Clear buffer so unused bytes will not have garbage in them. */
833d919c 763 buffer[2] = buffer[3] = 0;
a87a6478 764 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
833d919c 765 insn_length = 2;
a87a6478
PB
766 }
767
252b5132
RH
768 if (status != 0)
769 {
a87a6478
PB
770 (*info->memory_error_func) (status, memaddr, info);
771 return -1;
252b5132
RH
772 }
773
774 if (bigendian)
775 insn = bfd_getb32 (buffer);
776 else
777 insn = bfd_getl32 (buffer);
778
b9c361e0
JL
779 /* Get the major opcode of the insn. */
780 opcode = NULL;
7c1f4227 781 if ((dialect & PPC_OPCODE_POWER10) != 0
dd7efa79
PB
782 && PPC_OP (insn) == 0x1)
783 {
784 uint64_t temp_insn, suffix;
785 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
786 if (status == 0)
787 {
788 if (bigendian)
789 suffix = bfd_getb32 (buffer);
790 else
791 suffix = bfd_getl32 (buffer);
792 temp_insn = (insn << 32) | suffix;
793 opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
794 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
795 opcode = lookup_prefix (temp_insn, dialect);
796 if (opcode != NULL)
797 {
798 insn = temp_insn;
799 insn_length = 8;
800 if ((info->flags & WIDE_OUTPUT) != 0)
801 info->bytes_per_line = 8;
802 }
803 }
804 }
805 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
b9c361e0
JL
806 {
807 opcode = lookup_vle (insn);
a87a6478
PB
808 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
809 {
810 /* The operands will be fetched out of the 16-bit instruction. */
811 insn >>= 16;
812 insn_length = 2;
813 }
b9c361e0 814 }
833d919c
AM
815 if (opcode == NULL && insn_length == 4)
816 {
817 if ((dialect & PPC_OPCODE_SPE2) != 0)
818 opcode = lookup_spe2 (insn);
819 if (opcode == NULL)
820 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
821 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
822 opcode = lookup_powerpc (insn, dialect);
823 }
252b5132 824
d6688282 825 if (opcode != NULL)
252b5132 826 {
252b5132
RH
827 const unsigned char *opindex;
828 const struct powerpc_operand *operand;
e392bad3
AM
829 enum {
830 need_comma = 0,
831 need_1space = 1,
832 need_2spaces = 2,
833 need_3spaces = 3,
834 need_4spaces = 4,
835 need_5spaces = 5,
836 need_6spaces = 6,
837 need_7spaces = 7,
838 need_paren
839 } op_separator;
bda678b9 840 bfd_boolean skip_optional;
0e62b37a 841 int blanks;
252b5132 842
c2b1c275
AM
843 (*info->fprintf_func) (info->stream, "%s", opcode->name);
844 /* gdb fprintf_func doesn't return count printed. */
0e62b37a
JB
845 blanks = 8 - strlen (opcode->name);
846 if (blanks <= 0)
847 blanks = 1;
252b5132
RH
848
849 /* Now extract and print the operands. */
0e62b37a 850 op_separator = blanks;
bda678b9 851 skip_optional = FALSE;
252b5132
RH
852 for (opindex = opcode->operands; *opindex != 0; opindex++)
853 {
0f873fd5 854 int64_t value;
252b5132
RH
855
856 operand = powerpc_operands + *opindex;
857
0067be51
AM
858 /* If all of the optional operands past this one have their
859 default value, then don't print any of them. Except in
860 raw mode, print them all. */
861 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
862 && (dialect & PPC_OPCODE_RAW) == 0)
65b650b4 863 {
bda678b9
PB
864 if (!skip_optional)
865 skip_optional = skip_optional_operands (opindex, insn, dialect);
65b650b4
AM
866 if (skip_optional)
867 continue;
868 }
252b5132 869
ea192fa3
PB
870 value = operand_value_powerpc (operand, insn, dialect);
871
e392bad3
AM
872 if (op_separator == need_comma)
873 (*info->fprintf_func) (info->stream, ",");
874 else if (op_separator == need_paren)
875 (*info->fprintf_func) (info->stream, "(");
876 else
877 (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
252b5132
RH
878
879 /* Print the operand as directed by the flags. */
fdd12ef3
AM
880 if ((operand->flags & PPC_OPERAND_GPR) != 0
881 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 882 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 883 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 884 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 885 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 886 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 887 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 888 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
aa3c112f
AM
889 else if ((operand->flags & PPC_OPERAND_ACC) != 0)
890 (*info->fprintf_func) (info->stream, "a%" PRId64, value);
252b5132
RH
891 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
892 (*info->print_address_func) (memaddr + value, info);
893 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
894 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 895 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 896 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 897 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 898 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 899 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 900 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 901 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 902 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
903 && (((dialect & PPC_OPCODE_PPC) != 0)
904 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 905 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
906 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
907 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
908 && (((dialect & PPC_OPCODE_PPC) != 0)
909 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 910 {
b9c361e0
JL
911 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
912 int cr;
913 int cc;
914
915 cr = value >> 2;
916 if (cr != 0)
917 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
918 cc = value & 3;
919 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 920 }
70dc4e32 921 else
d1a3c973 922 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 923
e392bad3
AM
924 if (op_separator == need_paren)
925 (*info->fprintf_func) (info->stream, ")");
252b5132 926
e392bad3
AM
927 op_separator = need_comma;
928 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
929 op_separator = need_paren;
252b5132
RH
930 }
931
a87a6478
PB
932 /* We have found and printed an instruction. */
933 return insn_length;
252b5132
RH
934 }
935
936 /* We could not find a match. */
833d919c
AM
937 if (insn_length == 4)
938 (*info->fprintf_func) (info->stream, ".long 0x%x",
939 (unsigned int) insn);
940 else
941 (*info->fprintf_func) (info->stream, ".word 0x%x",
942 (unsigned int) insn >> 16);
943 return insn_length;
252b5132 944}
07dd56a9 945
471b9d15 946const disasm_options_and_args_t *
65b48a81
PB
947disassembler_options_powerpc (void)
948{
471b9d15 949 static disasm_options_and_args_t *opts_and_args;
65b48a81 950
471b9d15 951 if (opts_and_args == NULL)
65b48a81
PB
952 {
953 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
954 disasm_options_t *opts;
955
956 opts_and_args = XNEW (disasm_options_and_args_t);
957 opts_and_args->args = NULL;
958
959 opts = &opts_and_args->options;
65b48a81 960 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
961 opts->description = NULL;
962 opts->arg = NULL;
65b48a81
PB
963 for (i = 0; i < num_options; i++)
964 opts->name[i] = ppc_opts[i].opt;
965 /* The array we return must be NULL terminated. */
966 opts->name[i] = NULL;
65b48a81
PB
967 }
968
471b9d15 969 return opts_and_args;
65b48a81
PB
970}
971
07dd56a9 972void
823bbe9d 973print_ppc_disassembler_options (FILE *stream)
07dd56a9 974{
69fe9ce5
AM
975 unsigned int i, col;
976
977 fprintf (stream, _("\n\
07dd56a9 978The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
979the -M switch:\n"));
980
65b48a81 981 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
982 {
983 col += fprintf (stream, " %s,", ppc_opts[i].opt);
984 if (col > 66)
985 {
986 fprintf (stream, "\n");
987 col = 0;
988 }
989 }
65b48a81 990 fprintf (stream, "\n");
07dd56a9 991}
This page took 1.634028 seconds and 4 git commands to generate.