Author: aandrejevic
Date: Sat Jan 3 22:24:40 2015
New Revision: 65966
URL:
http://svn.reactos.org/svn/reactos?rev=65966&view=rev
Log:
[FAST486]
Fix FPU exceptions (again).
Modified:
trunk/reactos/lib/fast486/common.inl
trunk/reactos/lib/fast486/fpu.c
trunk/reactos/lib/fast486/fpu.h
trunk/reactos/lib/fast486/opcodes.c
Modified: trunk/reactos/lib/fast486/common.inl
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev…
==============================================================================
--- trunk/reactos/lib/fast486/common.inl [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.inl [iso-8859-1] Sat Jan 3 22:24:40 2015
@@ -1507,16 +1507,33 @@
FORCEINLINE
VOID
FASTCALL
+Fast486FpuException(PFAST486_STATE State)
+{
+ if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_NE)
+ {
+ /* Call the #MF handler */
+ Fast486Exception(State, FAST486_EXCEPTION_MF);
+ }
+ else
+ {
+ /* Use the external interrupt */
+ State->FpuCallback(State);
+ }
+}
+
+FORCEINLINE
+BOOLEAN
+FASTCALL
Fast486FpuNormalize(PFAST486_STATE State,
PFAST486_FPU_DATA_REG Data)
{
UINT LeadingZeros;
- if (FPU_IS_NORMALIZED(Data)) return;
+ if (FPU_IS_NORMALIZED(Data)) return TRUE;
if (FPU_IS_ZERO(Data))
{
Data->Exponent = 0;
- return;
+ return TRUE;
}
LeadingZeros = CountLeadingZeros64(Data->Mantissa);
@@ -1528,6 +1545,9 @@
}
else
{
+ /* Raise the underflow exception */
+ State->FpuStatus.Ue = TRUE;
+
if (State->FpuControl.Um)
{
/* Make it denormalized */
@@ -1536,16 +1556,18 @@
}
else
{
- /* Raise the underflow exception */
- State->FpuStatus.Ue = TRUE;
- }
- }
+ Fast486FpuException(State);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
}
FORCEINLINE
USHORT
FASTCALL
-Fast486GetValueTag(PFAST486_FPU_DATA_REG Data)
+Fast486FpuGetValueTag(PFAST486_FPU_DATA_REG Data)
{
if (FPU_IS_ZERO(Data)) return FPU_TAG_ZERO;
else if (FPU_IS_NAN(Data)) return FPU_TAG_SPECIAL;
@@ -1553,7 +1575,7 @@
}
FORCEINLINE
-VOID
+BOOLEAN
FASTCALL
Fast486FpuPush(PFAST486_STATE State,
PFAST486_FPU_DATA_REG Data)
@@ -1563,13 +1585,25 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
FPU_ST(0) = *Data;
- FPU_SET_TAG(0, Fast486GetValueTag(Data));
- }
- else State->FpuStatus.Sf = TRUE;
-}
-
-FORCEINLINE
-VOID
+ FPU_UPDATE_TAG(0);
+
+ return TRUE;
+ }
+ else
+ {
+ /* Raise the stack fault and invalid operation exception */
+ State->FpuStatus.Sf = State->FpuStatus.Ie = TRUE;
+
+ /* Set the C1 condition code bit (stack overflow) */
+ State->FpuStatus.Code1 = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
+ return FALSE;
+ }
+}
+
+FORCEINLINE
+BOOLEAN
FASTCALL
Fast486FpuPop(PFAST486_STATE State)
{
@@ -1577,8 +1611,20 @@
{
FPU_SET_TAG(0, FPU_TAG_EMPTY);
State->FpuStatus.Top++;
- }
- else State->FpuStatus.Sf = TRUE;
+
+ return TRUE;
+ }
+ else
+ {
+ /* Raise the stack fault and invalid operation exception */
+ State->FpuStatus.Sf = State->FpuStatus.Ie = TRUE;
+
+ /* Clear the C1 condition code bit (stack underflow) */
+ State->FpuStatus.Code1 = FALSE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
+ return FALSE;
+ }
}
#endif
Modified: trunk/reactos/lib/fast486/fpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=6596…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Sat Jan 3 22:24:40 2015
@@ -183,6 +183,9 @@
if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value)
|| (UnbiasedExp < 0) || (UnbiasedExp > 63))
{
+ /* Raise an invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
*Result = 0LL;
@@ -190,7 +193,7 @@
}
else
{
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return FALSE;
}
}
@@ -314,6 +317,9 @@
/* Check for underflow */
if (!FPU_IS_NORMALIZED(Value) || (UnbiasedExp < -1023))
{
+ /* Raise the underflow exception */
+ State->FpuStatus.Ue = TRUE;
+
if (State->FpuControl.Um)
{
/* The result is zero due to underflow */
@@ -322,8 +328,7 @@
}
else
{
- /* Raise the underflow exception */
- State->FpuStatus.Ue = TRUE;
+ Fast486FpuException(State);
return FALSE;
}
}
@@ -331,6 +336,9 @@
/* Check for overflow */
if (UnbiasedExp > 1023)
{
+ /* Raise the overflow exception */
+ State->FpuStatus.Oe = TRUE;
+
if (State->FpuControl.Om)
{
/* The result is infinity due to overflow */
@@ -339,8 +347,7 @@
}
else
{
- /* Raise the overflow exception */
- State->FpuStatus.Oe = TRUE;
+ Fast486FpuException(State);
return FALSE;
}
}
@@ -452,12 +459,16 @@
FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand;
FAST486_FPU_DATA_REG TempResult;
- if (!State->FpuControl.Dm
- && (!FPU_IS_NORMALIZED(FirstOperand) ||
!FPU_IS_NORMALIZED(SecondOperand)))
+ if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
{
/* Raise the denormalized exception */
State->FpuStatus.De = TRUE;
- return;
+
+ if (!State->FpuControl.Dm)
+ {
+ Fast486FpuException(State);
+ return;
+ }
}
/* Find the largest exponent */
@@ -503,6 +514,9 @@
{
if (TempResult.Exponent == FPU_MAX_EXPONENT)
{
+ /* Raise the overflow exception */
+ State->FpuStatus.Oe = TRUE;
+
if (State->FpuControl.Om)
{
/* Total overflow, return infinity */
@@ -511,8 +525,7 @@
}
else
{
- /* Raise the overflow exception */
- State->FpuStatus.Oe = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -606,12 +619,16 @@
{
FAST486_FPU_DATA_REG TempResult;
- if (!State->FpuControl.Dm
- && (!FPU_IS_NORMALIZED(FirstOperand) ||
!FPU_IS_NORMALIZED(SecondOperand)))
+ if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
{
/* Raise the denormalized exception */
State->FpuStatus.De = TRUE;
- return;
+
+ if (!State->FpuControl.Dm)
+ {
+ Fast486FpuException(State);
+ return;
+ }
}
UnsignedMult128(FirstOperand->Mantissa,
@@ -641,6 +658,9 @@
|| (FPU_IS_INFINITY(FirstOperand) && FPU_IS_INFINITY(SecondOperand))
|| (FPU_IS_ZERO(FirstOperand) && FPU_IS_ZERO(SecondOperand)))
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -648,17 +668,16 @@
Result->Exponent = FPU_MAX_EXPONENT + 1;
Result->Mantissa = FPU_INDEFINITE_MANTISSA;
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand))
{
+ /* Raise the division by zero exception */
+ State->FpuStatus.Ze = TRUE;
+
if (State->FpuControl.Zm)
{
/* Return infinity */
@@ -666,11 +685,7 @@
Result->Exponent = FPU_MAX_EXPONENT + 1;
Result->Mantissa = FPU_MANTISSA_HIGH_BIT;
}
- else
- {
- /* Raise the division by zero exception */
- State->FpuStatus.Ze = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -705,13 +720,6 @@
{
ULONG BitsToShift = 64 - CountLeadingZeros64(QuotientHigh);
- if (!State->FpuControl.Pm)
- {
- /* Raise the precision expection */
- State->FpuStatus.Pe = TRUE;
- return;
- }
-
TempResult.Mantissa >>= BitsToShift;
TempResult.Mantissa |= QuotientHigh << (64 - BitsToShift);
Exponent += BitsToShift;
@@ -723,13 +731,6 @@
{
TempResult.Mantissa >>= -(Exponent + FPU_REAL10_BIAS);
Exponent = -FPU_REAL10_BIAS;
-
- if ((TempResult.Mantissa == 0ULL) && !State->FpuControl.Um)
- {
- /* Raise the underflow exception */
- State->FpuStatus.Ue = TRUE;
- return;
- }
// TODO: Rounding
}
@@ -834,6 +835,9 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -843,33 +847,32 @@
FPU_SET_TAG(0, FPU_TAG_SPECIAL);
}
- else
+ else Fast486FpuException(State);
+
+ return;
+ }
+
+ if (ModRegRm.Memory)
+ {
+ /* Load the source operand from memory */
+ ULONG Value;
+
+ if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+ {
+ /* Exception occurred */
+ return;
+ }
+
+ Fast486FpuFromSingleReal(State, Value, &MemoryData);
+ SourceOperand = &MemoryData;
+ }
+ else
+ {
+ if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
{
/* Raise the invalid operation exception */
State->FpuStatus.Ie = TRUE;
- }
-
- return;
- }
-
- if (ModRegRm.Memory)
- {
- /* Load the source operand from memory */
- ULONG Value;
-
- if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
- {
- /* Exception occurred */
- return;
- }
-
- Fast486FpuFromSingleReal(State, Value, &MemoryData);
- SourceOperand = &MemoryData;
- }
- else
- {
- if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
- {
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -879,11 +882,7 @@
FPU_SET_TAG(0, FPU_TAG_SPECIAL);
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -925,6 +924,9 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -934,11 +936,7 @@
FPU_SET_TAG(0, FPU_TAG_SPECIAL);
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -970,6 +968,9 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
|| (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -979,11 +980,7 @@
FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_SPECIAL);
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -1124,8 +1121,10 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY))
{
- /* Raise the invalid operation exception, if unmasked */
- if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
+ /* Raise the invalid operation exception*/
+ State->FpuStatus.Ie = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
return;
}
@@ -1151,6 +1150,9 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -1160,11 +1162,7 @@
FPU_SET_TAG(0, FPU_TAG_SPECIAL);
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -1225,10 +1223,12 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) ==
FPU_TAG_SPECIAL))
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (!State->FpuControl.Im)
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1242,7 +1242,13 @@
if ((((ULONGLONG)Temp >> 31) + 1ULL) > 1ULL)
{
State->FpuStatus.Ie = TRUE;
- return;
+
+ if (State->FpuControl.Im) Temp = 0LL;
+ else
+ {
+ Fast486FpuException(State);
+ return;
+ }
}
if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE,
(ULONG)((LONG)Temp)))
@@ -1299,6 +1305,9 @@
}
else
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
*((PULONGLONG)Buffer) = FPU_INDEFINITE_MANTISSA;
@@ -1306,8 +1315,7 @@
}
else
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1442,10 +1450,12 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (!State->FpuControl.Im)
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1521,7 +1531,9 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
|| FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
{
- if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
+ State->FpuStatus.Ie = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
break;
}
@@ -1556,7 +1568,9 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
|| (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
{
- if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
+ State->FpuStatus.Ie = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
return;
}
@@ -1604,6 +1618,9 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (State->FpuControl.Im)
{
/* Return the indefinite NaN */
@@ -1613,11 +1630,7 @@
FPU_SET_TAG(0, FPU_TAG_SPECIAL);
}
- else
- {
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
- }
+ else Fast486FpuException(State);
return;
}
@@ -1652,8 +1665,9 @@
|| (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
{
/* Raise the invalid operation exception, if unmasked */
- if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
-
+ State->FpuStatus.Ie = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
return;
}
}
@@ -1712,10 +1726,12 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) ==
FPU_TAG_SPECIAL))
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (!State->FpuControl.Im)
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1728,8 +1744,15 @@
/* Check if it can fit in a signed 16-bit integer */
if ((((ULONGLONG)Temp >> 15) + 1ULL) > 1ULL)
{
+ /* Raise the invalid operation exception */
State->FpuStatus.Ie = TRUE;
- return;
+
+ if (State->FpuControl.Im) Temp = 0LL;
+ else
+ {
+ Fast486FpuException(State);
+ return;
+ }
}
if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE,
(USHORT)((SHORT)Temp)))
@@ -1802,10 +1825,12 @@
if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (!State->FpuControl.Im)
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1837,10 +1862,12 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) ==
FPU_TAG_SPECIAL))
{
+ /* Raise the invalid operation exception */
+ State->FpuStatus.Ie = TRUE;
+
if (!State->FpuControl.Im)
{
- /* Raise the invalid operation exception */
- State->FpuStatus.Ie = TRUE;
+ Fast486FpuException(State);
return;
}
}
@@ -1895,7 +1922,9 @@
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
|| FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
{
- if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
+ State->FpuStatus.Ie = TRUE;
+
+ if (!State->FpuControl.Im) Fast486FpuException(State);
break;
}
Modified: trunk/reactos/lib/fast486/fpu.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=6596…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.h [iso-8859-1] Sat Jan 3 22:24:40 2015
@@ -33,14 +33,15 @@
Fast486Exception(State, FAST486_EXCEPTION_NM); \
return; \
}
-#define FPU_ST(i) State->FpuRegisters[(State->FpuStatus.Top + (i)) %
FAST486_NUM_FPU_REGS]
+#define FPU_INDEX(i) ((State->FpuStatus.Top + (i)) % FAST486_NUM_FPU_REGS)
+#define FPU_ST(i) State->FpuRegisters[FPU_INDEX(i)]
-#define FPU_GET_TAG(i) ((State->FpuTag >> ((i) * 2)) & 3)
+#define FPU_GET_TAG(i) ((State->FpuTag >> (FPU_INDEX(i) * 2)) & 3)
#define FPU_SET_TAG(i, t) { \
- State->FpuTag &= ~((1 << ((i) * 2)) | (1
<< (((i) * 2) + 1))); \
- State->FpuTag |= ((t) & 3) << ((i) * 2); \
+ State->FpuTag &= ~((1 << (FPU_INDEX(i) * 2))
| (1 << ((FPU_INDEX(i) * 2) + 1))); \
+ State->FpuTag |= ((t) & 3) << (FPU_INDEX(i)
* 2); \
}
-#define FPU_UPDATE_TAG(i) FPU_SET_TAG((i), Fast486GetValueTag(&FPU_ST(i)))
+#define FPU_UPDATE_TAG(i) FPU_SET_TAG((i), Fast486FpuGetValueTag(&FPU_ST(i)))
#define FPU_REAL4_BIAS 0x7F
#define FPU_REAL8_BIAS 0x3FF
Modified: trunk/reactos/lib/fast486/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opcodes.c?rev=…
==============================================================================
--- trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] Sat Jan 3 22:24:40 2015
@@ -4125,16 +4125,7 @@
|| (!State->FpuControl.Dm && State->FpuStatus.De)
|| (!State->FpuControl.Im && State->FpuStatus.Ie))
{
- if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_NE)
- {
- /* Call the #MF handler */
- Fast486Exception(State, FAST486_EXCEPTION_MF);
- }
- else
- {
- /* Use the external interrupt */
- State->FpuCallback(State);
- }
+ Fast486FpuException(State);
}
#endif