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