summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/devices/cpu/mips/r3000.cpp1613
-rw-r--r--src/devices/cpu/mips/r3000.h458
-rw-r--r--src/devices/cpu/mips/r3kdasm.cpp16
-rw-r--r--src/devices/cpu/mips/r3kdasm.h6
-rw-r--r--src/mame/drivers/4dpi.cpp14
-rw-r--r--src/mame/drivers/decstation.cpp11
-rw-r--r--src/mame/drivers/indigo.cpp6
-rw-r--r--src/mame/drivers/jaguar.cpp6
-rw-r--r--src/mame/drivers/mips.cpp20
-rw-r--r--src/mame/drivers/speglsht.cpp10
-rw-r--r--src/mame/drivers/srmp5.cpp10
-rw-r--r--src/mame/drivers/tekxp33x.cpp6
-rw-r--r--src/mame/drivers/turrett.cpp22
-rw-r--r--src/mame/includes/mips.h2
-rw-r--r--src/mame/includes/turrett.h6
-rw-r--r--src/tools/unidasm.cpp4
16 files changed, 899 insertions, 1311 deletions
diff --git a/src/devices/cpu/mips/r3000.cpp b/src/devices/cpu/mips/r3000.cpp
index efbfaf99704..c43492c7871 100644
--- a/src/devices/cpu/mips/r3000.cpp
+++ b/src/devices/cpu/mips/r3000.cpp
@@ -1,96 +1,45 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
-/***************************************************************************
-
- r3000.c
- Core implementation for the portable MIPS R3000 emulator.
- Written by Aaron Giles
-
-***************************************************************************/
+/*
+ * MIPS-I emulation, including R2000[A], R3000[A] and IDT R30xx devices. The
+ * IDT devices come in two variations: those with an "E" suffix include a TLB,
+ * while those without have hard-wired address translation.
+ *
+ * TODO
+ * - FPU support
+ * - fix and enable overflow exceptions
+ * - further cleanup on coprocessors
+ * - R3041 features
+ * - cache emulation
+ *
+ */
#include "emu.h"
#include "r3000.h"
#include "r3kdasm.h"
#include "debugger.h"
+#define LOG_GENERAL (1U << 0)
+#define LOG_TLB (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL|LOG_TLB)
+#include "logmacro.h"
#define ENABLE_OVERFLOWS (0)
-#define ENABLE_IOP_KPUTS (1)
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define COP0_Index 0
-#define COP0_Random 1
-#define COP0_EntryLo 2
-#define COP0_Context 4
-#define COP0_BadVAddr 8
-#define COP0_Status 12
-#define COP0_Cause 13
-#define COP0_EPC 14
-#define COP0_PRId 15
-
-#define SR_IEc 0x00000001
-#define SR_KUc 0x00000002
-#define SR_IEp 0x00000004
-#define SR_KUp 0x00000008
-#define SR_IEo 0x00000010
-#define SR_KUo 0x00000020
-#define SR_IMSW0 0x00000100
-#define SR_IMSW1 0x00000200
-#define SR_IMEX0 0x00000400
-#define SR_IMEX1 0x00000800
-#define SR_IMEX2 0x00001000
-#define SR_IMEX3 0x00002000
-#define SR_IMEX4 0x00004000
-#define SR_IMEX5 0x00008000
-#define SR_IsC 0x00010000
-#define SR_SwC 0x00020000
-#define SR_PZ 0x00040000
-#define SR_CM 0x00080000
-#define SR_PE 0x00100000
-#define SR_TS 0x00200000
-#define SR_BEV 0x00400000
-#define SR_RE 0x02000000
-#define SR_COP0 0x10000000
-#define SR_COP1 0x20000000
-#define SR_COP2 0x40000000
-#define SR_COP3 0x80000000
-
-#define EXCEPTION_INTERRUPT 0
-#define EXCEPTION_TLBMOD 1
-#define EXCEPTION_TLBLOAD 2
-#define EXCEPTION_TLBSTORE 3
-#define EXCEPTION_ADDRLOAD 4
-#define EXCEPTION_ADDRSTORE 5
-#define EXCEPTION_BUSINST 6
-#define EXCEPTION_BUSDATA 7
-#define EXCEPTION_SYSCALL 8
-#define EXCEPTION_BREAK 9
-#define EXCEPTION_INVALIDOP 10
-#define EXCEPTION_BADCOP 11
-#define EXCEPTION_OVERFLOW 12
-#define EXCEPTION_TRAP 13
-
-
-/***************************************************************************
- HELPER MACROS
-***************************************************************************/
-
-#define RSREG ((m_op >> 21) & 31)
-#define RTREG ((m_op >> 16) & 31)
-#define RDREG ((m_op >> 11) & 31)
-#define SHIFT ((m_op >> 6) & 31)
+#define ENABLE_IOP_KPUTS (0)
+
+#define RSREG ((op >> 21) & 31)
+#define RTREG ((op >> 16) & 31)
+#define RDREG ((op >> 11) & 31)
+#define SHIFT ((op >> 6) & 31)
#define RSVAL m_r[RSREG]
#define RTVAL m_r[RTREG]
#define RDVAL m_r[RDREG]
-#define SIMMVAL ((int16_t)m_op)
-#define UIMMVAL ((uint16_t)m_op)
-#define LIMMVAL (m_op & 0x03ffffff)
+#define SIMMVAL s16(op)
+#define UIMMVAL u16(op)
+#define LIMMVAL (op & 0x03ffffff)
#define ADDPC(x) do { m_nextpc = m_pc + ((x) << 2); } while (0)
#define ADDPCL(x,l) do { m_nextpc = m_pc + ((x) << 2); m_r[l] = m_pc + 4; } while (0)
@@ -99,539 +48,233 @@
#define SETPC(x) do { m_nextpc = (x); } while (0)
#define SETPCL(x,l) do { m_nextpc = (x); m_r[l] = m_pc + 4; } while (0)
-#define RBYTE(x) (this->*m_cur->m_read_byte)(x)
-#define RWORD(x) (this->*m_cur->m_read_word)(x)
-#define RLONG(x) (this->*m_cur->m_read_dword)(x)
-
-#define WBYTE(x,v) (this->*m_cur->m_write_byte)(x, v)
-#define WWORD(x,v) (this->*m_cur->m_write_word)(x, v)
-#define WLONG(x,v) (this->*m_cur->m_write_dword)(x, v)
-
#define SR m_cpr[0][COP0_Status]
#define CAUSE m_cpr[0][COP0_Cause]
-
-//**************************************************************************
-// DEVICE INTERFACE
-//**************************************************************************
-
DEFINE_DEVICE_TYPE(R2000, r2000_device, "r2000", "MIPS R2000")
DEFINE_DEVICE_TYPE(R2000A, r2000a_device, "r2000a", "MIPS R2000A")
DEFINE_DEVICE_TYPE(R3000, r3000_device, "r3000", "MIPS R3000")
DEFINE_DEVICE_TYPE(R3000A, r3000a_device, "r3000a", "MIPS R3000A")
-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", "IDT R3041")
+DEFINE_DEVICE_TYPE(R3051, r3051_device, "r3051", "IDT R3051")
+DEFINE_DEVICE_TYPE(R3052, r3052_device, "r3052", "IDT R3052")
+DEFINE_DEVICE_TYPE(R3052E, r3052e_device, "r3052e", "IDT R3052E")
+DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "IDT R3071")
+DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "IDT R3081")
DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 IOP")
-
-//-------------------------------------------------
-// r3000_device_base - constructor
-//-------------------------------------------------
-
-r3000_device_base::r3000_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t cpurev, size_t icache_size, size_t dcache_size)
- : cpu_device(mconfig, type, tag, owner, clock),
- m_program_config_be("program", ENDIANNESS_BIG, 32, 29),
- m_program_config_le("program", ENDIANNESS_LITTLE, 32, 29),
- m_program(nullptr),
- m_cpurev(cpurev),
- m_hasfpu(false),
- m_fpurev(0),
- m_endianness(ENDIANNESS_BIG),
- m_pc(0),
- m_nextpc(0),
- m_hi(0),
- m_lo(0),
- m_ppc(0),
- m_op(0),
- m_icount(0),
- m_interrupt_cycles(0),
- m_icache_size(icache_size),
- m_dcache_size(dcache_size),
- m_in_brcond0(*this),
- m_in_brcond1(*this),
- m_in_brcond2(*this),
- m_in_brcond3(*this)
+mips1core_device_base::mips1core_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_program_config_be("program", ENDIANNESS_BIG, 32, 32)
+ , m_program_config_le("program", ENDIANNESS_LITTLE, 32, 32)
+ , m_icache_config("icache", ENDIANNESS_BIG, 32, 32)
+ , m_dcache_config("dcache", ENDIANNESS_BIG, 32, 32)
+ , m_cpurev(cpurev)
+ , m_hasfpu(false)
+ , m_fpurev(0)
+ , m_endianness(ENDIANNESS_BIG)
+ , m_pc(0)
+ , m_nextpc(0)
+ , m_ppc(0)
+ , m_icount(0)
+ , m_icache_size(icache_size)
+ , m_dcache_size(dcache_size)
+ , m_in_brcond{ *this, *this, *this, *this }
{
- // set our instruction counter
- set_icountptr(m_icount);
-
- // clear some additional state
- memset(m_r, 0, sizeof(m_r));
- memset(m_cpr, 0, sizeof(m_cpr));
- memset(m_ccr, 0, sizeof(m_ccr));
}
-
-//-------------------------------------------------
-// ~r3000_device_base - destructor
-//-------------------------------------------------
-
-r3000_device_base::~r3000_device_base()
+mips1_device_base::mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size)
+ : mips1core_device_base(mconfig, type, tag, owner, clock, cpurev, icache_size, dcache_size)
{
}
-//-------------------------------------------------
-// r2000_device - constructor
-//-------------------------------------------------
-
-r2000_device::r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R2000, tag, owner, clock, 0x0100, icache_size, dcache_size) { }
-
-//-------------------------------------------------
-// r2000a_device - constructor
-//-------------------------------------------------
-
-r2000a_device::r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R2000A, tag, owner, clock, 0x0216, icache_size, dcache_size) { }
-
-
-//-------------------------------------------------
-// r3000_device - constructor
-//-------------------------------------------------
-
-r3000_device::r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R3000, tag, owner, clock, 0x0220, icache_size, dcache_size) { }
-
-//-------------------------------------------------
-// r3000a_device - constructor
-//-------------------------------------------------
-
-r3000a_device::r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R3000A, tag, owner, clock, 0x0230, icache_size, dcache_size) { }
-
-
-//-------------------------------------------------
-// r3041_device - constructor
-//-------------------------------------------------
-
-r3041_device::r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : r3000_device_base(mconfig, R3041, tag, owner, clock, 0x0700, 2048, 512) { }
-
-
-//-------------------------------------------------
-// r3051_device - constructor
-//-------------------------------------------------
-
-r3051_device::r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : r3000_device_base(mconfig, R3051, tag, owner, clock, 0x0200, 4096, 2048) { }
-
-
-//-------------------------------------------------
-// r3052_device - constructor
-//-------------------------------------------------
-
-r3052_device::r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : r3000_device_base(mconfig, R3052, tag, owner, clock, 0x0200, 8192, 2048) { }
-
-
-//-------------------------------------------------
-// r3071_device - constructor
-//-------------------------------------------------
-
-r3071_device::r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size) { }
-
-
-//-------------------------------------------------
-// r3081_device - constructor
-//-------------------------------------------------
-
-r3081_device::r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size, size_t dcache_size)
- : r3000_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size)
+r2000_device::r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1_device_base(mconfig, R2000, tag, owner, clock, 0x0100, icache_size, dcache_size)
{
- set_fpurev(0x0300);
}
-
-//-------------------------------------------------
-// iop_device - constructor
-//-------------------------------------------------
-
-iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : r3000_device_base(mconfig, SONYPS2_IOP, tag, owner, clock, 0x001f, 4096, 1024)
+r2000a_device::r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1_device_base(mconfig, R2000A, tag, owner, clock, 0x0216, icache_size, dcache_size)
{
- m_endianness = ENDIANNESS_LITTLE;
}
-
-//-------------------------------------------------
-// device_start - start up the device
-//-------------------------------------------------
-
-void r3000_device_base::device_start()
+r3000_device::r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1_device_base(mconfig, R3000, tag, owner, clock, 0x0220, icache_size, dcache_size)
{
- // get our address spaces
- 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); };
- }
- 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); };
- }
-
- // allocate cache memory
- m_icache.resize(m_icache_size/4);
- m_dcache.resize(m_dcache_size/4);
-
- m_cache = &m_dcache[0];
- m_cache_size = m_dcache_size;
-
- // set up memory handlers
- m_memory_hand.m_read_byte = &r3000_device_base::readmem;
- m_memory_hand.m_read_word = &r3000_device_base::readmem_word;
- m_memory_hand.m_read_dword = &r3000_device_base::readmem_dword;
- m_memory_hand.m_write_byte = &r3000_device_base::writemem;
- m_memory_hand.m_write_word = &r3000_device_base::writemem_word;
- m_memory_hand.m_write_dword = &r3000_device_base::writemem_dword;
-
- if (m_endianness == ENDIANNESS_BIG)
- {
- m_lwl = &r3000_device_base::lwl_be;
- m_lwr = &r3000_device_base::lwr_be;
- m_swl = &r3000_device_base::swl_be;
- m_swr = &r3000_device_base::swr_be;
-
- m_cache_hand.m_read_byte = &r3000_device_base::readcache_be;
- m_cache_hand.m_read_word = &r3000_device_base::readcache_be_word;
- m_cache_hand.m_read_dword = &r3000_device_base::readcache_be_dword;
- m_cache_hand.m_write_byte = &r3000_device_base::writecache_be;
- m_cache_hand.m_write_word = &r3000_device_base::writecache_be_word;
- m_cache_hand.m_write_dword = &r3000_device_base::writecache_be_dword;
- }
- else
- {
- m_lwl = &r3000_device_base::lwl_le;
- m_lwr = &r3000_device_base::lwr_le;
- m_swl = &r3000_device_base::swl_le;
- m_swr = &r3000_device_base::swr_le;
-
- m_cache_hand.m_read_byte = &r3000_device_base::readcache_le;
- m_cache_hand.m_read_word = &r3000_device_base::readcache_le_word;
- m_cache_hand.m_read_dword = &r3000_device_base::readcache_le_dword;
- m_cache_hand.m_write_byte = &r3000_device_base::writecache_le;
- m_cache_hand.m_write_word = &r3000_device_base::writecache_le_word;
- m_cache_hand.m_write_dword = &r3000_device_base::writecache_le_dword;
- }
-
- // resolve conditional branch input handlers
- m_in_brcond0.resolve_safe(0);
- m_in_brcond1.resolve_safe(0);
- m_in_brcond2.resolve_safe(0);
- m_in_brcond3.resolve_safe(0);
-
- // register our state for the debugger
- state_add(STATE_GENPC, "GENPC", m_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow();
- state_add(STATE_GENSP, "GENSP", m_r[31]).noshow();
- state_add(STATE_GENFLAGS, "GENFLAGS", SR).callimport().callexport().formatstr("%6s").noshow();
- state_add(R3000_PC, "PC", m_pc);
- state_add(R3000_SR, "SR", SR);
- state_add(R3000_R0, "R0", m_r[0]);
- state_add(R3000_R1, "R1", m_r[1]);
- state_add(R3000_R2, "R2", m_r[2]);
- state_add(R3000_R3, "R3", m_r[3]);
- state_add(R3000_R4, "R4", m_r[4]);
- state_add(R3000_R5, "R5", m_r[5]);
- state_add(R3000_R6, "R6", m_r[6]);
- state_add(R3000_R7, "R7", m_r[7]);
- state_add(R3000_R8, "R8", m_r[8]);
- state_add(R3000_R9, "R9", m_r[9]);
- state_add(R3000_R10, "R10", m_r[10]);
- state_add(R3000_R11, "R11", m_r[11]);
- state_add(R3000_R12, "R12", m_r[12]);
- state_add(R3000_R13, "R13", m_r[13]);
- state_add(R3000_R14, "R14", m_r[14]);
- state_add(R3000_R15, "R15", m_r[15]);
- state_add(R3000_R16, "R16", m_r[16]);
- state_add(R3000_R17, "R17", m_r[17]);
- state_add(R3000_R18, "R18", m_r[18]);
- state_add(R3000_R19, "R19", m_r[19]);
- state_add(R3000_R20, "R20", m_r[20]);
- state_add(R3000_R21, "R21", m_r[21]);
- state_add(R3000_R22, "R22", m_r[22]);
- state_add(R3000_R23, "R23", m_r[23]);
- state_add(R3000_R24, "R24", m_r[24]);
- state_add(R3000_R25, "R25", m_r[25]);
- state_add(R3000_R26, "R26", m_r[26]);
- state_add(R3000_R27, "R27", m_r[27]);
- state_add(R3000_R28, "R28", m_r[28]);
- state_add(R3000_R29, "R29", m_r[29]);
- state_add(R3000_R30, "R30", m_r[30]);
- state_add(R3000_R31, "R31", m_r[31]);
-
- // register our state for saving
- save_item(NAME(m_pc));
- save_item(NAME(m_nextpc));
- save_item(NAME(m_hi));
- save_item(NAME(m_lo));
- save_item(NAME(m_r));
- save_item(NAME(m_cpr));
- save_item(NAME(m_ccr));
- save_item(NAME(m_ppc));
- save_item(NAME(m_op));
- save_item(NAME(m_interrupt_cycles));
- save_item(NAME(m_icache));
- save_item(NAME(m_dcache));
-
- // initialise cpu and fpu id registers
- m_cpr[0][COP0_PRId] = m_cpurev;
- m_ccr[1][0] = m_fpurev;
}
-//-------------------------------------------------
-// device_post_load -
-//-------------------------------------------------
-void r3000_device_base::device_post_load()
+r3000a_device::r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1_device_base(mconfig, R3000A, tag, owner, clock, 0x0230, icache_size, dcache_size)
{
- if (m_cpr[0][COP0_Status] & SR_IsC)
- m_cur = &m_cache_hand;
- else
- m_cur = &m_memory_hand;
}
-
-//-------------------------------------------------
-// device_reset - reset the device
-//-------------------------------------------------
-
-void r3000_device_base::device_reset()
+r3041_device::r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mips1core_device_base(mconfig, R3041, tag, owner, clock, 0x0700, 2048, 512)
{
- // initialize the rest of the config
- m_cur = &m_memory_hand;
-
- // initialize the state
- m_pc = 0xbfc00000;
- m_nextpc = ~0;
- m_cpr[0][COP0_Status] = 0x0000;
}
-
-//-------------------------------------------------
-// memory_space_config - return the configuration
-// of the specified address space, or nullptr if
-// the space doesn't exist
-//-------------------------------------------------
-
-device_memory_interface::space_config_vector r3000_device_base::memory_space_config() const
+r3051_device::r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mips1core_device_base(mconfig, R3051, tag, owner, clock, 0x0200, 4096, 2048)
{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, (m_endianness == ENDIANNESS_BIG) ? &m_program_config_be : &m_program_config_le)
- };
}
-
-//-------------------------------------------------
-// state_import - import state into the device,
-// after it has been set
-//-------------------------------------------------
-
-void r3000_device_base::state_import(const device_state_entry &entry)
+r3052_device::r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mips1core_device_base(mconfig, R3052, tag, owner, clock, 0x0200, 8192, 2048)
{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- break;
-
- default:
- fatalerror("r3000_device_base::state_import called for unexpected value\n");
- }
}
-
-//-------------------------------------------------
-// state_export - export state out of the device
-//-------------------------------------------------
-
-void r3000_device_base::state_export(const device_state_entry &entry)
+r3052e_device::r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mips1_device_base(mconfig, R3052E, tag, owner, clock, 0x0200, 8192, 2048)
{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- break;
-
- default:
- fatalerror("r3000_device_base::state_export called for unexpected value\n");
- }
}
-
-//-------------------------------------------------
-// state_string_export - export state as a string
-// for the debugger
-//-------------------------------------------------
-
-void r3000_device_base::state_string_export(const device_state_entry &entry, std::string &str) const
+r3071_device::r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1core_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size)
{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- break;
- }
}
-
-//-------------------------------------------------
-// disassemble - call the disassembly
-// helper function
-//-------------------------------------------------
-
-std::unique_ptr<util::disasm_interface> r3000_device_base::create_disassembler()
+r3081_device::r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
+ : mips1core_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size)
{
- return std::make_unique<r3000_disassembler>();
+ set_fpurev(0x0300);
}
-
-/***************************************************************************
- MEMORY ACCESSORS
-***************************************************************************/
-
-inline uint32_t r3000_device_base::readop(offs_t pc)
+iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mips1core_device_base(mconfig, SONYPS2_IOP, tag, owner, clock, 0x001f, 4096, 1024)
{
- return m_pr32(pc);
+ m_endianness = ENDIANNESS_LITTLE;
}
-uint8_t r3000_device_base::readmem(offs_t offset)
+/*
+ * Two additional address spaces are defined to represent the instruction and
+ * data caches. These are only used to simulate cache isolation functionality
+ * at this point, but could simulate other behaviour as needed in future.
+ */
+void mips1core_device_base::device_add_mconfig(machine_config &config)
{
- if (SR & SR_IsC)
- return 0;
- return m_program->read_byte(offset);
+ set_addrmap(1, &mips1core_device_base::icache_map);
+ set_addrmap(2, &mips1core_device_base::dcache_map);
}
-uint16_t r3000_device_base::readmem_word(offs_t offset)
+void mips1core_device_base::icache_map(address_map &map)
{
- if (SR & SR_IsC)
- return 0;
- return m_program->read_word(offset);
+ map(0, m_icache_size - 1).ram().mirror(~(m_icache_size - 1));
}
-uint32_t r3000_device_base::readmem_dword(offs_t offset)
+void mips1core_device_base::dcache_map(address_map &map)
{
- if (SR & SR_IsC)
- return 0;
- return m_program->read_dword(offset);
+ map(0, m_dcache_size - 1).ram().mirror(~(m_dcache_size - 1));
}
-void r3000_device_base::writemem(offs_t offset, uint8_t data)
+void mips1core_device_base::device_start()
{
- if (SR & SR_IsC)
- return;
- m_program->write_byte(offset, data);
-}
+ // set our instruction counter
+ set_icountptr(m_icount);
-void r3000_device_base::writemem_word(offs_t offset, uint16_t data)
-{
- if (SR & SR_IsC)
- return;
- m_program->write_word(offset, data);
-}
+ // resolve conditional branch input handlers
+ for (devcb_read_line &cb : m_in_brcond)
+ cb.resolve_safe(0);
-void r3000_device_base::writemem_dword(offs_t offset, uint32_t data)
-{
- if (SR & SR_IsC)
- return;
- m_program->write_dword(offset, data);
-}
+ // register our state for the debugger
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[31]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_cpr[0][COP0_Status]).noshow();
+ state_add(MIPS1_PC, "PC", m_pc);
+ state_add(MIPS1_COP0_SR, "SR", m_cpr[0][COP0_Status]);
-/***************************************************************************
- BIG ENDIAN CACHE I/O
-***************************************************************************/
+ for (int i = 0; i < 32; i++)
+ state_add(MIPS1_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]);
-uint8_t r3000_device_base::readcache_be(offs_t offset)
-{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? m_cache[BYTE4_XOR_BE(offset)] : 0xff;
-}
+ state_add(MIPS1_HI, "HI", m_hi);
+ state_add(MIPS1_LO, "LO", m_lo);
+ state_add(MIPS1_COP0_BADVADDR, "BadVAddr", m_cpr[0][COP0_BadVAddr]);
+ state_add(MIPS1_COP0_CAUSE, "Cause", m_cpr[0][COP0_Cause]);
+ state_add(MIPS1_COP0_EPC, "EPC", m_cpr[0][COP0_EPC]);
-uint16_t r3000_device_base::readcache_be_word(offs_t offset)
-{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? *(uint16_t *)&m_cache[WORD_XOR_BE(offset)] : 0xffff;
-}
+ // register our state for saving
+ save_item(NAME(m_pc));
+ save_item(NAME(m_nextpc));
+ save_item(NAME(m_hi));
+ save_item(NAME(m_lo));
+ save_item(NAME(m_r));
+ save_item(NAME(m_cpr));
+ save_item(NAME(m_ccr));
+ save_item(NAME(m_ppc));
-uint32_t r3000_device_base::readcache_be_dword(offs_t offset)
-{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? *(uint32_t *)&m_cache[offset] : 0xffffffff;
+ // initialise cpu and fpu id registers
+ m_cpr[0][COP0_PRId] = m_cpurev;
+ m_ccr[1][0] = m_fpurev;
}
-void r3000_device_base::writecache_be(offs_t offset, uint8_t data)
+void mips1_device_base::device_start()
{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) m_cache[BYTE4_XOR_BE(offset)] = data;
-}
+ mips1core_device_base::device_start();
-void r3000_device_base::writecache_be_word(offs_t offset, uint16_t data)
-{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) *(uint16_t *)&m_cache[WORD_XOR_BE(offset)] = data;
-}
+ // cop0 tlb registers
+ state_add(MIPS1_COP0_INDEX, "Index", m_cpr[0][COP0_Index]);
+ state_add(MIPS1_COP0_RANDOM, "Random", m_cpr[0][COP0_Random]);
+ state_add(MIPS1_COP0_ENTRYLO, "EntryLo", m_cpr[0][COP0_EntryLo]);
+ state_add(MIPS1_COP0_ENTRYHI, "EntryHi", m_cpr[0][COP0_EntryHi]);
+ state_add(MIPS1_COP0_CONTEXT, "Context", m_cpr[0][COP0_Context]);
-void r3000_device_base::writecache_be_dword(offs_t offset, uint32_t data)
-{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) *(uint32_t *)&m_cache[offset] = data;
+ save_item(NAME(m_reset_time));
+ save_item(NAME(m_tlb));
}
-uint8_t r3000_device_base::readcache_le(offs_t offset)
+void r3041_device::device_start()
{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? m_cache[BYTE4_XOR_LE(offset)] : 0xff;
+ mips1core_device_base::device_start();
+
+ // cop0 r3041 registers
+ state_add(MIPS1_COP0_BUSCTRL, "BusCtrl", m_cpr[0][COP0_BusCtrl]);
+ state_add(MIPS1_COP0_CONFIG, "Config", m_cpr[0][COP0_Config]);
+ state_add(MIPS1_COP0_COUNT, "Count", m_cpr[0][COP0_Count]);
+ state_add(MIPS1_COP0_PORTSIZE, "PortSize", m_cpr[0][COP0_PortSize]);
+ state_add(MIPS1_COP0_COMPARE, "Compare", m_cpr[0][COP0_Compare]);
}
+void mips1core_device_base::device_reset()
+{
+ // initialize the state
+ m_pc = 0xbfc00000;
+ m_nextpc = ~0;
-/***************************************************************************
- LITTLE ENDIAN CACHE I/O
-***************************************************************************/
+ // non-tlb devices have tlb shut down
+ m_cpr[0][COP0_Status] = SR_BEV | SR_TS;
-uint16_t r3000_device_base::readcache_le_word(offs_t offset)
-{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? *(uint16_t *)&m_cache[WORD_XOR_LE(offset)] : 0xffff;
+ m_data_spacenum = 0;
}
-uint32_t r3000_device_base::readcache_le_dword(offs_t offset)
+void mips1_device_base::device_reset()
{
- offset &= 0x1fffffff;
- return (offset * 4 < m_cache_size) ? *(uint32_t *)&m_cache[offset] : 0xffffffff;
-}
+ mips1core_device_base::device_reset();
-void r3000_device_base::writecache_le(offs_t offset, uint8_t data)
-{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) m_cache[BYTE4_XOR_LE(offset)] = data;
+ // tlb is not shut down
+ m_cpr[0][COP0_Status] &= ~SR_TS;
+
+ m_reset_time = total_cycles();
}
-void r3000_device_base::writecache_le_word(offs_t offset, uint16_t data)
+device_memory_interface::space_config_vector mips1core_device_base::memory_space_config() const
{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) *(uint16_t *)&m_cache[WORD_XOR_LE(offset)] = data;
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, (m_endianness == ENDIANNESS_BIG) ? &m_program_config_be : &m_program_config_le),
+ std::make_pair(1, &m_icache_config),
+ std::make_pair(2, &m_dcache_config)
+ };
}
-void r3000_device_base::writecache_le_dword(offs_t offset, uint32_t data)
+std::unique_ptr<util::disasm_interface> mips1core_device_base::create_disassembler()
{
- offset &= 0x1fffffff;
- if (offset * 4 < m_cache_size) *(uint32_t *)&m_cache[offset] = data;
+ return std::make_unique<mips1_disassembler>();
}
-
-/***************************************************************************
- EXECEPTION HANDLING
-***************************************************************************/
-
-inline void r3000_device_base::generate_exception(int exception, bool backup)
+void mips1core_device_base::generate_exception(int exception)
{
// set the exception PC
- m_cpr[0][COP0_EPC] = backup ? m_ppc : m_pc;
+ m_cpr[0][COP0_EPC] = (exception == EXCEPTION_INTERRUPT) ? m_pc : m_ppc;
// put the cause in the low 8 bits and clear the branch delay flag
CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
@@ -647,36 +290,22 @@ inline void r3000_device_base::generate_exception(int exception, bool backup)
// shift the exception bits
SR = (SR & 0xffffffc0) | ((SR << 2) & 0x3c);
- // based on the BEV bit, we either go to ROM or RAM
- bool bev = (SR & SR_BEV) ? true : false;
- m_pc = bev ? 0xbfc00000 : 0x80000000;
-
- // most exceptions go to offset 0x180, except for TLB stuff and syscall (if BEV is unset)
- if ((exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE) || !bev)
- m_pc += 0x80;
+ // only tlb misses on kuseg have dedicated vectors
+ if ((exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE) && !BIT(m_cpr[0][COP0_BadVAddr], 31))
+ m_pc = (SR & SR_BEV) ? 0xbfc00100 : 0x80000000;
else
- m_pc += 0x180;
-}
-
+ m_pc = (SR & SR_BEV) ? 0xbfc00180 : 0x80000080;
-inline void r3000_device_base::invalid_instruction()
-{
- generate_exception(EXCEPTION_INVALIDOP, true);
+ debugger_exception_hook(exception);
}
-
-/***************************************************************************
- IRQ HANDLING
-***************************************************************************/
-
-void r3000_device_base::check_irqs()
+void mips1core_device_base::check_irqs()
{
if ((CAUSE & SR & 0xff00) && (SR & SR_IEc))
- generate_exception(EXCEPTION_INTERRUPT, false);
+ generate_exception(EXCEPTION_INTERRUPT);
}
-
-void r3000_device_base::set_irq_line(int irqline, int state)
+void mips1core_device_base::set_irq_line(int irqline, int state)
{
if (state != CLEAR_LINE)
CAUSE |= 0x400 << irqline;
@@ -686,85 +315,59 @@ void r3000_device_base::set_irq_line(int irqline, int state)
check_irqs();
}
+u32 mips1core_device_base::get_cop0_reg(int const index)
+{
+ return m_cpr[0][index];
+}
-/***************************************************************************
- COP0 (SYSTEM) EXECUTION HANDLING
-***************************************************************************/
-
-inline uint32_t r3000_device_base::get_cop0_reg(int idx)
+u32 mips1_device_base::get_cop0_reg(int const index)
{
- return m_cpr[0][idx];
+ // assume 64-entry tlb with 8 wired entries
+ if (index == COP0_Random)
+ m_cpr[0][index] = (63 - ((total_cycles() - m_reset_time) % 56)) << 8;
+
+ return m_cpr[0][index];
}
-inline void r3000_device_base::set_cop0_reg(int idx, uint32_t val)
+void mips1core_device_base::set_cop0_reg(int const index, u32 const data)
{
- if (idx == COP0_Cause)
+ if (index == COP0_Cause)
{
- CAUSE = (CAUSE & 0xfc00) | (val & ~0xfc00);
+ CAUSE = (CAUSE & 0xfc00) | (data & ~0xfc00);
// update interrupts -- software ints can occur this way
check_irqs();
}
- else if (idx == COP0_Status)
+ else if (index == COP0_Status)
{
- uint32_t oldsr = m_cpr[0][idx];
- uint32_t diff = oldsr ^ val;
+ m_cpr[0][index] = data;
- // handle cache isolation
- if (diff & SR_IsC)
- {
- if (val & SR_IsC)
- m_cur = &m_cache_hand;
- else
- m_cur = &m_memory_hand;
- }
-
- // handle cache switching
- if (diff & SR_SwC)
- {
- if (val & SR_SwC)
- m_cache = &m_icache[0], m_cache_size = m_icache_size;
- else
- m_cache = &m_dcache[0], m_cache_size = m_dcache_size;
- }
- m_cpr[0][idx] = val;
+ // handle cache isolation and swap
+ m_data_spacenum = (data & SR_IsC) ? ((data & SR_SwC) ? 1 : 2) : 0;
// update interrupts
check_irqs();
}
- else if (idx != COP0_PRId)
- m_cpr[0][idx] = val;
-}
-
-inline uint32_t r3000_device_base::get_cop0_creg(int idx)
-{
- return m_ccr[0][idx];
+ else if (index != COP0_PRId)
+ m_cpr[0][index] = data;
}
-inline void r3000_device_base::set_cop0_creg(int idx, uint32_t val)
+void mips1core_device_base::handle_cop0(u32 const op)
{
- m_ccr[0][idx] = val;
-}
-
-inline void r3000_device_base::handle_cop0()
-{
- if (!(SR & SR_COP0) && (SR & SR_KUc))
- generate_exception(EXCEPTION_BADCOP, true);
-
switch (RSREG)
{
- case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop0_reg(RDREG); break;
- case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop0_creg(RDREG); break;
- case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL); break;
- case 0x06: /* CTCz */ set_cop0_creg(RDREG, RTVAL); break;
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop0_reg(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<0>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop_creg<0>(RDREG, RTVAL); break;
case 0x08: /* BC */
switch (RTREG)
{
- case 0x00: /* BCzF */ if (!m_in_brcond0()) ADDPC(SIMMVAL); break;
- case 0x01: /* BCzT */ if (m_in_brcond0()) ADDPC(SIMMVAL); break;
- case 0x02: /* BCzFL */ invalid_instruction(); break;
- case 0x03: /* BCzTL */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x00: /* BCzF */ if (!m_in_brcond[0]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[0]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
case 0x10:
@@ -783,134 +386,103 @@ inline void r3000_device_base::handle_cop0()
case 0x1d:
case 0x1e:
case 0x1f: /* COP */
- switch (m_op & 0x01ffffff)
+ switch (op & 0x01ffffff)
{
- case 0x01: /* TLBR */ break;
- case 0x02: /* TLBWI */ break;
- case 0x06: /* TLBWR */ break;
- case 0x08: /* TLBP */ break;
+ case 0x01: /* TLBR */ break;
+ case 0x02: /* TLBWI */ break;
+ case 0x06: /* TLBWR */ break;
+ case 0x08: /* TLBP */ break;
case 0x10: /* RFE */ SR = (SR & 0xfffffff0) | ((SR >> 2) & 0x0f); break;
- case 0x18: /* ERET */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x18: /* ERET */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
- default: invalid_instruction(); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
}
-
-/***************************************************************************
- COP1 (FPU) EXECUTION HANDLING
-***************************************************************************/
-
-inline uint32_t r3000_device_base::get_cop1_reg(int idx)
-{
- return m_cpr[1][idx];
-}
-
-inline void r3000_device_base::set_cop1_reg(int idx, uint32_t val)
+void mips1_device_base::handle_cop0(u32 const op)
{
- m_cpr[1][idx] = val;
-}
+ switch (op)
+ {
+ case 0x42000001: // TLBR - read tlb
+ {
+ u8 const index = (m_cpr[0][COP0_Index] >> 8) & 0x3f;
-inline uint32_t r3000_device_base::get_cop1_creg(int idx)
-{
- return m_ccr[1][idx];
-}
+ m_cpr[0][COP0_EntryHi] = m_tlb[index][0];
+ m_cpr[0][COP0_EntryLo] = m_tlb[index][1];
+ }
+ break;
-inline void r3000_device_base::set_cop1_creg(int idx, uint32_t val)
-{
- if (idx)
- m_ccr[1][idx] = val;
-}
+ case 0x42000002: // TLBWI - write tlb (indexed)
+ {
+ u8 const index = (m_cpr[0][COP0_Index] >> 8) & 0x3f;
-inline void r3000_device_base::handle_cop1()
-{
- if (!(SR & SR_COP1))
- generate_exception(EXCEPTION_BADCOP, true);
- if (!m_hasfpu)
- return;
+ m_tlb[index][0] = m_cpr[0][COP0_EntryHi];
+ m_tlb[index][1] = m_cpr[0][COP0_EntryLo];
- switch (RSREG)
- {
- case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop1_reg(RDREG); break;
- case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop1_creg(RDREG); break;
- case 0x04: /* MTCz */ set_cop1_reg(RDREG, RTVAL); break;
- case 0x06: /* CTCz */ set_cop1_creg(RDREG, RTVAL); break;
- case 0x08: /* BC */
- switch (RTREG)
- {
- case 0x00: /* BCzF */ if (!m_in_brcond1()) ADDPC(SIMMVAL); break;
- case 0x01: /* BCzT */ if (m_in_brcond1()) ADDPC(SIMMVAL); break;
- case 0x02: /* BCzFL */ invalid_instruction(); break;
- case 0x03: /* BCzTL */ invalid_instruction(); break;
- default: invalid_instruction(); break;
- }
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- case 0x1f: /* COP */ invalid_instruction(); break;
- default: invalid_instruction(); break;
- }
-}
+ LOGMASKED(LOG_TLB, "tlb index %d program 0x%08x physical 0x%08x\n",
+ index, m_cpr[0][COP0_EntryHi] & ~0xfff, m_cpr[0][COP0_EntryLo] & ~0xfff);
+ }
+ break;
+ case 0x42000006: // TLBWR - write tlb (random)
+ {
+ u8 const random = get_cop0_reg(COP0_Random) >> 8;
-/***************************************************************************
- COP2 (CUSTOM) EXECUTION HANDLING
-***************************************************************************/
+ m_tlb[random][0] = m_cpr[0][COP0_EntryHi];
+ m_tlb[random][1] = m_cpr[0][COP0_EntryLo];
-inline uint32_t r3000_device_base::get_cop2_reg(int idx)
-{
- return m_cpr[2][idx];
-}
+ LOGMASKED(LOG_TLB, "tlb random %d program 0x%08x physical 0x%08x\n",
+ random, m_cpr[0][COP0_EntryHi] & ~0xfff, m_cpr[0][COP0_EntryLo] & ~0xfff);
+ }
+ break;
-inline void r3000_device_base::set_cop2_reg(int idx, uint32_t val)
-{
- m_cpr[2][idx] = val;
-}
+ case 0x42000008: // TLBP - probe tlb
+ m_cpr[0][COP0_Index] = 0x80000000;
+ for (u8 index = 0; index < 64; index++)
+ {
+ // test vpn and optionally asid
+ u32 const mask = (m_tlb[index][1] & EL_G) ? EH_VPN : EH_VPN | EH_ASID;
+ if ((m_tlb[index][0] & mask) == (m_cpr[0][COP0_EntryHi] & mask))
+ {
+ m_cpr[0][COP0_Index] = index << 8;
+ break;
+ }
+ }
+ break;
-inline uint32_t r3000_device_base::get_cop2_creg(int idx)
-{
- return m_ccr[2][idx];
+ default:
+ mips1core_device_base::handle_cop0(op);
+ }
}
-inline void r3000_device_base::set_cop2_creg(int idx, uint32_t val)
+void mips1core_device_base::set_cop1_creg(int idx, u32 val)
{
- m_ccr[2][idx] = val;
+ // fpu revision register is read-only
+ if (idx)
+ m_ccr[1][idx] = val;
}
-inline void r3000_device_base::handle_cop2()
+void mips1core_device_base::handle_cop1(u32 const op)
{
- if (!(SR & SR_COP2))
- generate_exception(EXCEPTION_BADCOP, true);
+ if (!m_hasfpu)
+ return;
switch (RSREG)
{
- case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop2_reg(RDREG); break;
- case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop2_creg(RDREG); break;
- case 0x04: /* MTCz */ set_cop2_reg(RDREG, RTVAL); break;
- case 0x06: /* CTCz */ set_cop2_creg(RDREG, RTVAL); break;
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop_reg<1>(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<1>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop_reg<1>(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop1_creg(RDREG, RTVAL); break;
case 0x08: /* BC */
switch (RTREG)
{
- case 0x00: /* BCzF */ if (!m_in_brcond2()) ADDPC(SIMMVAL); break;
- case 0x01: /* BCzT */ if (m_in_brcond2()) ADDPC(SIMMVAL); break;
- case 0x02: /* BCzFL */ invalid_instruction(); break;
- case 0x03: /* BCzTL */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x00: /* BCzF */ if (!m_in_brcond[1]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[1]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
case 0x10:
@@ -928,55 +500,27 @@ inline void r3000_device_base::handle_cop2()
case 0x1c:
case 0x1d:
case 0x1e:
- case 0x1f: /* COP */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x1f: /* COP */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
}
-
-/***************************************************************************
- COP3 (CUSTOM) EXECUTION HANDLING
-***************************************************************************/
-
-inline uint32_t r3000_device_base::get_cop3_reg(int idx)
-{
- return m_cpr[3][idx];
-}
-
-inline void r3000_device_base::set_cop3_reg(int idx, uint32_t val)
-{
- m_cpr[3][idx] = val;
-}
-
-inline uint32_t r3000_device_base::get_cop3_creg(int idx)
-{
- return m_ccr[3][idx];
-}
-
-inline void r3000_device_base::set_cop3_creg(int idx, uint32_t val)
-{
- m_ccr[3][idx] = val;
-}
-
-inline void r3000_device_base::handle_cop3()
+template <unsigned Coprocessor> void mips1core_device_base::handle_cop(u32 const op)
{
- if (!(SR & SR_COP3))
- generate_exception(EXCEPTION_BADCOP, true);
-
switch (RSREG)
{
- case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop3_reg(RDREG); break;
- case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop3_creg(RDREG); break;
- case 0x04: /* MTCz */ set_cop3_reg(RDREG, RTVAL); break;
- case 0x06: /* CTCz */ set_cop3_creg(RDREG, RTVAL); break;
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop_reg<Coprocessor>(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<Coprocessor>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop_reg<Coprocessor>(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop_creg<Coprocessor>(RDREG, RTVAL); break;
case 0x08: /* BC */
switch (RTREG)
{
- case 0x00: /* BCzF */ if (!m_in_brcond3()) ADDPC(SIMMVAL); break;
- case 0x01: /* BCzT */ if (m_in_brcond3()) ADDPC(SIMMVAL); break;
- case 0x02: /* BCzFL */ invalid_instruction(); break;
- case 0x03: /* BCzTL */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x00: /* BCzF */ if (!m_in_brcond[Coprocessor]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[Coprocessor]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
case 0x10:
@@ -994,78 +538,19 @@ inline void r3000_device_base::handle_cop3()
case 0x1c:
case 0x1d:
case 0x1e:
- case 0x1f: /* COP */ invalid_instruction(); break;
- default: invalid_instruction(); break;
+ case 0x1f: /* COP */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
}
-
-/***************************************************************************
- CORE EXECUTION LOOP
-***************************************************************************/
-
-//-------------------------------------------------
-// execute_min_cycles - return minimum number of
-// cycles it takes for one instruction to execute
-//-------------------------------------------------
-
-uint32_t r3000_device_base::execute_min_cycles() const
-{
- return 1;
-}
-
-
-//-------------------------------------------------
-// execute_max_cycles - return maximum number of
-// cycles it takes for one instruction to execute
-//-------------------------------------------------
-
-uint32_t r3000_device_base::execute_max_cycles() const
-{
- return 40;
-}
-
-
-//-------------------------------------------------
-// execute_input_lines - return the number of
-// input/interrupt lines
-//-------------------------------------------------
-
-uint32_t r3000_device_base::execute_input_lines() const
-{
- return 6;
-}
-
-
-//-------------------------------------------------
-// execute_set_input
-//-------------------------------------------------
-
-void r3000_device_base::execute_set_input(int inputnum, int state)
-{
- set_irq_line(inputnum, state);
-}
-
-
-//-------------------------------------------------
-// execute_run
-//-------------------------------------------------
-
-void r3000_device_base::execute_run()
+void mips1core_device_base::execute_run()
{
- // count cycles and interrupt cycles
- m_icount -= m_interrupt_cycles;
- m_interrupt_cycles = 0;
-
// check for IRQs
check_irqs();
// core execution loop
do
{
- uint64_t temp64;
- int temp;
-
// debugging
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
@@ -1073,13 +558,13 @@ void r3000_device_base::execute_run()
#if ENABLE_IOP_KPUTS
if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C)
{
- uint32_t ptr = m_r[5];
- uint32_t length = m_r[6];
+ u32 ptr = m_r[5];
+ u32 length = m_r[6];
if (length >= 4096)
length = 4095;
while (length)
{
- printf("%c", (char)RBYTE(ptr));
+ load<u8>(ptr, [this](char c) { printf("%c", c); });
ptr++;
length--;
}
@@ -1087,56 +572,63 @@ void r3000_device_base::execute_run()
}
#endif
- // instruction fetch
- m_op = readop(m_pc);
-
- // adjust for next PC
- if (m_nextpc != ~0)
+ // fetch and execute instruction
+ fetch(m_pc, [this](u32 const op)
{
- m_pc = m_nextpc;
- m_nextpc = ~0;
- }
- else
- m_pc += 4;
+ {
+ // adjust for next PC
+ if (m_nextpc != ~0)
+ {
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+ }
+ else
+ m_pc += 4;
- // parse the instruction
- switch (m_op >> 26)
- {
- case 0x00: /* SPECIAL */
- switch (m_op & 63)
+ // parse the instruction
+ switch (op >> 26)
{
- case 0x00: /* SLL */ if (RDREG) RDVAL = RTVAL << SHIFT; break;
- case 0x02: /* SRL */ if (RDREG) RDVAL = RTVAL >> SHIFT; break;
- case 0x03: /* SRA */ if (RDREG) RDVAL = (int32_t)RTVAL >> SHIFT; break;
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: /* SLL */ if (RDREG) RDVAL = RTVAL << SHIFT; break;
+ case 0x02: /* SRL */ if (RDREG) RDVAL = RTVAL >> SHIFT; break;
+ case 0x03: /* SRA */ if (RDREG) RDVAL = s32(RTVAL) >> SHIFT; break;
case 0x04: /* SLLV */ if (RDREG) RDVAL = RTVAL << (RSVAL & 31); break;
case 0x06: /* SRLV */ if (RDREG) RDVAL = RTVAL >> (RSVAL & 31); break;
- case 0x07: /* SRAV */ if (RDREG) RDVAL = (int32_t)RTVAL >> (RSVAL & 31); break;
- case 0x08: /* JR */ SETPC(RSVAL); break;
- case 0x09: /* JALR */ SETPCL(RSVAL, RDREG); break;
- case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL, true); break;
- case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK, true); break;
- case 0x0f: /* SYNC */ invalid_instruction(); break;
- case 0x10: /* MFHI */ if (RDREG) RDVAL = m_hi; break;
- case 0x11: /* MTHI */ m_hi = RSVAL; break;
- case 0x12: /* MFLO */ if (RDREG) RDVAL = m_lo; break;
- case 0x13: /* MTLO */ m_lo = RSVAL; break;
+ case 0x07: /* SRAV */ if (RDREG) RDVAL = s32(RTVAL) >> (RSVAL & 31); break;
+ case 0x08: /* JR */ SETPC(RSVAL); break;
+ case 0x09: /* JALR */ SETPCL(RSVAL, RDREG); break;
+ case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL); break;
+ case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK); break;
+ case 0x0f: /* SYNC */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x10: /* MFHI */ if (RDREG) RDVAL = m_hi; break;
+ case 0x11: /* MTHI */ m_hi = RSVAL; break;
+ case 0x12: /* MFLO */ if (RDREG) RDVAL = m_lo; break;
+ case 0x13: /* MTLO */ m_lo = RSVAL; break;
case 0x18: /* MULT */
- temp64 = (int64_t)(int32_t)RSVAL * (int64_t)(int32_t)RTVAL;
- m_lo = (uint32_t)temp64;
- m_hi = (uint32_t)(temp64 >> 32);
+ {
+ u64 product = mul_32x32(RSVAL, RTVAL);
+
+ m_lo = product;
+ m_hi = product >> 32;
m_icount -= 11;
- break;
+ }
+ break;
case 0x19: /* MULTU */
- temp64 = (uint64_t)RSVAL * (uint64_t)RTVAL;
- m_lo = (uint32_t)temp64;
- m_hi = (uint32_t)(temp64 >> 32);
+ {
+ u64 product = mulu_32x32(RSVAL, RTVAL);
+
+ m_lo = product;
+ m_hi = product >> 32;
m_icount -= 11;
- break;
+ }
+ break;
case 0x1a: /* DIV */
if (RTVAL)
{
- m_lo = (int32_t)RSVAL / (int32_t)RTVAL;
- m_hi = (int32_t)RSVAL % (int32_t)RTVAL;
+ m_lo = s32(RSVAL) / s32(RTVAL);
+ m_hi = s32(RSVAL) % s32(RTVAL);
}
m_icount -= 34;
break;
@@ -1149,12 +641,12 @@ void r3000_device_base::execute_run()
m_icount -= 34;
break;
case 0x20: /* ADD */
- if (ENABLE_OVERFLOWS && RSVAL > ~RTVAL) generate_exception(EXCEPTION_OVERFLOW, true);
+ if (ENABLE_OVERFLOWS && RSVAL > ~RTVAL) generate_exception(EXCEPTION_OVERFLOW);
else RDVAL = RSVAL + RTVAL;
break;
case 0x21: /* ADDU */ if (RDREG) RDVAL = RSVAL + RTVAL; break;
case 0x22: /* SUB */
- if (ENABLE_OVERFLOWS && RSVAL < RTVAL) generate_exception(EXCEPTION_OVERFLOW, true);
+ if (ENABLE_OVERFLOWS && RSVAL < RTVAL) generate_exception(EXCEPTION_OVERFLOW);
else RDVAL = RSVAL - RTVAL;
break;
case 0x23: /* SUBU */ if (RDREG) RDVAL = RSVAL - RTVAL; break;
@@ -1162,215 +654,336 @@ void r3000_device_base::execute_run()
case 0x25: /* OR */ if (RDREG) RDVAL = RSVAL | RTVAL; break;
case 0x26: /* XOR */ if (RDREG) RDVAL = RSVAL ^ RTVAL; break;
case 0x27: /* NOR */ if (RDREG) RDVAL = ~(RSVAL | RTVAL); break;
- case 0x2a: /* SLT */ if (RDREG) RDVAL = (int32_t)RSVAL < (int32_t)RTVAL; break;
- case 0x2b: /* SLTU */ if (RDREG) RDVAL = (uint32_t)RSVAL < (uint32_t)RTVAL; break;
- case 0x30: /* TEQ */ invalid_instruction(); break;
- case 0x31: /* TGEU */ invalid_instruction(); break;
- case 0x32: /* TLT */ invalid_instruction(); break;
- case 0x33: /* TLTU */ invalid_instruction(); break;
- case 0x34: /* TGE */ invalid_instruction(); break;
- case 0x36: /* TNE */ invalid_instruction(); break;
- default: /* ??? */ invalid_instruction(); break;
+ case 0x2a: /* SLT */ if (RDREG) RDVAL = s32(RSVAL) < s32(RTVAL); break;
+ case 0x2b: /* SLTU */ if (RDREG) RDVAL = u32(RSVAL) < u32(RTVAL); break;
+ case 0x30: /* TEQ */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x31: /* TGEU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x32: /* TLT */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x33: /* TLTU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x34: /* TGE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x36: /* TNE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+ break;
+
+ case 0x01: /* REGIMM */
+ switch (RTREG)
+ {
+ case 0x00: /* BLTZ */ if (s32(RSVAL) < 0) ADDPC(SIMMVAL); break;
+ case 0x01: /* BGEZ */ if (s32(RSVAL) >= 0) ADDPC(SIMMVAL); break;
+ case 0x02: /* BLTZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BGEZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x08: /* TGEI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x09: /* TGEIU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0a: /* TLTI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0b: /* TLTIU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0c: /* TEQI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0e: /* TNEI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x10: /* BLTZAL */ if (s32(RSVAL) < 0) ADDPCL(SIMMVAL, 31); break;
+ case 0x11: /* BGEZAL */ if (s32(RSVAL) >= 0) ADDPCL(SIMMVAL, 31); break;
+ case 0x12: /* BLTZALL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x13: /* BGEZALL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+ break;
+
+ case 0x02: /* J */ ABSPC(LIMMVAL); break;
+ case 0x03: /* JAL */ ABSPCL(LIMMVAL, 31); break;
+ case 0x04: /* BEQ */ if (RSVAL == RTVAL) ADDPC(SIMMVAL); break;
+ case 0x05: /* BNE */ if (RSVAL != RTVAL) ADDPC(SIMMVAL); break;
+ case 0x06: /* BLEZ */ if (s32(RSVAL) <= 0) ADDPC(SIMMVAL); break;
+ case 0x07: /* BGTZ */ if (s32(RSVAL) > 0) ADDPC(SIMMVAL); break;
+ case 0x08: /* ADDI */
+ if (ENABLE_OVERFLOWS && RSVAL > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW);
+ else if (RTREG) RTVAL = RSVAL + SIMMVAL;
+ break;
+ case 0x09: /* ADDIU */ if (RTREG) RTVAL = RSVAL + SIMMVAL; break;
+ case 0x0a: /* SLTI */ if (RTREG) RTVAL = s32(RSVAL) < s32(SIMMVAL); break;
+ case 0x0b: /* SLTIU */ if (RTREG) RTVAL = u32(RSVAL) < u32(SIMMVAL); break;
+ case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMMVAL; break;
+ case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMMVAL; break;
+ case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMMVAL; break;
+ case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMMVAL << 16; break;
+ case 0x10: /* COP0 */
+ if (!(SR & SR_KUc) || (SR & SR_COP0))
+ handle_cop0(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x11: // COP1
+ if (SR & SR_COP1)
+ handle_cop1(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x12: // COP2
+ if (SR & SR_COP2)
+ handle_cop<2>(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x13: // COP3
+ if (SR & SR_COP3)
+ handle_cop<3>(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x14: /* BEQL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x15: /* BNEL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x16: /* BLEZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x17: /* BGTZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x20: /* LB */ load<u8>(SIMMVAL + RSVAL, [this, op](s8 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x21: /* LH */ load<u16>(SIMMVAL + RSVAL, [this, op](s16 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x22: /* LWL */ lwl(op); break;
+ case 0x23: /* LW */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x24: /* LBU */ load<u8>(SIMMVAL + RSVAL, [this, op](u8 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x25: /* LHU */ load<u16>(SIMMVAL + RSVAL, [this, op](u16 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x26: /* LWR */ lwr(op); break;
+ case 0x28: /* SB */ store<u8>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x29: /* SH */ store<u16>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x2a: /* SWL */ swl(op); break;
+ case 0x2b: /* SW */ store<u32>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x2e: /* SWR */ swr(op); break;
+ case 0x2f: /* CACHE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x30: /* LL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x31: /* LWC1 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<1>(RTREG, temp); }); break;
+ case 0x32: /* LWC2 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<2>(RTREG, temp); }); break;
+ case 0x33: /* LWC3 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<3>(RTREG, temp); }); break;
+ case 0x34: /* LDC0 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x35: /* LDC1 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x36: /* LDC2 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x37: /* LDC3 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x38: /* SC */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x39: /* LWC1 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<1>(RTREG)); break;
+ case 0x3a: /* LWC2 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<2>(RTREG)); break;
+ case 0x3b: /* LWC3 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<3>(RTREG)); break;
+ case 0x3c: /* SDC0 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3d: /* SDC1 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3e: /* SDC2 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3f: /* SDC3 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
}
- break;
-
- case 0x01: /* REGIMM */
- switch (RTREG)
- {
- case 0x00: /* BLTZ */ if ((int32_t)RSVAL < 0) ADDPC(SIMMVAL); break;
- case 0x01: /* BGEZ */ if ((int32_t)RSVAL >= 0) ADDPC(SIMMVAL); break;
- case 0x02: /* BLTZL */ invalid_instruction(); break;
- case 0x03: /* BGEZL */ invalid_instruction(); break;
- case 0x08: /* TGEI */ invalid_instruction(); break;
- case 0x09: /* TGEIU */ invalid_instruction(); break;
- case 0x0a: /* TLTI */ invalid_instruction(); break;
- case 0x0b: /* TLTIU */ invalid_instruction(); break;
- case 0x0c: /* TEQI */ invalid_instruction(); break;
- case 0x0e: /* TNEI */ invalid_instruction(); break;
- case 0x10: /* BLTZAL */ if ((int32_t)RSVAL < 0) ADDPCL(SIMMVAL,31); break;
- case 0x11: /* BGEZAL */ if ((int32_t)RSVAL >= 0) ADDPCL(SIMMVAL,31); break;
- case 0x12: /* BLTZALL */ invalid_instruction(); break;
- case 0x13: /* BGEZALL */ invalid_instruction(); break;
- default: /* ??? */ invalid_instruction(); break;
- }
- break;
-
- case 0x02: /* J */ ABSPC(LIMMVAL); break;
- case 0x03: /* JAL */ ABSPCL(LIMMVAL,31); break;
- case 0x04: /* BEQ */ if (RSVAL == RTVAL) ADDPC(SIMMVAL); break;
- case 0x05: /* BNE */ if (RSVAL != RTVAL) ADDPC(SIMMVAL); break;
- case 0x06: /* BLEZ */ if ((int32_t)RSVAL <= 0) ADDPC(SIMMVAL); break;
- case 0x07: /* BGTZ */ if ((int32_t)RSVAL > 0) ADDPC(SIMMVAL); break;
- case 0x08: /* ADDI */
- if (ENABLE_OVERFLOWS && RSVAL > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW, true);
- else if (RTREG) RTVAL = RSVAL + SIMMVAL;
- break;
- case 0x09: /* ADDIU */ if (RTREG) RTVAL = RSVAL + SIMMVAL; break;
- case 0x0a: /* SLTI */ if (RTREG) RTVAL = (int32_t)RSVAL < (int32_t)SIMMVAL; break;
- case 0x0b: /* SLTIU */ if (RTREG) RTVAL = (uint32_t)RSVAL < (uint32_t)SIMMVAL; break;
- case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMMVAL; break;
- case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMMVAL; break;
- case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMMVAL; break;
- case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMMVAL << 16; break;
- case 0x10: /* COP0 */ handle_cop0(); break;
- case 0x11: /* COP1 */ handle_cop1(); break;
- case 0x12: /* COP2 */ handle_cop2(); break;
- case 0x13: /* COP3 */ handle_cop3(); break;
- case 0x14: /* BEQL */ invalid_instruction(); break;
- case 0x15: /* BNEL */ invalid_instruction(); break;
- case 0x16: /* BLEZL */ invalid_instruction(); break;
- case 0x17: /* BGTZL */ invalid_instruction(); break;
- case 0x20: /* LB */ temp = RBYTE(SIMMVAL+RSVAL); if (RTREG) RTVAL = (int8_t)temp; break;
- case 0x21: /* LH */ temp = RWORD(SIMMVAL+RSVAL); if (RTREG) RTVAL = (int16_t)temp; break;
- case 0x22: /* LWL */ (*this.*m_lwl)(); break;
- case 0x23: /* LW */ temp = RLONG(SIMMVAL+RSVAL); if (RTREG) RTVAL = temp; break;
- case 0x24: /* LBU */ temp = RBYTE(SIMMVAL+RSVAL); if (RTREG) RTVAL = (uint8_t)temp; break;
- case 0x25: /* LHU */ temp = RWORD(SIMMVAL+RSVAL); if (RTREG) RTVAL = (uint16_t)temp; break;
- case 0x26: /* LWR */ (*this.*m_lwr)(); break;
- case 0x28: /* SB */ WBYTE(SIMMVAL+RSVAL, RTVAL); break;
- case 0x29: /* SH */ WWORD(SIMMVAL+RSVAL, RTVAL); break;
- case 0x2a: /* SWL */ (*this.*m_swl)(); break;
- case 0x2b: /* SW */ WLONG(SIMMVAL+RSVAL, RTVAL); break;
- case 0x2e: /* SWR */ (*this.*m_swr)(); break;
- case 0x2f: /* CACHE */ invalid_instruction(); break;
- case 0x30: /* LL */ invalid_instruction(); break;
- case 0x31: /* LWC1 */ set_cop1_reg(RTREG, RLONG(SIMMVAL+RSVAL)); break;
- case 0x32: /* LWC2 */ set_cop2_reg(RTREG, RLONG(SIMMVAL+RSVAL)); break;
- case 0x33: /* LWC3 */ set_cop3_reg(RTREG, RLONG(SIMMVAL+RSVAL)); break;
- case 0x34: /* LDC0 */ invalid_instruction(); break;
- case 0x35: /* LDC1 */ invalid_instruction(); break;
- case 0x36: /* LDC2 */ invalid_instruction(); break;
- case 0x37: /* LDC3 */ invalid_instruction(); break;
- case 0x38: /* SC */ invalid_instruction(); break;
- case 0x39: /* LWC1 */ WLONG(SIMMVAL+RSVAL, get_cop1_reg(RTREG)); break;
- case 0x3a: /* LWC2 */ WLONG(SIMMVAL+RSVAL, get_cop2_reg(RTREG)); break;
- case 0x3b: /* LWC3 */ WLONG(SIMMVAL+RSVAL, get_cop3_reg(RTREG)); break;
- case 0x3c: /* SDC0 */ invalid_instruction(); break;
- case 0x3d: /* SDC1 */ invalid_instruction(); break;
- case 0x3e: /* SDC2 */ invalid_instruction(); break;
- case 0x3f: /* SDC3 */ invalid_instruction(); break;
- default: /* ??? */ invalid_instruction(); break;
- }
+ }
+ });
m_icount--;
} while (m_icount > 0 || m_nextpc != ~0);
-
- m_icount -= m_interrupt_cycles;
- m_interrupt_cycles = 0;
}
-
-/***************************************************************************
- COMPLEX OPCODE IMPLEMENTATIONS
-***************************************************************************/
-
-void r3000_device_base::lwl_be()
+void mips1core_device_base::lwl(u32 const op)
{
- offs_t offs = SIMMVAL + RSVAL;
- uint32_t temp = RLONG(offs & ~3);
- if (RTREG)
+ offs_t const offset = SIMMVAL + RSVAL;
+ load<u32>(offset & ~3, [this, op, offset](u32 temp)
{
- if (!(offs & 3)) RTVAL = temp;
- else
+ if (RTREG)
{
- int shift = 8 * (offs & 3);
- RTVAL = (RTVAL & (0x00ffffff >> (24 - shift))) | (temp << shift);
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
+
+ RTVAL = (RTVAL & ~u32(0xffffffffU << shift)) | (temp << shift);
}
- }
+ });
}
-void r3000_device_base::lwr_be()
+void mips1core_device_base::lwr(u32 const op)
{
- offs_t offs = SIMMVAL + RSVAL;
- uint32_t temp = RLONG(offs & ~3);
- if (RTREG)
+ offs_t const offset = SIMMVAL + RSVAL;
+ load<u32>(offset & ~3, [this, op, offset](u32 temp)
{
- if ((offs & 3) == 3) RTVAL = temp;
- else
+ if (RTREG)
{
- int shift = 8 * (offs & 3);
- RTVAL = (RTVAL & (0xffffff00 << shift)) | (temp >> (24 - shift));
+ unsigned const shift = ((offset & 0x3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
+
+ RTVAL = (RTVAL & ~u32(0xffffffffU >> shift)) | (temp >> shift);
}
- }
+ });
}
-void r3000_device_base::swl_be()
+void mips1core_device_base::swl(u32 const op)
{
- offs_t offs = SIMMVAL + RSVAL;
- if (!(offs & 3)) WLONG(offs, RTVAL);
- else
+ offs_t const offset = SIMMVAL + RSVAL;
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
+
+ // only load if necessary
+ if (shift)
{
- uint32_t temp = RLONG(offs & ~3);
- int shift = 8 * (offs & 3);
- WLONG(offs & ~3, (temp & (0xffffff00 << (24 - shift))) | (RTVAL >> shift));
+ load<u32>(offset & ~3, [this, op, offset, shift](u32 temp)
+ {
+ store<u32>(offset & ~3, (temp & ~u32(0xffffffffU >> shift)) | (RTVAL >> shift));
+ });
}
+ else
+ store<u32>(offset & ~3, RTVAL);
}
-void r3000_device_base::swr_be()
+void mips1core_device_base::swr(u32 const op)
{
- offs_t offs = SIMMVAL + RSVAL;
- if ((offs & 3) == 3) WLONG(offs & ~3, RTVAL);
- else
+ offs_t const offset = SIMMVAL + RSVAL;
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
+
+ // only load if necessary
+ if (shift)
{
- uint32_t temp = RLONG(offs & ~3);
- int shift = 8 * (offs & 3);
- WLONG(offs & ~3, (temp & (0x00ffffff >> shift)) | (RTVAL << (24 - shift)));
+ load<u32>(offset & ~3, [this, op, offset, shift](u32 temp)
+ {
+ store<u32>(offset & ~3, (temp & ~u32(0xffffffffU << shift)) | (RTVAL << shift));
+ });
}
+ else
+ store<u32>(offset & ~3, RTVAL);
}
-
-
-void r3000_device_base::lwl_le()
+template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> mips1core_device_base::load(u32 program_address, U &&apply)
{
- offs_t offs = SIMMVAL + RSVAL;
- uint32_t temp = RLONG(offs & ~3);
- if (RTREG)
+ offs_t translated_address = program_address;
+
+ if (memory_translate(m_data_spacenum, TRANSLATE_READ, translated_address))
{
- if (!(offs & 3)) RTVAL = temp;
- else
+ switch (sizeof(T))
{
- int shift = 8 * (offs & 3);
- RTVAL = (RTVAL & (0xffffff00 << (24 - shift))) | (temp >> shift);
+ case 1: apply(T(space(m_data_spacenum).read_byte(translated_address))); break;
+ case 2: apply(T(space(m_data_spacenum).read_word(translated_address))); break;
+ case 4: apply(T(space(m_data_spacenum).read_dword(translated_address))); break;
}
}
}
-void r3000_device_base::lwr_le()
+template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> mips1core_device_base::store(u32 program_address, U data)
{
- offs_t offs = SIMMVAL + RSVAL;
- uint32_t temp = RLONG(offs & ~3);
- if (RTREG)
+ offs_t translated_address = program_address;
+
+ if (memory_translate(m_data_spacenum, TRANSLATE_WRITE, translated_address))
{
- if ((offs & 3) == 3) RTVAL = temp;
- else
+ switch (sizeof(T))
{
- int shift = 8 * (offs & 3);
- RTVAL = (RTVAL & (0x00ffffff >> shift)) | (temp << (24 - shift));
+ case 1: space(m_data_spacenum).write_byte(translated_address, T(data)); break;
+ case 2: space(m_data_spacenum).write_word(translated_address, T(data)); break;
+ case 4: space(m_data_spacenum).write_dword(translated_address, T(data)); break;
}
}
}
-void r3000_device_base::swl_le()
+bool mips1core_device_base::fetch(u32 program_address, std::function<void(u32)> &&apply)
{
- offs_t offs = SIMMVAL + RSVAL;
- if (!(offs & 3)) WLONG(offs, RTVAL);
- else
+ offs_t translated_address = program_address;
+
+ if (memory_translate(0, TRANSLATE_FETCH, translated_address))
{
- uint32_t temp = RLONG(offs & ~3);
- int shift = 8 * (offs & 3);
- WLONG(offs & ~3, (temp & (0x00ffffff >> (24 - shift))) | (RTVAL << shift));
+ apply(space(0).read_dword(translated_address));
+
+ return true;
}
+ else
+ return false;
}
-void r3000_device_base::swr_le()
+bool mips1core_device_base::memory_translate(int spacenum, int intention, offs_t &address)
{
- offs_t offs = SIMMVAL + RSVAL;
- if ((offs & 3) == 3) WLONG(offs & ~3, RTVAL);
+ // check for kernel memory address
+ if (BIT(address, 31))
+ {
+ // check debug or kernel mode
+ if ((intention & TRANSLATE_DEBUG_MASK) || !(SR & SR_KUc))
+ {
+ switch (address & 0xe0000000)
+ {
+ case 0x80000000: // kseg0: unmapped, cached, privileged
+ case 0xa0000000: // kseg1: unmapped, uncached, privileged
+ address &= ~0xe0000000;
+ break;
+
+ case 0xc0000000: // kseg2: mapped, cached, privileged
+ case 0xe0000000:
+ break;
+ }
+ }
+ else if (SR & SR_KUc)
+ {
+ // exception
+ m_cpr[0][COP0_BadVAddr] = address;
+
+ generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
+ return false;
+ }
+ }
else
+ // kuseg physical addresses have a 1GB offset
+ address += 0x40000000;
+
+ return true;
+}
+
+bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &address)
+{
+ // check for kernel memory address
+ if (BIT(address, 31))
+ {
+ // check debug or kernel mode
+ if ((intention & TRANSLATE_DEBUG_MASK) || !(SR & SR_KUc))
+ {
+ switch (address & 0xe0000000)
+ {
+ case 0x80000000: // kseg0: unmapped, cached, privileged
+ case 0xa0000000: // kseg1: unmapped, uncached, privileged
+ address &= ~0xe0000000;
+ return true;
+
+ case 0xc0000000: // kseg2: mapped, cached, privileged
+ case 0xe0000000:
+ break;
+ }
+ }
+ else if (SR & SR_KUc)
+ {
+ // exception
+ m_cpr[0][COP0_BadVAddr] = address;
+
+ generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
+ return false;
+ }
+ }
+
+ // key is a combination of VPN and ASID
+ u32 const key = (address & EH_VPN) | (m_cpr[0][COP0_EntryHi] & EH_ASID);
+ bool dirty = false;
+
+ for (u32 const *entry : m_tlb)
{
- uint32_t temp = RLONG(offs & ~3);
- int shift = 8 * (offs & 3);
- WLONG(offs & ~3, (temp & (0xffffff00 << shift)) | (RTVAL >> (24 - shift)));
+ // test vpn and optionally asid
+ u32 const mask = (entry[1] & EL_G) ? EH_VPN : EH_VPN | EH_ASID;
+ if ((entry[0] & mask) != (key & mask))
+ continue;
+
+ // test valid
+ if (!(entry[1] & EL_V))
+ break;
+
+ // test dirty
+ if ((intention & TRANSLATE_WRITE) && !(entry[1] & EL_D))
+ {
+ dirty = true;
+ break;
+ }
+
+ // translate the address
+ address &= ~EH_VPN;
+ address |= (entry[1] & EL_PFN);
+ return true;
}
+
+ if (!(intention & TRANSLATE_DEBUG_MASK))
+ {
+ if ((VERBOSE & LOG_TLB) && !dirty)
+ LOGMASKED(LOG_TLB, "tlb miss address 0x%08x\n", address);
+
+ // exception
+ m_cpr[0][COP0_BadVAddr] = address;
+ m_cpr[0][COP0_EntryHi] = key;
+ m_cpr[0][COP0_Context] &= ~0x001fffff;
+ m_cpr[0][COP0_Context] |= (address >> 11) & ~0x3;
+
+ generate_exception(dirty ? EXCEPTION_TLBMOD : (intention & TRANSLATE_WRITE) ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD);
+ }
+
+ return false;
}
diff --git a/src/devices/cpu/mips/r3000.h b/src/devices/cpu/mips/r3000.h
index 1ba98c11eea..047c049c112 100644
--- a/src/devices/cpu/mips/r3000.h
+++ b/src/devices/cpu/mips/r3000.h
@@ -1,338 +1,315 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
-/***************************************************************************
-
- r3000.h
- Interface file for the portable MIPS R3000 emulator.
- Written by Aaron Giles
-
-***************************************************************************/
#ifndef MAME_CPU_MIPS_R3000_H
#define MAME_CPU_MIPS_R3000_H
#pragma once
-
-/***************************************************************************
- INTERFACE CONFIGURATION MACROS
-***************************************************************************/
-
-#define MCFG_R3000_ENDIANNESS(_endianness) \
- downcast<r3000_device_base &>(*device).set_endianness(_endianness);
-
-#define MCFG_R3000_BRCOND0_INPUT(_devcb) \
- downcast<r3000_device_base &>(*device).set_brcond0_input(DEVCB_##_devcb);
-
-#define MCFG_R3000_BRCOND1_INPUT(_devcb) \
- downcast<r3000_device_base &>(*device).set_brcond1_input(DEVCB_##_devcb);
-
-#define MCFG_R3000_BRCOND2_INPUT(_devcb) \
- downcast<r3000_device_base &>(*device).set_brcond2_input(DEVCB_##_devcb);
-
-#define MCFG_R3000_BRCOND3_INPUT(_devcb) \
- downcast<r3000_device_base &>(*device).set_brcond3_input(DEVCB_##_devcb);
-
-
-/***************************************************************************
- REGISTER ENUMERATION
-***************************************************************************/
-
-enum
+class mips1core_device_base : public cpu_device
{
- R3000_PC=1,R3000_SR,
- R3000_R0,R3000_R1,R3000_R2,R3000_R3,R3000_R4,R3000_R5,R3000_R6,R3000_R7,
- R3000_R8,R3000_R9,R3000_R10,R3000_R11,R3000_R12,R3000_R13,R3000_R14,R3000_R15,
- R3000_R16,R3000_R17,R3000_R18,R3000_R19,R3000_R20,R3000_R21,R3000_R22,R3000_R23,
- R3000_R24,R3000_R25,R3000_R26,R3000_R27,R3000_R28,R3000_R29,R3000_R30,R3000_R31
-};
-
-
-/***************************************************************************
- INTERRUPT CONSTANTS
-***************************************************************************/
-
-#define R3000_IRQ0 0 /* IRQ0 */
-#define R3000_IRQ1 1 /* IRQ1 */
-#define R3000_IRQ2 2 /* IRQ2 */
-#define R3000_IRQ3 3 /* IRQ3 */
-#define R3000_IRQ4 4 /* IRQ4 */
-#define R3000_IRQ5 5 /* IRQ5 */
+public:
+ // device configuration
+ void set_endianness(endianness_t endianness) { m_endianness = endianness; }
+ void set_fpurev(u32 revision) { m_hasfpu = true; m_fpurev = revision; }
+ // input lines
+ template <unsigned Coprocessor> auto in_brcond() { return m_in_brcond[Coprocessor].bind(); }
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
+protected:
+ mips1core_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
-// ======================> r3000_device_base
+ enum registers
+ {
+ // general purpose cpu registers
+ MIPS1_R0, MIPS1_R1, MIPS1_R2, MIPS1_R3, MIPS1_R4, MIPS1_R5, MIPS1_R6, MIPS1_R7,
+ MIPS1_R8, MIPS1_R9, MIPS1_R10, MIPS1_R11, MIPS1_R12, MIPS1_R13, MIPS1_R14, MIPS1_R15,
+ MIPS1_R16, MIPS1_R17, MIPS1_R18, MIPS1_R19, MIPS1_R20, MIPS1_R21, MIPS1_R22, MIPS1_R23,
+ MIPS1_R24, MIPS1_R25, MIPS1_R26, MIPS1_R27, MIPS1_R28, MIPS1_R29, MIPS1_R30, MIPS1_R31,
+
+ // other cpu registers
+ MIPS1_HI,
+ MIPS1_LO,
+ MIPS1_PC,
+
+ // coprocessor 0 registers
+ MIPS1_COP0_INDEX, // reg 0, tlb only
+ MIPS1_COP0_RANDOM, // reg 1, tlb only
+ MIPS1_COP0_ENTRYLO, // reg 2, tlb only
+ MIPS1_COP0_BUSCTRL, // reg 2, r3041 only
+ MIPS1_COP0_CONFIG, // reg 3, r3041/r3071/r3081 only
+ MIPS1_COP0_CONTEXT, // reg 4, tlb only
+ MIPS1_COP0_BADVADDR, // reg 8
+ MIPS1_COP0_COUNT, // reg 9, r3041 only
+ MIPS1_COP0_ENTRYHI, // reg 10, tlb only
+ MIPS1_COP0_PORTSIZE, // reg 10, r3041 only
+ MIPS1_COP0_COMPARE, // reg 11, r3041 only
+ MIPS1_COP0_SR, // reg 12
+ MIPS1_COP0_CAUSE, // reg 13
+ MIPS1_COP0_EPC, // reg 14
+ MIPS1_COP0_PRID, // reg 15
+ };
-class r3000_device_base : public cpu_device
-{
-public:
- // construction/destruction
- virtual ~r3000_device_base();
+ enum exception : int
+ {
+ EXCEPTION_INTERRUPT = 0,
+ EXCEPTION_TLBMOD = 1,
+ EXCEPTION_TLBLOAD = 2,
+ EXCEPTION_TLBSTORE = 3,
+ EXCEPTION_ADDRLOAD = 4,
+ EXCEPTION_ADDRSTORE = 5,
+ EXCEPTION_BUSINST = 6,
+ EXCEPTION_BUSDATA = 7,
+ EXCEPTION_SYSCALL = 8,
+ EXCEPTION_BREAK = 9,
+ EXCEPTION_INVALIDOP = 10,
+ EXCEPTION_BADCOP = 11,
+ EXCEPTION_OVERFLOW = 12,
+ EXCEPTION_TRAP = 13,
+ };
- // inline configuration helpers
- void set_endianness(endianness_t endianness) { m_endianness = endianness; }
- void set_fpurev(uint32_t revision) { m_hasfpu = true; m_fpurev = revision; }
+ enum cop0_reg : u8
+ {
+ COP0_Index = 0,
+ COP0_Random = 1,
+ COP0_EntryLo = 2,
+ COP0_BusCtrl = 2, // r3041 only
+ COP0_Config = 3, // r3041/r3071/r3081 only
+ COP0_Context = 4,
+ COP0_BadVAddr = 8,
+ COP0_Count = 9, // r3041 only
+ COP0_EntryHi = 10,
+ COP0_PortSize = 10, // r3041 only
+ COP0_Compare = 11, // r3041 only
+ COP0_Status = 12,
+ COP0_Cause = 13,
+ COP0_EPC = 14,
+ COP0_PRId = 15,
+ };
- template <class Object> devcb_base &set_brcond0_input(Object &&cb) { return m_in_brcond0.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_brcond1_input(Object &&cb) { return m_in_brcond1.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_brcond2_input(Object &&cb) { return m_in_brcond2.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_brcond3_input(Object &&cb) { return m_in_brcond3.set_callback(std::forward<Object>(cb)); }
- auto in_brcond0() { return m_in_brcond0.bind(); }
- auto in_brcond1() { return m_in_brcond1.bind(); }
- auto in_brcond2() { return m_in_brcond2.bind(); }
- auto in_brcond3() { return m_in_brcond3.bind(); }
+ enum sr_mask : u32
+ {
+ SR_IEc = 0x00000001,
+ SR_KUc = 0x00000002,
+ SR_IEp = 0x00000004,
+ SR_KUp = 0x00000008,
+ SR_IEo = 0x00000010,
+ SR_KUo = 0x00000020,
+ SR_IMSW0 = 0x00000100,
+ SR_IMSW1 = 0x00000200,
+ SR_IMEX0 = 0x00000400,
+ SR_IMEX1 = 0x00000800,
+ SR_IMEX2 = 0x00001000,
+ SR_IMEX3 = 0x00002000,
+ SR_IMEX4 = 0x00004000,
+ SR_IMEX5 = 0x00008000,
+ SR_IsC = 0x00010000,
+ SR_SwC = 0x00020000,
+ SR_PZ = 0x00040000,
+ SR_CM = 0x00080000,
+ SR_PE = 0x00100000,
+ SR_TS = 0x00200000,
+ SR_BEV = 0x00400000,
+ SR_RE = 0x02000000,
+ SR_COP0 = 0x10000000,
+ SR_COP1 = 0x20000000,
+ SR_COP2 = 0x40000000,
+ SR_COP3 = 0x80000000,
+ };
-protected:
- r3000_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t cpurev, size_t icache_size, size_t dcache_size);
+ enum entryhi_mask : u32
+ {
+ EH_VPN = 0xfffff000, // virtual page number
+ EH_ASID = 0x00000fc0, // address space identifier
+ };
+ enum entrylo_mask : u32
+ {
+ EL_PFN = 0xfffff000, // physical frame
+ EL_N = 0x00000800, // noncacheable
+ EL_D = 0x00000400, // dirty
+ EL_V = 0x00000200, // valid
+ EL_G = 0x00000100, // global
+ };
- // device-level overrides
+ // device_t overrides
+ virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
- virtual void device_post_load() override;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override;
- virtual uint32_t execute_max_cycles() const override;
- virtual uint32_t execute_input_lines() const override;
+ virtual u32 execute_min_cycles() const override { return 1; }
+ virtual u32 execute_max_cycles() const override { return 40; }
+ virtual u32 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_set_input(int inputnum, int state) override { set_irq_line(inputnum, state); }
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
-
- // device_state_interface overrides
- virtual void state_import(const device_state_entry &entry) override;
- 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;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- // memory accessors
- struct r3000_data_accessors
- {
- uint8_t (r3000_device_base::*m_read_byte)(offs_t byteaddress);
- uint16_t (r3000_device_base::*m_read_word)(offs_t byteaddress);
- uint32_t (r3000_device_base::*m_read_dword)(offs_t byteaddress);
- void (r3000_device_base::*m_write_byte)(offs_t byteaddress, uint8_t data);
- void (r3000_device_base::*m_write_word)(offs_t byteaddress, uint16_t data);
- void (r3000_device_base::*m_write_dword)(offs_t byteaddress, uint32_t data);
- };
-
- uint32_t readop(offs_t pc);
- uint8_t readmem(offs_t offset);
- uint16_t readmem_word(offs_t offset);
- uint32_t readmem_dword(offs_t offset);
- void writemem(offs_t offset, uint8_t data);
- void writemem_word(offs_t offset, uint16_t data);
- void writemem_dword(offs_t offset, uint32_t data);
-
- uint8_t readcache_be(offs_t offset);
- uint16_t readcache_be_word(offs_t offset);
- uint32_t readcache_be_dword(offs_t offset);
- void writecache_be(offs_t offset, uint8_t data);
- void writecache_be_word(offs_t offset, uint16_t data);
- void writecache_be_dword(offs_t offset, uint32_t data);
-
- uint8_t readcache_le(offs_t offset);
- uint16_t readcache_le_word(offs_t offset);
- uint32_t readcache_le_dword(offs_t offset);
- void writecache_le(offs_t offset, uint8_t data);
- void writecache_le_word(offs_t offset, uint16_t data);
- void writecache_le_dword(offs_t offset, uint32_t data);
+ void icache_map(address_map &map);
+ void dcache_map(address_map &map);
// interrupts
- void generate_exception(int exception, bool backup);
+ void generate_exception(int exception);
void check_irqs();
void set_irq_line(int irqline, int state);
- void invalid_instruction();
-
- // instructions
- uint32_t get_cop0_reg(int idx);
- void set_cop0_reg(int idx, uint32_t val);
- uint32_t get_cop0_creg(int idx);
- void set_cop0_creg(int idx, uint32_t val);
- void handle_cop0();
-
- uint32_t get_cop1_reg(int idx);
- void set_cop1_reg(int idx, uint32_t val);
- uint32_t get_cop1_creg(int idx);
- void set_cop1_creg(int idx, uint32_t val);
- void handle_cop1();
-
- uint32_t get_cop2_reg(int idx);
- void set_cop2_reg(int idx, uint32_t val);
- uint32_t get_cop2_creg(int idx);
- void set_cop2_creg(int idx, uint32_t val);
- void handle_cop2();
-
- uint32_t get_cop3_reg(int idx);
- void set_cop3_reg(int idx, uint32_t val);
- uint32_t get_cop3_creg(int idx);
- void set_cop3_creg(int idx, uint32_t val);
- void handle_cop3();
-
- // complex opcodes
- void lwl_be();
- void lwr_be();
- void swl_be();
- void swr_be();
-
- void lwl_le();
- void lwr_le();
- void swl_le();
- void swr_le();
+
+ // cop0
+ virtual u32 get_cop0_reg(int const index);
+ void set_cop0_reg(int const index, u32 const data);
+ virtual void handle_cop0(u32 const op);
+
+ // cop1
+ void set_cop1_creg(int const index, u32 const data);
+ void handle_cop1(u32 const op);
+
+ // generic coprocessor implementation
+ template <unsigned Coprocessor> void handle_cop(u32 const op);
+ template <unsigned Coprocessor> u32 get_cop_reg(int const index) { return m_cpr[Coprocessor][index]; }
+ template <unsigned Coprocessor> void set_cop_reg(int const index, u32 const data) { m_cpr[Coprocessor][index] = data; }
+ template <unsigned Coprocessor> u32 get_cop_creg(int const index) { return m_ccr[Coprocessor][index]; }
+ template <unsigned Coprocessor> void set_cop_creg(int const index, u32 const data) { m_ccr[Coprocessor][index] = data; }
+
+ // load/store left/right opcodes
+ void lwl(u32 const op);
+ void lwr(u32 const op);
+ void swl(u32 const op);
+ void swr(u32 const op);
+
+ // memory accessors
+ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u32 program_address, U &&apply);
+ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u32 program_address, U data);
+ bool fetch(u32 program_address, std::function<void(u32)> &&apply);
// address spaces
const address_space_config m_program_config_be;
const address_space_config m_program_config_le;
- address_space *m_program;
- std::function<u32 (offs_t)> m_pr32;
- std::function<const void * (offs_t)> m_prptr;
+ const address_space_config m_icache_config;
+ const address_space_config m_dcache_config;
+
+ int m_data_spacenum;
// configuration
- uint32_t m_cpurev;
- bool m_hasfpu;
- uint32_t m_fpurev;
- endianness_t m_endianness;
+ u32 m_cpurev;
+ bool m_hasfpu;
+ u32 m_fpurev;
+ endianness_t m_endianness;
// core registers
- uint32_t m_pc;
- uint32_t m_nextpc;
- uint32_t m_hi;
- uint32_t m_lo;
- uint32_t m_r[32];
+ u32 m_pc;
+ u32 m_nextpc;
+ u32 m_hi;
+ u32 m_lo;
+ u32 m_r[32];
// COP registers
- uint32_t m_cpr[4][32];
- uint32_t m_ccr[4][32];
+ u32 m_cpr[4][32];
+ u32 m_ccr[4][32];
// internal stuff
- uint32_t m_ppc;
- uint32_t m_op;
- int m_icount;
- int m_interrupt_cycles;
-
- // endian-dependent load/store
- void (r3000_device_base::*m_lwl)();
- void (r3000_device_base::*m_lwr)();
- void (r3000_device_base::*m_swl)();
- void (r3000_device_base::*m_swr)();
-
- // memory accesses
- r3000_data_accessors *m_cur;
- r3000_data_accessors m_memory_hand;
- r3000_data_accessors m_cache_hand;
+ u32 m_ppc;
+ int m_icount;
// cache memory
- uint32_t * m_cache;
- std::vector<uint32_t> m_icache;
- std::vector<uint32_t> m_dcache;
- size_t m_cache_size;
size_t const m_icache_size;
size_t const m_dcache_size;
// I/O
- devcb_read_line m_in_brcond0;
- devcb_read_line m_in_brcond1;
- devcb_read_line m_in_brcond2;
- devcb_read_line m_in_brcond3;
+ devcb_read_line m_in_brcond[4];
};
-// ======================> r2000_device
-
-class r2000_device : public r3000_device_base
+class mips1_device_base : public mips1core_device_base
{
-public:
- r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 0, size_t dcache_size = 0);
-};
+protected:
+ mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
+ // device_t overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_memory_interface overrides
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+
+ virtual u32 get_cop0_reg(int idx) override;
+ virtual void handle_cop0(u32 const op) override;
-// ======================> r2000a_device
+private:
+ u64 m_reset_time;
+ u32 m_tlb[64][2]; // 0 is hi, 1 is lo
+};
-class r2000a_device : public r3000_device_base
+class r2000_device : public mips1_device_base
{
public:
- r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
-
-// ======================> r3000_device
-
-class r3000_device : public r3000_device_base
+class r2000a_device : public mips1_device_base
{
public:
- r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
-
-// ======================> r3000a_device
-
-class r3000a_device : public r3000_device_base
+class r3000_device : public mips1_device_base
{
public:
- r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
-
-// ======================> r3041_device
-
-class r3041_device : public r3000_device_base
+class r3000a_device : public mips1_device_base
{
public:
- r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
+class r3041_device : public mips1core_device_base
+{
+public:
+ r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-// ======================> r3051_device
+protected:
+ virtual void device_start() override;
+};
-class r3051_device : public r3000_device_base
+class r3051_device : public mips1core_device_base
{
public:
- r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
-
-// ======================> r3052_device
-
-class r3052_device : public r3000_device_base
+class r3052_device : public mips1core_device_base
{
public:
- r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
-
-// ======================> r3071_device
-
-class r3071_device : public r3000_device_base
+class r3052e_device : public mips1_device_base
{
public:
- r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 16384, size_t dcache_size = 4096);
+ r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
-
-// ======================> r3081_device
-
-class r3081_device : public r3000_device_base
+class r3071_device : public mips1core_device_base
{
public:
- r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, size_t icache_size = 16384, size_t dcache_size = 4096);
+ r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
};
-
-// ======================> iop_device
-
-class iop_device : public r3000_device_base
+class r3081_device : public mips1core_device_base
{
public:
- iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
};
-
-// device type definition
+class iop_device : public mips1core_device_base
+{
+public:
+ iop_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
DECLARE_DEVICE_TYPE(R2000, r2000_device)
DECLARE_DEVICE_TYPE(R2000A, r2000a_device)
@@ -341,6 +318,7 @@ DECLARE_DEVICE_TYPE(R3000A, r3000a_device)
DECLARE_DEVICE_TYPE(R3041, r3041_device)
DECLARE_DEVICE_TYPE(R3051, r3051_device)
DECLARE_DEVICE_TYPE(R3052, r3052_device)
+DECLARE_DEVICE_TYPE(R3052E, r3052e_device)
DECLARE_DEVICE_TYPE(R3071, r3071_device)
DECLARE_DEVICE_TYPE(R3081, r3081_device)
DECLARE_DEVICE_TYPE(SONYPS2_IOP, iop_device)
diff --git a/src/devices/cpu/mips/r3kdasm.cpp b/src/devices/cpu/mips/r3kdasm.cpp
index 7e004a95068..f31705d18f7 100644
--- a/src/devices/cpu/mips/r3kdasm.cpp
+++ b/src/devices/cpu/mips/r3kdasm.cpp
@@ -11,7 +11,7 @@
#include "emu.h"
#include "r3kdasm.h"
-const char *const r3000_disassembler::reg[32] =
+const char *const mips1_disassembler::reg[32] =
{
"0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
@@ -20,7 +20,7 @@ const char *const r3000_disassembler::reg[32] =
};
-const char *const r3000_disassembler::cpreg[4][32] =
+const char *const mips1_disassembler::cpreg[4][32] =
{
{
"Index","Random","EntryLo","cpr3", "Context", "cpr5", "cpr6", "cpr7",
@@ -49,7 +49,7 @@ const char *const r3000_disassembler::cpreg[4][32] =
};
-const char *const r3000_disassembler::ccreg[4][32] =
+const char *const mips1_disassembler::ccreg[4][32] =
{
{
"ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
@@ -82,7 +82,7 @@ const char *const r3000_disassembler::ccreg[4][32] =
CODE CODE
***************************************************************************/
-std::string r3000_disassembler::signed_16bit(int16_t val)
+std::string mips1_disassembler::signed_16bit(int16_t val)
{
if (val < 0)
return util::string_format("-$%x", -val);
@@ -90,7 +90,7 @@ std::string r3000_disassembler::signed_16bit(int16_t val)
return util::string_format("$%x", val);
}
-uint32_t r3000_disassembler::dasm_cop(uint32_t pc, int cop, uint32_t op, std::ostream &stream)
+uint32_t mips1_disassembler::dasm_cop(uint32_t pc, int cop, uint32_t op, std::ostream &stream)
{
int rt = (op >> 16) & 31;
int rd = (op >> 11) & 31;
@@ -150,7 +150,7 @@ uint32_t r3000_disassembler::dasm_cop(uint32_t pc, int cop, uint32_t op, std::os
return flags;
}
-uint32_t r3000_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream)
+uint32_t mips1_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &stream)
{
static const char *const format_table[] =
{
@@ -233,7 +233,7 @@ uint32_t r3000_disassembler::dasm_cop1(uint32_t pc, uint32_t op, std::ostream &s
return flags;
}
-offs_t r3000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+offs_t mips1_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
uint32_t op = opcodes.r32(pc);
int rs = (op >> 21) & 31;
@@ -376,7 +376,7 @@ offs_t r3000_disassembler::disassemble(std::ostream &stream, offs_t pc, const da
return 4 | flags | SUPPORTED;
}
-uint32_t r3000_disassembler::opcode_alignment() const
+uint32_t mips1_disassembler::opcode_alignment() const
{
return 4;
}
diff --git a/src/devices/cpu/mips/r3kdasm.h b/src/devices/cpu/mips/r3kdasm.h
index 7eec7e7c1f8..9341bb459f5 100644
--- a/src/devices/cpu/mips/r3kdasm.h
+++ b/src/devices/cpu/mips/r3kdasm.h
@@ -13,11 +13,11 @@
#pragma once
-class r3000_disassembler : public util::disasm_interface
+class mips1_disassembler : public util::disasm_interface
{
public:
- r3000_disassembler() = default;
- virtual ~r3000_disassembler() = default;
+ mips1_disassembler() = default;
+ virtual ~mips1_disassembler() = default;
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
diff --git a/src/mame/drivers/4dpi.cpp b/src/mame/drivers/4dpi.cpp
index a463ef7493e..2439d6d1d34 100644
--- a/src/mame/drivers/4dpi.cpp
+++ b/src/mame/drivers/4dpi.cpp
@@ -52,7 +52,7 @@ private:
uint32_t screen_update_sgi_ip6(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(sgi_ip6_vbl);
inline void ATTR_PRINTF(3,4) verboselog( int n_level, const char *s_fmt, ... );
- required_device<cpu_device> m_maincpu;
+ required_device<r2000_device> m_maincpu;
void sgi_ip6_map(address_map &map);
};
@@ -234,10 +234,10 @@ void sgi_ip6_state::sgi_ip6_map(address_map &map)
***************************************************************************/
MACHINE_CONFIG_START(sgi_ip6_state::sgi_ip6)
- MCFG_DEVICE_ADD( "maincpu", R3041, 20000000 ) // FIXME: Should be R2000
- MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
- MCFG_DEVICE_PROGRAM_MAP( sgi_ip6_map )
- MCFG_DEVICE_VBLANK_INT_DRIVER("screen", sgi_ip6_state, sgi_ip6_vbl)
+ R2000(config, m_maincpu, 25_MHz_XTAL / 2);
+ m_maincpu->set_endianness(ENDIANNESS_BIG);
+ m_maincpu->set_addrmap(AS_PROGRAM, &sgi_ip6_state::sgi_ip6_map);
+ m_maincpu->set_vblank_int("screen", FUNC(sgi_ip6_state::sgi_ip6_vbl));
/* video hardware */
@@ -271,5 +271,5 @@ ROM_START( sgi_ip6 )
ROM_LOAD( "4d202031.bin", 0x000000, 0x040000, CRC(065a290a) SHA1(6f5738e79643f94901e6efe3612468d14177f65b) )
ROM_END
-// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-COMP( 1988, sgi_ip6, 0, 0, sgi_ip6, sgi_ip6, sgi_ip6_state, init_sgi_ip6, "Silicon Graphics Inc", "4D/PI (R2000, 20MHz)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+COMP( 1988, sgi_ip6, 0, 0, sgi_ip6, sgi_ip6, sgi_ip6_state, init_sgi_ip6, "Silicon Graphics Inc", "4D/PI (R2000, 12.5MHz)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
diff --git a/src/mame/drivers/decstation.cpp b/src/mame/drivers/decstation.cpp
index 7580f89de9a..3190f11efcf 100644
--- a/src/mame/drivers/decstation.cpp
+++ b/src/mame/drivers/decstation.cpp
@@ -110,7 +110,7 @@ private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- required_device<r3041_device> m_maincpu;
+ required_device<r3000a_device> m_maincpu;
required_device<screen_device> m_screen;
required_device<lk201_device> m_lk201;
required_device<dec_ioga_device> m_ioga;
@@ -364,10 +364,11 @@ static void dec_scsi_devices(device_slot_interface &device)
}
MACHINE_CONFIG_START(decstation_state::kn02ba)
- MCFG_DEVICE_ADD( "maincpu", R3041, 33000000 ) // FIXME: Should be R3000A
- MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
- MCFG_R3000_BRCOND0_INPUT(READLINE(*this, decstation_state, brcond0_r))
- MCFG_DEVICE_PROGRAM_MAP( threemin_map )
+ R3000A(config, m_maincpu, 33.333_MHz_XTAL, 65536, 131072);
+ m_maincpu->set_endianness(ENDIANNESS_LITTLE);
+ m_maincpu->set_fpurev(0x340); // should be R3010A v4.0
+ m_maincpu->in_brcond<0>().set(FUNC(decstation_state::brcond0_r));
+ m_maincpu->set_addrmap(AS_PROGRAM, &decstation_state::threemin_map);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(130000000, 1704, 32, (1280+32), 1064, 3, (1024+3));
diff --git a/src/mame/drivers/indigo.cpp b/src/mame/drivers/indigo.cpp
index 0a2a43424fc..a1afaef6e3a 100644
--- a/src/mame/drivers/indigo.cpp
+++ b/src/mame/drivers/indigo.cpp
@@ -586,9 +586,9 @@ void indigo_state::cdrom_config(device_t *device)
}
MACHINE_CONFIG_START(indigo_state::indigo3k)
- MCFG_DEVICE_ADD("maincpu", R3041, 33000000)
- MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
- MCFG_DEVICE_PROGRAM_MAP(indigo3k_map)
+ R3000A(config, m_maincpu, 33.333_MHz_XTAL, 32768, 32768);
+ downcast<r3000a_device &>(*m_maincpu).set_endianness(ENDIANNESS_BIG);
+ m_maincpu->set_addrmap(AS_PROGRAM, &indigo_state::indigo3k_map);
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
diff --git a/src/mame/drivers/jaguar.cpp b/src/mame/drivers/jaguar.cpp
index 4613b2ce55d..5c203610a0d 100644
--- a/src/mame/drivers/jaguar.cpp
+++ b/src/mame/drivers/jaguar.cpp
@@ -1841,9 +1841,9 @@ INPUT_PORTS_END
MACHINE_CONFIG_START(jaguar_state::cojagr3k)
/* basic machine hardware */
- MCFG_DEVICE_ADD("maincpu", R3041, R3000_CLOCK)
- MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
- MCFG_DEVICE_PROGRAM_MAP(r3000_map)
+ R3041(config, m_maincpu, R3000_CLOCK);
+ downcast<r3041_device &>(*m_maincpu).set_endianness(ENDIANNESS_BIG);
+ m_maincpu->set_addrmap(AS_PROGRAM, &jaguar_state::r3000_map);
MCFG_DEVICE_ADD("gpu", JAGUARGPU, COJAG_CLOCK/2)
MCFG_JAGUAR_IRQ_HANDLER(WRITELINE(*this, jaguar_state, gpu_cpu_int))
diff --git a/src/mame/drivers/mips.cpp b/src/mame/drivers/mips.cpp
index ed9b67ef0b5..cc55820f6e8 100644
--- a/src/mame/drivers/mips.cpp
+++ b/src/mame/drivers/mips.cpp
@@ -234,10 +234,10 @@ void rx2030_state::iop_io_map(address_map &map)
{
switch (data)
{
- case 0: LOG("cpu interrupt 0 asserted\n"); m_cpu->set_input_line(R3000_IRQ0, ASSERT_LINE); break;
- case 1: LOG("cpu interrupt 1 asserted\n"); m_cpu->set_input_line(R3000_IRQ1, ASSERT_LINE); break;
- case 2: LOG("cpu interrupt 2 asserted\n"); m_cpu->set_input_line(R3000_IRQ2, ASSERT_LINE); break;
- case 3: LOG("cpu interrupt 4 asserted\n"); m_cpu->set_input_line(R3000_IRQ4, ASSERT_LINE); break;
+ case 0: LOG("cpu interrupt 0 asserted\n"); m_cpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); break;
+ case 1: LOG("cpu interrupt 1 asserted\n"); m_cpu->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); break;
+ case 2: LOG("cpu interrupt 2 asserted\n"); m_cpu->set_input_line(INPUT_LINE_IRQ2, ASSERT_LINE); break;
+ case 3: LOG("cpu interrupt 4 asserted\n"); m_cpu->set_input_line(INPUT_LINE_IRQ4, ASSERT_LINE); break;
case 4:
if (m_cpu->suspended())
@@ -274,10 +274,10 @@ void rx2030_state::rx2030_map(address_map &map)
{
switch (data)
{
- case 0: LOG("cpu interrupt 0 cleared\n"); m_cpu->set_input_line(R3000_IRQ0, CLEAR_LINE); break;
- case 1: LOG("cpu interrupt 1 cleared\n"); m_cpu->set_input_line(R3000_IRQ1, CLEAR_LINE); break;
- case 2: LOG("cpu interrupt 2 cleared\n"); m_cpu->set_input_line(R3000_IRQ2, CLEAR_LINE); break;
- case 3: LOG("cpu interrupt 4 cleared\n"); m_cpu->set_input_line(R3000_IRQ4, CLEAR_LINE); break;
+ case 0: LOG("cpu interrupt 0 cleared\n"); m_cpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); break;
+ case 1: LOG("cpu interrupt 1 cleared\n"); m_cpu->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); break;
+ case 2: LOG("cpu interrupt 2 cleared\n"); m_cpu->set_input_line(INPUT_LINE_IRQ2, CLEAR_LINE); break;
+ case 3: LOG("cpu interrupt 4 cleared\n"); m_cpu->set_input_line(INPUT_LINE_IRQ4, CLEAR_LINE); break;
break;
case 4:
@@ -344,7 +344,7 @@ void rx2030_state::rx2030(machine_config &config)
{
R2000A(config, m_cpu, 33.333_MHz_XTAL / 2, 32768, 32768);
m_cpu->set_fpurev(0x0315); // 0x0315 == R2010A v1.5
- m_cpu->in_brcond0().set([this]() { logerror("brcond0 sampled (%s)\n", machine().describe_context()); return ASSERT_LINE; });
+ m_cpu->in_brcond<0>().set([this]() { logerror("brcond0 sampled (%s)\n", machine().describe_context()); return ASSERT_LINE; });
V50(config, m_iop, 20_MHz_XTAL / 2);
m_iop->set_addrmap(AS_PROGRAM, &rx2030_state::iop_program_map);
@@ -480,7 +480,7 @@ void rx2030_state::rs2030(machine_config &config)
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(pixclock, 1688, 248, 1528, 1066, 38, 1062);
m_screen->set_screen_update(FUNC(rx2030_state::screen_update));
- m_screen->screen_vblank().set_inputline(m_cpu, R3000_IRQ5);
+ m_screen->screen_vblank().set_inputline(m_cpu, INPUT_LINE_IRQ5);
BT458(config, m_ramdac, pixclock);
}
diff --git a/src/mame/drivers/speglsht.cpp b/src/mame/drivers/speglsht.cpp
index 139ad2c6b96..779ebe93c79 100644
--- a/src/mame/drivers/speglsht.cpp
+++ b/src/mame/drivers/speglsht.cpp
@@ -132,7 +132,7 @@ public:
private:
required_device<palette_device> m_palette;
required_device<st0016_cpu_device> m_maincpu;
- required_device<cpu_device> m_subcpu;
+ required_device<r3051_device> m_subcpu;
required_shared_ptr<uint8_t> m_shared;
required_shared_ptr<uint32_t> m_framebuffer;
@@ -421,10 +421,10 @@ MACHINE_CONFIG_START(speglsht_state::speglsht)
MCFG_DEVICE_VBLANK_INT_DRIVER("screen", speglsht_state, irq0_line_hold)
- MCFG_DEVICE_ADD("sub", R3051, 25000000)
- MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
- MCFG_DEVICE_PROGRAM_MAP(speglsht_mem)
- MCFG_DEVICE_VBLANK_INT_DRIVER("screen", speglsht_state, irq4_line_assert)
+ R3051(config, m_subcpu, 25000000);
+ m_subcpu->set_endianness(ENDIANNESS_LITTLE);
+ m_subcpu->set_addrmap(AS_PROGRAM, &speglsht_state::speglsht_mem);
+ m_subcpu->set_vblank_int("screen", FUNC(speglsht_state::irq4_line_assert));
MCFG_QUANTUM_TIME(attotime::from_hz(6000))
MCFG_MACHINE_RESET_OVERRIDE(speglsht_state,speglsht)
diff --git a/src/mame/drivers/srmp5.cpp b/src/mame/drivers/srmp5.cpp
index 6c2dc2cc0a2..cbbb4e2e519 100644
--- a/src/mame/drivers/srmp5.cpp
+++ b/src/mame/drivers/srmp5.cpp
@@ -85,7 +85,7 @@ public:
private:
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
- required_device<cpu_device> m_maincpu;
+ required_device<r3051_device> m_maincpu;
required_device<st0016_cpu_device> m_soundcpu;
required_region_ptr<uint16_t> m_chrrom;
@@ -569,10 +569,10 @@ GFXDECODE_END
MACHINE_CONFIG_START(srmp5_state::srmp5)
/* basic machine hardware */
- MCFG_DEVICE_ADD("maincpu", R3051, 25000000)
- MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
- MCFG_DEVICE_PROGRAM_MAP(srmp5_mem)
- MCFG_DEVICE_VBLANK_INT_DRIVER("screen", srmp5_state, irq4_line_assert)
+ R3051(config, m_maincpu, 25000000);
+ m_maincpu->set_endianness(ENDIANNESS_LITTLE);
+ m_maincpu->set_addrmap(AS_PROGRAM, &srmp5_state::srmp5_mem);
+ m_maincpu->set_vblank_int("screen", FUNC(srmp5_state::irq4_line_assert));
MCFG_DEVICE_ADD("soundcpu",ST0016_CPU,8000000)
MCFG_DEVICE_PROGRAM_MAP(st0016_mem)
diff --git a/src/mame/drivers/tekxp33x.cpp b/src/mame/drivers/tekxp33x.cpp
index 9598b6ff9d4..58d91b17474 100644
--- a/src/mame/drivers/tekxp33x.cpp
+++ b/src/mame/drivers/tekxp33x.cpp
@@ -99,9 +99,9 @@ void tekxp330_state::machine_start()
MACHINE_CONFIG_START(tekxp330_state::tekxp330)
/* basic machine hardware */
- MCFG_DEVICE_ADD("maincpu", R3052, XTAL(20'000'000)) /* IDT 79R3052E, clock unknown */
- MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
- MCFG_DEVICE_PROGRAM_MAP(cpu_map)
+ r3052e_device &maincpu(R3052E(config, "maincpu", XTAL(20'000'000))); /* IDT 79R3052E, clock unknown */
+ maincpu.set_endianness(ENDIANNESS_BIG);
+ maincpu.set_addrmap(AS_PROGRAM, &tekxp330_state::cpu_map);
MCFG_DEVICE_ADD("tms", TMS34010, XTAL(40'000'000)) /* clock unknown */
MCFG_DEVICE_PROGRAM_MAP(tms_map)
diff --git a/src/mame/drivers/turrett.cpp b/src/mame/drivers/turrett.cpp
index 860eb55b5cb..74aa1dc94a9 100644
--- a/src/mame/drivers/turrett.cpp
+++ b/src/mame/drivers/turrett.cpp
@@ -11,14 +11,6 @@
#include "emu.h"
#include "includes/turrett.h"
-#include "cpu/mips/r3000.h"
-#include "machine/ataintf.h"
-#include "machine/idehd.h"
-#include "emupal.h"
-#include "speaker.h"
-
-
-
/*************************************
*
* Definitions
@@ -356,13 +348,13 @@ void turrett_devices(device_slot_interface &device)
MACHINE_CONFIG_START(turrett_state::turrett)
/* basic machine hardware */
- MCFG_DEVICE_ADD("maincpu", R3041, R3041_CLOCK)
- MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
- MCFG_R3000_BRCOND2_INPUT(READLINE(*this, turrett_state, sbrc2_r))
- MCFG_R3000_BRCOND3_INPUT(READLINE(*this, turrett_state, sbrc3_r))
- MCFG_DEVICE_PROGRAM_MAP(cpu_map)
- MCFG_DEVICE_VBLANK_INT_DRIVER("screen", turrett_state, vblank)
- MCFG_DEVICE_PERIODIC_INT_DRIVER(turrett_state, adc, 60)
+ R3041(config, m_maincpu, R3041_CLOCK);
+ m_maincpu->set_endianness(ENDIANNESS_BIG);
+ m_maincpu->in_brcond<2>().set(FUNC(turrett_state::sbrc2_r));
+ m_maincpu->in_brcond<3>().set(FUNC(turrett_state::sbrc3_r));
+ m_maincpu->set_addrmap(AS_PROGRAM, &turrett_state::cpu_map);
+ m_maincpu->set_vblank_int("screen", FUNC(turrett_state::vblank));
+ m_maincpu->set_periodic_int(FUNC(turrett_state::adc), attotime::from_hz(60));
ATA_INTERFACE(config, m_ata).options(turrett_devices, "hdd", nullptr, true);
diff --git a/src/mame/includes/mips.h b/src/mame/includes/mips.h
index d7df4116618..df042000405 100644
--- a/src/mame/includes/mips.h
+++ b/src/mame/includes/mips.h
@@ -98,7 +98,7 @@ private:
};
// processors and memory
- required_device<r3000_device_base> m_cpu;
+ required_device<r2000a_device> m_cpu;
required_device<v50_device> m_iop;
required_device<ram_device> m_ram;
diff --git a/src/mame/includes/turrett.h b/src/mame/includes/turrett.h
index f8e7cca90b7..a91728d215f 100644
--- a/src/mame/includes/turrett.h
+++ b/src/mame/includes/turrett.h
@@ -10,7 +10,11 @@
#pragma once
+#include "cpu/mips/r3000.h"
#include "machine/ataintf.h"
+#include "machine/idehd.h"
+#include "emupal.h"
+#include "speaker.h"
#include "screen.h"
@@ -38,7 +42,7 @@ private:
static const uint32_t VRAM_BANK_WORDS = 256 * 1024;
// devices
- required_device<cpu_device> m_maincpu;
+ required_device<r3041_device> m_maincpu;
required_device<ata_interface_device> m_ata;
required_shared_ptr<uint16_t> m_bank_a;
required_shared_ptr<uint16_t> m_bank_b;
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index feff5c5e580..1548763530e 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -420,8 +420,8 @@ static const dasm_table_entry dasm_table[] =
{ "powerpc", be, 0, []() -> util::disasm_interface * { return new powerpc_disassembler; } },
{ "pps4", le, 0, []() -> util::disasm_interface * { return new pps4_disassembler; } },
{ "psxcpu", le, 0, []() -> util::disasm_interface * { return new psxcpu_disassembler; } },
- { "r3000be", be, 0, []() -> util::disasm_interface * { return new r3000_disassembler; } },
- { "r3000le", le, 0, []() -> util::disasm_interface * { return new r3000_disassembler; } },
+ { "mips1be", be, 0, []() -> util::disasm_interface * { return new mips1_disassembler; } },
+ { "mips1le", le, 0, []() -> util::disasm_interface * { return new mips1_disassembler; } },
{ "rsp", le, 0, []() -> util::disasm_interface * { return new rsp_disassembler; } },
{ "s2650", le, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } },
{ "saturn", le, 0, []() -> util::disasm_interface * { return new saturn_disassembler(&saturn_unidasm); } },