Coverage Report

Created: 2023-08-28 06:23

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