Author: aandrejevic Date: Thu Feb 5 01:03:09 2015 New Revision: 66170
URL: http://svn.reactos.org/svn/reactos?rev=66170&view=rev Log: [FAST486] Implement FRNDINT.
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=66170... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Thu Feb 5 01:03:09 2015 @@ -34,59 +34,24 @@
/* 0.00 */ static const FAST486_FPU_DATA_REG FpuZero = {0ULL, 0, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = 0, -// .Mantissa = 0ULL -// };
/* 1.00 */ static const FAST486_FPU_DATA_REG FpuOne = {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS, -// .Mantissa = 0x8000000000000000ULL -// };
/* Pi */ static const FAST486_FPU_DATA_REG FpuPi = {0xC90FDAA22168C234ULL, FPU_REAL10_BIAS + 1, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS + 1, -// .Mantissa = 0xC90FDAA22168C234ULL -// };
/* lb(10) */ static const FAST486_FPU_DATA_REG FpuL2Ten = {0xD49A784BCD1D8AFEULL, FPU_REAL10_BIAS + 1, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS + 1, -// .Mantissa = 0xD49A784BCD1D8AFEULL -// };
/* lb(e) */ static const FAST486_FPU_DATA_REG FpuL2E = {0xB8AA3B295C17F0BBULL, FPU_REAL10_BIAS, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS, -// .Mantissa = 0xB8AA3B295C17F0BBULL -// };
/* lg(2) */ static const FAST486_FPU_DATA_REG FpuLgTwo = {0x9A209A84FBCFF798ULL, FPU_REAL10_BIAS - 2, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS - 2, -// .Mantissa = 0x9A209A84FBCFF798ULL -// };
/* ln(2) */ static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ABULL, FPU_REAL10_BIAS - 1, FALSE}; -// { -// .Sign = FALSE, -// .Exponent = FPU_REAL10_BIAS - 1, -// .Mantissa = 0xB17217F7D1CF79ABULL -// };
/* PRIVATE FUNCTIONS **********************************************************/
@@ -201,6 +166,52 @@ }
static inline VOID FASTCALL +Fast486FpuRound(PFAST486_STATE State, + PULONGLONG Result, + BOOLEAN Sign, + ULONGLONG Remainder, + INT RemainderHighBit) +{ + switch (State->FpuControl.Rc) + { + case FPU_ROUND_NEAREST: + { + /* Check if the highest bit of the remainder is set */ + if (Remainder & (1ULL << RemainderHighBit)) + { + (*Result)++; + + /* Check if all the other bits are clear */ + if (!(Remainder & ((1ULL << RemainderHighBit) - 1))) + { + /* Round to even */ + *Result &= ~1; + } + } + + break; + } + + case FPU_ROUND_DOWN: + { + if ((Remainder != 0ULL) && Sign) (*Result)++; + break; + } + + case FPU_ROUND_UP: + { + if ((Remainder != 0ULL) && !Sign) (*Result)++; + break; + } + + default: + { + /* Leave it truncated */ + } + } +} + +static inline VOID FASTCALL Fast486FpuFromInteger(PFAST486_STATE State, LONGLONG Value, PFAST486_FPU_DATA_REG Result) @@ -265,43 +276,8 @@ /* The result must be positive here */ ASSERT(*Result >= 0LL);
- switch (State->FpuControl.Rc) - { - case FPU_ROUND_NEAREST: - { - /* Check if the highest bit of the remainder is set */ - if (Remainder & (1 << (Bits - 1))) - { - (*Result)++; - - /* Check if all the other bits are clear */ - if (!(Remainder & ((1 << (Bits - 1)) - 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 */ - } - } + /* Perform rounding */ + Fast486FpuRound(State, (PULONGLONG)Result, Value->Sign, Remainder, Bits - 1);
if (Value->Sign) *Result = -*Result; return TRUE; @@ -335,6 +311,7 @@ { ULONGLONG Remainder; SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS; + ULONGLONG Result64;
if (FPU_IS_ZERO(Value)) { @@ -392,43 +369,10 @@ /* 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 */ - } - } + /* Perform rounding */ + Result64 = (ULONGLONG)*Result; + Fast486FpuRound(State, &Result64, Value->Sign, Remainder, 39); + *Result = (ULONG)Result64;
/* Store the biased exponent */ *Result |= (ULONG)(UnbiasedExp + FPU_REAL4_BIAS) << 23; @@ -524,43 +468,8 @@ /* Calculate the remainder */ Remainder = Value->Mantissa & ((1 << 11) - 1);
- switch (State->FpuControl.Rc) - { - case FPU_ROUND_NEAREST: - { - /* Check if the highest bit of the remainder is set */ - if (Remainder & (1 << 10)) - { - (*Result)++; - - /* Check if all the other bits are clear */ - if (!(Remainder & ((1 << 10) - 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 */ - } - } + /* Perform rounding */ + Fast486FpuRound(State, Result, Value->Sign, Remainder, 10);
/* Store the biased exponent */ *Result |= (ULONGLONG)(UnbiasedExp + FPU_REAL8_BIAS) << 52; @@ -1628,8 +1537,44 @@ /* FRNDINT */ case 0x3C: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + INT Bits; + ULONGLONG Result = 0ULL; + ULONGLONG Remainder; + + if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) + { + State->FpuStatus.Ie = TRUE; + + if (!State->FpuControl.Im) Fast486FpuException(State); + break; + } + + if (!FPU_IS_NORMALIZED(&FPU_ST(0))) + { + State->FpuStatus.De = TRUE; + + if (!State->FpuControl.Dm) + { + Fast486FpuException(State); + break; + } + } + + Bits = min(max(0, (INT)FPU_ST(0).Exponent - FPU_REAL10_BIAS + 1), 64); + if (Bits == 64) break; + + if (Bits) + { + Result = FPU_ST(0).Mantissa >> (64 - Bits); + Remainder = FPU_ST(0).Mantissa & ((1 << (64 - Bits)) - 1); + } + else Remainder = FPU_ST(0).Mantissa; + + /* Perform the rounding */ + Fast486FpuRound(State, &Result, FPU_ST(0).Sign, Remainder, 63 - Bits); + + State->FpuStatus.Pe = TRUE; + if (!State->FpuControl.Pm) Fast486FpuException(State);
break; }