Coverage Report

Created: 2024-05-21 06:29

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