* m68k-dis.c (print_insn_{m68k,arg}): Add MMU codes.
[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
29/* We use bfd_vma in a couple of places where gdb expects CORE_ADDR. */
30#ifdef HOST_64_BIT
31 #error FIXME: bfd_vma will not match gdb expectations
32#endif
33
34/* This file is used both by gdb and by objdump. A program which
35 wants to use this code must provide an external function
36 print_address. */
37extern int print_address PARAMS ((bfd_vma, FILE *));
38
39/* Mips instructions are never longer than this many bytes. */
40#define MAXLEN 4
41
42/* Number of elements in the opcode table. */
43#define NOPCODES (sizeof mips_opcodes / sizeof mips_opcodes[0])
44\f
45/* FIXME: This should be shared with gdb somehow. */
46#define REGISTER_NAMES \
47 { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
48 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
49 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
50 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
51 "sr", "lo", "hi", "bad", "cause","pc", \
52 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
53 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
54 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
55 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
56 "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
57 "epc", "prid"\
58 }
59
60static CONST char * CONST reg_names[] = REGISTER_NAMES;
61\f
62/* subroutine */
5d0734a7
JK
63static void
64print_insn_arg (d, l, pc, info)
d0ba1cea 65 char *d;
5d0734a7 66 register unsigned long int l;
d0ba1cea 67 bfd_vma pc;
5d0734a7 68 struct disassemble_info *info;
d0ba1cea
ILT
69{
70 switch (*d)
71 {
72 case ',':
73 case '(':
74 case ')':
5d0734a7 75 (*info->fprintf_func) (info->stream, "%c", *d);
d0ba1cea
ILT
76 break;
77
78 case 's':
5d0734a7
JK
79 (*info->fprintf_func) (info->stream, "$%s",
80 reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
d0ba1cea
ILT
81 break;
82
83 case 't':
5d0734a7
JK
84 (*info->fprintf_func) (info->stream, "$%s",
85 reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
d0ba1cea
ILT
86 break;
87
88 case 'i':
5d0734a7
JK
89 (*info->fprintf_func) (info->stream, "%d",
90 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
d0ba1cea
ILT
91 break;
92
93 case 'j': /* same as i, but sign-extended */
5d0734a7
JK
94 (*info->fprintf_func) (info->stream, "%d",
95 (l >> OP_SH_DELTA) & OP_MASK_DELTA);
d0ba1cea
ILT
96 break;
97
98 case 'a':
5d0734a7
JK
99 print_address (((pc & 0xF0000000)
100 | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
101 info->stream);
d0ba1cea
ILT
102 break;
103
104 case 'b':
5d0734a7
JK
105 print_address ((((l >> OP_SH_DELTA) & OP_MASK_DELTA) << 2) + pc + 4,
106 info->stream);
d0ba1cea
ILT
107 break;
108
109 case 'd':
5d0734a7
JK
110 (*info->fprintf_func) (info->stream, "$%s",
111 reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
d0ba1cea
ILT
112 break;
113
114 case 'h':
5d0734a7
JK
115 (*info->fprintf_func) (info->stream, "0x%x",
116 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
d0ba1cea
ILT
117 break;
118
119 case 'B':
5d0734a7
JK
120 (*info->fprintf_func) (info->stream, "0x%x",
121 (l >> OP_SH_CODE) & OP_MASK_CODE);
d0ba1cea
ILT
122 break;
123
124 case 'S':
5d0734a7
JK
125 (*info->fprintf_func) (info->stream, "$f%d",
126 (l >> OP_SH_FS) & OP_MASK_FS);
d0ba1cea
ILT
127 break;
128
129 case 'T':
5d0734a7
JK
130 (*info->fprintf_func) (info->stream, "$f%d",
131 (l >> OP_SH_FT) & OP_MASK_FT);
d0ba1cea
ILT
132 break;
133
134 case 'D':
5d0734a7
JK
135 (*info->fprintf_func) (info->stream, "$f%d",
136 (l >> OP_SH_FD) & OP_MASK_FD);
d0ba1cea
ILT
137 break;
138
139 default:
5d0734a7
JK
140 (*info->fprintf_func) (info->stream,
141 "# internal error, undefined modifier(%c)", *d);
d0ba1cea
ILT
142 break;
143 }
144}
145\f
146/* Print the mips instruction at address MEMADDR in debugged memory,
5d0734a7 147 on using INFO. Returns length of the instruction, in bytes, which is
d0ba1cea
ILT
148 always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
149 this is little-endian code. */
150
151int
5d0734a7 152_print_insn_mips (memaddr, word, info)
d0ba1cea 153 bfd_vma memaddr;
5d0734a7
JK
154 struct disassemble_info *info;
155 unsigned long int word;
d0ba1cea
ILT
156{
157 register int i;
158 register char *d;
d0ba1cea
ILT
159
160 for (i = 0; i < NOPCODES; i++)
161 {
162 register unsigned int opcode = mips_opcodes[i].opcode;
163 register unsigned int match = mips_opcodes[i].match;
5d0734a7 164 if ((word & match) == opcode)
d0ba1cea
ILT
165 break;
166 }
167
168 /* Handle undefined instructions. */
169 if (i == NOPCODES)
170 {
5d0734a7 171 (*info->fprintf_func) (info->stream, "0x%x", word);
d0ba1cea
ILT
172 return 4;
173 }
174
5d0734a7 175 (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
d0ba1cea
ILT
176
177 if (!(d = mips_opcodes[i].args))
178 return 4;
179
5d0734a7 180 (*info->fprintf_func) (info->stream, " ");
d0ba1cea
ILT
181
182 while (*d)
5d0734a7 183 print_insn_arg (d++, word, memaddr, info);
d0ba1cea
ILT
184
185 return 4;
186}
5d0734a7
JK
187
188int
189print_insn_big_mips (memaddr, info)
190 bfd_vma memaddr;
191 struct disassemble_info *info;
192{
193 bfd_byte buffer[4];
194 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
195 if (status == 0)
196 return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
197 else
198 {
199 (*info->memory_error_func) (status, memaddr, info);
200 return -1;
201 }
202}
203
204int
205print_insn_little_mips (memaddr, info)
206 bfd_vma memaddr;
207 struct disassemble_info *info;
208{
209 bfd_byte buffer[4];
210 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
211 if (status == 0)
212 return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
213 else
214 {
215 (*info->memory_error_func) (status, memaddr, info);
216 return -1;
217 }
218}
This page took 0.044717 seconds and 4 git commands to generate.