diff --git a/src/devices/cpu/mips/r3000.cpp b/src/devices/cpu/mips/r3000.cpp index 9ac90837ec2..efbfaf99704 100644 --- a/src/devices/cpu/mips/r3000.cpp +++ b/src/devices/cpu/mips/r3000.cpp @@ -116,6 +116,9 @@ //************************************************************************** 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") @@ -125,16 +128,17 @@ DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 //------------------------------------------------- -// r3000_device - constructor +// r3000_device_base - constructor //------------------------------------------------- -r3000_device::r3000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, chip_type chiptype) +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_chip_type(chiptype), + m_cpurev(cpurev), m_hasfpu(false), + m_fpurev(0), m_endianness(ENDIANNESS_BIG), m_pc(0), m_nextpc(0), @@ -144,6 +148,8 @@ r3000_device::r3000_device(const machine_config &mconfig, device_type type, cons 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), @@ -160,10 +166,10 @@ r3000_device::r3000_device(const machine_config &mconfig, device_type type, cons //------------------------------------------------- -// ~r3000_device - destructor +// ~r3000_device_base - destructor //------------------------------------------------- -r3000_device::~r3000_device() +r3000_device_base::~r3000_device_base() { } @@ -171,8 +177,30 @@ r3000_device::~r3000_device() // r2000_device - constructor //------------------------------------------------- -r2000_device::r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : r3000_device(mconfig, R2000, tag, owner, clock, CHIP_TYPE_R2000) { } +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) { } //------------------------------------------------- @@ -180,7 +208,7 @@ r2000_device::r2000_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- r3041_device::r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : r3000_device(mconfig, R3041, tag, owner, clock, CHIP_TYPE_R3041) { } + : r3000_device_base(mconfig, R3041, tag, owner, clock, 0x0700, 2048, 512) { } //------------------------------------------------- @@ -188,7 +216,7 @@ r3041_device::r3041_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- r3051_device::r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : r3000_device(mconfig, R3051, tag, owner, clock, CHIP_TYPE_R3051) { } + : r3000_device_base(mconfig, R3051, tag, owner, clock, 0x0200, 4096, 2048) { } //------------------------------------------------- @@ -196,23 +224,26 @@ r3051_device::r3051_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- r3052_device::r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : r3000_device(mconfig, R3052, tag, owner, clock, CHIP_TYPE_R3052) { } + : 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) - : r3000_device(mconfig, R3071, tag, owner, clock, CHIP_TYPE_R3071) { } +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) - : r3000_device(mconfig, R3081, tag, owner, clock, CHIP_TYPE_R3081) { } +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) +{ + set_fpurev(0x0300); +} //------------------------------------------------- @@ -220,7 +251,7 @@ r3081_device::r3081_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : r3000_device(mconfig, SONYPS2_IOP, tag, owner, clock, CHIP_TYPE_IOP) + : r3000_device_base(mconfig, SONYPS2_IOP, tag, owner, clock, 0x001f, 4096, 1024) { m_endianness = ENDIANNESS_LITTLE; } @@ -230,7 +261,7 @@ iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t // device_start - start up the device //------------------------------------------------- -void r3000_device::device_start() +void r3000_device_base::device_start() { // get our address spaces m_program = &space(AS_PROGRAM); @@ -247,56 +278,6 @@ void r3000_device::device_start() m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); }; } - // determine the cache sizes - switch (m_chip_type) - { - case CHIP_TYPE_R2000: - { - m_icache_size = 32768; // external - m_dcache_size = 32768; // external - break; - } - case CHIP_TYPE_R3041: - { - m_icache_size = 2048; - m_dcache_size = 512; - break; - } - case CHIP_TYPE_R3051: - { - m_icache_size = 4096; - m_dcache_size = 2048; - break; - } - case CHIP_TYPE_R3052: - { - m_icache_size = 8192; - m_dcache_size = 2048; - break; - } - - // TODO: R3071 and R3081 have configurable cache sizes - case CHIP_TYPE_R3071: - { - m_icache_size = 16384; // or 8kB - m_dcache_size = 4096; // or 8kB - break; - } - case CHIP_TYPE_R3081: - { - m_icache_size = 16384; // or 8kB - m_dcache_size = 4096; // or 8kB - m_hasfpu = true; - break; - } - case CHIP_TYPE_IOP: - { - m_icache_size = 4096; - m_dcache_size = 1024; - break; - } - } - // allocate cache memory m_icache.resize(m_icache_size/4); m_dcache.resize(m_dcache_size/4); @@ -305,40 +286,40 @@ void r3000_device::device_start() m_cache_size = m_dcache_size; // set up memory handlers - m_memory_hand.m_read_byte = &r3000_device::readmem; - m_memory_hand.m_read_word = &r3000_device::readmem_word; - m_memory_hand.m_read_dword = &r3000_device::readmem_dword; - m_memory_hand.m_write_byte = &r3000_device::writemem; - m_memory_hand.m_write_word = &r3000_device::writemem_word; - m_memory_hand.m_write_dword = &r3000_device::writemem_dword; + 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::lwl_be; - m_lwr = &r3000_device::lwr_be; - m_swl = &r3000_device::swl_be; - m_swr = &r3000_device::swr_be; + 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::readcache_be; - m_cache_hand.m_read_word = &r3000_device::readcache_be_word; - m_cache_hand.m_read_dword = &r3000_device::readcache_be_dword; - m_cache_hand.m_write_byte = &r3000_device::writecache_be; - m_cache_hand.m_write_word = &r3000_device::writecache_be_word; - m_cache_hand.m_write_dword = &r3000_device::writecache_be_dword; + 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::lwl_le; - m_lwr = &r3000_device::lwr_le; - m_swl = &r3000_device::swl_le; - m_swr = &r3000_device::swr_le; + 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::readcache_le; - m_cache_hand.m_read_word = &r3000_device::readcache_le_word; - m_cache_hand.m_read_dword = &r3000_device::readcache_le_dword; - m_cache_hand.m_write_byte = &r3000_device::writecache_le; - m_cache_hand.m_write_word = &r3000_device::writecache_le_word; - m_cache_hand.m_write_dword = &r3000_device::writecache_le_dword; + 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 @@ -400,12 +381,16 @@ void r3000_device::device_start() 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::device_post_load() +void r3000_device_base::device_post_load() { if (m_cpr[0][COP0_Status] & SR_IsC) m_cur = &m_cache_hand; @@ -418,7 +403,7 @@ void r3000_device::device_post_load() // device_reset - reset the device //------------------------------------------------- -void r3000_device::device_reset() +void r3000_device_base::device_reset() { // initialize the rest of the config m_cur = &m_memory_hand; @@ -426,16 +411,9 @@ void r3000_device::device_reset() // initialize the state m_pc = 0xbfc00000; m_nextpc = ~0; - m_cpr[0][COP0_PRId] = 0x0200; m_cpr[0][COP0_Status] = 0x0000; } -void iop_device::device_reset() -{ - r3000_device::device_reset(); - m_cpr[0][COP0_PRId] = 0x1f; -} - //------------------------------------------------- // memory_space_config - return the configuration @@ -443,7 +421,7 @@ void iop_device::device_reset() // the space doesn't exist //------------------------------------------------- -device_memory_interface::space_config_vector r3000_device::memory_space_config() const +device_memory_interface::space_config_vector r3000_device_base::memory_space_config() const { return space_config_vector { std::make_pair(AS_PROGRAM, (m_endianness == ENDIANNESS_BIG) ? &m_program_config_be : &m_program_config_le) @@ -456,7 +434,7 @@ device_memory_interface::space_config_vector r3000_device::memory_space_config() // after it has been set //------------------------------------------------- -void r3000_device::state_import(const device_state_entry &entry) +void r3000_device_base::state_import(const device_state_entry &entry) { switch (entry.index()) { @@ -464,7 +442,7 @@ void r3000_device::state_import(const device_state_entry &entry) break; default: - fatalerror("r3000_device::state_import called for unexpected value\n"); + fatalerror("r3000_device_base::state_import called for unexpected value\n"); } } @@ -473,7 +451,7 @@ void r3000_device::state_import(const device_state_entry &entry) // state_export - export state out of the device //------------------------------------------------- -void r3000_device::state_export(const device_state_entry &entry) +void r3000_device_base::state_export(const device_state_entry &entry) { switch (entry.index()) { @@ -481,7 +459,7 @@ void r3000_device::state_export(const device_state_entry &entry) break; default: - fatalerror("r3000_device::state_export called for unexpected value\n"); + fatalerror("r3000_device_base::state_export called for unexpected value\n"); } } @@ -491,7 +469,7 @@ void r3000_device::state_export(const device_state_entry &entry) // for the debugger //------------------------------------------------- -void r3000_device::state_string_export(const device_state_entry &entry, std::string &str) const +void r3000_device_base::state_string_export(const device_state_entry &entry, std::string &str) const { switch (entry.index()) { @@ -506,7 +484,7 @@ void r3000_device::state_string_export(const device_state_entry &entry, std::str // helper function //------------------------------------------------- -std::unique_ptr r3000_device::create_disassembler() +std::unique_ptr r3000_device_base::create_disassembler() { return std::make_unique(); } @@ -516,47 +494,47 @@ std::unique_ptr r3000_device::create_disassembler() MEMORY ACCESSORS ***************************************************************************/ -inline uint32_t r3000_device::readop(offs_t pc) +inline uint32_t r3000_device_base::readop(offs_t pc) { return m_pr32(pc); } -uint8_t r3000_device::readmem(offs_t offset) +uint8_t r3000_device_base::readmem(offs_t offset) { if (SR & SR_IsC) return 0; return m_program->read_byte(offset); } -uint16_t r3000_device::readmem_word(offs_t offset) +uint16_t r3000_device_base::readmem_word(offs_t offset) { if (SR & SR_IsC) return 0; return m_program->read_word(offset); } -uint32_t r3000_device::readmem_dword(offs_t offset) +uint32_t r3000_device_base::readmem_dword(offs_t offset) { if (SR & SR_IsC) return 0; return m_program->read_dword(offset); } -void r3000_device::writemem(offs_t offset, uint8_t data) +void r3000_device_base::writemem(offs_t offset, uint8_t data) { if (SR & SR_IsC) return; m_program->write_byte(offset, data); } -void r3000_device::writemem_word(offs_t offset, uint16_t data) +void r3000_device_base::writemem_word(offs_t offset, uint16_t data) { if (SR & SR_IsC) return; m_program->write_word(offset, data); } -void r3000_device::writemem_dword(offs_t offset, uint32_t data) +void r3000_device_base::writemem_dword(offs_t offset, uint32_t data) { if (SR & SR_IsC) return; @@ -568,43 +546,43 @@ void r3000_device::writemem_dword(offs_t offset, uint32_t data) BIG ENDIAN CACHE I/O ***************************************************************************/ -uint8_t r3000_device::readcache_be(offs_t offset) +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; } -uint16_t r3000_device::readcache_be_word(offs_t offset) +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; } -uint32_t r3000_device::readcache_be_dword(offs_t offset) +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; } -void r3000_device::writecache_be(offs_t offset, uint8_t data) +void r3000_device_base::writecache_be(offs_t offset, uint8_t data) { offset &= 0x1fffffff; if (offset * 4 < m_cache_size) m_cache[BYTE4_XOR_BE(offset)] = data; } -void r3000_device::writecache_be_word(offs_t offset, uint16_t data) +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; } -void r3000_device::writecache_be_dword(offs_t offset, uint32_t data) +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; } -uint8_t r3000_device::readcache_le(offs_t offset) +uint8_t r3000_device_base::readcache_le(offs_t offset) { offset &= 0x1fffffff; return (offset * 4 < m_cache_size) ? m_cache[BYTE4_XOR_LE(offset)] : 0xff; @@ -615,31 +593,31 @@ uint8_t r3000_device::readcache_le(offs_t offset) LITTLE ENDIAN CACHE I/O ***************************************************************************/ -uint16_t r3000_device::readcache_le_word(offs_t offset) +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; } -uint32_t r3000_device::readcache_le_dword(offs_t offset) +uint32_t r3000_device_base::readcache_le_dword(offs_t offset) { offset &= 0x1fffffff; return (offset * 4 < m_cache_size) ? *(uint32_t *)&m_cache[offset] : 0xffffffff; } -void r3000_device::writecache_le(offs_t offset, uint8_t data) +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; } -void r3000_device::writecache_le_word(offs_t offset, uint16_t data) +void r3000_device_base::writecache_le_word(offs_t offset, uint16_t data) { offset &= 0x1fffffff; if (offset * 4 < m_cache_size) *(uint16_t *)&m_cache[WORD_XOR_LE(offset)] = data; } -void r3000_device::writecache_le_dword(offs_t offset, uint32_t data) +void r3000_device_base::writecache_le_dword(offs_t offset, uint32_t data) { offset &= 0x1fffffff; if (offset * 4 < m_cache_size) *(uint32_t *)&m_cache[offset] = data; @@ -650,7 +628,7 @@ void r3000_device::writecache_le_dword(offs_t offset, uint32_t data) EXECEPTION HANDLING ***************************************************************************/ -inline void r3000_device::generate_exception(int exception, bool backup) +inline void r3000_device_base::generate_exception(int exception, bool backup) { // set the exception PC m_cpr[0][COP0_EPC] = backup ? m_ppc : m_pc; @@ -681,7 +659,7 @@ inline void r3000_device::generate_exception(int exception, bool backup) } -inline void r3000_device::invalid_instruction() +inline void r3000_device_base::invalid_instruction() { generate_exception(EXCEPTION_INVALIDOP, true); } @@ -691,14 +669,14 @@ inline void r3000_device::invalid_instruction() IRQ HANDLING ***************************************************************************/ -void r3000_device::check_irqs() +void r3000_device_base::check_irqs() { if ((CAUSE & SR & 0xff00) && (SR & SR_IEc)) generate_exception(EXCEPTION_INTERRUPT, false); } -void r3000_device::set_irq_line(int irqline, int state) +void r3000_device_base::set_irq_line(int irqline, int state) { if (state != CLEAR_LINE) CAUSE |= 0x400 << irqline; @@ -713,12 +691,12 @@ void r3000_device::set_irq_line(int irqline, int state) COP0 (SYSTEM) EXECUTION HANDLING ***************************************************************************/ -inline uint32_t r3000_device::get_cop0_reg(int idx) +inline uint32_t r3000_device_base::get_cop0_reg(int idx) { return m_cpr[0][idx]; } -inline void r3000_device::set_cop0_reg(int idx, uint32_t val) +inline void r3000_device_base::set_cop0_reg(int idx, uint32_t val) { if (idx == COP0_Cause) { @@ -754,21 +732,21 @@ inline void r3000_device::set_cop0_reg(int idx, uint32_t val) // update interrupts check_irqs(); } - else + else if (idx != COP0_PRId) m_cpr[0][idx] = val; } -inline uint32_t r3000_device::get_cop0_creg(int idx) +inline uint32_t r3000_device_base::get_cop0_creg(int idx) { return m_ccr[0][idx]; } -inline void r3000_device::set_cop0_creg(int idx, uint32_t val) +inline void r3000_device_base::set_cop0_creg(int idx, uint32_t val) { m_ccr[0][idx] = val; } -inline void r3000_device::handle_cop0() +inline void r3000_device_base::handle_cop0() { if (!(SR & SR_COP0) && (SR & SR_KUc)) generate_exception(EXCEPTION_BADCOP, true); @@ -825,27 +803,28 @@ inline void r3000_device::handle_cop0() COP1 (FPU) EXECUTION HANDLING ***************************************************************************/ -inline uint32_t r3000_device::get_cop1_reg(int idx) +inline uint32_t r3000_device_base::get_cop1_reg(int idx) { return m_cpr[1][idx]; } -inline void r3000_device::set_cop1_reg(int idx, uint32_t val) +inline void r3000_device_base::set_cop1_reg(int idx, uint32_t val) { m_cpr[1][idx] = val; } -inline uint32_t r3000_device::get_cop1_creg(int idx) +inline uint32_t r3000_device_base::get_cop1_creg(int idx) { return m_ccr[1][idx]; } -inline void r3000_device::set_cop1_creg(int idx, uint32_t val) +inline void r3000_device_base::set_cop1_creg(int idx, uint32_t val) { - m_ccr[1][idx] = val; + if (idx) + m_ccr[1][idx] = val; } -inline void r3000_device::handle_cop1() +inline void r3000_device_base::handle_cop1() { if (!(SR & SR_COP1)) generate_exception(EXCEPTION_BADCOP, true); @@ -893,27 +872,27 @@ inline void r3000_device::handle_cop1() COP2 (CUSTOM) EXECUTION HANDLING ***************************************************************************/ -inline uint32_t r3000_device::get_cop2_reg(int idx) +inline uint32_t r3000_device_base::get_cop2_reg(int idx) { return m_cpr[2][idx]; } -inline void r3000_device::set_cop2_reg(int idx, uint32_t val) +inline void r3000_device_base::set_cop2_reg(int idx, uint32_t val) { m_cpr[2][idx] = val; } -inline uint32_t r3000_device::get_cop2_creg(int idx) +inline uint32_t r3000_device_base::get_cop2_creg(int idx) { return m_ccr[2][idx]; } -inline void r3000_device::set_cop2_creg(int idx, uint32_t val) +inline void r3000_device_base::set_cop2_creg(int idx, uint32_t val) { m_ccr[2][idx] = val; } -inline void r3000_device::handle_cop2() +inline void r3000_device_base::handle_cop2() { if (!(SR & SR_COP2)) generate_exception(EXCEPTION_BADCOP, true); @@ -959,27 +938,27 @@ inline void r3000_device::handle_cop2() COP3 (CUSTOM) EXECUTION HANDLING ***************************************************************************/ -inline uint32_t r3000_device::get_cop3_reg(int idx) +inline uint32_t r3000_device_base::get_cop3_reg(int idx) { return m_cpr[3][idx]; } -inline void r3000_device::set_cop3_reg(int idx, uint32_t val) +inline void r3000_device_base::set_cop3_reg(int idx, uint32_t val) { m_cpr[3][idx] = val; } -inline uint32_t r3000_device::get_cop3_creg(int idx) +inline uint32_t r3000_device_base::get_cop3_creg(int idx) { return m_ccr[3][idx]; } -inline void r3000_device::set_cop3_creg(int idx, uint32_t val) +inline void r3000_device_base::set_cop3_creg(int idx, uint32_t val) { m_ccr[3][idx] = val; } -inline void r3000_device::handle_cop3() +inline void r3000_device_base::handle_cop3() { if (!(SR & SR_COP3)) generate_exception(EXCEPTION_BADCOP, true); @@ -1030,7 +1009,7 @@ inline void r3000_device::handle_cop3() // cycles it takes for one instruction to execute //------------------------------------------------- -uint32_t r3000_device::execute_min_cycles() const +uint32_t r3000_device_base::execute_min_cycles() const { return 1; } @@ -1041,7 +1020,7 @@ uint32_t r3000_device::execute_min_cycles() const // cycles it takes for one instruction to execute //------------------------------------------------- -uint32_t r3000_device::execute_max_cycles() const +uint32_t r3000_device_base::execute_max_cycles() const { return 40; } @@ -1052,7 +1031,7 @@ uint32_t r3000_device::execute_max_cycles() const // input/interrupt lines //------------------------------------------------- -uint32_t r3000_device::execute_input_lines() const +uint32_t r3000_device_base::execute_input_lines() const { return 6; } @@ -1062,7 +1041,7 @@ uint32_t r3000_device::execute_input_lines() const // execute_set_input //------------------------------------------------- -void r3000_device::execute_set_input(int inputnum, int state) +void r3000_device_base::execute_set_input(int inputnum, int state) { set_irq_line(inputnum, state); } @@ -1072,7 +1051,7 @@ void r3000_device::execute_set_input(int inputnum, int state) // execute_run //------------------------------------------------- -void r3000_device::execute_run() +void r3000_device_base::execute_run() { // count cycles and interrupt cycles m_icount -= m_interrupt_cycles; @@ -1285,7 +1264,7 @@ void r3000_device::execute_run() COMPLEX OPCODE IMPLEMENTATIONS ***************************************************************************/ -void r3000_device::lwl_be() +void r3000_device_base::lwl_be() { offs_t offs = SIMMVAL + RSVAL; uint32_t temp = RLONG(offs & ~3); @@ -1300,7 +1279,7 @@ void r3000_device::lwl_be() } } -void r3000_device::lwr_be() +void r3000_device_base::lwr_be() { offs_t offs = SIMMVAL + RSVAL; uint32_t temp = RLONG(offs & ~3); @@ -1315,7 +1294,7 @@ void r3000_device::lwr_be() } } -void r3000_device::swl_be() +void r3000_device_base::swl_be() { offs_t offs = SIMMVAL + RSVAL; if (!(offs & 3)) WLONG(offs, RTVAL); @@ -1328,7 +1307,7 @@ void r3000_device::swl_be() } -void r3000_device::swr_be() +void r3000_device_base::swr_be() { offs_t offs = SIMMVAL + RSVAL; if ((offs & 3) == 3) WLONG(offs & ~3, RTVAL); @@ -1342,7 +1321,7 @@ void r3000_device::swr_be() -void r3000_device::lwl_le() +void r3000_device_base::lwl_le() { offs_t offs = SIMMVAL + RSVAL; uint32_t temp = RLONG(offs & ~3); @@ -1357,7 +1336,7 @@ void r3000_device::lwl_le() } } -void r3000_device::lwr_le() +void r3000_device_base::lwr_le() { offs_t offs = SIMMVAL + RSVAL; uint32_t temp = RLONG(offs & ~3); @@ -1372,7 +1351,7 @@ void r3000_device::lwr_le() } } -void r3000_device::swl_le() +void r3000_device_base::swl_le() { offs_t offs = SIMMVAL + RSVAL; if (!(offs & 3)) WLONG(offs, RTVAL); @@ -1384,7 +1363,7 @@ void r3000_device::swl_le() } } -void r3000_device::swr_le() +void r3000_device_base::swr_le() { offs_t offs = SIMMVAL + RSVAL; if ((offs & 3) == 3) WLONG(offs & ~3, RTVAL); diff --git a/src/devices/cpu/mips/r3000.h b/src/devices/cpu/mips/r3000.h index cf495d188df..1ba98c11eea 100644 --- a/src/devices/cpu/mips/r3000.h +++ b/src/devices/cpu/mips/r3000.h @@ -19,19 +19,19 @@ ***************************************************************************/ #define MCFG_R3000_ENDIANNESS(_endianness) \ - downcast(*device).set_endianness(_endianness); + downcast(*device).set_endianness(_endianness); #define MCFG_R3000_BRCOND0_INPUT(_devcb) \ - downcast(*device).set_brcond0_input(DEVCB_##_devcb); + downcast(*device).set_brcond0_input(DEVCB_##_devcb); #define MCFG_R3000_BRCOND1_INPUT(_devcb) \ - downcast(*device).set_brcond1_input(DEVCB_##_devcb); + downcast(*device).set_brcond1_input(DEVCB_##_devcb); #define MCFG_R3000_BRCOND2_INPUT(_devcb) \ - downcast(*device).set_brcond2_input(DEVCB_##_devcb); + downcast(*device).set_brcond2_input(DEVCB_##_devcb); #define MCFG_R3000_BRCOND3_INPUT(_devcb) \ - downcast(*device).set_brcond3_input(DEVCB_##_devcb); + downcast(*device).set_brcond3_input(DEVCB_##_devcb); /*************************************************************************** @@ -64,16 +64,17 @@ enum // TYPE DEFINITIONS //************************************************************************** -// ======================> r3000_device +// ======================> r3000_device_base -class r3000_device : public cpu_device +class r3000_device_base : public cpu_device { public: // construction/destruction - virtual ~r3000_device(); + virtual ~r3000_device_base(); // inline configuration helpers void set_endianness(endianness_t endianness) { m_endianness = endianness; } + void set_fpurev(uint32_t revision) { m_hasfpu = true; m_fpurev = revision; } 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)); } @@ -85,18 +86,7 @@ public: auto in_brcond3() { return m_in_brcond3.bind(); } protected: - enum chip_type - { - CHIP_TYPE_R2000, - CHIP_TYPE_R3041, - CHIP_TYPE_R3051, - CHIP_TYPE_R3052, - CHIP_TYPE_R3071, - CHIP_TYPE_R3081, - CHIP_TYPE_IOP - }; - - r3000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, chip_type chiptype); + 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); // device-level overrides virtual void device_start() override; @@ -124,12 +114,12 @@ protected: // memory accessors struct r3000_data_accessors { - uint8_t (r3000_device::*m_read_byte)(offs_t byteaddress); - uint16_t (r3000_device::*m_read_word)(offs_t byteaddress); - uint32_t (r3000_device::*m_read_dword)(offs_t byteaddress); - void (r3000_device::*m_write_byte)(offs_t byteaddress, uint8_t data); - void (r3000_device::*m_write_word)(offs_t byteaddress, uint16_t data); - void (r3000_device::*m_write_dword)(offs_t byteaddress, uint32_t data); + 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); @@ -204,8 +194,9 @@ protected: std::function m_prptr; // configuration - chip_type m_chip_type; + uint32_t m_cpurev; bool m_hasfpu; + uint32_t m_fpurev; endianness_t m_endianness; // core registers @@ -226,10 +217,10 @@ protected: int m_interrupt_cycles; // endian-dependent load/store - void (r3000_device::*m_lwl)(); - void (r3000_device::*m_lwr)(); - void (r3000_device::*m_swl)(); - void (r3000_device::*m_swr)(); + 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; @@ -241,8 +232,8 @@ protected: std::vector m_icache; std::vector m_dcache; size_t m_cache_size; - size_t m_icache_size; - size_t m_dcache_size; + size_t const m_icache_size; + size_t const m_dcache_size; // I/O devcb_read_line m_in_brcond0; @@ -251,18 +242,45 @@ protected: devcb_read_line m_in_brcond3; }; -// ======================> r3041_device +// ======================> r2000_device -class r2000_device : public r3000_device +class r2000_device : public r3000_device_base { public: - r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + 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); +}; + + +// ======================> r2000a_device + +class r2000a_device : public r3000_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); +}; + + +// ======================> r3000_device + +class r3000_device : public r3000_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); +}; + + +// ======================> r3000a_device + +class r3000a_device : public r3000_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); }; // ======================> r3041_device -class r3041_device : public r3000_device +class r3041_device : public r3000_device_base { public: r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -271,7 +289,7 @@ public: // ======================> r3051_device -class r3051_device : public r3000_device +class r3051_device : public r3000_device_base { public: r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -280,7 +298,7 @@ public: // ======================> r3052_device -class r3052_device : public r3000_device +class r3052_device : public r3000_device_base { public: r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -289,37 +307,37 @@ public: // ======================> r3071_device -class r3071_device : public r3000_device +class r3071_device : public r3000_device_base { public: - r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + 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); }; // ======================> r3081_device -class r3081_device : public r3000_device +class r3081_device : public r3000_device_base { public: - r3081_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, uint32_t clock, size_t icache_size = 16384, size_t dcache_size = 4096); }; // ======================> iop_device -class iop_device : public r3000_device +class iop_device : public r3000_device_base { public: iop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual void device_reset() override; }; // device type definition DECLARE_DEVICE_TYPE(R2000, r2000_device) +DECLARE_DEVICE_TYPE(R2000A, r2000a_device) +DECLARE_DEVICE_TYPE(R3000, r3000_device) +DECLARE_DEVICE_TYPE(R3000A, r3000a_device) DECLARE_DEVICE_TYPE(R3041, r3041_device) DECLARE_DEVICE_TYPE(R3051, r3051_device) DECLARE_DEVICE_TYPE(R3052, r3052_device)