Virtualmips: fix disassembler for mips16e mode.

This commit is contained in:
Serge Vakulenko
2015-10-29 13:34:45 -07:00
parent f2c4d11b74
commit 94d38c939f
9 changed files with 2002 additions and 2364 deletions

View File

@@ -151,49 +151,8 @@ static const char *const mips_hwr_names[32] = {
*/
static int no_aliases = 0;
static int big_endian;
static int branch_delay_insns;
static int data_size;
static unsigned target;
enum dis_insn_type {
dis_noninsn, /* Not a valid instruction. */
dis_nonbranch, /* Not a branch instruction. */
dis_branch, /* Unconditional branch. */
dis_condbranch, /* Conditional branch. */
dis_jsr, /* Jump to subroutine. */
dis_condjsr, /* Conditional jump to subroutine. */
dis_dref, /* Data reference instruction. */
dis_dref2 /* Two data references in instruction. */
};
static enum dis_insn_type insn_type;
#if 0
/*
* Get LENGTH bytes from info's buffer, at target address memaddr.
* Transfer them to myaddr.
*/
int
read_memory (unsigned memaddr,
unsigned char *myaddr,
unsigned int nbytes)
{
//unsigned char *buffer;
//unsigned int buffer_length;
//unsigned int buffer_vma;
if (memaddr < buffer_vma ||
memaddr - buffer_vma > buffer_length ||
memaddr - buffer_vma + nbytes > buffer_length) {
/* Out of bounds. Use EIO because GDB uses it. */
return EIO;
}
memcpy (myaddr, info->buffer + memaddr - buffer_vma, nbytes);
return 0;
}
#endif
static void
print_address (unsigned address, FILE *stream)
{
@@ -763,11 +722,9 @@ print_insn_args (const char *d,
}
/*
* Print the mips instruction at address MEMADDR in debugged memory.
* Returns length of the instruction, in bytes, which is
* always INSNLEN.
* Print the mips instruction at address MEMADDR.
*/
int
static void
print_insn_mips (unsigned memaddr,
unsigned long int word, FILE *stream)
{
@@ -794,9 +751,6 @@ print_insn_mips (unsigned memaddr,
init = 1;
}
branch_delay_insns = 0;
data_size = 0;
insn_type = dis_nonbranch;
target = 0;
op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
@@ -807,25 +761,6 @@ print_insn_mips (unsigned memaddr,
&& (word & op->mask) == op->match) {
const char *d;
/* Figure out instruction type and branch delay information. */
if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0) {
if ((op->pinfo & (INSN_WRITE_GPR_31
| INSN_WRITE_GPR_D)) != 0)
insn_type = dis_jsr;
else
insn_type = dis_branch;
branch_delay_insns = 1;
} else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
| INSN_COND_BRANCH_LIKELY)) != 0) {
if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
insn_type = dis_condjsr;
else
insn_type = dis_condbranch;
branch_delay_insns = 1;
} else if ((op->pinfo & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY_DELAY)) != 0)
insn_type = dis_dref;
fprintf (stream, "%s", op->name);
d = op->args;
@@ -833,16 +768,13 @@ print_insn_mips (unsigned memaddr,
fprintf (stream, "\t");
print_insn_args (d, word, memaddr, stream, op);
}
return INSNLEN;
return;
}
}
}
/* Handle undefined instructions. */
insn_type = dis_noninsn;
fprintf (stream, "0x%lx", word);
return INSNLEN;
}
static unsigned
@@ -889,8 +821,7 @@ print_mips16_insn_arg (char type,
const struct mips_opcode *op,
int l,
int use_extend,
int extend, unsigned memaddr, FILE *stream,
int (*read_memory) (unsigned addr, unsigned char *buf, unsigned nbytes))
int extend, unsigned memaddr, FILE *stream)
{
switch (type) {
case ',':
@@ -1017,32 +948,21 @@ print_mips16_insn_arg (char type,
case '5':
nbits = 5;
immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
insn_type = dis_dref;
data_size = 1;
break;
case 'H':
nbits = 5;
shift = 1;
immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
insn_type = dis_dref;
data_size = 2;
break;
case 'W':
nbits = 5;
shift = 2;
immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
&& (op->pinfo & MIPS16_INSN_READ_SP) == 0) {
insn_type = dis_dref;
data_size = 4;
}
break;
case 'D':
nbits = 5;
shift = 3;
immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
insn_type = dis_dref;
data_size = 8;
break;
case 'j':
nbits = 5;
@@ -1063,15 +983,11 @@ print_mips16_insn_arg (char type,
immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
/* FIXME: This might be lw, or it might be addiu to $sp or
* $pc. We assume it's load. */
insn_type = dis_dref;
data_size = 4;
break;
case 'C':
nbits = 8;
shift = 3;
immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
insn_type = dis_dref;
data_size = 8;
break;
case 'U':
nbits = 8;
@@ -1109,16 +1025,12 @@ print_mips16_insn_arg (char type,
immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
pcrel = 1;
/* FIXME: This can be lw or la. We assume it is lw. */
insn_type = dis_dref;
data_size = 4;
break;
case 'B':
nbits = 5;
shift = 3;
immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
pcrel = 1;
insn_type = dis_dref;
data_size = 8;
break;
case 'E':
nbits = 5;
@@ -1158,35 +1070,10 @@ print_mips16_insn_arg (char type,
if (branch) {
immed *= 2;
baseaddr = memaddr + 2;
} else if (use_extend)
} else if (use_extend) {
baseaddr = memaddr - 2;
else {
int status;
unsigned char buffer[2];
} else {
baseaddr = memaddr;
/* If this instruction is in the delay slot of a jr
* instruction, the base address is the address of the
* jr instruction. If it is in the delay slot of jalr
* instruction, the base address is the address of the
* jalr instruction. This test is unreliable: we have
* no way of knowing whether the previous word is
* instruction or data. */
status = read_memory (memaddr - 4, buffer, 2);
if (status == 0
&& (((big_endian ? getb16 (buffer)
: getl16 (buffer))
& 0xf800) == 0x1800))
baseaddr = memaddr - 4;
else {
status = read_memory (memaddr - 2, buffer, 2);
if (status == 0
&& (((big_endian ? getb16 (buffer)
: getl16 (buffer))
& 0xf81f) == 0xe800))
baseaddr = memaddr - 2;
}
}
target = (baseaddr & ~((1 << shift) - 1)) + immed;
if (pcrel && branch)
@@ -1346,67 +1233,33 @@ print_mips16_insn_arg (char type,
}
}
/* Disassemble mips16 instructions. */
static int print_insn_mips16 (unsigned memaddr, FILE *stream,
int (*read_memory) (unsigned addr, unsigned char *buf, unsigned nbytes))
/*
* Disassemble mips16 instructions.
*/
static void print_insn_mips16 (unsigned memaddr,
unsigned int opcode, int nbytes, FILE *stream)
{
int status;
unsigned char buffer[2];
int length;
int insn;
int use_extend;
int extend = 0;
int insn, use_extend, extend;
const struct mips_opcode *op, *opend;
branch_delay_insns = 0;
data_size = 0;
insn_type = dis_nonbranch;
target = 0;
status = read_memory (memaddr, buffer, 2);
if (status != 0) {
memory_error (status, memaddr, stream);
return -1;
}
length = 2;
if (big_endian)
insn = getb16 (buffer);
else
insn = getl16 (buffer);
/* Handle the extend opcode specially. */
insn = opcode;
if (nbytes == 2) {
use_extend = 0;
if ((insn & 0xf800) == 0xf000) {
insn = opcode;
} else {
if ((opcode & 0xf8000000) == 0xf0000000) {
/* Handle the extend opcode specially. */
use_extend = 1;
extend = insn & 0x7ff;
memaddr += 2;
status = read_memory (memaddr, buffer, 2);
if (status != 0) {
fprintf (stream, "extend 0x%x",
(unsigned int) extend);
memory_error (status, memaddr, stream);
return -1;
insn = opcode & 0xffff;
extend = (opcode >> 16) & 0x7ff;
} else {
/* jal, jalx */
use_extend = 0;
insn = opcode >> 16;
extend = opcode & 0xffff;
}
if (big_endian)
insn = getb16 (buffer);
else
insn = getl16 (buffer);
/* Check for an extend opcode followed by an extend opcode. */
if ((insn & 0xf800) == 0xf000) {
fprintf (stream, "extend 0x%x",
(unsigned int) extend);
insn_type = dis_noninsn;
return length;
}
length += 2;
}
/* FIXME: Should probably use a hash table on the major opcode here. */
@@ -1414,33 +1267,9 @@ static int print_insn_mips16 (unsigned memaddr, FILE *stream,
opend = mips16_opcodes + mips16_num_opcodes;
for (op = mips16_opcodes; op < opend; op++) {
if (op->pinfo != INSN_MACRO
&& !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
&& (insn & op->mask) == op->match) {
const char *s;
if (strchr (op->args, 'a') != NULL) {
if (use_extend) {
fprintf (stream, "extend 0x%x",
(unsigned int) extend);
insn_type = dis_noninsn;
return length - 2;
}
use_extend = 0;
memaddr += 2;
status = read_memory (memaddr, buffer, 2);
if (status == 0) {
use_extend = 1;
if (big_endian)
extend = getb16 (buffer);
else
extend = getl16 (buffer);
length += 2;
}
}
fprintf (stream, "%s", op->name);
if (op->args[0] != '\0')
fprintf (stream, "\t");
@@ -1462,68 +1291,39 @@ static int print_insn_mips16 (unsigned memaddr, FILE *stream,
++s;
continue;
}
print_mips16_insn_arg (*s, op, insn, use_extend, extend,
memaddr, stream, read_memory);
print_mips16_insn_arg (*s, op, insn,
use_extend, extend, memaddr, stream);
}
/* Figure out branch instruction type and delay slot information. */
if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
branch_delay_insns = 1;
if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
| MIPS16_INSN_UNCOND_BRANCH)) != 0) {
if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
insn_type = dis_jsr;
else
insn_type = dis_branch;
} else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
insn_type = dis_condbranch;
return length;
return;
}
}
if (use_extend)
fprintf (stream, "0x%x", extend | 0xf000);
fprintf (stream, "0x%x", insn);
insn_type = dis_noninsn;
return length;
}
/*
* 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.
* Disassemble and print the instruction mnemonics.
* Opcode size can be 4 or 2 bytes.
* Parameter `isa' defines an instruction set architecture:
* 0 - mips32 encoding
* 1 - mips16e encoding
* 2 - micromips encoding (someday)
*/
int
print_mips (unsigned memaddr, FILE *stream, int bigendian_flag,
int (*read_memory) (unsigned addr, unsigned char *buf, unsigned nbytes))
void print_mips (unsigned memaddr, unsigned int opcode, int nbytes,
int isa, FILE *stream)
{
unsigned char buffer[INSNLEN];
int status;
big_endian = bigendian_flag;
#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, stream, read_memory);
#endif
status = read_memory (memaddr, buffer, INSNLEN);
if (status == 0) {
unsigned long insn;
if (big_endian)
insn = (unsigned long) getb32 (buffer);
else
insn = (unsigned long) getl32 (buffer);
return print_insn_mips (memaddr, insn, stream);
} else {
memory_error (status, memaddr, stream);
return -1;
switch (isa) {
default:
case 0:
print_insn_mips (memaddr, opcode, stream);
break;
case 1:
print_insn_mips16 (memaddr, opcode, nbytes, stream);
break;
case 2:
/* TODO: micromips encoding */
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -240,9 +240,6 @@ struct mips_opcode
unsigned long pinfo;
/* A collection of additional bits describing the instruction. */
unsigned long pinfo2;
/* A collection of bits describing the instruction sets of which this
instruction or macro is a member. */
unsigned long membership;
};
/* These are the characters which may appear in the args field of an
@@ -494,45 +491,6 @@ struct mips_opcode
same information. */
#define INSN2_M_FP_D 0x00000010
/* Masks used to mark instructions to indicate which MIPS ISA level
they were introduced in. INSN_ISA_MASK masks an enumeration that
specifies the base ISA level(s). The remainder of a 32-bit
word constructed using these macros is a bitmask of the remaining
INSN_* values below. */
#define INSN_ISA_MASK 0x0000000ful
/* We cannot start at zero due to ISA_UNKNOWN below. */
#define INSN_ISA1 1
#define INSN_ISA2 2
#define INSN_ISA3 3
#define INSN_ISA4 4
#define INSN_ISA5 5
#define INSN_ISA32 6
#define INSN_ISA32R2 7
#define INSN_ISA64 8
#define INSN_ISA64R2 9
/* Below this point the INSN_* values correspond to combinations of ISAs.
They are only for use in the opcodes table to indicate membership of
a combination of ISAs that cannot be expressed using the usual inclusion
ordering on the above INSN_* values. */
#define INSN_ISA3_32 10
#define INSN_ISA3_32R2 11
#define INSN_ISA4_32 12
#define INSN_ISA4_32R2 13
#define INSN_ISA5_32R2 14
/* Given INSN_ISA* values X and Y, where X ranges over INSN_ISA1 through
INSN_ISA5_32R2 and Y ranges over INSN_ISA1 through INSN_ISA64R2,
this table describes whether at least one of the ISAs described by X
is/are implemented by ISA Y. (Think of Y as the ISA level supported by
a particular core and X as the ISA level(s) at which a certain instruction
is defined.) The ISA(s) described by X is/are implemented by Y iff
(mips_isa_table[(Y & INSN_ISA_MASK) - 1] >> ((X & INSN_ISA_MASK) - 1)) & 1
is non-zero. */
static const unsigned int mips_isa_table[] =
{ 0x0001, 0x0003, 0x0607, 0x1e0f, 0x3e1f, 0x0a23, 0x3e63, 0x3ebf, 0x3fff };
/* Masks used for Chip specific instructions. */
#define INSN_CHIP_MASK 0xc3ff0820
@@ -640,41 +598,6 @@ static const unsigned int mips_isa_table[] =
#define CPU_OCTEON 6501
#define CPU_XLR 887682 /* decimal 'XLR' */
/* Test for membership in an ISA including chip specific ISAs. INSN
is pointer to an element of the opcode table; ISA is the specified
ISA/ASE bitmask to test against; and CPU is the CPU specific ISA to
test, or zero if no CPU specific ISA test is desired. */
#define OPCODE_IS_MEMBER(insn, isa, cpu) \
(((isa & INSN_ISA_MASK) != 0 \
&& ((insn)->membership & INSN_ISA_MASK) != 0 \
&& ((mips_isa_table [(isa & INSN_ISA_MASK) - 1] >> \
(((insn)->membership & INSN_ISA_MASK) - 1)) & 1) != 0) \
|| ((isa & ~INSN_ISA_MASK) \
& ((insn)->membership & ~INSN_ISA_MASK)) != 0 \
|| (cpu == CPU_R4650 && ((insn)->membership & INSN_4650) != 0) \
|| (cpu == CPU_RM7000 && ((insn)->membership & INSN_4650) != 0) \
|| (cpu == CPU_RM9000 && ((insn)->membership & INSN_4650) != 0) \
|| (cpu == CPU_R4010 && ((insn)->membership & INSN_4010) != 0) \
|| (cpu == CPU_VR4100 && ((insn)->membership & INSN_4100) != 0) \
|| (cpu == CPU_R3900 && ((insn)->membership & INSN_3900) != 0) \
|| ((cpu == CPU_R10000 || cpu == CPU_R12000 || cpu == CPU_R14000 \
|| cpu == CPU_R16000) \
&& ((insn)->membership & INSN_10000) != 0) \
|| (cpu == CPU_SB1 && ((insn)->membership & INSN_SB1) != 0) \
|| (cpu == CPU_R4111 && ((insn)->membership & INSN_4111) != 0) \
|| (cpu == CPU_VR4120 && ((insn)->membership & INSN_4120) != 0) \
|| (cpu == CPU_VR5400 && ((insn)->membership & INSN_5400) != 0) \
|| (cpu == CPU_VR5500 && ((insn)->membership & INSN_5500) != 0) \
|| (cpu == CPU_LOONGSON_2E \
&& ((insn)->membership & INSN_LOONGSON_2E) != 0) \
|| (cpu == CPU_LOONGSON_2F \
&& ((insn)->membership & INSN_LOONGSON_2F) != 0) \
|| (cpu == CPU_OCTEON \
&& ((insn)->membership & INSN_OCTEON) != 0) \
|| (cpu == CPU_XLR && ((insn)->membership & INSN_XLR) != 0) \
|| 0) /* Please keep this term for easier source merging. */
/* This is a list of macro expanded instructions.
_I appended means immediate

View File

@@ -384,7 +384,7 @@ if (code == 1) cpu->vm->debug_level = 1;
printf (") at %08x\n", cpu->pc);
return;
}
printf ("\n*** 0x%08x: exception ", cpu->pc);
printf ("\n--- 0x%08x: exception ", cpu->pc);
switch (exc_code) {
case MIPS_CP0_CAUSE_INTERRUPT: code = "Interrupt"; break;
@@ -407,7 +407,7 @@ if (code == 1) cpu->vm->debug_level = 1;
switch (exc_code) {
case MIPS_CP0_CAUSE_ADDR_LOAD:
case MIPS_CP0_CAUSE_ADDR_SAVE:
printf ("*** badvaddr = 0x%08x\n", cpu->cp0.reg[MIPS_CP0_BADVADDR]);
printf ("--- badvaddr = 0x%08x\n", cpu->cp0.reg[MIPS_CP0_BADVADDR]);
break;
}
printf (" t0 = %8x s0 = %8x t8 = %8x lo = %8x\n",
@@ -466,10 +466,6 @@ void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot)
/*TODO: RESET SOFT RESET AND NMI EXCEPTION */
cp0->reg[MIPS_CP0_STATUS] &= ~MIPS_CP0_STATUS_ERL;
if (cpu->vm->debug_level > 2) {
printf (" exception %u at %08x\n", exc_code, cpu->pc);
}
/* Compute the vector address. */
if (cp0->reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_BEV) {
/* Boot exception vector. */
@@ -493,9 +489,15 @@ void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot)
}
}
if (exc_code != MIPS_CP0_CAUSE_INTERRUPT &&
(exc_code != MIPS_CP0_CAUSE_SYSCALL || cpu->vm->debug_level > 0))
if (cpu->vm->debug_level > 2 ||
(exc_code != MIPS_CP0_CAUSE_INTERRUPT &&
(exc_code != MIPS_CP0_CAUSE_SYSCALL ||
cpu->vm->debug_level > 0)))
{
print_exception (cpu, exc_code);
if (cpu->vm->debug_level > 2)
printf ("\n");
}
cpu->pc = (m_va_t) new_pc;
@@ -537,11 +539,10 @@ void fastcall mips_exec_eret (cpu_mips_t * cpu)
void fastcall mips_exec_break (cpu_mips_t * cpu, u_int code)
{
//mips_dump_regs(cpu);
printf ("exec break cpu->pc %x\n", cpu->pc);
//printf ("exec break cpu->pc %x\n", cpu->pc);
/* XXX TODO: Branch Delay slot */
mips_trigger_exception (cpu, MIPS_CP0_CAUSE_BP, 0);
}
/* Trigger a Trap Exception */

View File

@@ -492,8 +492,16 @@ void mips_clear_irq (cpu_mips_t * cpu, m_uint8_t irq);
void set_timer_irq (cpu_mips_t *cpu);
void clear_timer_irq (cpu_mips_t *cpu);
/* Print the mips instruction at address MEMADDR in debugged memory. */
int print_insn_mips (unsigned memaddr, unsigned long int word, FILE *stream);
/*
* Disassemble and print the instruction mnemonics.
* Opcode size can be 4 or 2 bytes.
* Parameter `isa' defines an instruction set architecture:
* 0 - mips32 encoding
* 1 - mips16e encoding
* 2 - micromips encoding (someday)
*/
void print_mips (unsigned memaddr, unsigned int opcode, int nbytes,
int isa, FILE *stream);
const char *cp0reg_name (unsigned cp0reg, unsigned sel);

View File

@@ -44,186 +44,180 @@
#define TRAP INSN_TRAP
#define I1 INSN_ISA1
#define I3 INSN_ISA3
#define I32 INSN_ISA32
#define I64 INSN_ISA64
#define T3 INSN_3900
static const struct mips_opcode mips16_opcodes[] =
{
/* name, args, match, mask, pinfo, pinfo2, membership */
{"nop", "", 0x6500, 0xffff, RD_Z, 0, I1 }, /* move $0,$Z */
{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 },
{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO, 0, I1 },
{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, I1 },
{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, I1 },
{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 },
{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 },
{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 },
{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, I1 },
{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y, 0, I1 },
{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, 0, I1 },
{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x, 0, I1 },
{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 },
{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, 0, I1 },
{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, 0, I1 },
{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, 0, I1 },
{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
{"b", "q", 0x1000, 0xf800, UBR, 0, I1 },
{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, 0, I1 },
{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, 0, I1 },
{"beqz", "x,p", 0x2000, 0xf800, CBR|RD_x, 0, I1 },
{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, 0, I1 },
{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, 0, I1 },
{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, 0, I1 },
{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO, 0, I1 },
{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO, 0, I1 },
{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO, 0, I1 },
{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO, 0, I1 },
{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO, 0, I1 },
{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO, 0, I1 },
{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO, 0, I1 },
{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO, 0, I1 },
{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO, 0, I1 },
{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO, 0, I1 },
{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO, 0, I1 },
{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO, 0, I1 },
{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, 0, I1 },
{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, 0, I1 },
{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, 0, I1 },
{"bnez", "x,p", 0x2800, 0xf800, CBR|RD_x, 0, I1 },
{"break", "6", 0xe805, 0xf81f, TRAP, 0, I1 },
{"bteqz", "p", 0x6000, 0xff00, CBR|RD_T, 0, I1 },
{"btnez", "p", 0x6100, 0xff00, CBR|RD_T, 0, I1 },
{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 },
{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, 0, I1 },
{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, 0, I1 },
{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 },
{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 },
{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 },
{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 },
{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 },
{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 },
{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 },
{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y, 0, I3 },
{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, 0, I3 },
{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, 0, I3 },
{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 },
{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, 0, I3 },
{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, 0, I3 },
{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, 0, I3 },
{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO, 0, I1 },
{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO, 0, I1 },
{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO, 0, I1 },
{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO, 0, I1 },
{"dmul", "z,v,y", 0, (int) M_DMUL, INSN_MACRO, 0, I3 },
{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO, 0, I1 },
{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I3 },
{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO, 0, I1 },
{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y, 0, I3 },
{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y, 0, I3 },
{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y, 0, I3 },
{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, 0, I3 },
{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y, 0, I3 },
{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO, 0, I1 },
{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO, 0, I1 },
{"exit", "L", 0xed09, 0xff1f, TRAP, 0, I1 },
{"exit", "L", 0xee09, 0xff1f, TRAP, 0, I1 },
{"exit", "L", 0xef09, 0xff1f, TRAP, 0, I1 },
{"entry", "l", 0xe809, 0xf81f, TRAP, 0, I1 },
{"extend", "e", 0xf000, 0xf800, 0, 0, I1 },
{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, 0, I1 },
{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, 0, I1 },
{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, 0, I1 },
{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 },
{"jr", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 },
{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, 0, I1 },
{"j", "R", 0xe820, 0xffff, UBD|RD_31, 0, I1 },
{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, 0, I1 },
{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, 0, I1 },
{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, 0, I3 },
{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 },
{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC, 0, I3 },
{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP, 0, I3 },
{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x, 0, I1 },
{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x, 0, I1 },
{"li", "x,U", 0x6800, 0xf800, WR_x, 0, I1 },
{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x, 0, I1 },
{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC, 0, I1 },
{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, 0, I1 },
{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, 0, I1 },
{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, 0, I3 },
{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, 0, I1 },
{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, 0, I1 },
{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, 0, I1 },
{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, 0, I1 },
{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, 0, I1 },
{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y, 0, I1 },
{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y, 0, I1 },
{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO, 0, I1 },
{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, 0, I1 },
{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO, 0, I1 },
{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x, 0, I1 },
{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x, 0, I3 },
{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC, 0, I3 },
{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC, 0, I1 },
{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x, 0, I1 },
{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y, 0, I1 },
{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, I1 },
{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y, 0, I1 },
{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x, 0, I1 },
{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, I1 },
{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y, 0, I1 },
{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x, 0, I1 },
{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y, 0, I1 },
{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y, 0, I1 },
{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, 0, I1 },
{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y, 0, I1 },
{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO, 0, I1 },
{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO,0, I1 },
{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x, 0, I1 },
{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP, 0, I1 },
{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, 0, I1 },
{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, 0, I1 },
/* name, args, match, mask, pinfo */
{"nop", "", 0x6500, 0xffff, RD_Z, }, /* move $0,$Z */
{"la", "x,A", 0x0800, 0xf800, WR_x|RD_PC, },
{"abs", "x,w", 0, (int) M_ABS, INSN_MACRO, },
{"addiu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, },
{"addiu", "x,k", 0x4800, 0xf800, WR_x|RD_x, },
{"addiu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, },
{"addiu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, },
{"addiu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, },
{"addiu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, },
{"addu", "z,v,y", 0xe001, 0xf803, WR_z|RD_x|RD_y, },
{"addu", "y,x,4", 0x4000, 0xf810, WR_y|RD_x, },
{"addu", "x,k", 0x4800, 0xf800, WR_x|RD_x, },
{"addu", "S,K", 0x6300, 0xff00, WR_SP|RD_SP, },
{"addu", "S,S,K", 0x6300, 0xff00, WR_SP|RD_SP, },
{"addu", "x,P,V", 0x0800, 0xf800, WR_x|RD_PC, },
{"addu", "x,S,V", 0x0000, 0xf800, WR_x|RD_SP, },
{"and", "x,y", 0xe80c, 0xf81f, WR_x|RD_x|RD_y, },
{"b", "q", 0x1000, 0xf800, UBR, },
{"beq", "x,y,p", 0, (int) M_BEQ, INSN_MACRO, },
{"beq", "x,U,p", 0, (int) M_BEQ_I, INSN_MACRO, },
{"beqz", "x,p", 0x2000, 0xf800, CBR|RD_x, },
{"bge", "x,y,p", 0, (int) M_BGE, INSN_MACRO, },
{"bge", "x,8,p", 0, (int) M_BGE_I, INSN_MACRO, },
{"bgeu", "x,y,p", 0, (int) M_BGEU, INSN_MACRO, },
{"bgeu", "x,8,p", 0, (int) M_BGEU_I, INSN_MACRO, },
{"bgt", "x,y,p", 0, (int) M_BGT, INSN_MACRO, },
{"bgt", "x,8,p", 0, (int) M_BGT_I, INSN_MACRO, },
{"bgtu", "x,y,p", 0, (int) M_BGTU, INSN_MACRO, },
{"bgtu", "x,8,p", 0, (int) M_BGTU_I, INSN_MACRO, },
{"ble", "x,y,p", 0, (int) M_BLE, INSN_MACRO, },
{"ble", "x,8,p", 0, (int) M_BLE_I, INSN_MACRO, },
{"bleu", "x,y,p", 0, (int) M_BLEU, INSN_MACRO, },
{"bleu", "x,8,p", 0, (int) M_BLEU_I, INSN_MACRO, },
{"blt", "x,y,p", 0, (int) M_BLT, INSN_MACRO, },
{"blt", "x,8,p", 0, (int) M_BLT_I, INSN_MACRO, },
{"bltu", "x,y,p", 0, (int) M_BLTU, INSN_MACRO, },
{"bltu", "x,8,p", 0, (int) M_BLTU_I, INSN_MACRO, },
{"bne", "x,y,p", 0, (int) M_BNE, INSN_MACRO, },
{"bne", "x,U,p", 0, (int) M_BNE_I, INSN_MACRO, },
{"bnez", "x,p", 0x2800, 0xf800, CBR|RD_x, },
{"break", "6", 0xe805, 0xf81f, TRAP, },
{"bteqz", "p", 0x6000, 0xff00, CBR|RD_T, },
{"btnez", "p", 0x6100, 0xff00, CBR|RD_T, },
{"cmpi", "x,U", 0x7000, 0xf800, WR_T|RD_x, },
{"cmp", "x,y", 0xe80a, 0xf81f, WR_T|RD_x|RD_y, },
{"cmp", "x,U", 0x7000, 0xf800, WR_T|RD_x, },
{"dla", "y,E", 0xfe00, 0xff00, WR_y|RD_PC, },
{"daddiu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, },
{"daddiu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, },
{"daddiu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, },
{"daddiu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, },
{"daddiu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, },
{"daddiu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, },
{"daddu", "z,v,y", 0xe000, 0xf803, WR_z|RD_x|RD_y, },
{"daddu", "y,x,4", 0x4010, 0xf810, WR_y|RD_x, },
{"daddu", "y,j", 0xfd00, 0xff00, WR_y|RD_y, },
{"daddu", "S,K", 0xfb00, 0xff00, WR_SP|RD_SP, },
{"daddu", "S,S,K", 0xfb00, 0xff00, WR_SP|RD_SP, },
{"daddu", "y,P,W", 0xfe00, 0xff00, WR_y|RD_PC, },
{"daddu", "y,S,W", 0xff00, 0xff00, WR_y|RD_SP, },
{"ddiv", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"ddiv", "z,v,y", 0, (int) M_DDIV_3, INSN_MACRO, },
{"ddivu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"ddivu", "z,v,y", 0, (int) M_DDIVU_3, INSN_MACRO, },
{"div", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"div", "z,v,y", 0, (int) M_DIV_3, INSN_MACRO, },
{"divu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"divu", "z,v,y", 0, (int) M_DIVU_3, INSN_MACRO, },
{"dmul", "z,v,y", 0, (int) M_DMUL, INSN_MACRO, },
{"dmult", "x,y", 0xe81c, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"dmultu", "x,y", 0xe81d, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"drem", "0,x,y", 0xe81e, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"drem", "z,v,y", 0, (int) M_DREM_3, INSN_MACRO, },
{"dremu", "0,x,y", 0xe81f, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"dremu", "z,v,y", 0, (int) M_DREMU_3, INSN_MACRO, },
{"dsllv", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, },
{"dsll", "x,w,[", 0x3001, 0xf803, WR_x|RD_y, },
{"dsll", "y,x", 0xe814, 0xf81f, WR_y|RD_y|RD_x, },
{"dsrav", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, },
{"dsra", "y,]", 0xe813, 0xf81f, WR_y|RD_y, },
{"dsra", "y,x", 0xe817, 0xf81f, WR_y|RD_y|RD_x, },
{"dsrlv", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, },
{"dsrl", "y,]", 0xe808, 0xf81f, WR_y|RD_y, },
{"dsrl", "y,x", 0xe816, 0xf81f, WR_y|RD_y|RD_x, },
{"dsubu", "z,v,y", 0xe002, 0xf803, WR_z|RD_x|RD_y, },
{"dsubu", "y,x,4", 0, (int) M_DSUBU_I, INSN_MACRO, },
{"dsubu", "y,j", 0, (int) M_DSUBU_I_2, INSN_MACRO, },
{"exit", "L", 0xed09, 0xff1f, TRAP, },
{"exit", "L", 0xee09, 0xff1f, TRAP, },
{"exit", "L", 0xef09, 0xff1f, TRAP, },
{"entry", "l", 0xe809, 0xf81f, TRAP, },
{"extend", "e", 0xf000, 0xf800, 0, },
{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jal", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jal", "a", 0x1800, 0xfc00, UBD|WR_31, },
{"jalx", "a", 0x1c00, 0xfc00, UBD|WR_31, },
{"jr", "x", 0xe800, 0xf8ff, UBD|RD_x, },
{"jr", "R", 0xe820, 0xffff, UBD|RD_31, },
{"j", "x", 0xe800, 0xf8ff, UBD|RD_x, },
{"j", "R", 0xe820, 0xffff, UBD|RD_31, },
{"lb", "y,5(x)", 0x8000, 0xf800, WR_y|RD_x, },
{"lbu", "y,5(x)", 0xa000, 0xf800, WR_y|RD_x, },
{"ld", "y,D(x)", 0x3800, 0xf800, WR_y|RD_x, },
{"ld", "y,B", 0xfc00, 0xff00, WR_y|RD_PC, },
{"ld", "y,D(P)", 0xfc00, 0xff00, WR_y|RD_PC, },
{"ld", "y,D(S)", 0xf800, 0xff00, WR_y|RD_SP, },
{"lh", "y,H(x)", 0x8800, 0xf800, WR_y|RD_x, },
{"lhu", "y,H(x)", 0xa800, 0xf800, WR_y|RD_x, },
{"li", "x,U", 0x6800, 0xf800, WR_x, },
{"lw", "y,W(x)", 0x9800, 0xf800, WR_y|RD_x, },
{"lw", "x,A", 0xb000, 0xf800, WR_x|RD_PC, },
{"lw", "x,V(P)", 0xb000, 0xf800, WR_x|RD_PC, },
{"lw", "x,V(S)", 0x9000, 0xf800, WR_x|RD_SP, },
{"lwu", "y,W(x)", 0xb800, 0xf800, WR_y|RD_x, },
{"mfhi", "x", 0xe810, 0xf8ff, WR_x|RD_HI, },
{"mflo", "x", 0xe812, 0xf8ff, WR_x|RD_LO, },
{"move", "y,X", 0x6700, 0xff00, WR_y|RD_X, },
{"move", "Y,Z", 0x6500, 0xff00, WR_Y|RD_Z, },
{"mul", "z,v,y", 0, (int) M_MUL, INSN_MACRO, },
{"mult", "x,y", 0xe818, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"multu", "x,y", 0xe819, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"neg", "x,w", 0xe80b, 0xf81f, WR_x|RD_y, },
{"not", "x,w", 0xe80f, 0xf81f, WR_x|RD_y, },
{"or", "x,y", 0xe80d, 0xf81f, WR_x|RD_x|RD_y, },
{"rem", "0,x,y", 0xe81a, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"rem", "z,v,y", 0, (int) M_REM_3, INSN_MACRO, },
{"remu", "0,x,y", 0xe81b, 0xf81f, RD_x|RD_y|WR_HI|WR_LO, },
{"remu", "z,v,y", 0, (int) M_REMU_3, INSN_MACRO, },
{"sb", "y,5(x)", 0xc000, 0xf800, RD_y|RD_x, },
{"sd", "y,D(x)", 0x7800, 0xf800, RD_y|RD_x, },
{"sd", "y,D(S)", 0xf900, 0xff00, RD_y|RD_PC, },
{"sd", "R,C(S)", 0xfa00, 0xff00, RD_31|RD_PC, },
{"sh", "y,H(x)", 0xc800, 0xf800, RD_y|RD_x, },
{"sllv", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, },
{"sll", "x,w,<", 0x3000, 0xf803, WR_x|RD_y, },
{"sll", "y,x", 0xe804, 0xf81f, WR_y|RD_y|RD_x, },
{"slti", "x,8", 0x5000, 0xf800, WR_T|RD_x, },
{"slt", "x,y", 0xe802, 0xf81f, WR_T|RD_x|RD_y, },
{"slt", "x,8", 0x5000, 0xf800, WR_T|RD_x, },
{"sltiu", "x,8", 0x5800, 0xf800, WR_T|RD_x, },
{"sltu", "x,y", 0xe803, 0xf81f, WR_T|RD_x|RD_y, },
{"sltu", "x,8", 0x5800, 0xf800, WR_T|RD_x, },
{"srav", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, },
{"sra", "x,w,<", 0x3003, 0xf803, WR_x|RD_y, },
{"sra", "y,x", 0xe807, 0xf81f, WR_y|RD_y|RD_x, },
{"srlv", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, },
{"srl", "x,w,<", 0x3002, 0xf803, WR_x|RD_y, },
{"srl", "y,x", 0xe806, 0xf81f, WR_y|RD_y|RD_x, },
{"subu", "z,v,y", 0xe003, 0xf803, WR_z|RD_x|RD_y, },
{"subu", "y,x,4", 0, (int) M_SUBU_I, INSN_MACRO, },
{"subu", "x,k", 0, (int) M_SUBU_I_2, INSN_MACRO, },
{"sw", "y,W(x)", 0xd800, 0xf800, RD_y|RD_x, },
{"sw", "x,V(S)", 0xd000, 0xf800, RD_x|RD_SP, },
{"sw", "R,V(S)", 0x6200, 0xff00, RD_31|RD_SP, },
{"xor", "x,y", 0xe80e, 0xf81f, WR_x|RD_x|RD_y, },
/* MIPS16e additions */
{"jalrc", "x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
{"jalrc", "R,x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, 0, I32 },
{"jrc", "x", 0xe880, 0xf8ff, UBR|RD_x|TRAP, 0, I32 },
{"jrc", "R", 0xe8a0, 0xffff, UBR|RD_31|TRAP, 0, I32 },
{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0, I32 },
{"sdbbp", "6", 0xe801, 0xf81f, TRAP, 0, I32 },
{"seb", "x", 0xe891, 0xf8ff, WR_x|RD_x, 0, I32 },
{"seh", "x", 0xe8b1, 0xf8ff, WR_x|RD_x, 0, I32 },
{"sew", "x", 0xe8d1, 0xf8ff, WR_x|RD_x, 0, I64 },
{"zeb", "x", 0xe811, 0xf8ff, WR_x|RD_x, 0, I32 },
{"zeh", "x", 0xe831, 0xf8ff, WR_x|RD_x, 0, I32 },
{"zew", "x", 0xe851, 0xf8ff, WR_x|RD_x, 0, I64 },
{"jalrc", "x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, },
{"jalrc", "R,x", 0xe8c0, 0xf8ff, UBR|WR_31|RD_x|TRAP, },
{"jrc", "x", 0xe880, 0xf8ff, UBR|RD_x|TRAP, },
{"jrc", "R", 0xe8a0, 0xffff, UBR|RD_31|TRAP, },
{"restore", "M", 0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, },
{"save", "m", 0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, },
{"sdbbp", "6", 0xe801, 0xf81f, TRAP, },
{"seb", "x", 0xe891, 0xf8ff, WR_x|RD_x, },
{"seh", "x", 0xe8b1, 0xf8ff, WR_x|RD_x, },
{"sew", "x", 0xe8d1, 0xf8ff, WR_x|RD_x, },
{"zeb", "x", 0xe811, 0xf8ff, WR_x|RD_x, },
{"zeh", "x", 0xe831, 0xf8ff, WR_x|RD_x, },
{"zew", "x", 0xe851, 0xf8ff, WR_x|RD_x, },
};
static const int mips16_num_opcodes =
@@ -252,8 +246,3 @@ static const int mips16_num_opcodes =
#undef RD_HI
#undef RD_LO
#undef TRAP
#undef I1
#undef I3
#undef I32
#undef I64
#undef T3

View File

@@ -11,7 +11,7 @@ static int unknown_op (cpu_mips_t * cpu, mips_insn_t insn)
{
printf ("--- Unknown instruction:\n");
printf ("%08x: %08x ", cpu->pc, insn);
print_insn_mips (cpu->pc, insn, stdout);
print_mips (cpu->pc, insn, cpu->insn_len, cpu->is_mips16e, stdout);
printf ("\n");
exit (EXIT_FAILURE);
}

View File

@@ -239,7 +239,7 @@ start_cpu:
if (cpu->vm->trace_address == cpu->pc) {
/* Trace address. */
printf ("*** %08x: %08x ", cpu->pc, insn);
print_insn_mips (cpu->pc, insn, stdout);
print_mips (cpu->pc, insn, cpu->insn_len, cpu->is_mips16e, stdout);
printf ("\n");
dumpregs (cpu);
}
@@ -264,8 +264,13 @@ start_cpu:
! (cpu->cp0.reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_EXL)))
{
/* Print instructions in user mode. */
printf ("%08x: %08x ", cpu->pc, insn);
print_insn_mips (cpu->pc, insn, stdout);
printf ("%08x: ", cpu->pc);
if (insn_len == 2)
printf (" %04x ", insn);
else
printf ("%08x ", insn);
print_mips (cpu->pc, insn, insn_len, cpu->is_mips16e, stdout);
printf ("\n");
fflush (stdout);
#if 0
@@ -340,7 +345,7 @@ static forced_inline int mips_exec_bdslot (cpu_mips_t * cpu)
{
/* Print instructions in user mode. */
printf ("%08x: %08x ", cpu->pc + insn_len, insn);
print_insn_mips (cpu->pc, insn, stdout);
print_mips (cpu->pc, insn, insn_len, cpu->is_mips16e, stdout);
printf ("\n");
fflush (stdout);
}

View File

@@ -32,12 +32,12 @@ void bad_memory_access (cpu_mips_t * cpu, m_va_t vaddr)
printf ("*** %08x: bad memory reference\n", vaddr);
if (mips_fetch_instruction (cpu, cpu->pc, &insn) == 0) {
printf ("*** %08x: %08x ", cpu->pc, insn);
print_insn_mips (cpu->pc, insn, stdout);
print_mips (cpu->pc, insn, cpu->insn_len, cpu->is_mips16e, stdout);
printf ("\n");
}
if (mips_fetch_instruction (cpu, cpu->pc + 4, &insn) == 0) {
printf ("*** %08x: %08x ", cpu->pc + 4, insn);
print_insn_mips (cpu->pc, insn, stdout);
print_mips (cpu->pc, insn, cpu->insn_len, cpu->is_mips16e, stdout);
printf ("\n");
}
dumpregs (cpu);