mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
m68k: backport FPU fixes from upstream Musashi [R. Belmont, Jean-Francois Fabre]
This commit is contained in:
parent
b4cf1eb096
commit
27ad7de49c
@ -650,12 +650,9 @@ u64 m68000_base_device::READ_EA_64(int ea)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
floatx80 m68000_base_device::READ_EA_FPE(int ea)
|
||||
floatx80 m68000_base_device::READ_EA_FPE(int mode, int reg, uint32 di_mode_ea)
|
||||
{
|
||||
floatx80 fpr;
|
||||
int mode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
@ -682,16 +679,12 @@ floatx80 m68000_base_device::READ_EA_FPE(int ea)
|
||||
}
|
||||
case 5: // (d16, An)
|
||||
{
|
||||
// FIXME: will fail for fmovem
|
||||
u32 ea = EA_AY_DI_32();
|
||||
fpr = load_extended_float80(ea);
|
||||
fpr = load_extended_float80(di_mode_ea);
|
||||
break;
|
||||
}
|
||||
case 6: // (An) + (Xn) + d8
|
||||
{
|
||||
// FIXME: will fail for fmovem
|
||||
u32 ea = EA_AY_IX_32();
|
||||
fpr = load_extended_float80(ea);
|
||||
fpr = load_extended_float80(di_mode_ea);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1075,11 +1068,8 @@ void m68000_base_device::WRITE_EA_64(int ea, u64 data)
|
||||
}
|
||||
}
|
||||
|
||||
void m68000_base_device::WRITE_EA_FPE(int ea, floatx80 fpr)
|
||||
void m68000_base_device::WRITE_EA_FPE(int mode, int reg, floatx80 fpr, uint32 di_mode_ea)
|
||||
{
|
||||
int mode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 2: // (An)
|
||||
@ -1110,8 +1100,9 @@ void m68000_base_device::WRITE_EA_FPE(int ea, floatx80 fpr)
|
||||
|
||||
case 5: // (d16,An)
|
||||
{
|
||||
u32 ea = EA_AY_DI_32();
|
||||
store_extended_float80(ea, fpr);
|
||||
// EA_AY_DI_32() should not be done here because fmovem would increase
|
||||
// PC each time, reading incorrect displacement & advancing PC too much.
|
||||
store_extended_float80(di_mode_ea, fpr);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1199,7 +1190,10 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
}
|
||||
case 2: // Extended-precision Real
|
||||
{
|
||||
source = READ_EA_FPE(ea);
|
||||
int imode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
uint32 di_mode_ea = imode == 5 ? (REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16())) : 0;
|
||||
source = READ_EA_FPE(imode, reg, di_mode_ea);
|
||||
break;
|
||||
}
|
||||
case 3: // Packed-decimal Real
|
||||
@ -1341,6 +1335,7 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
|
||||
// handle it right here, the usual opmode bits aren't valid in the FMOVECR case
|
||||
m_fpr[dst] = source;
|
||||
SET_CONDITION_CODES(m_fpr[dst]);
|
||||
m_icount -= 4;
|
||||
return;
|
||||
}
|
||||
@ -1368,6 +1363,7 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
s32 temp;
|
||||
temp = floatx80_to_int32(source);
|
||||
m_fpr[dst] = int32_to_floatx80(temp);
|
||||
SET_CONDITION_CODES(m_fpr[dst]);
|
||||
break;
|
||||
}
|
||||
case 0x03: // FINTRZ
|
||||
@ -1375,6 +1371,7 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
s32 temp;
|
||||
temp = floatx80_to_int32_round_to_zero(source);
|
||||
m_fpr[dst] = int32_to_floatx80(temp);
|
||||
SET_CONDITION_CODES(m_fpr[dst]);
|
||||
break;
|
||||
}
|
||||
case 0x04: // FSQRT
|
||||
@ -1463,9 +1460,11 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
m_icount -= 6;
|
||||
break;
|
||||
}
|
||||
case 0x60: // FSDIVS
|
||||
case 0x20: // FDIV
|
||||
{
|
||||
m_fpr[dst] = floatx80_div(m_fpr[dst], source);
|
||||
SET_CONDITION_CODES(m_fpr[dst]);
|
||||
m_icount -= 43;
|
||||
break;
|
||||
}
|
||||
@ -1486,6 +1485,7 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
|
||||
m_icount -= 9;
|
||||
break;
|
||||
}
|
||||
case 0x63: // FSMULS (JFF)
|
||||
case 0x23: // FMUL
|
||||
{
|
||||
m_fpr[dst] = floatx80_mul(m_fpr[dst], source);
|
||||
@ -1578,7 +1578,11 @@ void m68000_base_device::fmove_reg_mem(u16 w2)
|
||||
}
|
||||
case 2: // Extended-precision Real
|
||||
{
|
||||
WRITE_EA_FPE(ea, m_fpr[src]);
|
||||
int mode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
uint32 di_mode_ea = mode == 5 ? (REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16())) : 0;
|
||||
|
||||
WRITE_EA_FPE(mode, reg, m_fpr[src], di_mode_ea);
|
||||
break;
|
||||
}
|
||||
case 3: // Packed-decimal Real with Static K-factor
|
||||
@ -1670,7 +1674,11 @@ void m68000_base_device::fmove_fpcr(u16 w2)
|
||||
}
|
||||
else // From <ea> to system control reg
|
||||
{
|
||||
if (regsel & 4) m_fpcr = READ_EA_32(ea);
|
||||
if (regsel & 4)
|
||||
{
|
||||
m_fpcr = READ_EA_32(ea);
|
||||
// should update softfloat rounding mode here
|
||||
}
|
||||
if (regsel & 2) m_fpsr = READ_EA_32(ea);
|
||||
if (regsel & 1) m_fpiar = READ_EA_32(ea);
|
||||
}
|
||||
@ -1756,20 +1764,23 @@ void m68000_base_device::fmovem(u16 w2)
|
||||
[[fallthrough]];
|
||||
case 0: // Static register list, predecrement or control addressing mode
|
||||
{
|
||||
// the "di_mode_ea" parameter kludge is required here else WRITE_EA_FPE would have
|
||||
// to call EA_AY_DI_32() (that advances PC & reads displacement) each time
|
||||
// when the proper behaviour is 1) read once, 2) increment ea for each matching register
|
||||
// this forces to pre-read the mode (named "imode") so we can decide to read displacement, only once
|
||||
int imode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
int di_mode = imode == 5;
|
||||
uint32 di_mode_ea = di_mode ? (REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16())) : 0;
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
{
|
||||
if (reglist & (1 << i))
|
||||
{
|
||||
switch (ea >> 3)
|
||||
WRITE_EA_FPE(imode, reg, m_fpr[i], di_mode_ea);
|
||||
if (di_mode)
|
||||
{
|
||||
case 5: // (d16, An)
|
||||
case 6: // (An) + (Xn) + d8
|
||||
store_extended_float80(mem_addr, m_fpr[i]);
|
||||
mem_addr += 12;
|
||||
break;
|
||||
default:
|
||||
WRITE_EA_FPE(ea, m_fpr[i]);
|
||||
break;
|
||||
di_mode_ea += 12;
|
||||
}
|
||||
|
||||
m_icount -= 2;
|
||||
@ -1784,20 +1795,20 @@ void m68000_base_device::fmovem(u16 w2)
|
||||
[[fallthrough]];
|
||||
case 2: // Static register list, postdecrement or control addressing mode
|
||||
{
|
||||
int imode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
int di_mode = imode == 5;
|
||||
|
||||
uint32 di_mode_ea = di_mode ? (REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16())) : 0;
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
{
|
||||
if (reglist & (1 << i))
|
||||
{
|
||||
switch (ea >> 3)
|
||||
WRITE_EA_FPE(imode, reg, m_fpr[7 - i], di_mode_ea);
|
||||
if (di_mode)
|
||||
{
|
||||
case 5: // (d16, An)
|
||||
case 6: // (An) + (Xn) + d8
|
||||
store_extended_float80(mem_addr, m_fpr[7-i]);
|
||||
mem_addr += 12;
|
||||
break;
|
||||
default:
|
||||
WRITE_EA_FPE(ea, m_fpr[7-i]);
|
||||
break;
|
||||
di_mode_ea += 12;
|
||||
}
|
||||
|
||||
m_icount -= 2;
|
||||
@ -1819,6 +1830,11 @@ void m68000_base_device::fmovem(u16 w2)
|
||||
[[fallthrough]];
|
||||
case 2: // Static register list, postincrement or control addressing mode
|
||||
{
|
||||
int imode = (ea >> 3) & 0x7;
|
||||
int reg = (ea & 0x7);
|
||||
int di_mode = imode == 5;
|
||||
uint32 di_mode_ea = di_mode ? (REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16())) : 0;
|
||||
|
||||
for (i=0; i < 8; i++)
|
||||
{
|
||||
if (reglist & (1 << i))
|
||||
@ -1831,7 +1847,7 @@ void m68000_base_device::fmovem(u16 w2)
|
||||
mem_addr += 12;
|
||||
break;
|
||||
default:
|
||||
m_fpr[7-i] = READ_EA_FPE(ea);
|
||||
m_fpr[7 - i] = READ_EA_FPE(imode, reg, di_mode_ea);
|
||||
break;
|
||||
}
|
||||
m_icount -= 2;
|
||||
@ -1847,10 +1863,24 @@ void m68000_base_device::fmovem(u16 w2)
|
||||
|
||||
void m68000_base_device::fscc()
|
||||
{
|
||||
int ea = m_ir & 0x3f;
|
||||
int condition = (s16)(OPER_I_16());
|
||||
const int mode = (m_ir & 0x38) >> 3;
|
||||
const int condition = OPER_I_16() & 0x3f;
|
||||
const int v = (TEST_CONDITION(condition) ? 0xff : 0x00);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 0: // Dx (handled specially because it only changes the low byte of Dx)
|
||||
{
|
||||
const int reg = m_ir & 7;
|
||||
REG_D()[reg] = (REG_D()[reg] & 0xffffff00) | v;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WRITE_EA_8(m_ir & 0x3f, v);
|
||||
break;
|
||||
}
|
||||
|
||||
WRITE_EA_8(ea, TEST_CONDITION(condition) ? 0xff : 0);
|
||||
m_icount -= 7; // ???
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user