summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m68000/m68kfpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m68000/m68kfpu.cpp')
-rw-r--r--src/devices/cpu/m68000/m68kfpu.cpp356
1 files changed, 249 insertions, 107 deletions
diff --git a/src/devices/cpu/m68000/m68kfpu.cpp b/src/devices/cpu/m68000/m68kfpu.cpp
index 07cca095357..e8acf965db6 100644
--- a/src/devices/cpu/m68000/m68kfpu.cpp
+++ b/src/devices/cpu/m68000/m68kfpu.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Karl Stenerud
#include "emu.h"
-#include "m68000.h"
+#include "m68kmusashi.h"
static constexpr int FPCC_N = 0x08000000;
static constexpr int FPCC_Z = 0x04000000;
@@ -19,7 +19,7 @@ static constexpr u64 DOUBLE_MANTISSA = 0x000fffffffffffffU;
#endif
// masks for packed dwords, positive k-factor
-const u32 m68000_base_device::pkmask2[18] =
+const u32 m68000_musashi_device::pkmask2[18] =
{
0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
@@ -27,14 +27,14 @@ const u32 m68000_base_device::pkmask2[18] =
0xffffffff, 0xffffffff, 0xffffffff
};
-const u32 m68000_base_device::pkmask3[18] =
+const u32 m68000_musashi_device::pkmask3[18] =
{
0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
};
-inline floatx80 m68000_base_device::load_extended_float80(u32 ea)
+inline floatx80 m68000_musashi_device::load_extended_float80(u32 ea)
{
u32 d1,d2;
u16 d3;
@@ -50,7 +50,7 @@ inline floatx80 m68000_base_device::load_extended_float80(u32 ea)
return fp;
}
-inline void m68000_base_device::store_extended_float80(u32 ea, floatx80 fpr)
+inline void m68000_musashi_device::store_extended_float80(u32 ea, floatx80 fpr)
{
m68ki_write_16(ea+0, fpr.high);
m68ki_write_16(ea+2, 0);
@@ -58,7 +58,7 @@ inline void m68000_base_device::store_extended_float80(u32 ea, floatx80 fpr)
m68ki_write_32(ea+8, fpr.low&0xffffffff);
}
-inline floatx80 m68000_base_device::load_pack_float80(u32 ea)
+inline floatx80 m68000_musashi_device::load_pack_float80(u32 ea)
{
u32 dw1, dw2, dw3;
floatx80 result;
@@ -109,7 +109,7 @@ inline floatx80 m68000_base_device::load_pack_float80(u32 ea)
return result;
}
-inline void m68000_base_device::store_pack_float80(u32 ea, int k, floatx80 fpr)
+inline void m68000_musashi_device::store_pack_float80(u32 ea, int k, floatx80 fpr)
{
u32 dw1, dw2, dw3;
char str[128], *ch;
@@ -118,7 +118,7 @@ inline void m68000_base_device::store_pack_float80(u32 ea, int k, floatx80 fpr)
dw1 = dw2 = dw3 = 0;
ch = &str[0];
- sprintf(str, "%.16e", fx80_to_double(fpr));
+ snprintf(str, 128, "%.16e", fx80_to_double(fpr));
if (*ch == '-')
{
@@ -241,7 +241,54 @@ inline void m68000_base_device::store_pack_float80(u32 ea, int k, floatx80 fpr)
m68ki_write_32(ea+8, dw3);
}
-inline void m68000_base_device::SET_CONDITION_CODES(floatx80 reg)
+inline floatx80 propagateFloatx80NaNOneArg(floatx80 a)
+{
+ if (floatx80_is_signaling_nan(a))
+ float_raise(float_flag_invalid);
+
+ a.low |= 0xC000000000000000U;
+
+ return a;
+}
+
+static void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr, uint64_t *zSigPtr)
+{
+ int shiftCount = countLeadingZeros64(aSig);
+ *zSigPtr = aSig << shiftCount;
+ *zExpPtr = 1 - shiftCount;
+}
+
+inline floatx80 getman(floatx80 src)
+{
+ const flag sign = (src.high >> 15);
+ int32_t exp = (src.high & 0x7fff);
+ uint64_t signific = src.low;
+
+ if (exp == 0x7fff)
+ {
+ if ((uint64_t)(signific << 1))
+ {
+ return propagateFloatx80NaNOneArg(src);
+ }
+ else
+ {
+ return packFloatx80(0, 0xffff, 0xffffffffffffffffU);
+ }
+ }
+
+ if (exp == 0)
+ {
+ if (signific == 0)
+ {
+ return packFloatx80(sign, 0, 0);
+ }
+ normalizeFloatx80Subnormal(signific, &exp, &signific);
+ }
+
+ return packFloatx80(sign, 0x3fff, signific);
+}
+
+inline void m68000_musashi_device::SET_CONDITION_CODES(floatx80 reg)
{
// u64 *regi;
@@ -274,7 +321,7 @@ inline void m68000_base_device::SET_CONDITION_CODES(floatx80 reg)
}
}
-inline int m68000_base_device::TEST_CONDITION(int condition)
+inline int m68000_musashi_device::TEST_CONDITION(int condition)
{
int n = (m_fpsr & FPCC_N) != 0;
int z = (m_fpsr & FPCC_Z) != 0;
@@ -336,7 +383,7 @@ inline int m68000_base_device::TEST_CONDITION(int condition)
return r;
}
-u8 m68000_base_device::READ_EA_8(int ea)
+u8 m68000_musashi_device::READ_EA_8(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -347,6 +394,10 @@ u8 m68000_base_device::READ_EA_8(int ea)
{
return REG_D()[reg];
}
+ case 1: // An
+ {
+ return REG_A()[reg];
+ }
case 2: // (An)
{
u32 ea = REG_A()[reg];
@@ -412,7 +463,7 @@ u8 m68000_base_device::READ_EA_8(int ea)
return 0;
}
-u16 m68000_base_device::READ_EA_16(int ea)
+u16 m68000_musashi_device::READ_EA_16(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -423,6 +474,10 @@ u16 m68000_base_device::READ_EA_16(int ea)
{
return (u16)(REG_D()[reg]);
}
+ case 1: // An
+ {
+ return (u16)REG_A()[reg];
+ }
case 2: // (An)
{
u32 ea = REG_A()[reg];
@@ -489,7 +544,7 @@ u16 m68000_base_device::READ_EA_16(int ea)
return 0;
}
-u32 m68000_base_device::READ_EA_32(int ea)
+u32 m68000_musashi_device::READ_EA_32(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -500,6 +555,10 @@ u32 m68000_base_device::READ_EA_32(int ea)
{
return REG_D()[reg];
}
+ case 1: // An
+ {
+ return REG_A()[reg];
+ }
case 2: // (An)
{
u32 ea = REG_A()[reg];
@@ -564,7 +623,7 @@ u32 m68000_base_device::READ_EA_32(int ea)
return 0;
}
-u64 m68000_base_device::READ_EA_64(int ea)
+u64 m68000_musashi_device::READ_EA_64(int ea)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -650,12 +709,9 @@ u64 m68000_base_device::READ_EA_64(int ea)
return 0;
}
-
-floatx80 m68000_base_device::READ_EA_FPE(int ea)
+floatx80 m68000_musashi_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 +738,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;
}
@@ -722,6 +774,11 @@ floatx80 m68000_base_device::READ_EA_FPE(int ea)
}
break;
+ case 4: // #<data>
+ fpr = load_extended_float80(m_pc);
+ m_pc += 12;
+ break;
+
default:
fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, m_pc);
break;
@@ -735,7 +792,7 @@ floatx80 m68000_base_device::READ_EA_FPE(int ea)
return fpr;
}
-floatx80 m68000_base_device::READ_EA_PACK(int ea)
+floatx80 m68000_musashi_device::READ_EA_PACK(int ea)
{
floatx80 fpr;
int mode = (ea >> 3) & 0x7;
@@ -758,6 +815,13 @@ floatx80 m68000_base_device::READ_EA_PACK(int ea)
break;
}
+ case 5: // (d16,An)
+ {
+ u32 ea = REG_A()[reg] + MAKE_INT_16(m68ki_read_imm_16());
+ fpr = load_pack_float80(ea);
+ break;
+ }
+
case 7: // extended modes
{
switch (reg)
@@ -782,7 +846,7 @@ floatx80 m68000_base_device::READ_EA_PACK(int ea)
return fpr;
}
-void m68000_base_device::WRITE_EA_8(int ea, u8 data)
+void m68000_musashi_device::WRITE_EA_8(int ea, u8 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -850,7 +914,7 @@ void m68000_base_device::WRITE_EA_8(int ea, u8 data)
}
}
-void m68000_base_device::WRITE_EA_16(int ea, u16 data)
+void m68000_musashi_device::WRITE_EA_16(int ea, u16 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -918,7 +982,7 @@ void m68000_base_device::WRITE_EA_16(int ea, u16 data)
}
}
-void m68000_base_device::WRITE_EA_32(int ea, u32 data)
+void m68000_musashi_device::WRITE_EA_32(int ea, u32 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -997,7 +1061,7 @@ void m68000_base_device::WRITE_EA_32(int ea, u32 data)
}
}
-void m68000_base_device::WRITE_EA_64(int ea, u64 data)
+void m68000_musashi_device::WRITE_EA_64(int ea, u64 data)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -1070,11 +1134,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_musashi_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)
@@ -1105,7 +1166,15 @@ void m68000_base_device::WRITE_EA_FPE(int ea, floatx80 fpr)
case 5: // (d16,An)
{
- u32 ea = EA_AY_DI_32();
+ // 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;
+ }
+
+ case 6: // (An) + (Xn) + d8
+ {
+ u32 ea = EA_AY_IX_32();
store_extended_float80(ea, fpr);
break;
}
@@ -1121,7 +1190,7 @@ void m68000_base_device::WRITE_EA_FPE(int ea, floatx80 fpr)
}
}
-void m68000_base_device::WRITE_EA_PACK(int ea, int k, floatx80 fpr)
+void m68000_musashi_device::WRITE_EA_PACK(int ea, int k, floatx80 fpr)
{
int mode = (ea >> 3) & 0x7;
int reg = (ea & 0x7);
@@ -1165,13 +1234,13 @@ void m68000_base_device::WRITE_EA_PACK(int ea, int k, floatx80 fpr)
}
}
-void m68000_base_device::fpgen_rm_reg(u16 w2)
+void m68000_musashi_device::fpgen_rm_reg(u16 w2)
{
- int ea = m_ir & 0x3f;
- int rm = (w2 >> 14) & 0x1;
- int src = (w2 >> 10) & 0x7;
- int dst = (w2 >> 7) & 0x7;
- int opmode = w2 & 0x7f;
+ const int ea = m_ir & 0x3f;
+ const int rm = (w2 >> 14) & 0x1;
+ const int src = (w2 >> 10) & 0x7;
+ const int dst = (w2 >> 7) & 0x7;
+ const int opmode = w2 & 0x7f;
floatx80 source;
// fmovecr #$f, fp0 f200 5c0f
@@ -1194,7 +1263,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
@@ -1336,6 +1408,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;
}
@@ -1363,6 +1436,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
@@ -1370,6 +1444,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
@@ -1381,11 +1456,18 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
}
case 0x06: // FLOGNP1
{
- m_fpr[dst] = floatx80_flognp1 (source);
+ m_fpr[dst] = floatx80_flognp1(source);
SET_CONDITION_CODES(m_fpr[dst]);
m_icount -= 594; // for MC68881
break;
}
+ case 0x0a: // FATAN
+ {
+ m_fpr[dst] = floatx80_fatan (source);
+ SET_CONDITION_CODES(m_fpr[dst]);
+ m_icount -= 426; // for MC68881
+ break;
+ }
case 0x0e: // FSIN
{
m_fpr[dst] = source;
@@ -1458,9 +1540,18 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
m_icount -= 6;
break;
}
+ case 0x1f: // FGETMAN
+ {
+ m_fpr[dst] = getman(source);
+ SET_CONDITION_CODES(m_fpr[dst]);
+ m_icount -= 31;
+ 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;
}
@@ -1481,6 +1572,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);
@@ -1529,6 +1621,24 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
m_icount -= 9;
break;
}
+ case 0x30: // FSINCOS
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ {
+ m_fpr[dst] = source;
+ floatx80_fsin(m_fpr[dst]);
+ SET_CONDITION_CODES(m_fpr[dst]); // condition codes are set for the sine result
+
+ m_fpr[(w2 & 0x7)] = source;
+ floatx80_fcos(m_fpr[(w2 & 0x7)]);
+ m_icount -= 451;
+ break;
+ }
case 0x38: // FCMP
{
floatx80 res;
@@ -1550,7 +1660,7 @@ void m68000_base_device::fpgen_rm_reg(u16 w2)
}
}
-void m68000_base_device::fmove_reg_mem(u16 w2)
+void m68000_musashi_device::fmove_reg_mem(u16 w2)
{
int ea = m_ir & 0x3f;
int src = (w2 >> 7) & 0x7;
@@ -1573,7 +1683,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
@@ -1622,7 +1736,7 @@ void m68000_base_device::fmove_reg_mem(u16 w2)
m_icount -= 12;
}
-void m68000_base_device::fmove_fpcr(u16 w2)
+void m68000_musashi_device::fmove_fpcr(u16 w2)
{
int ea = m_ir & 0x3f;
int dir = (w2 >> 13) & 0x1;
@@ -1665,7 +1779,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);
}
@@ -1722,7 +1840,7 @@ void m68000_base_device::fmove_fpcr(u16 w2)
m_icount -= 10;
}
-void m68000_base_device::fmovem(u16 w2)
+void m68000_musashi_device::fmovem(u16 w2)
{
int i;
int ea = m_ir & 0x3f;
@@ -1730,17 +1848,6 @@ void m68000_base_device::fmovem(u16 w2)
int mode = (w2 >> 11) & 0x3;
int reglist = w2 & 0xff;
- u32 mem_addr = 0;
- switch (ea >> 3)
- {
- case 5: // (d16, An)
- mem_addr= EA_AY_DI_32();
- break;
- case 6: // (An) + (Xn) + d8
- mem_addr= EA_AY_IX_32();
- break;
- }
-
if (dir) // From FP regs to mem
{
switch (mode)
@@ -1751,49 +1858,71 @@ void m68000_base_device::fmovem(u16 w2)
[[fallthrough]];
case 0: // Static register list, predecrement or control addressing mode
{
- for (i=0; i < 8; i++)
+ // 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;
+
+ if (reglist)
{
- if (reglist & (1 << i))
+ for (i=0; i < 8; i++)
{
- switch (ea >> 3)
+ if (reglist & (1 << i))
{
- 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;
- }
+ WRITE_EA_FPE(imode, reg, m_fpr[i], di_mode_ea);
+ if (di_mode)
+ {
+ di_mode_ea += 12;
+ }
- m_icount -= 2;
+ m_icount -= 2;
+ }
}
}
+ else if (imode == 6)
+ // advance PC if the register list is empty
+ EA_AY_IX_32();
+ else if (imode == 7)
+ fatalerror("m68881: fmovem addressing mode %d unimplemented at 0x%08x\n", imode, m_pc - 4);
break;
}
+ case 3: // Dynamic register list, postincrement or control addressing mode.
+ // FIXME: not really tested, but seems to work
+ reglist = REG_D()[(reglist >> 4) & 7];
+ [[fallthrough]];
case 2: // Static register list, postdecrement or control addressing mode
{
- for (i=0; i < 8; i++)
+ 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;
+
+ if (reglist)
{
- if (reglist & (1 << i))
+ for (i=0; i < 8; i++)
{
- switch (ea >> 3)
+ if (reglist & (1 << i))
{
- 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;
- }
+ WRITE_EA_FPE(imode, reg, m_fpr[7 - i], di_mode_ea);
+ if (di_mode)
+ {
+ di_mode_ea += 12;
+ }
- m_icount -= 2;
+ m_icount -= 2;
+ }
}
}
+ else if (imode == 6)
+ // advance PC if the register list is empty
+ EA_AY_IX_32();
+ else if (imode == 7)
+ fatalerror("m68881: fmovem addressing mode %d unimplemented at 0x%08x\n", imode, m_pc - 4);
break;
}
@@ -1810,20 +1939,19 @@ 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))
{
- switch (ea >> 3)
+ m_fpr[7 - i] = READ_EA_FPE(imode, reg, di_mode_ea);
+ if (di_mode)
{
- case 5: // (d16, An)
- case 6: // (An) + (Xn) + d8
- m_fpr[7-i] = load_extended_float80(mem_addr);
- mem_addr += 12;
- break;
- default:
- m_fpr[7-i] = READ_EA_FPE(ea);
- break;
+ di_mode_ea += 12;
}
m_icount -= 2;
}
@@ -1836,16 +1964,30 @@ void m68000_base_device::fmovem(u16 w2)
}
}
-void m68000_base_device::fscc()
+void m68000_musashi_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; // ???
}
-void m68000_base_device::fbcc16()
+void m68000_musashi_device::fbcc16()
{
s32 offset;
int condition = m_ir & 0x3f;
@@ -1862,7 +2004,7 @@ void m68000_base_device::fbcc16()
m_icount -= 7;
}
-void m68000_base_device::fbcc32()
+void m68000_musashi_device::fbcc32()
{
s32 offset;
int condition = m_ir & 0x3f;
@@ -1880,7 +2022,7 @@ void m68000_base_device::fbcc32()
}
-void m68000_base_device::m68040_fpu_op0()
+void m68000_musashi_device::m68040_fpu_op0()
{
m_fpu_just_reset = 0;
@@ -1951,7 +2093,7 @@ void m68000_base_device::m68040_fpu_op0()
}
}
-int m68000_base_device::perform_fsave(u32 addr, int inc)
+int m68000_musashi_device::perform_fsave(u32 addr, int inc)
{
if(m_cpu_type & CPU_TYPE_040)
{
@@ -1993,7 +2135,7 @@ int m68000_base_device::perform_fsave(u32 addr, int inc)
}
// FRESTORE on a nullptr frame reboots the FPU - all registers to NaN, the 3 status regs to 0
-void m68000_base_device::do_frestore_null()
+void m68000_musashi_device::do_frestore_null()
{
int i;
@@ -2011,7 +2153,7 @@ void m68000_base_device::do_frestore_null()
m_fpu_just_reset = 1;
}
-void m68000_base_device::m68040_do_fsave(u32 addr, int reg, int inc)
+void m68000_musashi_device::m68040_do_fsave(u32 addr, int reg, int inc)
{
if (m_fpu_just_reset)
{
@@ -2026,7 +2168,7 @@ void m68000_base_device::m68040_do_fsave(u32 addr, int reg, int inc)
}
}
-void m68000_base_device::m68040_do_frestore(u32 addr, int reg)
+void m68000_musashi_device::m68040_do_frestore(u32 addr, int reg)
{
bool m40 = m_cpu_type & CPU_TYPE_040;
u32 temp = m68ki_read_32(addr);
@@ -2064,7 +2206,7 @@ void m68000_base_device::m68040_do_frestore(u32 addr, int reg)
}
}
-void m68000_base_device::m68040_fpu_op1()
+void m68000_musashi_device::m68040_fpu_op1()
{
int ea = m_ir & 0x3f;
int mode = (ea >> 3) & 0x7;
@@ -2186,7 +2328,7 @@ void m68000_base_device::m68040_fpu_op1()
}
}
-void m68000_base_device::m68881_ftrap()
+void m68000_musashi_device::m68881_ftrap()
{
u16 w2 = OPER_I_16();