* m88k-dis.c (m88kdis): Make class unsigned.
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
d0ba1cea
ILT
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
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
5d0734a7 21#include <ansidecl.h>
d0ba1cea 22#include "sysdep.h"
5d0734a7 23#include "dis-asm.h"
d0ba1cea
ILT
24#include "opcode/mips.h"
25
26/* FIXME: we need direct access to the swapping functions. */
27#include "libbfd.h"
28
d0ba1cea
ILT
29/* Mips instructions are never longer than this many bytes. */
30#define MAXLEN 4
d0ba1cea
ILT
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
47static CONST char * CONST reg_names[] = REGISTER_NAMES;
48\f
49/* subroutine */
5d0734a7
JK
50static void
51print_insn_arg (d, l, pc, info)
d0ba1cea 52 char *d;
5d0734a7 53 register unsigned long int l;
d0ba1cea 54 bfd_vma pc;
5d0734a7 55 struct disassemble_info *info;
d0ba1cea 56{
fde326fb
ILT
57 int delta;
58
d0ba1cea
ILT
59 switch (*d)
60 {
61 case ',':
62 case '(':
63 case ')':
5d0734a7 64 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
65 break;
66
67 case 's':
fde326fb
ILT
68 case 'b':
69 case 'r':
70 case 'v':
5d0734a7
JK
71 (*info->fprintf_func) (info->stream, "$%s",
72 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
73 break;
74
75 case 't':
fde326fb 76 case 'w':
5d0734a7
JK
77 (*info->fprintf_func) (info->stream, "$%s",
78 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
79 break;
80
81 case 'i':
fde326fb 82 case 'u':
5d0734a7
JK
83 (*info->fprintf_func) (info->stream, "%d",
84 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
85 break;
86
87 case 'j': /* same as i, but sign-extended */
fde326fb
ILT
88 case 'o':
89 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
90 if (delta & 0x8000)
91 delta |= ~0xffff;
5d0734a7 92 (*info->fprintf_func) (info->stream, "%d",
fde326fb 93 delta);
d0ba1cea
ILT
94 break;
95
96 case 'a':
fde326fb
ILT
97 (*info->print_address_func)
98 (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
99 info);
d0ba1cea
ILT
100 break;
101
fde326fb
ILT
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);
d0ba1cea
ILT
110 break;
111
112 case 'd':
5d0734a7
JK
113 (*info->fprintf_func) (info->stream, "$%s",
114 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
115 break;
116
fde326fb 117 case '<':
5d0734a7
JK
118 (*info->fprintf_func) (info->stream, "0x%x",
119 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
120 break;
121
fde326fb 122 case 'c':
5d0734a7
JK
123 (*info->fprintf_func) (info->stream, "0x%x",
124 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
125 break;
126
fde326fb
ILT
127 case 'C':
128 (*info->fprintf_func) (info->stream, "0x%x",
129 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
130 break;
131
132 case 'B':
133 (*info->fprintf_func) (info->stream, "0x%x",
134 (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
135 break;
136
d0ba1cea 137 case 'S':
fde326fb 138 case 'V':
5d0734a7
JK
139 (*info->fprintf_func) (info->stream, "$f%d",
140 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
141 break;
142
143 case 'T':
fde326fb 144 case 'W':
5d0734a7
JK
145 (*info->fprintf_func) (info->stream, "$f%d",
146 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
147 break;
148
149 case 'D':
5d0734a7
JK
150 (*info->fprintf_func) (info->stream, "$f%d",
151 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
152 break;
153
fde326fb
ILT
154 case 'E':
155 (*info->fprintf_func) (info->stream, "$%d",
156 (l >> OP_SH_RT) & OP_MASK_RT);
157 break;
158
159 case 'G':
160 (*info->fprintf_func) (info->stream, "$%d",
161 (l >> OP_SH_RD) & OP_MASK_RD);
162 break;
163
d0ba1cea 164 default:
5d0734a7
JK
165 (*info->fprintf_func) (info->stream,
166 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
167 break;
168 }
169}
170\f
171/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 172 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
173 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
174 this is little-endian code. */
175
176int
5d0734a7 177_print_insn_mips (memaddr, word, info)
d0ba1cea 178 bfd_vma memaddr;
5d0734a7
JK
179 struct disassemble_info *info;
180 unsigned long int word;
d0ba1cea
ILT
181{
182 register int i;
183 register char *d;
d0ba1cea 184
fde326fb 185 for (i = 0; i < NUMOPCODES; i++)
d0ba1cea 186 {
fde326fb
ILT
187 if (mips_opcodes[i].pinfo != INSN_MACRO)
188 {
189 register unsigned int match = mips_opcodes[i].match;
190 register unsigned int mask = mips_opcodes[i].mask;
191 if ((word & mask) == match)
192 break;
193 }
d0ba1cea
ILT
194 }
195
196 /* Handle undefined instructions. */
fde326fb 197 if (i == NUMOPCODES)
d0ba1cea 198 {
5d0734a7 199 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
200 return 4;
201 }
202
5d0734a7 203 (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
d0ba1cea
ILT
204
205 if (!(d = mips_opcodes[i].args))
206 return 4;
207
5d0734a7 208 (*info->fprintf_func) (info->stream, " ");
d0ba1cea
ILT
209
210 while (*d)
5d0734a7 211 print_insn_arg (d++, word, memaddr, info);
d0ba1cea
ILT
212
213 return 4;
214}
5d0734a7
JK
215
216int
217print_insn_big_mips (memaddr, info)
218 bfd_vma memaddr;
219 struct disassemble_info *info;
220{
221 bfd_byte buffer[4];
222 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
223 if (status == 0)
224 return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
225 else
226 {
227 (*info->memory_error_func) (status, memaddr, info);
228 return -1;
229 }
230}
231
232int
233print_insn_little_mips (memaddr, info)
234 bfd_vma memaddr;
235 struct disassemble_info *info;
236{
237 bfd_byte buffer[4];
238 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
239 if (status == 0)
240 return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
241 else
242 {
243 (*info->memory_error_func) (status, memaddr, info);
244 return -1;
245 }
246}
This page took 0.054769 seconds and 4 git commands to generate.