Coverage Report

Created: 2026-09-14 08:07

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