mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[FAST486]
Implement FST/FSTP for single reals. svn path=/trunk/; revision=66126
This commit is contained in:
parent
7008e871d9
commit
73f35d3ca1
1 changed files with 137 additions and 3 deletions
|
@ -270,6 +270,117 @@ Fast486FpuFromSingleReal(PFAST486_STATE State,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FASTCALL
|
||||||
|
Fast486FpuToSingleReal(PFAST486_STATE State,
|
||||||
|
PFAST486_FPU_DATA_REG Value,
|
||||||
|
PULONG Result)
|
||||||
|
{
|
||||||
|
ULONGLONG Remainder;
|
||||||
|
SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
|
||||||
|
|
||||||
|
if (FPU_IS_ZERO(Value))
|
||||||
|
{
|
||||||
|
*Result = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the mantissa */
|
||||||
|
*Result = (ULONG)(Value->Mantissa >> 40) & 0x7FFFFF;
|
||||||
|
|
||||||
|
if (FPU_IS_NAN(Value))
|
||||||
|
{
|
||||||
|
*Result |= FPU_REAL4_INFINITY;
|
||||||
|
goto SetSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for underflow */
|
||||||
|
if (!FPU_IS_NORMALIZED(Value) || (UnbiasedExp < -127))
|
||||||
|
{
|
||||||
|
/* Raise the underflow exception */
|
||||||
|
State->FpuStatus.Ue = TRUE;
|
||||||
|
|
||||||
|
if (State->FpuControl.Um)
|
||||||
|
{
|
||||||
|
/* The result is zero due to underflow */
|
||||||
|
*Result = 0ULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fast486FpuException(State);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for overflow */
|
||||||
|
if (UnbiasedExp > 127)
|
||||||
|
{
|
||||||
|
/* Raise the overflow exception */
|
||||||
|
State->FpuStatus.Oe = TRUE;
|
||||||
|
|
||||||
|
if (State->FpuControl.Om)
|
||||||
|
{
|
||||||
|
/* The result is infinity due to overflow */
|
||||||
|
*Result = FPU_REAL4_INFINITY;
|
||||||
|
goto SetSign;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fast486FpuException(State);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the remainder */
|
||||||
|
Remainder = Value->Mantissa & ((1ULL << 40) - 1);
|
||||||
|
|
||||||
|
switch (State->FpuControl.Rc)
|
||||||
|
{
|
||||||
|
case FPU_ROUND_NEAREST:
|
||||||
|
{
|
||||||
|
/* Check if the highest bit of the remainder is set */
|
||||||
|
if (Remainder & (1ULL << 39))
|
||||||
|
{
|
||||||
|
(*Result)++;
|
||||||
|
|
||||||
|
/* Check if all the other bits are clear */
|
||||||
|
if (!(Remainder & ((1ULL << 39) - 1)))
|
||||||
|
{
|
||||||
|
/* Round to even */
|
||||||
|
*Result &= ~1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FPU_ROUND_DOWN:
|
||||||
|
{
|
||||||
|
if ((Remainder != 0ULL) && Value->Sign) (*Result)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FPU_ROUND_UP:
|
||||||
|
{
|
||||||
|
if ((Remainder != 0ULL) && !Value->Sign) (*Result)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Leave it truncated */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the biased exponent */
|
||||||
|
*Result |= (ULONG)(UnbiasedExp + FPU_REAL4_BIAS) << 23;
|
||||||
|
|
||||||
|
SetSign:
|
||||||
|
|
||||||
|
if (Value->Sign) *Result |= 0x80000000;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline VOID FASTCALL
|
static inline VOID FASTCALL
|
||||||
Fast486FpuFromDoubleReal(PFAST486_STATE State,
|
Fast486FpuFromDoubleReal(PFAST486_STATE State,
|
||||||
ULONGLONG Value,
|
ULONGLONG Value,
|
||||||
|
@ -310,7 +421,7 @@ Fast486FpuToDoubleReal(PFAST486_STATE State,
|
||||||
|
|
||||||
if (FPU_IS_NAN(Value))
|
if (FPU_IS_NAN(Value))
|
||||||
{
|
{
|
||||||
*Result |= 0x7FFULL << 52;
|
*Result |= FPU_REAL8_INFINITY;
|
||||||
goto SetSign;
|
goto SetSign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,9 +1147,32 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
|
||||||
/* FSTP */
|
/* FSTP */
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
ULONG Value = FPU_REAL4_INDEFINITE;
|
||||||
UNIMPLEMENTED;
|
|
||||||
|
|
||||||
|
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
|
||||||
|
{
|
||||||
|
/* Raise the invalid operation exception */
|
||||||
|
State->FpuStatus.Ie = TRUE;
|
||||||
|
|
||||||
|
if (!State->FpuControl.Im)
|
||||||
|
{
|
||||||
|
Fast486FpuException(State);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!Fast486FpuToSingleReal(State, &FPU_ST(0), &Value))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModRegRm.Register == 3) Fast486FpuPop(State);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue