diff options
author | Jim Kingdon <jkingdon@engr.sgi.com> | 1993-03-31 21:43:25 +0000 |
---|---|---|
committer | Jim Kingdon <jkingdon@engr.sgi.com> | 1993-03-31 21:43:25 +0000 |
commit | 5d0734a7d74cf01b73303aeb884b719b4b220035 (patch) | |
tree | f24aaaf513a030c64dd9b0dae5ddb405a1c214f3 /opcodes/mips-dis.c | |
parent | 79337c85b8e706bd247a99d26a237f6dddf4ffe5 (diff) | |
download | gdb-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.c | 113 |
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; + } +} |