mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
mips3: Added disassembler for Emotion Engine core opcodes. VU macro ops are still to-do. [Ryan Holtz]
This commit is contained in:
parent
b307f27d54
commit
dd30364632
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user