From d2fe91f89c1daf5e0c8be41eea134f6cd560e3c3 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Tue, 6 Nov 2018 13:53:11 +0700 Subject: r3000: modernize, add tlb support * replaced memory accessors * implemented tlb and address translation * corrected exception vector logic * improved cache isolation behaviour * comments/formatting --- src/devices/cpu/mips/r3000.cpp | 1613 +++++++++++++++----------------------- src/devices/cpu/mips/r3000.h | 458 ++++++----- src/devices/cpu/mips/r3kdasm.cpp | 16 +- src/devices/cpu/mips/r3kdasm.h | 6 +- src/mame/drivers/4dpi.cpp | 14 +- src/mame/drivers/decstation.cpp | 11 +- src/mame/drivers/indigo.cpp | 6 +- src/mame/drivers/jaguar.cpp | 6 +- src/mame/drivers/mips.cpp | 20 +- src/mame/drivers/speglsht.cpp | 10 +- src/mame/drivers/srmp5.cpp | 10 +- src/mame/drivers/tekxp33x.cpp | 6 +- src/mame/drivers/turrett.cpp | 22 +- src/mame/includes/mips.h | 2 +- src/mame/includes/turrett.h | 6 +- src/tools/unidasm.cpp | 4 +- 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 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(); + 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 mips1core_device_base::create_disassembler() { - offset &= 0x1fffffff; - if (offset * 4 < m_cache_size) *(uint32_t *)&m_cache[offset] = data; + return std::make_unique(); } - -/*************************************************************************** - 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 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(RDREG); break; + case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg(RDREG); break; + case 0x04: /* MTCz */ set_cop_reg(RDREG, RTVAL); break; + case 0x06: /* CTCz */ set_cop_creg(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(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(SIMMVAL + RSVAL, [this, op](s8 temp) { if (RTREG) RTVAL = temp; }); break; + case 0x21: /* LH */ load(SIMMVAL + RSVAL, [this, op](s16 temp) { if (RTREG) RTVAL = temp; }); break; + case 0x22: /* LWL */ lwl(op); break; + case 0x23: /* LW */ load(SIMMVAL + RSVAL, [this, op](u32 temp) { if (RTREG) RTVAL = temp; }); break; + case 0x24: /* LBU */ load(SIMMVAL + RSVAL, [this, op](u8 temp) { if (RTREG) RTVAL = temp; }); break; + case 0x25: /* LHU */ load(SIMMVAL + RSVAL, [this, op](u16 temp) { if (RTREG) RTVAL = temp; }); break; + case 0x26: /* LWR */ lwr(op); break; + case 0x28: /* SB */ store(SIMMVAL + RSVAL, RTVAL); break; + case 0x29: /* SH */ store(SIMMVAL + RSVAL, RTVAL); break; + case 0x2a: /* SWL */ swl(op); break; + case 0x2b: /* SW */ store(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(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<1>(RTREG, temp); }); break; + case 0x32: /* LWC2 */ load(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<2>(RTREG, temp); }); break; + case 0x33: /* LWC3 */ load(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(SIMMVAL + RSVAL, get_cop_reg<1>(RTREG)); break; + case 0x3a: /* LWC2 */ store(SIMMVAL + RSVAL, get_cop_reg<2>(RTREG)); break; + case 0x3b: /* LWC3 */ store(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(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(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(offset & ~3, [this, op, offset, shift](u32 temp) + { + store(offset & ~3, (temp & ~u32(0xffffffffU >> shift)) | (RTVAL >> shift)); + }); } + else + store(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(offset & ~3, [this, op, offset, shift](u32 temp) + { + store(offset & ~3, (temp & ~u32(0xffffffffU << shift)) | (RTVAL << shift)); + }); } + else + store(offset & ~3, RTVAL); } - - -void r3000_device_base::lwl_le() +template std::enable_if_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 std::enable_if_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 &&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(*device).set_endianness(_endianness); - -#define MCFG_R3000_BRCOND0_INPUT(_devcb) \ - downcast(*device).set_brcond0_input(DEVCB_##_devcb); - -#define MCFG_R3000_BRCOND1_INPUT(_devcb) \ - downcast(*device).set_brcond1_input(DEVCB_##_devcb); - -#define MCFG_R3000_BRCOND2_INPUT(_devcb) \ - downcast(*device).set_brcond2_input(DEVCB_##_devcb); - -#define MCFG_R3000_BRCOND3_INPUT(_devcb) \ - downcast(*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 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 devcb_base &set_brcond0_input(Object &&cb) { return m_in_brcond0.set_callback(std::forward(cb)); } - template devcb_base &set_brcond1_input(Object &&cb) { return m_in_brcond1.set_callback(std::forward(cb)); } - template devcb_base &set_brcond2_input(Object &&cb) { return m_in_brcond2.set_callback(std::forward(cb)); } - template devcb_base &set_brcond3_input(Object &&cb) { return m_in_brcond3.set_callback(std::forward(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 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 void handle_cop(u32 const op); + template u32 get_cop_reg(int const index) { return m_cpr[Coprocessor][index]; } + template void set_cop_reg(int const index, u32 const data) { m_cpr[Coprocessor][index] = data; } + template u32 get_cop_creg(int const index) { return m_ccr[Coprocessor][index]; } + template 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 std::enable_if_t>::value, void> load(u32 program_address, U &&apply); + template std::enable_if_t::value, void> store(u32 program_address, U data); + bool fetch(u32 program_address, std::function &&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 m_pr32; - std::function 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 m_icache; - std::vector 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 ¶ms) +offs_t mips1_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { 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 ¶ms) 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 m_maincpu; + required_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 m_maincpu; + required_device m_maincpu; required_device m_screen; required_device m_lk201; required_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(*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(*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 m_palette; required_device m_maincpu; - required_device m_subcpu; + required_device m_subcpu; required_shared_ptr m_shared; required_shared_ptr 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 m_gfxdecode; required_device m_palette; - required_device m_maincpu; + required_device m_maincpu; required_device m_soundcpu; required_region_ptr 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 m_cpu; + required_device m_cpu; required_device m_iop; required_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 m_maincpu; + required_device m_maincpu; required_device m_ata; required_shared_ptr m_bank_a; required_shared_ptr 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); } }, -- cgit v1.2.3