/* 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. */
+ system as when it is used for disassembler support in a monitor. */
#if !defined(EMBEDDED_ENV)
#define SYMTAB_AVAILABLE 1
PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *));
static void print_insn_arg
PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *));
+static void mips_isa_type
+ PARAMS ((int, int *, int *));
static int print_insn_mips16
PARAMS ((bfd_vma, struct disassemble_info *));
+static int is_newabi
+ PARAMS ((Elf_Internal_Ehdr *));
static void print_mips16_insn_arg
PARAMS ((int, const struct mips_opcode *, int, boolean, int, bfd_vma,
struct disassemble_info *));
/* FIXME: These should be shared with gdb somehow. */
/* The mips16 register names. */
-static const char * const mips16_reg_names[] =
-{
+static const char * const mips16_reg_names[] = {
"s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
};
-static const char * const mips32_reg_names[] =
-{
+static const char * const mips32_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"epc", "prid"
};
-static const char * const mips64_reg_names[] =
-{
+static const char * const mips64_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
table to use. */
static const char * const *reg_names = NULL;
\f
-/* Print insn arguments for 32/64-bit code */
+/* Print insn arguments for 32/64-bit code. */
static void
print_insn_arg (d, l, pc, info)
case 'i':
case 'u':
(*info->fprintf_func) (info->stream, "0x%x",
- (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
+ (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
break;
- case 'j': /* same as i, but sign-extended */
+ case 'j': /* Same as i, but sign-extended. */
case 'o':
delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
if (delta & 0x8000)
case 'a':
(*info->print_address_func)
- ((((pc + 4) & ~ (bfd_vma) 0x0fffffff)
+ ((((pc + 4) & ~(bfd_vma) 0x0fffffff)
| (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
info);
break;
case 'p':
- /* sign extend the displacement */
+ /* Sign extend the displacement. */
delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
if (delta & 0x8000)
delta |= ~0xffff;
case 'U':
{
- /* First check for both rd and rt being equal. */
- unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
- if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
- (*info->fprintf_func) (info->stream, "%s",
- reg_names[reg]);
- else
- {
- /* If one is zero use the other. */
- if (reg == 0)
- (*info->fprintf_func) (info->stream, "%s",
- reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
- else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
- (*info->fprintf_func) (info->stream, "%s",
- reg_names[reg]);
- else /* Bogus, result depends on processor. */
- (*info->fprintf_func) (info->stream, "%s or %s",
- reg_names[reg],
- reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
- }
+ /* First check for both rd and rt being equal. */
+ unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
+ if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
+ (*info->fprintf_func) (info->stream, "%s",
+ reg_names[reg]);
+ else
+ {
+ /* If one is zero use the other. */
+ if (reg == 0)
+ (*info->fprintf_func) (info->stream, "%s",
+ reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
+ else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
+ (*info->fprintf_func) (info->stream, "%s",
+ reg_names[reg]);
+ else /* Bogus, result depends on processor. */
+ (*info->fprintf_func) (info->stream, "%s or %s",
+ reg_names[reg],
+ reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
+ }
}
break;
break;
case 'E':
- (*info->fprintf_func) (info->stream, "%s",
- reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
+ (*info->fprintf_func) (info->stream, "$%d",
+ (l >> OP_SH_RT) & OP_MASK_RT);
break;
case 'G':
- (*info->fprintf_func) (info->stream, "%s",
- reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
+ (*info->fprintf_func) (info->stream, "$%d",
+ (l >> OP_SH_RD) & OP_MASK_RD);
break;
case 'N':
}
}
\f
-/* Figure out the MIPS ISA and CPU based on the machine number. */
+/* Figure out the MIPS ISA and CPU based on the machine number. */
static void
mips_isa_type (mach, isa, cputype)
*cputype = CPU_R10000;
*isa = ISA_MIPS4;
break;
+ case bfd_mach_mips12000:
+ *cputype = CPU_R12000;
+ *isa = ISA_MIPS4;
+ break;
case bfd_mach_mips16:
*cputype = CPU_MIPS16;
*isa = ISA_MIPS3;
break;
- case bfd_mach_mips32:
- *cputype = CPU_MIPS32;
- *isa = ISA_MIPS32;
- break;
- case bfd_mach_mips32_4k:
- *cputype = CPU_MIPS32_4K;
- *isa = ISA_MIPS32;
- break;
case bfd_mach_mips5:
*cputype = CPU_MIPS5;
*isa = ISA_MIPS5;
break;
- case bfd_mach_mips64:
- *cputype = CPU_MIPS64;
- *isa = ISA_MIPS64;
- break;
case bfd_mach_mips_sb1:
*cputype = CPU_SB1;
*isa = ISA_MIPS64;
break;
+ case bfd_mach_mipsisa32:
+ * cputype = CPU_MIPS32;
+ * isa = ISA_MIPS32;
+ break;
+ case bfd_mach_mipsisa64:
+ * cputype = CPU_MIPS64;
+ * isa = ISA_MIPS64;
+ break;
+
default:
*cputype = CPU_R3000;
*isa = ISA_MIPS3;
}
}
-/* Figure out ISA from disassemble_info data */
+/* Check if the object uses NewABI conventions. */
static int
-get_mips_isa (info)
- struct disassemble_info *info;
+is_newabi (header)
+ Elf_Internal_Ehdr *header;
{
- int isa;
- int cpu;
+ if ((header->e_flags
+ & (E_MIPS_ABI_EABI32 | E_MIPS_ABI_EABI64 | EF_MIPS_ABI2)) != 0
+ || (header->e_ident[EI_CLASS] == ELFCLASS64
+ && (header->e_flags & E_MIPS_ABI_O64) == 0))
+ return 1;
- mips_isa_type (info->mach, &isa, &cpu);
- return isa;
+ return 0;
}
\f
/* Print the mips instruction at address MEMADDR in debugged memory,
break;
}
}
- }
+ }
init = 1;
}
{
register const char *d;
- if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor, 0))
+ if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor))
continue;
(*info->fprintf_func) (info->stream, "%s", op->name);
d = op->args;
if (d != NULL && *d != '\0')
{
- (*info->fprintf_func) (info->stream, "\t");
+ (*info->fprintf_func) (info->stream, "\t");
for (; *d != '\0'; d++)
- print_insn_arg (d, word, memaddr, info);
+ print_insn_arg (d, word, memaddr, info);
}
return INSNLEN;
#endif
/* Use mips64_reg_names for new ABI. */
- if (info->flavour == bfd_target_elf_flavour
- && info->symbols != NULL
- && (((get_mips_isa(info) | INSN_ISA_MASK) & ISA_MIPS2) != 0)
- && ((elf_elfheader (bfd_asymbol_bfd(*(info->symbols)))->e_flags
- & EF_MIPS_ABI2) != 0))
- reg_names = mips64_reg_names;
- else
- reg_names = mips32_reg_names;
+ reg_names = mips32_reg_names;
+
+ if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
+ {
+ Elf_Internal_Ehdr *header;
+
+ header = elf_elfheader (bfd_asymbol_bfd (*(info->symbols)));
+ if (is_newabi (header))
+ reg_names = mips64_reg_names;
+ }
status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
if (status == 0)
unsigned long insn;
if (endianness == BFD_ENDIAN_BIG)
- insn = (unsigned long) bfd_getb32 (buffer);
+ insn = (unsigned long) bfd_getb32 (buffer);
else
insn = (unsigned long) bfd_getl32 (buffer);
case 'X':
(*info->fprintf_func) (info->stream, "%s",
mips32_reg_names[((l >> MIPS16OP_SH_REGR32)
- & MIPS16OP_MASK_REGR32)]);
+ & MIPS16OP_MASK_REGR32)]);
break;
case 'Y':
baseaddr = memaddr - 2;
}
}
- val = (baseaddr & ~ ((1 << shift) - 1)) + immed;
+ val = (baseaddr & ~((1 << shift) - 1)) + immed;
(*info->print_address_func) (val, info);
info->target = val;
}