Coverage Report

Created: 2023-06-29 07:13

/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
3.17M
{
55
3.17M
  return (struct dis_private *) info->private_data;
56
3.17M
}
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
3.16M
{
294
3.16M
  ppc_cpu_t dialect = 0;
295
296
3.16M
  if (info->private_data)
297
3.16M
    dialect = private_data (info)->dialect;
298
299
  /* Disassemble according to the section headers flags for VLE-mode.  */
300
3.16M
  if (dialect & PPC_OPCODE_VLE
301
3.16M
      && info->section != NULL && info->section->owner != NULL
302
3.16M
      && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
303
3.16M
      && elf_object_id (info->section->owner) == PPC32_ELF_DATA
304
3.16M
      && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
305
0
    return dialect;
306
3.16M
  else
307
3.16M
    return dialect & ~ PPC_OPCODE_VLE;
308
3.16M
}
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
841
{
315
841
  unsigned int i;
316
317
41.7k
  for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
318
41.7k
    if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
319
841
      {
320
841
  if (ppc_opts[i].sticky)
321
88
    {
322
88
      *sticky |= ppc_opts[i].sticky;
323
88
      if ((ppc_cpu & ~*sticky) != 0)
324
0
        break;
325
88
    }
326
841
  ppc_cpu = ppc_opts[i].cpu;
327
841
  break;
328
841
      }
329
841
  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
841
  if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0)
336
0
    *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2);
337
841
  else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0)
338
0
    *sticky &= ~PPC_OPCODE_LSP;
339
841
  ppc_cpu |= *sticky;
340
341
841
  return ppc_cpu;
342
841
}
343
344
/* Determine which set of machines to disassemble for.  */
345
346
static void
347
powerpc_init_dialect (struct disassemble_info *info)
348
841
{
349
841
  ppc_cpu_t dialect = 0;
350
841
  ppc_cpu_t sticky = 0;
351
841
  struct dis_private *priv = calloc (sizeof (*priv), 1);
352
353
841
  if (priv == NULL)
354
0
    return;
355
356
841
  switch (info->mach)
357
841
    {
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
3
    case bfd_mach_ppc_601:
366
3
      dialect = ppc_parse_cpu (dialect, &sticky, "601");
367
3
      break;
368
0
    case bfd_mach_ppc_750:
369
0
      dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
370
0
      break;
371
1
    case bfd_mach_ppc_a35:
372
1
    case bfd_mach_ppc_rs64ii:
373
1
    case bfd_mach_ppc_rs64iii:
374
1
      dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
375
1
      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
4
    case bfd_mach_ppc_titan:
392
4
      dialect = ppc_parse_cpu (dialect, &sticky, "titan");
393
4
      break;
394
88
    case bfd_mach_ppc_vle:
395
88
      dialect = ppc_parse_cpu (dialect, &sticky, "vle");
396
88
      break;
397
745
    default:
398
745
      if (info->arch == bfd_arch_powerpc)
399
571
  dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
400
174
      else
401
174
  dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
402
745
      break;
403
841
    }
404
405
841
  const char *opt;
406
841
  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
841
  info->private_data = priv;
422
841
  private_data (info)->dialect = dialect;
423
841
}
424
425
973
#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
426
static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
427
68
#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
428
static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
429
68
#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
68
#define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1))
432
static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1];
433
36
#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
841
{
464
841
  info->symbol_is_valid = ppc_symbol_is_valid;
465
466
841
  if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
467
2
    {
468
2
      unsigned seg, idx, op;
469
470
      /* PPC opcodes */
471
132
      for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
472
130
  {
473
130
    powerpc_opcd_indices[seg] = idx;
474
8.14k
    for (; idx < powerpc_num_opcodes; idx++)
475
8.14k
      if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
476
126
        break;
477
130
  }
478
479
      /* 64-bit prefix opcodes */
480
68
      for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
481
66
  {
482
66
    prefix_opcd_indices[seg] = idx;
483
284
    for (; idx < prefix_num_opcodes; idx++)
484
280
      if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
485
62
        break;
486
66
  }
487
488
      /* VLE opcodes */
489
68
      for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
490
66
  {
491
66
    vle_opcd_indices[seg] = idx;
492
512
    for (; idx < vle_num_opcodes; idx++)
493
504
      {
494
504
        op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
495
504
        if (seg < VLE_OP_TO_SEG (op))
496
58
    break;
497
504
      }
498
66
  }
499
500
      /* LSP opcodes */
501
68
      for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++)
502
66
  {
503
66
    lsp_opcd_indices[seg] = idx;
504
1.42k
    for (; idx < lsp_num_opcodes; idx++)
505
1.41k
      if (seg < LSP_OP_TO_SEG (lsp_opcodes[idx].opcode))
506
54
        break;
507
66
  }
508
509
      /* SPE2 opcodes */
510
36
      for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
511
34
  {
512
34
    spe2_opcd_indices[seg] = idx;
513
1.61k
    for (; idx < spe2_num_opcodes; idx++)
514
1.60k
      {
515
1.60k
        op = SPE2_XOP (spe2_opcodes[idx].opcode);
516
1.60k
        if (seg < SPE2_XOP_TO_SEG (op))
517
24
    break;
518
1.60k
      }
519
34
  }
520
2
    }
521
522
841
  powerpc_init_dialect (info);
523
841
  if (info->private_data != NULL)
524
841
    {
525
841
      private_data (info)->special[0].name = ".got";
526
841
      private_data (info)->special[1].name = ".plt";
527
841
    }
528
841
}
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.65M
{
535
1.65M
  return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
536
1.65M
}
537
538
/* Print a little endian PowerPC instruction.  */
539
540
int
541
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
542
1.51M
{
543
1.51M
  return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
544
1.51M
}
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.05M
{
552
6.05M
  int64_t value;
553
6.05M
  int invalid = 0;
554
  /* Extract the value from the instruction.  */
555
6.05M
  if (operand->extract)
556
451k
    value = (*operand->extract) (insn, dialect, &invalid);
557
5.60M
  else
558
5.60M
    {
559
5.60M
      if (operand->shift >= 0)
560
5.60M
  value = (insn >> operand->shift) & operand->bitm;
561
0
      else
562
0
  value = (insn << -operand->shift) & operand->bitm;
563
5.60M
      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
564
1.26M
  {
565
    /* BITM is always some number of zeros followed by some
566
       number of ones, followed by some number of zeros.  */
567
1.26M
    uint64_t top = operand->bitm;
568
    /* top & -top gives the rightmost 1 bit, so this
569
       fills in any trailing zeros.  */
570
1.26M
    top |= (top & -top) - 1;
571
1.26M
    top &= ~(top >> 1);
572
1.26M
    value = (value ^ top) - top;
573
1.26M
  }
574
5.60M
    }
575
576
6.05M
  if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
577
0
    ++value;
578
579
6.05M
  return value;
580
6.05M
}
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
218k
{
588
218k
  const struct powerpc_operand *operand;
589
218k
  int num_optional;
590
591
275k
  for (num_optional = 0; *opindex != 0; opindex++)
592
250k
    {
593
250k
      operand = &powerpc_operands[*opindex];
594
250k
      if ((operand->flags & PPC_OPERAND_NEXT) != 0)
595
97.4k
  return false;
596
153k
      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
597
121k
  {
598
121k
    int64_t value = operand_value_powerpc (operand, insn, dialect);
599
600
121k
    if (operand->shift == 52)
601
1.08k
      *is_pcrel = value != 0;
602
603
    /* Negative count is used as a flag to extract function.  */
604
121k
    --num_optional;
605
121k
    if (value != ppc_optional_operand_value (operand, insn, dialect,
606
121k
               num_optional))
607
96.8k
      return false;
608
121k
  }
609
153k
    }
610
611
24.5k
  return true;
612
218k
}
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
4.41M
{
619
4.41M
  const struct powerpc_opcode *opcode, *opcode_end;
620
4.41M
  unsigned long op;
621
622
  /* Get the major opcode of the instruction.  */
623
4.41M
  op = PPC_OP (insn);
624
625
  /* Find the first match in the opcode table for this major opcode.  */
626
4.41M
  opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
627
4.41M
  for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
628
254M
       opcode < opcode_end;
629
250M
       ++opcode)
630
252M
    {
631
252M
      const ppc_opindex_t *opindex;
632
252M
      const struct powerpc_operand *operand;
633
252M
      int invalid;
634
635
252M
      if ((insn & opcode->mask) != opcode->opcode
636
252M
    || ((dialect & PPC_OPCODE_ANY) == 0
637
2.52M
        && ((opcode->flags & dialect) == 0
638
2.32M
      || (opcode->deprecated & dialect) != 0))
639
252M
    || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0)
640
250M
  continue;
641
642
      /* Check validity of operands.  */
643
2.20M
      invalid = 0;
644
8.69M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
645
6.48M
  {
646
6.48M
    operand = powerpc_operands + *opindex;
647
6.48M
    if (operand->extract)
648
714k
      (*operand->extract) (insn, dialect, &invalid);
649
6.48M
  }
650
2.20M
      if (invalid)
651
206k
  continue;
652
653
2.00M
      return opcode;
654
2.20M
    }
655
656
2.41M
  return NULL;
657
4.41M
}
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
129k
{
664
129k
  const struct powerpc_opcode *opcode, *opcode_end;
665
129k
  unsigned long seg;
666
667
  /* Get the opcode segment of the instruction.  */
668
129k
  seg = PPC_PREFIX_SEG (insn);
669
670
  /* Find the first match in the opcode table for this major opcode.  */
671
129k
  opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
672
129k
  for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
673
482k
       opcode < opcode_end;
674
353k
       ++opcode)
675
354k
    {
676
354k
      const ppc_opindex_t *opindex;
677
354k
      const struct powerpc_operand *operand;
678
354k
      int invalid;
679
680
354k
      if ((insn & opcode->mask) != opcode->opcode
681
354k
    || ((dialect & PPC_OPCODE_ANY) == 0
682
1.80k
        && (opcode->flags & dialect) == 0)
683
354k
    || (opcode->deprecated & dialect) != 0)
684
352k
  continue;
685
686
      /* Check validity of operands.  */
687
1.80k
      invalid = 0;
688
7.96k
      for (opindex = opcode->operands; *opindex != 0; opindex++)
689
6.16k
  {
690
6.16k
    operand = powerpc_operands + *opindex;
691
6.16k
    if (operand->extract)
692
3.64k
      (*operand->extract) (insn, dialect, &invalid);
693
6.16k
  }
694
1.80k
      if (invalid)
695
559
  continue;
696
697
1.24k
      return opcode;
698
1.80k
    }
699
700
127k
  return NULL;
701
129k
}
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
1.09M
{
763
1.09M
  const struct powerpc_opcode *opcode, *opcode_end;
764
1.09M
  unsigned op, seg;
765
766
1.09M
  op = PPC_OP (insn);
767
1.09M
  if (op != 0x4)
768
1.09M
    return NULL;
769
770
4.14k
  seg = LSP_OP_TO_SEG (insn);
771
772
  /* Find the first match in the opcode table for this opcode.  */
773
4.14k
  opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1];
774
4.14k
  for (opcode = lsp_opcodes + lsp_opcd_indices[seg];
775
43.8k
       opcode < opcode_end;
776
39.6k
       ++opcode)
777
40.4k
    {
778
40.4k
      const ppc_opindex_t *opindex;
779
40.4k
      const struct powerpc_operand *operand;
780
40.4k
      int invalid;
781
782
40.4k
      if ((insn & opcode->mask) != opcode->opcode
783
40.4k
    || (opcode->deprecated & dialect) != 0)
784
39.4k
  continue;
785
786
      /* Check validity of operands.  */
787
918
      invalid = 0;
788
3.67k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
789
2.75k
  {
790
2.75k
    operand = powerpc_operands + *opindex;
791
2.75k
    if (operand->extract)
792
650
      (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid);
793
2.75k
  }
794
918
      if (invalid)
795
171
  continue;
796
797
747
      return opcode;
798
918
    }
799
800
3.39k
  return NULL;
801
4.14k
}
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
1.18M
{
808
1.18M
  const struct powerpc_opcode *opcode, *opcode_end;
809
1.18M
  unsigned op, xop, seg;
810
811
1.18M
  op = PPC_OP (insn);
812
1.18M
  if (op != 0x4)
813
1.17M
    {
814
      /* This is not SPE2 insn.
815
       * All SPE2 instructions have OP=4 and differs by XOP  */
816
1.17M
      return NULL;
817
1.17M
    }
818
11.1k
  xop = SPE2_XOP (insn);
819
11.1k
  seg = SPE2_XOP_TO_SEG (xop);
820
821
  /* Find the first match in the opcode table for this opcode.  */
822
11.1k
  opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
823
11.1k
  for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
824
433k
       opcode < opcode_end;
825
422k
       ++opcode)
826
427k
    {
827
427k
      uint64_t table_opcd = opcode->opcode;
828
427k
      uint64_t table_mask = opcode->mask;
829
427k
      uint64_t insn2;
830
427k
      const ppc_opindex_t *opindex;
831
427k
      const struct powerpc_operand *operand;
832
427k
      int invalid;
833
834
427k
      insn2 = insn;
835
427k
      if ((insn2 & table_mask) != table_opcd
836
427k
    || (opcode->deprecated & dialect) != 0)
837
422k
  continue;
838
839
      /* Check validity of operands.  */
840
5.76k
      invalid = 0;
841
22.9k
      for (opindex = opcode->operands; *opindex != 0; ++opindex)
842
17.1k
  {
843
17.1k
    operand = powerpc_operands + *opindex;
844
17.1k
    if (operand->extract)
845
990
      (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
846
17.1k
  }
847
5.76k
      if (invalid)
848
609
  continue;
849
850
5.15k
      return opcode;
851
5.76k
    }
852
853
6.02k
  return NULL;
854
11.1k
}
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
3.16M
{
945
3.16M
  bfd_byte buffer[4];
946
3.16M
  int status;
947
3.16M
  uint64_t insn;
948
3.16M
  const struct powerpc_opcode *opcode;
949
3.16M
  int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
950
951
3.16M
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
952
953
  /* The final instruction may be a 2-byte VLE insn.  */
954
3.16M
  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
3.16M
  if (status != 0)
963
482
    {
964
482
      (*info->memory_error_func) (status, memaddr, info);
965
482
      return -1;
966
482
    }
967
968
3.16M
  if (bigendian)
969
1.65M
    insn = bfd_getb32 (buffer);
970
1.51M
  else
971
1.51M
    insn = bfd_getl32 (buffer);
972
973
  /* Get the major opcode of the insn.  */
974
3.16M
  opcode = NULL;
975
3.16M
  if ((dialect & PPC_OPCODE_POWER10) != 0
976
3.16M
      && PPC_OP (insn) == 0x1)
977
65.2k
    {
978
65.2k
      uint64_t temp_insn, suffix;
979
65.2k
      status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
980
65.2k
      if (status == 0)
981
65.2k
  {
982
65.2k
    if (bigendian)
983
26.3k
      suffix = bfd_getb32 (buffer);
984
38.9k
    else
985
38.9k
      suffix = bfd_getl32 (buffer);
986
65.2k
    temp_insn = (insn << 32) | suffix;
987
65.2k
    opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
988
65.2k
    if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
989
63.9k
      opcode = lookup_prefix (temp_insn, dialect);
990
65.2k
    if (opcode != NULL)
991
1.24k
      {
992
1.24k
        insn = temp_insn;
993
1.24k
        insn_length = 8;
994
1.24k
        if ((info->flags & WIDE_OUTPUT) != 0)
995
0
    info->bytes_per_line = 8;
996
1.24k
      }
997
65.2k
  }
998
65.2k
    }
999
3.16M
  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
3.16M
  if (opcode == NULL && insn_length == 4)
1010
3.16M
    {
1011
3.16M
      if ((dialect & PPC_OPCODE_LSP) != 0)
1012
0
  opcode = lookup_lsp (insn, dialect);
1013
3.16M
      if ((dialect & PPC_OPCODE_SPE2) != 0)
1014
84.7k
  opcode = lookup_spe2 (insn, dialect);
1015
3.16M
      if (opcode == NULL)
1016
3.16M
  opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
1017
3.16M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1018
1.24M
  opcode = lookup_powerpc (insn, dialect);
1019
3.16M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1020
1.09M
  opcode = lookup_spe2 (insn, dialect);
1021
3.16M
      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
1022
1.09M
  opcode = lookup_lsp (insn, dialect);
1023
3.16M
    }
1024
1025
3.16M
  if (opcode != NULL)
1026
2.01M
    {
1027
2.01M
      const ppc_opindex_t *opindex;
1028
2.01M
      const struct powerpc_operand *operand;
1029
2.01M
      enum {
1030
2.01M
  need_comma = 0,
1031
2.01M
  need_1space = 1,
1032
2.01M
  need_2spaces = 2,
1033
2.01M
  need_3spaces = 3,
1034
2.01M
  need_4spaces = 4,
1035
2.01M
  need_5spaces = 5,
1036
2.01M
  need_6spaces = 6,
1037
2.01M
  need_7spaces = 7,
1038
2.01M
  need_paren
1039
2.01M
      } op_separator;
1040
2.01M
      bool skip_optional;
1041
2.01M
      bool is_pcrel;
1042
2.01M
      uint64_t d34;
1043
2.01M
      int blanks;
1044
1045
2.01M
      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1046
2.01M
            "%s", opcode->name);
1047
      /* gdb fprintf_styled_func doesn't return count printed.  */
1048
2.01M
      blanks = 8 - strlen (opcode->name);
1049
2.01M
      if (blanks <= 0)
1050
34.7k
  blanks = 1;
1051
1052
      /* Now extract and print the operands.  */
1053
2.01M
      op_separator = blanks;
1054
2.01M
      skip_optional = false;
1055
2.01M
      is_pcrel = false;
1056
2.01M
      d34 = 0;
1057
7.96M
      for (opindex = opcode->operands; *opindex != 0; opindex++)
1058
5.95M
  {
1059
5.95M
    int64_t value;
1060
1061
5.95M
    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
5.95M
    if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
1067
5.95M
        && (dialect & PPC_OPCODE_RAW) == 0)
1068
218k
      {
1069
218k
        if (!skip_optional)
1070
218k
    skip_optional = skip_optional_operands (opindex, insn,
1071
218k
              dialect, &is_pcrel);
1072
218k
        if (skip_optional)
1073
24.5k
    continue;
1074
218k
      }
1075
1076
5.93M
    value = operand_value_powerpc (operand, insn, dialect);
1077
1078
5.93M
    if (op_separator == need_comma)
1079
3.23M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
1080
2.70M
    else if (op_separator == need_paren)
1081
738k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
1082
1.96M
    else
1083
1.96M
      (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
1084
1.96M
            op_separator, " ");
1085
1086
    /* Print the operand as directed by the flags.  */
1087
5.93M
    if ((operand->flags & PPC_OPERAND_GPR) != 0
1088
5.93M
        || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
1089
2.95M
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1090
2.95M
            "r%" PRId64, value);
1091
2.97M
    else if ((operand->flags & PPC_OPERAND_FPR) != 0)
1092
486k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1093
486k
            "f%" PRId64, value);
1094
2.48M
    else if ((operand->flags & PPC_OPERAND_VR) != 0)
1095
151k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1096
151k
            "v%" PRId64, value);
1097
2.33M
    else if ((operand->flags & PPC_OPERAND_VSR) != 0)
1098
107k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1099
107k
            "vs%" PRId64, value);
1100
2.23M
    else if ((operand->flags & PPC_OPERAND_DMR) != 0)
1101
873
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1102
873
            "dm%" PRId64, value);
1103
2.22M
    else if ((operand->flags & PPC_OPERAND_ACC) != 0)
1104
401
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1105
401
            "a%" PRId64, value);
1106
2.22M
    else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
1107
106k
      (*info->print_address_func) (memaddr + value, info);
1108
2.12M
    else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
1109
34.5k
      (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
1110
2.08M
    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.08M
    else if ((operand->flags & PPC_OPERAND_FCR) != 0)
1114
91
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1115
91
            "fcr%" PRId64, value);
1116
2.08M
    else if ((operand->flags & PPC_OPERAND_UDI) != 0)
1117
252
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1118
252
            "%" PRId64, value);
1119
2.08M
    else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
1120
2.08M
       && (operand->flags & PPC_OPERAND_CR_BIT) == 0
1121
2.08M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1122
105k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1123
104k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1124
104k
            "cr%" PRId64, value);
1125
1.98M
    else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
1126
1.98M
       && (operand->flags & PPC_OPERAND_CR_REG) == 0
1127
1.98M
       && (((dialect & PPC_OPCODE_PPC) != 0)
1128
34.7k
           || ((dialect & PPC_OPCODE_VLE) != 0)))
1129
33.8k
      {
1130
33.8k
        static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
1131
33.8k
        int cr;
1132
33.8k
        int cc;
1133
1134
33.8k
        cr = value >> 2;
1135
33.8k
        cc = value & 3;
1136
33.8k
        if (cr != 0)
1137
15.2k
    {
1138
15.2k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1139
15.2k
            "4*");
1140
15.2k
      (*info->fprintf_styled_func) (info->stream,
1141
15.2k
            dis_style_register,
1142
15.2k
            "cr%d", cr);
1143
15.2k
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1144
15.2k
            "+");
1145
15.2k
    }
1146
1147
33.8k
        (*info->fprintf_styled_func) (info->stream,
1148
33.8k
              dis_style_sub_mnemonic,
1149
33.8k
              "%s", cbnames[cc]);
1150
33.8k
      }
1151
1.94M
    else
1152
1.94M
      {
1153
        /* An immediate, but what style?  */
1154
1.94M
        enum disassembler_style style;
1155
1156
1.94M
        if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1157
738k
    style = dis_style_address_offset;
1158
1.21M
        else
1159
1.21M
    style = dis_style_immediate;
1160
1161
1.94M
        (*info->fprintf_styled_func) (info->stream, style,
1162
1.94M
              "%" PRId64, value);
1163
1.94M
      }
1164
1165
5.93M
    if (operand->shift == 52)
1166
0
      is_pcrel = value != 0;
1167
5.93M
    else if (operand->bitm == UINT64_C (0x3ffffffff))
1168
929
      d34 = value;
1169
1170
5.93M
    if (op_separator == need_paren)
1171
738k
      (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1172
1173
5.93M
    op_separator = need_comma;
1174
5.93M
    if ((operand->flags & PPC_OPERAND_PARENS) != 0)
1175
738k
      op_separator = need_paren;
1176
5.93M
  }
1177
1178
2.01M
      if (is_pcrel)
1179
29
  {
1180
29
    d34 += memaddr;
1181
29
    (*info->fprintf_styled_func) (info->stream,
1182
29
          dis_style_comment_start,
1183
29
          "\t# %" PRIx64, d34);
1184
29
    asymbol *sym = (*info->symbol_at_address_func) (d34, info);
1185
29
    if (sym)
1186
0
      (*info->fprintf_styled_func) (info->stream, dis_style_text,
1187
0
            " <%s>", bfd_asymbol_name (sym));
1188
1189
29
    if (info->private_data != NULL
1190
29
        && info->section != NULL
1191
29
        && info->section->owner != NULL
1192
29
        && (bfd_get_file_flags (info->section->owner)
1193
0
      & (EXEC_P | DYNAMIC)) != 0
1194
29
        && ((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
29
  }
1202
1203
      /* We have found and printed an instruction.  */
1204
2.01M
      return insn_length;
1205
2.01M
    }
1206
1207
  /* We could not find a match.  */
1208
1.15M
  if (insn_length == 4)
1209
1.15M
    (*info->fprintf_styled_func) (info->stream,
1210
1.15M
          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
1.15M
  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1218
1.15M
  (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
1219
1.15M
        (unsigned int) insn);
1220
1221
1222
1.15M
  return insn_length;
1223
3.16M
}
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
}