]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ppc-dis.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / opcodes / ppc-dis.c
CommitLineData
252b5132 1/* ppc-dis.c -- Disassemble PowerPC instructions
250d07de 2 Copyright (C) 1994-2021 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 401
7ad57880
NC
402static bfd_boolean
403ppc_symbol_is_valid (asymbol *sym,
404 struct disassemble_info *info ATTRIBUTE_UNUSED)
405{
406 elf_symbol_type * est;
407
408 if (sym == NULL)
409 return FALSE;
410
c1229f84 411 est = elf_symbol_from (sym);
7ad57880
NC
412
413 /* Ignore ELF hidden, local, no-type symbols.
414 These are generated by annobin. */
415 if (est != NULL
416 && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN
417 && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL
418 && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE)
419 return FALSE;
420
421 return TRUE;
422}
423
b240011a
AM
424/* Calculate opcode table indices to speed up disassembly,
425 and init dialect. */
426
427void
428disassemble_init_powerpc (struct disassemble_info *info)
429{
7ad57880
NC
430 info->symbol_is_valid = ppc_symbol_is_valid;
431
27c49e9a 432 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
b240011a 433 {
2ceb7719 434 unsigned seg, idx, op;
27c49e9a 435
2ceb7719
PB
436 /* PPC opcodes */
437 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
0f873fd5 438 {
2ceb7719
PB
439 powerpc_opcd_indices[seg] = idx;
440 for (; idx < powerpc_num_opcodes; idx++)
441 if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
442 break;
0f873fd5 443 }
27c49e9a 444
dd7efa79
PB
445 /* 64-bit prefix opcodes */
446 for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
447 {
448 prefix_opcd_indices[seg] = idx;
449 for (; idx < prefix_num_opcodes; idx++)
450 if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
451 break;
452 }
453
2ceb7719
PB
454 /* VLE opcodes */
455 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
0f873fd5 456 {
2ceb7719
PB
457 vle_opcd_indices[seg] = idx;
458 for (; idx < vle_num_opcodes; idx++)
459 {
460 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
461 if (seg < VLE_OP_TO_SEG (op))
462 break;
463 }
0f873fd5 464 }
27c49e9a 465
2ceb7719
PB
466 /* SPE2 opcodes */
467 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
0f873fd5 468 {
2ceb7719
PB
469 spe2_opcd_indices[seg] = idx;
470 for (; idx < spe2_num_opcodes; idx++)
471 {
472 op = SPE2_XOP (spe2_opcodes[idx].opcode);
473 if (seg < SPE2_XOP_TO_SEG (op))
474 break;
475 }
0f873fd5 476 }
b9c361e0
JL
477 }
478
52fe4420 479 powerpc_init_dialect (info);
418c1742
MG
480}
481
482/* Print a big endian PowerPC instruction. */
252b5132
RH
483
484int
823bbe9d 485print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 486{
b9c361e0 487 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
252b5132
RH
488}
489
418c1742 490/* Print a little endian PowerPC instruction. */
252b5132
RH
491
492int
823bbe9d 493print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
252b5132 494{
b9c361e0 495 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
252b5132
RH
496}
497
ea192fa3
PB
498/* Extract the operand value from the PowerPC or POWER instruction. */
499
0f873fd5 500static int64_t
ea192fa3 501operand_value_powerpc (const struct powerpc_operand *operand,
0f873fd5 502 uint64_t insn, ppc_cpu_t dialect)
ea192fa3 503{
0f873fd5 504 int64_t value;
9cf7e568 505 int invalid = 0;
ea192fa3
PB
506 /* Extract the value from the instruction. */
507 if (operand->extract)
508 value = (*operand->extract) (insn, dialect, &invalid);
509 else
510 {
b9c361e0
JL
511 if (operand->shift >= 0)
512 value = (insn >> operand->shift) & operand->bitm;
513 else
514 value = (insn << -operand->shift) & operand->bitm;
ea192fa3
PB
515 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
516 {
517 /* BITM is always some number of zeros followed by some
b9c361e0 518 number of ones, followed by some number of zeros. */
0f873fd5 519 uint64_t top = operand->bitm;
ea192fa3
PB
520 /* top & -top gives the rightmost 1 bit, so this
521 fills in any trailing zeros. */
522 top |= (top & -top) - 1;
523 top &= ~(top >> 1);
524 value = (value ^ top) - top;
525 }
526 }
527
528 return value;
529}
530
531/* Determine whether the optional operand(s) should be printed. */
532
bda678b9 533static bfd_boolean
ea192fa3 534skip_optional_operands (const unsigned char *opindex,
0f873fd5 535 uint64_t insn, ppc_cpu_t dialect)
ea192fa3
PB
536{
537 const struct powerpc_operand *operand;
9cf7e568 538 int num_optional;
ea192fa3 539
9cf7e568 540 for (num_optional = 0; *opindex != 0; opindex++)
ea192fa3
PB
541 {
542 operand = &powerpc_operands[*opindex];
9cf7e568 543 if ((operand->flags & PPC_OPERAND_NEXT) != 0)
bda678b9 544 return FALSE;
9cf7e568
AM
545 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
546 {
547 /* Negative count is used as a flag to extract function. */
548 --num_optional;
549 if (operand_value_powerpc (operand, insn, dialect)
550 != ppc_optional_operand_value (operand, insn, dialect,
551 num_optional))
bda678b9 552 return FALSE;
9cf7e568 553 }
ea192fa3
PB
554 }
555
bda678b9 556 return TRUE;
ea192fa3
PB
557}
558
52be03fd 559/* Find a match for INSN in the opcode table, given machine DIALECT. */
b9c361e0 560
d6688282 561static const struct powerpc_opcode *
0f873fd5 562lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
d6688282 563{
52be03fd 564 const struct powerpc_opcode *opcode, *opcode_end, *last;
d6688282
AM
565 unsigned long op;
566
567 /* Get the major opcode of the instruction. */
568 op = PPC_OP (insn);
569
570 /* Find the first match in the opcode table for this major opcode. */
571 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
52be03fd 572 last = NULL;
d6688282
AM
573 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
574 opcode < opcode_end;
575 ++opcode)
576 {
577 const unsigned char *opindex;
578 const struct powerpc_operand *operand;
579 int invalid;
580
581 if ((insn & opcode->mask) != opcode->opcode
52be03fd 582 || ((dialect & PPC_OPCODE_ANY) == 0
d6688282
AM
583 && ((opcode->flags & dialect) == 0
584 || (opcode->deprecated & dialect) != 0)))
585 continue;
586
587 /* Check validity of operands. */
588 invalid = 0;
589 for (opindex = opcode->operands; *opindex != 0; opindex++)
590 {
591 operand = powerpc_operands + *opindex;
592 if (operand->extract)
593 (*operand->extract) (insn, dialect, &invalid);
594 }
595 if (invalid)
596 continue;
597
52be03fd
AM
598 if ((dialect & PPC_OPCODE_RAW) == 0)
599 return opcode;
600
601 /* The raw machine insn is one that is not a specialization. */
602 if (last == NULL
603 || (last->mask & ~opcode->mask) != 0)
604 last = opcode;
d6688282
AM
605 }
606
52be03fd 607 return last;
d6688282
AM
608}
609
dd7efa79
PB
610/* Find a match for INSN in the PREFIX opcode table. */
611
612static const struct powerpc_opcode *
613lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
614{
615 const struct powerpc_opcode *opcode, *opcode_end, *last;
616 unsigned long seg;
617
618 /* Get the opcode segment of the instruction. */
619 seg = PPC_PREFIX_SEG (insn);
620
621 /* Find the first match in the opcode table for this major opcode. */
622 opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
623 last = NULL;
624 for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
625 opcode < opcode_end;
626 ++opcode)
627 {
628 const unsigned char *opindex;
629 const struct powerpc_operand *operand;
630 int invalid;
631
632 if ((insn & opcode->mask) != opcode->opcode
633 || ((dialect & PPC_OPCODE_ANY) == 0
634 && ((opcode->flags & dialect) == 0
635 || (opcode->deprecated & dialect) != 0)))
636 continue;
637
638 /* Check validity of operands. */
639 invalid = 0;
640 for (opindex = opcode->operands; *opindex != 0; opindex++)
641 {
642 operand = powerpc_operands + *opindex;
643 if (operand->extract)
644 (*operand->extract) (insn, dialect, &invalid);
645 }
646 if (invalid)
647 continue;
648
649 if ((dialect & PPC_OPCODE_RAW) == 0)
650 return opcode;
651
652 /* The raw machine insn is one that is not a specialization. */
653 if (last == NULL
654 || (last->mask & ~opcode->mask) != 0)
655 last = opcode;
656 }
657
658 return last;
659}
660
b9c361e0
JL
661/* Find a match for INSN in the VLE opcode table. */
662
663static const struct powerpc_opcode *
0f873fd5 664lookup_vle (uint64_t insn)
b9c361e0
JL
665{
666 const struct powerpc_opcode *opcode;
667 const struct powerpc_opcode *opcode_end;
668 unsigned op, seg;
669
670 op = PPC_OP (insn);
671 if (op >= 0x20 && op <= 0x37)
672 {
673 /* This insn has a 4-bit opcode. */
674 op &= 0x3c;
675 }
676 seg = VLE_OP_TO_SEG (op);
677
678 /* Find the first match in the opcode table for this major opcode. */
679 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
680 for (opcode = vle_opcodes + vle_opcd_indices[seg];
681 opcode < opcode_end;
682 ++opcode)
683 {
0f873fd5
PB
684 uint64_t table_opcd = opcode->opcode;
685 uint64_t table_mask = opcode->mask;
b9c361e0 686 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
0f873fd5 687 uint64_t insn2;
b9c361e0
JL
688 const unsigned char *opindex;
689 const struct powerpc_operand *operand;
690 int invalid;
691
692 insn2 = insn;
693 if (table_op_is_short)
694 insn2 >>= 16;
695 if ((insn2 & table_mask) != table_opcd)
696 continue;
697
698 /* Check validity of operands. */
699 invalid = 0;
700 for (opindex = opcode->operands; *opindex != 0; ++opindex)
701 {
702 operand = powerpc_operands + *opindex;
703 if (operand->extract)
704 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
705 }
706 if (invalid)
707 continue;
708
709 return opcode;
710 }
711
712 return NULL;
713}
714
74081948
AF
715/* Find a match for INSN in the SPE2 opcode table. */
716
717static const struct powerpc_opcode *
0f873fd5 718lookup_spe2 (uint64_t insn)
74081948
AF
719{
720 const struct powerpc_opcode *opcode, *opcode_end;
721 unsigned op, xop, seg;
722
723 op = PPC_OP (insn);
724 if (op != 0x4)
725 {
726 /* This is not SPE2 insn.
727 * All SPE2 instructions have OP=4 and differs by XOP */
728 return NULL;
729 }
730 xop = SPE2_XOP (insn);
731 seg = SPE2_XOP_TO_SEG (xop);
732
733 /* Find the first match in the opcode table for this major opcode. */
734 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
735 for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
736 opcode < opcode_end;
737 ++opcode)
738 {
0f873fd5
PB
739 uint64_t table_opcd = opcode->opcode;
740 uint64_t table_mask = opcode->mask;
741 uint64_t insn2;
74081948
AF
742 const unsigned char *opindex;
743 const struct powerpc_operand *operand;
744 int invalid;
745
746 insn2 = insn;
747 if ((insn2 & table_mask) != table_opcd)
748 continue;
749
750 /* Check validity of operands. */
751 invalid = 0;
752 for (opindex = opcode->operands; *opindex != 0; ++opindex)
753 {
754 operand = powerpc_operands + *opindex;
755 if (operand->extract)
756 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
757 }
758 if (invalid)
759 continue;
760
761 return opcode;
762 }
763
764 return NULL;
765}
766
252b5132
RH
767/* Print a PowerPC or POWER instruction. */
768
769static int
823bbe9d
AM
770print_insn_powerpc (bfd_vma memaddr,
771 struct disassemble_info *info,
772 int bigendian,
fa452fa6 773 ppc_cpu_t dialect)
252b5132
RH
774{
775 bfd_byte buffer[4];
776 int status;
0f873fd5 777 uint64_t insn;
252b5132 778 const struct powerpc_opcode *opcode;
a87a6478 779 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
252b5132
RH
780
781 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
a87a6478
PB
782
783 /* The final instruction may be a 2-byte VLE insn. */
784 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
785 {
786 /* Clear buffer so unused bytes will not have garbage in them. */
833d919c 787 buffer[2] = buffer[3] = 0;
a87a6478 788 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
833d919c 789 insn_length = 2;
a87a6478
PB
790 }
791
252b5132
RH
792 if (status != 0)
793 {
a87a6478
PB
794 (*info->memory_error_func) (status, memaddr, info);
795 return -1;
252b5132
RH
796 }
797
798 if (bigendian)
799 insn = bfd_getb32 (buffer);
800 else
801 insn = bfd_getl32 (buffer);
802
b9c361e0
JL
803 /* Get the major opcode of the insn. */
804 opcode = NULL;
7c1f4227 805 if ((dialect & PPC_OPCODE_POWER10) != 0
dd7efa79
PB
806 && PPC_OP (insn) == 0x1)
807 {
808 uint64_t temp_insn, suffix;
809 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
810 if (status == 0)
811 {
812 if (bigendian)
813 suffix = bfd_getb32 (buffer);
814 else
815 suffix = bfd_getl32 (buffer);
816 temp_insn = (insn << 32) | suffix;
817 opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
818 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
819 opcode = lookup_prefix (temp_insn, dialect);
820 if (opcode != NULL)
821 {
822 insn = temp_insn;
823 insn_length = 8;
824 if ((info->flags & WIDE_OUTPUT) != 0)
825 info->bytes_per_line = 8;
826 }
827 }
828 }
829 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
b9c361e0
JL
830 {
831 opcode = lookup_vle (insn);
a87a6478
PB
832 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
833 {
834 /* The operands will be fetched out of the 16-bit instruction. */
835 insn >>= 16;
836 insn_length = 2;
837 }
b9c361e0 838 }
833d919c
AM
839 if (opcode == NULL && insn_length == 4)
840 {
841 if ((dialect & PPC_OPCODE_SPE2) != 0)
842 opcode = lookup_spe2 (insn);
843 if (opcode == NULL)
844 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
845 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
846 opcode = lookup_powerpc (insn, dialect);
847 }
252b5132 848
d6688282 849 if (opcode != NULL)
252b5132 850 {
252b5132
RH
851 const unsigned char *opindex;
852 const struct powerpc_operand *operand;
e392bad3
AM
853 enum {
854 need_comma = 0,
855 need_1space = 1,
856 need_2spaces = 2,
857 need_3spaces = 3,
858 need_4spaces = 4,
859 need_5spaces = 5,
860 need_6spaces = 6,
861 need_7spaces = 7,
862 need_paren
863 } op_separator;
bda678b9 864 bfd_boolean skip_optional;
0e62b37a 865 int blanks;
252b5132 866
c2b1c275
AM
867 (*info->fprintf_func) (info->stream, "%s", opcode->name);
868 /* gdb fprintf_func doesn't return count printed. */
0e62b37a
JB
869 blanks = 8 - strlen (opcode->name);
870 if (blanks <= 0)
871 blanks = 1;
252b5132
RH
872
873 /* Now extract and print the operands. */
0e62b37a 874 op_separator = blanks;
bda678b9 875 skip_optional = FALSE;
252b5132
RH
876 for (opindex = opcode->operands; *opindex != 0; opindex++)
877 {
0f873fd5 878 int64_t value;
252b5132
RH
879
880 operand = powerpc_operands + *opindex;
881
0067be51
AM
882 /* If all of the optional operands past this one have their
883 default value, then don't print any of them. Except in
884 raw mode, print them all. */
885 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
886 && (dialect & PPC_OPCODE_RAW) == 0)
65b650b4 887 {
bda678b9
PB
888 if (!skip_optional)
889 skip_optional = skip_optional_operands (opindex, insn, dialect);
65b650b4
AM
890 if (skip_optional)
891 continue;
892 }
252b5132 893
ea192fa3
PB
894 value = operand_value_powerpc (operand, insn, dialect);
895
e392bad3
AM
896 if (op_separator == need_comma)
897 (*info->fprintf_func) (info->stream, ",");
898 else if (op_separator == need_paren)
899 (*info->fprintf_func) (info->stream, "(");
900 else
901 (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
252b5132
RH
902
903 /* Print the operand as directed by the flags. */
fdd12ef3
AM
904 if ((operand->flags & PPC_OPERAND_GPR) != 0
905 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
d1a3c973 906 (*info->fprintf_func) (info->stream, "r%" PRId64, value);
252b5132 907 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
d1a3c973 908 (*info->fprintf_func) (info->stream, "f%" PRId64, value);
786e2c0f 909 else if ((operand->flags & PPC_OPERAND_VR) != 0)
d1a3c973 910 (*info->fprintf_func) (info->stream, "v%" PRId64, value);
9b4e5766 911 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
d1a3c973 912 (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
aa3c112f
AM
913 else if ((operand->flags & PPC_OPERAND_ACC) != 0)
914 (*info->fprintf_func) (info->stream, "a%" PRId64, value);
252b5132
RH
915 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
916 (*info->print_address_func) (memaddr + value, info);
917 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
918 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
43e65147 919 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
d1a3c973 920 (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
081ba1b3 921 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
d1a3c973 922 (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
081ba1b3 923 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
d1a3c973 924 (*info->fprintf_func) (info->stream, "%" PRId64, value);
b9c361e0 925 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
96a86c01 926 && (operand->flags & PPC_OPERAND_CR_BIT) == 0
b9c361e0
JL
927 && (((dialect & PPC_OPCODE_PPC) != 0)
928 || ((dialect & PPC_OPCODE_VLE) != 0)))
d1a3c973 929 (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
96a86c01
AM
930 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
931 && (operand->flags & PPC_OPERAND_CR_REG) == 0
b9c361e0
JL
932 && (((dialect & PPC_OPCODE_PPC) != 0)
933 || ((dialect & PPC_OPCODE_VLE) != 0)))
252b5132 934 {
b9c361e0
JL
935 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
936 int cr;
937 int cc;
938
939 cr = value >> 2;
940 if (cr != 0)
941 (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
942 cc = value & 3;
943 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
252b5132 944 }
70dc4e32 945 else
d1a3c973 946 (*info->fprintf_func) (info->stream, "%" PRId64, value);
252b5132 947
e392bad3
AM
948 if (op_separator == need_paren)
949 (*info->fprintf_func) (info->stream, ")");
252b5132 950
e392bad3
AM
951 op_separator = need_comma;
952 if ((operand->flags & PPC_OPERAND_PARENS) != 0)
953 op_separator = need_paren;
252b5132
RH
954 }
955
a87a6478
PB
956 /* We have found and printed an instruction. */
957 return insn_length;
252b5132
RH
958 }
959
960 /* We could not find a match. */
833d919c
AM
961 if (insn_length == 4)
962 (*info->fprintf_func) (info->stream, ".long 0x%x",
963 (unsigned int) insn);
964 else
965 (*info->fprintf_func) (info->stream, ".word 0x%x",
966 (unsigned int) insn >> 16);
967 return insn_length;
252b5132 968}
07dd56a9 969
471b9d15 970const disasm_options_and_args_t *
65b48a81
PB
971disassembler_options_powerpc (void)
972{
471b9d15 973 static disasm_options_and_args_t *opts_and_args;
65b48a81 974
471b9d15 975 if (opts_and_args == NULL)
65b48a81
PB
976 {
977 size_t i, num_options = ARRAY_SIZE (ppc_opts);
471b9d15
MR
978 disasm_options_t *opts;
979
980 opts_and_args = XNEW (disasm_options_and_args_t);
981 opts_and_args->args = NULL;
982
983 opts = &opts_and_args->options;
65b48a81 984 opts->name = XNEWVEC (const char *, num_options + 1);
471b9d15
MR
985 opts->description = NULL;
986 opts->arg = NULL;
65b48a81
PB
987 for (i = 0; i < num_options; i++)
988 opts->name[i] = ppc_opts[i].opt;
989 /* The array we return must be NULL terminated. */
990 opts->name[i] = NULL;
65b48a81
PB
991 }
992
471b9d15 993 return opts_and_args;
65b48a81
PB
994}
995
07dd56a9 996void
823bbe9d 997print_ppc_disassembler_options (FILE *stream)
07dd56a9 998{
69fe9ce5
AM
999 unsigned int i, col;
1000
1001 fprintf (stream, _("\n\
07dd56a9 1002The following PPC specific disassembler options are supported for use with\n\
69fe9ce5
AM
1003the -M switch:\n"));
1004
65b48a81 1005 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
69fe9ce5
AM
1006 {
1007 col += fprintf (stream, " %s,", ppc_opts[i].opt);
1008 if (col > 66)
1009 {
1010 fprintf (stream, "\n");
1011 col = 0;
1012 }
1013 }
65b48a81 1014 fprintf (stream, "\n");
07dd56a9 1015}