diff options
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r-- | src/devices/cpu/mips/mips3.cpp | 1151 |
1 files changed, 1116 insertions, 35 deletions
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index f48682fd20a..021b81293b8 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -123,12 +123,12 @@ DEFINE_DEVICE_TYPE(RM7000LE, rm7000le_device, "rm7000le", "MIPS RM7000 (littl // VR4300 and VR5432 have 4 fewer PFN bits, and only 32 TLB entries -mips3_device::mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endianness) +mips3_device::mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endianness, uint32_t data_bits) : cpu_device(mconfig, type, tag, owner, clock) , device_vtlb_interface(mconfig, *this, AS_PROGRAM) - , m_program_config("program", endianness, 32, 32, 0, 32, MIPS3_MIN_PAGE_SHIFT) - , m_flavor(flavor) , m_core(nullptr) + , m_program_config("program", endianness, data_bits, 32, 0, 32, MIPS3_MIN_PAGE_SHIFT) + , m_flavor(flavor) , m_ppc(0) , m_nextpc(0) , m_pcbase(0) @@ -146,6 +146,7 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons , m_ldr(endianness == ENDIANNESS_BIG ? &mips3_device::ldr_be : &mips3_device::ldr_le) , m_sdl(endianness == ENDIANNESS_BIG ? &mips3_device::sdl_be : &mips3_device::sdl_le) , m_sdr(endianness == ENDIANNESS_BIG ? &mips3_device::sdr_be : &mips3_device::sdr_le) + , m_data_bits(data_bits) , c_system_clock(0) , m_pfnmask(flavor == MIPS3_TYPE_VR4300 ? 0x000fffff : 0x00ffffff) , m_tlbentries(flavor == MIPS3_TYPE_VR4300 ? 32 : MIPS3_MAX_TLB_ENTRIES) @@ -280,7 +281,10 @@ void mips3_device::generate_exception(int exception, int backup) { osd_printf_debug("TLB miss @ %08X\n", (uint32_t)m_core->cpr[0][COP0_BadVAddr]); } - m_core->pc += offset; + else + { + m_core->pc += offset; + } /* useful for tracking interrupts @@ -336,21 +340,41 @@ 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_core->vfmem = &m_core->vumem[0]; + m_core->vimem = reinterpret_cast<uint32_t*>(m_core->vfmem); m_cpu_clock = clock(); m_program = &space(AS_PROGRAM); if(m_program->endianness() == ENDIANNESS_LITTLE) { - auto cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); - m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; - m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + if (m_data_bits == 32) + { + auto cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); + m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; + m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + } + else + { + auto cache = m_program->cache<3, 0, ENDIANNESS_LITTLE>(); + m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; + m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + } } else { - auto cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); - m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; - m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; - } + if (m_data_bits == 32) + { + auto cache = m_program->cache<2, 0, ENDIANNESS_BIG>(); + m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; + m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + } + else + { + auto cache = m_program->cache<3, 0, ENDIANNESS_BIG>(); + m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); }; + m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; + } + } /* set up the endianness */ m_program->accessors(m_memory); @@ -360,7 +384,7 @@ void mips3_device::device_start() uint32_t flags = 0; /* initialize the UML generator */ - m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 8, 32, 2); + m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 8, m_data_bits, 2); /* add symbols for our stuff */ m_drcuml->symbol_add(&m_core->pc, sizeof(m_core->pc), "pc"); @@ -652,6 +676,77 @@ void mips3_device::device_start() set_icountptr(m_core->icount); } +void r5900le_device::device_start() +{ + mips3_device::device_start(); +#if USE_ABI_REG_NAMES + state_add( MIPS3_R0H, "zeroh", m_core->rh[0]).callimport().formatstr("%016X"); // Can't change R0 + state_add( MIPS3_R1H, "ath", m_core->rh[1]).formatstr("%016X"); + state_add( MIPS3_R2H, "v0h", m_core->rh[2]).formatstr("%016X"); + state_add( MIPS3_R3H, "v1h", m_core->rh[3]).formatstr("%016X"); + state_add( MIPS3_R4H, "a0h", m_core->rh[4]).formatstr("%016X"); + state_add( MIPS3_R5H, "a1h", m_core->rh[5]).formatstr("%016X"); + state_add( MIPS3_R6H, "a2h", m_core->rh[6]).formatstr("%016X"); + state_add( MIPS3_R7H, "a3h", m_core->rh[7]).formatstr("%016X"); + state_add( MIPS3_R8H, "t0h", m_core->rh[8]).formatstr("%016X"); + state_add( MIPS3_R9H, "t1h", m_core->rh[9]).formatstr("%016X"); + state_add( MIPS3_R10H, "t2h", m_core->rh[10]).formatstr("%016X"); + state_add( MIPS3_R11H, "t3h", m_core->rh[11]).formatstr("%016X"); + state_add( MIPS3_R12H, "t4h", m_core->rh[12]).formatstr("%016X"); + state_add( MIPS3_R13H, "t5h", m_core->rh[13]).formatstr("%016X"); + state_add( MIPS3_R14H, "t6h", m_core->rh[14]).formatstr("%016X"); + state_add( MIPS3_R15H, "t7h", m_core->rh[15]).formatstr("%016X"); + state_add( MIPS3_R16H, "s0h", m_core->rh[16]).formatstr("%016X"); + state_add( MIPS3_R17H, "s1h", m_core->rh[17]).formatstr("%016X"); + state_add( MIPS3_R18H, "s2h", m_core->rh[18]).formatstr("%016X"); + state_add( MIPS3_R19H, "s3h", m_core->rh[19]).formatstr("%016X"); + state_add( MIPS3_R20H, "s4h", m_core->rh[20]).formatstr("%016X"); + state_add( MIPS3_R21H, "s5h", m_core->rh[21]).formatstr("%016X"); + state_add( MIPS3_R22H, "s6h", m_core->rh[22]).formatstr("%016X"); + state_add( MIPS3_R23H, "s7h", m_core->rh[23]).formatstr("%016X"); + state_add( MIPS3_R24H, "t8h", m_core->rh[24]).formatstr("%016X"); + state_add( MIPS3_R25H, "t9h", m_core->rh[25]).formatstr("%016X"); + state_add( MIPS3_R26H, "k0h", m_core->rh[26]).formatstr("%016X"); + state_add( MIPS3_R27H, "k1h", m_core->rh[27]).formatstr("%016X"); + state_add( MIPS3_R28H, "gph", m_core->rh[28]).formatstr("%016X"); + state_add( MIPS3_R29H, "sph", m_core->rh[29]).formatstr("%016X"); + state_add( MIPS3_R30H, "fph", m_core->rh[30]).formatstr("%016X"); + state_add( MIPS3_R31H, "rah", m_core->rh[31]).formatstr("%016X"); +#else + state_add( MIPS3_R0H, "R0H", m_core->rh[0]).callimport().formatstr("%016X"); // Can't change R0 + state_add( MIPS3_R1H, "R1H", m_core->rh[1]).formatstr("%016X"); + state_add( MIPS3_R2H, "R2H", m_core->rh[2]).formatstr("%016X"); + state_add( MIPS3_R3H, "R3H", m_core->rh[3]).formatstr("%016X"); + state_add( MIPS3_R4H, "R4H", m_core->rh[4]).formatstr("%016X"); + state_add( MIPS3_R5H, "R5H", m_core->rh[5]).formatstr("%016X"); + state_add( MIPS3_R6H, "R6H", m_core->rh[6]).formatstr("%016X"); + state_add( MIPS3_R7H, "R7H", m_core->rh[7]).formatstr("%016X"); + state_add( MIPS3_R8H, "R8H", m_core->rh[8]).formatstr("%016X"); + state_add( MIPS3_R9H, "R9H", m_core->rh[9]).formatstr("%016X"); + state_add( MIPS3_R10H, "R10H", m_core->rh[10]).formatstr("%016X"); + state_add( MIPS3_R11H, "R11H", m_core->rh[11]).formatstr("%016X"); + state_add( MIPS3_R12H, "R12H", m_core->rh[12]).formatstr("%016X"); + state_add( MIPS3_R13H, "R13H", m_core->rh[13]).formatstr("%016X"); + state_add( MIPS3_R14H, "R14H", m_core->rh[14]).formatstr("%016X"); + state_add( MIPS3_R15H, "R15H", m_core->rh[15]).formatstr("%016X"); + state_add( MIPS3_R16H, "R16H", m_core->rh[16]).formatstr("%016X"); + state_add( MIPS3_R17H, "R17H", m_core->rh[17]).formatstr("%016X"); + state_add( MIPS3_R18H, "R18H", m_core->rh[18]).formatstr("%016X"); + state_add( MIPS3_R19H, "R19H", m_core->rh[19]).formatstr("%016X"); + state_add( MIPS3_R20H, "R20H", m_core->rh[20]).formatstr("%016X"); + state_add( MIPS3_R21H, "R21H", m_core->rh[21]).formatstr("%016X"); + state_add( MIPS3_R22H, "R22H", m_core->rh[22]).formatstr("%016X"); + state_add( MIPS3_R23H, "R23H", m_core->rh[23]).formatstr("%016X"); + state_add( MIPS3_R24H, "R24H", m_core->rh[24]).formatstr("%016X"); + state_add( MIPS3_R25H, "R25H", m_core->rh[25]).formatstr("%016X"); + state_add( MIPS3_R26H, "R26H", m_core->rh[26]).formatstr("%016X"); + state_add( MIPS3_R27H, "R27H", m_core->rh[27]).formatstr("%016X"); + state_add( MIPS3_R28H, "R28H", m_core->rh[28]).formatstr("%016X"); + state_add( MIPS3_R29H, "R29H", m_core->rh[29]).formatstr("%016X"); + state_add( MIPS3_R30H, "R30H", m_core->rh[30]).formatstr("%016X"); + state_add( MIPS3_R31H, "R31H", m_core->rh[31]).formatstr("%016X"); +#endif +} void mips3_device::state_export(const device_state_entry &entry) { @@ -1346,6 +1441,163 @@ inline void mips3_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t } } +inline void r5900le_device::WBYTE(offs_t address, uint8_t data) +{ + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_byte)(*m_program, address, data); + else mips3_device::WBYTE(address, data); +} + +inline void r5900le_device::WHALF(offs_t address, uint16_t data) +{ + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_word)(*m_program, address, data); + else mips3_device::WHALF(address, data); +} + +inline void r5900le_device::WWORD(offs_t address, uint32_t data) +{ + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword)(*m_program, address, data); + else mips3_device::WWORD(address, data); +} + +inline void r5900le_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) +{ + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword_masked)(*m_program, address, data, mem_mask); + else mips3_device::WWORD_MASKED(address, data, mem_mask); +} + +inline void r5900le_device::WDOUBLE(offs_t address, uint64_t data) { + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword)(*m_program, address, data); + else mips3_device::WDOUBLE(address, data); +} + +inline void r5900le_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) +{ + if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword_masked)(*m_program, address, data, mem_mask); + else mips3_device::WDOUBLE_MASKED(address, data, mem_mask); +} + +inline void r5900le_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t data_lo) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + (*m_memory.write_qword)(*m_program, address, data_hi); + (*m_memory.write_qword)(*m_program, address + 8, data_lo); + return; + } + + const uint32_t tlbval = vtlb_table()[address >> 12]; + if (tlbval & VTLB_WRITE_ALLOWED) + { + (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_hi); + (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_lo); + } + else + { + if(tlbval & VTLB_READ_ALLOWED) + { + generate_tlb_exception(EXCEPTION_TLBMOD, address); + } + else if(tlbval & VTLB_FLAG_FIXED) + { + generate_tlb_exception(EXCEPTION_TLBSTORE, address); + } + else + { + generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address); + } + } +} + +inline bool r5900le_device::RBYTE(offs_t address, uint32_t *result) { + if (address >= 0x70000000 && address < 0x70004000) { + *result = (*m_memory.read_byte)(*m_program, address); + return true; + } + return mips3_device::RBYTE(address, result); +} + +inline bool r5900le_device::RHALF(offs_t address, uint32_t *result) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = (*m_memory.read_word)(*m_program, address); + return true; + } + return mips3_device::RHALF(address, result); +} + +inline bool r5900le_device::RWORD(offs_t address, uint32_t *result) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = (*m_memory.read_dword)(*m_program, address); + return true; + } + return mips3_device::RWORD(address, result); +} + +inline bool r5900le_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = (*m_memory.read_dword_masked)(*m_program, address, mem_mask); + return true; + } + return mips3_device::RWORD_MASKED(address, result, mem_mask); +} + +inline bool r5900le_device::RDOUBLE(offs_t address, uint64_t *result) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = (*m_memory.read_qword)(*m_program, address); + return true; + } + return mips3_device::RDOUBLE(address, result); +} + +inline bool r5900le_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result = (*m_memory.read_qword_masked)(*m_program, address, mem_mask); + return true; + } + return mips3_device::RDOUBLE_MASKED(address, result, mem_mask); +} + +inline bool r5900le_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t *result_lo) +{ + if (address >= 0x70000000 && address < 0x70004000) + { + *result_hi = (*m_memory.read_qword)(*m_program, address); + *result_lo = (*m_memory.read_qword)(*m_program, address + 8); + return true; + } + + const uint32_t tlbval = vtlb_table()[address >> 12]; + if (tlbval & VTLB_READ_ALLOWED) + { + *result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); + *result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff)); + } + else + { + if(tlbval & VTLB_FLAG_FIXED) + { + generate_tlb_exception(EXCEPTION_TLBLOAD, address); + } + else + { + generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address); + } + *result_hi = 0; + *result_lo = 0; + return false; + } + return true; +} + /*************************************************************************** @@ -1845,6 +2097,12 @@ void mips3_device::handle_cop1_fr0(uint32_t op) FDVALD_FR0 = 1.0 / sqrt(FSVALD_FR0); break; + case 0x18: /* R5900 */ + if (m_flavor != MIPS3_TYPE_R5900) + break; + m_core->acc = FSVALS_FR0 + FTVALS_FR0; + break; + case 0x20: if (IS_INTEGRAL(op)) { @@ -2485,6 +2743,16 @@ void mips3_device::handle_cop1x_fr1(uint32_t op) COP2 (CUSTOM) EXECUTION HANDLING ***************************************************************************/ +inline void mips3_device::handle_dmfc2(uint32_t op) +{ + if (RTREG) RTVAL64 = get_cop2_reg(RDREG); +} + +inline void mips3_device::handle_dmtc2(uint32_t op) +{ + set_cop2_reg(RDREG, RTVAL64); +} + inline uint64_t mips3_device::get_cop2_reg(int idx) { return m_core->cpr[2][idx]; @@ -2502,7 +2770,112 @@ inline uint64_t mips3_device::get_cop2_creg(int idx) inline void mips3_device::set_cop2_creg(int idx, uint64_t val) { - m_core->ccr[2][idx] = val; + m_core->vfr[idx][0] = val; +} + +inline void r5900le_device::handle_dmfc2(uint32_t op) +{ + // QMFC2 + if (!RTREG) + { + return; + } + const int rt = RTREG; + uint32_t rtval[4] = { 0 }; + uint32_t *reg = reinterpret_cast<uint32_t*>(m_core->vfr[RDREG]); + for (int i = 0; i < 4; i++) + { + rtval[i] = reg[i]; + } + m_core->r[rt] = ((uint64_t)rtval[1] << 32) | rtval[0]; + m_core->rh[rt] = ((uint64_t)rtval[3] << 32) | rtval[2]; +} + +inline void r5900le_device::handle_dmtc2(uint32_t op) +{ + // QMTC2 + uint32_t rt = RTREG; + uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) }; + uint32_t *reg = reinterpret_cast<uint32_t*>(m_core->vfr[RDREG]); + for (int i = 0; i < 4; i++) + { + reg[i] = rtval[i]; + } +} + +inline uint64_t r5900le_device::get_cop2_reg(int idx) +{ + return reinterpret_cast<uint32_t*>(m_core->vfr[idx])[0]; +} + +inline void r5900le_device::set_cop2_reg(int idx, uint64_t val) +{ + reinterpret_cast<uint32_t*>(m_core->vfr[idx])[0] = (uint32_t)val; +} + +inline uint64_t r5900le_device::get_cop2_creg(int idx) +{ + return m_core->vcr[idx]; +} + +inline void r5900le_device::set_cop2_creg(int idx, uint64_t val) +{ + if (idx < 16) + { + m_core->vcr[idx] = val & 0xffff; + } + else + { + switch (idx) + { + case 16: // Status flag + m_core->vcr[idx] = val & 0xf30; + break; + + case 17: // MAC flag + case 26: // TPC register + case 27: // CMSAR0 register + m_core->vcr[idx] = val & 0xffff; + break; + + case 18: // clipping flag + m_core->vcr[idx] = val & 0xffffff; + break; + + case 20: // R register + m_core->vcr[idx] = val & 0x7fffff; + break; + + case 21: // I register + case 22: // Q register + m_core->vcr[idx] = val; + break; + + case 28: // FBRST register + m_core->vcr[idx] = val & 0xf0f; + break; + + case 29: // VPU-STAT register + // Register is read-only + break; + + case 31: // CMSAR1 register + m_core->vcr[idx] = val & 0xffff; + // TODO: Begin execution + break; + + case 19: + case 23: + case 24: + case 25: + case 30: // reserved + break; + + default: + m_core->vcr[idx] = val; + break; + } + } } void mips3_device::handle_cop2(uint32_t op) @@ -2516,12 +2889,12 @@ void mips3_device::handle_cop2(uint32_t op) switch (RSREG) { - case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (int32_t)get_cop2_reg(RDREG); break; - case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop2_reg(RDREG); break; - case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (int32_t)get_cop2_creg(RDREG); break; - case 0x04: /* MTCz */ set_cop2_reg(RDREG, RTVAL32); break; - case 0x05: /* DMTCz */ set_cop2_reg(RDREG, RTVAL64); break; - case 0x06: /* CTCz */ set_cop2_creg(RDREG, RTVAL32); break; + case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (int32_t)get_cop2_reg(RDREG); break; + case 0x01: /* DMFCz */ handle_dmfc2(op); break; + case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (int32_t)get_cop2_creg(RDREG); break; + case 0x04: /* MTCz */ set_cop2_reg(RDREG, RTVAL32); break; + case 0x05: /* DMTCz */ handle_dmtc2(op); break; + case 0x06: /* CTCz */ set_cop2_creg(RDREG, RTVAL32); break; case 0x08: /* BC */ switch (RTREG) { @@ -2543,18 +2916,186 @@ void mips3_device::handle_extra_cop2(uint32_t op) /*************************************************************************** - VU0 (COP2) EXECUTION HANDLING (R5900) + VU0/1 (COP2) EXECUTION HANDLING (R5900) ***************************************************************************/ void r5900le_device::handle_extra_cop2(uint32_t op) { - invalid_instruction(op); + const int rd = (op >> 6) & 31; + const int rs = (op >> 11) & 31; + const int rt = (op >> 16) & 31; + const int ext = ((op >> 4) & 0x7c) | (op & 3); + + switch (op & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: + printf("Unsupported instruction: VADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x04: case 0x05: case 0x06: case 0x07: + printf("Unsupported instruction: VSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x08: case 0x09: case 0x0a: case 0x0b: + printf("Unsupported instruction: VMADDbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + printf("Unsupported instruction: VMSUBbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x10: case 0x11: case 0x12: case 0x13: + printf("Unsupported instruction: VMAXbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x14: case 0x15: case 0x16: case 0x17: + printf("Unsupported instruction: VMINIbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x18: case 0x19: case 0x1a: case 0x1b: + printf("Unsupported instruction: VMULbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1c: printf("Unsupported instruction: VMULq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1d: printf("Unsupported instruction: VMAXi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1e: printf("Unsupported instruction: VMULi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1f: printf("Unsupported instruction: VMINIi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x20: printf("Unsupported instruction: VADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x21: printf("Unsupported instruction: VMADDq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x22: printf("Unsupported instruction: VADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x23: printf("Unsupported instruction: VMADDi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x24: printf("Unsupported instruction: VSUBq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x25: printf("Unsupported instruction: VMSUBq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x26: printf("Unsupported instruction: VSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x27: printf("Unsupported instruction: VMSUBi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x28: printf("Unsupported instruction: VADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x29: printf("Unsupported instruction: VMADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2a: printf("Unsupported instruction: VMUL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2b: printf("Unsupported instruction: VMAX @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2c: + { + float *fs = m_core->vfr[rs]; + float *ft = m_core->vfr[rt]; + float *fd = m_core->vfr[rt]; + for (int field = 0; field < 4; field++) + { + if (BIT(op, 24-field)) + { + fd[field] = fs[field] - ft[field]; + } + } + break; + } + case 0x2d: printf("Unsupported instruction: VMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2e: printf("Unsupported instruction: VOPMSUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2f: printf("Unsupported instruction: VMINI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x30: + if (rd) + { + m_core->vcr[rd] = (m_core->vcr[rs] + m_core->vcr[rt]) & 0xffff; + } + break; + case 0x31: printf("Unsupported instruction: VISUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x32: printf("Unsupported instruction: VIADDI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x34: printf("Unsupported instruction: VIAND @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x35: printf("Unsupported instruction: VIOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x38: printf("Unsupported instruction: VCALLMS @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x39: printf("Unsupported instruction: VCALLMSR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + switch (ext) + { + case 0x00: case 0x01: case 0x02: case 0x03: + printf("Unsupported instruction: VADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x04: case 0x05: case 0x06: case 0x07: + printf("Unsupported instruction: VSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x08: case 0x09: case 0x0a: case 0x0b: + printf("Unsupported instruction: VMADDAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + printf("Unsupported instruction: VMSUBAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x10: printf("Unsupported instruction: VITOF0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x11: printf("Unsupported instruction: VITOF4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x12: printf("Unsupported instruction: VITOF12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x13: printf("Unsupported instruction: VITOF15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x14: printf("Unsupported instruction: VFTOI0 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x15: printf("Unsupported instruction: VFTOI4 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x16: printf("Unsupported instruction: VFTOI12 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x17: printf("Unsupported instruction: VFTOI15 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x18: case 0x19: case 0x1a: case 0x1b: + printf("Unsupported instruction: VMULAbc @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1c: printf("Unsupported instruction: VMULAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1d: printf("Unsupported instruction: VABS @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1e: printf("Unsupported instruction: VMULAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x1f: printf("Unsupported instruction: VCLIP @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x20: printf("Unsupported instruction: VADDAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x21: printf("Unsupported instruction: VMADDAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x22: printf("Unsupported instruction: VADDAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x23: printf("Unsupported instruction: VMADDAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x24: printf("Unsupported instruction: VSUBAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x25: printf("Unsupported instruction: VMSUBAq @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x26: printf("Unsupported instruction: VSUBAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x27: printf("Unsupported instruction: VMSUBAi @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x28: printf("Unsupported instruction: VADDA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x29: printf("Unsupported instruction: VMADDA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2a: printf("Unsupported instruction: VMULA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + // 2b? + case 0x2c: printf("Unsupported instruction: VSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2d: printf("Unsupported instruction: VMSUBA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2e: printf("Unsupported instruction: VOPMULA @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x2f: printf("Unsupported instruction: VNOP @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x30: printf("Unsupported instruction: VMOVE @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x31: printf("Unsupported instruction: VMR32 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + // 32? + // 33? + case 0x34: printf("Unsupported instruction: VLQI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x35: + { + uint32_t *base = &m_core->vimem[m_core->vcr[rt] << 2]; + uint32_t *fs = reinterpret_cast<uint32_t*>(m_core->vfr[rs]); + for (int field = 0; field < 4; field++) + { + if (BIT(op, 24-field)) + { + base[field] = fs[field]; + } + } + if (rt) + { + m_core->vcr[rt]++; + m_core->vcr[rt] &= 0xffff; + } + break; + } + case 0x36: printf("Unsupported instruction: VLQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x37: printf("Unsupported instruction: VSQD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x38: printf("Unsupported instruction: VDIV @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x39: printf("Unsupported instruction: VSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3a: printf("Unsupported instruction: VRSQRT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3b: printf("Unsupported instruction: VWAITQ @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3c: printf("Unsupported instruction: VMTIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3d: printf("Unsupported instruction: VMFIR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3e: printf("Unsupported instruction: VILWR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x3f: /* VISWR */ + { + const uint32_t val = m_core->vcr[rt]; + const uint32_t base = m_core->vcr[rs] << 2; + for (int field = 0; field < 4; field++) + { + if (BIT(op, 24-field)) + { + m_core->vimem[base + field] = val; + } + } + break; + } + case 0x40: printf("Unsupported instruction: VRNEXT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x41: printf("Unsupported instruction: VRGET @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x42: printf("Unsupported instruction: VRINIT @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + case 0x43: printf("Unsupported instruction: VRXOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break; + default: invalid_instruction(op); break; + } + break; + default: + invalid_instruction(op); + break; + } } /*************************************************************************** CORE EXECUTION LOOP ***************************************************************************/ +void mips3_device::handle_extra_base(uint32_t op) +{ + /* ??? */ + invalid_instruction(op); +} + void mips3_device::handle_regimm(uint32_t op) { switch (RTREG) @@ -2608,6 +3149,8 @@ void mips3_device::handle_special(uint32_t op) LOVAL64 = (int32_t)temp64; HIVAL64 = (int32_t)(temp64 >> 32); m_core->icount -= 3; + if (m_flavor == MIPS3_TYPE_R5900 && RDREG) + RDVAL64 = LOVAL64; break; } case 0x19: /* MULTU */ @@ -2616,6 +3159,8 @@ void mips3_device::handle_special(uint32_t op) LOVAL64 = (int32_t)temp64; HIVAL64 = (int32_t)(temp64 >> 32); m_core->icount -= 3; + if (m_flavor == MIPS3_TYPE_R5900 && RDREG) + RDVAL64 = LOVAL64; break; } case 0x1a: /* DIV */ @@ -2696,7 +3241,8 @@ void mips3_device::handle_special(uint32_t op) 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 0x28: handle_extra_special(op); 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); @@ -2729,21 +3275,11 @@ void mips3_device::handle_extra_special(uint32_t op) invalid_instruction(op); } -void r5900le_device::handle_extra_special(uint32_t op) -{ - invalid_instruction(op); -} - void mips3_device::handle_extra_regimm(uint32_t op) { invalid_instruction(op); } -void r5900le_device::handle_extra_regimm(uint32_t op) -{ - invalid_instruction(op); -} - void mips3_device::handle_idt(uint32_t op) { switch (op & 0x1f) @@ -2758,8 +3294,551 @@ void mips3_device::handle_idt(uint32_t op) } } +void r5900le_device::handle_extra_base(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rt = (op >> 16) & 31; + + switch (op >> 26) + { + case 0x1e: /* LQ */ + { + uint64_t temp64[2]; + bool success = RQUAD(SIMMVAL + m_core->r[rs], &temp64[1], &temp64[0]); + if (success && rt) + { + m_core->r[rt] = temp64[0]; + m_core->rh[rt] = temp64[1]; + } + m_core->icount--; + break; + } + case 0x1f: /* SQ */ + WQUAD(SIMMVAL + m_core->r[rs], m_core->rh[rt], m_core->r[rt]); + m_core->icount--; + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_extra_special(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rd = (op >> 11) & 31; + + switch (op & 63) + { + case 0x28: /* MFSA */ + m_core->r[rd] = m_core->sa; + break; + case 0x29: /* MTSA */ + m_core->sa = (uint32_t)m_core->r[rs]; + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_extra_regimm(uint32_t op) +{ + switch (op & 63) + { + case 0x18: /* MTSAB */ + printf("Unsupported instruction: MTSAB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x19: /* MTSAH */ + printf("Unsupported instruction: MTSAH @%08x\n", m_core->pc - 4); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + void r5900le_device::handle_idt(uint32_t op) { + //const int rs = (op >> 21) & 31; + //const int rt = (op >> 16) & 31; + const int rd = (op >> 11) & 31; + + switch (op & 0x3f) + { + case 0x00: /* MADD */ + printf("Unsupported instruction: MADD @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x01: /* MADDU */ + printf("Unsupported instruction: MADDU @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x04: /* PLZCW */ + printf("Unsupported instruction: PLZCW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x08: /* MMI0 */ + handle_mmi0(op); + break; + case 0x09: /* MMI2 */ + handle_mmi2(op); + break; + case 0x10: /* MFHI1 */ + if (rd) + m_core->r[rd] = m_core->rh[REG_HI]; + m_core->icount--; + break; + case 0x11: /* MTHI1 */ + printf("Unsupported instruction: MTHI1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x12: /* MFLO1 */ + if (rd) + m_core->r[rd] = m_core->rh[REG_LO]; + m_core->icount--; + break; + case 0x13: /* MTLO1 */ + printf("Unsupported instruction: MTLO1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x18: /* MULT1 */ + { + uint64_t temp64 = (int64_t)(int32_t)RSVAL32 * (int64_t)(int32_t)RTVAL32; + m_core->rh[REG_LO] = (int32_t)temp64; + m_core->rh[REG_HI] = (int32_t)(temp64 >> 32); + if (rd) + m_core->r[rd] = m_core->rh[REG_LO]; + m_core->icount -= 3; // ? + break; + } + case 0x19: /* MULTU1 */ + printf("Unsupported instruction: MULTU1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1a: /* DIV1 */ + if (RTVAL32) + { + m_core->rh[REG_LO] = (int32_t)((int32_t)RSVAL32 / (int32_t)RTVAL32); + m_core->rh[REG_HI] = (int32_t)((int32_t)RSVAL32 % (int32_t)RTVAL32); + } + m_core->icount -= 35; // ? + break; + case 0x1b: /* DIVU1 */ + if (RTVAL32) + { + m_core->rh[REG_LO] = (int32_t)(RSVAL32 / RTVAL32); + m_core->rh[REG_HI] = (int32_t)(RSVAL32 % RTVAL32); + } + m_core->icount -= 35; // ? + break; + case 0x20: /* MADD1 */ + printf("Unsupported instruction: MADD1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x21: /* MADDU1 */ + printf("Unsupported instruction: MADDU1 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x28: /* MMI1 */ + handle_mmi1(op); + break; + case 0x29: /* MMI3 */ + handle_mmi3(op); + break; + case 0x30: /* PMFHL */ + printf("Unsupported instruction: PMFHL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x31: /* PMTHL */ + printf("Unsupported instruction: PMTHL @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x34: /* PSLLH */ + printf("Unsupported instruction: PSLLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x36: /* PSRLH */ + printf("Unsupported instruction: PSRLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x37: /* PSRAH */ + printf("Unsupported instruction: PSRAH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x3c: /* PSLLW */ + printf("Unsupported instruction: PSLLW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x3e: /* PSRLW */ + printf("Unsupported instruction: PSRLW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x3f: /* PSRAW */ + printf("Unsupported instruction: PSRAW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_mmi0(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rt = (op >> 16) & 31; + const int rd = (op >> 11) & 31; + + switch ((op >> 6) & 0x1f) + { + case 0x00: /* PADDW */ + printf("Unsupported instruction: PADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x01: /* PSUBW */ + printf("Unsupported instruction: PSUBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x02: /* PCGTW */ + printf("Unsupported instruction: PCGTW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x03: /* PMAXW */ + printf("Unsupported instruction: PMAXW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x04: /* PADDH */ + printf("Unsupported instruction: PADDH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x05: /* PSUBH */ + printf("Unsupported instruction: PSUBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x06: /* PCGTH */ + printf("Unsupported instruction: PCGTH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x07: /* PMAXH */ + printf("Unsupported instruction: PMAXH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x08: /* PADDB */ + printf("Unsupported instruction: PADDB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x09: /* PSUBB */ + printf("Unsupported instruction: PSUBB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0a: /* PCGTB */ + printf("Unsupported instruction: PCGTB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x10: /* PADDSW */ + printf("Unsupported instruction: PADDSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x11: /* PSUBSW */ + printf("Unsupported instruction: PSUBSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x12: /* PEXTLW */ + { + if (rd) + { + uint64_t rsval = m_core->r[rs]; + uint64_t rtval = m_core->r[rt]; + uint32_t rdval[4] = { (uint32_t)rtval, (uint32_t)rsval, (uint32_t)(rtval >> 32), (uint32_t)(rsval >> 32) }; + m_core->r[rd] = (uint64_t)rdval[1] << 32 | rdval[0]; + m_core->rh[rd] = (uint64_t)rdval[3] << 32 | rdval[2]; + } + break; + } + case 0x13: /* PPACW */ + printf("Unsupported instruction: PPACW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x14: /* PADDSH */ + printf("Unsupported instruction: PADDSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x15: /* PSUBSH */ + printf("Unsupported instruction: PSUBSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x16: /* PEXTLH */ + printf("Unsupported instruction: PEXTLH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x17: /* PPACH */ + printf("Unsupported instruction: PPACH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x18: /* PADDSB */ + printf("Unsupported instruction: PADDSB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x19: /* PSUBSB */ + printf("Unsupported instruction: PSUBSB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1a: /* PEXTLB */ + printf("Unsupported instruction: PEXTLB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1b: /* PPACB */ + printf("Unsupported instruction: PPACB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1e: /* PEXT5 */ + printf("Unsupported instruction: PEXT5 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1f: /* PPAC5 */ + printf("Unsupported instruction: PPAC5 @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_mmi1(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rt = (op >> 16) & 31; + const int rd = (op >> 11) & 31; + + switch ((op >> 6) & 0x1f) + { + case 0x01: /* PABSW */ + printf("Unsupported instruction: PABSW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x02: /* PCEQW */ + printf("Unsupported instruction: PCEQW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x03: /* PMINW */ + printf("Unsupported instruction: PMINW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x04: /* PADSBH */ + printf("Unsupported instruction: PADSBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x05: /* PABSH */ + printf("Unsupported instruction: PABSH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x06: /* PCEQH */ + printf("Unsupported instruction: PCEQH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x07: /* PMINH */ + printf("Unsupported instruction: PMINH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0a: /* PCEQB */ + printf("Unsupported instruction: PCEQB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x10: /* PADDUW */ + { + if (rd == 0) break; + + uint32_t rsval[4] = { (uint32_t)m_core->r[rs], (uint32_t)(m_core->r[rs] >> 32), (uint32_t)m_core->rh[rs], (uint32_t)(m_core->rh[rs] >> 32) }; + uint32_t rtval[4] = { (uint32_t)m_core->r[rt], (uint32_t)(m_core->r[rt] >> 32), (uint32_t)m_core->rh[rt], (uint32_t)(m_core->rh[rt] >> 32) }; + uint64_t rdval[4] = { 0 }; + + for (int i = 0; i < 4; i++) + { + uint64_t sum = (uint64_t)rsval[i] + (uint64_t)rtval[i]; + rdval[i] = (sum >= 0x100000000ULL) ? 0xffffffffULL : sum; + } + m_core->r[rd] = rdval[0] | (rdval[1] << 32); + m_core->rh[rd] = rdval[2] | (rdval[3] << 32); + m_core->icount -= 1; + break; + } + case 0x11: /* PSUBUW */ + printf("Unsupported instruction: PSUBUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x12: /* PEXTUW */ + printf("Unsupported instruction: PEXTUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x14: /* PADDUH */ + printf("Unsupported instruction: PADDUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x15: /* PSUBUH */ + printf("Unsupported instruction: PSUBUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x16: /* PEXTUH */ + printf("Unsupported instruction: PEXTUH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x18: /* PADDUB */ + printf("Unsupported instruction: PADDUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x19: /* PSUBUB */ + printf("Unsupported instruction: PSUBUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1a: /* PEXTUB */ + printf("Unsupported instruction: PEXTUB @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1b: /* QFSRV */ + printf("Unsupported instruction: QFSRV @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_mmi2(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rt = (op >> 16) & 31; + const int rd = (op >> 11) & 31; + + switch ((op >> 6) & 0x1f) + { + case 0x00: /* PMADDW */ + printf("Unsupported instruction: PMADDW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x02: /* PSLLVW */ + printf("Unsupported instruction: PSLLVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x03: /* PSRLVW */ + printf("Unsupported instruction: PSRLVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x04: /* PMSUBW */ + printf("Unsupported instruction: PMSUBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x08: /* PMFHI */ + if (rd) + { + m_core->r[rd] = m_core->r[REG_HI]; + m_core->rh[rd] = m_core->rh[REG_HI]; + } + m_core->icount--; + break; + case 0x09: /* PMFLO */ + if (rd) + { + m_core->r[rd] = m_core->r[REG_LO]; + m_core->rh[rd] = m_core->rh[REG_LO]; + } + m_core->icount--; + break; + case 0x0a: /* PINTH */ + printf("Unsupported instruction: PINTH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0c: /* PMULTW */ + printf("Unsupported instruction: PMULTW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0d: /* PDIVW */ + printf("Unsupported instruction: PDIVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0e: /* PCPYLD */ + if (rd) + { + m_core->rh[rd] = m_core->r[rs]; + m_core->r[rd] = m_core->r[rt]; + } + m_core->icount--; + break; + case 0x10: /* PMADDH */ + printf("Unsupported instruction: PMADDH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x11: /* PHMADH */ + printf("Unsupported instruction: PHMADH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x12: /* PAND */ + printf("Unsupported instruction: PAND @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x13: /* PXOR */ + printf("Unsupported instruction: PXOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x14: /* PMSUBH */ + printf("Unsupported instruction: PMSUBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x15: /* PHMSBH */ + printf("Unsupported instruction: PHMSBH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1a: /* PEXEH */ + printf("Unsupported instruction: PEXEH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1b: /* PREVH */ + printf("Unsupported instruction: PREVH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1c: /* PMULTH */ + printf("Unsupported instruction: PMULTH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1d: /* PDIVBW */ + printf("Unsupported instruction: PDIVBW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1e: /* PEXEW */ + printf("Unsupported instruction: PEXEW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1f: /* PROT3W */ + printf("Unsupported instruction: PROT3W @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + +void r5900le_device::handle_mmi3(uint32_t op) +{ + const int rs = (op >> 21) & 31; + const int rt = (op >> 16) & 31; + const int rd = (op >> 11) & 31; + + switch ((op >> 6) & 0x1f) + { + case 0x00: /* PMADDUW */ + printf("Unsupported instruction: PMADDUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x03: /* PSRAVW */ + printf("Unsupported instruction: PSRAVW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x08: /* PMTHI */ + printf("Unsupported instruction: PMTHI @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x09: /* PTMLO */ + printf("Unsupported instruction: PMTLO @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0a: /* PINTEH */ + printf("Unsupported instruction: PINTEH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0c: /* PMULTUW */ + printf("Unsupported instruction: PMULTUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0d: /* PDIVUW */ + printf("Unsupported instruction: PDIVUW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x0e: /* PCPYUD */ + if (rd) + { + m_core->rh[rd] = m_core->rh[rs]; + m_core->r[rd] = m_core->rh[rt]; + } + m_core->icount--; + break; + case 0x12: /* POR */ + if (rd) + { + m_core->rh[rd] = m_core->rh[rs] | m_core->rh[rt]; + m_core->r[rd] = m_core->r[rs] | m_core->r[rt]; + } + m_core->icount--; + break; + case 0x13: /* PNOR */ + printf("Unsupported instruction: PNOR @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1a: /* PEXCH */ + printf("Unsupported instruction: PEXCH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1b: /* PCPYH */ + printf("Unsupported instruction: PCPYH @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + case 0x1e: /* PEXCW */ + printf("Unsupported instruction: PEXCW @%08x\n", m_core->pc - 4); fflush(stdout); fatalerror("Unsupported parallel instruction\n"); + break; + default: + invalid_instruction(op); + break; + } +} + +void mips3_device::handle_ldc2(uint32_t op) +{ + uint64_t temp64 = 0; + if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) set_cop2_reg(RTREG, temp64); +} + +void mips3_device::handle_sdc2(uint32_t op) +{ + WDOUBLE(SIMMVAL+RSVAL32, get_cop2_reg(RTREG)); +} + +void r5900le_device::handle_ldc2(uint32_t op) +{ + /* LQC2 */ + const uint32_t base = SIMMVAL + RSVAL32; + uint32_t *reg = reinterpret_cast<uint32_t*>(m_core->vfr[RTREG]); + for (uint32_t i = 0; i < 4; i++) + { + uint32_t temp = 0; + if (RWORD(base + (i << 2), &temp)) reg[i] = temp; + } +} + +void r5900le_device::handle_sdc2(uint32_t op) +{ + /* SQC2 */ + const uint32_t base = SIMMVAL + RSVAL32; + uint32_t *reg = reinterpret_cast<uint32_t*>(m_core->vfr[RTREG]); + for (uint32_t i = 0; i < 4; i++) + { + WWORD(base + (i << 2), reg[i]); + } } void mips3_device::burn_cycles(int32_t cycles) @@ -2941,7 +4020,7 @@ void mips3_device::execute_run() if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) set_cop1_reg64(RTREG, temp64); break; - case 0x36: /* LDC2 */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) set_cop2_reg(RTREG, temp64); break; + case 0x36: handle_ldc2(op); break; case 0x37: /* LD */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64) && RTREG) RTVAL64 = temp64; break; case 0x38: /* SC */ if (RWORD(SIMMVAL+RSVAL32, &temp) && RTREG) { @@ -2989,9 +4068,11 @@ void mips3_device::execute_run() } WDOUBLE(SIMMVAL+RSVAL32, get_cop1_reg64(RTREG)); break; - case 0x3e: /* SDC2 */ WDOUBLE(SIMMVAL+RSVAL32, get_cop2_reg(RTREG)); break; + case 0x3e: handle_sdc2(op); break; case 0x3f: /* SD */ WDOUBLE(SIMMVAL+RSVAL32, RTVAL64); break; - default: /* ??? */ invalid_instruction(op); break; + default: + handle_extra_base(op); + break; } /* Clear this flag once instruction execution is finished, will interfere with interrupt exceptions otherwise */ m_delayslot = false; |