/* Print mips instructions for GDB, the GNU debugger, or for objdump.
Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001
+ 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
break;
case 'a':
- (*info->print_address_func)
- ((((pc + 4) & ~(bfd_vma) 0x0fffffff)
- | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
- info);
+ info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
+ | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
+ (*info->print_address_func) (info->target, info);
break;
case 'p':
delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
if (delta & 0x8000)
delta |= ~0xffff;
- (*info->print_address_func)
- ((delta << 2) + pc + INSNLEN,
- info);
+ info->target = (delta << 2) + pc + INSNLEN;
+ (*info->print_address_func) (info->target, info);
break;
case 'd':
(l >> OP_SH_SEL) & OP_MASK_SEL);
break;
+ case 'O':
+ (*info->fprintf_func) (info->stream, "%d",
+ (l >> OP_SH_ALN) & OP_MASK_ALN);
+ break;
+
+ case 'Q':
+ {
+ unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
+ if ((vsel & 0x10) == 0)
+ {
+ int fmt;
+ vsel &= 0x0f;
+ for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
+ if ((vsel & 1) == 0)
+ break;
+ (*info->fprintf_func) (info->stream, "$v%d[%d]",
+ (l >> OP_SH_FT) & OP_MASK_FT,
+ vsel >> 1);
+ }
+ else if ((vsel & 0x08) == 0)
+ {
+ (*info->fprintf_func) (info->stream, "$v%d",
+ (l >> OP_SH_FT) & OP_MASK_FT);
+ }
+ else
+ {
+ (*info->fprintf_func) (info->stream, "0x%x",
+ (l >> OP_SH_FT) & OP_MASK_FT);
+ }
+ }
+ break;
+
+ case 'X':
+ (*info->fprintf_func) (info->stream, "$v%d",
+ (l >> OP_SH_FD) & OP_MASK_FD);
+ break;
+
+ case 'Y':
+ (*info->fprintf_func) (info->stream, "$v%d",
+ (l >> OP_SH_FS) & OP_MASK_FS);
+ break;
+
+ case 'Z':
+ (*info->fprintf_func) (info->stream, "$v%d",
+ (l >> OP_SH_FT) & OP_MASK_FT);
+ break;
+
default:
/* xgettext:c-format */
(*info->fprintf_func) (info->stream,
break;
case bfd_mach_mips16:
*cputype = CPU_MIPS16;
- *isa = ISA_MIPS3;
+ *isa = ISA_MIPS3 | INSN_MIPS16;
break;
case bfd_mach_mips5:
*cputype = CPU_MIPS5;
break;
case bfd_mach_mips_sb1:
*cputype = CPU_SB1;
- *isa = ISA_MIPS64 | INSN_SB1;
+ *isa = ISA_MIPS64 | INSN_MIPS3D | INSN_SB1;
break;
case bfd_mach_mipsisa32:
- * cputype = CPU_MIPS32;
- * isa = ISA_MIPS32;
+ *cputype = CPU_MIPS32;
+ /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
+ Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
+ _MIPS32 Architecture For Programmers Volume I: Introduction to the
+ MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
+ page 1. */
+ *isa = ISA_MIPS32 | INSN_MIPS16;
break;
case bfd_mach_mipsisa64:
- * cputype = CPU_MIPS64;
- * isa = ISA_MIPS64;
+ *cputype = CPU_MIPS64;
+ /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
+ *isa = ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX;
break;
default:
is_newabi (header)
Elf_Internal_Ehdr *header;
{
- 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))
+ /* There are no old-style ABIs which use 64-bit ELF. */
+ if (header->e_ident[EI_CLASS] == ELFCLASS64)
+ return 1;
+
+ /* If a 32-bit ELF file, n32 is a new-style ABI. */
+ if ((header->e_flags & EF_MIPS_ABI2) != 0)
return 1;
return 0;
info->bytes_per_chunk = INSNLEN;
info->display_endian = info->endian;
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_nonbranch;
+ info->target = 0;
+ info->target2 = 0;
op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
if (op != NULL)
if (! OPCODE_IS_MEMBER (op, mips_isa, target_processor))
continue;
+ /* Figure out instruction type and branch delay information. */
+ if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
+ {
+ if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
+ info->insn_type = dis_jsr;
+ else
+ info->insn_type = dis_branch;
+ info->branch_delay_insns = 1;
+ }
+ else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY)) != 0)
+ {
+ if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
+ info->insn_type = dis_condjsr;
+ else
+ info->insn_type = dis_condbranch;
+ info->branch_delay_insns = 1;
+ }
+ else if ((op->pinfo & (INSN_STORE_MEMORY
+ | INSN_LOAD_MEMORY_DELAY)) != 0)
+ info->insn_type = dis_dref;
+
(*info->fprintf_func) (info->stream, "%s", op->name);
d = op->args;
}
/* Handle undefined instructions. */
+ info->insn_type = dis_noninsn;
(*info->fprintf_func) (info->stream, "0x%x", word);
return INSNLEN;
}
else
{
bfd_vma baseaddr;
- bfd_vma val;
if (branch)
{
baseaddr = memaddr - 2;
}
}
- val = (baseaddr & ~((1 << shift) - 1)) + immed;
- (*info->print_address_func) (val, info);
- info->target = val;
+ info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
+ (*info->print_address_func) (info->target, info);
}
}
break;
if (! use_extend)
extend = 0;
l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
- (*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info);
+ info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
+ (*info->print_address_func) (info->target, info);
info->insn_type = dis_jsr;
- info->target = ((memaddr + 4) & 0xf0000000) | l;
info->branch_delay_insns = 1;
break;