Coverage Report

Created: 2025-06-24 06:45

/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-2025 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
6.64M
{
55
6.64M
  return (struct dis_private *) info->private_data;
56
6.64M
}
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
  { "power11", (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_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
215
    0 },
216
  { "libresoc",(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_ALTIVEC | PPC_OPCODE_VSX | PPC_OPCODE_SVP64),
220
    0 },
221
  { "future",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
222
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
223
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
224
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
225
    | PPC_OPCODE_FUTURE),
226
    0 },
227
  { "ppc",     PPC_OPCODE_PPC,
228
    0 },
229
  { "ppc32",   PPC_OPCODE_PPC,
230
    0 },
231
  { "32",      PPC_OPCODE_PPC,
232
    0 },
233
  { "ppc64",   PPC_OPCODE_PPC | PPC_OPCODE_64,
234
    0 },
235
  { "64",      PPC_OPCODE_PPC | PPC_OPCODE_64,
236
    0 },
237
  { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
238
    0 },
239
  { "ppcps",   PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
240
    0 },
241
  { "pwr",     PPC_OPCODE_POWER,
242
    0 },
243
  { "pwr2",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
244
    0 },
245
  { "pwr4",    PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
246
    0 },
247
  { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
248
    | PPC_OPCODE_POWER5),
249
    0 },
250
  { "pwr5x",   (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
251
    | PPC_OPCODE_POWER5),
252
    0 },
253
  { "pwr6",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
254
    | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
255
    0 },
256
  { "pwr7",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
257
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
258
    | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
259
    0 },
260
  { "pwr8",    (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
263
    | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
264
    0 },
265
  { "pwr9",    (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_ALTIVEC | PPC_OPCODE_VSX),
269
    0 },
270
  { "pwr10",   (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
271
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
272
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
273
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
274
    0 },
275
  { "pwr11",   (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
276
    | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
277
    | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
278
    | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
279
    0 },
280
  { "pwrx",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
281
    0 },
282
  { "raw",     PPC_OPCODE_PPC,
283
    PPC_OPCODE_RAW },
284
  { "spe",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
285
    PPC_OPCODE_SPE },
286
  { "spe2",     PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
287
    PPC_OPCODE_SPE2 },
288
  { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
289
    | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
290
    0 },
291
  { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
292
    | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
293
    | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
294
    | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
295
    PPC_OPCODE_VLE },
296
  { "vsx",     PPC_OPCODE_PPC,
297
    PPC_OPCODE_VSX },
298
};
299
300
/* Switch between Booke and VLE dialects for interlinked dumps.  */
301
static ppc_cpu_t
302
get_powerpc_dialect (struct disassemble_info *info)
303
6.63M
{
304
6.63M
  ppc_cpu_t dialect = 0;
305
306
6.63M
  if (info->private_data)
307
6.63M
    dialect = private_data (info)->dialect;
308
309
  /* Disassemble according to the section headers flags for VLE-mode.  */
310
6.63M
  if (dialect & PPC_OPCODE_VLE
311
6.63M
      && info->section != NULL && info->section->owner != NULL
312
6.63M
      && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
313
6.63M
      && elf_object_id (info->section->owner) == PPC32_ELF_DATA
314
6.63M
      && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
315
0
    return dialect;
316
6.63M
  else
317
6.63M
    return dialect & ~ PPC_OPCODE_VLE;
318
6.63M
}
319
320
/* Handle -m and -M options that set cpu type, and .machine arg.  */
321
322
ppc_cpu_t
323
ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
324
1.14k
{
325
1.14k
  unsigned int i;
326
327
57.9k
  for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
328
57.9k
    if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
329
1.14k
      {
330
1.14k
  if (ppc_opts[i].sticky)
331
178
    {
332
178
      *sticky |= ppc_opts[i].sticky;
333
178
      if ((ppc_cpu & ~*sticky) != 0)
334
0
        break;
335
178
    }
336
1.14k
  ppc_cpu = ppc_opts[i].cpu;
337
1.14k
  break;
338
1.14k
      }
339
1.14k
  if (i >= ARRAY_SIZE (ppc_opts))
340
0
    return 0;
341
342
  /* SPE and LSP are mutually exclusive, don't allow them both in
343
     sticky options.  However do allow them both in ppc_cpu, so that
344
     for example, -mvle -mlsp enables both SPE and LSP for assembly.  */
345
1.14k
  if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0)
346
0
    *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2);
347
1.14k
  else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0)
348
0
    *sticky &= ~PPC_OPCODE_LSP;
349
1.14k
  ppc_cpu |= *sticky;
350
351
1.14k
  return ppc_cpu;
352
1.14k
}
353
354
/* Determine which set of machines to disassemble for.  */
355
356
static void
357
powerpc_init_dialect (struct disassemble_info *info)
358
1.14k
{
359
1.14k
  ppc_cpu_t dialect = 0;
360
1.14k
  ppc_cpu_t sticky = 0;
361
1.14k
  struct dis_private *priv = calloc (1, sizeof (*priv));
362
363
1.14k
  if (priv == NULL)
364
0
    return;
365
366
1.14k
  switch (info->mach)
367
1.14k
    {
368
1
    case bfd_mach_ppc_403:
369
1
    case bfd_mach_ppc_403gc:
370
1
      dialect = ppc_parse_cpu (dialect, &sticky, "403");
371
1
      break;
372
0
    case bfd_mach_ppc_405:
373
0
      dialect = ppc_parse_cpu (dialect, &sticky, "405");
374
0
      break;
375
1
    case bfd_mach_ppc_601:
376
1
      dialect = ppc_parse_cpu (dialect, &sticky, "601");
377
1
      break;
378
0
    case bfd_mach_ppc_750:
379
0
      dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
380
0
      break;
381
6
    case bfd_mach_ppc_a35:
382
7
    case bfd_mach_ppc_rs64ii:
383
8
    case bfd_mach_ppc_rs64iii:
384
8
      dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
385
8
      break;
386
3
    case bfd_mach_ppc_e500:
387
3
      dialect = ppc_parse_cpu (dialect, &sticky, "e500");
388
3
      break;
389
2
    case bfd_mach_ppc_e500mc:
390
2
      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
391
2
      break;
392
2
    case bfd_mach_ppc_e500mc64:
393
2
      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
394
2
      break;
395
1
    case bfd_mach_ppc_e5500:
396
1
      dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
397
1
      break;
398
3
    case bfd_mach_ppc_e6500:
399
3
      dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
400
3
      break;
401
2
    case bfd_mach_ppc_titan:
402
2
      dialect = ppc_parse_cpu (dialect, &sticky, "titan");
403
2
      break;
404
178
    case bfd_mach_ppc_vle:
405
178
      dialect = ppc_parse_cpu (dialect, &sticky, "vle");
406
178
      break;
407
939
    default:
408
939
      if (info->arch == bfd_arch_powerpc)
409
839
  dialect = ppc_parse_cpu (dialect, &sticky, "power11") | PPC_OPCODE_ANY;
410
100
      else
411
100
  dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
412
939
      break;
413
1.14k
    }
414
415
1.14k
  const char *opt;
416
1.14k
  FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
417
0
    {
418
0
      ppc_cpu_t new_cpu = 0;
419
420
0
      if (disassembler_options_cmp (opt, "32") == 0)
421
0
  dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
422
0
      else if (disassembler_options_cmp (opt, "64") == 0)
423
0
  dialect |= PPC_OPCODE_64;
424
0
      else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
425
0
  dialect = new_cpu;
426
0
      else
427
  /* xgettext: c-format */
428
0
  opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
429
0
    }
430
431
1.14k
  info->private_data = priv;
432
1.14k
  private_data (info)->dialect = dialect;
433
1.14k
}
434
435
1.27k
#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
436
static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
437
68
#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
438
static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
439
68
#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
440
static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
441
68
#define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1))
442
static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1];
443
36
#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
444
static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
445
446
static bool
447
ppc_symbol_is_valid (asymbol *sym,
448
         struct disassemble_info *info ATTRIBUTE_UNUSED)
449
111k
{
450
111k
  elf_symbol_type * est;
451
452
111k
  if (sym == NULL)
453
0
    return false;
454
455
111k
  est = elf_symbol_from (sym);
456
457
  /* Ignore ELF hidden, local, no-type symbols.
458
     These are generated by annobin.  */
459
111k
  if (est != NULL
460
111k
      && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN
461
111k
      && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL
462
111k
      && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE)
463
0
    return false;
464
465
111k
  return true;
466
111k
}
467
468
/* Calculate opcode table indices to speed up disassembly,
469
   and init dialect.  */
470
471
void
472
disassemble_init_powerpc (struct disassemble_info *info)
473
1.14k
{
474
1.14k
  info->symbol_is_valid = ppc_symbol_is_valid;
475
476
1.14k
  if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
477
2
    {
478
2
      unsigned seg, idx, op;
479
480
      /* PPC opcodes */
481
132
      for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
482
130
  {
483
130
    powerpc_opcd_indices[seg] = idx;
484
8.20k
    for (; idx < powerpc_num_opcodes; idx++)
485
8.19k
      if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
486
126
        break;
487
130
  }
488
489
      /* 64-bit prefix opcodes */
490
68
      for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
491
66
  {
492
66
    prefix_opcd_indices[seg] = idx;
493
290
    for (; idx < prefix_num_opcodes; idx++)
494
286
      if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
495
62
        break;
496
66
  }
497
498
      /* VLE opcodes */
499
68
      for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
500
66
  {
501
66
    vle_opcd_indices[seg] = idx;
502
512
    for (; idx < vle_num_opcodes; idx++)
503
504
      {
504
504
        op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
505
504
        if (seg < VLE_OP_TO_SEG (op))
506
58
    break;
507
504
      }
508
66
  }
509
510
      /* LSP opcodes */
511
68
      for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++)
512
66
  {
513
66
    lsp_opcd_indices[seg] = idx;
514
1.42k
    for (; idx < lsp_num_opcodes; idx++)
515
1.41k
      if (seg < LSP_OP_TO_SEG (lsp_opcodes[idx].opcode))
516
54
        break;
517
66
  }
518
519
      /* SPE2 opcodes */
520
36
      for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
521
34
  {
522
34
    spe2_opcd_indices[seg] = idx;
523
1.61k
    for (; idx < spe2_num_opcodes; idx++)
524
1.60k
      {
525
1.60k
        op = SPE2_XOP (spe2_opcodes[idx].opcode);
526
1.60k
        if (seg < SPE2_XOP_TO_SEG (op))
527
24
    break;
528
1.60k
      }
529
34
  }
530
2
    }
531
532
1.14k
  powerpc_init_dialect (info);
533
1.14k
  if (info->private_data != NULL)
534
1.14k
    {
535
1.14k
      private_data (info)->special[0].name = ".got";
536
1.14k
      private_data (info)->special[1].name = ".plt";
537
1.14k
    }
538
1.14k
}
539
540
void
541
disassemble_free_powerpc (struct disassemble_info *info)
542
1.04k
{
543
1.04k
  if (info->private_data != NULL)
544
1.04k
    {
545
1.04k
      free (private_data (info)->special[0].buf);
546
1.04k
      free (private_data (info)->special[1].buf);
547
1.04k
    }
548
1.04k
}
549
550
/* Print a big endian PowerPC instruction.  */
551
552
int
553
print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
554
6.28M
{
555
6.28M
  return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
556
6.28M
}
557
558
/* Print a little endian PowerPC instruction.  */
559
560
int
561
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
562
350k
{
563
350k
  return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
564
350k
}
565
566
/* Extract the operand value from the PowerPC or POWER instruction.  */
567
568
static int64_t
569
operand_value_powerpc (const struct powerpc_operand *operand,
570
           uint64_t insn, ppc_cpu_t dialect)
571
11.6M
{
572
11.6M
  int64_t value;
573
11.6M
  int invalid = 0;
574
  /* Extract the value from the instruction.  */
575
11.6M
  if (operand->extract)
576
794k
    value = (*operand->extract) (insn, dialect, &invalid);
577
10.8M
  else
578
10.8M
    {
579
10.8M
      if (operand->shift >= 0)
580
10.8M
  value = (insn >> operand->shift) & operand->bitm;
581
0
      else
582
0
  value = (insn << -operand->shift) & operand->bitm;
583
10.8M
      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
584
2.59M
  {
585
    /* BITM is always some number of zeros followed by some
586
       number of ones, followed by some number of zeros.  */
587
2.59M
    uint64_t top = operand->bitm;
588
    /* top & -top gives the rightmost 1 bit, so this
589
       fills in any trailing zeros.  */
590
2.59M
    top |= (top & -top) - 1;
591
2.59M
    top &= ~(top >> 1);
592
2.59M
    value = (value ^ top) - top;
593
2.59M
  }
594
10.8M
    }
595
596
11.6M
  if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
597
0
    ++value;
598
599
11.6M
  return value;
600
11.6M
}
601
602
/* Determine whether the optional operand(s) should be printed.  */
603
604
static bool
605
skip_optional_operands (const ppc_opindex_t *opindex,
606
      uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
607
425k
{
608
425k
  const struct powerpc_operand *operand;
609
425k
  int num_optional;
610
611
531k
  for (num_optional = 0; *opindex != 0; opindex++)
612
480k
    {
613
480k
      operand = &powerpc_operands[*opindex];
614
480k
      if ((operand->flags & PPC_OPERAND_NEXT) != 0)
615
173k
  return false;
616
306k
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
617
252k
  {
618
252k
    int64_t value = operand_value_powerpc (operand, insn, dialect);
619
620
252k
    if (operand->shift == 52)
621
2.14k
      *is_pcrel = value != 0;
622
623
    /* Negative count is used as a flag to extract function.  */
624
252k
    --num_optional;
625
252k
    if (value != ppc_optional_operand_value (operand, insn, dialect,
626
252k
               num_optional))
627
200k
      return false;
628
252k
  }
629
306k
    }
630
631
51.5k
  return true;
632
425k
}
633
634
/* Find a match for INSN in the opcode table, given machine DIALECT.  */
635
636
static const struct powerpc_opcode *
637
lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
638
8.29M
{
639
8.29M
  const struct powerpc_opcode *opcode, *opcode_end;
640
8.29M
  unsigned long op;
641
642
  /* Get the major opcode of the instruction.  */
643
8.29M
  op = PPC_OP (insn);
644
645
  /* Find the first match in the opcode table for this major opcode.  */
646
8.29M
  opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
647
8.29M
  for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
648
412M
       opcode < opcode_end;
649
404M
       ++opcode)
650
407M
    {
651
407M
      const ppc_opindex_t *opindex;
652
407M
      const struct powerpc_operand *operand;
653
407M
      int invalid;
654
655
407M
      if ((insn & opcode->mask) != opcode->opcode
656
407M
    || ((dialect & PPC_OPCODE_ANY) == 0
657
5.73M
        && ((opcode->flags & dialect) == 0
658
5.46M
      || (opcode->deprecated & dialect) != 0))
659
407M
    || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
660
403M
  continue;
661
662
      /* Check validity of operands.  */
663
4.42M
      invalid = 0;
664
17.1M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
665
12.7M
  {
666
12.7M
    operand = powerpc_operands + *opindex;
667
12.7M
    if (operand->extract)
668
1.36M
      (*operand->extract) (insn, dialect, &invalid);
669
12.7M
  }
670
4.42M
      if (invalid)
671
487k
  continue;
672
673
3.93M
      return opcode;
674
4.42M
    }
675
676
4.36M
  return NULL;
677
8.29M
}
678
679
/* Find a match for INSN in the PREFIX opcode table.  */
680
681
static const struct powerpc_opcode *
682
lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
683
218k
{
684
218k
  const struct powerpc_opcode *opcode, *opcode_end;
685
218k
  unsigned long seg;
686
687
  /* Get the opcode segment of the instruction.  */
688
218k
  seg = PPC_PREFIX_SEG (insn);
689
690
  /* Find the first match in the opcode table for this major opcode.  */
691
218k
  opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
692
218k
  for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
693
725k
       opcode < opcode_end;
694
506k
       ++opcode)
695
508k
    {
696
508k
      const ppc_opindex_t *opindex;
697
508k
      const struct powerpc_operand *operand;
698
508k
      int invalid;
699
700
508k
      if ((insn & opcode->mask) != opcode->opcode
701
508k
    || ((dialect & PPC_OPCODE_ANY) == 0
702
2.52k
        && (opcode->flags & dialect) == 0)
703
508k
    || (opcode->deprecated & dialect) != 0)
704
506k
  continue;
705
706
      /* Check validity of operands.  */
707
2.48k
      invalid = 0;
708
11.1k
      for (opindex = opcode->operands; *opindex != 0; opindex++)
709
8.62k
  {
710
8.62k
    operand = powerpc_operands + *opindex;
711
8.62k
    if (operand->extract)
712
4.94k
      (*operand->extract) (insn, dialect, &invalid);
713
8.62k
  }
714
2.48k
      if (invalid)
715
561
  continue;
716
717
1.92k
      return opcode;
718
2.48k
    }
719
720
217k
  return NULL;
721
218k
}
722
723
/* Find a match for INSN in the VLE opcode table.  */
724
725
static const struct powerpc_opcode *
726
lookup_vle (uint64_t insn, ppc_cpu_t dialect)
727
0
{
728
0
  const struct powerpc_opcode *opcode;
729
0
  const struct powerpc_opcode *opcode_end;
730
0
  unsigned op, seg;
731
732
0
  op = PPC_OP (insn);
733
0
  if (op >= 0x20 && op <= 0x37)
734
0
    {
735
      /* This insn has a 4-bit opcode.  */
736
0
      op &= 0x3c;
737
0
    }
738
0
  seg = VLE_OP_TO_SEG (op);
739
740
  /* Find the first match in the opcode table for this major opcode.  */
741
0
  opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
742
0
  for (opcode = vle_opcodes + vle_opcd_indices[seg];
743
0
       opcode < opcode_end;
744
0
       ++opcode)
745
0
    {
746
0
      uint64_t table_opcd = opcode->opcode;
747
0
      uint64_t table_mask = opcode->mask;
748
0
      bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
749
0
      uint64_t insn2;
750
0
      const ppc_opindex_t *opindex;
751
0
      const struct powerpc_operand *operand;
752
0
      int invalid;
753
754
0
      insn2 = insn;
755
0
      if (table_op_is_short)
756
0
  insn2 >>= 16;
757
0
      if ((insn2 & table_mask) != table_opcd
758
0
    || (opcode->deprecated & dialect) != 0)
759
0
  continue;
760
761
      /* Check validity of operands.  */
762
0
      invalid = 0;
763
0
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
764
0
  {
765
0
    operand = powerpc_operands + *opindex;
766
0
    if (operand->extract)
767
0
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
768
0
  }
769
0
      if (invalid)
770
0
  continue;
771
772
0
      return opcode;
773
0
    }
774
775
0
  return NULL;
776
0
}
777
778
/* Find a match for INSN in the LSP opcode table.  */
779
780
static const struct powerpc_opcode *
781
lookup_lsp (uint64_t insn, ppc_cpu_t dialect)
782
1.50M
{
783
1.50M
  const struct powerpc_opcode *opcode, *opcode_end;
784
1.50M
  unsigned op, seg;
785
786
1.50M
  op = PPC_OP (insn);
787
1.50M
  if (op != 0x4)
788
1.50M
    return NULL;
789
790
5.39k
  seg = LSP_OP_TO_SEG (insn);
791
792
  /* Find the first match in the opcode table for this opcode.  */
793
5.39k
  opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1];
794
5.39k
  for (opcode = lsp_opcodes + lsp_opcd_indices[seg];
795
52.0k
       opcode < opcode_end;
796
46.6k
       ++opcode)
797
47.5k
    {
798
47.5k
      const ppc_opindex_t *opindex;
799
47.5k
      const struct powerpc_operand *operand;
800
47.5k
      int invalid;
801
802
47.5k
      if ((insn & opcode->mask) != opcode->opcode
803
47.5k
    || (opcode->deprecated & dialect) != 0)
804
46.3k
  continue;
805
806
      /* Check validity of operands.  */
807
1.19k
      invalid = 0;
808
4.78k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
809
3.58k
  {
810
3.58k
    operand = powerpc_operands + *opindex;
811
3.58k
    if (operand->extract)
812
558
      (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
813
3.58k
  }
814
1.19k
      if (invalid)
815
263
  continue;
816
817
932
      return opcode;
818
1.19k
    }
819
820
4.46k
  return NULL;
821
5.39k
}
822
823
/* Find a match for INSN in the SPE2 opcode table.  */
824
825
static const struct powerpc_opcode *
826
lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
827
1.58M
{
828
1.58M
  const struct powerpc_opcode *opcode, *opcode_end;
829
1.58M
  unsigned op, xop, seg;
830
831
1.58M
  op = PPC_OP (insn);
832
1.58M
  if (op != 0x4)
833
1.57M
    {
834
      /* This is not SPE2 insn.
835
       * All SPE2 instructions have OP=4 and differs by XOP  */
836
1.57M
      return NULL;
837
1.57M
    }
838
13.4k
  xop = SPE2_XOP (insn);
839
13.4k
  seg = SPE2_XOP_TO_SEG (xop);
840
841
  /* Find the first match in the opcode table for this opcode.  */
842
13.4k
  opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
843
13.4k
  for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
844
454k
       opcode < opcode_end;
845
441k
       ++opcode)
846
447k
    {
847
447k
      uint64_t table_opcd = opcode->opcode;
848
447k
      uint64_t table_mask = opcode->mask;
849
447k
      uint64_t insn2;
850
447k
      const ppc_opindex_t *opindex;
851
447k
      const struct powerpc_operand *operand;
852
447k
      int invalid;
853
854
447k
      insn2 = insn;
855
447k
      if ((insn2 & table_mask) != table_opcd
856
447k
    || (opcode->deprecated & dialect) != 0)
857
440k
  continue;
858
859
      /* Check validity of operands.  */
860
6.66k
      invalid = 0;
861
26.7k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
862
20.1k
  {
863
20.1k
    operand = powerpc_operands + *opindex;
864
20.1k
    if (operand->extract)
865
882
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
866
20.1k
  }
867
6.66k
      if (invalid)
868
504
  continue;
869
870
6.16k
      return opcode;
871
6.66k
    }
872
873
7.24k
  return NULL;
874
13.4k
}
875
876
static arelent *
877
bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma)
878
0
{
879
0
  while (lo < hi)
880
0
    {
881
0
      arelent **mid = lo + (hi - lo) / 2;
882
0
      arelent *rel = *mid;
883
884
0
      if (vma < rel->address)
885
0
  hi = mid;
886
0
      else if (vma > rel->address)
887
0
  lo = mid + 1;
888
0
      else
889
0
  return rel;
890
0
    }
891
0
  return NULL;
892
0
}
893
894
static bool
895
print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
896
0
{
897
0
  if (sb->name != NULL)
898
0
    {
899
0
      asection *s = sb->sec;
900
0
      if (s == NULL)
901
0
  {
902
0
    s = bfd_get_section_by_name (info->section->owner, sb->name);
903
0
    sb->sec = s;
904
0
    if (s == NULL)
905
0
      sb->name = NULL;
906
0
  }
907
0
      if (s != NULL
908
0
    && vma >= s->vma
909
0
    && vma < s->vma + s->size)
910
0
  {
911
0
    asymbol *sym = NULL;
912
0
    uint64_t ent = 0;
913
0
    if (info->dynrelcount > 0)
914
0
      {
915
0
        arelent **lo = info->dynrelbuf;
916
0
        arelent **hi = lo + info->dynrelcount;
917
0
        arelent *rel = bsearch_reloc (lo, hi, vma);
918
0
        if (rel != NULL && rel->sym_ptr_ptr != NULL)
919
0
    sym = *rel->sym_ptr_ptr;
920
0
      }
921
0
    if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0)
922
0
      {
923
0
        if (sb->buf == NULL
924
0
      && !bfd_malloc_and_get_section (s->owner, s, &sb->buf))
925
0
    sb->name = NULL;
926
0
        if (sb->buf != NULL)
927
0
    {
928
0
      ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma));
929
0
      if (ent != 0)
930
0
        sym = (*info->symbol_at_address_func) (ent, info);
931
0
    }
932
0
      }
933
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
934
0
    if (sym != NULL)
935
0
      {
936
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
937
0
              "%s", bfd_asymbol_name (sym));
938
0
        (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
939
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
940
0
              "%s", sb->name + 1);
941
0
      }
942
0
    else
943
0
      {
944
0
        (*info->fprintf_styled_func) (info->stream, dis_style_address,
945
0
              "%" PRIx64, ent);
946
0
        (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
947
0
        (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
948
0
              "%s", sb->name + 1);
949
0
      }
950
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
951
0
    return true;
952
0
  }
953
0
    }
954
0
  return false;
955
0
}
956
957
/* Print a PowerPC or POWER instruction.  */
958
959
static int
960
print_insn_powerpc (bfd_vma memaddr,
961
        struct disassemble_info *info,
962
        int bigendian,
963
        ppc_cpu_t dialect)
964
6.63M
{
965
6.63M
  bfd_byte buffer[4];
966
6.63M
  int status;
967
6.63M
  uint64_t insn;
968
6.63M
  const struct powerpc_opcode *opcode;
969
6.63M
  int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
970
971
6.63M
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
972
973
  /* The final instruction may be a 2-byte VLE insn.  */
974
6.63M
  if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
975
0
    {
976
      /* Clear buffer so unused bytes will not have garbage in them.  */
977
0
      buffer[2] = buffer[3] = 0;
978
0
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
979
0
      insn_length = 2;
980
0
    }
981
982
6.63M
  if (status != 0)
983
1.05k
    {
984
1.05k
      (*info->memory_error_func) (status, memaddr, info);
985
1.05k
      return -1;
986
1.05k
    }
987
988
6.63M
  if (bigendian)
989
6.28M
    insn = bfd_getb32 (buffer);
990
349k
  else
991
349k
    insn = bfd_getl32 (buffer);
992
993
  /* Get the major opcode of the insn.  */
994
6.63M
  opcode = NULL;
995
6.63M
  if ((dialect & PPC_OPCODE_POWER10) != 0
996
6.63M
      && PPC_OP (insn) == 0x1)
997
110k
    {
998
110k
      uint64_t temp_insn, suffix;
999
110k
      status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
1000
110k
      if (status == 0)
1001
110k
  {
1002
110k
    if (bigendian)
1003
102k
      suffix = bfd_getb32 (buffer);
1004
8.05k
    else
1005
8.05k
      suffix = bfd_getl32 (buffer);
1006
110k
    temp_insn = (insn << 32) | suffix;
1007
110k
    opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
1008
110k
    if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1009
108k
      opcode = lookup_prefix (temp_insn, dialect);
1010
110k
    if (opcode != NULL)
1011
1.92k
      {
1012
1.92k
        insn = temp_insn;
1013
1.92k
        insn_length = 8;
1014
1.92k
        if ((info->flags & WIDE_OUTPUT) != 0)
1015
0
    info->bytes_per_line = 8;
1016
1.92k
      }
1017
110k
  }
1018
110k
    }
1019
6.63M
  if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
1020
0
    {
1021
0
      opcode = lookup_vle (insn, dialect);
1022
0
      if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
1023
0
  {
1024
    /* The operands will be fetched out of the 16-bit instruction.  */
1025
0
    insn >>= 16;
1026
0
    insn_length = 2;
1027
0
  }
1028
0
    }
1029
6.63M
  if (opcode == NULL && insn_length == 4)
1030
6.63M
    {
1031
6.63M
      if ((dialect & PPC_OPCODE_LSP) != 0)
1032
0
  opcode = lookup_lsp (insn, dialect);
1033
6.63M
      if ((dialect & PPC_OPCODE_SPE2) != 0)
1034
77.7k
  opcode = lookup_spe2 (insn, dialect);
1035
6.63M
      if (opcode == NULL)
1036
6.63M
  opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
1037
6.63M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1038
1.66M
  opcode = lookup_powerpc (insn, dialect);
1039
6.63M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1040
1.51M
  opcode = lookup_spe2 (insn, dialect);
1041
6.63M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1042
1.50M
  opcode = lookup_lsp (insn, dialect);
1043
6.63M
    }
1044
1045
6.63M
  if (opcode != NULL)
1046
3.94M
    {
1047
3.94M
      const ppc_opindex_t *opindex;
1048
3.94M
      const struct powerpc_operand *operand;
1049
3.94M
      enum {
1050
3.94M
  need_comma = 0,
1051
3.94M
  need_1space = 1,
1052
3.94M
  need_2spaces = 2,
1053
3.94M
  need_3spaces = 3,
1054
3.94M
  need_4spaces = 4,
1055
3.94M
  need_5spaces = 5,
1056
3.94M
  need_6spaces = 6,
1057
3.94M
  need_7spaces = 7,
1058
3.94M
  need_paren
1059
3.94M
      } op_separator;
1060
3.94M
      bool skip_optional;
1061
3.94M
      bool is_pcrel;
1062
3.94M
      uint64_t d34;
1063
3.94M
      int blanks;
1064
1065
3.94M
      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1066
3.94M
            "%s", opcode->name);
1067
      /* gdb fprintf_styled_func doesn't return count printed.  */
1068
3.94M
      blanks = 8 - strlen (opcode->name);
1069
3.94M
      if (blanks <= 0)
1070
43.5k
  blanks = 1;
1071
1072
      /* Now extract and print the operands.  */
1073
3.94M
      op_separator = blanks;
1074
3.94M
      skip_optional = false;
1075
3.94M
      is_pcrel = false;
1076
3.94M
      d34 = 0;
1077
15.4M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
1078
11.4M
  {
1079
11.4M
    int64_t value;
1080
1081
11.4M
    operand = powerpc_operands + *opindex;
1082
1083
    /* If all of the optional operands past this one have their
1084
       default value, then don't print any of them.  Except in
1085
       raw mode, print them all.  */
1086
11.4M
    if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
1087
11.4M
        && (dialect & PPC_OPCODE_RAW) == 0)
1088
425k
      {
1089
425k
        if (!skip_optional)
1090
425k
    skip_optional = skip_optional_operands (opindex, insn,
1091
425k
              dialect, &is_pcrel);
1092
425k
        if (skip_optional)
1093
51.8k
    continue;
1094
425k
      }
1095
1096
11.4M
    value = operand_value_powerpc (operand, insn, dialect);
1097
1098
11.4M
    if (op_separator == need_comma)
1099
6.24M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
1100
5.19M
    else if (op_separator == need_paren)
1101
1.30M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
1102
3.88M
    else
1103
3.88M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
1104
3.88M
            op_separator, " ");
1105
1106
    /* Print the operand as directed by the flags.  */
1107
11.4M
    if ((operand->flags & PPC_OPERAND_GPR) != 0
1108
11.4M
        || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
1109
5.82M
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1110
5.82M
            "r%" PRId64, value);
1111
5.61M
    else if ((operand->flags & PPC_OPERAND_FPR) != 0)
1112
839k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1113
839k
            "f%" PRId64, value);
1114
4.77M
    else if ((operand->flags & PPC_OPERAND_VR) != 0)
1115
175k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1116
175k
            "v%" PRId64, value);
1117
4.60M
    else if ((operand->flags & PPC_OPERAND_VSR) != 0)
1118
129k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1119
129k
            "vs%" PRId64, value);
1120
4.47M
    else if ((operand->flags & PPC_OPERAND_DMR) != 0)
1121
154
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1122
154
            "dm%" PRId64, value);
1123
4.47M
    else if ((operand->flags & PPC_OPERAND_ACC) != 0)
1124
237
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1125
237
            "a%" PRId64, value);
1126
4.47M
    else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
1127
284k
      (*info->print_address_func) (memaddr + value, info);
1128
4.18M
    else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
1129
60.0k
      (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
1130
4.12M
    else if ((operand->flags & PPC_OPERAND_FSL) != 0)
1131
0
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1132
0
            "fsl%" PRId64, value);
1133
4.12M
    else if ((operand->flags & PPC_OPERAND_FCR) != 0)
1134
504
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1135
504
            "fcr%" PRId64, value);
1136
4.12M
    else if ((operand->flags & PPC_OPERAND_UDI) != 0)
1137
192
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1138
192
            "%" PRId64, value);
1139
4.12M
    else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
1140
4.12M
       && (operand->flags & PPC_OPERAND_CR_BIT) == 0
1141
4.12M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1142
273k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1143
204k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1144
204k
            "cr%" PRId64, value);
1145
3.92M
    else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1146
3.92M
       && (operand->flags & PPC_OPERAND_CR_REG) == 0
1147
3.92M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1148
72.4k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1149
64.8k
      {
1150
64.8k
        static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1151
64.8k
        int cr;
1152
64.8k
        int cc;
1153
1154
64.8k
        cr = value >> 2;
1155
64.8k
        cc = value & 3;
1156
64.8k
        if (cr != 0)
1157
25.8k
    {
1158
25.8k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1159
25.8k
            "4*");
1160
25.8k
      (*info->fprintf_styled_func) (info->stream,
1161
25.8k
            dis_style_register,
1162
25.8k
            "cr%d", cr);
1163
25.8k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1164
25.8k
            "+");
1165
25.8k
    }
1166
1167
64.8k
        (*info->fprintf_styled_func) (info->stream,
1168
64.8k
              dis_style_sub_mnemonic,
1169
64.8k
              "%s", cbnames[cc]);
1170
64.8k
      }
1171
3.85M
    else
1172
3.85M
      {
1173
        /* An immediate, but what style?  */
1174
3.85M
        enum disassembler_style style;
1175
1176
3.85M
        if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1177
1.30M
    style = dis_style_address_offset;
1178
2.55M
        else
1179
2.55M
    style = dis_style_immediate;
1180
1181
3.85M
        (*info->fprintf_styled_func) (info->stream, style,
1182
3.85M
              "%" PRId64, value);
1183
3.85M
      }
1184
1185
11.4M
    if (operand->shift == 52)
1186
0
      is_pcrel = value != 0;
1187
11.4M
    else if (operand->bitm == UINT64_C (0x3ffffffff))
1188
1.33k
      d34 = value;
1189
1190
11.4M
    if (op_separator == need_paren)
1191
1.30M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1192
1193
11.4M
    op_separator = need_comma;
1194
11.4M
    if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1195
1.30M
      op_separator = need_paren;
1196
11.4M
  }
1197
1198
3.94M
      if (is_pcrel)
1199
63
  {
1200
63
    d34 += memaddr;
1201
63
    (*info->fprintf_styled_func) (info->stream,
1202
63
          dis_style_comment_start,
1203
63
          "\t# %" PRIx64, d34);
1204
63
    asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1205
63
    if (sym)
1206
0
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1207
0
            " <%s>", bfd_asymbol_name (sym));
1208
1209
63
    if (info->private_data != NULL
1210
63
        && info->section != NULL
1211
63
        && info->section->owner != NULL
1212
63
        && (bfd_get_file_flags (info->section->owner)
1213
11
      & (EXEC_P | DYNAMIC)) != 0
1214
63
        && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
1215
11
      == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
1216
0
      {
1217
0
        for (int i = 0; i < 2; i++)
1218
0
    if (print_got_plt (private_data (info)->special + i, d34, info))
1219
0
      break;
1220
0
      }
1221
63
  }
1222
1223
      /* We have found and printed an instruction.  */
1224
3.94M
      return insn_length;
1225
3.94M
    }
1226
1227
  /* We could not find a match.  */
1228
2.69M
  if (insn_length == 4)
1229
2.69M
    (*info->fprintf_styled_func) (info->stream,
1230
2.69M
          dis_style_assembler_directive, ".long");
1231
0
  else
1232
0
    {
1233
0
      (*info->fprintf_styled_func) (info->stream,
1234
0
            dis_style_assembler_directive, ".word");
1235
0
      insn >>= 16;
1236
0
    }
1237
2.69M
  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1238
2.69M
  (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
1239
2.69M
        (unsigned int) insn);
1240
1241
1242
2.69M
  return insn_length;
1243
6.63M
}
1244
1245
const disasm_options_and_args_t *
1246
disassembler_options_powerpc (void)
1247
0
{
1248
0
  static disasm_options_and_args_t *opts_and_args;
1249
1250
0
  if (opts_and_args == NULL)
1251
0
    {
1252
0
      size_t i, num_options = ARRAY_SIZE (ppc_opts);
1253
0
      disasm_options_t *opts;
1254
1255
0
      opts_and_args = XNEW (disasm_options_and_args_t);
1256
0
      opts_and_args->args = NULL;
1257
1258
0
      opts = &opts_and_args->options;
1259
0
      opts->name = XNEWVEC (const char *, num_options + 1);
1260
0
      opts->description = NULL;
1261
0
      opts->arg = NULL;
1262
0
      for (i = 0; i < num_options; i++)
1263
0
  opts->name[i] = ppc_opts[i].opt;
1264
      /* The array we return must be NULL terminated.  */
1265
0
      opts->name[i] = NULL;
1266
0
    }
1267
1268
0
  return opts_and_args;
1269
0
}
1270
1271
void
1272
print_ppc_disassembler_options (FILE *stream)
1273
0
{
1274
0
  unsigned int i, col;
1275
1276
0
  fprintf (stream, _("\n\
1277
0
The following PPC specific disassembler options are supported for use with\n\
1278
0
the -M switch:\n"));
1279
1280
0
  for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
1281
0
    {
1282
0
      col += fprintf (stream, " %s,", ppc_opts[i].opt);
1283
0
      if (col > 66)
1284
0
  {
1285
0
    fprintf (stream, "\n");
1286
0
    col = 0;
1287
0
  }
1288
0
    }
1289
0
  fprintf (stream, "\n");
1290
0
}