From dd30364632520a2137858d43760d5a6f8a6077fc Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sat, 23 Jun 2018 12:59:15 +0200 Subject: [PATCH] mips3: Added disassembler for Emotion Engine core opcodes. VU macro ops are still to-do. [Ryan Holtz] --- src/devices/cpu/mips/mips3.cpp | 89 ++-- src/devices/cpu/mips/mips3.h | 160 ++++--- src/devices/cpu/mips/mips3com.cpp | 3 + src/devices/cpu/mips/mips3dsm.cpp | 737 +++++++++++++++++++++--------- src/devices/cpu/mips/mips3dsm.h | 27 +- src/mame/drivers/ps2sony.cpp | 2 +- 6 files changed, 705 insertions(+), 313 deletions(-) diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 411c6ca5d6f..08841b0f5a6 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -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 mips3_device::create_disassembler() { return std::make_unique(); } +std::unique_ptr r5900le_device::create_disassembler() +{ + return std::make_unique(); +} + /*************************************************************************** @@ -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; diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index 6c192b5436c..1b4c5a77f7e 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -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 m_pr32; std::function 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 m_drcuml; /* DRC UML generator state */ - std::unique_ptr 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 m_drcuml;/* DRC UML generator state */ + std::unique_ptr 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 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: diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp index d5260a8b05e..9edd05f8b67 100644 --- a/src/devices/cpu/mips/mips3com.cpp +++ b/src/devices/cpu/mips/mips3com.cpp @@ -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"); } diff --git a/src/devices/cpu/mips/mips3dsm.cpp b/src/devices/cpu/mips/mips3dsm.cpp index 5252a552b8c..42ebae6fe81 100644 --- a/src/devices/cpu/mips/mips3dsm.cpp +++ b/src/devices/cpu/mips/mips3dsm.cpp @@ -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; } diff --git a/src/devices/cpu/mips/mips3dsm.h b/src/devices/cpu/mips/mips3dsm.h index a38771bbba0..50bb28875ea 100644 --- a/src/devices/cpu/mips/mips3dsm.h +++ b/src/devices/cpu/mips/mips3dsm.h @@ -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 diff --git a/src/mame/drivers/ps2sony.cpp b/src/mame/drivers/ps2sony.cpp index 467be7f5da3..e13fcffeb0d 100644 --- a/src/mame/drivers/ps2sony.cpp +++ b/src/mame/drivers/ps2sony.cpp @@ -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)