Coverage Report

Created: 2023-08-28 06:30

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