provide a new interface (using read_memory_func) to call the disassemblers

which copes with errors in a plausible way
This commit is contained in:
Jim Kingdon
1993-03-31 21:43:25 +00:00
parent 79337c85b8
commit 5d0734a7d7
18 changed files with 3961 additions and 533 deletions

View File

@@ -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;
}
}