summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author mooglyguy <therealmogminer@gmail.com>2018-06-28 18:16:55 +0200
committer mooglyguy <therealmogminer@gmail.com>2018-06-28 18:24:16 +0200
commiteb5a8a3dc85b2cb3572687633b07bf93292ead62 (patch)
treec81c264a72bb19ebde9f758c406ff17b6d01905a
parent85a16dfb9d98283b6dfccb4b1b915fd19c432361 (diff)
-ps2sony: Fleshing out the skeleton driver. [Ryan Holtz]
* Added ps2timer device to encapsulate Playstation 2 timers. * Temporarily hacked R5900 core to always have scratchpad RAM mapped at 0x70000000. * Added reference counting to divtlb so that it does not unmap pages that are still shared with other entries. * Added a considerable amount of logging to ps2sony.cpp. -mips3: Added basic Emotion Engine support. [Ryan Holtz] * Added S bit to TLB mapping. * Added support for VSUB, VIADD, VSQI, VISWR, VOR, LQ, SQ, MFSA, MTSA, MFHI1, MFLO1, MULT1, DIV1, DIVU1, PEXTLW, PADDUW, PMFHI, PMFLO, PCPYLD, PCPYUD, SQC2, LQC2 opcodes. [Ryan Holtz]
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/cpu/mips/mips3.cpp1151
-rw-r--r--src/devices/cpu/mips/mips3.h1383
-rw-r--r--src/devices/cpu/mips/mips3com.cpp6
-rw-r--r--src/devices/cpu/mips/mips3com.h4
-rw-r--r--src/devices/cpu/mips/mips3dsm.cpp6
-rw-r--r--src/devices/cpu/mips/r3000.cpp31
-rw-r--r--src/devices/cpu/mips/r3000.h26
-rw-r--r--src/devices/machine/wd33c93.cpp2
-rw-r--r--src/emu/divtlb.cpp23
-rw-r--r--src/emu/divtlb.h1
-rw-r--r--src/mame/drivers/ps2sony.cpp1045
-rw-r--r--src/mame/machine/ps2timer.cpp270
-rw-r--r--src/mame/machine/ps2timer.h118
14 files changed, 3337 insertions, 731 deletions
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 2e5db83356e..3009590149e 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -3061,6 +3061,8 @@ files {
MAME_DIR .. "src/mame/drivers/pve500.cpp",
MAME_DIR .. "src/mame/drivers/smc777.cpp",
MAME_DIR .. "src/mame/drivers/ps2sony.cpp",
+ MAME_DIR .. "src/mame/machine/ps2timer.cpp",
+ MAME_DIR .. "src/mame/machine/ps2timer.h",
}
createMESSProjects(_target, _subtarget, "sord")
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;
diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h
index 1e55cd81478..b896235c85a 100644
--- a/src/devices/cpu/mips/mips3.h
+++ b/src/devices/cpu/mips/mips3.h
@@ -2,10 +2,10 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- mips3.h
+mips3.h
- Interface file for the universal machine language-based
- MIPS III/IV emulator.
+Interface file for the universal machine language-based
+MIPS III/IV emulator.
***************************************************************************/
@@ -21,188 +21,219 @@
// NEC VR4300 series is MIPS III with 32-bit address bus and slightly custom COP0/TLB
-DECLARE_DEVICE_TYPE(VR4300BE, vr4300be_device)
-DECLARE_DEVICE_TYPE(VR4300LE, vr4300le_device)
+DECLARE_DEVICE_TYPE(VR4300BE, vr4300be_device)
+DECLARE_DEVICE_TYPE(VR4300LE, vr4300le_device)
// VR4310 = VR4300 with different speed bin
-DECLARE_DEVICE_TYPE(VR4310BE, vr4310be_device)
-DECLARE_DEVICE_TYPE(VR4310LE, vr4310le_device)
-DECLARE_DEVICE_TYPE(R4600BE, r4600be_device)
-DECLARE_DEVICE_TYPE(R4600LE, r4600le_device)
-DECLARE_DEVICE_TYPE(R4650BE, r4650be_device)
-DECLARE_DEVICE_TYPE(R4650LE, r4650le_device)
-DECLARE_DEVICE_TYPE(R4700BE, r4700be_device)
-DECLARE_DEVICE_TYPE(R4700LE, r4700le_device)
-DECLARE_DEVICE_TYPE(TX4925BE, tx4925be_device)
-DECLARE_DEVICE_TYPE(TX4925LE, tx4925le_device)
-DECLARE_DEVICE_TYPE(R5000BE, r5000be_device)
-DECLARE_DEVICE_TYPE(R5000LE, r5000le_device)
-DECLARE_DEVICE_TYPE(VR5500BE, vr5500be_device)
-DECLARE_DEVICE_TYPE(VR5500LE, vr5500le_device)
+DECLARE_DEVICE_TYPE(VR4310BE, vr4310be_device)
+DECLARE_DEVICE_TYPE(VR4310LE, vr4310le_device)
+DECLARE_DEVICE_TYPE(R4600BE, r4600be_device)
+DECLARE_DEVICE_TYPE(R4600LE, r4600le_device)
+DECLARE_DEVICE_TYPE(R4650BE, r4650be_device)
+DECLARE_DEVICE_TYPE(R4650LE, r4650le_device)
+DECLARE_DEVICE_TYPE(R4700BE, r4700be_device)
+DECLARE_DEVICE_TYPE(R4700LE, r4700le_device)
+DECLARE_DEVICE_TYPE(TX4925BE, tx4925be_device)
+DECLARE_DEVICE_TYPE(TX4925LE, tx4925le_device)
+DECLARE_DEVICE_TYPE(R5000BE, r5000be_device)
+DECLARE_DEVICE_TYPE(R5000LE, r5000le_device)
+DECLARE_DEVICE_TYPE(VR5500BE, vr5500be_device)
+DECLARE_DEVICE_TYPE(VR5500LE, vr5500le_device)
DECLARE_DEVICE_TYPE(QED5271BE, qed5271be_device)
DECLARE_DEVICE_TYPE(QED5271LE, qed5271le_device)
-DECLARE_DEVICE_TYPE(RM7000BE, rm7000be_device)
-DECLARE_DEVICE_TYPE(RM7000LE, rm7000le_device)
-DECLARE_DEVICE_TYPE(R5900LE, r5900le_device)
+DECLARE_DEVICE_TYPE(RM7000BE, rm7000be_device)
+DECLARE_DEVICE_TYPE(RM7000LE, rm7000le_device)
+DECLARE_DEVICE_TYPE(R5900LE, r5900le_device)
/***************************************************************************
- REGISTER ENUMERATION
+REGISTER ENUMERATION
***************************************************************************/
-enum
-{
- MIPS3_PC = STATE_GENPC,
- MIPS3_R0 = 1,
- MIPS3_R1,
- MIPS3_R2,
- MIPS3_R3,
- MIPS3_R4,
- MIPS3_R5,
- MIPS3_R6,
- MIPS3_R7,
- MIPS3_R8,
- MIPS3_R9,
- MIPS3_R10,
- MIPS3_R11,
- MIPS3_R12,
- MIPS3_R13,
- MIPS3_R14,
- MIPS3_R15,
- MIPS3_R16,
- MIPS3_R17,
- MIPS3_R18,
- MIPS3_R19,
- MIPS3_R20,
- MIPS3_R21,
- MIPS3_R22,
- MIPS3_R23,
- MIPS3_R24,
- MIPS3_R25,
- MIPS3_R26,
- MIPS3_R27,
- MIPS3_R28,
- MIPS3_R29,
- MIPS3_R30,
- MIPS3_R31,
- MIPS3_HI,
- MIPS3_LO,
- MIPS3_FPR0,
- MIPS3_FPS0,
- MIPS3_FPD0,
- MIPS3_FPR1,
- MIPS3_FPS1,
- MIPS3_FPD1,
- MIPS3_FPR2,
- MIPS3_FPS2,
- MIPS3_FPD2,
- MIPS3_FPR3,
- MIPS3_FPS3,
- MIPS3_FPD3,
- MIPS3_FPR4,
- MIPS3_FPS4,
- MIPS3_FPD4,
- MIPS3_FPR5,
- MIPS3_FPS5,
- MIPS3_FPD5,
- MIPS3_FPR6,
- MIPS3_FPS6,
- MIPS3_FPD6,
- MIPS3_FPR7,
- MIPS3_FPS7,
- MIPS3_FPD7,
- MIPS3_FPR8,
- MIPS3_FPS8,
- MIPS3_FPD8,
- MIPS3_FPR9,
- MIPS3_FPS9,
- MIPS3_FPD9,
- MIPS3_FPR10,
- MIPS3_FPS10,
- MIPS3_FPD10,
- MIPS3_FPR11,
- MIPS3_FPS11,
- MIPS3_FPD11,
- MIPS3_FPR12,
- MIPS3_FPS12,
- MIPS3_FPD12,
- MIPS3_FPR13,
- MIPS3_FPS13,
- MIPS3_FPD13,
- MIPS3_FPR14,
- MIPS3_FPS14,
- MIPS3_FPD14,
- MIPS3_FPR15,
- MIPS3_FPS15,
- MIPS3_FPD15,
- MIPS3_FPR16,
- MIPS3_FPS16,
- MIPS3_FPD16,
- MIPS3_FPR17,
- MIPS3_FPS17,
- MIPS3_FPD17,
- MIPS3_FPR18,
- MIPS3_FPS18,
- MIPS3_FPD18,
- MIPS3_FPR19,
- MIPS3_FPS19,
- MIPS3_FPD19,
- MIPS3_FPR20,
- MIPS3_FPS20,
- MIPS3_FPD20,
- MIPS3_FPR21,
- MIPS3_FPS21,
- MIPS3_FPD21,
- MIPS3_FPR22,
- MIPS3_FPS22,
- MIPS3_FPD22,
- MIPS3_FPR23,
- MIPS3_FPS23,
- MIPS3_FPD23,
- MIPS3_FPR24,
- MIPS3_FPS24,
- MIPS3_FPD24,
- MIPS3_FPR25,
- MIPS3_FPS25,
- MIPS3_FPD25,
- MIPS3_FPR26,
- MIPS3_FPS26,
- MIPS3_FPD26,
- MIPS3_FPR27,
- MIPS3_FPS27,
- MIPS3_FPD27,
- MIPS3_FPR28,
- MIPS3_FPS28,
- MIPS3_FPD28,
- MIPS3_FPR29,
- MIPS3_FPS29,
- MIPS3_FPD29,
- MIPS3_FPR30,
- MIPS3_FPS30,
- MIPS3_FPD30,
- MIPS3_FPR31,
- MIPS3_FPS31,
- MIPS3_FPD31,
- MIPS3_CCR1_31,
- MIPS3_SR,
- MIPS3_EPC,
- MIPS3_CAUSE,
- MIPS3_COUNT,
- MIPS3_COMPARE,
- MIPS3_INDEX,
- MIPS3_RANDOM,
- MIPS3_ENTRYHI,
- MIPS3_ENTRYLO0,
- MIPS3_ENTRYLO1,
- MIPS3_PAGEMASK,
- MIPS3_WIRED,
- MIPS3_BADVADDR
+enum {
+ MIPS3_PC = STATE_GENPC,
+ MIPS3_R0 = 1,
+ MIPS3_R1,
+ MIPS3_R2,
+ MIPS3_R3,
+ MIPS3_R4,
+ MIPS3_R5,
+ MIPS3_R6,
+ MIPS3_R7,
+ MIPS3_R8,
+ MIPS3_R9,
+ MIPS3_R10,
+ MIPS3_R11,
+ MIPS3_R12,
+ MIPS3_R13,
+ MIPS3_R14,
+ MIPS3_R15,
+ MIPS3_R16,
+ MIPS3_R17,
+ MIPS3_R18,
+ MIPS3_R19,
+ MIPS3_R20,
+ MIPS3_R21,
+ MIPS3_R22,
+ MIPS3_R23,
+ MIPS3_R24,
+ MIPS3_R25,
+ MIPS3_R26,
+ MIPS3_R27,
+ MIPS3_R28,
+ MIPS3_R29,
+ MIPS3_R30,
+ MIPS3_R31,
+ MIPS3_HI,
+ MIPS3_LO,
+ MIPS3_FPR0,
+ MIPS3_FPS0,
+ MIPS3_FPD0,
+ MIPS3_FPR1,
+ MIPS3_FPS1,
+ MIPS3_FPD1,
+ MIPS3_FPR2,
+ MIPS3_FPS2,
+ MIPS3_FPD2,
+ MIPS3_FPR3,
+ MIPS3_FPS3,
+ MIPS3_FPD3,
+ MIPS3_FPR4,
+ MIPS3_FPS4,
+ MIPS3_FPD4,
+ MIPS3_FPR5,
+ MIPS3_FPS5,
+ MIPS3_FPD5,
+ MIPS3_FPR6,
+ MIPS3_FPS6,
+ MIPS3_FPD6,
+ MIPS3_FPR7,
+ MIPS3_FPS7,
+ MIPS3_FPD7,
+ MIPS3_FPR8,
+ MIPS3_FPS8,
+ MIPS3_FPD8,
+ MIPS3_FPR9,
+ MIPS3_FPS9,
+ MIPS3_FPD9,
+ MIPS3_FPR10,
+ MIPS3_FPS10,
+ MIPS3_FPD10,
+ MIPS3_FPR11,
+ MIPS3_FPS11,
+ MIPS3_FPD11,
+ MIPS3_FPR12,
+ MIPS3_FPS12,
+ MIPS3_FPD12,
+ MIPS3_FPR13,
+ MIPS3_FPS13,
+ MIPS3_FPD13,
+ MIPS3_FPR14,
+ MIPS3_FPS14,
+ MIPS3_FPD14,
+ MIPS3_FPR15,
+ MIPS3_FPS15,
+ MIPS3_FPD15,
+ MIPS3_FPR16,
+ MIPS3_FPS16,
+ MIPS3_FPD16,
+ MIPS3_FPR17,
+ MIPS3_FPS17,
+ MIPS3_FPD17,
+ MIPS3_FPR18,
+ MIPS3_FPS18,
+ MIPS3_FPD18,
+ MIPS3_FPR19,
+ MIPS3_FPS19,
+ MIPS3_FPD19,
+ MIPS3_FPR20,
+ MIPS3_FPS20,
+ MIPS3_FPD20,
+ MIPS3_FPR21,
+ MIPS3_FPS21,
+ MIPS3_FPD21,
+ MIPS3_FPR22,
+ MIPS3_FPS22,
+ MIPS3_FPD22,
+ MIPS3_FPR23,
+ MIPS3_FPS23,
+ MIPS3_FPD23,
+ MIPS3_FPR24,
+ MIPS3_FPS24,
+ MIPS3_FPD24,
+ MIPS3_FPR25,
+ MIPS3_FPS25,
+ MIPS3_FPD25,
+ MIPS3_FPR26,
+ MIPS3_FPS26,
+ MIPS3_FPD26,
+ MIPS3_FPR27,
+ MIPS3_FPS27,
+ MIPS3_FPD27,
+ MIPS3_FPR28,
+ MIPS3_FPS28,
+ MIPS3_FPD28,
+ MIPS3_FPR29,
+ MIPS3_FPS29,
+ MIPS3_FPD29,
+ MIPS3_FPR30,
+ MIPS3_FPS30,
+ MIPS3_FPD30,
+ MIPS3_FPR31,
+ MIPS3_FPS31,
+ MIPS3_FPD31,
+ MIPS3_CCR1_31,
+ MIPS3_SR,
+ MIPS3_EPC,
+ MIPS3_CAUSE,
+ MIPS3_COUNT,
+ MIPS3_COMPARE,
+ MIPS3_INDEX,
+ MIPS3_RANDOM,
+ MIPS3_ENTRYHI,
+ MIPS3_ENTRYLO0,
+ MIPS3_ENTRYLO1,
+ MIPS3_PAGEMASK,
+ MIPS3_WIRED,
+ MIPS3_BADVADDR,
+ MIPS3_R0H,
+ MIPS3_R1H,
+ MIPS3_R2H,
+ MIPS3_R3H,
+ MIPS3_R4H,
+ MIPS3_R5H,
+ MIPS3_R6H,
+ MIPS3_R7H,
+ MIPS3_R8H,
+ MIPS3_R9H,
+ MIPS3_R10H,
+ MIPS3_R11H,
+ MIPS3_R12H,
+ MIPS3_R13H,
+ MIPS3_R14H,
+ MIPS3_R15H,
+ MIPS3_R16H,
+ MIPS3_R17H,
+ MIPS3_R18H,
+ MIPS3_R19H,
+ MIPS3_R20H,
+ MIPS3_R21H,
+ MIPS3_R22H,
+ MIPS3_R23H,
+ MIPS3_R24H,
+ MIPS3_R25H,
+ MIPS3_R26H,
+ MIPS3_R27H,
+ MIPS3_R28H,
+ MIPS3_R29H,
+ MIPS3_R30H,
+ MIPS3_R31H,
};
#define MIPS3_MAX_FASTRAM 3
#define MIPS3_MAX_HOTSPOTS 16
/***************************************************************************
- INTERRUPT CONSTANTS
+INTERRUPT CONSTANTS
***************************************************************************/
#define MIPS3_IRQ0 0 /* IRQ0 */
@@ -215,15 +246,14 @@ enum
/***************************************************************************
- STRUCTURES
+STRUCTURES
***************************************************************************/
/* MIPS3 TLB entry */
-struct mips3_tlb_entry
-{
- uint64_t page_mask;
- uint64_t entry_hi;
- uint64_t entry_lo[2];
+struct mips3_tlb_entry {
+ uint64_t page_mask;
+ uint64_t entry_hi;
+ uint64_t entry_lo[2];
};
#define MIPS3_MAX_TLB_ENTRIES 48
@@ -240,583 +270,616 @@ struct mips3_tlb_entry
class mips3_frontend;
-class mips3_device : public cpu_device, public device_vtlb_interface
-{
- friend class mips3_frontend;
+class mips3_device : public cpu_device, public device_vtlb_interface {
+ friend class mips3_frontend;
protected:
- /* MIPS flavors */
- enum mips3_flavor
- {
- /* MIPS III variants */
- MIPS3_TYPE_MIPS_III,
- MIPS3_TYPE_VR4300,
- MIPS3_TYPE_R4600,
- MIPS3_TYPE_R4650,
- MIPS3_TYPE_R4700,
- MIPS3_TYPE_TX4925,
-
- /* MIPS IV variants */
- MIPS3_TYPE_MIPS_IV,
- MIPS3_TYPE_R5000,
- MIPS3_TYPE_VR5500,
- MIPS3_TYPE_QED5271,
- MIPS3_TYPE_R5900,
- MIPS3_TYPE_RM7000
- };
+ /* MIPS flavors */
+ enum mips3_flavor {
+ /* MIPS III variants */
+ MIPS3_TYPE_MIPS_III,
+ MIPS3_TYPE_VR4300,
+ MIPS3_TYPE_R4600,
+ MIPS3_TYPE_R4650,
+ MIPS3_TYPE_R4700,
+ MIPS3_TYPE_TX4925,
+
+ /* MIPS IV variants */
+ MIPS3_TYPE_MIPS_IV,
+ MIPS3_TYPE_R5000,
+ MIPS3_TYPE_VR5500,
+ MIPS3_TYPE_QED5271,
+ MIPS3_TYPE_R5900,
+ MIPS3_TYPE_RM7000
+ };
public:
- // construction/destruction
- mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endiannes);
+ // construction/destruction
+ mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endiannes, uint32_t data_bits);
- void set_icache_size(size_t icache_size) { c_icache_size = icache_size; }
- void set_dcache_size(size_t dcache_size) { c_dcache_size = dcache_size; }
- void set_system_clock(uint32_t system_clock) { c_system_clock = system_clock; }
+ void set_icache_size(size_t icache_size) { c_icache_size = icache_size; }
+ void set_dcache_size(size_t dcache_size) { c_dcache_size = dcache_size; }
+ void set_system_clock(uint32_t system_clock) { c_system_clock = system_clock; }
- TIMER_CALLBACK_MEMBER(compare_int_callback);
+ TIMER_CALLBACK_MEMBER(compare_int_callback);
- void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
- void clear_fastram(uint32_t select_start);
- void mips3drc_set_options(uint32_t options);
- void mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles);
- void burn_cycles(int32_t cycles);
+ void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
+ void clear_fastram(uint32_t select_start);
+ void mips3drc_set_options(uint32_t options);
+ void mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles);
+ void burn_cycles(int32_t cycles);
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
-
- // device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 40; }
- virtual uint32_t execute_input_lines() const override { return 6; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
- virtual void execute_burn(int32_t cycles) override { m_totalcycles += cycles; }
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
-
- // device_state_interface overrides
- virtual void state_export(const device_state_entry &entry) override;
- virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- void invalid_instruction(uint32_t op);
-
-private:
- struct internal_mips3_state
- {
- /* core registers */
- uint32_t pc;
- int icount;
- uint64_t r[35];
-
- /* upper 64 bits of 128-bit GPRs (R5900 only) */
- uint64_t rh[35];
-
- /* COP registers */
- uint64_t cpr[3][32];
- uint64_t ccr[3][32];
- uint32_t llbit;
-
- /* VU0 registers (R5900 only) */
- float vfr[32][4];
- uint32_t vcr[32];
-
- uint32_t mode; /* current global mode */
-
- /* parameters for subroutines */
- uint64_t numcycles; /* return value from gettotalcycles */
- const char * format; /* format string for print_debug */
- uint32_t arg0; /* print_debug argument 1 */
- uint32_t arg1; /* print_debug argument 2 */
-
- uint64_t count_zero_time;
- uint32_t compare_armed;
- uint32_t jmpdest; /* destination jump target */
- };
-
- address_space_config m_program_config;
- mips3_flavor m_flavor;
-
- /* core state */
- internal_mips3_state *m_core;
-
- /* internal stuff */
- uint32_t m_ppc;
- uint32_t m_nextpc;
- uint32_t m_pcbase;
- uint8_t m_cf[4][8];
- bool m_delayslot;
- int m_op;
- int m_interrupt_cycles;
- uint32_t m_ll_value;
- uint64_t m_lld_value;
- uint32_t m_badcop_value;
-
- /* endian-dependent load/store */
- typedef void (mips3_device::*loadstore_func)(uint32_t op);
- loadstore_func m_lwl;
- loadstore_func m_lwr;
- loadstore_func m_swl;
- loadstore_func m_swr;
- loadstore_func m_ldl;
- loadstore_func m_ldr;
- loadstore_func m_sdl;
- loadstore_func m_sdr;
-
- address_space * m_program;
- std::function<u32 (offs_t)> m_pr32;
- std::function<const void * (offs_t)> m_prptr;
- uint32_t c_system_clock;
- uint32_t m_cpu_clock;
- emu_timer * m_compare_int_timer;
-
- /* derived info based on flavor */
- uint32_t m_pfnmask;
- uint8_t m_tlbentries;
-
- /* memory accesses */
- bool m_bigendian;
- uint32_t m_byte_xor;
- uint32_t m_word_xor;
- data_accessors m_memory;
-
- /* cache memory */
- size_t c_icache_size;
- size_t c_dcache_size;
-
- /* MMU */
- mips3_tlb_entry m_tlb[MIPS3_MAX_TLB_ENTRIES];
-
- /* fast RAM */
- uint32_t m_fastram_select;
- struct
- {
- offs_t start; /* start of the RAM block */
- offs_t end; /* end of the RAM block */
- bool readonly; /* true if read-only */
- void * base; /* base in memory where the RAM lives */
- uint8_t * offset_base8; /* base in memory where the RAM lives, 8-bit pointer, with the start offset pre-applied */
- uint16_t * offset_base16; /* base in memory where the RAM lives, 16-bit pointer, with the start offset pre-applied */
- uint32_t * offset_base32; /* base in memory where the RAM lives, 32-bit pointer, with the start offset pre-applied */
- } m_fastram[MIPS3_MAX_FASTRAM];
-
- uint32_t m_debugger_temp;
-
- /* core state */
- drc_cache m_cache; /* pointer to the DRC code cache */
- std::unique_ptr<drcuml_state> m_drcuml;/* DRC UML generator state */
- std::unique_ptr<mips3_frontend> m_drcfe; /* pointer to the DRC front-end state */
- uint32_t m_drcoptions; /* configurable DRC options */
-
- /* internal stuff */
- uint8_t m_cache_dirty; /* true if we need to flush the cache */
-
- /* tables */
- uint8_t m_fpmode[4]; /* FPU mode table */
-
- /* register mappings */
- uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
- uml::parameter m_regmaplo[34]; /* parameter to register mappings for all 32 integer registers */
-
- /* subroutines */
- uml::code_handle * m_entry; /* entry point */
- uml::code_handle * m_nocode; /* nocode exception handler */
- uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */
- uml::code_handle * m_tlb_mismatch; /* tlb mismatch handler */
- uml::code_handle * m_read8[3]; /* read byte */
- uml::code_handle * m_write8[3]; /* write byte */
- uml::code_handle * m_read16[3]; /* read half */
- uml::code_handle * m_write16[3]; /* write half */
- uml::code_handle * m_read32[3]; /* read word */
- uml::code_handle * m_read32mask[3]; /* read word masked */
- uml::code_handle * m_write32[3]; /* write word */
- uml::code_handle * m_write32mask[3]; /* write word masked */
- uml::code_handle * m_read64[3]; /* read double */
- uml::code_handle * m_read64mask[3]; /* read double masked */
- uml::code_handle * m_write64[3]; /* write double */
- uml::code_handle * m_write64mask[3]; /* write double masked */
- uml::code_handle * m_exception[18/*EXCEPTION_COUNT*/]; /* array of exception handlers */
- uml::code_handle * m_exception_norecover[18/*EXCEPTION_COUNT*/]; /* array of no-recover exception handlers */
-
- /* hotspots */
- uint32_t m_hotspot_select;
- struct
- {
- offs_t pc; /* PC to consider */
- uint32_t opcode; /* required opcode at that PC */
- uint32_t cycles; /* number of cycles to eat when hit */
- } m_hotspot[MIPS3_MAX_HOTSPOTS];
- bool m_isdrc;
-
-
- void generate_exception(int exception, int backup);
- void generate_tlb_exception(int exception, offs_t address);
- void check_irqs();
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_stop() override;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const override { return 1; }
+ virtual uint32_t execute_max_cycles() const override { return 40; }
+ virtual uint32_t execute_input_lines() const override { return 6; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+ virtual void execute_burn(int32_t cycles) override { m_totalcycles += cycles; }
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+
+ // device_state_interface overrides
+ virtual void state_export(const device_state_entry &entry) override;
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ void invalid_instruction(uint32_t op);
+
+ virtual bool RBYTE(offs_t address, uint32_t *result);
+ virtual bool RHALF(offs_t address, uint32_t *result);
+ virtual bool RWORD(offs_t address, uint32_t *result);
+ virtual bool RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask);
+ virtual bool RDOUBLE(offs_t address, uint64_t *result);
+ virtual bool RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask);
+ virtual void WBYTE(offs_t address, uint8_t data);
+ virtual void WHALF(offs_t address, uint16_t data);
+ virtual void WWORD(offs_t address, uint32_t data);
+ virtual void WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask);
+ virtual void WDOUBLE(offs_t address, uint64_t data);
+ virtual void WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask);
+
+ struct internal_mips3_state {
+ /* core registers */
+ uint32_t pc;
+ int icount;
+ uint64_t r[35];
+ uint32_t sa;
+
+ /* upper 64 bits of 128-bit GPRs (R5900 only) */
+ uint64_t rh[35];
+
+ /* COP registers */
+ uint64_t cpr[3][32];
+ uint64_t ccr[3][32];
+ uint32_t llbit;
+ float acc;
+
+ /* VU0 registers (R5900 only) */
+ float vfr[32][4];
+ uint32_t vcr[32];
+ float vumem[0x1000];
+ float* vfmem;
+ uint32_t* vimem;
+
+ uint32_t mode; /* current global mode */
+
+ /* parameters for subroutines */
+ uint64_t numcycles; /* return value from gettotalcycles */
+ const char * format; /* format string for print_debug */
+ uint32_t arg0; /* print_debug argument 1 */
+ uint32_t arg1; /* print_debug argument 2 */
+
+ uint64_t count_zero_time;
+ uint32_t compare_armed;
+ uint32_t jmpdest; /* destination jump target */
+ };
+
+ /* core state */
+ internal_mips3_state *m_core;
+
+ address_space_config m_program_config;
+ mips3_flavor m_flavor;
+
+ /* internal stuff */
+ uint32_t m_ppc;
+ uint32_t m_nextpc;
+ uint32_t m_pcbase;
+ uint8_t m_cf[4][8];
+ bool m_delayslot;
+ int m_op;
+ int m_interrupt_cycles;
+ uint32_t m_ll_value;
+ uint64_t m_lld_value;
+ uint32_t m_badcop_value;
+
+ /* endian-dependent load/store */
+ typedef void (mips3_device::*loadstore_func)(uint32_t op);
+ loadstore_func m_lwl;
+ loadstore_func m_lwr;
+ loadstore_func m_swl;
+ loadstore_func m_swr;
+ loadstore_func m_ldl;
+ loadstore_func m_ldr;
+ loadstore_func m_sdl;
+ loadstore_func m_sdr;
+
+ address_space * m_program;
+ uint32_t m_data_bits;
+ std::function<u32(offs_t)> m_pr32;
+ std::function<const void * (offs_t)> m_prptr;
+ uint32_t c_system_clock;
+ uint32_t m_cpu_clock;
+ emu_timer * m_compare_int_timer;
+
+ /* derived info based on flavor */
+ uint32_t m_pfnmask;
+ uint8_t m_tlbentries;
+
+ /* memory accesses */
+ bool m_bigendian;
+ uint32_t m_byte_xor;
+ uint32_t m_word_xor;
+ data_accessors m_memory;
+
+ /* cache memory */
+ size_t c_icache_size;
+ size_t c_dcache_size;
+
+ /* MMU */
+ mips3_tlb_entry m_tlb[MIPS3_MAX_TLB_ENTRIES];
+
+ /* fast RAM */
+ uint32_t m_fastram_select;
+ struct {
+ offs_t start; /* start of the RAM block */
+ offs_t end; /* end of the RAM block */
+ bool readonly; /* true if read-only */
+ void * base; /* base in memory where the RAM lives */
+ uint8_t * offset_base8; /* base in memory where the RAM lives, 8-bit pointer, with the start offset pre-applied */
+ uint16_t * offset_base16; /* base in memory where the RAM lives, 16-bit pointer, with the start offset pre-applied */
+ uint32_t * offset_base32; /* base in memory where the RAM lives, 32-bit pointer, with the start offset pre-applied */
+ } m_fastram[MIPS3_MAX_FASTRAM];
+
+ uint32_t m_debugger_temp;
+
+ /* core state */
+ drc_cache m_cache; /* pointer to the DRC code cache */
+ std::unique_ptr<drcuml_state> m_drcuml;/* DRC UML generator state */
+ std::unique_ptr<mips3_frontend> m_drcfe; /* pointer to the DRC front-end state */
+ uint32_t m_drcoptions; /* configurable DRC options */
+
+ /* internal stuff */
+ uint8_t m_cache_dirty; /* true if we need to flush the cache */
+
+ /* tables */
+ uint8_t m_fpmode[4]; /* FPU mode table */
+
+ /* register mappings */
+ uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
+ uml::parameter m_regmaplo[34]; /* parameter to register mappings for all 32 integer registers */
+
+ /* subroutines */
+ uml::code_handle * m_entry; /* entry point */
+ uml::code_handle * m_nocode; /* nocode exception handler */
+ uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */
+ uml::code_handle * m_tlb_mismatch; /* tlb mismatch handler */
+ uml::code_handle * m_read8[3]; /* read byte */
+ uml::code_handle * m_write8[3]; /* write byte */
+ uml::code_handle * m_read16[3]; /* read half */
+ uml::code_handle * m_write16[3]; /* write half */
+ uml::code_handle * m_read32[3]; /* read word */
+ uml::code_handle * m_read32mask[3]; /* read word masked */
+ uml::code_handle * m_write32[3]; /* write word */
+ uml::code_handle * m_write32mask[3]; /* write word masked */
+ uml::code_handle * m_read64[3]; /* read double */
+ uml::code_handle * m_read64mask[3]; /* read double masked */
+ uml::code_handle * m_write64[3]; /* write double */
+ uml::code_handle * m_write64mask[3]; /* write double masked */
+ uml::code_handle * m_exception[18/*EXCEPTION_COUNT*/]; /* array of exception handlers */
+ uml::code_handle * m_exception_norecover[18/*EXCEPTION_COUNT*/]; /* array of no-recover exception handlers */
+
+ /* hotspots */
+ uint32_t m_hotspot_select;
+ struct {
+ offs_t pc; /* PC to consider */
+ uint32_t opcode; /* required opcode at that PC */
+ uint32_t cycles; /* number of cycles to eat when hit */
+ } m_hotspot[MIPS3_MAX_HOTSPOTS];
+ bool m_isdrc;
+
+
+ void generate_exception(int exception, int backup);
+ void generate_tlb_exception(int exception, offs_t address);
+ void check_irqs();
public:
- void mips3com_update_cycle_counting();
- void mips3com_asid_changed();
- void mips3com_tlbr();
- void mips3com_tlbwi();
- void mips3com_tlbwr();
- void mips3com_tlbp();
+ void mips3com_update_cycle_counting();
+ void mips3com_asid_changed();
+ void mips3com_tlbr();
+ void mips3com_tlbwi();
+ void mips3com_tlbwr();
+ void mips3com_tlbp();
private:
- uint32_t compute_config_register();
- uint32_t compute_prid_register();
-
- void tlb_map_entry(int tlbindex);
- void tlb_write_common(int tlbindex);
-
- bool RBYTE(offs_t address, uint32_t *result);
- bool RHALF(offs_t address, uint32_t *result);
- bool RWORD(offs_t address, uint32_t *result);
- bool RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask);
- bool RDOUBLE(offs_t address, uint64_t *result);
- bool RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask);
- void WBYTE(offs_t address, uint8_t data);
- void WHALF(offs_t address, uint16_t data);
- void WWORD(offs_t address, uint32_t data);
- void WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask);
- void WDOUBLE(offs_t address, uint64_t data);
- void WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask);
-
- uint64_t get_cop0_reg(int idx);
- void set_cop0_reg(int idx, uint64_t val);
- uint64_t get_cop0_creg(int idx);
- void set_cop0_creg(int idx, uint64_t val);
- void handle_cop0(uint32_t op);
-
- uint32_t get_cop1_reg32(int idx);
- uint64_t get_cop1_reg64(int idx);
- void set_cop1_reg32(int idx, uint32_t val);
- void set_cop1_reg64(int idx, uint64_t val);
- uint64_t get_cop1_creg(int idx);
- void set_cop1_creg(int idx, uint64_t val);
- void handle_cop1_fr0(uint32_t op);
- void handle_cop1_fr1(uint32_t op);
- void handle_cop1x_fr0(uint32_t op);
- void handle_cop1x_fr1(uint32_t op);
-
- uint64_t get_cop2_reg(int idx);
- void set_cop2_reg(int idx, uint64_t val);
- uint64_t get_cop2_creg(int idx);
- void set_cop2_creg(int idx, uint64_t val);
- void handle_cop2(uint32_t op);
-
- void handle_special(uint32_t op);
- void handle_regimm(uint32_t op);
- virtual void handle_extra_special(uint32_t op);
- virtual void handle_extra_regimm(uint32_t op);
- virtual void handle_extra_cop2(uint32_t op);
- virtual void handle_idt(uint32_t op);
-
- void lwl_be(uint32_t op);
- void lwr_be(uint32_t op);
- void ldl_be(uint32_t op);
- void ldr_be(uint32_t op);
- void swl_be(uint32_t op);
- void swr_be(uint32_t op);
- void sdl_be(uint32_t op);
- void sdr_be(uint32_t op);
- void lwl_le(uint32_t op);
- void lwr_le(uint32_t op);
- void ldl_le(uint32_t op);
- void ldr_le(uint32_t op);
- void swl_le(uint32_t op);
- void swr_le(uint32_t op);
- void sdl_le(uint32_t op);
- void sdr_le(uint32_t op);
- void load_fast_iregs(drcuml_block &block);
- void save_fast_iregs(drcuml_block &block);
- void code_flush_cache();
- void code_compile_block(uint8_t mode, offs_t pc);
+ uint32_t compute_config_register();
+ uint32_t compute_prid_register();
+
+ void tlb_map_entry(int tlbindex);
+ void tlb_write_common(int tlbindex);
+
+ uint64_t get_cop0_reg(int idx);
+ void set_cop0_reg(int idx, uint64_t val);
+ uint64_t get_cop0_creg(int idx);
+ void set_cop0_creg(int idx, uint64_t val);
+ void handle_cop0(uint32_t op);
+
+ uint32_t get_cop1_reg32(int idx);
+ uint64_t get_cop1_reg64(int idx);
+ void set_cop1_reg32(int idx, uint32_t val);
+ void set_cop1_reg64(int idx, uint64_t val);
+ uint64_t get_cop1_creg(int idx);
+ void set_cop1_creg(int idx, uint64_t val);
+ void handle_cop1_fr0(uint32_t op);
+ void handle_cop1_fr1(uint32_t op);
+ void handle_cop1x_fr0(uint32_t op);
+ void handle_cop1x_fr1(uint32_t op);
+
+ virtual uint64_t get_cop2_reg(int idx);
+ virtual void set_cop2_reg(int idx, uint64_t val);
+ virtual uint64_t get_cop2_creg(int idx);
+ virtual void set_cop2_creg(int idx, uint64_t val);
+ void handle_cop2(uint32_t op);
+
+ void handle_special(uint32_t op);
+ void handle_regimm(uint32_t op);
+ virtual void handle_extra_base(uint32_t op);
+ virtual void handle_extra_special(uint32_t op);
+ virtual void handle_extra_regimm(uint32_t op);
+ virtual void handle_extra_cop2(uint32_t op);
+ virtual void handle_idt(uint32_t op);
+ virtual void handle_ldc2(uint32_t op);
+ virtual void handle_sdc2(uint32_t op);
+ virtual void handle_dmfc2(uint32_t op);
+ virtual void handle_dmtc2(uint32_t op);
+
+ void lwl_be(uint32_t op);
+ void lwr_be(uint32_t op);
+ void ldl_be(uint32_t op);
+ void ldr_be(uint32_t op);
+ void swl_be(uint32_t op);
+ void swr_be(uint32_t op);
+ void sdl_be(uint32_t op);
+ void sdr_be(uint32_t op);
+ void lwl_le(uint32_t op);
+ void lwr_le(uint32_t op);
+ void ldl_le(uint32_t op);
+ void ldr_le(uint32_t op);
+ void swl_le(uint32_t op);
+ void swr_le(uint32_t op);
+ void sdl_le(uint32_t op);
+ void sdr_le(uint32_t op);
+ void load_fast_iregs(drcuml_block &block);
+ void save_fast_iregs(drcuml_block &block);
+ void code_flush_cache();
+ void code_compile_block(uint8_t mode, offs_t pc);
public:
- void func_get_cycles();
- void func_printf_exception();
- void func_printf_debug();
- void func_printf_probe();
- void func_unimplemented();
+ void func_get_cycles();
+ void func_printf_exception();
+ void func_printf_debug();
+ void func_printf_probe();
+ void func_unimplemented();
private:
- /* internal compiler state */
- struct compiler_state
- {
- compiler_state &operator=(compiler_state &) = delete;
-
- uint32_t cycles; /* accumulated cycles */
- uint8_t checkints; /* need to check interrupts before next instruction */
- uint8_t checksoftints; /* need to check software interrupts before next instruction */
- uml::code_label labelnum; /* index for local labels */
- };
-
- void static_generate_entry_point();
- void static_generate_nocode_handler();
- void static_generate_out_of_cycles();
- void static_generate_tlb_mismatch();
- void static_generate_exception(uint8_t exception, int recover, const char *name);
- void static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle *&handleptr);
-
- void generate_update_mode(drcuml_block &block);
- void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception);
- void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
- void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg);
-
- bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_idt(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
-
- bool generate_set_cop0_reg(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t reg);
- bool generate_get_cop0_reg(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t reg);
- bool generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_cop1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_cop1x(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
-
- void check_cop0_access(drcuml_block &block);
- void check_cop1_access(drcuml_block &block);
- void generate_badcop(drcuml_block &block, const int cop);
-
- void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
- const char *log_desc_flags_to_string(uint32_t flags);
- void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist);
- void log_opcode_desc(const opcode_desc *desclist, int indent);
+ /* internal compiler state */
+ struct compiler_state {
+ compiler_state &operator=(compiler_state &) = delete;
+
+ uint32_t cycles; /* accumulated cycles */
+ uint8_t checkints; /* need to check interrupts before next instruction */
+ uint8_t checksoftints; /* need to check software interrupts before next instruction */
+ uml::code_label labelnum; /* index for local labels */
+ };
+
+ void static_generate_entry_point();
+ void static_generate_nocode_handler();
+ void static_generate_out_of_cycles();
+ void static_generate_tlb_mismatch();
+ void static_generate_exception(uint8_t exception, int recover, const char *name);
+ void static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle *&handleptr);
+
+ void generate_update_mode(drcuml_block &block);
+ void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception);
+ void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+ void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ void generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg);
+
+ bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ bool generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ bool generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ bool generate_idt(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+
+ bool generate_set_cop0_reg(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t reg);
+ bool generate_get_cop0_reg(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t reg);
+ bool generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ bool generate_cop1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ bool generate_cop1x(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+
+ void check_cop0_access(drcuml_block &block);
+ void check_cop1_access(drcuml_block &block);
+ void generate_badcop(drcuml_block &block, const int cop);
+
+ void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
+ const char *log_desc_flags_to_string(uint32_t flags);
+ void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist);
+ void log_opcode_desc(const opcode_desc *desclist, int indent);
};
-class vr4300be_device : public mips3_device
-{
+class vr4300be_device : public mips3_device {
public:
- // construction/destruction
- vr4300be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR4300BE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ vr4300be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR4300BE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class vr4300le_device : public mips3_device
-{
+class vr4300le_device : public mips3_device {
public:
- // construction/destruction
- vr4300le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR4300LE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ vr4300le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR4300LE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class vr4310be_device : public mips3_device
-{
+class vr4310be_device : public mips3_device {
public:
- // construction/destruction
- vr4310be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR4310BE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ vr4310be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR4310BE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class vr4310le_device : public mips3_device
-{
+class vr4310le_device : public mips3_device {
public:
- // construction/destruction
- vr4310le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR4310LE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ vr4310le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR4310LE, tag, owner, clock, MIPS3_TYPE_VR4300, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class r4600be_device : public mips3_device
-{
+class r4600be_device : public mips3_device {
public:
- // construction/destruction
- r4600be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4600BE, tag, owner, clock, MIPS3_TYPE_R4600, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ r4600be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4600BE, tag, owner, clock, MIPS3_TYPE_R4600, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class r4600le_device : public mips3_device
-{
+class r4600le_device : public mips3_device {
public:
- // construction/destruction
- r4600le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4600LE, tag, owner, clock, MIPS3_TYPE_R4600, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ r4600le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4600LE, tag, owner, clock, MIPS3_TYPE_R4600, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class r4650be_device : public mips3_device
-{
+class r4650be_device : public mips3_device {
public:
- // construction/destruction
- r4650be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4650BE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ r4650be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4650BE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class r4650le_device : public mips3_device
-{
+class r4650le_device : public mips3_device {
public:
- // construction/destruction
- r4650le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4650LE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ r4650le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4650LE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class r4700be_device : public mips3_device
-{
+class r4700be_device : public mips3_device {
public:
- // construction/destruction
- r4700be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4700BE, tag, owner, clock, MIPS3_TYPE_R4700, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ r4700be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4700BE, tag, owner, clock, MIPS3_TYPE_R4700, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class r4700le_device : public mips3_device
-{
+class r4700le_device : public mips3_device {
public:
- // construction/destruction
- r4700le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R4700LE, tag, owner, clock, MIPS3_TYPE_R4700, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ r4700le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R4700LE, tag, owner, clock, MIPS3_TYPE_R4700, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class tx4925be_device : public mips3_device
-{
+class tx4925be_device : public mips3_device {
public:
- // construction/destruction
- tx4925be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, TX4925BE, tag, owner, clock, MIPS3_TYPE_TX4925, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ tx4925be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, TX4925BE, tag, owner, clock, MIPS3_TYPE_TX4925, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class tx4925le_device : public mips3_device
-{
+class tx4925le_device : public mips3_device {
public:
- // construction/destruction
- tx4925le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, TX4925LE, tag, owner, clock, MIPS3_TYPE_TX4925, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ tx4925le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, TX4925LE, tag, owner, clock, MIPS3_TYPE_TX4925, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class r5000be_device : public mips3_device
-{
+class r5000be_device : public mips3_device {
public:
- // construction/destruction
- r5000be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R5000BE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ r5000be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R5000BE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class r5000le_device : public mips3_device
-{
+class r5000le_device : public mips3_device {
public:
- // construction/destruction
- r5000le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R5000LE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ r5000le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R5000LE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class vr5500be_device : public mips3_device
-{
+class vr5500be_device : public mips3_device {
public:
- // construction/destruction
- vr5500be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR5500BE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ vr5500be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR5500BE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_BIG, 32) {
+ }
};
-class vr5500le_device : public mips3_device
-{
+class vr5500le_device : public mips3_device {
public:
- // construction/destruction
- vr5500le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, VR5500LE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ vr5500le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, VR5500LE, tag, owner, clock, MIPS3_TYPE_R5000, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class r5900le_device : public mips3_device
-{
+class r5900le_device : public mips3_device {
public:
- // construction/destruction
- r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE, 64) {
+ }
protected:
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+ virtual void device_start() override;
- void handle_extra_special(uint32_t op) override;
- void handle_extra_regimm(uint32_t op) override;
- void handle_extra_cop2(uint32_t op) override;
- void handle_idt(uint32_t op) override;
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ bool RBYTE(offs_t address, uint32_t *result) override;
+ bool RHALF(offs_t address, uint32_t *result) override;
+ bool RWORD(offs_t address, uint32_t *result) override;
+ bool RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) override;
+ bool RDOUBLE(offs_t address, uint64_t *result) override;
+ bool RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) override;
+ void WBYTE(offs_t address, uint8_t data) override;
+ void WHALF(offs_t address, uint16_t data) override;
+ void WWORD(offs_t address, uint32_t data) override;
+ void WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) override;
+ void WDOUBLE(offs_t address, uint64_t data) override;
+ void WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) override;
+
+ bool RQUAD(offs_t address, uint64_t *result_hi, uint64_t *result_lo);
+ void WQUAD(offs_t address, uint64_t data_hi, uint64_t data_lo);
+
+ uint64_t get_cop2_reg(int idx) override;
+ void set_cop2_reg(int idx, uint64_t val) override;
+ uint64_t get_cop2_creg(int idx) override;
+ void set_cop2_creg(int idx, uint64_t val) override;
+
+ void handle_extra_base(uint32_t op) override;
+ void handle_extra_special(uint32_t op) override;
+ void handle_extra_regimm(uint32_t op) override;
+ void handle_extra_cop2(uint32_t op) override;
+ void handle_idt(uint32_t op) override;
+ void handle_mmi0(uint32_t op);
+ void handle_mmi1(uint32_t op);
+ void handle_mmi2(uint32_t op);
+ void handle_mmi3(uint32_t op);
+ void handle_ldc2(uint32_t op) override;
+ void handle_sdc2(uint32_t op) override;
+ void handle_dmfc2(uint32_t op) override;
+ void handle_dmtc2(uint32_t op) override;
};
-class qed5271be_device : public mips3_device
-{
+class qed5271be_device : public mips3_device {
public:
- // construction/destruction
- qed5271be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, QED5271BE, tag, owner, clock, MIPS3_TYPE_QED5271, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ qed5271be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, QED5271BE, tag, owner, clock, MIPS3_TYPE_QED5271, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class qed5271le_device : public mips3_device
-{
+class qed5271le_device : public mips3_device {
public:
- // construction/destruction
- qed5271le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, QED5271LE, tag, owner, clock, MIPS3_TYPE_QED5271, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ qed5271le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, QED5271LE, tag, owner, clock, MIPS3_TYPE_QED5271, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class rm7000be_device : public mips3_device
-{
+class rm7000be_device : public mips3_device {
public:
- // construction/destruction
- rm7000be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, RM7000BE, tag, owner, clock, MIPS3_TYPE_RM7000, ENDIANNESS_BIG)
- { }
+ // construction/destruction
+ rm7000be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, RM7000BE, tag, owner, clock, MIPS3_TYPE_RM7000, ENDIANNESS_BIG, 32) // checkme
+ {
+ }
};
-class rm7000le_device : public mips3_device
-{
+class rm7000le_device : public mips3_device {
public:
- // construction/destruction
- rm7000le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mips3_device(mconfig, RM7000LE, tag, owner, clock, MIPS3_TYPE_RM7000, ENDIANNESS_LITTLE)
- { }
+ // construction/destruction
+ rm7000le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mips3_device(mconfig, RM7000LE, tag, owner, clock, MIPS3_TYPE_RM7000, ENDIANNESS_LITTLE, 32) // checkme
+ {
+ }
};
-class mips3_frontend : public drc_frontend
-{
+class mips3_frontend : public drc_frontend {
public:
- // construction/destruction
- mips3_frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
+ // construction/destruction
+ mips3_frontend(mips3_device *mips3, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
protected:
- // required overrides
- virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
private:
- // internal helpers
- bool describe_special(uint32_t op, opcode_desc &desc);
- bool describe_regimm(uint32_t op, opcode_desc &desc);
- bool describe_idt(uint32_t op, opcode_desc &desc);
- bool describe_cop0(uint32_t op, opcode_desc &desc);
- bool describe_cop1(uint32_t op, opcode_desc &desc);
- bool describe_cop1x(uint32_t op, opcode_desc &desc);
- bool describe_cop2(uint32_t op, opcode_desc &desc);
-
- // internal state
- mips3_device *m_mips3;
+ // internal helpers
+ bool describe_special(uint32_t op, opcode_desc &desc);
+ bool describe_regimm(uint32_t op, opcode_desc &desc);
+ bool describe_idt(uint32_t op, opcode_desc &desc);
+ bool describe_cop0(uint32_t op, opcode_desc &desc);
+ bool describe_cop1(uint32_t op, opcode_desc &desc);
+ bool describe_cop1x(uint32_t op, opcode_desc &desc);
+ bool describe_cop2(uint32_t op, opcode_desc &desc);
+
+ // internal state
+ mips3_device *m_mips3;
};
/***************************************************************************
- COMPILER-SPECIFIC OPTIONS
+COMPILER-SPECIFIC OPTIONS
***************************************************************************/
/* fix me -- how do we make this work?? */
diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp
index 9edd05f8b67..8b8accf8c4c 100644
--- a/src/devices/cpu/mips/mips3com.cpp
+++ b/src/devices/cpu/mips/mips3com.cpp
@@ -366,7 +366,11 @@ void mips3_device::tlb_map_entry(int tlbindex)
}
/* get the number of pages from the page mask */
- count = ((entry->page_mask >> 13) & 0x00fff) + 1;
+ /* R5900: if the S bit is set in EntryLo, it is the scratchpad, and is always 4 pages. */
+ if ((entry->entry_lo[0] & 0x80000000) && m_flavor == MIPS3_TYPE_R5900)
+ count = 4;
+ else
+ count = ((entry->page_mask >> 13) & 0x00fff) + 1;
/* loop over both the even and odd pages */
for (which = 0; which < 2; which++)
diff --git a/src/devices/cpu/mips/mips3com.h b/src/devices/cpu/mips/mips3com.h
index befde0cf60c..9365deff603 100644
--- a/src/devices/cpu/mips/mips3com.h
+++ b/src/devices/cpu/mips/mips3com.h
@@ -72,8 +72,8 @@
#define MIPS3_MAX_PADDR_SHIFT 32
/* cycle parameters */
-#define MIPS3_COUNT_READ_CYCLES 250
-#define MIPS3_CAUSE_READ_CYCLES 250
+#define MIPS3_COUNT_READ_CYCLES 1
+#define MIPS3_CAUSE_READ_CYCLES 1
/* TLB bits */
#define TLB_GLOBAL 0x01
diff --git a/src/devices/cpu/mips/mips3dsm.cpp b/src/devices/cpu/mips/mips3dsm.cpp
index 0ee0bd36058..c93e8166344 100644
--- a/src/devices/cpu/mips/mips3dsm.cpp
+++ b/src/devices/cpu/mips/mips3dsm.cpp
@@ -799,11 +799,13 @@ uint32_t ee_disassembler::dasm_extra_base(uint32_t pc, uint32_t op, std::ostream
uint32_t ee_disassembler::dasm_extra_special(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rs = (op >> 21) & 31;
+ const int rd = (op >> 11) & 31;
switch (op & 63)
{
- case 0x29: util::stream_format(stream, "mtsa %s", reg[rs]); break;
- default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
+ case 0x28: util::stream_format(stream, "mfsa %s", reg[rd]); break;
+ case 0x29: util::stream_format(stream, "mtsa %s", reg[rs]); break;
+ default: util::stream_format(stream, "dc.l $%08x [invalid]", op); break;
}
return 0;
}
diff --git a/src/devices/cpu/mips/r3000.cpp b/src/devices/cpu/mips/r3000.cpp
index 1cf74b4bff4..4a15b1f60a6 100644
--- a/src/devices/cpu/mips/r3000.cpp
+++ b/src/devices/cpu/mips/r3000.cpp
@@ -114,11 +114,12 @@
// DEVICE INTERFACE
//**************************************************************************
-DEFINE_DEVICE_TYPE(R3041, r3041_device, "r3041", "MIPS R3041")
-DEFINE_DEVICE_TYPE(R3051, r3051_device, "r3051", "MIPS R3051")
-DEFINE_DEVICE_TYPE(R3052, r3052_device, "r3052", "MIPS R3052")
-DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "MIPS R3071")
-DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "MIPS R3081")
+DEFINE_DEVICE_TYPE(R3041, r3041_device, "r3041", "MIPS R3041")
+DEFINE_DEVICE_TYPE(R3051, r3051_device, "r3051", "MIPS R3051")
+DEFINE_DEVICE_TYPE(R3052, r3052_device, "r3052", "MIPS R3052")
+DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "MIPS R3071")
+DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "MIPS R3081")
+DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 IOP")
//-------------------------------------------------
@@ -206,6 +207,14 @@ r3081_device::r3081_device(const machine_config &mconfig, const char *tag, devic
//-------------------------------------------------
+// iop_device - constructor
+//-------------------------------------------------
+
+iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : r3000_device(mconfig, SONYPS2_IOP, tag, owner, clock, CHIP_TYPE_IOP) { }
+
+
+//-------------------------------------------------
// device_start - start up the device
//-------------------------------------------------
@@ -262,6 +271,12 @@ void r3000_device::device_start()
m_hasfpu = true;
break;
}
+ case CHIP_TYPE_IOP:
+ {
+ m_icache_size = 4096;
+ m_dcache_size = 1024;
+ break;
+ }
}
// allocate cache memory
@@ -398,6 +413,12 @@ void r3000_device::device_reset()
m_cpr[0][COP0_Status] = 0x0000;
}
+void iop_device::device_reset()
+{
+ r3000_device::device_reset();
+ m_cpr[0][COP0_PRId] = 0x2;
+}
+
//-------------------------------------------------
// memory_space_config - return the configuration
diff --git a/src/devices/cpu/mips/r3000.h b/src/devices/cpu/mips/r3000.h
index 0abea62316d..64537788aa5 100644
--- a/src/devices/cpu/mips/r3000.h
+++ b/src/devices/cpu/mips/r3000.h
@@ -87,7 +87,8 @@ protected:
CHIP_TYPE_R3051,
CHIP_TYPE_R3052,
CHIP_TYPE_R3071,
- CHIP_TYPE_R3081
+ CHIP_TYPE_R3081,
+ CHIP_TYPE_IOP
};
r3000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, chip_type chiptype);
@@ -291,12 +292,25 @@ public:
};
+// ======================> iop_device
+
+class iop_device : public r3000_device
+{
+public:
+ iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_reset() override;
+};
+
+
// device type definition
-DECLARE_DEVICE_TYPE(R3041, r3041_device)
-DECLARE_DEVICE_TYPE(R3051, r3051_device)
-DECLARE_DEVICE_TYPE(R3052, r3052_device)
-DECLARE_DEVICE_TYPE(R3071, r3071_device)
-DECLARE_DEVICE_TYPE(R3081, r3081_device)
+DECLARE_DEVICE_TYPE(R3041, r3041_device)
+DECLARE_DEVICE_TYPE(R3051, r3051_device)
+DECLARE_DEVICE_TYPE(R3052, r3052_device)
+DECLARE_DEVICE_TYPE(R3071, r3071_device)
+DECLARE_DEVICE_TYPE(R3081, r3081_device)
+DECLARE_DEVICE_TYPE(SONYPS2_IOP, iop_device)
#endif // MAME_CPU_MIPS_R3000_H
diff --git a/src/devices/machine/wd33c93.cpp b/src/devices/machine/wd33c93.cpp
index 401e2666765..ec9c8017434 100644
--- a/src/devices/machine/wd33c93.cpp
+++ b/src/devices/machine/wd33c93.cpp
@@ -16,7 +16,7 @@
#include "emu.h"
#include "wd33c93.h"
-//#define VERBOSE 1
+#define VERBOSE 1
#include "logmacro.h"
diff --git a/src/emu/divtlb.cpp b/src/emu/divtlb.cpp
index 0689bb9c68a..d6cc8b34e21 100644
--- a/src/emu/divtlb.cpp
+++ b/src/emu/divtlb.cpp
@@ -91,9 +91,11 @@ void device_vtlb_interface::interface_pre_start()
memset(&m_live[0], 0, m_live.size()*sizeof(m_live[0]));
// allocate the lookup table
- m_table.resize((size_t) 1 << (m_addrwidth - m_pageshift));
- memset(&m_table[0], 0, m_table.size()*sizeof(m_table[0]));
- // pointer to first element for quick access
+ m_table.resize((size_t)1 << (m_addrwidth - m_pageshift));
+ memset(&m_table[0], 0, m_table.size() * sizeof(m_table[0]));
+ m_refcnt.resize((size_t)1 << (m_addrwidth - m_pageshift));
+ memset(&m_refcnt[0], 0, m_refcnt.size() * sizeof(m_refcnt[0]));
+ // pointer to first element for quick access
m_table_base = &m_table[0];
// allocate the fixed page count array
@@ -114,6 +116,7 @@ void device_vtlb_interface::interface_post_start()
{
device().save_item(NAME(m_live));
device().save_item(NAME(m_table));
+ device().save_item(NAME(m_refcnt));
if (m_fixed > 0)
device().save_item(NAME(m_fixedpages));
}
@@ -177,8 +180,9 @@ bool device_vtlb_interface::vtlb_fill(offs_t address, int intention)
int liveindex = m_dynindex++ % m_dynamic;
// if an entry already exists at this index, free it
- if (m_live[liveindex] != 0)
+ if (m_live[liveindex] != 0 && m_refcnt[m_live[liveindex] - 1] <= 1)
m_table[m_live[liveindex] - 1] = 0;
+ m_refcnt[m_live[liveindex] - 1]--;
// claim this new entry
m_live[liveindex] = tableindex + 1;
@@ -230,14 +234,19 @@ void device_vtlb_interface::vtlb_load(int entrynum, int numpages, offs_t address
// if an entry already exists at this index, free it
if (m_live[liveindex] != 0)
{
- int pagecount = m_fixedpages[entrynum];
int oldtableindex = m_live[liveindex] - 1;
- for (pagenum = 0; pagenum < pagecount; pagenum++)
- m_table[oldtableindex + pagenum] = 0;
+ m_refcnt[oldtableindex]--;
+ if (m_refcnt[oldtableindex] == 0) {
+ int pagecount = m_fixedpages[entrynum];
+ for (pagenum = 0; pagenum < pagecount; pagenum++) {
+ m_table[oldtableindex + pagenum] = 0;
+ }
+ }
}
// claim this new entry
m_live[liveindex] = tableindex + 1;
+ m_refcnt[tableindex]++;
// store the raw value, making sure the "fixed" flag is set
value |= VTLB_FLAG_FIXED;
diff --git a/src/emu/divtlb.h b/src/emu/divtlb.h
index 3acfec4f215..03ee4d1ed84 100644
--- a/src/emu/divtlb.h
+++ b/src/emu/divtlb.h
@@ -83,6 +83,7 @@ private:
std::vector<offs_t> m_live; // array of live entries by table index
std::vector<int> m_fixedpages; // number of pages each fixed entry covers
std::vector<vtlb_entry> m_table; // table of entries by address
+ std::vector<offs_t> m_refcnt; // table of entry reference counts by address
vtlb_entry *m_table_base; // pointer to m_table[0]
};
diff --git a/src/mame/drivers/ps2sony.cpp b/src/mame/drivers/ps2sony.cpp
index e13fcffeb0d..4b36effbf38 100644
--- a/src/mame/drivers/ps2sony.cpp
+++ b/src/mame/drivers/ps2sony.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:
+// copyright-holders:Ryan Holtz
/**********************************************************************************************************************
2017-11-05 Skeleton PLACEHOLDER ONLY.
@@ -158,30 +158,1006 @@ iLinkSGUID=0x--------
#include "emu.h"
#include "cpu/mips/mips3.h"
#include "cpu/mips/r3000.h"
+#include "machine/ps2timer.h"
#include "emupal.h"
#include "screen.h"
-
class ps2sony_state : public driver_device
{
public:
ps2sony_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
+ , m_timer(*this, "timer%u", 0U)
+ , m_screen(*this, "screen")
+ , m_iop_ram(*this, "iop_ram")
+ , m_sp_ram(*this, "sp_ram")
+ , m_vu0_imem(*this, "vu0imem")
+ , m_vu0_dmem(*this, "vu0dmem")
+ , m_vu1_imem(*this, "vu1imem")
+ , m_vu1_dmem(*this, "vu1dmem")
+ , m_vblank_timer(nullptr)
{ }
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
void ps2sony(machine_config &config);
- void mem_map(address_map &map);
-private:
- virtual void video_start() override;
- required_device<cpu_device> m_maincpu;
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ TIMER_CALLBACK_MEMBER(vblank);
+
+ DECLARE_READ64_MEMBER(gs_regs0_r);
+ DECLARE_WRITE64_MEMBER(gs_regs0_w);
+ DECLARE_READ64_MEMBER(gs_regs1_r);
+ DECLARE_WRITE64_MEMBER(gs_regs1_w);
+
+ DECLARE_READ32_MEMBER(ipu_r);
+ DECLARE_WRITE32_MEMBER(ipu_w);
+ DECLARE_READ64_MEMBER(vif0_fifo_r);
+ DECLARE_WRITE64_MEMBER(vif0_fifo_w);
+ DECLARE_READ64_MEMBER(vif1_fifo_r);
+ DECLARE_WRITE64_MEMBER(vif1_fifo_w);
+ DECLARE_READ64_MEMBER(gif_fifo_r);
+ DECLARE_WRITE64_MEMBER(gif_fifo_w);
+ DECLARE_READ64_MEMBER(ipu_fifo_r);
+ DECLARE_WRITE64_MEMBER(ipu_fifo_w);
+ DECLARE_READ32_MEMBER(dmac_channel_r);
+ DECLARE_WRITE32_MEMBER(dmac_channel_w);
+ DECLARE_READ32_MEMBER(dmac_r);
+ DECLARE_WRITE32_MEMBER(dmac_w);
+ DECLARE_READ32_MEMBER(intc_r);
+ DECLARE_WRITE32_MEMBER(intc_w);
+ DECLARE_READ32_MEMBER(sif_smflg_r);
+ DECLARE_WRITE32_MEMBER(sif_smflg_w);
+ DECLARE_WRITE8_MEMBER(debug_w);
+ DECLARE_READ32_MEMBER(unk_f430_r);
+ DECLARE_WRITE32_MEMBER(unk_f430_w);
+ DECLARE_READ32_MEMBER(unk_f440_r);
+ DECLARE_WRITE32_MEMBER(unk_f440_w);
+ DECLARE_READ32_MEMBER(unk_f520_r);
+
+ void check_irq0();
+ void raise_interrupt(int line);
+
+ void mem_map(address_map &map);
+ void iop_map(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device_array<ps2_timer_device, 4> m_timer;
+ required_device<screen_device> m_screen;
+ required_shared_ptr<uint64_t> m_iop_ram;
+ required_shared_ptr<uint64_t> m_sp_ram;
+ required_shared_ptr<uint64_t> m_vu0_imem;
+ required_shared_ptr<uint64_t> m_vu0_dmem;
+ required_shared_ptr<uint64_t> m_vu1_imem;
+ required_shared_ptr<uint64_t> m_vu1_dmem;
+
+ uint64_t m_gs_base_regs[15];
+ uint64_t m_gs_csr;
+ uint64_t m_gs_imr;
+ uint64_t m_gs_busdir;
+ uint64_t m_gs_sig_label_id;
+
+ uint32_t m_unk_f430_reg;
+ uint32_t m_unk_f440_counter;
+ uint32_t m_unk_f440_reg;
+ uint32_t m_unk_f440_ret;
+
+ uint32_t m_ipu_ctrl;
+ uint64_t m_ipu_in_fifo[0x1000];
+ uint64_t m_ipu_in_fifo_index;
+ uint64_t m_ipu_out_fifo[0x1000];
+ uint64_t m_ipu_out_fifo_index;
+
+ enum
+ {
+ INT_GS = 0,
+ INT_SBUS,
+ INT_VB_ON,
+ INT_VB_OFF,
+ INT_VIF0,
+ INT_VIF1,
+ INT_VU0,
+ INT_VU1,
+ INT_IPU,
+ INT_TIMER0,
+ INT_TIMER1,
+ INT_TIMER2,
+ INT_TIMER3,
+ INT_SFIFO,
+ INT_VU0WD
+ };
+
+ uint32_t m_istat;
+ uint32_t m_imask;
+
+ emu_timer *m_vblank_timer;
};
+/**************************************
+ *
+ * Machine Hardware
+ *
+ */
+
+READ32_MEMBER(ps2sony_state::dmac_r)
+{
+ uint32_t ret = 0;
+ switch (offset)
+ {
+ case 0: /* D_CTRL */
+ logerror("%s: dmac_r: D_CTRL (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 2: /* D_STAT */
+ logerror("%s: dmac_r: D_STAT (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 4: /* D_PCR */
+ logerror("%s: dmac_r: D_PCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 6: /* D_SQWC */
+ logerror("%s: dmac_r: D_SQWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 8: /* D_RBSR */
+ logerror("%s: dmac_r: D_RBSR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 10: /* D_RBOR */
+ logerror("%s: dmac_r: D_RBOR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 12: /* D_STADR */
+ logerror("%s: dmac_r: D_STADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ default:
+ logerror("%s: dmac_r: Unknown offset %08x\n", machine().describe_context(), 0x1000e000 + (offset << 3));
+ break;
+ }
+ return ret;
+}
+
+WRITE32_MEMBER(ps2sony_state::dmac_w)
+{
+ switch (offset)
+ {
+ case 0: /* D_CTRL */
+ logerror("%s: dmac_w: D_CTRL = %08x\n", machine().describe_context(), data);
+ break;
+ case 2: /* D_STAT */
+ logerror("%s: dmac_w: D_STAT = %08x\n", machine().describe_context(), data);
+ break;
+ case 4: /* D_PCR */
+ logerror("%s: dmac_w: D_PCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 6: /* D_SQWC */
+ logerror("%s: dmac_w: D_SQWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 8: /* D_RBSR */
+ logerror("%s: dmac_w: D_RBSR = %08x\n", machine().describe_context(), data);
+ break;
+ case 10: /* D_RBOR */
+ logerror("%s: dmac_w: D_RBOR = %08x\n", machine().describe_context(), data);
+ break;
+ case 12: /* D_STADR */
+ logerror("%s: dmac_w: D_STADR = %08x\n", machine().describe_context(), data);
+ break;
+ default:
+ logerror("%s: dmac_w: Unknown offset %08x = %08X\n", machine().describe_context(), 0x1000e000 + (offset << 3), data);
+ break;
+ }
+}
+
+READ32_MEMBER(ps2sony_state::dmac_channel_r)
+{
+ uint32_t ret = 0;
+ switch (offset + 0x8000/8)
+ {
+ case 0x8000/8: /* D0_CHCR */
+ logerror("%s: dmac_channel_r: D0_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x8010/8: /* D0_MADR */
+ logerror("%s: dmac_channel_r: D0_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x8020/8: /* D0_QWC */
+ logerror("%s: dmac_channel_r: D0_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x8030/8: /* D0_TADR */
+ logerror("%s: dmac_channel_r: D0_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x8040/8: /* D0_ASR0 */
+ logerror("%s: dmac_channel_r: D0_ASR0 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x8050/8: /* D0_ASR1 */
+ logerror("%s: dmac_channel_r: D0_ASR1 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9000/8: /* D1_CHCR */
+ logerror("%s: dmac_channel_r: D1_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9010/8: /* D1_MADR */
+ logerror("%s: dmac_channel_r: D1_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9020/8: /* D1_QWC */
+ logerror("%s: dmac_channel_r: D1_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9030/8: /* D1_TADR */
+ logerror("%s: dmac_channel_r: D1_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9040/8: /* D1_ASR0 */
+ logerror("%s: dmac_channel_r: D1_ASR0 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0x9050/8: /* D1_ASR1 */
+ logerror("%s: dmac_channel_r: D1_ASR1 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa000/8: /* D2_CHCR */
+ logerror("%s: dmac_channel_r: D2_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa010/8: /* D2_MADR */
+ logerror("%s: dmac_channel_r: D2_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa020/8: /* D2_QWC */
+ logerror("%s: dmac_channel_r: D2_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa030/8: /* D2_TADR */
+ logerror("%s: dmac_channel_r: D2_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa040/8: /* D2_ASR0 */
+ logerror("%s: dmac_channel_r: D2_ASR0 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xa050/8: /* D2_ASR1 */
+ logerror("%s: dmac_channel_r: D2_ASR1 (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb000/8: /* D3_CHCR */
+ logerror("%s: dmac_channel_r: D3_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb010/8: /* D3_MADR */
+ logerror("%s: dmac_channel_r: D3_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb020/8: /* D3_QWC */
+ logerror("%s: dmac_channel_r: D3_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb400/8: /* D4_CHCR */
+ logerror("%s: dmac_channel_r: D4_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb410/8: /* D4_MADR */
+ logerror("%s: dmac_channel_r: D4_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb420/8: /* D4_QWC */
+ logerror("%s: dmac_channel_r: D4_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xb430/8: /* D4_TADR */
+ logerror("%s: dmac_channel_r: D4_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc000/8: /* D5_CHCR */
+ logerror("%s: dmac_channel_r: D5_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc010/8: /* D5_MADR */
+ logerror("%s: dmac_channel_r: D5_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc020/8: /* D5_QWC */
+ logerror("%s: dmac_channel_r: D5_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc400/8: /* D6_CHCR */
+ logerror("%s: dmac_channel_r: D6_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc410/8: /* D6_MADR */
+ logerror("%s: dmac_channel_r: D6_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc420/8: /* D6_QWC */
+ logerror("%s: dmac_channel_r: D6_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc430/8: /* D6_TADR */
+ logerror("%s: dmac_channel_r: D6_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc800/8: /* D7_CHCR */
+ logerror("%s: dmac_channel_r: D7_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc810/8: /* D7_MADR */
+ logerror("%s: dmac_channel_r: D7_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xc820/8: /* D7_QWC */
+ logerror("%s: dmac_channel_r: D7_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd000/8: /* D8_CHCR */
+ logerror("%s: dmac_channel_r: D8_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd010/8: /* D8_MADR */
+ logerror("%s: dmac_channel_r: D8_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd020/8: /* D8_QWC */
+ logerror("%s: dmac_channel_r: D8_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd080/8: /* D8_SADR */
+ logerror("%s: dmac_channel_r: D8_SADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd400/8: /* D9_CHCR */
+ logerror("%s: dmac_channel_r: D9_CHCR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd410/8: /* D9_MADR */
+ logerror("%s: dmac_channel_r: D9_MADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd420/8: /* D9_QWC */
+ logerror("%s: dmac_channel_r: D9_QWC (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd430/8: /* D9_TADR */
+ logerror("%s: dmac_channel_r: D9_TADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 0xd480/8: /* D9_SADR */
+ logerror("%s: dmac_channel_r: D9_SADR (%08x)\n", machine().describe_context(), ret);
+ break;
+ default:
+ logerror("%s: dmac_channel_r: Unknown offset %08x\n", machine().describe_context(), 0x10008000 + (offset << 3));
+ break;
+ }
+ return ret;
+}
+
+WRITE32_MEMBER(ps2sony_state::dmac_channel_w)
+{
+ switch (offset + 0x8000/8)
+ {
+ case 0x8000/8: /* D0_CHCR */
+ logerror("%s: dmac_channel_w: D0_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x8010/8: /* D0_MADR */
+ logerror("%s: dmac_channel_w: D0_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x8020/8: /* D0_QWC */
+ logerror("%s: dmac_channel_w: D0_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x8030/8: /* D0_TADR */
+ logerror("%s: dmac_channel_w: D0_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x8040/8: /* D0_ASR0 */
+ logerror("%s: dmac_channel_w: D0_ASR0 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x8050/8: /* D0_ASR1 */
+ logerror("%s: dmac_channel_w: D0_ASR1 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9000/8: /* D1_CHCR */
+ logerror("%s: dmac_channel_w: D1_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9010/8: /* D1_MADR */
+ logerror("%s: dmac_channel_w: D1_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9020/8: /* D1_QWC */
+ logerror("%s: dmac_channel_w: D1_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9030/8: /* D1_TADR */
+ logerror("%s: dmac_channel_w: D1_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9040/8: /* D1_ASR0 */
+ logerror("%s: dmac_channel_w: D1_ASR0 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0x9050/8: /* D1_ASR1 */
+ logerror("%s: dmac_channel_w: D1_ASR1 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa000/8: /* D2_CHCR */
+ logerror("%s: dmac_channel_w: D2_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa010/8: /* D2_MADR */
+ logerror("%s: dmac_channel_w: D2_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa020/8: /* D2_QWC */
+ logerror("%s: dmac_channel_w: D2_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa030/8: /* D2_TADR */
+ logerror("%s: dmac_channel_w: D2_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa040/8: /* D2_ASR0 */
+ logerror("%s: dmac_channel_w: D2_ASR0 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xa050/8: /* D2_ASR1 */
+ logerror("%s: dmac_channel_w: D2_ASR1 = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb000/8: /* D3_CHCR */
+ logerror("%s: dmac_channel_w: D3_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb010/8: /* D3_MADR */
+ logerror("%s: dmac_channel_w: D3_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb020/8: /* D3_QWC */
+ logerror("%s: dmac_channel_w: D3_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb400/8: /* D4_CHCR */
+ logerror("%s: dmac_channel_w: D4_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb410/8: /* D4_MADR */
+ logerror("%s: dmac_channel_w: D4_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb420/8: /* D4_QWC */
+ logerror("%s: dmac_channel_w: D4_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xb430/8: /* D4_TADR */
+ logerror("%s: dmac_channel_w: D4_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc000/8: /* D5_CHCR */
+ logerror("%s: dmac_channel_w: D5_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc010/8: /* D5_MADR */
+ logerror("%s: dmac_channel_w: D5_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc020/8: /* D5_QWC */
+ logerror("%s: dmac_channel_w: D5_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc400/8: /* D6_CHCR */
+ logerror("%s: dmac_channel_w: D6_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc410/8: /* D6_MADR */
+ logerror("%s: dmac_channel_w: D6_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc420/8: /* D6_QWC */
+ logerror("%s: dmac_channel_w: D6_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc430/8: /* D6_TADR */
+ logerror("%s: dmac_channel_w: D6_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc800/8: /* D7_CHCR */
+ logerror("%s: dmac_channel_w: D7_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc810/8: /* D7_MADR */
+ logerror("%s: dmac_channel_w: D7_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xc820/8: /* D7_QWC */
+ logerror("%s: dmac_channel_w: D7_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd000/8: /* D8_CHCR */
+ logerror("%s: dmac_channel_w: D8_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd010/8: /* D8_MADR */
+ logerror("%s: dmac_channel_w: D8_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd020/8: /* D8_QWC */
+ logerror("%s: dmac_channel_w: D8_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd080/8: /* D8_SADR */
+ logerror("%s: dmac_channel_w: D8_SADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd400/8: /* D9_CHCR */
+ logerror("%s: dmac_channel_w: D9_CHCR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd410/8: /* D9_MADR */
+ logerror("%s: dmac_channel_w: D9_MADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd420/8: /* D9_QWC */
+ logerror("%s: dmac_channel_w: D9_QWC = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd430/8: /* D9_TADR */
+ logerror("%s: dmac_channel_w: D9_TADR = %08x\n", machine().describe_context(), data);
+ break;
+ case 0xd480/8: /* D9_SADR */
+ logerror("%s: dmac_channel_w: D9_SADR = %08x\n", machine().describe_context(), data);
+ break;
+ default:
+ logerror("%s: dmac_channel_w: Unknown offset %08x = %08x\n", machine().describe_context(), 0x10008000 + (offset << 3), data);
+ break;
+ }
+}
+
+READ64_MEMBER(ps2sony_state::vif0_fifo_r)
+{
+ uint64_t ret = 0ULL;
+ if (offset)
+ {
+ logerror("%s: vif0_fifo_r [127..64]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ else
+ {
+ logerror("%s: vif0_fifo_r [63..0]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::vif0_fifo_w)
+{
+ if (offset)
+ {
+ logerror("%s: vif0_fifo_w [127..64]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+ else
+ {
+ logerror("%s: vif0_fifo_w [63..0]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+}
+
+READ64_MEMBER(ps2sony_state::vif1_fifo_r)
+{
+ uint64_t ret = 0ULL;
+ if (offset)
+ {
+ logerror("%s: vif1_fifo_r [127..64]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ else
+ {
+ logerror("%s: vif1_fifo_r [63..0]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::vif1_fifo_w)
+{
+ if (offset)
+ {
+ logerror("%s: vif1_fifo_w [127..64]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+ else
+ {
+ logerror("%s: vif1_fifo_w [63..0]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+}
+
+READ64_MEMBER(ps2sony_state::gif_fifo_r)
+{
+ uint64_t ret = 0ULL;
+ if (offset)
+ {
+ logerror("%s: gif_fifo_r [127..64]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ else
+ {
+ logerror("%s: gif_fifo_r [63..0]: (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::gif_fifo_w)
+{
+ if (offset)
+ {
+ logerror("%s: gif_fifo_w [127..64]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+ else
+ {
+ logerror("%s: gif_fifo_w [63..0]: %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ }
+}
+
+READ32_MEMBER(ps2sony_state::ipu_r)
+{
+ uint32_t ret = 0;
+ switch (offset)
+ {
+ case 0: /* IPU_CMD */
+ logerror("%s: ipu_r: IPU_CMD (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 2: /* IPU_CTRL */
+ ret = m_ipu_in_fifo_index | (m_ipu_out_fifo_index << 4);
+ logerror("%s: ipu_r: IPU_CTRL (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 4: /* IPU_BP */
+ ret = m_ipu_in_fifo_index << 8;
+ logerror("%s: ipu_r: IPU_BP (%08x)\n", machine().describe_context(), ret);
+ break;
+ case 6: /* IPU_TOP */
+ logerror("%s: ipu_r: IPU_TOP (%08x)\n", machine().describe_context(), ret);
+ break;
+ default:
+ logerror("%s: ipu_r: Unknown offset %08x\n", machine().describe_context(), 0x10002000 + (offset << 3));
+ break;
+ }
+ return ret;
+}
+
+WRITE32_MEMBER(ps2sony_state::ipu_w)
+{
+ switch (offset)
+ {
+ case 0: /* IPU_CMD */
+ logerror("%s: ipu_w: IPU_CMD = %08x\n", machine().describe_context(), data);
+ switch ((data >> 28) & 0xf)
+ {
+ case 0x00: /* BCLR */
+ m_ipu_in_fifo_index = 0;
+ logerror("%s: IPU command: BCLR (%08x)\n", machine().describe_context(), data);
+ break;
+ case 0x01: /* IDEC */
+ logerror("%s: IPU command: IDEC (%08x)\n", machine().describe_context(), data);
+ logerror("%s: FB:%d QSC:%d DT_DECODE:%d SGN:%d DITHER:%d OFM:%s\n", machine().describe_context(),
+ data & 0x3f, (data >> 16) & 0x1f, BIT(data, 24), BIT(data, 25), BIT(data, 26), BIT(data, 27) ? "RGB16" : "RGB32");
+ break;
+ case 0x02: /* BDEC */
+ logerror("%s: IPU command: BDEC (%08x)\n", machine().describe_context(), data);
+ logerror("%s: FB:%d QSC:%d DT:%d DCR:%d MBI:%d\n", machine().describe_context(),
+ data & 0x3f, (data >> 16) & 0x1f, BIT(data, 25), BIT(data, 26), BIT(data, 27));
+ break;
+ case 0x03: /* VDEC */
+ {
+ static const char *vlc[4] =
+ {
+ "Macroblock Address Increment",
+ "Macroblock Type",
+ "Motion Code",
+ "DMVector"
+ };
+ logerror("%s: IPU command: VDEC (%08x)\n", machine().describe_context(), data);
+ logerror("%s: FB:%d TBL:%s\n", machine().describe_context(), data & 0x3f, vlc[(data >> 26) & 3]);
+ break;
+ }
+ case 0x04: /* FDEC */
+ logerror("%s: IPU command: FDEC (%08x)\n", machine().describe_context(), data);
+ logerror("%s: FB:%d\n", machine().describe_context(), data & 0x3f);
+ break;
+ case 0x05: /* SETIQ */
+ logerror("%s: IPU command: SETIQ (%08x)\n", machine().describe_context(), data);
+ logerror("%s: FB:%d IQM:%s quantization matrix\n", machine().describe_context(), data & 0x3f, BIT(data, 27) ? "Non-intra" : "Intra");
+ break;
+ case 0x06: /* SETVQ */
+ logerror("%s: IPU command: SETVQ (%08x)\n", machine().describe_context(), data);
+ break;
+ case 0x07: /* CSC */
+ logerror("%s: IPU command: CSC (%08x)\n", machine().describe_context(), data);
+ logerror("%s: MBC:%d DTE:%d OFM:%s\n", machine().describe_context(), data & 0x3ff, BIT(data, 26), BIT(data, 27) ? "RGB16" : "RGB32");
+ break;
+ case 0x08: /* PACK */
+ logerror("%s: IPU command: PACK (%08x)\n", machine().describe_context(), data);
+ logerror("%s: DITHER:%d OFM:%s\n", machine().describe_context(), BIT(data, 26), BIT(data, 27) ? "RGB16" : "INDX4");
+ break;
+ case 0x09: /* SETTH */
+ logerror("%s: IPU command: SETTH (%08x)\n", machine().describe_context(), data);
+ logerror("%s: TH0:%d TH1:%s\n", machine().describe_context(), data & 0x1ff, (data >> 16) & 0x1ff);
+ break;
+ default:
+ logerror("%s: Unknown IPU command: %08x\n", machine().describe_context(), data);
+ break;
+ }
+ break;
+ case 2: /* IPU_CTRL */
+ logerror("%s: ipu_w: IPU_CTRL = %08x\n", machine().describe_context(), data);
+ if (BIT(data, 30))
+ {
+ m_ipu_in_fifo_index = 0;
+ m_ipu_out_fifo_index = 0;
+ m_ipu_ctrl &= ~(0x8000c000);
+ }
+ break;
+ case 4: /* IPU_BP */
+ logerror("%s: ipu_w: IPU_BP = %08x (Not Valid!)\n", machine().describe_context(), data);
+ break;
+ case 6: /* IPU_TOP */
+ logerror("%s: ipu_w: IPU_TOP = %08x\n", machine().describe_context(), data);
+ break;
+ default:
+ logerror("%s: ipu_w: Unknown offset %08x = %08x\n", machine().describe_context(), 0x10002000 + (offset << 3), data);
+ break;
+ }
+}
+
+READ64_MEMBER(ps2sony_state::ipu_fifo_r)
+{
+ uint64_t ret = 0ULL;
+ switch (offset)
+ {
+ case 0:
+ logerror("%s: ipu_fifo_r: IPU_OUT_FIFO[127..64] (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ case 1:
+ logerror("%s: ipu_fifo_r: IPU_OUT_FIFO[63..0] (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ case 2:
+ logerror("%s: ipu_fifo_r: IPU_IN_FIFO[127..64] (Not Valid!)\n", machine().describe_context());
+ break;
+ case 3:
+ logerror("%s: ipu_fifo_r: IPU_IN_FIFO[63..0] (Not Valid!)\n", machine().describe_context());
+ break;
+ default:
+ logerror("%s: ipu_fifo_r: Unknown offset %08x\n", machine().describe_context(), 0x10007000 + (offset << 1));
+ break;
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::ipu_fifo_w)
+{
+ switch (offset)
+ {
+ case 0:
+ logerror("%s: ipu_fifo_w: IPU_OUT_FIFO[127..64] = %08x%08x (Not Valid!)\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ break;
+ case 1:
+ logerror("%s: ipu_fifo_w: IPU_OUT_FIFO[63..0] = %08x%08x (Not Valid!)\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ break;
+ case 2:
+ logerror("%s: ipu_fifo_w: IPU_IN_FIFO[127..64] = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ m_ipu_in_fifo[m_ipu_in_fifo_index] = data;
+ m_ipu_in_fifo_index++;
+ m_ipu_in_fifo_index &= 0xf;
+ break;
+ case 3:
+ logerror("%s: ipu_fifo_w: IPU_IN_FIFO[63..0] = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ break;
+ default:
+ logerror("%s: ipu_fifo_w: Unknown offset %08x = %08x%08x\n", machine().describe_context(), 0x10007000 + (offset << 1), (uint32_t)(data >> 32), (uint32_t)data);
+ break;
+ }
+}
+
+void ps2sony_state::check_irq0()
+{
+ m_maincpu->set_input_line(MIPS3_IRQ0, (m_istat & m_imask) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void ps2sony_state::raise_interrupt(int line)
+{
+ printf("raise_interrupt: %d\n", (1 << line));
+ m_istat |= (1 << line);
+ check_irq0();
+}
-void ps2sony_state::video_start()
+READ32_MEMBER(ps2sony_state::intc_r)
{
+ switch (offset)
+ {
+ case 0: // I_STAT
+ logerror("%s: intc_r: I_STAT %08x\n", machine().describe_context(), m_istat);
+ return m_istat;
+ case 2: // I_MASK
+ logerror("%s: intc_r: I_MASK %08x\n", machine().describe_context(), m_imask);
+ return m_imask;
+ default:
+ logerror("%s: intc_r: Unknown offset %08x\n", machine().describe_context(), 0x1000f000 + (offset << 2));
+ return 0;
+ }
+}
+
+WRITE32_MEMBER(ps2sony_state::intc_w)
+{
+ switch (offset)
+ {
+ case 0: // I_STAT
+ logerror("%s: intc_w: I_STAT = %08x\n", machine().describe_context(), data);
+ m_istat &= ~data;
+ check_irq0();
+ break;
+ case 2: // I_MASK
+ logerror("%s: intc_w: I_MASK = %08x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_imask);
+ check_irq0();
+ break;
+ default:
+ logerror("%s: intc_w: Unknown offset %08x = %08x\n", machine().describe_context(), 0x1000f000 + (offset << 2), data);
+ break;
+ }
+}
+
+READ32_MEMBER(ps2sony_state::sif_smflg_r)
+{
+ uint32_t ret = 0x00010000;
+ logerror("%s: sif_smflg_r (%08x)\n", machine().describe_context(), ret);
+ return ret;
+}
+
+WRITE32_MEMBER(ps2sony_state::sif_smflg_w)
+{
+ logerror("%s: sif_smflg_w = %08x\n", machine().describe_context(), data);
+}
+
+void ps2sony_state::machine_start()
+{
+ if (!m_vblank_timer)
+ m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ps2sony_state::vblank), this));
+}
+
+void ps2sony_state::machine_reset()
+{
+ m_unk_f430_reg = 0;
+ m_unk_f440_reg = 0;
+ m_unk_f440_ret = 0;
+ m_unk_f440_counter = 0;
+
+ m_ipu_ctrl = 0;
+ memset(m_ipu_in_fifo, 0, sizeof(uint64_t)*0x1000);
+ m_ipu_in_fifo_index = 0;
+ memset(m_ipu_out_fifo, 0, sizeof(uint64_t)*0x1000);
+ m_ipu_out_fifo_index = 0;
+
+ memset(m_gs_base_regs, 0, sizeof(uint64_t) * 15);
+ m_gs_csr = 0ULL;
+ m_gs_imr = 0ULL;
+ m_gs_busdir = 0ULL;
+ m_gs_sig_label_id = 0ULL;
+
+ m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
+}
+
+TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
+{
+ if (param)
+ {
+ // VBlank enter
+ printf("1 ");
+ raise_interrupt(INT_VB_ON);
+ m_vblank_timer->adjust(m_screen->time_until_pos(0), 0);
+ }
+ else
+ {
+ printf("0 ");
+ // VBlank exit
+ raise_interrupt(INT_VB_OFF);
+ m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
+ }
+}
+
+WRITE8_MEMBER(ps2sony_state::debug_w)
+{
+ printf("%c", (char)data);
+}
+
+READ32_MEMBER(ps2sony_state::unk_f520_r)
+{
+ // Unknown purpose - BIOS seems to expect this value initially
+ return 0x1201;
+}
+
+READ32_MEMBER(ps2sony_state::unk_f430_r)
+{
+ logerror("%s: Unknown 1000f430 read: %08x\n", machine().describe_context(), 0);
+ //return m_unk_f430_reg;
+ //return ~0;
+ return 0; // BIOS seems unhappy if we return anything else
+}
+
+WRITE32_MEMBER(ps2sony_state::unk_f430_w)
+{
+ m_unk_f430_reg = data & ~0x80000000;
+ const uint16_t cmd = (data >> 16) & 0xfff;
+ const uint8_t subcmd = (data >> 6) & 0xf;
+ switch (cmd)
+ {
+ case 0x0021:
+ if (subcmd == 1 && !BIT(m_unk_f440_reg, 7))
+ {
+ m_unk_f440_counter = 0;
+ }
+ break;
+ }
+ logerror("%s: Unknown 1000f430 write: %08x (cmd:%02x lsb:%02x)\n", machine().describe_context(), data, (data >> 16) & 0xff, data & 0xff);
+}
+
+READ32_MEMBER(ps2sony_state::unk_f440_r)
+{
+ uint32_t ret = 0;
+
+ const uint8_t lsb5 = m_unk_f430_reg & 0x1f;
+ const uint16_t cmd = (uint16_t)(m_unk_f430_reg >> 16);
+ const uint8_t subcmd = (m_unk_f430_reg >> 6) & 0xf;
+ if (subcmd == 0)
+ {
+ switch (cmd)
+ {
+ case 0x21:
+ if (m_unk_f440_counter < 2)
+ {
+ ret = 0x1f;
+ m_unk_f440_counter++;
+ }
+ break;
+
+ case 0x40:
+ ret = lsb5;
+ break;
+
+ default:
+ fatalerror("!");
+ break;
+ }
+ }
+
+ logerror("%s: Unknown 1000f440 read: %08x\n", machine().describe_context(), ret);
+ return ret;
+}
+
+WRITE32_MEMBER(ps2sony_state::unk_f440_w)
+{
+ logerror("%s: Unknown 1000f440 write: %08x\n", machine().describe_context(), data);
+ m_unk_f440_reg = data;
+}
+
+/**************************************
+ *
+ * Video Hardware
+ *
+ */
+
+READ64_MEMBER(ps2sony_state::gs_regs0_r)
+{
+ uint64_t ret = m_gs_base_regs[offset >> 1];
+ switch (offset)
+ {
+ case 0x00: logerror("%s: gs_regs0_r: PMODE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x02: logerror("%s: gs_regs0_r: SMODE1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x04: logerror("%s: gs_regs0_r: SMODE2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x06: logerror("%s: gs_regs0_r: SRFSH (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x08: logerror("%s: gs_regs0_r: SYNCH1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x0a: logerror("%s: gs_regs0_r: SYNCH2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x0c: logerror("%s: gs_regs0_r: SYNCV (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x0e: logerror("%s: gs_regs0_r: DISPFB1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x10: logerror("%s: gs_regs0_r: DISPLAY1 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x12: logerror("%s: gs_regs0_r: DISPFB2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x14: logerror("%s: gs_regs0_r: DISPLAY2 (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x16: logerror("%s: gs_regs0_r: EXTBUF (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x18: logerror("%s: gs_regs0_r: EXTDATA (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x1a: logerror("%s: gs_regs0_r: EXTWRITE (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ case 0x1c: logerror("%s: gs_regs0_r: BGCOLOR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret); break;
+ default: logerror("%s: gs_regs0_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3)); break;
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::gs_regs0_w)
+{
+ switch (offset)
+ {
+ case 0x00: logerror("%s: gs_regs0_w: PMODE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x02: logerror("%s: gs_regs0_w: SMODE1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x04: logerror("%s: gs_regs0_w: SMODE2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x06: logerror("%s: gs_regs0_w: SRFSH = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x08: logerror("%s: gs_regs0_w: SYNCH1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x0a: logerror("%s: gs_regs0_w: SYNCH2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x0c: logerror("%s: gs_regs0_w: SYNCV = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x0e: logerror("%s: gs_regs0_w: DISPFB1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x10: logerror("%s: gs_regs0_w: DISPLAY1 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x12: logerror("%s: gs_regs0_w: DISPFB2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x14: logerror("%s: gs_regs0_w: DISPLAY2 = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x16: logerror("%s: gs_regs0_w: EXTBUF = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x18: logerror("%s: gs_regs0_w: EXTDATA = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x1a: logerror("%s: gs_regs0_w: EXTWRITE = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ case 0x1c: logerror("%s: gs_regs0_w: BGCOLOR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data); break;
+ default: logerror("%s: gs_regs0_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data); break;
+ }
+ COMBINE_DATA(&m_gs_base_regs[offset >> 1]);
+}
+
+READ64_MEMBER(ps2sony_state::gs_regs1_r)
+{
+ uint64_t ret = 0;
+ switch (offset)
+ {
+ case 0x00:
+ ret = m_gs_csr;
+ logerror("%s: gs_regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ case 0x02:
+ ret = m_gs_imr;
+ logerror("%s: gs_regs1_r: IMR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ case 0x08:
+ ret = m_gs_busdir;
+ logerror("%s: gs_regs1_r: BUSDIR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ case 0x10:
+ ret = m_gs_sig_label_id;
+ logerror("%s: gs_regs1_r: SIGLBLID (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
+ break;
+ default:
+ logerror("%s: gs_regs1_r: Unknown (%08x)\n", machine().describe_context(), 0x12000000 + (offset << 3));
+ break;
+ }
+ return ret;
+}
+
+WRITE64_MEMBER(ps2sony_state::gs_regs1_w)
+{
+ switch (offset)
+ {
+ case 0x00:
+ logerror("%s: gs_regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ COMBINE_DATA(&m_gs_csr);
+ break;
+ case 0x02:
+ logerror("%s: gs_regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ COMBINE_DATA(&m_gs_imr);
+ break;
+ case 0x08:
+ logerror("%s: gs_regs1_w: BUSDIR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ COMBINE_DATA(&m_gs_busdir);
+ break;
+ case 0x10:
+ logerror("%s: gs_regs1_w: SIGLBLID = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
+ COMBINE_DATA(&m_gs_sig_label_id);
+ break;
+ default:
+ logerror("%s: gs_regs1_w: Unknown %08x = %08x%08x\n", machine().describe_context(), 0x12000000 + (offset << 3), (uint32_t)(data >> 32), (uint32_t)data);
+ break;
+ }
}
uint32_t ps2sony_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -191,8 +1167,43 @@ uint32_t ps2sony_state::screen_update(screen_device &screen, bitmap_rgb32 &bitma
void ps2sony_state::mem_map(address_map &map)
{
- map(0x00000000, 0x01ffffff).ram(); // 32 MB RAM
- map(0x1fc00000, 0x1fdfffff).rom().region("bios", 0);
+ map(0x00000000, 0x01ffffff).mirror(0xe000000).ram(); // 32 MB RAM
+ map(0x10000000, 0x100007ff).rw(m_timer[0], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
+ map(0x10000800, 0x10000fff).rw(m_timer[1], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
+ map(0x10001000, 0x100017ff).rw(m_timer[2], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
+ map(0x10001800, 0x10001fff).rw(m_timer[3], FUNC(ps2_timer_device::read), FUNC(ps2_timer_device::write)).umask64(0x00000000ffffffff);
+ map(0x10002000, 0x10002fff).rw(FUNC(ps2sony_state::ipu_r), FUNC(ps2sony_state::ipu_w)).umask64(0x00000000ffffffff);
+ map(0x10004000, 0x1000400f).mirror(0xff0).rw(FUNC(ps2sony_state::vif0_fifo_r), FUNC(ps2sony_state::vif0_fifo_w));
+ map(0x10005000, 0x1000500f).mirror(0xff0).rw(FUNC(ps2sony_state::vif1_fifo_r), FUNC(ps2sony_state::vif1_fifo_w));
+ map(0x10006000, 0x1000600f).mirror(0xff0).rw(FUNC(ps2sony_state::gif_fifo_r), FUNC(ps2sony_state::gif_fifo_w));
+ map(0x10007000, 0x1000701f).mirror(0xfe0).rw(FUNC(ps2sony_state::ipu_fifo_r), FUNC(ps2sony_state::ipu_fifo_w));
+ map(0x10008000, 0x1000dfff).rw(FUNC(ps2sony_state::dmac_channel_r), FUNC(ps2sony_state::dmac_channel_w)).umask64(0x00000000ffffffff);;
+ map(0x1000e000, 0x1000efff).rw(FUNC(ps2sony_state::dmac_r), FUNC(ps2sony_state::dmac_w)).umask64(0x00000000ffffffff);
+ map(0x1000f000, 0x1000f017).rw(FUNC(ps2sony_state::intc_r), FUNC(ps2sony_state::intc_w)).umask64(0x00000000ffffffff);
+ map(0x1000f130, 0x1000f137).nopr();
+ map(0x1000f180, 0x1000f187).w(FUNC(ps2sony_state::debug_w)).umask64(0x00000000000000ff);
+ map(0x1000f230, 0x1000f237).rw(FUNC(ps2sony_state::sif_smflg_r), FUNC(ps2sony_state::sif_smflg_w)).umask64(0x00000000ffffffff);
+ map(0x1000f430, 0x1000f437).rw(FUNC(ps2sony_state::unk_f430_r), FUNC(ps2sony_state::unk_f430_w)).umask64(0x00000000ffffffff); // Unknown
+ map(0x1000f440, 0x1000f447).rw(FUNC(ps2sony_state::unk_f440_r), FUNC(ps2sony_state::unk_f440_w)).umask64(0x00000000ffffffff); // Unknown
+ map(0x1000f520, 0x1000f527).r(FUNC(ps2sony_state::unk_f520_r)).umask64(0x00000000ffffffff); // Unknown
+ map(0x11000000, 0x11000fff).mirror(0x3000).ram().share(m_vu0_imem);
+ map(0x11004000, 0x11004fff).mirror(0x3000).ram().share(m_vu0_dmem);
+ map(0x11008000, 0x1100bfff).ram().share(m_vu1_imem);
+ map(0x1100c000, 0x1100ffff).ram().share(m_vu1_dmem);
+ map(0x12000000, 0x120003ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs0_r), FUNC(ps2sony_state::gs_regs0_w));
+ map(0x12001000, 0x120013ff).mirror(0xc00).rw(FUNC(ps2sony_state::gs_regs1_r), FUNC(ps2sony_state::gs_regs1_w));
+ map(0x1c000000, 0x1c1fffff).ram().share(m_iop_ram); // IOP has 2MB EDO RAM per Wikipedia, and writes go up to this point
+ map(0x1fc00000, 0x1fffffff).rom().region("bios", 0);
+
+ map(0x70000000, 0x70003fff).ram().share(m_sp_ram); // 16KB Scratchpad RAM
+}
+
+void ps2sony_state::iop_map(address_map &map)
+{
+ map(0x00000000, 0x001fffff).ram().share(m_iop_ram);
+ map(0x1f802070, 0x1f802073).noprw();
+ map(0x1fc00000, 0x1fdfffff).rom().region("bios", 0);
+
}
static INPUT_PORTS_START( ps2sony )
@@ -200,15 +1211,25 @@ INPUT_PORTS_END
MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_DEVICE_ADD("maincpu", R5900LE, 294'912'000)
+ MCFG_CPU_FORCE_NO_DRC()
MCFG_MIPS3_ICACHE_SIZE(16384)
MCFG_MIPS3_DCACHE_SIZE(16384)
MCFG_DEVICE_PROGRAM_MAP(mem_map)
+ MCFG_DEVICE_ADD("iop", SONYPS2_IOP, XTAL(67'737'600)/2)
+ MCFG_DEVICE_PROGRAM_MAP(iop_map)
+
+ MCFG_QUANTUM_TIME(attotime::from_hz(1000000))
+ MCFG_DEVICE_ADD(m_timer[0], SONYPS2_TIMER, 294912000/2, true)
+ MCFG_DEVICE_ADD(m_timer[1], SONYPS2_TIMER, 294912000/2, true)
+ MCFG_DEVICE_ADD(m_timer[2], SONYPS2_TIMER, 294912000/2, false)
+ MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false)
+
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_UPDATE_DRIVER(ps2sony_state, screen_update)
- MCFG_SCREEN_SIZE(640, 480)
+ MCFG_SCREEN_SIZE(640, 525)
MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
MCFG_PALETTE_ADD("palette", 65536)
diff --git a/src/mame/machine/ps2timer.cpp b/src/mame/machine/ps2timer.cpp
new file mode 100644
index 00000000000..2ba6668715d
--- /dev/null
+++ b/src/mame/machine/ps2timer.cpp
@@ -0,0 +1,270 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/******************************************************************************
+*
+* Sony Playstation 2 Timer device skeleton
+*
+* To Do:
+* Everything
+*
+*/
+
+#include "ps2timer.h"
+
+DEFINE_DEVICE_TYPE(SONYPS2_TIMER, ps2_timer_device, "ps2timer", "EE Core Timer")
+
+ps2_timer_device::ps2_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SONYPS2_TIMER, tag, owner, clock)
+ , m_compare_timer(nullptr)
+ , m_overflow_timer(nullptr)
+ , m_mode(0)
+ , m_last_enable_time(attotime::zero)
+ , m_last_update_time(attotime::zero)
+ , m_elapsed_time(attotime::zero)
+ , m_enabled(false)
+ , m_zero_return(false)
+ , m_count(0)
+ , m_compare(0)
+ , m_can_hold(false)
+ , m_hold(0)
+ , m_clk_select(CLKS_BUSCLK1)
+ , m_gate_enable(false)
+ , m_gate_select(GATS_HBLNK)
+ , m_gate_mode(GATM_LOW)
+ , m_cmp_int_enabled(false)
+ , m_cmp_int(false)
+ , m_ovf_int_enabled(false)
+ , m_ovf_int(false)
+{
+}
+
+void ps2_timer_device::device_start()
+{
+ if (!m_compare_timer)
+ m_compare_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ps2_timer_device::compare), this));
+
+ if (!m_overflow_timer)
+ m_overflow_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ps2_timer_device::overflow), this));
+}
+
+void ps2_timer_device::device_reset()
+{
+ m_mode = 0;
+
+ m_last_enable_time = attotime::zero;
+ m_last_update_time = attotime::zero;
+ m_elapsed_time = attotime::zero;
+
+ m_enabled = false;
+ m_zero_return = false;
+
+ m_count = 0;
+ m_compare = 0;
+
+ m_can_hold = false;
+ m_hold = 0;
+
+ m_clk_select = CLKS_BUSCLK1;
+
+ m_gate_enable = false;
+ m_gate_select = GATS_HBLNK;
+ m_gate_mode = GATM_LOW;
+
+ m_cmp_int_enabled = false;
+ m_cmp_int = false;
+
+ m_ovf_int_enabled = false;
+ m_ovf_int = false;
+
+ m_compare_timer->adjust(attotime::never);
+ m_overflow_timer->adjust(attotime::never);
+}
+
+void ps2_timer_device::update_gate()
+{
+ // TODO
+}
+
+void ps2_timer_device::update_interrupts()
+{
+ // TODO
+}
+
+void ps2_timer_device::update_compare_timer()
+{
+ // TODO
+}
+
+void ps2_timer_device::update_overflow_timer()
+{
+ // TODO
+}
+
+void ps2_timer_device::update_count()
+{
+ if (!m_enabled) return;
+ uint32_t frequency = 0;
+
+ switch (m_clk_select)
+ {
+ case CLKS_BUSCLK1:
+ frequency = clock();
+ break;
+ case CLKS_BUSCLK16:
+ frequency = clock() / 16;
+ break;
+ case CLKS_BUSCLK256:
+ frequency = clock() / 256;
+ break;
+ case CLKS_HBLNK:
+ frequency = clock() / 18700;
+ break;
+ }
+
+ attotime curr_time = machine().scheduler().time();
+ attotime time_delta = curr_time - m_last_update_time;
+ m_last_update_time = curr_time;
+ m_elapsed_time += time_delta;
+ uint32_t ticks = (uint32_t)m_elapsed_time.as_ticks(frequency);
+ if (ticks > 0)
+ {
+ m_elapsed_time -= attotime::from_ticks(ticks, frequency);
+ m_count += ticks;
+ }
+}
+
+void ps2_timer_device::update_hold()
+{
+ // TODO
+}
+
+void ps2_timer_device::set_mode(uint32_t data)
+{
+ static const char *clks_names[4] = { "BUSCLK", "BUSCLK/16", "BUSCLK/256", "HBLNK" };
+ static const char *gatm_names[4] = { "low", "reset+rising", "reset+falling", "reset+both" };
+ logerror("%s: CLKS=%s, GATE=%d, GATS=%cBLNK\n", machine().describe_context(), clks_names[data & 3], BIT(data, 2), BIT(data, 3) ? 'V' : 'H');
+ logerror("%s: GATM=%s, ZRET=%d, CUE=%d\n", machine().describe_context(), gatm_names[(data >> 4) & 3], BIT(data, 6), BIT(data, 7));
+ logerror("%s: CMPE=%d, OVFE=%d, %s, %s\n", machine().describe_context(), BIT(data, 8), BIT(data, 9), BIT(data, 10) ? "Clear Equal" : "", BIT(data, 11) ? "Clear Overflow" : "");
+
+ if (!(data & (MODE_EQUF | MODE_OVFF)) && data == m_mode) return;
+
+ const uint32_t old = m_mode;
+ m_mode = data;
+ const uint32_t changed = old ^ data;
+
+ m_clk_select = (timer_clock_select)(data & 3);
+ m_gate_enable = BIT(data, 2);
+ m_gate_select = BIT(data, 3) ? GATS_VBLNK : GATS_HBLNK;
+ m_gate_mode = (timer_gate_mode)((data >> 4) & 3);
+ m_zero_return = BIT(data, 6);
+ m_enabled = BIT(data, 7);
+
+ if (changed & (MODE_GATE | MODE_GATS | MODE_GATM))
+ {
+ update_gate();
+ }
+
+ if (changed & (MODE_CUE | MODE_CLKS | MODE_ZRET))
+ {
+ update_compare_timer();
+ update_overflow_timer();
+ }
+
+ if (changed & (MODE_CMPE | MODE_OVFE | MODE_EQUF | MODE_OVFF))
+ {
+ m_cmp_int_enabled = BIT(data, 8);
+ m_ovf_int_enabled = BIT(data, 9);
+ m_cmp_int = BIT(data, 10) ? 0 : m_cmp_int;
+ m_ovf_int = BIT(data, 11) ? 0 : m_ovf_int;
+ update_interrupts();
+ }
+}
+
+TIMER_CALLBACK_MEMBER(ps2_timer_device::compare)
+{
+}
+
+TIMER_CALLBACK_MEMBER(ps2_timer_device::overflow)
+{
+}
+
+READ32_MEMBER(ps2_timer_device::read)
+{
+ uint32_t ret = 0;
+ switch (offset)
+ {
+ case 0x00:
+ {
+ const uint32_t old = m_count;
+ update_count();
+ ret = m_count;
+ if (old != m_count)
+ logerror("%s: PS2 timer read: COUNT (%08x)\n", machine().describe_context(), ret);
+ break;
+ }
+
+ case 0x02:
+ ret = m_mode;
+ logerror("%s: PS2 timer read: MODE (%08x)\n", machine().describe_context(), ret);
+ break;
+
+ case 0x04:
+ ret = m_compare;
+ logerror("%s: PS2 timer read: COMP (%08x)\n", machine().describe_context(), ret);
+ break;
+
+ case 0x06:
+ ret = m_hold;
+ logerror("%s: PS2 timer read: HOLD (%08x)\n", machine().describe_context(), ret);
+ break;
+
+ default:
+ break;
+ }
+ return ret;
+}
+
+WRITE32_MEMBER(ps2_timer_device::write)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_count = data;
+ logerror("%s: PS2 timer write: COUNT = %08x\n", machine().describe_context(), data);
+ update_compare_timer();
+ update_overflow_timer();
+ break;
+
+ case 0x02:
+ set_mode(data);
+ break;
+
+ case 0x04:
+ {
+ logerror("%s: PS2 timer write: COMP = %08x\n", machine().describe_context(), data);
+ if (m_compare == data)
+ break;
+
+ m_compare = data;
+ update_compare_timer();
+ break;
+ }
+
+ case 0x06:
+ {
+ if (!m_can_hold)
+ break;
+
+ logerror("%s: PS2 timer write: HOLD = %08x\n", machine().describe_context(), data);
+ if (m_hold == data)
+ break;
+
+ m_hold = data;
+ update_hold();
+ break;
+ }
+
+ default:
+ break;
+ }
+}
diff --git a/src/mame/machine/ps2timer.h b/src/mame/machine/ps2timer.h
new file mode 100644
index 00000000000..879526f1d92
--- /dev/null
+++ b/src/mame/machine/ps2timer.h
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/******************************************************************************
+*
+* Sony Playstation 2 Timer device skeleton
+*
+* To Do:
+* Everything
+*
+*/
+
+#ifndef MAME_MACHINE_PS2TIMER_H
+#define MAME_MACHINE_PS2TIMER_H
+
+#pragma once
+
+#include "emu.h"
+
+class ps2_timer_device : public device_t
+{
+public:
+ ps2_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool can_hold)
+ : ps2_timer_device(mconfig, tag, owner, clock)
+ {
+ m_can_hold = can_hold;
+ }
+
+ ps2_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_READ32_MEMBER(read);
+ DECLARE_WRITE32_MEMBER(write);
+
+protected:
+ enum timer_mode_mask : uint32_t
+ {
+ MODE_CLKS = (3 << 0),
+ MODE_GATE = (1 << 2),
+ MODE_GATS = (1 << 3),
+ MODE_GATM = (3 << 4),
+ MODE_ZRET = (1 << 6),
+ MODE_CUE = (1 << 7),
+ MODE_CMPE = (1 << 8),
+ MODE_OVFE = (1 << 9),
+ MODE_EQUF = (1 << 10),
+ MODE_OVFF = (1 << 11),
+ };
+
+ enum timer_gate_mode : uint32_t
+ {
+ GATM_LOW = 0,
+ GATM_RISING,
+ GATM_FALLING,
+ GATM_BOTH
+ };
+
+ enum timer_clock_select : uint32_t
+ {
+ CLKS_BUSCLK1 = 0,
+ CLKS_BUSCLK16,
+ CLKS_BUSCLK256,
+ CLKS_HBLNK
+ };
+
+ enum timer_gate_select : uint32_t
+ {
+ GATS_HBLNK = 0,
+ GATS_VBLNK
+ };
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ TIMER_CALLBACK_MEMBER(compare);
+ TIMER_CALLBACK_MEMBER(overflow);
+
+ void update_gate();
+ void update_interrupts();
+
+ void update_compare_timer();
+ void update_overflow_timer();
+
+ void update_count();
+ void update_hold();
+
+ void set_mode(uint32_t data);
+
+ emu_timer *m_compare_timer;
+ emu_timer *m_overflow_timer;
+
+ uint32_t m_mode;
+
+ attotime m_last_enable_time;
+ attotime m_last_update_time;
+ attotime m_elapsed_time;
+ bool m_enabled;
+ bool m_zero_return;
+ uint32_t m_count;
+ uint32_t m_compare;
+
+ bool m_can_hold;
+ uint32_t m_hold;
+
+ timer_clock_select m_clk_select;
+
+ bool m_gate_enable;
+ timer_gate_select m_gate_select;
+ timer_gate_mode m_gate_mode;
+
+ bool m_cmp_int_enabled;
+ bool m_cmp_int;
+
+ bool m_ovf_int_enabled;
+ bool m_ovf_int;
+};
+
+DECLARE_DEVICE_TYPE(SONYPS2_TIMER, ps2_timer_device)
+
+#endif // MAME_MACHINE_PS2TIMER_H \ No newline at end of file