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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [opcodes/] [ppc-dis.c] - Blame information for rev 1767

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

Line No. Rev Author Line
1 106 markom
/* ppc-dis.c -- Disassemble PowerPC instructions
2
   Copyright 1994 Free Software Foundation, Inc.
3
   Written by Ian Lance Taylor, Cygnus Support
4
 
5
This file is part of GDB, GAS, and the GNU binutils.
6
 
7
GDB, GAS, and the GNU binutils are free software; you can redistribute
8
them and/or modify them under the terms of the GNU General Public
9
License as published by the Free Software Foundation; either version
10
2, or (at your option) any later version.
11
 
12
GDB, GAS, and the GNU binutils are distributed in the hope that they
13
will be useful, but WITHOUT ANY WARRANTY; without even the implied
14
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15
the GNU General Public 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 Free
19
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
 
21
#include <stdio.h>
22
#include "ansidecl.h"
23
#include "sysdep.h"
24
#include "dis-asm.h"
25
#include "opcode/ppc.h"
26
 
27
/* This file provides several disassembler functions, all of which use
28
   the disassembler interface defined in dis-asm.h.  Several functions
29
   are provided because this file handles disassembly for the PowerPC
30
   in both big and little endian mode and also for the POWER (RS/6000)
31
   chip.  */
32
 
33
static int print_insn_powerpc PARAMS ((bfd_vma, struct disassemble_info *,
34
                                       int bigendian, int dialect));
35
 
36
/* Print a big endian PowerPC instruction.  For convenience, also
37
   disassemble instructions supported by the Motorola PowerPC 601.  */
38
 
39
int
40
print_insn_big_powerpc (memaddr, info)
41
     bfd_vma memaddr;
42
     struct disassemble_info *info;
43
{
44
  return print_insn_powerpc (memaddr, info, 1,
45
                             PPC_OPCODE_PPC | PPC_OPCODE_601);
46
}
47
 
48
/* Print a little endian PowerPC instruction.  For convenience, also
49
   disassemble instructions supported by the Motorola PowerPC 601.  */
50
 
51
int
52
print_insn_little_powerpc (memaddr, info)
53
     bfd_vma memaddr;
54
     struct disassemble_info *info;
55
{
56
  return print_insn_powerpc (memaddr, info, 0,
57
                             PPC_OPCODE_PPC | PPC_OPCODE_601);
58
}
59
 
60
/* Print a POWER (RS/6000) instruction.  */
61
 
62
int
63
print_insn_rs6000 (memaddr, info)
64
     bfd_vma memaddr;
65
     struct disassemble_info *info;
66
{
67
  return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
68
}
69
 
70
/* Print a PowerPC or POWER instruction.  */
71
 
72
static int
73
print_insn_powerpc (memaddr, info, bigendian, dialect)
74
     bfd_vma memaddr;
75
     struct disassemble_info *info;
76
     int bigendian;
77
     int dialect;
78
{
79
  bfd_byte buffer[4];
80
  int status;
81
  unsigned long insn;
82
  const struct powerpc_opcode *opcode;
83
  const struct powerpc_opcode *opcode_end;
84
  unsigned long op;
85
 
86
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
87
  if (status != 0)
88
    {
89
      (*info->memory_error_func) (status, memaddr, info);
90
      return -1;
91
    }
92
 
93
  if (bigendian)
94
    insn = bfd_getb32 (buffer);
95
  else
96
    insn = bfd_getl32 (buffer);
97
 
98
  /* Get the major opcode of the instruction.  */
99
  op = PPC_OP (insn);
100
 
101
  /* Find the first match in the opcode table.  We could speed this up
102
     a bit by doing a binary search on the major opcode.  */
103
  opcode_end = powerpc_opcodes + powerpc_num_opcodes;
104
  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
105
    {
106
      unsigned long table_op;
107
      const unsigned char *opindex;
108
      const struct powerpc_operand *operand;
109
      int invalid;
110
      int need_comma;
111
      int need_paren;
112
 
113
      table_op = PPC_OP (opcode->opcode);
114
      if (op < table_op)
115
        break;
116
      if (op > table_op)
117
        continue;
118
 
119
      if ((insn & opcode->mask) != opcode->opcode
120
          || (opcode->flags & dialect) == 0)
121
        continue;
122
 
123
      /* Make two passes over the operands.  First see if any of them
124
         have extraction functions, and, if they do, make sure the
125
         instruction is valid.  */
126
      invalid = 0;
127
      for (opindex = opcode->operands; *opindex != 0; opindex++)
128
        {
129
          operand = powerpc_operands + *opindex;
130
          if (operand->extract)
131
            (*operand->extract) (insn, &invalid);
132
        }
133
      if (invalid)
134
        continue;
135
 
136
      /* The instruction is valid.  */
137
      (*info->fprintf_func) (info->stream, "%s", opcode->name);
138
      if (opcode->operands[0] != 0)
139
        (*info->fprintf_func) (info->stream, "\t");
140
 
141
      /* Now extract and print the operands.  */
142
      need_comma = 0;
143
      need_paren = 0;
144
      for (opindex = opcode->operands; *opindex != 0; opindex++)
145
        {
146
          long value;
147
 
148
          operand = powerpc_operands + *opindex;
149
 
150
          /* Operands that are marked FAKE are simply ignored.  We
151
             already made sure that the extract function considered
152
             the instruction to be valid.  */
153
          if ((operand->flags & PPC_OPERAND_FAKE) != 0)
154
            continue;
155
 
156
          /* Extract the value from the instruction.  */
157
          if (operand->extract)
158
            value = (*operand->extract) (insn, (int *) NULL);
159
          else
160
            {
161
              value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
162
              if ((operand->flags & PPC_OPERAND_SIGNED) != 0
163
                  && (value & (1 << (operand->bits - 1))) != 0)
164
                value -= 1 << operand->bits;
165
            }
166
 
167
          /* If the operand is optional, and the value is zero, don't
168
             print anything.  */
169
          if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
170
              && (operand->flags & PPC_OPERAND_NEXT) == 0
171
              && value == 0)
172
            continue;
173
 
174
          if (need_comma)
175
            {
176
              (*info->fprintf_func) (info->stream, ",");
177
              need_comma = 0;
178
            }
179
 
180
          /* Print the operand as directed by the flags.  */
181
          if ((operand->flags & PPC_OPERAND_GPR) != 0)
182
            (*info->fprintf_func) (info->stream, "r%ld", value);
183
          else if ((operand->flags & PPC_OPERAND_FPR) != 0)
184
            (*info->fprintf_func) (info->stream, "f%ld", value);
185
          else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
186
            (*info->print_address_func) (memaddr + value, info);
187
          else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
188
            (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
189
          else if ((operand->flags & PPC_OPERAND_CR) == 0
190
                   || (dialect & PPC_OPCODE_PPC) == 0)
191
            (*info->fprintf_func) (info->stream, "%ld", value);
192
          else
193
            {
194
              if (operand->bits == 3)
195
                (*info->fprintf_func) (info->stream, "cr%d", value);
196
              else
197
                {
198
                  static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
199
                  int cr;
200
                  int cc;
201
 
202
                  cr = value >> 2;
203
                  if (cr != 0)
204
                    (*info->fprintf_func) (info->stream, "4*cr%d", cr);
205
                  cc = value & 3;
206
                  if (cc != 0)
207
                    {
208
                      if (cr != 0)
209
                        (*info->fprintf_func) (info->stream, "+");
210
                      (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
211
                    }
212
                }
213
            }
214
 
215
          if (need_paren)
216
            {
217
              (*info->fprintf_func) (info->stream, ")");
218
              need_paren = 0;
219
            }
220
 
221
          if ((operand->flags & PPC_OPERAND_PARENS) == 0)
222
            need_comma = 1;
223
          else
224
            {
225
              (*info->fprintf_func) (info->stream, "(");
226
              need_paren = 1;
227
            }
228
        }
229
 
230
      /* We have found and printed an instruction; return.  */
231
      return 4;
232
    }
233
 
234
  /* We could not find a match.  */
235
  (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
236
 
237
  return 4;
238
}

powered by: WebSVN 2.1.0

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