* mips-dis.c (print_insn_arg): Print condition code registers as
[deliverable/binutils-gdb.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include <ansidecl.h>
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #include "opcode/mips.h"
25
26 /* Mips instructions are never longer than this many bytes. */
27 #define MAXLEN 4
28 \f
29 /* FIXME: This should be shared with gdb somehow. */
30 #define REGISTER_NAMES \
31 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
32 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
33 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
34 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
35 "sr", "lo", "hi", "bad", "cause","pc", \
36 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
37 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
38 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
39 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
40 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
41 "epc", "prid"\
42 }
43
44 static CONST char * CONST reg_names[] = REGISTER_NAMES;
45 \f
46 /* subroutine */
47 static void
48 print_insn_arg (d, l, pc, info)
49 const char *d;
50 register unsigned long int l;
51 bfd_vma pc;
52 struct disassemble_info *info;
53 {
54 int delta;
55
56 switch (*d)
57 {
58 case ',':
59 case '(':
60 case ')':
61 (*info->fprintf_func) (info->stream, "%c", *d);
62 break;
63
64 case 's':
65 case 'b':
66 case 'r':
67 case 'v':
68 (*info->fprintf_func) (info->stream, "$%s",
69 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
70 break;
71
72 case 't':
73 case 'w':
74 (*info->fprintf_func) (info->stream, "$%s",
75 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
76 break;
77
78 case 'i':
79 case 'u':
80 (*info->fprintf_func) (info->stream, "0x%x",
81 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
82 break;
83
84 case 'j': /* same as i, but sign-extended */
85 case 'o':
86 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
87 if (delta & 0x8000)
88 delta |= ~0xffff;
89 (*info->fprintf_func) (info->stream, "%d",
90 delta);
91 break;
92
93 case 'h':
94 (*info->fprintf_func) (info->stream, "0x%x",
95 (unsigned int) ((l >> OP_SH_PREFX)
96 & OP_MASK_PREFX));
97 break;
98
99 case 'k':
100 (*info->fprintf_func) (info->stream, "0x%x",
101 (unsigned int) ((l >> OP_SH_CACHE)
102 & OP_MASK_CACHE));
103 break;
104
105 case 'a':
106 (*info->print_address_func)
107 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
108 info);
109 break;
110
111 case 'p':
112 /* sign extend the displacement */
113 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
114 if (delta & 0x8000)
115 delta |= ~0xffff;
116 (*info->print_address_func)
117 ((delta << 2) + pc + 4,
118 info);
119 break;
120
121 case 'd':
122 (*info->fprintf_func) (info->stream, "$%s",
123 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
124 break;
125
126 case 'z':
127 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
128 break;
129
130 case '<':
131 (*info->fprintf_func) (info->stream, "0x%x",
132 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
133 break;
134
135 case 'c':
136 (*info->fprintf_func) (info->stream, "0x%x",
137 (l >> OP_SH_CODE) & OP_MASK_CODE);
138 break;
139
140 case 'C':
141 (*info->fprintf_func) (info->stream, "0x%x",
142 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
143 break;
144
145 case 'B':
146 (*info->fprintf_func) (info->stream, "0x%x",
147 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
148 break;
149
150 case 'S':
151 case 'V':
152 (*info->fprintf_func) (info->stream, "$f%d",
153 (l >> OP_SH_FS) & OP_MASK_FS);
154 break;
155
156 case 'T':
157 case 'W':
158 (*info->fprintf_func) (info->stream, "$f%d",
159 (l >> OP_SH_FT) & OP_MASK_FT);
160 break;
161
162 case 'D':
163 (*info->fprintf_func) (info->stream, "$f%d",
164 (l >> OP_SH_FD) & OP_MASK_FD);
165 break;
166
167 case 'R':
168 (*info->fprintf_func) (info->stream, "$f%d",
169 (l >> OP_SH_FR) & OP_MASK_FR);
170 break;
171
172 case 'E':
173 (*info->fprintf_func) (info->stream, "$%d",
174 (l >> OP_SH_RT) & OP_MASK_RT);
175 break;
176
177 case 'G':
178 (*info->fprintf_func) (info->stream, "$%d",
179 (l >> OP_SH_RD) & OP_MASK_RD);
180 break;
181
182 case 'N':
183 (*info->fprintf_func) (info->stream, "$fcc%d",
184 (l >> OP_SH_BCC) & OP_MASK_BCC);
185 break;
186
187 case 'M':
188 (*info->fprintf_func) (info->stream, "$fcc%d",
189 (l >> OP_SH_CCC) & OP_MASK_CCC);
190 break;
191
192 default:
193 (*info->fprintf_func) (info->stream,
194 "# internal error, undefined modifier(%c)", *d);
195 break;
196 }
197 }
198 \f
199 /* Print the mips instruction at address MEMADDR in debugged memory,
200 on using INFO. Returns length of the instruction, in bytes, which is
201 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
202 this is little-endian code. */
203
204 static int
205 _print_insn_mips (memaddr, word, info)
206 bfd_vma memaddr;
207 struct disassemble_info *info;
208 unsigned long int word;
209 {
210 register const struct mips_opcode *op;
211 static boolean init = 0;
212 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
213
214 /* Build a hash table to shorten the search time. */
215 if (! init)
216 {
217 unsigned int i;
218
219 for (i = 0; i <= OP_MASK_OP; i++)
220 {
221 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
222 {
223 if (op->pinfo == INSN_MACRO)
224 continue;
225 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
226 {
227 mips_hash[i] = op;
228 break;
229 }
230 }
231 }
232
233 init = 1;
234 }
235
236 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
237 if (op != NULL)
238 {
239 for (; op < &mips_opcodes[NUMOPCODES]; op++)
240 {
241 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
242 {
243 register const char *d;
244
245 (*info->fprintf_func) (info->stream, "%s", op->name);
246
247 d = op->args;
248 if (d != NULL)
249 {
250 (*info->fprintf_func) (info->stream, " ");
251 for (; *d != '\0'; d++)
252 print_insn_arg (d, word, memaddr, info);
253 }
254
255 return 4;
256 }
257 }
258 }
259
260 /* Handle undefined instructions. */
261 (*info->fprintf_func) (info->stream, "0x%x", word);
262 return 4;
263 }
264
265 int
266 print_insn_big_mips (memaddr, info)
267 bfd_vma memaddr;
268 struct disassemble_info *info;
269 {
270 bfd_byte buffer[4];
271 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
272 if (status == 0)
273 return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer), info);
274 else
275 {
276 (*info->memory_error_func) (status, memaddr, info);
277 return -1;
278 }
279 }
280
281 int
282 print_insn_little_mips (memaddr, info)
283 bfd_vma memaddr;
284 struct disassemble_info *info;
285 {
286 bfd_byte buffer[4];
287 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
288 if (status == 0)
289 return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer), info);
290 else
291 {
292 (*info->memory_error_func) (status, memaddr, info);
293 return -1;
294 }
295 }
This page took 0.040487 seconds and 5 git commands to generate.