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