X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fmips-dis.c;h=4efd91c6a6f2705dea3a44fdaaca054f75b16e9b;hb=c29d7797d215507ac0b737d9bc81fc8a2cc9524c;hp=f7f29bc1b8be2ae967fe46578b3b1eadd80bb1ac;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index f7f29bc1b8..4efd91c6a6 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -1,5 +1,5 @@ /* Print mips instructions for GDB, the GNU debugger, or for objdump. - Copyright 1989, 91-97, 1998 Free Software Foundation, Inc. + Copyright (c) 1989, 91-97, 1998 Free Software Foundation, Inc. Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp). This file is part of GDB, GAS, and the GNU binutils. @@ -22,11 +22,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sysdep.h" #include "dis-asm.h" #include "opcode/mips.h" +#include "opintl.h" -/* FIXME: These are needed to figure out if this is a mips16 symbol or - not. It would be better to think of a cleaner way to do this. */ +/* FIXME: These are needed to figure out if the code is mips16 or + not. The low bit of the address is often a good indicator. No + symbol table is available when this code runs out in an embedded + system as when it is used for disassembler support in a monitor. */ + +#if !defined(EMBEDDED_ENV) +#define SYMTAB_AVAILABLE 1 #include "elf-bfd.h" #include "elf/mips.h" +#endif static int print_insn_mips16 PARAMS ((bfd_vma, struct disassemble_info *)); static void print_mips16_insn_arg @@ -87,7 +94,7 @@ print_insn_arg (d, l, pc, info) /* start-sanitize-r5900 */ case '+': case '-': - /* end-santiize-r5900 */ + /* end-sanitize-r5900 */ (*info->fprintf_func) (info->stream, "%c", *d); break; @@ -167,6 +174,12 @@ print_insn_arg (d, l, pc, info) (l >> OP_SH_CODE) & OP_MASK_CODE); break; + + case 'q': + (*info->fprintf_func) (info->stream, "0x%x", + (l >> OP_SH_CODE2) & OP_MASK_CODE2); + break; + case 'C': (*info->fprintf_func) (info->stream, "0x%x", (l >> OP_SH_COPZ) & OP_MASK_COPZ); @@ -183,14 +196,14 @@ print_insn_arg (d, l, pc, info) (l >> OP_SH_FS) & OP_MASK_FS); break; - /* start-sanitize-r5900 + /* start-sanitize-r5900 */ case '0': (*info->fprintf_func) (info->stream, "0x%x", (l >> 6) & 0x1f); break; case '9': - (*info->fprintf_func) (info->stream, "vi19"); + (*info->fprintf_func) (info->stream, "vi27"); break; case '1': @@ -241,6 +254,10 @@ print_insn_arg (d, l, pc, info) case 'K': break; + case ';': + (*info->fprintf_func) (info->stream, ".xyz\t"); + break; + case '&': (*info->fprintf_func) (info->stream, "."); if (l & (1 << 21)) @@ -351,51 +368,29 @@ print_insn_arg (d, l, pc, info) /* end-sanitize-vr5400 */ default: + /* xgettext:c-format */ (*info->fprintf_func) (info->stream, - "# internal error, undefined modifier(%c)", *d); + _("# internal error, undefined modifier(%c)"), + *d); break; } } -/* Print the mips instruction at address MEMADDR in debugged memory, - 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. */ - -static int -_print_insn_mips (memaddr, word, info) - bfd_vma memaddr; - unsigned long int word; - struct disassemble_info *info; -{ - register const struct mips_opcode *op; - int target_processor, mips_isa; - static boolean init = 0; - static const struct mips_opcode *mips_hash[OP_MASK_OP + 1]; - - /* Build a hash table to shorten the search time. */ - if (! init) - { - unsigned int i; +#if SYMTAB_AVAILABLE - for (i = 0; i <= OP_MASK_OP; i++) - { - for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++) - { - if (op->pinfo == INSN_MACRO) - continue; - if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) - { - mips_hash[i] = op; - break; - } - } - } +/* Figure out the MIPS ISA and CPU based on the machine number. + FIXME: What does this have to do with SYMTAB_AVAILABLE? */ - init = 1; - } +static void +set_mips_isa_type (mach, isa, cputype) + int mach; + int *isa; + int *cputype; +{ + int target_processor = 0; + int mips_isa = 0; - switch (info->mach) + switch (mach) { /* start-sanitize-tx19 */ case bfd_mach_mips1900: @@ -490,6 +485,59 @@ _print_insn_mips (memaddr, word, info) } + *isa = mips_isa; + *cputype = target_processor; +} + +#endif /* SYMTAB_AVAILABLE */ + +/* Print the mips instruction at address MEMADDR in debugged memory, + 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. */ + +static int +_print_insn_mips (memaddr, word, info) + bfd_vma memaddr; + unsigned long int word; + struct disassemble_info *info; +{ + register const struct mips_opcode *op; + int target_processor, mips_isa; + static boolean init = 0; + static const struct mips_opcode *mips_hash[OP_MASK_OP + 1]; + + /* Build a hash table to shorten the search time. */ + if (! init) + { + unsigned int i; + + for (i = 0; i <= OP_MASK_OP; i++) + { + for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++) + { + if (op->pinfo == INSN_MACRO) + continue; + if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) + { + mips_hash[i] = op; + break; + } + } + } + + init = 1; + } + +#if ! SYMTAB_AVAILABLE + /* This is running out on a target machine, not in a host tool. + FIXME: Where does mips_target_info come from? */ + target_processor = mips_target_info.processor; + mips_isa = mips_target_info.isa; +#else + set_mips_isa_type (info->mach, &target_processor, &mips_isa); +#endif + info->bytes_per_chunk = 4; info->display_endian = info->endian; @@ -549,7 +597,7 @@ _print_insn_mips (memaddr, word, info) /* start-sanitize-r5900 */ /* If this is an opcode completer, then do not emit a tab after the opcode. */ - if (*d != '&') + if (*d != '&' && *d != ';') /* end-sanitize-r5900 */ (*info->fprintf_func) (info->stream, "\t"); for (; *d != '\0'; d++) @@ -576,6 +624,13 @@ _print_insn_mips (memaddr, word, info) return 4; } + +/* In an environment where we do not know the symbol type of the + instruction we are forced to assume that the low order bit of the + instructions' address may mark it as a mips16 instruction. If we + are single stepping, or the pc is within the disassembled function, + this works. Otherwise, we need a clue. Sometimes. */ + int print_insn_big_mips (memaddr, info) bfd_vma memaddr; @@ -584,12 +639,21 @@ print_insn_big_mips (memaddr, info) bfd_byte buffer[4]; int status; +#if 1 + /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */ + /* Only a few tools will work this way. */ + if (memaddr & 0x01) + return print_insn_mips16 (memaddr, info); +#endif + +#if SYMTAB_AVAILABLE if (info->mach == 16 || (info->flavour == bfd_target_elf_flavour && info->symbols != NULL && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other == STO_MIPS16))) return print_insn_mips16 (memaddr, info); +#endif status = (*info->read_memory_func) (memaddr, buffer, 4, info); if (status == 0) @@ -625,12 +689,19 @@ print_insn_little_mips (memaddr, info) #endif /* end-sanitize-sky */ +#if 1 + if (memaddr & 0x01) + return print_insn_mips16 (memaddr, info); +#endif + +#if SYMTAB_AVAILABLE if (info->mach == 16 || (info->flavour == bfd_target_elf_flavour && info->symbols != NULL && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other == STO_MIPS16))) return print_insn_mips16 (memaddr, info); +#endif status = (*info->read_memory_func) (memaddr, buffer, 4, info); if (status == 0) @@ -655,7 +726,7 @@ print_insn_mips16 (memaddr, info) int length; int insn; boolean use_extend; - int extend; + int extend = 0; const struct mips_opcode *op, *opend; info->bytes_per_chunk = 2; @@ -1060,7 +1131,7 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info) if (signedp && immed >= (1 << (nbits - 1))) immed -= 1 << nbits; immed <<= shift; - if ((type == '<' || type == '>' || type == '[' || type == '[') + if ((type == '<' || type == '>' || type == '[' || type == ']') && immed == 0) immed = 8; }