Skip to content

Commit

Permalink
m68kfpu: implement FGETMAN and FSINCOS. Photoshop 3.0 starts & loads …
Browse files Browse the repository at this point in the history
…pictures now. (GitHub #8109) [R. Belmont]
  • Loading branch information
rb6502 committed Jun 8, 2021
1 parent c1744a1 commit 60c3d14
Showing 1 changed file with 80 additions and 5 deletions.
85 changes: 80 additions & 5 deletions src/devices/cpu/m68000/m68kfpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 60c3d14

Please sign in to comment.