r3000: improve configurability (nw)

* add R2000A, R3000, R3000A device types
* configurable cache sizing
* configurable fpu
* improve device type and cpu/fpu id logic
This commit is contained in:
Patrick Mackinlay 2018-11-01 15:10:25 +07:00
parent 8740d148c1
commit 427272321e
2 changed files with 210 additions and 213 deletions

View File

@ -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<util::disasm_interface> r3000_device::create_disassembler()
std::unique_ptr<util::disasm_interface> r3000_device_base::create_disassembler()
{
return std::make_unique<r3000_disassembler>();
}
@ -516,47 +494,47 @@ std::unique_ptr<util::disasm_interface> 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);

View File

@ -19,19 +19,19 @@
***************************************************************************/
#define MCFG_R3000_ENDIANNESS(_endianness) \
downcast<r3000_device &>(*device).set_endianness(_endianness);
downcast<r3000_device_base &>(*device).set_endianness(_endianness);
#define MCFG_R3000_BRCOND0_INPUT(_devcb) \
downcast<r3000_device &>(*device).set_brcond0_input(DEVCB_##_devcb);
downcast<r3000_device_base &>(*device).set_brcond0_input(DEVCB_##_devcb);
#define MCFG_R3000_BRCOND1_INPUT(_devcb) \
downcast<r3000_device &>(*device).set_brcond1_input(DEVCB_##_devcb);
downcast<r3000_device_base &>(*device).set_brcond1_input(DEVCB_##_devcb);
#define MCFG_R3000_BRCOND2_INPUT(_devcb) \
downcast<r3000_device &>(*device).set_brcond2_input(DEVCB_##_devcb);
downcast<r3000_device_base &>(*device).set_brcond2_input(DEVCB_##_devcb);
#define MCFG_R3000_BRCOND3_INPUT(_devcb) \
downcast<r3000_device &>(*device).set_brcond3_input(DEVCB_##_devcb);
downcast<r3000_device_base &>(*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 <class Object> devcb_base &set_brcond0_input(Object &&cb) { return m_in_brcond0.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_brcond1_input(Object &&cb) { return m_in_brcond1.set_callback(std::forward<Object>(cb)); }
@ -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<const void * (offs_t)> 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<uint32_t> m_icache;
std::vector<uint32_t> 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)