Modernised the R3000 core: [Phil Bennett]

* The following variants are supported: R3041, R3051, R3052, R3071 and R3081
 * Endianness is now specified by MCFG_R3000_ENDIANNESS() (default is big-endian)
 * Removed configuration struct. Cache sizes and FPU availability are now determined from the CPU type
 * Added state saving
 * Added BrCond input callbacks
This commit is contained in:
Phil Bennett 2013-01-19 12:25:09 +00:00
parent 7a27335077
commit 444777967b
7 changed files with 1149 additions and 965 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,10 +10,24 @@
#define __R3000_H__
/***************************************************************************
COMPILE-TIME DEFINITIONS
INTERFACE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_R3000_ENDIANNESS(_endianness) \
r3000_device::static_set_endianness(*device, _endianness);
#define MCFG_R3000_BRCOND0_INPUT(_devcb) \
devcb = &r3000_device::static_set_brcond0_input(*device, DEVCB2_##_devcb);
#define MCFG_R3000_BRCOND1_INPUT(_devcb) \
devcb = &r3000_device::static_set_brcond1_input(*device, DEVCB2_##_devcb);
#define MCFG_R3000_BRCOND2_INPUT(_devcb) \
devcb = &r3000_device::static_set_brcond2_input(*device, DEVCB2_##_devcb);
#define MCFG_R3000_BRCOND3_INPUT(_devcb) \
devcb = &r3000_device::static_set_brcond3_input(*device, DEVCB2_##_devcb);
/***************************************************************************
@ -42,26 +56,262 @@ enum
#define R3000_IRQ5 5 /* IRQ5 */
/***************************************************************************
STRUCTURES
***************************************************************************/
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
struct r3000_cpu_core
// ======================> r3000_device
class r3000_device : public cpu_device
{
UINT8 hasfpu; /* 1 if we have an FPU, 0 otherwise */
size_t icache; /* code cache size */
size_t dcache; /* data cache size */
protected:
enum chip_type
{
CHIP_TYPE_R3041,
CHIP_TYPE_R3051,
CHIP_TYPE_R3052,
CHIP_TYPE_R3071,
CHIP_TYPE_R3081,
};
// construction/destruction
r3000_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, chip_type chiptype);
virtual ~r3000_device();
public:
// inline configuration helpers
static void static_set_endianness(device_t &device, endianness_t endianness)
{
downcast<r3000_device &>(device).m_endianness = endianness;
}
template<class _Object> static devcb2_base &static_set_brcond0_input(device_t &device, _Object object)
{
return downcast<r3000_device &>(device).m_in_brcond0.set_callback(object);
}
template<class _Object> static devcb2_base &static_set_brcond1_input(device_t &device, _Object object)
{
return downcast<r3000_device &>(device).m_in_brcond1.set_callback(object);
}
template<class _Object> static devcb2_base &static_set_brcond2_input(device_t &device, _Object object)
{
return downcast<r3000_device &>(device).m_in_brcond2.set_callback(object);
}
template<class _Object> static devcb2_base &static_set_brcond3_input(device_t &device, _Object object)
{
return downcast<r3000_device &>(device).m_in_brcond3.set_callback(object);
}
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void device_post_load();
// device_execute_interface overrides
virtual UINT32 execute_min_cycles() const;
virtual UINT32 execute_max_cycles() const;
virtual UINT32 execute_input_lines() const;
virtual void execute_run();
virtual void execute_set_input(int inputnum, int state);
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
// device_state_interface overrides
virtual void state_import(const device_state_entry &entry);
virtual void state_export(const device_state_entry &entry);
virtual void state_string_export(const device_state_entry &entry, astring &string);
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const;
virtual UINT32 disasm_max_opcode_bytes() const;
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
// memory accessors
struct r3000_data_accessors
{
UINT8 (r3000_device::*m_read_byte)(offs_t byteaddress);
UINT16 (r3000_device::*m_read_word)(offs_t byteaddress);
UINT32 (r3000_device::*m_read_dword)(offs_t byteaddress);
void (r3000_device::*m_write_byte)(offs_t byteaddress, UINT8 data);
void (r3000_device::*m_write_word)(offs_t byteaddress, UINT16 data);
void (r3000_device::*m_write_dword)(offs_t byteaddress, UINT32 data);
};
UINT32 readop(off_t pc);
UINT8 readmem(offs_t offset);
UINT16 readmem_word(offs_t offset);
UINT32 readmem_dword(offs_t offset);
void writemem(offs_t offset, UINT8 data);
void writemem_word(offs_t offset, UINT16 data);
void writemem_dword(offs_t offset, UINT32 data);
UINT8 readcache_be(offs_t offset);
UINT16 readcache_be_word(offs_t offset);
UINT32 readcache_be_dword(offs_t offset);
void writecache_be(offs_t offset, UINT8 data);
void writecache_be_word(offs_t offset, UINT16 data);
void writecache_be_dword(offs_t offset, UINT32 data);
UINT8 readcache_le(offs_t offset);
UINT16 readcache_le_word(offs_t offset);
UINT32 readcache_le_dword(offs_t offset);
void writecache_le(offs_t offset, UINT8 data);
void writecache_le_word(offs_t offset, UINT16 data);
void writecache_le_dword(offs_t offset, UINT32 data);
// interrupts
void generate_exception(int exception);
void check_irqs();
void set_irq_line(int irqline, int state);
void invalid_instruction();
// instructions
UINT32 get_cop0_reg(int idx);
void set_cop0_reg(int idx, UINT32 val);
UINT32 get_cop0_creg(int idx);
void set_cop0_creg(int idx, UINT32 val);
void handle_cop0();
UINT32 get_cop1_reg(int idx);
void set_cop1_reg(int idx, UINT32 val);
UINT32 get_cop1_creg(int idx);
void set_cop1_creg(int idx, UINT32 val);
void handle_cop1();
UINT32 get_cop2_reg(int idx);
void set_cop2_reg(int idx, UINT32 val);
UINT32 get_cop2_creg(int idx);
void set_cop2_creg(int idx, UINT32 val);
void handle_cop2();
UINT32 get_cop3_reg(int idx);
void set_cop3_reg(int idx, UINT32 val);
UINT32 get_cop3_creg(int idx);
void set_cop3_creg(int idx, UINT32 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();
// address spaces
const address_space_config m_program_config_be;
const address_space_config m_program_config_le;
address_space *m_program;
direct_read_data *m_direct;
// configuration
chip_type m_chip_type;
bool m_hasfpu;
endianness_t m_endianness;
// core registers
UINT32 m_pc;
UINT32 m_nextpc;
UINT32 m_hi;
UINT32 m_lo;
UINT32 m_r[32];
// COP registers
UINT32 m_cpr[4][32];
UINT32 m_ccr[4][32];
// internal stuff
UINT32 m_ppc;
UINT32 m_op;
int m_icount;
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)();
// memory accesses
r3000_data_accessors *m_cur;
r3000_data_accessors m_memory_hand;
r3000_data_accessors m_cache_hand;
// cache memory
UINT32 * m_cache;
UINT32 * m_icache;
UINT32 * m_dcache;
size_t m_cache_size;
size_t m_icache_size;
size_t m_dcache_size;
// I/O
devcb2_read_line m_in_brcond0;
devcb2_read_line m_in_brcond1;
devcb2_read_line m_in_brcond2;
devcb2_read_line m_in_brcond3;
};
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
// ======================> r3041_device
DECLARE_LEGACY_CPU_DEVICE(R3000BE, r3000be);
DECLARE_LEGACY_CPU_DEVICE(R3000LE, r3000le);
class r3041_device : public r3000_device
{
public:
r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
DECLARE_LEGACY_CPU_DEVICE(R3041BE, r3041be);
DECLARE_LEGACY_CPU_DEVICE(R3041LE, r3041le);
// ======================> r3051_device
class r3051_device : public r3000_device
{
public:
r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
// ======================> r3052_device
class r3052_device : public r3000_device
{
public:
r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
// ======================> r3071_device
class r3071_device : public r3000_device
{
public:
r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
// ======================> r3081_device
class r3081_device : public r3000_device
{
public:
r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};
// device type definition
extern const device_type R3041;
extern const device_type R3051;
extern const device_type R3052;
extern const device_type R3071;
extern const device_type R3081;
#endif /* __R3000_H__ */

View File

@ -1545,15 +1545,7 @@ INPUT_PORTS_END
*
*************************************/
static const r3000_cpu_core r3000_config =
{
0, /* 1 if we have an FPU, 0 otherwise */
4096, /* code cache size */
4096 /* data cache size */
};
static const jaguar_cpu_config gpu_config =
static const jaguar_cpu_config gpu_config =
{
&jaguar_state::gpu_cpu_int
};
@ -1567,8 +1559,8 @@ static const jaguar_cpu_config dsp_config =
static MACHINE_CONFIG_START( cojagr3k, jaguar_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", R3041BE, R3000_CLOCK)
MCFG_CPU_CONFIG(r3000_config)
MCFG_CPU_ADD("maincpu", R3041, R3000_CLOCK)
MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
MCFG_CPU_PROGRAM_MAP(r3000_map)
MCFG_CPU_ADD("gpu", JAGUARGPU, COJAG_CLOCK/2)
@ -2263,7 +2255,7 @@ void jaguar_state::cojag_common_init(UINT16 gpu_jump_offs, UINT16 spin_pc)
m_is_cojag = true;
/* copy over the ROM */
m_is_r3000 = (m_main_cpu->type() == R3041BE);
m_is_r3000 = (m_main_cpu->type() == R3041);
/* install synchronization hooks for GPU */
if (m_is_r3000)

View File

@ -402,19 +402,11 @@ INPUT_PORTS_END
*
*************************************/
static const r3000_cpu_core r3000_config =
{
0, /* 1 if we have an FPU, 0 otherwise */
4096, /* code cache size */
4096 /* data cache size */
};
static MACHINE_CONFIG_START( policetr, policetr_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", R3000BE, MASTER_CLOCK/2)
MCFG_CPU_CONFIG(r3000_config)
MCFG_CPU_ADD("maincpu", R3041, MASTER_CLOCK/2)
MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
MCFG_CPU_PROGRAM_MAP(policetr_map)
MCFG_CPU_VBLANK_INT_DRIVER("screen", policetr_state, irq4_gen)

View File

@ -326,13 +326,6 @@ static const st0016_interface st0016_config =
&st0016_charram
};
static const r3000_cpu_core r3000_config =
{
0,
4096, /* code cache size */
2048 /* data cache size */
};
MACHINE_RESET_MEMBER(speglsht_state,speglsht)
{
memset(m_shared,0,0x1000);
@ -393,8 +386,8 @@ static MACHINE_CONFIG_START( speglsht, speglsht_state )
MCFG_CPU_VBLANK_INT_DRIVER("screen", speglsht_state, irq0_line_hold)
MCFG_CPU_ADD("sub", R3000LE, 25000000)
MCFG_CPU_CONFIG(r3000_config)
MCFG_CPU_ADD("sub", R3051, 25000000)
MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_CPU_PROGRAM_MAP(speglsht_mem)
MCFG_CPU_VBLANK_INT_DRIVER("screen", speglsht_state, irq4_line_assert)

View File

@ -501,13 +501,6 @@ static const st0016_interface st0016_config =
&st0016_charram
};
static const r3000_cpu_core r3000_config =
{
1, /* 1 if we have an FPU, 0 otherwise */
4096, /* code cache size */
4096 /* data cache size */
};
static const gfx_layout tile_16x8x8_layout =
{
16,8,
@ -545,8 +538,8 @@ static MACHINE_CONFIG_START( srmp5, srmp5_state )
MCFG_CPU_IO_MAP(st0016_io)
MCFG_CPU_VBLANK_INT_DRIVER("screen", srmp5_state, irq0_line_hold)
MCFG_CPU_ADD("sub", R3000LE, 25000000)
MCFG_CPU_CONFIG(r3000_config)
MCFG_CPU_ADD("sub", R3051, 25000000)
MCFG_R3000_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_CPU_PROGRAM_MAP(srmp5_mem)
MCFG_CPU_VBLANK_INT_DRIVER("screen", srmp5_state, irq4_line_assert)

View File

@ -115,19 +115,12 @@ static INPUT_PORTS_START( turrett )
INPUT_PORTS_END
static const r3000_cpu_core r3000_config =
{
0, /* 1 if we have an FPU, 0 otherwise */
2048, /* code cache size */
512 /* data cache size */
};
static MACHINE_CONFIG_START( turrett, turrett_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", R3041BE, R3041_CLOCK)
MCFG_CPU_ADD("maincpu", R3041, R3041_CLOCK)
MCFG_R3000_ENDIANNESS(ENDIANNESS_BIG)
MCFG_CPU_PROGRAM_MAP(cpu_map)
MCFG_CPU_CONFIG(r3000_config)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)