mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
-r4000: Added basic R5000 support. [Ryan Holtz]
This commit is contained in:
parent
edc2024fc0
commit
c0d388dc09
@ -84,6 +84,7 @@
|
||||
DEFINE_DEVICE_TYPE(R4000, r4000_device, "r4000", "MIPS R4000")
|
||||
DEFINE_DEVICE_TYPE(R4400, r4400_device, "r4400", "MIPS R4400")
|
||||
DEFINE_DEVICE_TYPE(R4600, r4600_device, "r4600", "QED R4600")
|
||||
DEFINE_DEVICE_TYPE(R5000, r5000_device, "r5000", "MIPS R5000")
|
||||
|
||||
r4000_base_device::r4000_base_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size icache_size, cache_size dcache_size)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
@ -609,10 +610,7 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
break;
|
||||
|
||||
default:
|
||||
// * Operation codes marked with an asterisk cause reserved
|
||||
// instruction exceptions in all current implementations and are
|
||||
// reserved for future versions of the architecture.
|
||||
cpu_exception(EXCEPTION_RI);
|
||||
handle_reserved_instruction(op);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -816,7 +814,9 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
case 0x12: // COP2
|
||||
cp2_execute(op);
|
||||
break;
|
||||
//case 0x13: // *
|
||||
case 0x13: // COP1X
|
||||
cp1x_execute(op);
|
||||
break;
|
||||
case 0x14: // BEQL
|
||||
if (m_r[RSREG] == m_r[RTREG])
|
||||
{
|
||||
@ -1044,7 +1044,7 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
case 0x32: // LWC2
|
||||
cp2_execute(op);
|
||||
break;
|
||||
//case 0x33: // *
|
||||
// case 0x33: *
|
||||
case 0x34: // LLD
|
||||
load_linked<u64>(ADDR(m_r[RSREG], s16(op)),
|
||||
[this, op](u64 address, u64 data)
|
||||
@ -1119,6 +1119,33 @@ void r4000_base_device::cpu_execute(u32 const op)
|
||||
}
|
||||
}
|
||||
|
||||
void r4000_base_device::handle_reserved_instruction(u32 const op)
|
||||
{
|
||||
// Unahdnled operation codes cause reserved instruction
|
||||
// exceptions in all current implementations and are
|
||||
// reserved for future versions of the architecture.
|
||||
cpu_exception(EXCEPTION_RI);
|
||||
}
|
||||
|
||||
void r5000_device::handle_reserved_instruction(u32 const op)
|
||||
{
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0x33: // PREF (effective no-op)
|
||||
break;
|
||||
default:
|
||||
switch (op >> 26)
|
||||
{
|
||||
case 0x0a: // MOVN
|
||||
if (m_r[RTREG] == 0) { if (RDREG) m_r[RDREG] = m_r[RSREG]; }
|
||||
break;
|
||||
case 0x0b: // MOVZ
|
||||
if (m_r[RTREG] != 0) { if (RDREG) m_r[RDREG] = m_r[RSREG]; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void r4000_base_device::cpu_exception(u32 exception, u16 const vector)
|
||||
{
|
||||
if (exception != EXCEPTION_INT)
|
||||
@ -2601,6 +2628,186 @@ void r4000_base_device::cp1_execute(u32 const op)
|
||||
}
|
||||
}
|
||||
|
||||
void r4000_base_device::cp1x_execute(u32 const op)
|
||||
{
|
||||
if (!(SR & SR_CU1))
|
||||
{
|
||||
cpu_exception(EXCEPTION_CP1);
|
||||
return;
|
||||
}
|
||||
|
||||
logerror("cp1x not supported < R5000 (%s)\n", machine().describe_context());
|
||||
}
|
||||
|
||||
void r5000_device::cp1x_execute(u32 const op)
|
||||
{
|
||||
if (!(SR & SR_CU1))
|
||||
{
|
||||
cpu_exception(EXCEPTION_CP1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (op & 0x3f)
|
||||
{
|
||||
case 0x00: // LWXC1
|
||||
load<u32>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))),
|
||||
[this, op](u32 data)
|
||||
{
|
||||
if (SR & SR_FR)
|
||||
m_f[RTREG] = (m_f[RTREG] & ~0xffffffffULL) | data;
|
||||
else
|
||||
if (RTREG & 1)
|
||||
// load the high half of the even floating point register
|
||||
m_f[RTREG & ~1] = (u64(data) << 32) | u32(m_f[RTREG & ~1]);
|
||||
else
|
||||
// load the low half of the even floating point register
|
||||
m_f[RTREG & ~1] = (m_f[RTREG & ~1] & ~0xffffffffULL) | data;
|
||||
});
|
||||
break;
|
||||
case 0x01: // LDXC1
|
||||
load<u64>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))),
|
||||
[this, op](u64 data)
|
||||
{
|
||||
if ((SR & SR_FR) || !(RTREG & 1))
|
||||
m_f[RTREG] = data;
|
||||
});
|
||||
break;
|
||||
case 0x08: // SWXC1
|
||||
if (SR & SR_FR)
|
||||
store<u32>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))), u32(m_f[RTREG]));
|
||||
else
|
||||
if (RTREG & 1)
|
||||
// store the high half of the even floating point register
|
||||
store<u32>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))), u32(m_f[RTREG & ~1] >> 32));
|
||||
else
|
||||
// store the low half of the even floating point register
|
||||
store<u32>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))), u32(m_f[RTREG & ~1]));
|
||||
break;
|
||||
case 0x09: // SDXC1
|
||||
if ((SR & SR_FR) || !(RTREG & 1))
|
||||
store<u64>(s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG]))), m_f[RTREG]);
|
||||
break;
|
||||
case 0x0f: // PREFX
|
||||
// Do nothing for now (implementations are permitted to do this)
|
||||
break;
|
||||
case 0x20: // MADD.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fr = float32_t{ u32(m_f[FRREG]) };
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
float32_t const ft = float32_t{ u32(m_f[FTREG]) };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f32_add(f32_mul(fs, ft), fr).v);
|
||||
}
|
||||
break;
|
||||
case 0x21: // MADD.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fr = float64_t{ m_f[FRREG] };
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
float64_t const ft = float64_t{ m_f[FTREG] };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f64_add(f64_mul(fs, ft), fr).v);
|
||||
}
|
||||
break;
|
||||
case 0x28: // MSUB.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fr = float32_t{ u32(m_f[FRREG]) };
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
float32_t const ft = float32_t{ u32(m_f[FTREG]) };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f32_sub(f32_mul(fs, ft), fr).v);
|
||||
}
|
||||
break;
|
||||
case 0x29: // MSUB.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fr = float64_t{ m_f[FRREG] };
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
float64_t const ft = float64_t{ m_f[FTREG] };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f64_sub(f64_mul(fs, ft), fr).v);
|
||||
}
|
||||
break;
|
||||
case 0x30: // NMADD.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fr = float32_t{ u32(m_f[FRREG]) };
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
float32_t const ft = float32_t{ u32(m_f[FTREG]) };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f32_mul(f32_add(f32_mul(fs, ft), fr), i32_to_f32(-1)).v);
|
||||
}
|
||||
break;
|
||||
case 0x31: // NMADD.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fr = float64_t{ m_f[FRREG] };
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
float64_t const ft = float64_t{ m_f[FTREG] };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f64_mul(f64_add(f64_mul(fs, ft), fr), i32_to_f64(-1)).v);
|
||||
}
|
||||
break;
|
||||
case 0x38: // NMSUB.S
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float32_t const fr = float32_t{ u32(m_f[FRREG]) };
|
||||
float32_t const fs = float32_t{ u32(m_f[FSREG]) };
|
||||
float32_t const ft = float32_t{ u32(m_f[FTREG]) };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f32_mul(f32_sub(f32_mul(fs, ft), fr), i32_to_f32(-1)).v);
|
||||
}
|
||||
break;
|
||||
case 0x39: // NMSUB.D
|
||||
if ((SR & SR_FR) || !(op & ODD_REGS))
|
||||
{
|
||||
float64_t const fr = float64_t{ m_f[FRREG] };
|
||||
float64_t const fs = float64_t{ m_f[FSREG] };
|
||||
float64_t const ft = float64_t{ m_f[FTREG] };
|
||||
|
||||
if (cp1_op(fr) && cp1_op(fs) && cp1_op(ft))
|
||||
cp1_set(FDREG, f64_mul(f64_sub(f64_mul(fs, ft), fr), i32_to_f64(-1)).v);
|
||||
}
|
||||
break;
|
||||
case 0x24: /* MADD.W */
|
||||
logerror("cp1x unsupported op (%s): MADD.W\n", machine().describe_context());
|
||||
break;
|
||||
case 0x25: /* MADD.L */
|
||||
logerror("cp1x unsupported op (%s): MADD.L\n", machine().describe_context());
|
||||
break;
|
||||
case 0x2c: /* MSUB.W */
|
||||
logerror("cp1x unsupported op (%s): MSUB.W\n", machine().describe_context());
|
||||
break;
|
||||
case 0x2d: /* MSUB.L */
|
||||
logerror("cp1x unsupported op (%s): MSUB.L\n", machine().describe_context());
|
||||
break;
|
||||
case 0x34: /* NMADD.W */
|
||||
logerror("cp1x unsupported op (%s): NMADD.W\n", machine().describe_context());
|
||||
break;
|
||||
case 0x35: /* NMADD.L */
|
||||
logerror("cp1x unsupported op (%s): NMADD.L\n", machine().describe_context());
|
||||
break;
|
||||
case 0x3c: /* NMSUB.W */
|
||||
logerror("cp1x unsupported op (%s): NMSUB.W\n", machine().describe_context());
|
||||
break;
|
||||
case 0x3d: /* NMSUB.L */
|
||||
logerror("cp1x unsupported op (%s): NMSUB.L\n", machine().describe_context());
|
||||
break;
|
||||
default:
|
||||
logerror("cp1x unsupported op (%s): [unknown]\n", machine().describe_context());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void r4000_base_device::cp1_set(unsigned const reg, T const data)
|
||||
{
|
||||
// translate softfloat exception flags to cause register
|
||||
|
@ -9,6 +9,7 @@
|
||||
DECLARE_DEVICE_TYPE(R4000, r4000_device)
|
||||
DECLARE_DEVICE_TYPE(R4400, r4400_device)
|
||||
DECLARE_DEVICE_TYPE(R4600, r4600_device)
|
||||
DECLARE_DEVICE_TYPE(R5000, r5000_device)
|
||||
|
||||
class r4000_base_device : public cpu_device
|
||||
{
|
||||
@ -326,6 +327,7 @@ protected:
|
||||
virtual void execute_set_input(int inputnum, int state) override;
|
||||
|
||||
// cpu implementation
|
||||
virtual void handle_reserved_instruction(u32 const op);
|
||||
void cpu_execute(u32 const op);
|
||||
void cpu_exception(u32 exception, u16 const vector = 0x180);
|
||||
void cpu_lwl(u32 const op);
|
||||
@ -355,6 +357,7 @@ protected:
|
||||
void cp1_unimplemented();
|
||||
template <typename T> bool cp1_op(T op);
|
||||
void cp1_execute(u32 const op);
|
||||
virtual void cp1x_execute(u32 const op);
|
||||
template <typename T> void cp1_set(unsigned const reg, T const data);
|
||||
|
||||
// cp2 implementation
|
||||
@ -470,4 +473,19 @@ public:
|
||||
m_cp0[CP0_Config] |= CONFIG_SC;
|
||||
}
|
||||
};
|
||||
|
||||
class r5000_device : public r4000_base_device
|
||||
{
|
||||
public:
|
||||
r5000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: r4000_base_device(mconfig, R5000, tag, owner, clock, 0x2320, 0x2320, CACHE_32K, CACHE_32K)
|
||||
{
|
||||
// no secondary cache
|
||||
m_cp0[CP0_Config] |= CONFIG_SC;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void handle_reserved_instruction(u32 const op) override;
|
||||
virtual void cp1x_execute(u32 const op) override;
|
||||
};
|
||||
#endif // MAME_CPU_MIPS_R4000_H
|
||||
|
@ -413,9 +413,7 @@ void ip24_state::indy_5015(machine_config &config)
|
||||
{
|
||||
ip24(config);
|
||||
|
||||
R4000(config, m_maincpu, 50000000*3);
|
||||
//m_maincpu->set_icache_size(32768);
|
||||
//m_maincpu->set_dcache_size(32768);
|
||||
R5000(config, m_maincpu, 50000000*3);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ip24_state::ip24_map);
|
||||
}
|
||||
|
||||
@ -424,8 +422,6 @@ void ip24_state::indy_4613(machine_config &config)
|
||||
ip24(config);
|
||||
|
||||
R4600(config, m_maincpu, 33333333*4);
|
||||
//m_maincpu->set_icache_size(16384);
|
||||
//m_maincpu->set_dcache_size(16384);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ip24_state::ip24_map);
|
||||
}
|
||||
|
||||
@ -434,8 +430,6 @@ void ip24_state::indy_4610(machine_config &config)
|
||||
ip24(config);
|
||||
|
||||
R4600(config, m_maincpu, 33333333*3);
|
||||
//m_maincpu->set_icache_size(16384);
|
||||
//m_maincpu->set_dcache_size(16384);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ip24_state::ip24_map);
|
||||
}
|
||||
|
||||
@ -449,8 +443,6 @@ void ip22_state::wd33c93_2(device_t *device)
|
||||
void ip22_state::indigo2_4415(machine_config &config)
|
||||
{
|
||||
R4400(config, m_maincpu, 50000000*3);
|
||||
//m_maincpu->set_icache_size(32768);
|
||||
//m_maincpu->set_dcache_size(32768);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &ip22_state::ip22_map);
|
||||
|
||||
ip24_base(config);
|
||||
|
Loading…
Reference in New Issue
Block a user