From 60c3d14cf6932af876e7bc5ba0e0b46d717ed061 Mon Sep 17 00:00:00 2001 From: arbee Date: Mon, 7 Jun 2021 23:18:05 -0400 Subject: [PATCH] m68kfpu: implement FGETMAN and FSINCOS. Photoshop 3.0 starts & loads pictures now. (GitHub #8109) [R. Belmont] --- src/devices/cpu/m68000/m68kfpu.cpp | 85 ++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/src/devices/cpu/m68000/m68kfpu.cpp b/src/devices/cpu/m68000/m68kfpu.cpp index ed439f2fe5f..9d0bd52111a 100644 --- a/src/devices/cpu/m68000/m68kfpu.cpp +++ b/src/devices/cpu/m68000/m68kfpu.cpp @@ -241,6 +241,53 @@ inline void m68000_base_device::store_pack_float80(u32 ea, int k, floatx80 fpr) m68ki_write_32(ea+8, dw3); } +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_base_device::SET_CONDITION_CODES(floatx80 reg) { // u64 *regi; @@ -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]; @@ -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]; @@ -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]; @@ -1163,11 +1222,11 @@ void m68000_base_device::WRITE_EA_PACK(int ea, int k, floatx80 fpr) void m68000_base_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 @@ -1460,6 +1519,12 @@ 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; + } case 0x60: // FSDIVS case 0x20: // FDIV { @@ -1534,6 +1599,16 @@ void m68000_base_device::fpgen_rm_reg(u16 w2) m_icount -= 9; break; } + case 0x31: // FSINCOS + { + 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; + } case 0x38: // FCMP { floatx80 res;