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=65966&r1=65965&r2=65966&view=diff ============================================================================== --- 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=65966&r1=65965&r2=65966&view=diff ============================================================================== --- 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=65966&r1=65965&r2=65966&view=diff ============================================================================== --- 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=65966&r1=65965&r2=65966&view=diff ============================================================================== --- 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