Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/opcodes/ppc-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* ppc-dis.c -- Disassemble PowerPC instructions
2
   Copyright (C) 1994-2023 Free Software Foundation, Inc.
3
   Written by Ian Lance Taylor, Cygnus Support
4
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.  */
21
22
#include "sysdep.h"
23
#include <stdio.h>
24
#include "disassemble.h"
25
#include "elf-bfd.h"
26
#include "elf/ppc.h"
27
#include "opintl.h"
28
#include "opcode/ppc.h"
29
#include "libiberty.h"
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.  */
36
static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
37
             ppc_cpu_t);
38
39
struct dis_private
40
{
41
  /* Stash the result of parsing disassembler_options here.  */
42
  ppc_cpu_t dialect;
43
44
  /* .got and .plt sections.  NAME is set to NULL if not present.  */
45
  struct sec_buf {
46
    asection *sec;
47
    bfd_byte *buf;
48
    const char *name;
49
  } special[2];
50
};
51
52
static inline struct dis_private *
53
private_data (struct disassemble_info *info)
54
4.70M
{
55
4.70M
  return (struct dis_private *) info->private_data;
56
4.70M
}
57
58
struct ppc_mopt {
59
  /* Option string, without -m or -M prefix.  */
60
  const char *opt;
61
  /* CPU option flags.  */
62
  ppc_cpu_t cpu;
63
  /* Flags that should stay on, even when combined with another cpu
64
     option.  This should only be used for generic options like
65
     "-many" or "-maltivec" where it is reasonable to add some
66
     capability to another cpu selection.  The added flags are sticky
67
     so that, for example, "-many -me500" and "-me500 -many" result in
68
     the same assembler or disassembler behaviour.  Do not use
69
     "sticky" for specific cpus, as this will prevent that cpu's flags
70
     from overriding the defaults set in powerpc_init_dialect or a
71
     prior -m option.  */
72
  ppc_cpu_t sticky;
73
};
74
75
struct ppc_mopt ppc_opts[] = {
76
  { "403",     PPC_OPCODE_PPC | PPC_OPCODE_403,
77
    0 },
78
  { "405",     PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
79
    0 },
80
  { "440",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
81
    | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
82
    0 },
83
  { "464",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
84
    | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
85
    0 },
86
  { "476",     (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
87
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
88
    0 },
89
  { "601",     PPC_OPCODE_PPC | PPC_OPCODE_601,
90
    0 },
91
  { "603",     PPC_OPCODE_PPC,
92
    0 },
93
  { "604",     PPC_OPCODE_PPC,
94
    0 },
95
  { "620",     PPC_OPCODE_PPC | PPC_OPCODE_64,
96
    0 },
97
  { "7400",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
98
    0 },
99
  { "7410",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
100
    0 },
101
  { "7450",    PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
102
    0 },
103
  { "7455",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
104
    0 },
105
  { "750cl",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
106
    , 0 },
107
  { "gekko",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
108
    , 0 },
109
  { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
110
    , 0 },
111
  { "821",     PPC_OPCODE_PPC | PPC_OPCODE_860,
112
    0 },
113
  { "850",     PPC_OPCODE_PPC | PPC_OPCODE_860,
114
    0 },
115
  { "860",     PPC_OPCODE_PPC | PPC_OPCODE_860,
116
    0 },
117
  { "a2",      (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
118
    | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
119
    | PPC_OPCODE_A2),
120
    0 },
121
  { "altivec", PPC_OPCODE_PPC,
122
    PPC_OPCODE_ALTIVEC },
123
  { "any",     PPC_OPCODE_PPC,
124
    PPC_OPCODE_ANY },
125
  { "booke",   PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
126
    0 },
127
  { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
128
    0 },
129
  { "cell",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
130
    | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
131
    0 },
132
  { "com",     PPC_OPCODE_COMMON,
133
    0 },
134
  { "e200z2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_LSP
135
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
136
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
137
    | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
138
    | PPC_OPCODE_EFS2),
139
    0 },
140
  { "e200z4",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
141
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
142
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
143
    | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
144
    | PPC_OPCODE_EFS2),
145
    0 },
146
  { "e300",    PPC_OPCODE_PPC | PPC_OPCODE_E300,
147
    0 },
148
  { "e500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
149
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
150
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
151
    | PPC_OPCODE_E500),
152
    0 },
153
  { "e500mc",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
154
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
155
    | PPC_OPCODE_E500MC),
156
    0 },
157
  { "e500mc64",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
158
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
159
    | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
160
    | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
161
    0 },
162
  { "e5500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
163
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
164
    | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
165
    | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
166
    0 },
167
  { "e6500",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
168
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
169
    | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
170
    | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
171
    | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
172
    0 },
173
  { "e500x2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
174
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
175
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
176
    | PPC_OPCODE_E500),
177
    0 },
178
  { "efs",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
179
    0 },
180
  { "efs2",    PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
181
    0 },
182
  { "lsp",     PPC_OPCODE_PPC,
183
    PPC_OPCODE_LSP },
184
  { "power4",  PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
185
    0 },
186
  { "power5",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
187
    | PPC_OPCODE_POWER5),
188
    0 },
189
  { "power6",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
190
    | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
191
    0 },
192
  { "power7",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
193
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
194
    | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
195
    0 },
196
  { "power8",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
197
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
198
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
199
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
200
    0 },
201
  { "power9",  (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_POWER8 | PPC_OPCODE_POWER9
204
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
205
    0 },
206
  { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
207
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
208
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
209
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
210
    0 },
211
  { "libresoc",(PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
212
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
213
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
214
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX | PPC_OPCODE_SVP64),
215
    0 },
216
  { "future",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
217
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
218
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
219
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
220
    | PPC_OPCODE_FUTURE),
221
    0 },
222
  { "ppc",     PPC_OPCODE_PPC,
223
    0 },
224
  { "ppc32",   PPC_OPCODE_PPC,
225
    0 },
226
  { "32",      PPC_OPCODE_PPC,
227
    0 },
228
  { "ppc64",   PPC_OPCODE_PPC | PPC_OPCODE_64,
229
    0 },
230
  { "64",      PPC_OPCODE_PPC | PPC_OPCODE_64,
231
    0 },
232
  { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
233
    0 },
234
  { "ppcps",   PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
235
    0 },
236
  { "pwr",     PPC_OPCODE_POWER,
237
    0 },
238
  { "pwr2",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
239
    0 },
240
  { "pwr4",    PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
241
    0 },
242
  { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
243
    | PPC_OPCODE_POWER5),
244
    0 },
245
  { "pwr5x",   (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
246
    | PPC_OPCODE_POWER5),
247
    0 },
248
  { "pwr6",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
249
    | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
250
    0 },
251
  { "pwr7",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
252
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
253
    | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
254
    0 },
255
  { "pwr8",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
256
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
257
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
258
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
259
    0 },
260
  { "pwr9",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
261
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
262
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
263
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
264
    0 },
265
  { "pwr10",   (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
266
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
267
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
268
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
269
    0 },
270
  { "pwrx",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
271
    0 },
272
  { "raw",     PPC_OPCODE_PPC,
273
    PPC_OPCODE_RAW },
274
  { "spe",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
275
    PPC_OPCODE_SPE },
276
  { "spe2",     PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
277
    PPC_OPCODE_SPE2 },
278
  { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
279
    | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
280
    0 },
281
  { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
282
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
283
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
284
    | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
285
    PPC_OPCODE_VLE },
286
  { "vsx",     PPC_OPCODE_PPC,
287
    PPC_OPCODE_VSX },
288
};
289
290
/* Switch between Booke and VLE dialects for interlinked dumps.  */
291
static ppc_cpu_t
292
get_powerpc_dialect (struct disassemble_info *info)
293
4.69M
{
294
4.69M
  ppc_cpu_t dialect = 0;
295
296
4.69M
  if (info->private_data)
297
4.69M
    dialect = private_data (info)->dialect;
298
299
  /* Disassemble according to the section headers flags for VLE-mode.  */
300
4.69M
  if (dialect & PPC_OPCODE_VLE
301
4.69M
      && info->section != NULL && info->section->owner != NULL
302
4.69M
      && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
303
4.69M
      && elf_object_id (info->section->owner) == PPC32_ELF_DATA
304
4.69M
      && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
305
0
    return dialect;
306
4.69M
  else
307
4.69M
    return dialect & ~ PPC_OPCODE_VLE;
308
4.69M
}
309
310
/* Handle -m and -M options that set cpu type, and .machine arg.  */
311
312
ppc_cpu_t
313
ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
314
1.01k
{
315
1.01k
  unsigned int i;
316
317
51.1k
  for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
318
51.1k
    if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
319
1.01k
      {
320
1.01k
  if (ppc_opts[i].sticky)
321
84
    {
322
84
      *sticky |= ppc_opts[i].sticky;
323
84
      if ((ppc_cpu & ~*sticky) != 0)
324
0
        break;
325
84
    }
326
1.01k
  ppc_cpu = ppc_opts[i].cpu;
327
1.01k
  break;
328
1.01k
      }
329
1.01k
  if (i >= ARRAY_SIZE (ppc_opts))
330
0
    return 0;
331
332
  /* SPE and LSP are mutually exclusive, don't allow them both in
333
     sticky options.  However do allow them both in ppc_cpu, so that
334
     for example, -mvle -mlsp enables both SPE and LSP for assembly.  */
335
1.01k
  if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0)
336
0
    *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2);
337
1.01k
  else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0)
338
0
    *sticky &= ~PPC_OPCODE_LSP;
339
1.01k
  ppc_cpu |= *sticky;
340
341
1.01k
  return ppc_cpu;
342
1.01k
}
343
344
/* Determine which set of machines to disassemble for.  */
345
346
static void
347
powerpc_init_dialect (struct disassemble_info *info)
348
1.01k
{
349
1.01k
  ppc_cpu_t dialect = 0;
350
1.01k
  ppc_cpu_t sticky = 0;
351
1.01k
  struct dis_private *priv = calloc (sizeof (*priv), 1);
352
353
1.01k
  if (priv == NULL)
354
0
    return;
355
356
1.01k
  switch (info->mach)
357
1.01k
    {
358
0
    case bfd_mach_ppc_403:
359
0
    case bfd_mach_ppc_403gc:
360
0
      dialect = ppc_parse_cpu (dialect, &sticky, "403");
361
0
      break;
362
0
    case bfd_mach_ppc_405:
363
0
      dialect = ppc_parse_cpu (dialect, &sticky, "405");
364
0
      break;
365
2
    case bfd_mach_ppc_601:
366
2
      dialect = ppc_parse_cpu (dialect, &sticky, "601");
367
2
      break;
368
0
    case bfd_mach_ppc_750:
369
0
      dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
370
0
      break;
371
1
    case bfd_mach_ppc_a35:
372
1
    case bfd_mach_ppc_rs64ii:
373
1
    case bfd_mach_ppc_rs64iii:
374
1
      dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
375
1
      break;
376
0
    case bfd_mach_ppc_e500:
377
0
      dialect = ppc_parse_cpu (dialect, &sticky, "e500");
378
0
      break;
379
0
    case bfd_mach_ppc_e500mc:
380
0
      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
381
0
      break;
382
0
    case bfd_mach_ppc_e500mc64:
383
0
      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
384
0
      break;
385
0
    case bfd_mach_ppc_e5500:
386
0
      dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
387
0
      break;
388
0
    case bfd_mach_ppc_e6500:
389
0
      dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
390
0
      break;
391
9
    case bfd_mach_ppc_titan:
392
9
      dialect = ppc_parse_cpu (dialect, &sticky, "titan");
393
9
      break;
394
84
    case bfd_mach_ppc_vle:
395
84
      dialect = ppc_parse_cpu (dialect, &sticky, "vle");
396
84
      break;
397
918
    default:
398
918
      if (info->arch == bfd_arch_powerpc)
399
593
  dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
400
325
      else
401
325
  dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
402
918
      break;
403
1.01k
    }
404
405
1.01k
  const char *opt;
406
1.01k
  FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
407
0
    {
408
0
      ppc_cpu_t new_cpu = 0;
409
410
0
      if (disassembler_options_cmp (opt, "32") == 0)
411
0
  dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
412
0
      else if (disassembler_options_cmp (opt, "64") == 0)
413
0
  dialect |= PPC_OPCODE_64;
414
0
      else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
415
0
  dialect = new_cpu;
416
0
      else
417
  /* xgettext: c-format */
418
0
  opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
419
0
    }
420
421
1.01k
  info->private_data = priv;
422
1.01k
  private_data (info)->dialect = dialect;
423
1.01k
}
424
425
1.14k
#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
426
static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
427
68
#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
428
static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
429
68
#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
430
static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
431
68
#define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1))
432
static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1];
433
36
#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
434
static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
435
436
static bool
437
ppc_symbol_is_valid (asymbol *sym,
438
         struct disassemble_info *info ATTRIBUTE_UNUSED)
439
58.8k
{
440
58.8k
  elf_symbol_type * est;
441
442
58.8k
  if (sym == NULL)
443
0
    return false;
444
445
58.8k
  est = elf_symbol_from (sym);
446
447
  /* Ignore ELF hidden, local, no-type symbols.
448
     These are generated by annobin.  */
449
58.8k
  if (est != NULL
450
58.8k
      && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN
451
58.8k
      && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL
452
58.8k
      && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE)
453
0
    return false;
454
455
58.8k
  return true;
456
58.8k
}
457
458
/* Calculate opcode table indices to speed up disassembly,
459
   and init dialect.  */
460
461
void
462
disassemble_init_powerpc (struct disassemble_info *info)
463
1.01k
{
464
1.01k
  info->symbol_is_valid = ppc_symbol_is_valid;
465
466
1.01k
  if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
467
2
    {
468
2
      unsigned seg, idx, op;
469
470
      /* PPC opcodes */
471
132
      for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
472
130
  {
473
130
    powerpc_opcd_indices[seg] = idx;
474
8.14k
    for (; idx < powerpc_num_opcodes; idx++)
475
8.14k
      if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
476
126
        break;
477
130
  }
478
479
      /* 64-bit prefix opcodes */
480
68
      for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
481
66
  {
482
66
    prefix_opcd_indices[seg] = idx;
483
284
    for (; idx < prefix_num_opcodes; idx++)
484
280
      if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
485
62
        break;
486
66
  }
487
488
      /* VLE opcodes */
489
68
      for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
490
66
  {
491
66
    vle_opcd_indices[seg] = idx;
492
512
    for (; idx < vle_num_opcodes; idx++)
493
504
      {
494
504
        op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
495
504
        if (seg < VLE_OP_TO_SEG (op))
496
58
    break;
497
504
      }
498
66
  }
499
500
      /* LSP opcodes */
501
68
      for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++)
502
66
  {
503
66
    lsp_opcd_indices[seg] = idx;
504
1.42k
    for (; idx < lsp_num_opcodes; idx++)
505
1.41k
      if (seg < LSP_OP_TO_SEG (lsp_opcodes[idx].opcode))
506
54
        break;
507
66
  }
508
509
      /* SPE2 opcodes */
510
36
      for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
511
34
  {
512
34
    spe2_opcd_indices[seg] = idx;
513
1.61k
    for (; idx < spe2_num_opcodes; idx++)
514
1.60k
      {
515
1.60k
        op = SPE2_XOP (spe2_opcodes[idx].opcode);
516
1.60k
        if (seg < SPE2_XOP_TO_SEG (op))
517
24
    break;
518
1.60k
      }
519
34
  }
520
2
    }
521
522
1.01k
  powerpc_init_dialect (info);
523
1.01k
  if (info->private_data != NULL)
524
1.01k
    {
525
1.01k
      private_data (info)->special[0].name = ".got";
526
1.01k
      private_data (info)->special[1].name = ".plt";
527
1.01k
    }
528
1.01k
}
529
530
/* Print a big endian PowerPC instruction.  */
531
532
int
533
print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
534
1.83M
{
535
1.83M
  return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
536
1.83M
}
537
538
/* Print a little endian PowerPC instruction.  */
539
540
int
541
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
542
2.86M
{
543
2.86M
  return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
544
2.86M
}
545
546
/* Extract the operand value from the PowerPC or POWER instruction.  */
547
548
static int64_t
549
operand_value_powerpc (const struct powerpc_operand *operand,
550
           uint64_t insn, ppc_cpu_t dialect)
551
7.38M
{
552
7.38M
  int64_t value;
553
7.38M
  int invalid = 0;
554
  /* Extract the value from the instruction.  */
555
7.38M
  if (operand->extract)
556
540k
    value = (*operand->extract) (insn, dialect, &invalid);
557
6.84M
  else
558
6.84M
    {
559
6.84M
      if (operand->shift >= 0)
560
6.84M
  value = (insn >> operand->shift) & operand->bitm;
561
0
      else
562
0
  value = (insn << -operand->shift) & operand->bitm;
563
6.84M
      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
564
1.51M
  {
565
    /* BITM is always some number of zeros followed by some
566
       number of ones, followed by some number of zeros.  */
567
1.51M
    uint64_t top = operand->bitm;
568
    /* top & -top gives the rightmost 1 bit, so this
569
       fills in any trailing zeros.  */
570
1.51M
    top |= (top & -top) - 1;
571
1.51M
    top &= ~(top >> 1);
572
1.51M
    value = (value ^ top) - top;
573
1.51M
  }
574
6.84M
    }
575
576
7.38M
  if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
577
0
    ++value;
578
579
7.38M
  return value;
580
7.38M
}
581
582
/* Determine whether the optional operand(s) should be printed.  */
583
584
static bool
585
skip_optional_operands (const ppc_opindex_t *opindex,
586
      uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
587
263k
{
588
263k
  const struct powerpc_operand *operand;
589
263k
  int num_optional;
590
591
335k
  for (num_optional = 0; *opindex != 0; opindex++)
592
305k
    {
593
305k
      operand = &powerpc_operands[*opindex];
594
305k
      if ((operand->flags & PPC_OPERAND_NEXT) != 0)
595
126k
  return false;
596
179k
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
597
137k
  {
598
137k
    int64_t value = operand_value_powerpc (operand, insn, dialect);
599
600
137k
    if (operand->shift == 52)
601
1.22k
      *is_pcrel = value != 0;
602
603
    /* Negative count is used as a flag to extract function.  */
604
137k
    --num_optional;
605
137k
    if (value != ppc_optional_operand_value (operand, insn, dialect,
606
137k
               num_optional))
607
107k
      return false;
608
137k
  }
609
179k
    }
610
611
29.7k
  return true;
612
263k
}
613
614
/* Find a match for INSN in the opcode table, given machine DIALECT.  */
615
616
static const struct powerpc_opcode *
617
lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
618
6.99M
{
619
6.99M
  const struct powerpc_opcode *opcode, *opcode_end;
620
6.99M
  unsigned long op;
621
622
  /* Get the major opcode of the instruction.  */
623
6.99M
  op = PPC_OP (insn);
624
625
  /* Find the first match in the opcode table for this major opcode.  */
626
6.99M
  opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
627
6.99M
  for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
628
281M
       opcode < opcode_end;
629
274M
       ++opcode)
630
277M
    {
631
277M
      const ppc_opindex_t *opindex;
632
277M
      const struct powerpc_operand *operand;
633
277M
      int invalid;
634
635
277M
      if ((insn & opcode->mask) != opcode->opcode
636
277M
    || ((dialect & PPC_OPCODE_ANY) == 0
637
3.09M
        && ((opcode->flags & dialect) == 0
638
2.87M
      || (opcode->deprecated & dialect) != 0))
639
277M
    || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
640
274M
  continue;
641
642
      /* Check validity of operands.  */
643
2.71M
      invalid = 0;
644
10.5M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
645
7.87M
  {
646
7.87M
    operand = powerpc_operands + *opindex;
647
7.87M
    if (operand->extract)
648
826k
      (*operand->extract) (insn, dialect, &invalid);
649
7.87M
  }
650
2.71M
      if (invalid)
651
227k
  continue;
652
653
2.48M
      return opcode;
654
2.71M
    }
655
656
4.50M
  return NULL;
657
6.99M
}
658
659
/* Find a match for INSN in the PREFIX opcode table.  */
660
661
static const struct powerpc_opcode *
662
lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
663
176k
{
664
176k
  const struct powerpc_opcode *opcode, *opcode_end;
665
176k
  unsigned long seg;
666
667
  /* Get the opcode segment of the instruction.  */
668
176k
  seg = PPC_PREFIX_SEG (insn);
669
670
  /* Find the first match in the opcode table for this major opcode.  */
671
176k
  opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
672
176k
  for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
673
617k
       opcode < opcode_end;
674
441k
       ++opcode)
675
443k
    {
676
443k
      const ppc_opindex_t *opindex;
677
443k
      const struct powerpc_operand *operand;
678
443k
      int invalid;
679
680
443k
      if ((insn & opcode->mask) != opcode->opcode
681
443k
    || ((dialect & PPC_OPCODE_ANY) == 0
682
2.08k
        && (opcode->flags & dialect) == 0)
683
443k
    || (opcode->deprecated & dialect) != 0)
684
441k
  continue;
685
686
      /* Check validity of operands.  */
687
2.08k
      invalid = 0;
688
8.44k
      for (opindex = opcode->operands; *opindex != 0; opindex++)
689
6.36k
  {
690
6.36k
    operand = powerpc_operands + *opindex;
691
6.36k
    if (operand->extract)
692
3.71k
      (*operand->extract) (insn, dialect, &invalid);
693
6.36k
  }
694
2.08k
      if (invalid)
695
570
  continue;
696
697
1.51k
      return opcode;
698
2.08k
    }
699
700
174k
  return NULL;
701
176k
}
702
703
/* Find a match for INSN in the VLE opcode table.  */
704
705
static const struct powerpc_opcode *
706
lookup_vle (uint64_t insn, ppc_cpu_t dialect)
707
0
{
708
0
  const struct powerpc_opcode *opcode;
709
0
  const struct powerpc_opcode *opcode_end;
710
0
  unsigned op, seg;
711
712
0
  op = PPC_OP (insn);
713
0
  if (op >= 0x20 && op <= 0x37)
714
0
    {
715
      /* This insn has a 4-bit opcode.  */
716
0
      op &= 0x3c;
717
0
    }
718
0
  seg = VLE_OP_TO_SEG (op);
719
720
  /* Find the first match in the opcode table for this major opcode.  */
721
0
  opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
722
0
  for (opcode = vle_opcodes + vle_opcd_indices[seg];
723
0
       opcode < opcode_end;
724
0
       ++opcode)
725
0
    {
726
0
      uint64_t table_opcd = opcode->opcode;
727
0
      uint64_t table_mask = opcode->mask;
728
0
      bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
729
0
      uint64_t insn2;
730
0
      const ppc_opindex_t *opindex;
731
0
      const struct powerpc_operand *operand;
732
0
      int invalid;
733
734
0
      insn2 = insn;
735
0
      if (table_op_is_short)
736
0
  insn2 >>= 16;
737
0
      if ((insn2 & table_mask) != table_opcd
738
0
    || (opcode->deprecated & dialect) != 0)
739
0
  continue;
740
741
      /* Check validity of operands.  */
742
0
      invalid = 0;
743
0
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
744
0
  {
745
0
    operand = powerpc_operands + *opindex;
746
0
    if (operand->extract)
747
0
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
748
0
  }
749
0
      if (invalid)
750
0
  continue;
751
752
0
      return opcode;
753
0
    }
754
755
0
  return NULL;
756
0
}
757
758
/* Find a match for INSN in the LSP opcode table.  */
759
760
static const struct powerpc_opcode *
761
lookup_lsp (uint64_t insn, ppc_cpu_t dialect)
762
2.13M
{
763
2.13M
  const struct powerpc_opcode *opcode, *opcode_end;
764
2.13M
  unsigned op, seg;
765
766
2.13M
  op = PPC_OP (insn);
767
2.13M
  if (op != 0x4)
768
2.12M
    return NULL;
769
770
4.69k
  seg = LSP_OP_TO_SEG (insn);
771
772
  /* Find the first match in the opcode table for this opcode.  */
773
4.69k
  opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1];
774
4.69k
  for (opcode = lsp_opcodes + lsp_opcd_indices[seg];
775
35.4k
       opcode < opcode_end;
776
30.7k
       ++opcode)
777
31.3k
    {
778
31.3k
      const ppc_opindex_t *opindex;
779
31.3k
      const struct powerpc_operand *operand;
780
31.3k
      int invalid;
781
782
31.3k
      if ((insn & opcode->mask) != opcode->opcode
783
31.3k
    || (opcode->deprecated & dialect) != 0)
784
30.5k
  continue;
785
786
      /* Check validity of operands.  */
787
812
      invalid = 0;
788
3.24k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
789
2.43k
  {
790
2.43k
    operand = powerpc_operands + *opindex;
791
2.43k
    if (operand->extract)
792
458
      (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
793
2.43k
  }
794
812
      if (invalid)
795
182
  continue;
796
797
630
      return opcode;
798
812
    }
799
800
4.06k
  return NULL;
801
4.69k
}
802
803
/* Find a match for INSN in the SPE2 opcode table.  */
804
805
static const struct powerpc_opcode *
806
lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
807
2.19M
{
808
2.19M
  const struct powerpc_opcode *opcode, *opcode_end;
809
2.19M
  unsigned op, xop, seg;
810
811
2.19M
  op = PPC_OP (insn);
812
2.19M
  if (op != 0x4)
813
2.18M
    {
814
      /* This is not SPE2 insn.
815
       * All SPE2 instructions have OP=4 and differs by XOP  */
816
2.18M
      return NULL;
817
2.18M
    }
818
10.3k
  xop = SPE2_XOP (insn);
819
10.3k
  seg = SPE2_XOP_TO_SEG (xop);
820
821
  /* Find the first match in the opcode table for this opcode.  */
822
10.3k
  opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
823
10.3k
  for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
824
368k
       opcode < opcode_end;
825
358k
       ++opcode)
826
363k
    {
827
363k
      uint64_t table_opcd = opcode->opcode;
828
363k
      uint64_t table_mask = opcode->mask;
829
363k
      uint64_t insn2;
830
363k
      const ppc_opindex_t *opindex;
831
363k
      const struct powerpc_operand *operand;
832
363k
      int invalid;
833
834
363k
      insn2 = insn;
835
363k
      if ((insn2 & table_mask) != table_opcd
836
363k
    || (opcode->deprecated & dialect) != 0)
837
358k
  continue;
838
839
      /* Check validity of operands.  */
840
5.01k
      invalid = 0;
841
20.0k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
842
15.0k
  {
843
15.0k
    operand = powerpc_operands + *opindex;
844
15.0k
    if (operand->extract)
845
901
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
846
15.0k
  }
847
5.01k
      if (invalid)
848
455
  continue;
849
850
4.55k
      return opcode;
851
5.01k
    }
852
853
5.78k
  return NULL;
854
10.3k
}
855
856
static arelent *
857
bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
858
0
{
859
0
  while (lo < hi)
860
0
    {
861
0
      arelent **mid = lo + (hi - lo) / 2;
862
0
      arelent *rel = *mid;
863
864
0
      if (vma < rel->address)
865
0
  hi = mid;
866
0
      else if (vma > rel->address)
867
0
  lo = mid + 1;
868
0
      else
869
0
  return rel;
870
0
    }
871
0
  return NULL;
872
0
}
873
874
static bool
875
print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
876
0
{
877
0
  if (sb->name != NULL)
878
0
    {
879
0
      asection *s = sb->sec;
880
0
      if (s == NULL)
881
0
  {
882
0
    s = bfd_get_section_by_name (info->section->owner, sb->name);
883
0
    sb->sec = s;
884
0
    if (s == NULL)
885
0
      sb->name = NULL;
886
0
  }
887
0
      if (s != NULL
888
0
    && vma >= s->vma
889
0
    && vma < s->vma + s->size)
890
0
  {
891
0
    asymbol *sym = NULL;
892
0
    uint64_t ent = 0;
893
0
    if (info->dynrelcount > 0)
894
0
      {
895
0
        arelent **lo = info->dynrelbuf;
896
0
        arelent **hi = lo + info->dynrelcount;
897
0
        arelent *rel = bsearch_reloc (lo, hi, vma);
898
0
        if (rel != NULL && rel->sym_ptr_ptr != NULL)
899
0
    sym = *rel->sym_ptr_ptr;
900
0
      }
901
0
    if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
902
0
      {
903
0
        if (sb->buf == NULL
904
0
      && !bfd_malloc_and_get_section (s->owner, s, &sb->buf))
905
0
    sb->name = NULL;
906
0
        if (sb->buf != NULL)
907
0
    {
908
0
      ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma));
909
0
      if (ent != 0)
910
0
        sym = (*info->symbol_at_address_func) (ent, info);
911
0
    }
912
0
      }
913
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
914
0
    if (sym != NULL)
915
0
      {
916
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
917
0
              "%s", bfd_asymbol_name (sym));
918
0
        (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
919
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
920
0
              "%s", sb->name + 1);
921
0
      }
922
0
    else
923
0
      {
924
0
        (*info->fprintf_styled_func) (info->stream, dis_style_address,
925
0
              "%" PRIx64, ent);
926
0
        (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
927
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
928
0
              "%s", sb->name + 1);
929
0
      }
930
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
931
0
    return true;
932
0
  }
933
0
    }
934
0
  return false;
935
0
}
936
937
/* Print a PowerPC or POWER instruction.  */
938
939
static int
940
print_insn_powerpc (bfd_vma memaddr,
941
        struct disassemble_info *info,
942
        int bigendian,
943
        ppc_cpu_t dialect)
944
4.69M
{
945
4.69M
  bfd_byte buffer[4];
946
4.69M
  int status;
947
4.69M
  uint64_t insn;
948
4.69M
  const struct powerpc_opcode *opcode;
949
4.69M
  int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
950
951
4.69M
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
952
953
  /* The final instruction may be a 2-byte VLE insn.  */
954
4.69M
  if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
955
0
    {
956
      /* Clear buffer so unused bytes will not have garbage in them.  */
957
0
      buffer[2] = buffer[3] = 0;
958
0
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
959
0
      insn_length = 2;
960
0
    }
961
962
4.69M
  if (status != 0)
963
1.01k
    {
964
1.01k
      (*info->memory_error_func) (status, memaddr, info);
965
1.01k
      return -1;
966
1.01k
    }
967
968
4.69M
  if (bigendian)
969
1.83M
    insn = bfd_getb32 (buffer);
970
2.86M
  else
971
2.86M
    insn = bfd_getl32 (buffer);
972
973
  /* Get the major opcode of the insn.  */
974
4.69M
  opcode = NULL;
975
4.69M
  if ((dialect & PPC_OPCODE_POWER10) != 0
976
4.69M
      && PPC_OP (insn) == 0x1)
977
88.9k
    {
978
88.9k
      uint64_t temp_insn, suffix;
979
88.9k
      status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
980
88.9k
      if (status == 0)
981
88.8k
  {
982
88.8k
    if (bigendian)
983
30.8k
      suffix = bfd_getb32 (buffer);
984
57.9k
    else
985
57.9k
      suffix = bfd_getl32 (buffer);
986
88.8k
    temp_insn = (insn << 32) | suffix;
987
88.8k
    opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
988
88.8k
    if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
989
87.3k
      opcode = lookup_prefix (temp_insn, dialect);
990
88.8k
    if (opcode != NULL)
991
1.51k
      {
992
1.51k
        insn = temp_insn;
993
1.51k
        insn_length = 8;
994
1.51k
        if ((info->flags & WIDE_OUTPUT) != 0)
995
0
    info->bytes_per_line = 8;
996
1.51k
      }
997
88.8k
  }
998
88.9k
    }
999
4.69M
  if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
1000
0
    {
1001
0
      opcode = lookup_vle (insn, dialect);
1002
0
      if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
1003
0
  {
1004
    /* The operands will be fetched out of the 16-bit instruction.  */
1005
0
    insn >>= 16;
1006
0
    insn_length = 2;
1007
0
  }
1008
0
    }
1009
4.69M
  if (opcode == NULL && insn_length == 4)
1010
4.69M
    {
1011
4.69M
      if ((dialect & PPC_OPCODE_LSP) != 0)
1012
0
  opcode = lookup_lsp (insn, dialect);
1013
4.69M
      if ((dialect & PPC_OPCODE_SPE2) != 0)
1014
58.1k
  opcode = lookup_spe2 (insn, dialect);
1015
4.69M
      if (opcode == NULL)
1016
4.69M
  opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
1017
4.69M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1018
2.29M
  opcode = lookup_powerpc (insn, dialect);
1019
4.69M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1020
2.13M
  opcode = lookup_spe2 (insn, dialect);
1021
4.69M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1022
2.13M
  opcode = lookup_lsp (insn, dialect);
1023
4.69M
    }
1024
1025
4.69M
  if (opcode != NULL)
1026
2.49M
    {
1027
2.49M
      const ppc_opindex_t *opindex;
1028
2.49M
      const struct powerpc_operand *operand;
1029
2.49M
      enum {
1030
2.49M
  need_comma = 0,
1031
2.49M
  need_1space = 1,
1032
2.49M
  need_2spaces = 2,
1033
2.49M
  need_3spaces = 3,
1034
2.49M
  need_4spaces = 4,
1035
2.49M
  need_5spaces = 5,
1036
2.49M
  need_6spaces = 6,
1037
2.49M
  need_7spaces = 7,
1038
2.49M
  need_paren
1039
2.49M
      } op_separator;
1040
2.49M
      bool skip_optional;
1041
2.49M
      bool is_pcrel;
1042
2.49M
      uint64_t d34;
1043
2.49M
      int blanks;
1044
1045
2.49M
      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1046
2.49M
            "%s", opcode->name);
1047
      /* gdb fprintf_styled_func doesn't return count printed.  */
1048
2.49M
      blanks = 8 - strlen (opcode->name);
1049
2.49M
      if (blanks <= 0)
1050
39.3k
  blanks = 1;
1051
1052
      /* Now extract and print the operands.  */
1053
2.49M
      op_separator = blanks;
1054
2.49M
      skip_optional = false;
1055
2.49M
      is_pcrel = false;
1056
2.49M
      d34 = 0;
1057
9.76M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
1058
7.27M
  {
1059
7.27M
    int64_t value;
1060
1061
7.27M
    operand = powerpc_operands + *opindex;
1062
1063
    /* If all of the optional operands past this one have their
1064
       default value, then don't print any of them.  Except in
1065
       raw mode, print them all.  */
1066
7.27M
    if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
1067
7.27M
        && (dialect & PPC_OPCODE_RAW) == 0)
1068
263k
      {
1069
263k
        if (!skip_optional)
1070
263k
    skip_optional = skip_optional_operands (opindex, insn,
1071
263k
              dialect, &is_pcrel);
1072
263k
        if (skip_optional)
1073
29.8k
    continue;
1074
263k
      }
1075
1076
7.24M
    value = operand_value_powerpc (operand, insn, dialect);
1077
1078
7.24M
    if (op_separator == need_comma)
1079
3.98M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
1080
3.25M
    else if (op_separator == need_paren)
1081
880k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
1082
2.37M
    else
1083
2.37M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
1084
2.37M
            op_separator, " ");
1085
1086
    /* Print the operand as directed by the flags.  */
1087
7.24M
    if ((operand->flags & PPC_OPERAND_GPR) != 0
1088
7.24M
        || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
1089
3.45M
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1090
3.45M
            "r%" PRId64, value);
1091
3.78M
    else if ((operand->flags & PPC_OPERAND_FPR) != 0)
1092
745k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1093
745k
            "f%" PRId64, value);
1094
3.04M
    else if ((operand->flags & PPC_OPERAND_VR) != 0)
1095
197k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1096
197k
            "v%" PRId64, value);
1097
2.84M
    else if ((operand->flags & PPC_OPERAND_VSR) != 0)
1098
145k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1099
145k
            "vs%" PRId64, value);
1100
2.70M
    else if ((operand->flags & PPC_OPERAND_DMR) != 0)
1101
1.09k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1102
1.09k
            "dm%" PRId64, value);
1103
2.70M
    else if ((operand->flags & PPC_OPERAND_ACC) != 0)
1104
380
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1105
380
            "a%" PRId64, value);
1106
2.69M
    else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
1107
118k
      (*info->print_address_func) (memaddr + value, info);
1108
2.58M
    else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
1109
42.9k
      (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
1110
2.53M
    else if ((operand->flags & PPC_OPERAND_FSL) != 0)
1111
0
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1112
0
            "fsl%" PRId64, value);
1113
2.53M
    else if ((operand->flags & PPC_OPERAND_FCR) != 0)
1114
110
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1115
110
            "fcr%" PRId64, value);
1116
2.53M
    else if ((operand->flags & PPC_OPERAND_UDI) != 0)
1117
279
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1118
279
            "%" PRId64, value);
1119
2.53M
    else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
1120
2.53M
       && (operand->flags & PPC_OPERAND_CR_BIT) == 0
1121
2.53M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1122
127k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1123
125k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1124
125k
            "cr%" PRId64, value);
1125
2.41M
    else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1126
2.41M
       && (operand->flags & PPC_OPERAND_CR_REG) == 0
1127
2.41M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1128
38.6k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1129
37.8k
      {
1130
37.8k
        static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1131
37.8k
        int cr;
1132
37.8k
        int cc;
1133
1134
37.8k
        cr = value >> 2;
1135
37.8k
        cc = value & 3;
1136
37.8k
        if (cr != 0)
1137
18.4k
    {
1138
18.4k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1139
18.4k
            "4*");
1140
18.4k
      (*info->fprintf_styled_func) (info->stream,
1141
18.4k
            dis_style_register,
1142
18.4k
            "cr%d", cr);
1143
18.4k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1144
18.4k
            "+");
1145
18.4k
    }
1146
1147
37.8k
        (*info->fprintf_styled_func) (info->stream,
1148
37.8k
              dis_style_sub_mnemonic,
1149
37.8k
              "%s", cbnames[cc]);
1150
37.8k
      }
1151
2.37M
    else
1152
2.37M
      {
1153
        /* An immediate, but what style?  */
1154
2.37M
        enum disassembler_style style;
1155
1156
2.37M
        if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1157
880k
    style = dis_style_address_offset;
1158
1.49M
        else
1159
1.49M
    style = dis_style_immediate;
1160
1161
2.37M
        (*info->fprintf_styled_func) (info->stream, style,
1162
2.37M
              "%" PRId64, value);
1163
2.37M
      }
1164
1165
7.24M
    if (operand->shift == 52)
1166
0
      is_pcrel = value != 0;
1167
7.24M
    else if (operand->bitm == UINT64_C (0x3ffffffff))
1168
1.01k
      d34 = value;
1169
1170
7.24M
    if (op_separator == need_paren)
1171
880k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1172
1173
7.24M
    op_separator = need_comma;
1174
7.24M
    if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1175
880k
      op_separator = need_paren;
1176
7.24M
  }
1177
1178
2.49M
      if (is_pcrel)
1179
5
  {
1180
5
    d34 += memaddr;
1181
5
    (*info->fprintf_styled_func) (info->stream,
1182
5
          dis_style_comment_start,
1183
5
          "\t# %" PRIx64, d34);
1184
5
    asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1185
5
    if (sym)
1186
0
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1187
0
            " <%s>", bfd_asymbol_name (sym));
1188
1189
5
    if (info->private_data != NULL
1190
5
        && info->section != NULL
1191
5
        && info->section->owner != NULL
1192
5
        && (bfd_get_file_flags (info->section->owner)
1193
0
      & (EXEC_P | DYNAMIC)) != 0
1194
5
        && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
1195
0
      == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
1196
0
      {
1197
0
        for (int i = 0; i < 2; i++)
1198
0
    if (print_got_plt (private_data (info)->special + i, d34, info))
1199
0
      break;
1200
0
      }
1201
5
  }
1202
1203
      /* We have found and printed an instruction.  */
1204
2.49M
      return insn_length;
1205
2.49M
    }
1206
1207
  /* We could not find a match.  */
1208
2.20M
  if (insn_length == 4)
1209
2.20M
    (*info->fprintf_styled_func) (info->stream,
1210
2.20M
          dis_style_assembler_directive, ".long");
1211
0
  else
1212
0
    {
1213
0
      (*info->fprintf_styled_func) (info->stream,
1214
0
            dis_style_assembler_directive, ".word");
1215
0
      insn >>= 16;
1216
0
    }
1217
2.20M
  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1218
2.20M
  (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
1219
2.20M
        (unsigned int) insn);
1220
1221
1222
2.20M
  return insn_length;
1223
4.69M
}
1224
1225
const disasm_options_and_args_t *
1226
disassembler_options_powerpc (void)
1227
0
{
1228
0
  static disasm_options_and_args_t *opts_and_args;
1229
1230
0
  if (opts_and_args == NULL)
1231
0
    {
1232
0
      size_t i, num_options = ARRAY_SIZE (ppc_opts);
1233
0
      disasm_options_t *opts;
1234
1235
0
      opts_and_args = XNEW (disasm_options_and_args_t);
1236
0
      opts_and_args->args = NULL;
1237
1238
0
      opts = &opts_and_args->options;
1239
0
      opts->name = XNEWVEC (const char *, num_options + 1);
1240
0
      opts->description = NULL;
1241
0
      opts->arg = NULL;
1242
0
      for (i = 0; i < num_options; i++)
1243
0
  opts->name[i] = ppc_opts[i].opt;
1244
      /* The array we return must be NULL terminated.  */
1245
0
      opts->name[i] = NULL;
1246
0
    }
1247
1248
0
  return opts_and_args;
1249
0
}
1250
1251
void
1252
print_ppc_disassembler_options (FILE *stream)
1253
0
{
1254
0
  unsigned int i, col;
1255
1256
0
  fprintf (stream, _("\n\
1257
0
The following PPC specific disassembler options are supported for use with\n\
1258
0
the -M switch:\n"));
1259
1260
0
  for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
1261
0
    {
1262
0
      col += fprintf (stream, " %s,", ppc_opts[i].opt);
1263
0
      if (col > 66)
1264
0
  {
1265
0
    fprintf (stream, "\n");
1266
0
    col = 0;
1267
0
  }
1268
0
    }
1269
0
  fprintf (stream, "\n");
1270
0
}