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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [m88k-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
2
   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1998, 2000, 2001
3
   Free Software Foundation, Inc.
4
   Contributed by Data General Corporation, November 1989.
5
   Partially derived from an earlier printcmd.c.
6
 
7
This file is part of GDB and the GNU Binutils.
8
 
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13
 
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
 
23
#include "sysdep.h"
24
#include "dis-asm.h"
25
#include "opcode/m88k.h"
26
#include "opintl.h"
27
 
28
INSTAB  *hashtable[HASHVAL] = {0};
29
 
30
static int
31
m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
32
 
33
static void
34
printop PARAMS ((struct disassemble_info *, OPSPEC *, unsigned long, bfd_vma, int));
35
 
36
static void
37
init_disasm PARAMS ((void));
38
 
39
static void
40
install PARAMS ((INSTAB *instptr));
41
 
42
 
43
/* Disassemble an M88000 instruction at `memaddr'.  */
44
 
45
int
46
print_insn_m88k (memaddr, info)
47
     bfd_vma memaddr;
48
     struct disassemble_info *info;
49
{
50
  bfd_byte buffer[4];
51
  int status;
52
 
53
  /* Instruction addresses may have low two bits set. Clear them.  */
54
  memaddr &=~ (bfd_vma) 3;
55
 
56
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
57
  if (status != 0)
58
    {
59
      (*info->memory_error_func) (status, memaddr, info);
60
      return -1;
61
    }
62
 
63
  return m88kdis (memaddr, bfd_getb32 (buffer), info);
64
}
65
 
66
/*
67
 * Disassemble the instruction in `instruction'.
68
 * `pc' should be the address of this instruction, it will be used to
69
 * print the target address if this is a relative jump or call the
70
 * disassembled instruction is written to `info'.
71
 *
72
 * The function returns the length of this instruction in bytes.
73
 */
74
 
75
static int
76
m88kdis (pc, instruction, info)
77
     bfd_vma pc;
78
     unsigned long instruction;
79
     struct disassemble_info *info;
80
{
81
  static int ihashtab_initialized = 0;
82
  unsigned int opcode;
83
  INSTAB *entry_ptr;
84
  int opmask;
85
  unsigned int class;
86
 
87
  if (! ihashtab_initialized)
88
    init_disasm ();
89
 
90
  /* Create the appropriate mask to isolate the opcode.  */
91
  opmask = DEFMASK;
92
  class = instruction & DEFMASK;
93
  if ((class >= SFU0) && (class <= SFU7))
94
    {
95
      if (instruction < SFU1)
96
        opmask = CTRLMASK;
97
      else
98
        opmask = SFUMASK;
99
    }
100
  else if (class == RRR)
101
    opmask = RRRMASK;
102
  else if (class == RRI10)
103
    opmask = RRI10MASK;
104
 
105
  /* Isolate the opcode.  */
106
  opcode = instruction & opmask;
107
 
108
  /* Search the hash table with the isolated opcode.  */
109
  for (entry_ptr = hashtable[opcode % HASHVAL];
110
       (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
111
       entry_ptr = entry_ptr->next)
112
    ;
113
 
114
  if (entry_ptr == NULL)
115
    (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
116
  else
117
    {
118
      (*info->fprintf_func) (info->stream, "%s", entry_ptr->mnemonic);
119
      printop (info, &(entry_ptr->op1), instruction, pc, 1);
120
      printop (info, &(entry_ptr->op2), instruction, pc, 0);
121
      printop (info, &(entry_ptr->op3), instruction, pc, 0);
122
    }
123
 
124
  return 4;
125
}
126
 
127
/*
128
 * Decode an Operand of an instruction.
129
 *
130
 * This function formats and writes an operand of an instruction to
131
 * info based on the operand specification.  When the `first' flag is
132
 * set this is the first operand of an instruction.  Undefined operand
133
 * types cause a <dis error> message.
134
 *
135
 * Parameters:
136
 *  disassemble_info    where the operand may be printed
137
 *  OPSPEC  *opptr      pointer to an operand specification
138
 *  UINT    inst        instruction from which operand is extracted
139
 *  UINT    pc          pc of instruction; used for pc-relative disp.
140
 *  int     first       flag which if nonzero indicates the first
141
 *                      operand of an instruction
142
 *
143
 * The operand specified is extracted from the instruction and is
144
 * written to buf in the format specified. The operand is preceded by
145
 * a comma if it is not the first operand of an instruction and it is
146
 * not a register indirect form.  Registers are preceded by 'r' and
147
 * hex values by '0x'.
148
 */
149
 
150
static void
151
printop (info, opptr, inst, pc, first)
152
     struct disassemble_info *info;
153
     OPSPEC *opptr;
154
     unsigned long inst;
155
     bfd_vma pc;
156
     int first;
157
{
158
  int extracted_field;
159
  char *cond_mask_sym;
160
 
161
  if (opptr->width == 0)
162
    return;
163
 
164
  if (! first)
165
    {
166
      switch (opptr->type)
167
        {
168
        case REGSC:
169
        case CONT:
170
          break;
171
        default:
172
          (*info->fprintf_func) (info->stream, ",");
173
          break;
174
        }
175
    }
176
 
177
  switch (opptr->type)
178
    {
179
    case CRREG:
180
      (*info->fprintf_func) (info->stream, "cr%d",
181
                             UEXT (inst, opptr->offset, opptr->width));
182
      break;
183
 
184
    case FCRREG:
185
      (*info->fprintf_func) (info->stream, "fcr%d",
186
                             UEXT (inst, opptr->offset, opptr->width));
187
      break;
188
 
189
    case REGSC:
190
      (*info->fprintf_func) (info->stream, "[r%d]",
191
                             UEXT (inst, opptr->offset, opptr->width));
192
      break;
193
 
194
    case REG:
195
      (*info->fprintf_func) (info->stream, "r%d",
196
                             UEXT (inst, opptr->offset, opptr->width));
197
      break;
198
 
199
    case XREG:
200
      (*info->fprintf_func) (info->stream, "x%d",
201
                             UEXT (inst, opptr->offset, opptr->width));
202
      break;
203
 
204
    case HEX:
205
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
206
      if (extracted_field == 0)
207
        (*info->fprintf_func) (info->stream, "0");
208
      else
209
        (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
210
      break;
211
 
212
    case DEC:
213
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
214
      (*info->fprintf_func) (info->stream, "%d", extracted_field);
215
      break;
216
 
217
    case CONDMASK:
218
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
219
      switch (extracted_field & 0x0f)
220
        {
221
        case 0x1: cond_mask_sym = "gt0"; break;
222
        case 0x2: cond_mask_sym = "eq0"; break;
223
        case 0x3: cond_mask_sym = "ge0"; break;
224
        case 0xc: cond_mask_sym = "lt0"; break;
225
        case 0xd: cond_mask_sym = "ne0"; break;
226
        case 0xe: cond_mask_sym = "le0"; break;
227
        default: cond_mask_sym = NULL; break;
228
        }
229
      if (cond_mask_sym != NULL)
230
        (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
231
      else
232
        (*info->fprintf_func) (info->stream, "%x", extracted_field);
233
      break;
234
 
235
    case PCREL:
236
      (*info->print_address_func)
237
        (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
238
         info);
239
      break;
240
 
241
    case CONT:
242
      (*info->fprintf_func) (info->stream, "%d,r%d",
243
                             UEXT (inst, opptr->offset, 5),
244
                             UEXT (inst, (opptr->offset) + 5, 5));
245
      break;
246
 
247
    case BF:
248
      (*info->fprintf_func) (info->stream, "%d<%d>",
249
                             UEXT (inst, (opptr->offset) + 5, 5),
250
                             UEXT (inst, opptr->offset, 5));
251
      break;
252
 
253
    default:
254
      /* xgettext:c-format */
255
      (*info->fprintf_func) (info->stream, _("# <dis error: %08x>"), inst);
256
    }
257
}
258
 
259
/*
260
 * Initialize the disassembler instruction table.
261
 *
262
 * Initialize the hash table and instruction table for the
263
 * disassembler.  This should be called once before the first call to
264
 * disasm().
265
 */
266
 
267
static void
268
init_disasm ()
269
{
270
  int i, size;
271
 
272
  for (i = 0; i < HASHVAL; i++)
273
    hashtable[i] = NULL;
274
 
275
  size = sizeof (instructions) / sizeof (INSTAB);
276
  for (i = 0; i < size; i++)
277
    install (&instructions[i]);
278
}
279
 
280
/*
281
 * Insert an instruction into the disassembler table by hashing the
282
 * opcode and inserting it into the linked list for that hash value.
283
 */
284
 
285
static void
286
install (instptr)
287
     INSTAB *instptr;
288
{
289
  unsigned int i;
290
 
291
  i = (instptr->opcode) % HASHVAL;
292
  instptr->next = hashtable[i];
293
  hashtable[i] = instptr;
294
}

powered by: WebSVN 2.1.0

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