Author: aandrejevic Date: Sun May 17 16:21:29 2015 New Revision: 67814
URL: http://svn.reactos.org/svn/reactos?rev=67814&view=rev Log: [FAST486] Implement F2XM1 using a Maclaurin series.
Modified: trunk/reactos/lib/fast486/fpu.c trunk/reactos/lib/fast486/fpu.h
Modified: trunk/reactos/lib/fast486/fpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=67814... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Sun May 17 16:21:29 2015 @@ -53,6 +53,30 @@ /* ln(2) */ static const FAST486_FPU_DATA_REG FpuLnTwo = {0xB17217F7D1CF79ABULL, FPU_REAL10_BIAS - 1, FALSE};
+static const FAST486_FPU_DATA_REG FpuInverseNumber[INVERSE_NUMBERS_COUNT] = +{ + {0x8000000000000000ULL, FPU_REAL10_BIAS, FALSE}, /* 1 / 1 */ + {0x8000000000000000ULL, FPU_REAL10_BIAS - 1, FALSE}, /* 1 / 2 */ + {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 2, FALSE}, /* 1 / 3 */ + {0x8000000000000000ULL, FPU_REAL10_BIAS - 2, FALSE}, /* 1 / 4 */ + {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 5 */ + {0xAAAAAAAAAAAAAAAAULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 6 */ + {0x9249249249249249ULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 7 */ + {0x8000000000000000ULL, FPU_REAL10_BIAS - 3, FALSE}, /* 1 / 8 */ + {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 9 */ + {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 10 */ + {0xBA2E8BA2E8BA2E8CULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 11 */ + {0xAAAAAAAAAAAAAAABULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 12 */ + {0x9D89D89D89D89D8AULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 13 */ + {0x9249249249249249ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 14 */ + {0x8888888888888889ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 15 */ + {0x8000000000000000ULL, FPU_REAL10_BIAS - 4, FALSE}, /* 1 / 16 */ + {0xF0F0F0F0F0F0F0F0ULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 17 */ + {0xE38E38E38E38E38EULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 18 */ + {0xD79435E50D79435EULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 19 */ + {0xCCCCCCCCCCCCCCCDULL, FPU_REAL10_BIAS - 5, FALSE}, /* 1 / 20 */ +}; + /* PRIVATE FUNCTIONS **********************************************************/
#ifndef FAST486_NO_FPU @@ -527,7 +551,7 @@ return TRUE; }
-static inline VOID FASTCALL +static inline BOOLEAN FASTCALL Fast486FpuAdd(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, @@ -545,7 +569,7 @@ if (!State->FpuControl.Dm) { Fast486FpuException(State); - return; + return FALSE; } }
@@ -604,7 +628,7 @@ else { Fast486FpuException(State); - return; + return FALSE; } } else @@ -617,11 +641,17 @@ }
/* Normalize the result and return it */ - Fast486FpuNormalize(State, &TempResult); + if (!Fast486FpuNormalize(State, &TempResult)) + { + /* Exception occurred */ + return FALSE; + } + *Result = TempResult; + return TRUE; }
-static inline VOID FASTCALL +static inline BOOLEAN FASTCALL Fast486FpuSubtract(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, @@ -633,7 +663,7 @@ NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign;
/* And perform an addition instead */ - Fast486FpuAdd(State, FirstOperand, &NegativeSecondOperand, Result); + return Fast486FpuAdd(State, FirstOperand, &NegativeSecondOperand, Result); }
static inline VOID FASTCALL @@ -689,7 +719,7 @@ } }
-static inline VOID FASTCALL +static inline BOOLEAN FASTCALL Fast486FpuMultiply(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, @@ -707,7 +737,7 @@ Result->Sign = TRUE; Result->Exponent = FPU_MAX_EXPONENT + 1; Result->Mantissa = FPU_INDEFINITE_MANTISSA; - return; + return TRUE; }
if (FPU_IS_ZERO(FirstOperand) || FPU_IS_ZERO(SecondOperand)) @@ -716,7 +746,7 @@ Result->Sign = FirstOperand->Sign ^ SecondOperand->Sign; Result->Exponent = 0; Result->Mantissa = 0ULL; - return; + return TRUE; }
if (FPU_IS_INFINITY(FirstOperand) || FPU_IS_INFINITY(SecondOperand)) @@ -725,7 +755,7 @@ Result->Sign = FirstOperand->Sign ^ SecondOperand->Sign; Result->Exponent = FPU_MAX_EXPONENT + 1; Result->Mantissa = FPU_MANTISSA_HIGH_BIT; - return; + return TRUE; }
if ((!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))) @@ -736,7 +766,7 @@ if (!State->FpuControl.Dm) { Fast486FpuException(State); - return; + return FALSE; } }
@@ -759,7 +789,7 @@ if (!State->FpuControl.Um) { Fast486FpuException(State); - return; + return FALSE; }
/* The exponent will be zero */ @@ -777,7 +807,7 @@ if (!State->FpuControl.Om) { Fast486FpuException(State); - return; + return FALSE; }
/* Make the result infinity */ @@ -787,11 +817,17 @@ else TempResult.Exponent = (USHORT)Exponent;
/* Normalize the result */ - Fast486FpuNormalize(State, &TempResult); + if (!Fast486FpuNormalize(State, &TempResult)) + { + /* Exception occurred */ + return FALSE; + } + *Result = TempResult; + return TRUE; }
-static inline VOID FASTCALL +static inline BOOLEAN FASTCALL Fast486FpuDivide(PFAST486_STATE State, PCFAST486_FPU_DATA_REG FirstOperand, PCFAST486_FPU_DATA_REG SecondOperand, @@ -815,10 +851,13 @@ Result->Sign = TRUE; Result->Exponent = FPU_MAX_EXPONENT + 1; Result->Mantissa = FPU_INDEFINITE_MANTISSA; - } - else Fast486FpuException(State); - - return; + return TRUE; + } + else + { + Fast486FpuException(State); + return FALSE; + } }
if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand)) @@ -832,10 +871,13 @@ Result->Sign = FirstOperand->Sign; Result->Exponent = FPU_MAX_EXPONENT + 1; Result->Mantissa = FPU_MANTISSA_HIGH_BIT; - } - else Fast486FpuException(State); - - return; + return TRUE; + } + else + { + Fast486FpuException(State); + return FALSE; + } }
/* Calculate the sign of the result */ @@ -847,7 +889,7 @@ Result->Sign = TempResult.Sign; Result->Mantissa = 0ULL; Result->Exponent = 0; - return; + return TRUE; }
/* Calculate the exponent of the result */ @@ -886,7 +928,62 @@ TempResult.Exponent = (USHORT)(Exponent + FPU_REAL10_BIAS);
/* Normalize the result */ - Fast486FpuNormalize(State, &TempResult); + if (!Fast486FpuNormalize(State, &TempResult)) + { + /* Exception occurred */ + return FALSE; + } + + *Result = TempResult; + return TRUE; +} + +/* + * Calculates using the identity: + * 2 ^ x - 1 = 1 + sum { 2 * (((x - 1) * ln(2)) ^ n) / n! } + */ +static inline VOID FASTCALL +Fast486FpuCalculateTwoPowerMinusOne(PFAST486_STATE State, + PFAST486_FPU_DATA_REG Operand, + PFAST486_FPU_DATA_REG Result) +{ + INT i; + FAST486_FPU_DATA_REG TempResult = FpuOne; + FAST486_FPU_DATA_REG Value; + FAST486_FPU_DATA_REG SeriesElement; + + /* Calculate the first series element, which is 2 * (x - 1) * ln(2) */ + Fast486FpuSubtract(State, Operand, &FpuOne, &Value); + Fast486FpuMultiply(State, &Value, &FpuLnTwo, &Value); + Fast486FpuAdd(State, &Value, &Value, &SeriesElement); + + for (i = 2; i < INVERSE_NUMBERS_COUNT; i++) + { + /* Add the series element to the final sum */ + if (!Fast486FpuAdd(State, &TempResult, &SeriesElement, &TempResult)) + { + /* An exception occurred */ + return; + } + + /* + * Calculate the next series element (partially) by multiplying + * it with (x - 1) * ln(2) + */ + if (!Fast486FpuMultiply(State, &SeriesElement, &Value, &SeriesElement)) + { + /* An exception occurred */ + return; + } + + /* And now multiply the series element by the inverse counter */ + if (!Fast486FpuMultiply(State, &SeriesElement, &FpuInverseNumber[i], &SeriesElement)) + { + /* An exception occurred */ + return; + } + } + *Result = TempResult; }
@@ -1471,8 +1568,10 @@ /* F2XM1 */ case 0x30: { - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; + FPU_SAVE_LAST_INST(); + + Fast486FpuCalculateTwoPowerMinusOne(State, &FPU_ST(0), &FPU_ST(0)); + FPU_UPDATE_TAG(0);
break; }
Modified: trunk/reactos/lib/fast486/fpu.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=67814... ============================================================================== --- trunk/reactos/lib/fast486/fpu.h [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.h [iso-8859-1] Sun May 17 16:21:29 2015 @@ -71,6 +71,8 @@ #define FPU_IS_NEG_INF(x) (FPU_IS_INFINITY(x) && (x)->Sign) #define FPU_IS_INDEFINITE(x) (FPU_IS_NAN(x) && !FPU_IS_INFINITY(x))
+#define INVERSE_NUMBERS_COUNT 21 + enum { FPU_SINGLE_PRECISION = 0,