Author: aandrejevic Date: Mon May 18 15:27:08 2015 New Revision: 67821
URL: http://svn.reactos.org/svn/reactos?rev=67821&view=rev Log: [FAST486] Implement FYL2X and FYL2XP1.
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=67821... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Mon May 18 15:27:08 2015 @@ -1020,6 +1020,110 @@ }
/* + * Calculates using the identities: + * log2(x) = log10(x) / log10(2) + * log10(x)= sum { -1^(n+1) * x^n / n!, n >= 1 } + */ +static inline BOOLEAN FASTCALL +Fast486FpuCalculateLogBase2(PFAST486_STATE State, + PFAST486_FPU_DATA_REG Operand, + PFAST486_FPU_DATA_REG Result) +{ + INT i; + FAST486_FPU_DATA_REG Value = *Operand; + FAST486_FPU_DATA_REG SeriesElement; + FAST486_FPU_DATA_REG TempResult; + FAST486_FPU_DATA_REG TempValue; + LONGLONG UnbiasedExp = (LONGLONG)Operand->Exponent - FPU_REAL10_BIAS; + + if (Operand->Sign) + { + /* Raise the invalid operation exception */ + State->FpuStatus.Ie = TRUE; + + if (State->FpuControl.Im) + { + /* Return the indefinite NaN */ + Result->Sign = TRUE; + Result->Exponent = FPU_MAX_EXPONENT + 1; + Result->Mantissa = FPU_INDEFINITE_MANTISSA; + return TRUE; + } + else + { + Fast486FpuException(State); + return FALSE; + } + } + + /* Get only the mantissa as a floating-pointer number between 1 and 2 */ + Value.Exponent = FPU_REAL10_BIAS; + + /* Check if it's denormalized */ + if (!FPU_IS_NORMALIZED(&Value)) + { + ULONG Bits; + State->FpuStatus.De = TRUE; + + if (!State->FpuControl.Dm) + { + Fast486FpuException(State); + return FALSE; + } + + /* Normalize the number */ + Bits = CountLeadingZeros64(Value.Mantissa); + UnbiasedExp -= Bits; + Value.Mantissa <<= Bits; + } + + /* Subtract one from the value */ + if (!Fast486FpuSubtract(State, &Value, &FpuOne, &Value)) return FALSE; + + /* Calculate the base 10 logarithm */ + SeriesElement = TempResult = Value; + + for (i = 2; i < INVERSE_NUMBERS_COUNT / 2; i++) + { + if (!Fast486FpuMultiply(State, &SeriesElement, &Value, &SeriesElement)) + { + /* An exception occurred */ + return FALSE; + } + + /* Toggle the sign of the series element */ + SeriesElement.Sign = !SeriesElement.Sign; + + /* Divide it by the counter */ + if (!Fast486FpuMultiply(State, &SeriesElement, &FpuInverseNumber[i - 1], &TempValue)) + { + /* An exception occurred */ + return FALSE; + } + + /* And add it to the result */ + if (!Fast486FpuAdd(State, &TempResult, &TempValue, &TempResult)) + { + /* An exception occurred */ + return FALSE; + } + } + + /* Now convert the base 10 logarithm into a base 2 logarithm */ + if (!Fast486FpuDivide(State, &TempResult, &FpuLgTwo, &TempResult)) return FALSE; + + /* + * Add the exponent to the result + * log2(x * 2^y) = log2(x) + log2(2^y) = log2(x) + y + */ + Fast486FpuFromInteger(State, UnbiasedExp, &TempValue); + if (!Fast486FpuAdd(State, &TempValue, &TempResult, &TempResult)) return FALSE; + + *Result = TempResult; + return TRUE; +} + +/* * Calculates using the identity: * sin(x) = sum { -1^n * x^(2n + 1) / (2n + 1)!, n >= 0 } */ @@ -1726,8 +1830,31 @@ /* FYL2X */ case 0x31: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + FAST486_FPU_DATA_REG Logarithm; + + if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) + { + State->FpuStatus.Ie = TRUE; + + if (!State->FpuControl.Im) Fast486FpuException(State); + break; + } + + if (!Fast486FpuCalculateLogBase2(State, &FPU_ST(0), &Logarithm)) + { + /* Exception occurred */ + break; + } + + if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1))) + { + /* Exception occurred */ + break; + } + + /* Pop the stack so that the result ends up in ST0 */ + Fast486FpuPop(State); + FPU_UPDATE_TAG(0);
break; } @@ -1828,8 +1955,37 @@ /* FYL2XP1 */ case 0x39: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + FAST486_FPU_DATA_REG Value, Logarithm; + + if (FPU_GET_TAG(0) == FPU_TAG_EMPTY || FPU_GET_TAG(1) == FPU_TAG_EMPTY) + { + State->FpuStatus.Ie = TRUE; + + if (!State->FpuControl.Im) Fast486FpuException(State); + break; + } + + if (!Fast486FpuAdd(State, &FPU_ST(0), &FpuOne, &Value)) + { + /* Exception occurred */ + break; + } + + if (!Fast486FpuCalculateLogBase2(State, &Value, &Logarithm)) + { + /* Exception occurred */ + break; + } + + if (!Fast486FpuMultiply(State, &Logarithm, &FPU_ST(1), &FPU_ST(1))) + { + /* Exception occurred */ + break; + } + + /* Pop the stack so that the result ends up in ST0 */ + Fast486FpuPop(State); + FPU_UPDATE_TAG(0);
break; }