OSDN Git Service

More portability patches. Include sysdep.h everywhere.
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / m88k-dis.c
1 /* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
2    Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1998
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 *,
35                  unsigned long, bfd_vma, int));
36
37 static void
38 init_disasm PARAMS ((void));
39
40 static void
41 install PARAMS ((INSTAB *instptr));
42
43 /*
44 *               Disassemble an M88000 Instruction
45 *
46 *
47 *       This module decodes the instruction at memaddr.
48 *
49 *                       Revision History
50 *
51 *       Revision 1.0    11/08/85        Creation date by Motorola
52 *                       05/11/89        R. Trawick adapted to GDB interface.
53 *                       07/12/93        Ian Lance Taylor updated to
54 *                                       binutils interface.
55 */
56
57 int
58 print_insn_m88k (memaddr, info)
59      bfd_vma memaddr;
60      struct disassemble_info *info;
61 {
62   bfd_byte buffer[4];
63   int status;
64
65   /* Instruction addresses may have low two bits set. Clear them.       */
66   memaddr &=~ (bfd_vma) 3;
67
68   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
69   if (status != 0)
70     {
71       (*info->memory_error_func) (status, memaddr, info);
72       return -1;
73     }
74
75   return m88kdis (memaddr, bfd_getb32 (buffer), info);
76 }
77
78 /*
79  * disassemble the instruction in 'instruction'.
80  * 'pc' should be the address of this instruction, it will
81  *   be used to print the target address if this is a relative jump or call
82  * the disassembled instruction is written to 'info'.
83  * The function returns the length of this instruction in bytes.
84  */
85
86 static int
87 m88kdis (pc, instruction, info)
88      bfd_vma pc;
89      unsigned long instruction;
90      struct disassemble_info *info;
91 {
92   static int ihashtab_initialized = 0;
93   unsigned int opcode;
94   INSTAB *entry_ptr;
95   int opmask;
96   unsigned int class;
97
98   if (! ihashtab_initialized)
99     init_disasm ();
100
101   /* create the appropriate mask to isolate the opcode */
102   opmask = DEFMASK;
103   class = instruction & DEFMASK;
104   if ((class >= SFU0) && (class <= SFU7))
105     {
106       if (instruction < SFU1)
107         opmask = CTRLMASK;
108       else
109         opmask = SFUMASK;
110     }
111   else if (class == RRR)
112     opmask = RRRMASK;
113   else if (class == RRI10)
114     opmask = RRI10MASK;
115
116   /* isolate the opcode */
117   opcode = instruction & opmask;
118
119   /* search the hash table with the isolated opcode */
120   for (entry_ptr = hashtable[opcode % HASHVAL];
121        (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
122        entry_ptr = entry_ptr->next)
123     ;
124
125   if (entry_ptr == NULL)
126     (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
127   else
128     {
129       (*info->fprintf_func) (info->stream, "%s", entry_ptr->mnemonic);
130       printop (info, &(entry_ptr->op1), instruction, pc, 1);
131       printop (info, &(entry_ptr->op2), instruction, pc, 0);
132       printop (info, &(entry_ptr->op3), instruction, pc, 0);
133     }
134
135   return 4;
136 }
137 \f
138 /*
139 *                      Decode an Operand of an Instruction
140 *
141 *                       Functional Description
142 *
143 *       This module formats and writes an operand of an instruction to info
144 *       based on the operand specification.  When the first flag is set this
145 *       is the first operand of an instruction.  Undefined operand types
146 *       cause a <dis error> message.
147 *
148 *                       Parameters
149 *       disassemble_info        where the operand may be printed
150 *       OPSPEC  *opptr          Pointer to an operand specification
151 *       UINT    inst            Instruction from which operand is extracted
152 *       UINT    pc              PC of instruction; used for pc-relative disp.
153 *       int     first           Flag which if nonzero indicates the first
154 *                               operand of an instruction
155 *
156 *                       Output
157 *
158 *       The operand specified is extracted from the instruction and is
159 *       written to buf in the format specified. The operand is preceded
160 *       by a comma if it is not the first operand of an instruction and it
161 *       is not a register indirect form.  Registers are preceded by 'r' and
162 *       hex values by '0x'.
163 *
164 *                       Revision History
165 *
166 *       Revision 1.0    11/08/85        Creation date
167 */
168
169 static void
170 printop (info, opptr, inst, pc, first)
171      struct disassemble_info *info;
172      OPSPEC *opptr;
173      unsigned long inst;
174      bfd_vma pc;
175      int first;
176 {
177   int extracted_field;
178   char *cond_mask_sym;
179
180   if (opptr->width == 0)
181     return;
182
183   if (! first)
184     {
185       switch (opptr->type)
186         {
187         case REGSC:
188         case CONT:
189           break;
190         default:
191           (*info->fprintf_func) (info->stream, ",");
192           break;
193         }
194     }
195
196   switch (opptr->type)
197     {
198     case CRREG:
199       (*info->fprintf_func) (info->stream, "cr%d",
200                              UEXT (inst, opptr->offset, opptr->width));
201       break;
202
203     case FCRREG:
204       (*info->fprintf_func) (info->stream, "fcr%d",
205                              UEXT (inst, opptr->offset, opptr->width));
206       break;
207
208     case REGSC:
209       (*info->fprintf_func) (info->stream, "[r%d]",
210                              UEXT (inst, opptr->offset, opptr->width));
211       break;
212
213     case REG:
214       (*info->fprintf_func) (info->stream, "r%d",
215                              UEXT (inst, opptr->offset, opptr->width));
216       break;
217
218     case XREG:
219       (*info->fprintf_func) (info->stream, "x%d",
220                              UEXT (inst, opptr->offset, opptr->width));
221       break;
222
223     case HEX:
224       extracted_field = UEXT (inst, opptr->offset, opptr->width);
225       if (extracted_field == 0)
226         (*info->fprintf_func) (info->stream, "0");
227       else
228         (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
229       break;
230
231     case DEC:
232       extracted_field = UEXT (inst, opptr->offset, opptr->width);
233       (*info->fprintf_func) (info->stream, "%d", extracted_field);
234       break;
235
236     case CONDMASK:
237       extracted_field = UEXT (inst, opptr->offset, opptr->width);
238       switch (extracted_field & 0x0f)
239         {
240         case 0x1: cond_mask_sym = "gt0"; break;
241         case 0x2: cond_mask_sym = "eq0"; break;
242         case 0x3: cond_mask_sym = "ge0"; break;
243         case 0xc: cond_mask_sym = "lt0"; break;
244         case 0xd: cond_mask_sym = "ne0"; break;
245         case 0xe: cond_mask_sym = "le0"; break;
246         default: cond_mask_sym = NULL; break;
247         }
248       if (cond_mask_sym != NULL)
249         (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
250       else
251         (*info->fprintf_func) (info->stream, "%x", extracted_field);
252       break;
253                         
254     case PCREL:
255       (*info->print_address_func)
256         (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
257          info);
258       break;
259
260     case CONT:
261       (*info->fprintf_func) (info->stream, "%d,r%d",
262                              UEXT (inst, opptr->offset, 5),
263                              UEXT (inst, (opptr->offset) + 5, 5));
264       break;
265
266     case BF:
267       (*info->fprintf_func) (info->stream, "%d<%d>",
268                               UEXT (inst, (opptr->offset) + 5, 5),
269                               UEXT (inst, opptr->offset, 5));
270       break;
271
272     default:
273       /* xgettext:c-format */
274       (*info->fprintf_func) (info->stream, _("# <dis error: %08x>"), inst);
275     }
276 }
277
278 /*
279 *                 Initialize the Disassembler Instruction Table
280 *
281 *       Initialize the hash table and instruction table for the disassembler.
282 *       This should be called once before the first call to disasm().
283 *
284 *                       Parameters
285 *
286 *                       Output
287 *
288 *       If the debug option is selected, certain statistics about the hashing
289 *       distribution are written to stdout.
290 *
291 *                       Revision History
292 *
293 *       Revision 1.0    11/08/85        Creation date
294 */
295
296 static void
297 init_disasm ()
298 {
299    int i, size;
300
301    for (i = 0; i < HASHVAL; i++)
302      hashtable[i] = NULL;
303
304    size = sizeof (instructions) / sizeof (INSTAB);
305    for (i = 0; i < size; i++)
306      install (&instructions[i]);
307 }
308
309 /*
310 *       Insert an instruction into the disassembler table by hashing the
311 *       opcode and inserting it into the linked list for that hash value.
312 *
313 *                       Parameters
314 *
315 *       INSTAB *instptr         Pointer to the entry in the instruction table
316 *                               to be installed
317 *
318 *       Revision 1.0    11/08/85        Creation date
319 *                       05/11/89        R. TRAWICK ADAPTED FROM MOTOROLA
320 */
321
322 static void
323 install (instptr)
324      INSTAB *instptr;
325 {
326   unsigned int i;
327
328   i = (instptr->opcode) % HASHVAL;
329   instptr->next = hashtable[i];
330   hashtable[i] = instptr;
331 }