Keep COPYING.NEWLIB if keep-newlib.
[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)
547998d2 52 const 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
547998d2
ILT
117 case 'z':
118 (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
119 break;
120
fde326fb 121 case '<':
5d0734a7
JK
122 (*info->fprintf_func) (info->stream, "0x%x",
123 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
124 break;
125
fde326fb 126 case 'c':
5d0734a7
JK
127 (*info->fprintf_func) (info->stream, "0x%x",
128 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
129 break;
130
fde326fb
ILT
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
d0ba1cea 141 case 'S':
fde326fb 142 case 'V':
5d0734a7
JK
143 (*info->fprintf_func) (info->stream, "$f%d",
144 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
145 break;
146
147 case 'T':
fde326fb 148 case 'W':
5d0734a7
JK
149 (*info->fprintf_func) (info->stream, "$f%d",
150 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
151 break;
152
153 case 'D':
5d0734a7
JK
154 (*info->fprintf_func) (info->stream, "$f%d",
155 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
156 break;
157
fde326fb
ILT
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
d0ba1cea 168 default:
5d0734a7
JK
169 (*info->fprintf_func) (info->stream,
170 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
171 break;
172 }
173}
174\f
175/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 176 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
177 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
178 this is little-endian code. */
179
180int
5d0734a7 181_print_insn_mips (memaddr, word, info)
d0ba1cea 182 bfd_vma memaddr;
5d0734a7
JK
183 struct disassemble_info *info;
184 unsigned long int word;
d0ba1cea
ILT
185{
186 register int i;
547998d2 187 register const char *d;
d0ba1cea 188
fde326fb 189 for (i = 0; i < NUMOPCODES; i++)
d0ba1cea 190 {
fde326fb
ILT
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 }
d0ba1cea
ILT
198 }
199
200 /* Handle undefined instructions. */
fde326fb 201 if (i == NUMOPCODES)
d0ba1cea 202 {
5d0734a7 203 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
204 return 4;
205 }
206
5d0734a7 207 (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
d0ba1cea
ILT
208
209 if (!(d = mips_opcodes[i].args))
210 return 4;
211
5d0734a7 212 (*info->fprintf_func) (info->stream, " ");
d0ba1cea
ILT
213
214 while (*d)
5d0734a7 215 print_insn_arg (d++, word, memaddr, info);
d0ba1cea
ILT
216
217 return 4;
218}
5d0734a7
JK
219
220int
221print_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
236int
237print_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}
This page took 0.12248 seconds and 4 git commands to generate.