OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [opcodes/] [ppc-dis.c] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jlechner
/* ppc-dis.c -- Disassemble PowerPC instructions
2
   Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3
   2008 Free Software Foundation, Inc.
4
   Written by Ian Lance Taylor, Cygnus Support
5
 
6
   This file is part of the GNU opcodes library.
7
 
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this file; see the file COPYING.  If not, write to the
20
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include <stdio.h>
24
#include "sysdep.h"
25
#include "dis-asm.h"
26
#include "opcode/ppc.h"
27
 
28
/* This file provides several disassembler functions, all of which use
29
   the disassembler interface defined in dis-asm.h.  Several functions
30
   are provided because this file handles disassembly for the PowerPC
31
   in both big and little endian mode and also for the POWER (RS/6000)
32
   chip.  */
33
static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
34
                               ppc_cpu_t);
35
 
36
struct dis_private
37
{
38
  /* Stash the result of parsing disassembler_options here.  */
39
  ppc_cpu_t dialect;
40
};
41
 
42
#define POWERPC_DIALECT(INFO) \
43
  (((struct dis_private *) ((INFO)->private_data))->dialect)
44
 
45
/* Determine which set of machines to disassemble for.  PPC403/601 or
46
   BookE.  For convenience, also disassemble instructions supported
47
   by the AltiVec vector unit.  */
48
 
49
static int
50
powerpc_init_dialect (struct disassemble_info *info)
51
{
52
  ppc_cpu_t dialect = PPC_OPCODE_PPC;
53
  struct dis_private *priv = calloc (sizeof (*priv), 1);
54
 
55
  if (priv == NULL)
56
    return FALSE;
57
 
58
  if (BFD_DEFAULT_TARGET_SIZE == 64)
59
    dialect |= PPC_OPCODE_64;
60
 
61
  if (info->disassembler_options
62
      && strstr (info->disassembler_options, "ppcps") != NULL)
63
    dialect |= PPC_OPCODE_PPCPS;
64
  else if (info->disassembler_options
65
      && strstr (info->disassembler_options, "booke") != NULL)
66
    dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
67
  else if ((info->mach == bfd_mach_ppc_e500mc)
68
           || (info->disassembler_options
69
               && strstr (info->disassembler_options, "e500mc") != NULL))
70
    dialect |= (PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
71
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
72
                | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
73
  else if ((info->mach == bfd_mach_ppc_e500)
74
           || (info->disassembler_options
75
               && strstr (info->disassembler_options, "e500") != NULL))
76
    dialect |= (PPC_OPCODE_BOOKE
77
                | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
78
                | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
79
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
80
                | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
81
  else if (info->disassembler_options
82
           && strstr (info->disassembler_options, "efs") != NULL)
83
    dialect |= PPC_OPCODE_EFS;
84
  else if (info->disassembler_options
85
           && strstr (info->disassembler_options, "e300") != NULL)
86
    dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON;
87
  else if (info->disassembler_options
88
           && (strstr (info->disassembler_options, "440") != NULL
89
               || strstr (info->disassembler_options, "464") != NULL))
90
    dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32
91
      | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI;
92
  else
93
    dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
94
                | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC);
95
 
96
  if (info->disassembler_options
97
      && strstr (info->disassembler_options, "power4") != NULL)
98
    dialect |= PPC_OPCODE_POWER4;
99
 
100
  if (info->disassembler_options
101
      && strstr (info->disassembler_options, "power5") != NULL)
102
    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5;
103
 
104
  if (info->disassembler_options
105
      && strstr (info->disassembler_options, "cell") != NULL)
106
    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
107
 
108
  if (info->disassembler_options
109
      && strstr (info->disassembler_options, "power6") != NULL)
110
    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
111
               | PPC_OPCODE_ALTIVEC;
112
 
113
  if (info->disassembler_options
114
      && strstr (info->disassembler_options, "power7") != NULL)
115
    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
116
               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX;
117
 
118
  if (info->disassembler_options
119
      && strstr (info->disassembler_options, "vsx") != NULL)
120
    dialect |= PPC_OPCODE_VSX;
121
 
122
  if (info->disassembler_options
123
      && strstr (info->disassembler_options, "any") != NULL)
124
    dialect |= PPC_OPCODE_ANY;
125
 
126
  if (info->disassembler_options)
127
    {
128
      if (strstr (info->disassembler_options, "32") != NULL)
129
        dialect &= ~PPC_OPCODE_64;
130
      else if (strstr (info->disassembler_options, "64") != NULL)
131
        dialect |= PPC_OPCODE_64;
132
    }
133
 
134
  info->private_data = priv;
135
  POWERPC_DIALECT(info) = dialect;
136
 
137
  return TRUE;
138
}
139
 
140
/* Print a big endian PowerPC instruction.  */
141
 
142
int
143
print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
144
{
145
  if (info->private_data == NULL && !powerpc_init_dialect (info))
146
    return -1;
147
  return print_insn_powerpc (memaddr, info, 1, POWERPC_DIALECT(info));
148
}
149
 
150
/* Print a little endian PowerPC instruction.  */
151
 
152
int
153
print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
154
{
155
  if (info->private_data == NULL && !powerpc_init_dialect (info))
156
    return -1;
157
  return print_insn_powerpc (memaddr, info, 0, POWERPC_DIALECT(info));
158
}
159
 
160
/* Print a POWER (RS/6000) instruction.  */
161
 
162
int
163
print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
164
{
165
  return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
166
}
167
 
168
/* Extract the operand value from the PowerPC or POWER instruction.  */
169
 
170
static long
171
operand_value_powerpc (const struct powerpc_operand *operand,
172
                       unsigned long insn, ppc_cpu_t dialect)
173
{
174
  long value;
175
  int invalid;
176
  /* Extract the value from the instruction.  */
177
  if (operand->extract)
178
    value = (*operand->extract) (insn, dialect, &invalid);
179
  else
180
    {
181
      value = (insn >> operand->shift) & operand->bitm;
182
      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
183
        {
184
          /* BITM is always some number of zeros followed by some
185
             number of ones, followed by some numer of zeros.  */
186
          unsigned long top = operand->bitm;
187
          /* top & -top gives the rightmost 1 bit, so this
188
             fills in any trailing zeros.  */
189
          top |= (top & -top) - 1;
190
          top &= ~(top >> 1);
191
          value = (value ^ top) - top;
192
        }
193
    }
194
 
195
  return value;
196
}
197
 
198
/* Determine whether the optional operand(s) should be printed.  */
199
 
200
static int
201
skip_optional_operands (const unsigned char *opindex,
202
                        unsigned long insn, ppc_cpu_t dialect)
203
{
204
  const struct powerpc_operand *operand;
205
 
206
  for (; *opindex != 0; opindex++)
207
    {
208
      operand = &powerpc_operands[*opindex];
209
      if ((operand->flags & PPC_OPERAND_NEXT) != 0
210
          || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
211
              && operand_value_powerpc (operand, insn, dialect) != 0))
212
        return 0;
213
    }
214
 
215
  return 1;
216
}
217
 
218
/* Print a PowerPC or POWER instruction.  */
219
 
220
static int
221
print_insn_powerpc (bfd_vma memaddr,
222
                    struct disassemble_info *info,
223
                    int bigendian,
224
                    ppc_cpu_t dialect)
225
{
226
  bfd_byte buffer[4];
227
  int status;
228
  unsigned long insn;
229
  const struct powerpc_opcode *opcode;
230
  const struct powerpc_opcode *opcode_end;
231
  unsigned long op;
232
 
233
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
234
  if (status != 0)
235
    {
236
      (*info->memory_error_func) (status, memaddr, info);
237
      return -1;
238
    }
239
 
240
  if (bigendian)
241
    insn = bfd_getb32 (buffer);
242
  else
243
    insn = bfd_getl32 (buffer);
244
 
245
  /* Get the major opcode of the instruction.  */
246
  op = PPC_OP (insn);
247
 
248
  /* Find the first match in the opcode table.  We could speed this up
249
     a bit by doing a binary search on the major opcode.  */
250
  opcode_end = powerpc_opcodes + powerpc_num_opcodes;
251
 again:
252
  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
253
    {
254
      unsigned long table_op;
255
      const unsigned char *opindex;
256
      const struct powerpc_operand *operand;
257
      int invalid;
258
      int need_comma;
259
      int need_paren;
260
      int skip_optional;
261
 
262
      table_op = PPC_OP (opcode->opcode);
263
      if (op < table_op)
264
        break;
265
      if (op > table_op)
266
        continue;
267
 
268
      if ((insn & opcode->mask) != opcode->opcode
269
          || (opcode->flags & dialect) == 0)
270
        continue;
271
 
272
      /* Make two passes over the operands.  First see if any of them
273
         have extraction functions, and, if they do, make sure the
274
         instruction is valid.  */
275
      invalid = 0;
276
      for (opindex = opcode->operands; *opindex != 0; opindex++)
277
        {
278
          operand = powerpc_operands + *opindex;
279
          if (operand->extract)
280
            (*operand->extract) (insn, dialect, &invalid);
281
        }
282
      if (invalid)
283
        continue;
284
 
285
      /* The instruction is valid.  */
286
      if (opcode->operands[0] != 0)
287
        (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
288
      else
289
        (*info->fprintf_func) (info->stream, "%s", opcode->name);
290
 
291
      /* Now extract and print the operands.  */
292
      need_comma = 0;
293
      need_paren = 0;
294
      skip_optional = -1;
295
      for (opindex = opcode->operands; *opindex != 0; opindex++)
296
        {
297
          long value;
298
 
299
          operand = powerpc_operands + *opindex;
300
 
301
          /* Operands that are marked FAKE are simply ignored.  We
302
             already made sure that the extract function considered
303
             the instruction to be valid.  */
304
          if ((operand->flags & PPC_OPERAND_FAKE) != 0)
305
            continue;
306
 
307
          /* If all of the optional operands have the value zero,
308
             then don't print any of them.  */
309
          if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
310
            {
311
              if (skip_optional < 0)
312
                skip_optional = skip_optional_operands (opindex, insn,
313
                                                        dialect);
314
              if (skip_optional)
315
                continue;
316
            }
317
 
318
          value = operand_value_powerpc (operand, insn, dialect);
319
 
320
          if (need_comma)
321
            {
322
              (*info->fprintf_func) (info->stream, ",");
323
              need_comma = 0;
324
            }
325
 
326
          /* Print the operand as directed by the flags.  */
327
          if ((operand->flags & PPC_OPERAND_GPR) != 0
328
              || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
329
            (*info->fprintf_func) (info->stream, "r%ld", value);
330
          else if ((operand->flags & PPC_OPERAND_FPR) != 0)
331
            (*info->fprintf_func) (info->stream, "f%ld", value);
332
          else if ((operand->flags & PPC_OPERAND_VR) != 0)
333
            (*info->fprintf_func) (info->stream, "v%ld", value);
334
          else if ((operand->flags & PPC_OPERAND_VSR) != 0)
335
            (*info->fprintf_func) (info->stream, "vs%ld", value);
336
          else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
337
            (*info->print_address_func) (memaddr + value, info);
338
          else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
339
            (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
340
          else if ((operand->flags & PPC_OPERAND_CR) == 0
341
                   || (dialect & PPC_OPCODE_PPC) == 0)
342
            (*info->fprintf_func) (info->stream, "%ld", value);
343
          else if ((operand->flags & PPC_OPERAND_FSL) != 0)
344
            (*info->fprintf_func) (info->stream, "fsl%ld", value);
345
          else if ((operand->flags & PPC_OPERAND_FCR) != 0)
346
            (*info->fprintf_func) (info->stream, "fcr%ld", value);
347
          else if ((operand->flags & PPC_OPERAND_UDI) != 0)
348
            (*info->fprintf_func) (info->stream, "%ld", value);
349
          else
350
            {
351
              if (operand->bitm == 7)
352
                (*info->fprintf_func) (info->stream, "cr%ld", value);
353
              else
354
                {
355
                  static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
356
                  int cr;
357
                  int cc;
358
 
359
                  cr = value >> 2;
360
                  if (cr != 0)
361
                    (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
362
                  cc = value & 3;
363
                  (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
364
                }
365
            }
366
 
367
          if (need_paren)
368
            {
369
              (*info->fprintf_func) (info->stream, ")");
370
              need_paren = 0;
371
            }
372
 
373
          if ((operand->flags & PPC_OPERAND_PARENS) == 0)
374
            need_comma = 1;
375
          else
376
            {
377
              (*info->fprintf_func) (info->stream, "(");
378
              need_paren = 1;
379
            }
380
        }
381
 
382
      /* We have found and printed an instruction; return.  */
383
      return 4;
384
    }
385
 
386
  if ((dialect & PPC_OPCODE_ANY) != 0)
387
    {
388
      dialect = ~PPC_OPCODE_ANY;
389
      goto again;
390
    }
391
 
392
  /* We could not find a match.  */
393
  (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
394
 
395
  return 4;
396
}
397
 
398
void
399
print_ppc_disassembler_options (FILE *stream)
400
{
401
  fprintf (stream, "\n\
402
The following PPC specific disassembler options are supported for use with\n\
403
the -M switch:\n");
404
 
405
  fprintf (stream, "  booke|booke32|booke64    Disassemble the BookE instructions\n");
406
  fprintf (stream, "  e300                     Disassemble the e300 instructions\n");
407
  fprintf (stream, "  e500|e500x2              Disassemble the e500 instructions\n");
408
  fprintf (stream, "  e500mc                   Disassemble the e500mc instructions\n");
409
  fprintf (stream, "  440                      Disassemble the 440 instructions\n");
410
  fprintf (stream, "  464                      Disassemble the 464 instructions\n");
411
  fprintf (stream, "  efs                      Disassemble the EFS instructions\n");
412
  fprintf (stream, "  ppcps                    Disassemble the PowerPC paired singles instructions\n");
413
  fprintf (stream, "  power4                   Disassemble the Power4 instructions\n");
414
  fprintf (stream, "  power5                   Disassemble the Power5 instructions\n");
415
  fprintf (stream, "  power6                   Disassemble the Power6 instructions\n");
416
  fprintf (stream, "  power7                   Disassemble the Power7 instructions\n");
417
  fprintf (stream, "  vsx                      Disassemble the Vector-Scalar (VSX) instructions\n");
418
  fprintf (stream, "  32                       Do not disassemble 64-bit instructions\n");
419
  fprintf (stream, "  64                       Allow disassembly of 64-bit instructions\n");
420
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.