Coverage Report

Created: 2026-07-25 10:20

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