aboutsummaryrefslogtreecommitdiff
path: root/opcodes/mips-dis.c
diff options
context:
space:
mode:
authorJim Kingdon <jkingdon@engr.sgi.com>1993-03-31 21:43:25 +0000
committerJim Kingdon <jkingdon@engr.sgi.com>1993-03-31 21:43:25 +0000
commit5d0734a7d74cf01b73303aeb884b719b4b220035 (patch)
treef24aaaf513a030c64dd9b0dae5ddb405a1c214f3 /opcodes/mips-dis.c
parent79337c85b8e706bd247a99d26a237f6dddf4ffe5 (diff)
downloadgdb-5d0734a7d74cf01b73303aeb884b719b4b220035.zip
gdb-5d0734a7d74cf01b73303aeb884b719b4b220035.tar.gz
gdb-5d0734a7d74cf01b73303aeb884b719b4b220035.tar.bz2
provide a new interface (using read_memory_func) to call the disassemblers
which copes with errors in a plausible way
Diffstat (limited to 'opcodes/mips-dis.c')
-rw-r--r--opcodes/mips-dis.c113
1 files changed, 75 insertions, 38 deletions
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index 1be0fbd..aaf2beb 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -18,9 +18,9 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <ansidecl.h>
#include "sysdep.h"
-#include <stdio.h>
-#include "bfd.h"
+#include "dis-asm.h"
#include "opcode/mips.h"
/* FIXME: we need direct access to the swapping functions. */
@@ -60,122 +60,159 @@ extern int print_address PARAMS ((bfd_vma, FILE *));
static CONST char * CONST reg_names[] = REGISTER_NAMES;
/* subroutine */
-static unsigned char *
-print_insn_arg (d, l, stream, pc)
+static void
+print_insn_arg (d, l, pc, info)
char *d;
- register unsigned long int *l;
- FILE *stream;
+ register unsigned long int l;
bfd_vma pc;
+ struct disassemble_info *info;
{
switch (*d)
{
case ',':
case '(':
case ')':
- fputc (*d, stream);
+ (*info->fprintf_func) (info->stream, "%c", *d);
break;
case 's':
- fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rs]);
+ (*info->fprintf_func) (info->stream, "$%s",
+ reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
break;
case 't':
- fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rt]);
+ (*info->fprintf_func) (info->stream, "$%s",
+ reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
break;
case 'i':
- fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
+ (*info->fprintf_func) (info->stream, "%d",
+ (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
break;
case 'j': /* same as i, but sign-extended */
- fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
+ (*info->fprintf_func) (info->stream, "%d",
+ (l >> OP_SH_DELTA) & OP_MASK_DELTA);
break;
case 'a':
- print_address ((pc & 0xF0000000) | (((struct op_j_fmt *)l)->target << 2),
- stream);
+ print_address (((pc & 0xF0000000)
+ | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
+ info->stream);
break;
case 'b':
- print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4, stream);
+ print_address ((((l >> OP_SH_DELTA) & OP_MASK_DELTA) << 2) + pc + 4,
+ info->stream);
break;
case 'd':
- fprintf (stream, "$%s", reg_names[((struct op_r_fmt *) l)->rd]);
+ (*info->fprintf_func) (info->stream, "$%s",
+ reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
break;
case 'h':
- fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
+ (*info->fprintf_func) (info->stream, "0x%x",
+ (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
break;
case 'B':
- fprintf (stream, "0x%x", ((struct op_brk_fmt *) l)->code);
+ (*info->fprintf_func) (info->stream, "0x%x",
+ (l >> OP_SH_CODE) & OP_MASK_CODE);
break;
case 'S':
- fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
+ (*info->fprintf_func) (info->stream, "$f%d",
+ (l >> OP_SH_FS) & OP_MASK_FS);
break;
case 'T':
- fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
+ (*info->fprintf_func) (info->stream, "$f%d",
+ (l >> OP_SH_FT) & OP_MASK_FT);
break;
case 'D':
- fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
+ (*info->fprintf_func) (info->stream, "$f%d",
+ (l >> OP_SH_FD) & OP_MASK_FD);
break;
default:
- fprintf (stream, "# internal error, undefined modifier(%c)", *d);
+ (*info->fprintf_func) (info->stream,
+ "# internal error, undefined modifier(%c)", *d);
break;
}
}
/* Print the mips instruction at address MEMADDR in debugged memory,
- on STREAM. Returns length of the instruction, in bytes, which is
+ on using INFO. Returns length of the instruction, in bytes, which is
always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if
this is little-endian code. */
int
-print_insn_mips (memaddr, buffer, stream, bigendian)
+_print_insn_mips (memaddr, word, info)
bfd_vma memaddr;
- bfd_byte *buffer;
- FILE *stream;
- int bigendian;
+ struct disassemble_info *info;
+ unsigned long int word;
{
register int i;
register char *d;
- unsigned long int l;
-
- /* FIXME: can't we export these functions from bfd? */
- if (bigendian)
- l = _do_getb32 (buffer);
- else
- l = _do_getl32 (buffer);
for (i = 0; i < NOPCODES; i++)
{
register unsigned int opcode = mips_opcodes[i].opcode;
register unsigned int match = mips_opcodes[i].match;
- if ((l & match) == opcode)
+ if ((word & match) == opcode)
break;
}
/* Handle undefined instructions. */
if (i == NOPCODES)
{
- fprintf (stream, "0x%x",l);
+ (*info->fprintf_func) (info->stream, "0x%x", word);
return 4;
}
- fprintf (stream, "%s", mips_opcodes[i].name);
+ (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
if (!(d = mips_opcodes[i].args))
return 4;
- fputc (' ', stream);
+ (*info->fprintf_func) (info->stream, " ");
while (*d)
- print_insn_arg (d++, &l, stream, memaddr);
+ print_insn_arg (d++, word, memaddr, info);
return 4;
}
+
+int
+print_insn_big_mips (memaddr, info)
+ bfd_vma memaddr;
+ struct disassemble_info *info;
+{
+ bfd_byte buffer[4];
+ int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status == 0)
+ return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
+ else
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+}
+
+int
+print_insn_little_mips (memaddr, info)
+ bfd_vma memaddr;
+ struct disassemble_info *info;
+{
+ bfd_byte buffer[4];
+ int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status == 0)
+ return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
+ else
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+}