Coverage Report

Created: 2026-04-04 08:16

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
662k
{
55
662k
  return (struct dis_private *) info->private_data;
56
662k
}
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
659k
{
304
659k
  ppc_cpu_t dialect = 0;
305
306
659k
  if (info->private_data)
307
659k
    dialect = private_data (info)->dialect;
308
309
  /* Disassemble according to the section headers flags for VLE-mode.  */
310
659k
  if (dialect & PPC_OPCODE_VLE
311
57.4k
      && info->section != NULL && info->section->owner != NULL
312
522
      && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
313
522
      && elf_object_id (info->section->owner) == PPC32_ELF_DATA
314
522
      && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
315
0
    return dialect;
316
659k
  else
317
659k
    return dialect & ~ PPC_OPCODE_VLE;
318
659k
}
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
707
{
325
707
  unsigned int i;
326
327
35.1k
  for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
328
35.1k
    if (strcmp (ppc_opts[i].opt, arg) == 0)
329
707
      {
330
707
  if (ppc_opts[i].sticky)
331
85
    {
332
85
      *sticky |= ppc_opts[i].sticky;
333
85
      if ((ppc_cpu & ~*sticky) != 0)
334
0
        break;
335
85
    }
336
707
  ppc_cpu = ppc_opts[i].cpu;
337
707
  break;
338
707
      }
339
707
  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
707
  if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0)
346
0
    *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2);
347
707
  else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0)
348
0
    *sticky &= ~PPC_OPCODE_LSP;
349
707
  ppc_cpu |= *sticky;
350
351
707
  return ppc_cpu;
352
707
}
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
707
{
383
707
  struct ppc_parse_data out = { 0, 0 };
384
707
  struct dis_private *priv = calloc (1, sizeof (*priv));
385
386
707
  if (priv == NULL)
387
0
    return;
388
389
707
  switch (info->mach)
390
707
    {
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
2
    case bfd_mach_ppc_a35:
405
3
    case bfd_mach_ppc_rs64ii:
406
5
    case bfd_mach_ppc_rs64iii:
407
5
      out.dialect = (ppc_parse_cpu (out.dialect, &out.sticky, "pwr2")
408
5
         | PPC_OPCODE_64);
409
5
      break;
410
7
    case bfd_mach_ppc_e500:
411
7
      out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e500");
412
7
      break;
413
0
    case bfd_mach_ppc_e500mc:
414
0
      out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e500mc");
415
0
      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
1
    case bfd_mach_ppc_e6500:
423
1
      out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "e6500");
424
1
      break;
425
1
    case bfd_mach_ppc_titan:
426
1
      out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "titan");
427
1
      break;
428
85
    case bfd_mach_ppc_vle:
429
85
      out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "vle");
430
85
      break;
431
604
    default:
432
604
      if (info->arch == bfd_arch_powerpc)
433
544
  out.dialect = (ppc_parse_cpu (out.dialect, &out.sticky, "power11")
434
544
           | PPC_OPCODE_ANY);
435
60
      else
436
60
  out.dialect = ppc_parse_cpu (out.dialect, &out.sticky, "pwr");
437
604
      break;
438
707
    }
439
440
707
  for_each_disassembler_option (info, ppc_parse_option, &out);
441
442
707
  info->private_data = priv;
443
707
  private_data (info)->dialect = out.dialect;
444
707
}
445
446
839
#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
389
{
461
389
  elf_symbol_type * est;
462
463
389
  if (sym == NULL)
464
0
    return false;
465
466
389
  est = elf_symbol_from (sym);
467
468
  /* Ignore ELF hidden, local, no-type symbols.
469
     These are generated by annobin.  */
470
389
  if (est != NULL
471
389
      && 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
389
  return true;
477
389
}
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
707
{
485
707
  info->symbol_is_valid = ppc_symbol_is_valid;
486
487
707
  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
707
  powerpc_init_dialect (info);
544
707
  if (info->private_data != NULL)
545
707
    {
546
707
      private_data (info)->special[0].name = ".got";
547
707
      private_data (info)->special[1].name = ".plt";
548
707
    }
549
707
}
550
551
void
552
disassemble_free_powerpc (struct disassemble_info *info)
553
647
{
554
647
  if (info->private_data != NULL)
555
647
    {
556
647
      free (private_data (info)->special[0].buf);
557
647
      free (private_data (info)->special[1].buf);
558
647
    }
559
647
}
560
561
/* Print a big endian PowerPC instruction.  */
562
563
int
564
print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
565
337k
{
566
337k
  return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
567
337k
}
568
569
/* Print a little endian PowerPC instruction.  */
570
571
int
572
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
573
321k
{
574
321k
  return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
575
321k
}
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.24M
{
583
1.24M
  int64_t value;
584
1.24M
  int invalid = 0;
585
  /* Extract the value from the instruction.  */
586
1.24M
  if (operand->extract)
587
111k
    value = (*operand->extract) (insn, dialect, &invalid);
588
1.13M
  else
589
1.13M
    {
590
1.13M
      if (operand->shift >= 0)
591
1.13M
  value = (insn >> operand->shift) & operand->bitm;
592
0
      else
593
0
  value = (insn << -operand->shift) & operand->bitm;
594
1.13M
      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
595
237k
  {
596
    /* BITM is always some number of zeros followed by some
597
       number of ones, followed by some number of zeros.  */
598
237k
    uint64_t top = operand->bitm;
599
    /* top & -top gives the rightmost 1 bit, so this
600
       fills in any trailing zeros.  */
601
237k
    top |= (top & -top) - 1;
602
237k
    top &= ~(top >> 1);
603
237k
    value = (value ^ top) - top;
604
237k
  }
605
1.13M
    }
606
607
1.24M
  if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
608
0
    ++value;
609
610
1.24M
  return value;
611
1.24M
}
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
44.7k
{
619
44.7k
  const struct powerpc_operand *operand;
620
44.7k
  int num_optional;
621
622
60.1k
  for (num_optional = 0; *opindex != 0; opindex++)
623
54.2k
    {
624
54.2k
      operand = &powerpc_operands[*opindex];
625
54.2k
      if ((operand->flags & PPC_OPERAND_NEXT) != 0)
626
24.3k
  return false;
627
29.9k
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
628
20.7k
  {
629
20.7k
    int64_t value = operand_value_powerpc (operand, insn, dialect);
630
631
20.7k
    if (operand->shift == 52)
632
1.22k
      *is_pcrel = value != 0;
633
634
    /* Negative count is used as a flag to extract function.  */
635
20.7k
    --num_optional;
636
20.7k
    if (value != ppc_optional_operand_value (operand, insn, dialect,
637
20.7k
               num_optional))
638
14.5k
      return false;
639
20.7k
  }
640
29.9k
    }
641
642
5.85k
  return true;
643
44.7k
}
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
922k
{
650
922k
  const struct powerpc_opcode *opcode, *opcode_end;
651
922k
  unsigned long op;
652
653
  /* Get the major opcode of the instruction.  */
654
922k
  op = PPC_OP (insn);
655
656
  /* Find the first match in the opcode table for this major opcode.  */
657
922k
  opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
658
922k
  for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
659
54.7M
       opcode < opcode_end;
660
53.8M
       ++opcode)
661
54.2M
    {
662
54.2M
      const ppc_opindex_t *opindex;
663
54.2M
      const struct powerpc_operand *operand;
664
54.2M
      int invalid;
665
666
54.2M
      if ((insn & opcode->mask) != opcode->opcode
667
533k
    || ((dialect & PPC_OPCODE_ANY) == 0
668
484k
        && ((opcode->flags & dialect) == 0
669
402k
      || (opcode->deprecated & dialect) != 0))
670
434k
    || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
671
53.7M
  continue;
672
673
      /* Check validity of operands.  */
674
434k
      invalid = 0;
675
1.79M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
676
1.35M
  {
677
1.35M
    operand = powerpc_operands + *opindex;
678
1.35M
    if (operand->extract)
679
181k
      (*operand->extract) (insn, dialect, &invalid);
680
1.35M
  }
681
434k
      if (invalid)
682
49.5k
  continue;
683
684
385k
      return opcode;
685
434k
    }
686
687
536k
  return NULL;
688
922k
}
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
25.9k
{
695
25.9k
  const struct powerpc_opcode *opcode, *opcode_end;
696
25.9k
  unsigned long seg;
697
698
  /* Get the opcode segment of the instruction.  */
699
25.9k
  seg = PPC_PREFIX_SEG (insn);
700
701
  /* Find the first match in the opcode table for this major opcode.  */
702
25.9k
  opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
703
25.9k
  for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
704
75.5k
       opcode < opcode_end;
705
49.6k
       ++opcode)
706
50.7k
    {
707
50.7k
      const ppc_opindex_t *opindex;
708
50.7k
      const struct powerpc_operand *operand;
709
50.7k
      int invalid;
710
711
50.7k
      if ((insn & opcode->mask) != opcode->opcode
712
1.79k
    || ((dialect & PPC_OPCODE_ANY) == 0
713
1.56k
        && (opcode->flags & dialect) == 0)
714
1.50k
    || (opcode->deprecated & dialect) != 0)
715
49.2k
  continue;
716
717
      /* Check validity of operands.  */
718
1.50k
      invalid = 0;
719
7.09k
      for (opindex = opcode->operands; *opindex != 0; opindex++)
720
5.59k
  {
721
5.59k
    operand = powerpc_operands + *opindex;
722
5.59k
    if (operand->extract)
723
3.15k
      (*operand->extract) (insn, dialect, &invalid);
724
5.59k
  }
725
1.50k
      if (invalid)
726
373
  continue;
727
728
1.13k
      return opcode;
729
1.50k
    }
730
731
24.7k
  return NULL;
732
25.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
0
{
739
0
  const struct powerpc_opcode *opcode;
740
0
  const struct powerpc_opcode *opcode_end;
741
0
  unsigned op, seg;
742
743
0
  op = PPC_OP (insn);
744
0
  if (op >= 0x20 && op <= 0x37)
745
0
    {
746
      /* This insn has a 4-bit opcode.  */
747
0
      op &= 0x3c;
748
0
    }
749
0
  seg = VLE_OP_TO_SEG (op);
750
751
  /* Find the first match in the opcode table for this major opcode.  */
752
0
  opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
753
0
  for (opcode = vle_opcodes + vle_opcd_indices[seg];
754
0
       opcode < opcode_end;
755
0
       ++opcode)
756
0
    {
757
0
      uint64_t table_opcd = opcode->opcode;
758
0
      uint64_t table_mask = opcode->mask;
759
0
      bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
760
0
      uint64_t insn2;
761
0
      const ppc_opindex_t *opindex;
762
0
      const struct powerpc_operand *operand;
763
0
      int invalid;
764
765
0
      insn2 = insn;
766
0
      if (table_op_is_short)
767
0
  insn2 >>= 16;
768
0
      if ((insn2 & table_mask) != table_opcd
769
0
    || (opcode->deprecated & dialect) != 0)
770
0
  continue;
771
772
      /* Check validity of operands.  */
773
0
      invalid = 0;
774
0
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
775
0
  {
776
0
    operand = powerpc_operands + *opindex;
777
0
    if (operand->extract)
778
0
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
779
0
  }
780
0
      if (invalid)
781
0
  continue;
782
783
0
      return opcode;
784
0
    }
785
786
0
  return NULL;
787
0
}
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
227k
{
794
227k
  const struct powerpc_opcode *opcode, *opcode_end;
795
227k
  unsigned op, seg;
796
797
227k
  op = PPC_OP (insn);
798
227k
  if (op != 0x4)
799
226k
    return NULL;
800
801
1.31k
  seg = LSP_OP_TO_SEG (insn);
802
803
  /* Find the first match in the opcode table for this opcode.  */
804
1.31k
  opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1];
805
1.31k
  for (opcode = lsp_opcodes + lsp_opcd_indices[seg];
806
31.8k
       opcode < opcode_end;
807
30.5k
       ++opcode)
808
30.6k
    {
809
30.6k
      const ppc_opindex_t *opindex;
810
30.6k
      const struct powerpc_operand *operand;
811
30.6k
      int invalid;
812
813
30.6k
      if ((insn & opcode->mask) != opcode->opcode
814
563
    || (opcode->deprecated & dialect) != 0)
815
30.1k
  continue;
816
817
      /* Check validity of operands.  */
818
563
      invalid = 0;
819
2.25k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
820
1.68k
  {
821
1.68k
    operand = powerpc_operands + *opindex;
822
1.68k
    if (operand->extract)
823
591
      (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
824
1.68k
  }
825
563
      if (invalid)
826
410
  continue;
827
828
153
      return opcode;
829
563
    }
830
831
1.16k
  return NULL;
832
1.31k
}
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
287k
{
839
287k
  const struct powerpc_opcode *opcode, *opcode_end;
840
287k
  unsigned op, xop, seg;
841
842
287k
  op = PPC_OP (insn);
843
287k
  if (op != 0x4)
844
280k
    {
845
      /* This is not SPE2 insn.
846
       * All SPE2 instructions have OP=4 and differs by XOP  */
847
280k
      return NULL;
848
280k
    }
849
7.10k
  xop = SPE2_XOP (insn);
850
7.10k
  seg = SPE2_XOP_TO_SEG (xop);
851
852
  /* Find the first match in the opcode table for this opcode.  */
853
7.10k
  opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
854
7.10k
  for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
855
285k
       opcode < opcode_end;
856
277k
       ++opcode)
857
281k
    {
858
281k
      uint64_t table_opcd = opcode->opcode;
859
281k
      uint64_t table_mask = opcode->mask;
860
281k
      uint64_t insn2;
861
281k
      const ppc_opindex_t *opindex;
862
281k
      const struct powerpc_operand *operand;
863
281k
      int invalid;
864
865
281k
      insn2 = insn;
866
281k
      if ((insn2 & table_mask) != table_opcd
867
3.74k
    || (opcode->deprecated & dialect) != 0)
868
277k
  continue;
869
870
      /* Check validity of operands.  */
871
3.74k
      invalid = 0;
872
15.0k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
873
11.3k
  {
874
11.3k
    operand = powerpc_operands + *opindex;
875
11.3k
    if (operand->extract)
876
709
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
877
11.3k
  }
878
3.74k
      if (invalid)
879
364
  continue;
880
881
3.38k
      return opcode;
882
3.74k
    }
883
884
3.72k
  return NULL;
885
7.10k
}
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
659k
{
976
659k
  bfd_byte buffer[4];
977
659k
  int status;
978
659k
  uint64_t insn;
979
659k
  const struct powerpc_opcode *opcode;
980
659k
  int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
981
982
659k
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
983
984
  /* The final instruction may be a 2-byte VLE insn.  */
985
659k
  if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
986
0
    {
987
      /* Clear buffer so unused bytes will not have garbage in them.  */
988
0
      buffer[2] = buffer[3] = 0;
989
0
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
990
0
      insn_length = 2;
991
0
    }
992
993
659k
  if (status != 0)
994
535
    {
995
535
      (*info->memory_error_func) (status, memaddr, info);
996
535
      return -1;
997
535
    }
998
999
658k
  if (bigendian)
1000
337k
    insn = bfd_getb32 (buffer);
1001
320k
  else
1002
320k
    insn = bfd_getl32 (buffer);
1003
1004
  /* Get the major opcode of the insn.  */
1005
658k
  opcode = NULL;
1006
658k
  if ((dialect & PPC_OPCODE_POWER10) != 0
1007
578k
      && PPC_OP (insn) == 0x1)
1008
13.4k
    {
1009
13.4k
      uint64_t temp_insn, suffix;
1010
13.4k
      status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
1011
13.4k
      if (status == 0)
1012
13.4k
  {
1013
13.4k
    if (bigendian)
1014
6.97k
      suffix = bfd_getb32 (buffer);
1015
6.49k
    else
1016
6.49k
      suffix = bfd_getl32 (buffer);
1017
13.4k
    temp_insn = (insn << 32) | suffix;
1018
13.4k
    opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
1019
13.4k
    if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1020
12.4k
      opcode = lookup_prefix (temp_insn, dialect);
1021
13.4k
    if (opcode != NULL)
1022
1.13k
      {
1023
1.13k
        insn = temp_insn;
1024
1.13k
        insn_length = 8;
1025
1.13k
        if ((info->flags & WIDE_OUTPUT) != 0)
1026
0
    info->bytes_per_line = 8;
1027
1.13k
      }
1028
13.4k
  }
1029
13.4k
    }
1030
658k
  if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
1031
0
    {
1032
0
      opcode = lookup_vle (insn, dialect);
1033
0
      if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
1034
0
  {
1035
    /* The operands will be fetched out of the 16-bit instruction.  */
1036
0
    insn >>= 16;
1037
0
    insn_length = 2;
1038
0
  }
1039
0
    }
1040
658k
  if (opcode == NULL && insn_length == 4)
1041
657k
    {
1042
657k
      if ((dialect & PPC_OPCODE_LSP) != 0)
1043
0
  opcode = lookup_lsp (insn, dialect);
1044
657k
      if ((dialect & PPC_OPCODE_SPE2) != 0)
1045
57.3k
  opcode = lookup_spe2 (insn, dialect);
1046
657k
      if (opcode == NULL)
1047
656k
  opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
1048
657k
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1049
265k
  opcode = lookup_powerpc (insn, dialect);
1050
657k
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1051
230k
  opcode = lookup_spe2 (insn, dialect);
1052
657k
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1053
227k
  opcode = lookup_lsp (insn, dialect);
1054
657k
    }
1055
1056
658k
  if (opcode != NULL)
1057
389k
    {
1058
389k
      const ppc_opindex_t *opindex;
1059
389k
      const struct powerpc_operand *operand;
1060
389k
      enum {
1061
389k
  need_comma = 0,
1062
389k
  need_1space = 1,
1063
389k
  need_2spaces = 2,
1064
389k
  need_3spaces = 3,
1065
389k
  need_4spaces = 4,
1066
389k
  need_5spaces = 5,
1067
389k
  need_6spaces = 6,
1068
389k
  need_7spaces = 7,
1069
389k
  need_paren
1070
389k
      } op_separator;
1071
389k
      bool skip_optional;
1072
389k
      bool is_pcrel;
1073
389k
      uint64_t d34;
1074
389k
      int blanks;
1075
1076
389k
      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1077
389k
            "%s", opcode->name);
1078
      /* gdb fprintf_styled_func doesn't return count printed.  */
1079
389k
      blanks = 8 - strlen (opcode->name);
1080
389k
      if (blanks <= 0)
1081
10.4k
  blanks = 1;
1082
1083
      /* Now extract and print the operands.  */
1084
389k
      op_separator = blanks;
1085
389k
      skip_optional = false;
1086
389k
      is_pcrel = false;
1087
389k
      d34 = 0;
1088
1.61M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
1089
1.22M
  {
1090
1.22M
    int64_t value;
1091
1092
1.22M
    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.22M
    if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
1098
44.9k
        && (dialect & PPC_OPCODE_RAW) == 0)
1099
44.9k
      {
1100
44.9k
        if (!skip_optional)
1101
44.7k
    skip_optional = skip_optional_operands (opindex, insn,
1102
44.7k
              dialect, &is_pcrel);
1103
44.9k
        if (skip_optional)
1104
6.00k
    continue;
1105
44.9k
      }
1106
1107
1.22M
    value = operand_value_powerpc (operand, insn, dialect);
1108
1109
1.22M
    if (op_separator == need_comma)
1110
693k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
1111
527k
    else if (op_separator == need_paren)
1112
140k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
1113
386k
    else
1114
386k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
1115
386k
            op_separator, " ");
1116
1117
    /* Print the operand as directed by the flags.  */
1118
1.22M
    if ((operand->flags & PPC_OPERAND_GPR) != 0
1119
792k
        || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
1120
556k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1121
556k
            "r%" PRId64, value);
1122
664k
    else if ((operand->flags & PPC_OPERAND_FPR) != 0)
1123
140k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1124
140k
            "f%" PRId64, value);
1125
524k
    else if ((operand->flags & PPC_OPERAND_VR) != 0)
1126
36.4k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1127
36.4k
            "v%" PRId64, value);
1128
487k
    else if ((operand->flags & PPC_OPERAND_VSR) != 0)
1129
27.4k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1130
27.4k
            "vs%" PRId64, value);
1131
460k
    else if ((operand->flags & PPC_OPERAND_DMR) != 0)
1132
76
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1133
76
            "dm%" PRId64, value);
1134
460k
    else if ((operand->flags & PPC_OPERAND_ACC) != 0)
1135
32
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1136
32
            "a%" PRId64, value);
1137
460k
    else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
1138
10.3k
      (*info->print_address_func) (memaddr + value, info);
1139
450k
    else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
1140
16.1k
      (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
1141
433k
    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
433k
    else if ((operand->flags & PPC_OPERAND_FCR) != 0)
1145
28
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1146
28
            "fcr%" PRId64, value);
1147
433k
    else if ((operand->flags & PPC_OPERAND_UDI) != 0)
1148
177
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1149
177
            "%" PRId64, value);
1150
433k
    else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
1151
16.7k
       && (operand->flags & PPC_OPERAND_CR_BIT) == 0
1152
16.7k
       && (((dialect & PPC_OPCODE_PPC) != 0)
1153
1.05k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1154
15.6k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1155
15.6k
            "cr%" PRId64, value);
1156
418k
    else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1157
16.8k
       && (operand->flags & PPC_OPERAND_CR_REG) == 0
1158
16.8k
       && (((dialect & PPC_OPCODE_PPC) != 0)
1159
686
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1160
16.1k
      {
1161
16.1k
        static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1162
16.1k
        int cr;
1163
16.1k
        int cc;
1164
1165
16.1k
        cr = value >> 2;
1166
16.1k
        cc = value & 3;
1167
16.1k
        if (cr != 0)
1168
3.87k
    {
1169
3.87k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1170
3.87k
            "4*");
1171
3.87k
      (*info->fprintf_styled_func) (info->stream,
1172
3.87k
            dis_style_register,
1173
3.87k
            "cr%d", cr);
1174
3.87k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1175
3.87k
            "+");
1176
3.87k
    }
1177
1178
16.1k
        (*info->fprintf_styled_func) (info->stream,
1179
16.1k
              dis_style_sub_mnemonic,
1180
16.1k
              "%s", cbnames[cc]);
1181
16.1k
      }
1182
401k
    else
1183
401k
      {
1184
        /* An immediate, but what style?  */
1185
401k
        enum disassembler_style style;
1186
1187
401k
        if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1188
140k
    style = dis_style_address_offset;
1189
260k
        else
1190
260k
    style = dis_style_immediate;
1191
1192
401k
        (*info->fprintf_styled_func) (info->stream, style,
1193
401k
              "%" PRId64, value);
1194
401k
      }
1195
1196
1.22M
    if (operand->shift == 52)
1197
93
      is_pcrel = value != 0;
1198
1.22M
    else if (operand->bitm == UINT64_C (0x3ffffffff))
1199
908
      d34 = value;
1200
1201
1.22M
    if (op_separator == need_paren)
1202
140k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1203
1204
1.22M
    op_separator = need_comma;
1205
1.22M
    if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1206
140k
      op_separator = need_paren;
1207
1.22M
  }
1208
1209
389k
      if (is_pcrel)
1210
227
  {
1211
227
    d34 += memaddr;
1212
227
    (*info->fprintf_styled_func) (info->stream,
1213
227
          dis_style_comment_start,
1214
227
          "\t# %" PRIx64, d34);
1215
227
    asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1216
227
    if (sym)
1217
0
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1218
0
            " <%s>", bfd_asymbol_name (sym));
1219
1220
227
    if (info->private_data != NULL
1221
227
        && info->section != NULL
1222
1
        && info->section->owner != NULL
1223
1
        && (bfd_get_file_flags (info->section->owner)
1224
1
      & (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
227
  }
1233
1234
      /* We have found and printed an instruction.  */
1235
389k
      return insn_length;
1236
389k
    }
1237
1238
  /* We could not find a match.  */
1239
268k
  if (insn_length == 4)
1240
268k
    (*info->fprintf_styled_func) (info->stream,
1241
268k
          dis_style_assembler_directive, ".long");
1242
0
  else
1243
0
    {
1244
0
      (*info->fprintf_styled_func) (info->stream,
1245
0
            dis_style_assembler_directive, ".word");
1246
0
      insn >>= 16;
1247
0
    }
1248
268k
  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1249
268k
  (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
1250
268k
        (unsigned int) insn);
1251
1252
1253
268k
  return insn_length;
1254
658k
}
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
}