Virtualmips: fix disassembler for mips16e mode.
This commit is contained in:
@@ -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. */
|
||||
use_extend = 0;
|
||||
if ((insn & 0xf800) == 0xf000) {
|
||||
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;
|
||||
if (nbytes == 2) {
|
||||
use_extend = 0;
|
||||
insn = opcode;
|
||||
} else {
|
||||
if ((opcode & 0xf8000000) == 0xf0000000) {
|
||||
/* Handle the extend opcode specially. */
|
||||
use_extend = 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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user