mirror of
https://github.com/holub/mame
synced 2025-04-23 17:00:53 +03:00
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:
parent
7a27335077
commit
444777967b
File diff suppressed because it is too large
Load Diff
@ -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__ */
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user