mips3: Added disassembler for Emotion Engine core opcodes. VU macro ops are still to-do. [Ryan Holtz]

This commit is contained in:
mooglyguy 2018-06-23 12:59:15 +02:00
parent b307f27d54
commit dd30364632
6 changed files with 705 additions and 313 deletions

View File

@ -115,6 +115,7 @@ DEFINE_DEVICE_TYPE(R5000BE, r5000be_device, "r5000be", "MIPS R5000 (big)")
DEFINE_DEVICE_TYPE(R5000LE, r5000le_device, "r5000le", "MIPS R5000 (little)")
DEFINE_DEVICE_TYPE(VR5500BE, vr5500be_device, "vr5500be", "NEC VR5500 (big)")
DEFINE_DEVICE_TYPE(VR5500LE, vr5500le_device, "vr5500le", "NEC VR5500 (little)")
DEFINE_DEVICE_TYPE(R5900LE, r5900le_device, "r5900le", "Emotion Engine Core")
DEFINE_DEVICE_TYPE(QED5271BE, qed5271be_device, "qed5271be", "MIPS QED5271 (big)")
DEFINE_DEVICE_TYPE(QED5271LE, qed5271le_device, "qed5271le", "MIPS QED5271 (little)")
DEFINE_DEVICE_TYPE(RM7000BE, rm7000be_device, "rm7000be", "MIPS RM7000 (big)")
@ -334,6 +335,7 @@ void mips3_device::device_start()
/* initialize based on the config */
memset(m_core, 0, sizeof(internal_mips3_state));
m_core->vfr[0][3] = 1.0f;
m_cpu_clock = clock();
m_program = &space(AS_PROGRAM);
@ -986,12 +988,16 @@ bool mips3_device::memory_translate(int spacenum, int intention, offs_t &address
return true;
}
std::unique_ptr<util::disasm_interface> mips3_device::create_disassembler()
{
return std::make_unique<mips3_disassembler>();
}
std::unique_ptr<util::disasm_interface> r5900le_device::create_disassembler()
{
return std::make_unique<ee_disassembler>();
}
/***************************************************************************
@ -2556,21 +2562,21 @@ void mips3_device::handle_regimm(uint32_t op)
{
switch (RTREG)
{
case 0x00: /* BLTZ */ if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); break;
case 0x01: /* BGEZ */ if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); break;
case 0x02: /* BLTZL */ if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
case 0x03: /* BGEZL */ if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
case 0x08: /* TGEI */ if ((int64_t)RSVAL64 >= SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x09: /* TGEIU */ if (RSVAL64 >= UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0a: /* TLTI */ if ((int64_t)RSVAL64 < SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0b: /* TLTIU */ if (RSVAL64 >= UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0c: /* TEQI */ if (RSVAL64 == UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0e: /* TNEI */ if (RSVAL64 != UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x00: /* BLTZ */ if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); break;
case 0x01: /* BGEZ */ if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); break;
case 0x02: /* BLTZL */ if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
case 0x03: /* BGEZL */ if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
case 0x08: /* TGEI */ if ((int64_t)RSVAL64 >= SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x09: /* TGEIU */ if (RSVAL64 >= UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0a: /* TLTI */ if ((int64_t)RSVAL64 < SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0b: /* TLTIU */ if (RSVAL64 >= UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0c: /* TEQI */ if (RSVAL64 == UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x0e: /* TNEI */ if (RSVAL64 != UIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x10: /* BLTZAL */ m_core->r[31] = (int32_t)(m_core->pc + 4); if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); break;
case 0x11: /* BGEZAL */ m_core->r[31] = (int32_t)(m_core->pc + 4); if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); break;
case 0x12: /* BLTZALL */ m_core->r[31] = (int32_t)(m_core->pc + 4); if ((int64_t)RSVAL64 < 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
case 0x13: /* BGEZALL */ m_core->r[31] = (int32_t)(m_core->pc + 4); if ((int64_t)RSVAL64 >= 0) ADDPC(SIMMVAL); else m_core->pc += 4; break;
default: /* ??? */ invalid_instruction(op); break;
default: /* ??? */ handle_extra_regimm(op); break;
}
}
@ -2683,18 +2689,18 @@ void mips3_device::handle_special(uint32_t op)
if (ENABLE_OVERFLOWS && RSVAL32 > ~RTVAL32) generate_exception(EXCEPTION_OVERFLOW, 1);
else if (RDREG) RDVAL64 = (int32_t)(RSVAL32 + RTVAL32);
break;
case 0x21: /* ADDU */ if (RDREG) RDVAL64 = (int32_t)(RSVAL32 + RTVAL32); break;
case 0x21: /* ADDU */ if (RDREG) RDVAL64 = (int32_t)(RSVAL32 + RTVAL32); break;
case 0x22: /* SUB */
if (ENABLE_OVERFLOWS && RSVAL32 < RTVAL32) generate_exception(EXCEPTION_OVERFLOW, 1);
else if (RDREG) RDVAL64 = (int32_t)(RSVAL32 - RTVAL32);
break;
case 0x23: /* SUBU */ if (RDREG) RDVAL64 = (int32_t)(RSVAL32 - RTVAL32); break;
case 0x23: /* SUBU */ if (RDREG) RDVAL64 = (int32_t)(RSVAL32 - RTVAL32); break;
case 0x24: /* AND */ if (RDREG) RDVAL64 = RSVAL64 & RTVAL64; break;
case 0x25: /* OR */ if (RDREG) RDVAL64 = RSVAL64 | RTVAL64; break;
case 0x26: /* XOR */ if (RDREG) RDVAL64 = RSVAL64 ^ RTVAL64; break;
case 0x27: /* NOR */ if (RDREG) RDVAL64 = ~(RSVAL64 | RTVAL64); break;
case 0x2a: /* SLT */ if (RDREG) RDVAL64 = (int64_t)RSVAL64 < (int64_t)RTVAL64; break;
case 0x2b: /* SLTU */ if (RDREG) RDVAL64 = (uint64_t)RSVAL64 < (uint64_t)RTVAL64; break;
case 0x2a: /* SLT */ if (RDREG) RDVAL64 = (int64_t)RSVAL64 < (int64_t)RTVAL64; break;
case 0x2b: /* SLTU */ if (RDREG) RDVAL64 = (uint64_t)RSVAL64 < (uint64_t)RTVAL64; break;
case 0x2c: /* DADD */
if (ENABLE_OVERFLOWS && RSVAL64 > ~RTVAL64) generate_exception(EXCEPTION_OVERFLOW, 1);
else if (RDREG) RDVAL64 = RSVAL64 + RTVAL64;
@ -2713,14 +2719,50 @@ void mips3_device::handle_special(uint32_t op)
case 0x36: /* TNE */ if (RSVAL64 != RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
case 0x38: /* DSLL */ if (RDREG) RDVAL64 = RTVAL64 << SHIFT; break;
case 0x3a: /* DSRL */ if (RDREG) RDVAL64 = RTVAL64 >> SHIFT; break;
case 0x3b: /* DSRA */ if (RDREG) RDVAL64 = (int64_t)RTVAL64 >> SHIFT; break;
case 0x3b: /* DSRA */ if (RDREG) RDVAL64 = (int64_t)RTVAL64 >> SHIFT; break;
case 0x3c: /* DSLL32 */ if (RDREG) RDVAL64 = RTVAL64 << (SHIFT + 32); break;
case 0x3e: /* DSRL32 */ if (RDREG) RDVAL64 = RTVAL64 >> (SHIFT + 32); break;
case 0x3f: /* DSRA32 */ if (RDREG) RDVAL64 = (int64_t)RTVAL64 >> (SHIFT + 32); break;
default: /* ??? */ invalid_instruction(op); break;
case 0x3f: /* DSRA32 */ if (RDREG) RDVAL64 = (int64_t)RTVAL64 >> (SHIFT + 32); break;
default: /* ??? */ handle_extra_special(op); break;
}
}
void mips3_device::handle_extra_special(uint32_t op)
{
invalid_instruction(op);
}
void r5900le_device::handle_extra_special(uint32_t op)
{
}
void mips3_device::handle_extra_regimm(uint32_t op)
{
invalid_instruction(op);
}
void r5900le_device::handle_extra_regimm(uint32_t op)
{
}
void mips3_device::handle_idt(uint32_t op)
{
switch (op & 0x1f)
{
case 2: /* MUL */
RDVAL64 = (int32_t)((int32_t)RSVAL32 * (int32_t)RTVAL32);
m_core->icount -= 3;
break;
default:
invalid_instruction(op);
break;
}
}
void r5900le_device::handle_idt(uint32_t op)
{
}
void mips3_device::burn_cycles(int32_t cycles)
{
execute_burn(cycles);
@ -2858,14 +2900,7 @@ void mips3_device::execute_run()
case 0x1a: /* LDL */ (this->*m_ldl)(op); break;
case 0x1b: /* LDR */ (this->*m_ldr)(op); break;
case 0x1c: /* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
switch (op & 0x1f)
{
case 2: /* MUL */
RDVAL64 = (int32_t)((int32_t)RSVAL32 * (int32_t)RTVAL32);
m_core->icount -= 3;
break;
default: invalid_instruction(op);
}
handle_idt(op);
break;
case 0x20: /* LB */ if (RBYTE(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (int8_t)temp; break;
case 0x21: /* LH */ if (RHALF(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (int16_t)temp; break;

View File

@ -42,6 +42,7 @@ DECLARE_DEVICE_TYPE(QED5271BE, qed5271be_device)
DECLARE_DEVICE_TYPE(QED5271LE, qed5271le_device)
DECLARE_DEVICE_TYPE(RM7000BE, rm7000be_device)
DECLARE_DEVICE_TYPE(RM7000LE, rm7000le_device)
DECLARE_DEVICE_TYPE(R5900LE, r5900le_device)
/***************************************************************************
@ -260,6 +261,7 @@ protected:
MIPS3_TYPE_R5000,
MIPS3_TYPE_VR5500,
MIPS3_TYPE_QED5271,
MIPS3_TYPE_R5900,
MIPS3_TYPE_RM7000
};
@ -309,73 +311,79 @@ private:
struct internal_mips3_state
{
/* core registers */
uint32_t pc;
int icount;
uint64_t r[35];
uint32_t pc;
int icount;
uint64_t r[35];
/* upper 64 bits of 128-bit GPRs (R5900 only) */
uint64_t rh[35];
/* COP registers */
uint64_t cpr[3][32];
uint64_t ccr[3][32];
uint32_t llbit;
uint64_t cpr[3][32];
uint64_t ccr[3][32];
uint32_t llbit;
uint32_t mode; /* current global mode */
/* VU0 registers (R5900 only) */
float vfr[32][4];
uint32_t vcr[32];
uint32_t mode; /* current global mode */
/* parameters for subroutines */
uint64_t numcycles; /* return value from gettotalcycles */
const char * format; /* format string for print_debug */
uint32_t arg0; /* print_debug argument 1 */
uint32_t arg1; /* print_debug argument 2 */
uint64_t count_zero_time;
uint32_t compare_armed;
uint32_t jmpdest; /* destination jump target */
uint64_t numcycles; /* return value from gettotalcycles */
const char * format; /* format string for print_debug */
uint32_t arg0; /* print_debug argument 1 */
uint32_t arg1; /* print_debug argument 2 */
uint64_t count_zero_time;
uint32_t compare_armed;
uint32_t jmpdest; /* destination jump target */
};
address_space_config m_program_config;
mips3_flavor m_flavor;
mips3_flavor m_flavor;
/* core state */
internal_mips3_state *m_core;
/* internal stuff */
uint32_t m_ppc;
uint32_t m_nextpc;
uint32_t m_pcbase;
uint8_t m_cf[4][8];
bool m_delayslot;
int m_op;
int m_interrupt_cycles;
uint32_t m_ll_value;
uint64_t m_lld_value;
uint32_t m_badcop_value;
uint32_t m_ppc;
uint32_t m_nextpc;
uint32_t m_pcbase;
uint8_t m_cf[4][8];
bool m_delayslot;
int m_op;
int m_interrupt_cycles;
uint32_t m_ll_value;
uint64_t m_lld_value;
uint32_t m_badcop_value;
/* endian-dependent load/store */
typedef void (mips3_device::*loadstore_func)(uint32_t op);
loadstore_func m_lwl;
loadstore_func m_lwr;
loadstore_func m_swl;
loadstore_func m_swr;
loadstore_func m_ldl;
loadstore_func m_ldr;
loadstore_func m_sdl;
loadstore_func m_sdr;
loadstore_func m_lwl;
loadstore_func m_lwr;
loadstore_func m_swl;
loadstore_func m_swr;
loadstore_func m_ldl;
loadstore_func m_ldr;
loadstore_func m_sdl;
loadstore_func m_sdr;
address_space *m_program;
address_space * m_program;
std::function<u32 (offs_t)> m_pr32;
std::function<const void * (offs_t)> m_prptr;
uint32_t c_system_clock;
uint32_t m_cpu_clock;
uint32_t c_system_clock;
uint32_t m_cpu_clock;
emu_timer * m_compare_int_timer;
/* derived info based on flavor */
uint32_t m_pfnmask;
uint8_t m_tlbentries;
uint32_t m_pfnmask;
uint8_t m_tlbentries;
/* memory accesses */
bool m_bigendian;
uint32_t m_byte_xor;
uint32_t m_word_xor;
bool m_bigendian;
uint32_t m_byte_xor;
uint32_t m_word_xor;
data_accessors m_memory;
/* cache memory */
@ -386,35 +394,35 @@ private:
mips3_tlb_entry m_tlb[MIPS3_MAX_TLB_ENTRIES];
/* fast RAM */
uint32_t m_fastram_select;
uint32_t m_fastram_select;
struct
{
offs_t start; /* start of the RAM block */
offs_t end; /* end of the RAM block */
bool readonly; /* true if read-only */
void * base; /* base in memory where the RAM lives */
uint8_t * offset_base8; /* base in memory where the RAM lives, 8-bit pointer, with the start offset pre-applied */
uint16_t * offset_base16; /* base in memory where the RAM lives, 16-bit pointer, with the start offset pre-applied */
uint32_t * offset_base32; /* base in memory where the RAM lives, 32-bit pointer, with the start offset pre-applied */
} m_fastram[MIPS3_MAX_FASTRAM];
offs_t start; /* start of the RAM block */
offs_t end; /* end of the RAM block */
bool readonly; /* true if read-only */
void * base; /* base in memory where the RAM lives */
uint8_t * offset_base8; /* base in memory where the RAM lives, 8-bit pointer, with the start offset pre-applied */
uint16_t * offset_base16; /* base in memory where the RAM lives, 16-bit pointer, with the start offset pre-applied */
uint32_t * offset_base32; /* base in memory where the RAM lives, 32-bit pointer, with the start offset pre-applied */
} m_fastram[MIPS3_MAX_FASTRAM];
uint32_t m_debugger_temp;
uint32_t m_debugger_temp;
/* core state */
drc_cache m_cache; /* pointer to the DRC code cache */
std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */
std::unique_ptr<mips3_frontend> m_drcfe; /* pointer to the DRC front-end state */
uint32_t m_drcoptions; /* configurable DRC options */
drc_cache m_cache; /* pointer to the DRC code cache */
std::unique_ptr<drcuml_state> m_drcuml;/* DRC UML generator state */
std::unique_ptr<mips3_frontend> m_drcfe; /* pointer to the DRC front-end state */
uint32_t m_drcoptions; /* configurable DRC options */
/* internal stuff */
uint8_t m_cache_dirty; /* true if we need to flush the cache */
uint8_t m_cache_dirty; /* true if we need to flush the cache */
/* tables */
uint8_t m_fpmode[4]; /* FPU mode table */
uint8_t m_fpmode[4]; /* FPU mode table */
/* register mappings */
uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
uml::parameter m_regmaplo[34]; /* parameter to register mappings for all 32 integer registers */
uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
uml::parameter m_regmaplo[34]; /* parameter to register mappings for all 32 integer registers */
/* subroutines */
uml::code_handle * m_entry; /* entry point */
@ -437,14 +445,14 @@ private:
uml::code_handle * m_exception_norecover[18/*EXCEPTION_COUNT*/]; /* array of no-recover exception handlers */
/* hotspots */
uint32_t m_hotspot_select;
uint32_t m_hotspot_select;
struct
{
offs_t pc; /* PC to consider */
uint32_t opcode; /* required opcode at that PC */
uint32_t cycles; /* number of cycles to eat when hit */
} m_hotspot[MIPS3_MAX_HOTSPOTS];
bool m_isdrc;
offs_t pc; /* PC to consider */
uint32_t opcode; /* required opcode at that PC */
uint32_t cycles; /* number of cycles to eat when hit */
} m_hotspot[MIPS3_MAX_HOTSPOTS];
bool m_isdrc;
void generate_exception(int exception, int backup);
@ -503,6 +511,9 @@ private:
void handle_special(uint32_t op);
void handle_regimm(uint32_t op);
virtual void handle_extra_special(uint32_t op);
virtual void handle_extra_regimm(uint32_t op);
virtual void handle_idt(uint32_t op);
void lwl_be(uint32_t op);
void lwr_be(uint32_t op);
@ -722,6 +733,23 @@ public:
{ }
};
class r5900le_device : public mips3_device
{
public:
// construction/destruction
r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE)
{ }
protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
void handle_extra_special(uint32_t op) override;
void handle_extra_regimm(uint32_t op) override;
void handle_idt(uint32_t op) override;
};
class qed5271be_device : public mips3_device
{
public:

View File

@ -325,6 +325,9 @@ uint32_t mips3_device::compute_prid_register()
case MIPS3_TYPE_RM7000:
return 0x2700;
case MIPS3_TYPE_R5900:
return 0x2e59;
default:
fatalerror("Unknown MIPS flavor specified\n");
}

View File

@ -31,6 +31,14 @@ const char *const mips3_disassembler::reg[32] =
};
#endif
const char *const ee_disassembler::vreg[32] =
{
"$vf0", "$vf1", "$vf2", "$vf3", "$vf4", "$vf5", "$vf6", "$vf7",
"$vf8", "$vf9", "$vf10", "$vf11", "$vf12", "$vf13", "$vf14", "$vf15",
"$vf16", "$vf17", "$vf18", "$vf19", "$vf20", "$vf21", "$vf22", "$vf23",
"$vf24", "$vf25", "$vf26", "$vf27", "$vf28", "$vf29", "$vf30", "$vf31"
};
const char *const mips3_disassembler::cacheop[32] =
{
"I_Invd", "D_WBInvd", "Unknown 2", "Unknown 3", "I_IndexLoadTag", "D_IndexLoadTag", "Unknown 6", "Unknown 7",
@ -118,20 +126,20 @@ uint32_t mips3_disassembler::dasm_cop0(uint32_t pc, uint32_t op, std::ostream &s
switch ((op >> 21) & 31)
{
case 0x00: util::stream_format(stream, "mfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x01: util::stream_format(stream, "dmfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x02: util::stream_format(stream, "cfc0 %s,%s", reg[rt], ccreg[0][rd]); break;
case 0x04: util::stream_format(stream, "mtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x05: util::stream_format(stream, "dmtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x06: util::stream_format(stream, "ctc0 %s,%s", reg[rt], ccreg[0][rd]); break;
case 0x00: util::stream_format(stream, "mfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x01: util::stream_format(stream, "dmfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x02: util::stream_format(stream, "cfc0 %s,%s", reg[rt], ccreg[0][rd]); break;
case 0x04: util::stream_format(stream, "mtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x05: util::stream_format(stream, "dmtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
case 0x06: util::stream_format(stream, "ctc0 %s,%s", reg[rt], ccreg[0][rd]); break;
case 0x08: /* BC */
switch (rt)
{
case 0x00: util::stream_format(stream, "bc0f $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bc0t $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bc0fl [invalid]"); break;
case 0x03: util::stream_format(stream, "bc0tl [invalid]"); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
case 0x00: util::stream_format(stream, "bc0f $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bc0t $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bc0fl [invalid]"); break;
case 0x03: util::stream_format(stream, "bc0tl [invalid]"); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
break;
case 0x10:
@ -157,11 +165,11 @@ uint32_t mips3_disassembler::dasm_cop0(uint32_t pc, uint32_t op, std::ostream &s
case 0x06: util::stream_format(stream, "tlbwr"); break;
case 0x08: util::stream_format(stream, "tlbp"); break;
case 0x10: util::stream_format(stream, "rfe"); flags = STEP_OUT; break;
case 0x18: util::stream_format(stream, "eret [invalid]"); break;
default: util::stream_format(stream, "cop0 $%07x", op & 0x01ffffff); break;
case 0x18: util::stream_format(stream, "eret [invalid]"); break;
default: util::stream_format(stream, "cop0 $%07x", op & 0x01ffffff); break;
}
break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return flags;
}
@ -183,66 +191,66 @@ uint32_t mips3_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &s
switch ((op >> 21) & 31)
{
case 0x00: util::stream_format(stream, "mfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x01: util::stream_format(stream, "dmfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x02: util::stream_format(stream, "cfc1 %s,%s", reg[rt], ccreg[1][rd]); break;
case 0x04: util::stream_format(stream, "mtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x05: util::stream_format(stream, "dmtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x06: util::stream_format(stream, "ctc1 %s,%s", reg[rt], ccreg[1][rd]); break;
case 0x00: util::stream_format(stream, "mfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x01: util::stream_format(stream, "dmfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x02: util::stream_format(stream, "cfc1 %s,%s", reg[rt], ccreg[1][rd]); break;
case 0x04: util::stream_format(stream, "mtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x05: util::stream_format(stream, "dmtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
case 0x06: util::stream_format(stream, "ctc1 %s,%s", reg[rt], ccreg[1][rd]); break;
case 0x08: /* BC */
switch (rt & 3)
{
case 0x00: util::stream_format(stream, "bc1f $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); break;
case 0x01: util::stream_format(stream, "bc1t $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); break;
case 0x02: util::stream_format(stream, "bc1fl $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
case 0x03: util::stream_format(stream, "bc1tl $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
case 0x00: util::stream_format(stream, "bc1f $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); break;
case 0x01: util::stream_format(stream, "bc1t $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); break;
case 0x02: util::stream_format(stream, "bc1fl $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
case 0x03: util::stream_format(stream, "bc1tl $%08x,%d", pc + 4 + ((int16_t)op << 2), (op >> 18) & 7); flags = STEP_OVER | step_over_extra(1); break;
}
break;
default: /* COP */
switch (op & 0x3f)
{
case 0x00: util::stream_format(stream, "add.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x01: util::stream_format(stream, "sub.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x02: util::stream_format(stream, "mul.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x03: util::stream_format(stream, "div.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x04: util::stream_format(stream, "sqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x05: util::stream_format(stream, "abs.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x06: util::stream_format(stream, "mov.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x07: util::stream_format(stream, "neg.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x00: util::stream_format(stream, "add.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x01: util::stream_format(stream, "sub.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x02: util::stream_format(stream, "mul.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x03: util::stream_format(stream, "div.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
case 0x04: util::stream_format(stream, "sqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x05: util::stream_format(stream, "abs.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x06: util::stream_format(stream, "mov.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x07: util::stream_format(stream, "neg.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x08: util::stream_format(stream, "round.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x09: util::stream_format(stream, "trunc.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0a: util::stream_format(stream, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0a: util::stream_format(stream, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0b: util::stream_format(stream, "floor.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0c: util::stream_format(stream, "round.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0d: util::stream_format(stream, "trunc.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0e: util::stream_format(stream, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0e: util::stream_format(stream, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x0f: util::stream_format(stream, "floor.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x11: util::stream_format(stream, "mov%c.%s %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7); break;
case 0x12: util::stream_format(stream, "movz.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
case 0x13: util::stream_format(stream, "movn.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
case 0x15: util::stream_format(stream, "recip.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x16: util::stream_format(stream, "rsqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x20: util::stream_format(stream, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x21: util::stream_format(stream, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x24: util::stream_format(stream, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x25: util::stream_format(stream, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x30: util::stream_format(stream, "c.f.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x31: util::stream_format(stream, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x32: util::stream_format(stream, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x33: util::stream_format(stream, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x34: util::stream_format(stream, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x35: util::stream_format(stream, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x36: util::stream_format(stream, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x37: util::stream_format(stream, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x38: util::stream_format(stream, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x39: util::stream_format(stream, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
case 0x3a: util::stream_format(stream, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3b: util::stream_format(stream, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3c: util::stream_format(stream, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3d: util::stream_format(stream, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3e: util::stream_format(stream, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3f: util::stream_format(stream, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break;
case 0x11: util::stream_format(stream, "mov%c.%s %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7); break;
case 0x12: util::stream_format(stream, "movz.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
case 0x13: util::stream_format(stream, "movn.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
case 0x15: util::stream_format(stream, "recip.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x16: util::stream_format(stream, "rsqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x20: util::stream_format(stream, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x21: util::stream_format(stream, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x24: util::stream_format(stream, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x25: util::stream_format(stream, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
case 0x30: util::stream_format(stream, "c.f.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x31: util::stream_format(stream, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x32: util::stream_format(stream, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x33: util::stream_format(stream, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x34: util::stream_format(stream, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x35: util::stream_format(stream, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x36: util::stream_format(stream, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x37: util::stream_format(stream, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x38: util::stream_format(stream, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x39: util::stream_format(stream, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
case 0x3a: util::stream_format(stream, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3b: util::stream_format(stream, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3c: util::stream_format(stream, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3d: util::stream_format(stream, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3e: util::stream_format(stream, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
case 0x3f: util::stream_format(stream, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break;
}
break;
}
@ -267,11 +275,11 @@ uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &
switch (op & 0x3f)
{
case 0x00: util::stream_format(stream, "lwxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x01: util::stream_format(stream, "ldxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x08: util::stream_format(stream, "swxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x09: util::stream_format(stream, "sdxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x0f: util::stream_format(stream, "prefx %d,%s(%s)", rd, reg[rt], reg[rs]); break;
case 0x00: util::stream_format(stream, "lwxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x01: util::stream_format(stream, "ldxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x08: util::stream_format(stream, "swxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x09: util::stream_format(stream, "sdxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
case 0x0f: util::stream_format(stream, "prefx %d,%s(%s)", rd, reg[rt], reg[rs]); break;
case 0x20:
case 0x21:
case 0x22:
@ -279,7 +287,7 @@ uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &
case 0x24:
case 0x25:
case 0x26:
case 0x27: util::stream_format(stream, "madd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x27: util::stream_format(stream, "madd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x28:
case 0x29:
case 0x2a:
@ -287,7 +295,7 @@ uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &
case 0x2c:
case 0x2d:
case 0x2e:
case 0x2f: util::stream_format(stream, "msub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x2f: util::stream_format(stream, "msub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x30:
case 0x31:
case 0x32:
@ -295,7 +303,7 @@ uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &
case 0x34:
case 0x35:
case 0x36:
case 0x37: util::stream_format(stream, "nmadd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x37: util::stream_format(stream, "nmadd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
case 0x38:
case 0x39:
case 0x3a:
@ -303,8 +311,8 @@ uint32_t mips3_disassembler::dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f: util::stream_format(stream, "nmsub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break;
case 0x3f: util::stream_format(stream, "nmsub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
default: util::stream_format(stream, "cop1 $%07x", op & 0x01ffffff); break;
}
return flags;
}
@ -317,20 +325,20 @@ uint32_t mips3_disassembler::dasm_cop2(uint32_t pc, uint32_t op, std::ostream &s
switch ((op >> 21) & 31)
{
case 0x00: util::stream_format(stream, "mfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x01: util::stream_format(stream, "dmfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x02: util::stream_format(stream, "cfc2 %s,%s", reg[rt], ccreg[2][rd]); break;
case 0x04: util::stream_format(stream, "mtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x05: util::stream_format(stream, "dmtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x06: util::stream_format(stream, "ctc2 %s,%s", reg[rt], ccreg[2][rd]); break;
case 0x00: util::stream_format(stream, "mfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x01: util::stream_format(stream, "dmfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x02: util::stream_format(stream, "cfc2 %s,%s", reg[rt], ccreg[2][rd]); break;
case 0x04: util::stream_format(stream, "mtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x05: util::stream_format(stream, "dmtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
case 0x06: util::stream_format(stream, "ctc2 %s,%s", reg[rt], ccreg[2][rd]); break;
case 0x08: /* BC */
switch (rt)
{
case 0x00: util::stream_format(stream, "bc2f $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bc2t $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bc2fl [invalid]"); break;
case 0x03: util::stream_format(stream, "bc2tl [invalid]"); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
case 0x00: util::stream_format(stream, "bc2f $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bc2t $%08x", pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bc2fl [invalid]"); break;
case 0x03: util::stream_format(stream, "bc2tl [invalid]"); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
break;
case 0x10:
@ -349,13 +357,317 @@ uint32_t mips3_disassembler::dasm_cop2(uint32_t pc, uint32_t op, std::ostream &s
case 0x1d:
case 0x1e:
case 0x1f: /* COP */
util::stream_format(stream, "cop2 $%07x", op & 0x01ffffff);
util::stream_format(stream, "cop2 $%07x", op & 0x01ffffff);
break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return flags;
}
uint32_t mips3_disassembler::dasm_idt(uint32_t pc, uint32_t op, std::ostream &stream)
{
int rs = (op >> 21) & 31;
int rt = (op >> 16) & 31;
int rd = (op >> 11) & 31;
uint32_t flags = 0;
/* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
switch (op & 0x1f)
{
case 0: util::stream_format(stream, "mad %s,%s", reg[rs], reg[rt]); break;
case 1: util::stream_format(stream, "madu %s,%s", reg[rs], reg[rt]); break;
case 2: util::stream_format(stream, "mul %s,%s,%s", reg[rs], reg[rt], reg[rd]); break;
case 4: util::stream_format(stream, "msub %s,%s", reg[rs], reg[rt]); break;
default:util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return flags;
}
uint32_t mips3_disassembler::dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream)
{
util::stream_format(stream, "dc.l $%08x [invalid]", op);
return 0;
}
uint32_t mips3_disassembler::dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream)
{
util::stream_format(stream, "dc.l $%08x [invalid]", op);
return 0;
}
uint32_t mips3_disassembler::dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream)
{
util::stream_format(stream, "dc.l $%08x [invalid]", op);
return 0;
}
uint32_t ee_disassembler::dasm_idt(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
const int rd = (op >> 11) & 31;
const int fmt = (op >> 6) & 31;
const int shift = fmt; // convenience
uint32_t flags = 0;
switch (op & 0x3f)
{
case 0x00:
if (rd)
util::stream_format(stream, "madd %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "madd %s,%s", reg[rs], reg[rt]);
break;
case 0x01:
if (rd)
util::stream_format(stream, "maddu %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "maddu %s,%s", reg[rs], reg[rt]);
break;
case 0x04: util::stream_format(stream, "plzcw ?"); break;
case 0x08: flags = dasm_mmi0(pc, op, stream); break;
case 0x09: flags = dasm_mmi2(pc, op, stream); break;
case 0x10: util::stream_format(stream, "mfhi1 %s", reg[rd]); break;
case 0x11: util::stream_format(stream, "mthi1 %s", reg[rs]); break;
case 0x12: util::stream_format(stream, "mflo1 %s", reg[rd]); break;
case 0x13: util::stream_format(stream, "mtlo1 %s", reg[rs]); break;
case 0x18:
if (rd)
util::stream_format(stream, "mult1 %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "mult1 %s,%s", reg[rs], reg[rt]);
break;
case 0x19:
if (rd)
util::stream_format(stream, "multu1 %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "multu1 %s,%s", reg[rs], reg[rt]);
break;
case 0x1a: util::stream_format(stream, "div1 %s,%s", reg[rs], reg[rt]); break;
case 0x1b: util::stream_format(stream, "divu1 %s,%s", reg[rs], reg[rt]); break;
case 0x20:
if (rd)
util::stream_format(stream, "madd1 %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "madd1 %s,%s", reg[rs], reg[rt]);
break;
case 0x21:
if (rd)
util::stream_format(stream, "maddu1 %s,%s,%s", reg[rd], reg[rs], reg[rt]);
else
util::stream_format(stream, "maddu1 %s,%s", reg[rs], reg[rt]);
break;
case 0x28: flags = dasm_mmi1(pc, op, stream); break;
case 0x29: flags = dasm_mmi3(pc, op, stream); break;
case 0x30:
switch (fmt)
{
case 0: util::stream_format(stream, "pmfhl.lw %s", reg[rd]); break;
case 1: util::stream_format(stream, "pmfhl.uw %s", reg[rd]); break;
case 2: util::stream_format(stream, "pmfhl.slw %s", reg[rd]); break;
case 3: util::stream_format(stream, "pmfhl.lh %s", reg[rd]); break;
case 4: util::stream_format(stream, "pmfhl.sh %s", reg[rd]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
break;
case 0x31:
switch (fmt)
{
case 0: util::stream_format(stream, "pmthl.lw %s", reg[rd]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
break;
case 0x34: util::stream_format(stream, "psllh %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x36: util::stream_format(stream, "psrlh %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x37: util::stream_format(stream, "psrah %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3c: util::stream_format(stream, "psllw %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3e: util::stream_format(stream, "psrlw %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3f: util::stream_format(stream, "psraw %s,%s,%d", reg[rd], reg[rt], shift); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return flags;
}
uint32_t ee_disassembler::dasm_mmi0(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
const int rd = (op >> 11) & 31;
const int code = (op >> 6) & 31;
switch (code)
{
case 0x00: util::stream_format(stream, "paddw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x01: util::stream_format(stream, "psubw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x02: util::stream_format(stream, "pcgtw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x03: util::stream_format(stream, "pmaxw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x04: util::stream_format(stream, "paddh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x05: util::stream_format(stream, "psubh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x06: util::stream_format(stream, "pcgth %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x07: util::stream_format(stream, "pmaxh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x08: util::stream_format(stream, "paddb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x09: util::stream_format(stream, "psubb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0a: util::stream_format(stream, "pcgtb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x10: util::stream_format(stream, "paddsw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x11: util::stream_format(stream, "psubsw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x12: util::stream_format(stream, "pextlw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x13: util::stream_format(stream, "ppacw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x14: util::stream_format(stream, "paddsh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x15: util::stream_format(stream, "psubsh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x16: util::stream_format(stream, "pextlh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x17: util::stream_format(stream, "ppach %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x18: util::stream_format(stream, "paddsb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x19: util::stream_format(stream, "psubsb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "pextlb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1b: util::stream_format(stream, "ppacb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1e: util::stream_format(stream, "pext5 %s,%s", reg[rd], reg[rt]); break;
case 0x1f: util::stream_format(stream, "ppac5 %s,%s", reg[rd], reg[rt]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_mmi1(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
const int rd = (op >> 11) & 31;
const int code = (op >> 6) & 31;
switch (code)
{
case 0x01: util::stream_format(stream, "pabsw %s,%s", reg[rd], reg[rt]); break;
case 0x02: util::stream_format(stream, "pceqw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x03: util::stream_format(stream, "pminw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x04: util::stream_format(stream, "padsbh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x05: util::stream_format(stream, "pabsh %s,%s", reg[rd], reg[rt]); break;
case 0x06: util::stream_format(stream, "pceqh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x07: util::stream_format(stream, "pminh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0a: util::stream_format(stream, "pceqb %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x10: util::stream_format(stream, "padduw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x11: util::stream_format(stream, "psubuw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x12: util::stream_format(stream, "pextuw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x14: util::stream_format(stream, "padduh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x15: util::stream_format(stream, "psubuh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x16: util::stream_format(stream, "pextuh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x18: util::stream_format(stream, "paddub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x19: util::stream_format(stream, "psubub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "pextub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1b: util::stream_format(stream, "qfsrv %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_mmi2(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
const int rd = (op >> 11) & 31;
const int code = (op >> 6) & 31;
switch (code)
{
case 0x00: util::stream_format(stream, "pmaddw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x02: util::stream_format(stream, "psllvw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x03: util::stream_format(stream, "psrlvw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x04: util::stream_format(stream, "pmsubw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x08: util::stream_format(stream, "pmfhi %s", reg[rd]); break;
case 0x09: util::stream_format(stream, "pmflo %s", reg[rd]); break;
case 0x0a: util::stream_format(stream, "pinth %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0c: util::stream_format(stream, "pmultw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0d: util::stream_format(stream, "pdivw %s,%s", reg[rs], reg[rt]); break;
case 0x0e: util::stream_format(stream, "pcpyld %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x10: util::stream_format(stream, "pmaddh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x11: util::stream_format(stream, "phmadh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x12: util::stream_format(stream, "pand %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x13: util::stream_format(stream, "pxor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x14: util::stream_format(stream, "pmsubh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x15: util::stream_format(stream, "phmsbh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "pexeh %s,%s", reg[rd], reg[rt]); break;
case 0x1b: util::stream_format(stream, "prevh %s,%s", reg[rd], reg[rt]); break;
case 0x1c: util::stream_format(stream, "pmulth %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1d: util::stream_format(stream, "pdivbw %s,%s", reg[rs], reg[rt]); break;
case 0x1e: util::stream_format(stream, "pexew %s,%s", reg[rd], reg[rt]); break;
case 0x1f: util::stream_format(stream, "prot3w %s,%s", reg[rd], reg[rt]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_mmi3(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
const int rd = (op >> 11) & 31;
const int code = (op >> 6) & 31;
switch (code)
{
case 0x00: util::stream_format(stream, "pmadduw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x03: util::stream_format(stream, "psravw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x08: util::stream_format(stream, "pmthi %s", reg[rs]); break;
case 0x09: util::stream_format(stream, "pmtlo %s", reg[rs]); break;
case 0x0a: util::stream_format(stream, "pinteh %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0c: util::stream_format(stream, "pmultuw %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0d: util::stream_format(stream, "pdivuw %s,%s", reg[rs], reg[rt]); break;
case 0x0e: util::stream_format(stream, "pcpyud %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x12: util::stream_format(stream, "por %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x13: util::stream_format(stream, "pnor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "pexch %s,%s", reg[rd], reg[rt]); break;
case 0x1b: util::stream_format(stream, "pcpyh %s,%s", reg[rd], reg[rt]); break;
case 0x1e: util::stream_format(stream, "pexcw %s,%s", reg[rd], reg[rt]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
const int rt = (op >> 16) & 31;
switch (op >> 26)
{
case 0x1e: util::stream_format(stream, "lq %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x1f: util::stream_format(stream, "sq %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
switch (op & 63)
{
case 0x29: util::stream_format(stream, "mtsa %s", reg[rs]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
uint32_t ee_disassembler::dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
switch ((op >> 16) & 31)
{
case 0x18: util::stream_format(stream, "mtsab %s,%s", reg[rs], signed_16bit(op)); break;
case 0x19: util::stream_format(stream, "mtsah %s,%s", reg[rs], signed_16bit(op)); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
u32 mips3_disassembler::opcode_alignment() const
{
return 4;
@ -377,164 +689,155 @@ offs_t mips3_disassembler::dasm_one(std::ostream &stream, offs_t pc, u32 op)
case 0x00: if (op == 0)
util::stream_format(stream, "nop");
else
util::stream_format(stream, "sll %s,%s,%d", reg[rd], reg[rt], shift);
util::stream_format(stream, "sll %s,%s,%d", reg[rd], reg[rt], shift);
break;
case 0x01: util::stream_format(stream, "mov%c %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', reg[rd], reg[rs], (op >> 18) & 7); break;
case 0x02: util::stream_format(stream, "srl %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x03: util::stream_format(stream, "sra %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x04: util::stream_format(stream, "sllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x06: util::stream_format(stream, "srlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x07: util::stream_format(stream, "srav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x08: util::stream_format(stream, "jr %s", reg[rs]); if (rs == 31) flags = STEP_OUT; break;
case 0x01: util::stream_format(stream, "mov%c %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', reg[rd], reg[rs], (op >> 18) & 7); break;
case 0x02: util::stream_format(stream, "srl %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x03: util::stream_format(stream, "sra %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x04: util::stream_format(stream, "sllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x06: util::stream_format(stream, "srlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x07: util::stream_format(stream, "srav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x08: util::stream_format(stream, "jr %s", reg[rs]); if (rs == 31) flags = STEP_OUT; break;
case 0x09: if (rd == 31)
util::stream_format(stream, "jalr %s", reg[rs]);
util::stream_format(stream, "jalr %s", reg[rs]);
else
util::stream_format(stream, "jalr %s,%s", reg[rs], reg[rd]);
util::stream_format(stream, "jalr %s,%s", reg[rs], reg[rd]);
flags = STEP_OVER | step_over_extra(1);
break;
case 0x0a: util::stream_format(stream, "movz %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0b: util::stream_format(stream, "movn %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0a: util::stream_format(stream, "movz %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0b: util::stream_format(stream, "movn %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x0c: util::stream_format(stream, "syscall"); flags = STEP_OVER; break;
case 0x0d: util::stream_format(stream, "break"); flags = STEP_OVER; break;
case 0x0f: util::stream_format(stream, "sync"); break;
case 0x10: util::stream_format(stream, "mfhi %s", reg[rd]); break;
case 0x11: util::stream_format(stream, "mthi %s", reg[rs]); break;
case 0x12: util::stream_format(stream, "mflo %s", reg[rd]); break;
case 0x13: util::stream_format(stream, "mtlo %s", reg[rs]); break;
case 0x14: util::stream_format(stream, "dsllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x16: util::stream_format(stream, "dsrlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x17: util::stream_format(stream, "dsrav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x18: util::stream_format(stream, "mult %s,%s", reg[rs], reg[rt]); break;
case 0x19: util::stream_format(stream, "multu %s,%s", reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "div %s,%s", reg[rs], reg[rt]); break;
case 0x1b: util::stream_format(stream, "divu %s,%s", reg[rs], reg[rt]); break;
case 0x1c: util::stream_format(stream, "dmult %s,%s", reg[rs], reg[rt]); break;
case 0x1d: util::stream_format(stream, "dmultu %s,%s", reg[rs], reg[rt]); break;
case 0x1e: util::stream_format(stream, "ddiv %s,%s", reg[rs], reg[rt]); break;
case 0x1f: util::stream_format(stream, "ddivu %s,%s", reg[rs], reg[rt]); break;
case 0x20: util::stream_format(stream, "add %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x21: util::stream_format(stream, "addu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x22: util::stream_format(stream, "sub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x23: util::stream_format(stream, "subu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x24: util::stream_format(stream, "and %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x25: util::stream_format(stream, "or %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x26: util::stream_format(stream, "xor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x27: util::stream_format(stream, "nor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2a: util::stream_format(stream, "slt %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2b: util::stream_format(stream, "sltu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2c: util::stream_format(stream, "dadd %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2d: util::stream_format(stream, "daddu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2e: util::stream_format(stream, "dsub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2f: util::stream_format(stream, "dsubu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x30: util::stream_format(stream, "tge %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x31: util::stream_format(stream, "tgeu %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x32: util::stream_format(stream, "tlt %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x33: util::stream_format(stream, "tltu %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x34: util::stream_format(stream, "teq %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x36: util::stream_format(stream, "tne %s,%s", reg[rs], reg[rt]) ;flags = STEP_OVER; break;
case 0x38: util::stream_format(stream, "dsll %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3a: util::stream_format(stream, "dsrl %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3b: util::stream_format(stream, "dsra %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3c: util::stream_format(stream, "dsll %s,%s,%d", reg[rd], reg[rt], shift+32); break;
case 0x3e: util::stream_format(stream, "dsrl %s,%s,%d", reg[rd], reg[rt], shift+32); break;
case 0x3f: util::stream_format(stream, "dsra %s,%s,%d", reg[rd], reg[rt], shift+32); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
case 0x10: util::stream_format(stream, "mfhi %s", reg[rd]); break;
case 0x11: util::stream_format(stream, "mthi %s", reg[rs]); break;
case 0x12: util::stream_format(stream, "mflo %s", reg[rd]); break;
case 0x13: util::stream_format(stream, "mtlo %s", reg[rs]); break;
case 0x14: util::stream_format(stream, "dsllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x16: util::stream_format(stream, "dsrlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x17: util::stream_format(stream, "dsrav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
case 0x18: util::stream_format(stream, "mult %s,%s", reg[rs], reg[rt]); break;
case 0x19: util::stream_format(stream, "multu %s,%s", reg[rs], reg[rt]); break;
case 0x1a: util::stream_format(stream, "div %s,%s", reg[rs], reg[rt]); break;
case 0x1b: util::stream_format(stream, "divu %s,%s", reg[rs], reg[rt]); break;
case 0x1c: util::stream_format(stream, "dmult %s,%s", reg[rs], reg[rt]); break;
case 0x1d: util::stream_format(stream, "dmultu %s,%s", reg[rs], reg[rt]); break;
case 0x1e: util::stream_format(stream, "ddiv %s,%s", reg[rs], reg[rt]); break;
case 0x1f: util::stream_format(stream, "ddivu %s,%s", reg[rs], reg[rt]); break;
case 0x20: util::stream_format(stream, "add %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x21: util::stream_format(stream, "addu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x22: util::stream_format(stream, "sub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x23: util::stream_format(stream, "subu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x24: util::stream_format(stream, "and %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x25: util::stream_format(stream, "or %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x26: util::stream_format(stream, "xor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x27: util::stream_format(stream, "nor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2a: util::stream_format(stream, "slt %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2b: util::stream_format(stream, "sltu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2c: util::stream_format(stream, "dadd %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2d: util::stream_format(stream, "daddu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2e: util::stream_format(stream, "dsub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x2f: util::stream_format(stream, "dsubu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
case 0x30: util::stream_format(stream, "tge %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x31: util::stream_format(stream, "tgeu %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x32: util::stream_format(stream, "tlt %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x33: util::stream_format(stream, "tltu %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x34: util::stream_format(stream, "teq %s,%s", reg[rs], reg[rt]); flags = STEP_OVER; break;
case 0x36: util::stream_format(stream, "tne %s,%s", reg[rs], reg[rt]) ;flags = STEP_OVER; break;
case 0x38: util::stream_format(stream, "dsll %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3a: util::stream_format(stream, "dsrl %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3b: util::stream_format(stream, "dsra %s,%s,%d", reg[rd], reg[rt], shift); break;
case 0x3c: util::stream_format(stream, "dsll %s,%s,%d", reg[rd], reg[rt], shift+32); break;
case 0x3e: util::stream_format(stream, "dsrl %s,%s,%d", reg[rd], reg[rt], shift+32); break;
case 0x3f: util::stream_format(stream, "dsra %s,%s,%d", reg[rd], reg[rt], shift+32); break;
default: flags = dasm_extra_special(pc, op, stream); break;
}
break;
case 0x01: /* REGIMM */
switch ((op >> 16) & 31)
{
case 0x00: util::stream_format(stream, "bltz %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bgez %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bltzl %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x03: util::stream_format(stream, "bgezl %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x08: util::stream_format(stream, "tgei %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x09: util::stream_format(stream, "tgeiu %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0a: util::stream_format(stream, "tlti %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0b: util::stream_format(stream, "tltiu %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0c: util::stream_format(stream, "teqi %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0e: util::stream_format(stream, "tnei %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x10: util::stream_format(stream, "bltzal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x11: util::stream_format(stream, "bgezal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x12: util::stream_format(stream, "bltzall %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x13: util::stream_format(stream, "bgezall %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
case 0x00: util::stream_format(stream, "bltz %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x01: util::stream_format(stream, "bgez %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x02: util::stream_format(stream, "bltzl %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x03: util::stream_format(stream, "bgezl %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x08: util::stream_format(stream, "tgei %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x09: util::stream_format(stream, "tgeiu %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0a: util::stream_format(stream, "tlti %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0b: util::stream_format(stream, "tltiu %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0c: util::stream_format(stream, "teqi %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x0e: util::stream_format(stream, "tnei %s,%s", reg[rs], signed_16bit(op)); flags = STEP_OVER; break;
case 0x10: util::stream_format(stream, "bltzal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x11: util::stream_format(stream, "bgezal %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x12: util::stream_format(stream, "bltzall %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x13: util::stream_format(stream, "bgezall %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); flags = STEP_OVER | step_over_extra(1); break;
default: flags = dasm_extra_regimm(pc, op, stream); break;
}
break;
case 0x02: util::stream_format(stream, "j $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); break;
case 0x03: util::stream_format(stream, "jal $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x02: util::stream_format(stream, "j $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); break;
case 0x03: util::stream_format(stream, "jal $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); flags = STEP_OVER | step_over_extra(1); break;
case 0x04: if (rs == 0 && rt == 0)
util::stream_format(stream, "b $%08x", pc + 4 + ((int16_t)op << 2));
util::stream_format(stream, "b $%08x", pc + 4 + ((int16_t)op << 2));
else
util::stream_format(stream, "beq %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));
util::stream_format(stream, "beq %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));
break;
case 0x05: util::stream_format(stream, "bne %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x06: util::stream_format(stream, "blez %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x07: util::stream_format(stream, "bgtz %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x08: util::stream_format(stream, "addi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x09: util::stream_format(stream, "addiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0a: util::stream_format(stream, "slti %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0b: util::stream_format(stream, "sltiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0c: util::stream_format(stream, "andi %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0d: util::stream_format(stream, "ori %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0e: util::stream_format(stream, "xori %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0f: util::stream_format(stream, "lui %s,$%04x", reg[rt], (uint16_t)op); break;
case 0x05: util::stream_format(stream, "bne %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x06: util::stream_format(stream, "blez %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x07: util::stream_format(stream, "bgtz %s,$%08x", reg[rs], pc + 4 + ((int16_t)op << 2)); break;
case 0x08: util::stream_format(stream, "addi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x09: util::stream_format(stream, "addiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0a: util::stream_format(stream, "slti %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0b: util::stream_format(stream, "sltiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x0c: util::stream_format(stream, "andi %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0d: util::stream_format(stream, "ori %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0e: util::stream_format(stream, "xori %s,%s,$%04x", reg[rt], reg[rs], (uint16_t)op); break;
case 0x0f: util::stream_format(stream, "lui %s,$%04x", reg[rt], (uint16_t)op); break;
case 0x10: flags = dasm_cop0(pc, op, stream); break;
case 0x11: flags = dasm_cop1(pc, op, stream); break;
case 0x12: flags = dasm_cop2(pc, op, stream); break;
case 0x13: flags = dasm_cop1x(pc, op, stream); break;
case 0x14: util::stream_format(stream, "beql %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x15: util::stream_format(stream, "bnel %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x16: util::stream_format(stream, "blezl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x17: util::stream_format(stream, "bgtzl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x18: util::stream_format(stream, "daddi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x19: util::stream_format(stream, "daddiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x1a: util::stream_format(stream, "ldl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x1b: util::stream_format(stream, "ldr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x1c: /* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
switch (op & 0x1f)
{
case 0: util::stream_format(stream, "mad %s,%s", reg[rs], reg[rt]); break;
case 1: util::stream_format(stream, "madu %s,%s", reg[rs], reg[rt]); break;
case 2: util::stream_format(stream, "mul %s,%s,%s", reg[rs], reg[rt], reg[rd]); break;
case 4: util::stream_format(stream, "msub %s,%s", reg[rs], reg[rt]); break;
default:util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
break;
case 0x20: util::stream_format(stream, "lb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x21: util::stream_format(stream, "lh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x22: util::stream_format(stream, "lwl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x23: util::stream_format(stream, "lw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x24: util::stream_format(stream, "lbu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x25: util::stream_format(stream, "lhu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x26: util::stream_format(stream, "lwr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x27: util::stream_format(stream, "lwu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x28: util::stream_format(stream, "sb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x29: util::stream_format(stream, "sh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2a: util::stream_format(stream, "swl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2b: util::stream_format(stream, "sw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2c: util::stream_format(stream, "sdl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2d: util::stream_format(stream, "sdr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2e: util::stream_format(stream, "swr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2f: util::stream_format(stream, "cache %s,%s(%s)", cacheop[rt], reg[rs], signed_16bit(op)); break;
case 0x30: util::stream_format(stream, "ll %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x31: util::stream_format(stream, "lwc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x32: util::stream_format(stream, "lwc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x33: util::stream_format(stream, "pref $%x,%s(%s)", rt, signed_16bit(op), reg[rs]); break;
case 0x34: util::stream_format(stream, "lld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x35: util::stream_format(stream, "ldc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x36: util::stream_format(stream, "ldc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x37: util::stream_format(stream, "ld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x38: util::stream_format(stream, "sc %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x39: util::stream_format(stream, "swc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x3a: util::stream_format(stream, "swc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x3c: util::stream_format(stream, "scd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x3d: util::stream_format(stream, "sdc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x3e: util::stream_format(stream, "sdc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x3f: util::stream_format(stream, "sd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
case 0x14: util::stream_format(stream, "beql %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x15: util::stream_format(stream, "bnel %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x16: util::stream_format(stream, "blezl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x17: util::stream_format(stream, "bgtzl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((int16_t)op << 2));break;
case 0x18: util::stream_format(stream, "daddi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x19: util::stream_format(stream, "daddiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
case 0x1a: util::stream_format(stream, "ldl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x1b: util::stream_format(stream, "ldr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x1c: flags = dasm_idt(pc, op, stream); break;
case 0x20: util::stream_format(stream, "lb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x21: util::stream_format(stream, "lh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x22: util::stream_format(stream, "lwl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x23: util::stream_format(stream, "lw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x24: util::stream_format(stream, "lbu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x25: util::stream_format(stream, "lhu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x26: util::stream_format(stream, "lwr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x27: util::stream_format(stream, "lwu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x28: util::stream_format(stream, "sb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x29: util::stream_format(stream, "sh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2a: util::stream_format(stream, "swl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2b: util::stream_format(stream, "sw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2c: util::stream_format(stream, "sdl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2d: util::stream_format(stream, "sdr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2e: util::stream_format(stream, "swr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x2f: util::stream_format(stream, "cache %s,%s(%s)", cacheop[rt], reg[rs], signed_16bit(op)); break;
case 0x30: util::stream_format(stream, "ll %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x31: util::stream_format(stream, "lwc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x32: util::stream_format(stream, "lwc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x33: util::stream_format(stream, "pref $%x,%s(%s)", rt, signed_16bit(op), reg[rs]); break;
case 0x34: util::stream_format(stream, "lld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x35: util::stream_format(stream, "ldc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x36: util::stream_format(stream, "ldc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x37: util::stream_format(stream, "ld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x38: util::stream_format(stream, "sc %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x39: util::stream_format(stream, "swc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x3a: util::stream_format(stream, "swc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x3c: util::stream_format(stream, "scd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
case 0x3d: util::stream_format(stream, "sdc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
case 0x3e: util::stream_format(stream, "sdc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
case 0x3f: util::stream_format(stream, "sd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
default: flags = dasm_extra_base(pc, op, stream); break;
}
return 4 | flags | SUPPORTED;
}

View File

@ -24,17 +24,40 @@ public:
offs_t dasm_one(std::ostream &stream, offs_t pc, u32 op);
private:
protected:
static const char *const reg[32];
static const char *const cacheop[32];
static const char *const cpreg[4][32];
static const char *const ccreg[4][32];
inline std::string signed_16bit(int16_t val);
virtual uint32_t dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream);
virtual uint32_t dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream);
virtual uint32_t dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_cop0(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_cop1x(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_cop2(uint32_t pc, uint32_t op, std::ostream &stream);
virtual uint32_t dasm_cop2(uint32_t pc, uint32_t op, std::ostream &stream);
virtual uint32_t dasm_idt(uint32_t pc, uint32_t op, std::ostream &stream);
};
class ee_disassembler : public mips3_disassembler
{
public:
ee_disassembler() = default;
virtual ~ee_disassembler() = default;
protected:
static const char *const vreg[32];
uint32_t dasm_extra_base(uint32_t pc, uint32_t op, std::ostream &stream) override;
uint32_t dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream) override;
uint32_t dasm_extra_regimm(uint32_t pc, uint32_t op, std::ostream &stream) override;
uint32_t dasm_idt(uint32_t pc, uint32_t op, std::ostream &stream) override;
uint32_t dasm_mmi(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_mmi0(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_mmi1(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_mmi2(uint32_t pc, uint32_t op, std::ostream &stream);
uint32_t dasm_mmi3(uint32_t pc, uint32_t op, std::ostream &stream);
};
#endif

View File

@ -199,7 +199,7 @@ static INPUT_PORTS_START( ps2sony )
INPUT_PORTS_END
MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_DEVICE_ADD("maincpu", R5000LE, 294'912'000) // actually R5900
MCFG_DEVICE_ADD("maincpu", R5900LE, 294'912'000)
MCFG_MIPS3_ICACHE_SIZE(16384)
MCFG_MIPS3_DCACHE_SIZE(16384)
MCFG_DEVICE_PROGRAM_MAP(mem_map)