summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips3.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips3.cpp')
-rw-r--r--src/devices/cpu/mips/mips3.cpp1151
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;