Author: aandrejevic
Date: Sat Jan 31 16:13:40 2015
New Revision: 66126
URL:
http://svn.reactos.org/svn/reactos?rev=66126&view=rev
Log:
[FAST486]
Implement FST/FSTP for single reals.
Modified:
trunk/reactos/lib/fast486/fpu.c
Modified: trunk/reactos/lib/fast486/fpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=6612…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Sat Jan 31 16:13:40 2015
@@ -270,6 +270,117 @@
}
}
+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
Fast486FpuFromDoubleReal(PFAST486_STATE State,
ULONGLONG Value,
@@ -310,7 +421,7 @@
if (FPU_IS_NAN(Value))
{
- *Result |= 0x7FFULL << 52;
+ *Result |= FPU_REAL8_INFINITY;
goto SetSign;
}
@@ -1036,9 +1147,32 @@
/* FSTP */
case 3:
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
+ ULONG Value = FPU_REAL4_INDEFINITE;
+
+ 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;
}