]> Git Repo - binutils.git/blob - opcodes/mips-dis.c
Thu Jan 7 13:15:17 1993 Ian Lance Taylor ([email protected])
[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([email protected]).
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 "sysdep.h"
22 #include <stdio.h>
23 #include "bfd.h"
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.  */
37 extern 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
60 static CONST char * CONST reg_names[] = REGISTER_NAMES;
61 \f
62 /* subroutine */
63 static unsigned char *
64 print_insn_arg (d, l, stream, pc)
65      char *d;
66      register unsigned long int *l;
67      FILE *stream;
68      bfd_vma pc;
69 {
70   switch (*d)
71     {
72     case ',':
73     case '(':
74     case ')':
75       fputc (*d, stream);
76       break;
77
78     case 's':
79       fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rs]);
80       break;
81
82     case 't':
83       fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rt]);
84       break;
85
86     case 'i':
87       fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
88       break;
89
90     case 'j': /* same as i, but sign-extended */
91       fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
92       break;
93
94     case 'a':
95       print_address ((pc & 0xF0000000) | (((struct op_j_fmt *)l)->target << 2),
96                      stream);
97       break;
98
99     case 'b':
100       print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4, stream);
101       break;
102
103     case 'd':
104       fprintf (stream, "$%s", reg_names[((struct op_r_fmt *) l)->rd]);
105       break;
106
107     case 'h':
108       fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
109       break;
110
111     case 'B':
112       fprintf (stream, "0x%x", ((struct op_brk_fmt *) l)->code);
113       break;
114
115     case 'S':
116       fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
117       break;
118
119     case 'T':
120       fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
121       break;
122
123     case 'D':
124       fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
125       break;
126
127     default:
128       fprintf (stream, "# internal error, undefined modifier(%c)", *d);
129       break;
130     }
131 }
132 \f
133 /* Print the mips instruction at address MEMADDR in debugged memory,
134    on STREAM.  Returns length of the instruction, in bytes, which is
135    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
136    this is little-endian code.  */
137
138 int
139 print_insn_mips (memaddr, buffer, stream, bigendian)
140      bfd_vma memaddr;
141      bfd_byte *buffer;
142      FILE *stream;
143      int bigendian;
144 {
145   register int i;
146   register char *d;
147   unsigned long int l;
148
149   /* FIXME: can't we export these functions from bfd?  */
150   if (bigendian)
151     l = _do_getb32 (buffer);
152   else
153     l = _do_getl32 (buffer);
154
155   for (i = 0; i < NOPCODES; i++)
156     {
157       register unsigned int opcode = mips_opcodes[i].opcode;
158       register unsigned int match = mips_opcodes[i].match;
159       if ((l & match) == opcode)
160         break;
161     }
162
163   /* Handle undefined instructions.  */
164   if (i == NOPCODES)
165     {
166       fprintf (stream, "0x%x",l);
167       return 4;
168     }
169
170   fprintf (stream, "%s", mips_opcodes[i].name);
171
172   if (!(d = mips_opcodes[i].args))
173     return 4;
174
175   fputc (' ', stream);
176
177   while (*d)
178     print_insn_arg (d++, &l, stream, memaddr);
179
180   return 4;
181 }
This page took 0.033945 seconds and 4 git commands to generate.