* hppa-dis.c (print_insn_hppa): For '?' and '@' only adjust the
[external/binutils.git] / opcodes / mips-dis.c
1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2    Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
5 This file is part of GDB.
6
7 This program 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 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 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 program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include <ansidecl.h>
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #include "opcode/mips.h"
25
26 /* FIXME: we need direct access to the swapping functions.  */
27 #include "libbfd.h"
28
29 /* Mips instructions are never longer than this many bytes.  */
30 #define MAXLEN 4
31 \f
32 /* FIXME: This should be shared with gdb somehow.  */
33 #define REGISTER_NAMES  \
34     {   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", \
35         "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7", \
36         "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", \
37         "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra", \
38         "sr",   "lo",   "hi",   "bad",  "cause","pc",    \
39         "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
40         "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
41         "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
42         "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
43         "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
44         "epc",  "prid"\
45     }
46
47 static CONST char * CONST reg_names[] = REGISTER_NAMES;
48 \f
49 /* subroutine */
50 static void
51 print_insn_arg (d, l, pc, info)
52      const char *d;
53      register unsigned long int l;
54      bfd_vma pc;
55      struct disassemble_info *info;
56 {
57   int delta;
58
59   switch (*d)
60     {
61     case ',':
62     case '(':
63     case ')':
64       (*info->fprintf_func) (info->stream, "%c", *d);
65       break;
66
67     case 's':
68     case 'b':
69     case 'r':
70     case 'v':
71       (*info->fprintf_func) (info->stream, "$%s",
72                              reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
73       break;
74
75     case 't':
76     case 'w':
77       (*info->fprintf_func) (info->stream, "$%s",
78                              reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
79       break;
80
81     case 'i':
82     case 'u':
83       (*info->fprintf_func) (info->stream, "%d",
84                         (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
85       break;
86
87     case 'j': /* same as i, but sign-extended */
88     case 'o':
89       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
90       if (delta & 0x8000)
91         delta |= ~0xffff;
92       (*info->fprintf_func) (info->stream, "%d",
93                              delta);
94       break;
95
96     case 'a':
97       (*info->print_address_func)
98         (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
99          info);
100       break;
101
102     case 'p':
103       /* sign extend the displacement */
104       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
105       if (delta & 0x8000)
106         delta |= ~0xffff;
107       (*info->print_address_func)
108         ((delta << 2) + pc + 4,
109          info);
110       break;
111
112     case 'd':
113       (*info->fprintf_func) (info->stream, "$%s",
114                              reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
115       break;
116
117     case 'z':
118       (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
119       break;
120
121     case '<':
122       (*info->fprintf_func) (info->stream, "0x%x",
123                              (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
124       break;
125
126     case 'c':
127       (*info->fprintf_func) (info->stream, "0x%x",
128                              (l >> OP_SH_CODE) & OP_MASK_CODE);
129       break;
130
131     case 'C':
132       (*info->fprintf_func) (info->stream, "0x%x",
133                              (l >> OP_SH_COPZ) & OP_MASK_COPZ);
134       break;
135
136     case 'B':
137       (*info->fprintf_func) (info->stream, "0x%x",
138                              (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
139       break;
140
141     case 'S':
142     case 'V':
143       (*info->fprintf_func) (info->stream, "$f%d",
144                              (l >> OP_SH_FS) & OP_MASK_FS);
145       break;
146
147     case 'T':
148     case 'W':
149       (*info->fprintf_func) (info->stream, "$f%d",
150                              (l >> OP_SH_FT) & OP_MASK_FT);
151       break;
152
153     case 'D':
154       (*info->fprintf_func) (info->stream, "$f%d",
155                              (l >> OP_SH_FD) & OP_MASK_FD);
156       break;
157
158     case 'E':
159       (*info->fprintf_func) (info->stream, "$%d",
160                              (l >> OP_SH_RT) & OP_MASK_RT);
161       break;
162
163     case 'G':
164       (*info->fprintf_func) (info->stream, "$%d",
165                              (l >> OP_SH_RD) & OP_MASK_RD);
166       break;
167
168     default:
169       (*info->fprintf_func) (info->stream,
170                              "# internal error, undefined modifier(%c)", *d);
171       break;
172     }
173 }
174 \f
175 /* Print the mips instruction at address MEMADDR in debugged memory,
176    on using INFO.  Returns length of the instruction, in bytes, which is
177    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
178    this is little-endian code.  */
179
180 int
181 _print_insn_mips (memaddr, word, info)
182      bfd_vma memaddr;
183      struct disassemble_info *info;
184      unsigned long int word;
185 {
186   register int i;
187   register const char *d;
188
189   for (i = 0; i < NUMOPCODES; i++)
190     {
191       if (mips_opcodes[i].pinfo != INSN_MACRO)
192         {
193           register unsigned int match = mips_opcodes[i].match;
194           register unsigned int mask = mips_opcodes[i].mask;
195           if ((word & mask) == match)
196             break;
197         }
198     }
199
200   /* Handle undefined instructions.  */
201   if (i == NUMOPCODES)
202     {
203       (*info->fprintf_func) (info->stream, "0x%x", word);
204       return 4;
205     }
206
207   (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
208
209   if (!(d = mips_opcodes[i].args))
210     return 4;
211
212   (*info->fprintf_func) (info->stream, " ");
213
214   while (*d)
215     print_insn_arg (d++, word, memaddr, info);
216
217   return 4;
218 }
219
220 int
221 print_insn_big_mips (memaddr, info)
222      bfd_vma memaddr;
223      struct disassemble_info *info;
224 {
225   bfd_byte buffer[4];
226   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
227   if (status == 0)
228     return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
229   else
230     {
231       (*info->memory_error_func) (status, memaddr, info);
232       return -1;
233     }
234 }
235
236 int
237 print_insn_little_mips (memaddr, info)
238      bfd_vma memaddr;
239      struct disassemble_info *info;
240 {
241   bfd_byte buffer[4];
242   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
243   if (status == 0)
244     return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
245   else
246     {
247       (*info->memory_error_func) (status, memaddr, info);
248       return -1;
249     }
250 }