+static VOID Fast486FpuGetDoubleReal(PFAST486_STATE State,
+ ULONGLONG Value,
+ PFAST486_FPU_DATA_REG Result)
+{
+ /* Extract the sign, exponent and mantissa */
+ Result->Sign = (UCHAR)(Value >> 63);
+ Result->Exponent = (USHORT)((Value >> 52) & 0x7FF);
+ Result->Mantissa = (((ULONGLONG)Value & 0xFFFFFFFFFFFFFULL) | 0x10000000000000ULL) << 11;
+
+ /* If this is a zero, we're done */
+ if (Value == 0) return;
+
+ if (Result->Exponent == 0x3FF) Result->Exponent = FPU_MAX_EXPONENT + 1;
+ else
+ {
+ /* Adjust the exponent bias */
+ Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL8_BIAS);
+ }
+}
+
+static VOID Fast486FpuAdd(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG FirstAdjusted = *FirstOperand;
+ FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand;
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+ {
+ /* Denormalized */
+ State->FpuStatus.De = TRUE;
+ }
+
+ /* Find the largest exponent */
+ TempResult.Exponent = max(FirstOperand->Exponent, SecondOperand->Exponent);
+
+ /* Adjust the first operand to it */
+ if (FirstAdjusted.Exponent < TempResult.Exponent)
+ {
+ FirstAdjusted.Mantissa >>= (TempResult.Exponent - FirstAdjusted.Exponent);
+ FirstAdjusted.Exponent = TempResult.Exponent;
+ }
+
+ /* ... and the second one too */
+ if (SecondAdjusted.Exponent < TempResult.Exponent)
+ {
+ SecondAdjusted.Mantissa >>= (TempResult.Exponent - SecondAdjusted.Exponent);
+ SecondAdjusted.Exponent = TempResult.Exponent;
+ }
+
+ if (FirstAdjusted.Sign == SecondAdjusted.Sign)
+ {
+ /* Calculate the mantissa and sign of the result */
+ TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
+ TempResult.Sign = FirstAdjusted.Sign;
+ }
+ else
+ {
+ /* Calculate the sign of the result */
+ if (FirstAdjusted.Mantissa > SecondAdjusted.Mantissa) TempResult.Sign = FirstAdjusted.Sign;
+ else if (FirstAdjusted.Mantissa < SecondAdjusted.Mantissa) TempResult.Sign = SecondAdjusted.Sign;
+ else TempResult.Sign = FALSE;
+
+ /* Invert the negative mantissa */
+ if (FirstAdjusted.Sign) FirstAdjusted.Mantissa = -FirstAdjusted.Mantissa;
+ if (SecondAdjusted.Sign) SecondAdjusted.Mantissa = -SecondAdjusted.Mantissa;
+
+ /* Calculate the mantissa of the result */
+ TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
+ }
+
+ /* Did it overflow? */
+ if (FPU_IS_NORMALIZED(&FirstAdjusted) && FPU_IS_NORMALIZED(&SecondAdjusted))
+ {
+ if (TempResult.Exponent == FPU_MAX_EXPONENT)
+ {
+ /* Total overflow, return infinity */
+ TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT;
+ TempResult.Exponent = FPU_MAX_EXPONENT + 1;
+
+ /* Update flags */
+ State->FpuStatus.Oe = TRUE;
+ }
+ else
+ {
+ /* Lose the LSB in favor of the carry */
+ TempResult.Mantissa >>= 1;
+ TempResult.Mantissa |= FPU_MANTISSA_HIGH_BIT;
+ TempResult.Exponent++;
+ }
+ }
+
+ /* Normalize the result and return it */
+ Fast486FpuNormalize(State, &TempResult);
+ *Result = TempResult;
+}
+
+static VOID Fast486FpuSubtract(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG NegativeSecondOperand = *SecondOperand;
+
+ /* Invert the sign */
+ NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign;
+
+ /* And perform an addition instead */
+ Fast486FpuAdd(State, Result, FirstOperand, &NegativeSecondOperand);
+}
+
+static VOID Fast486FpuCompare(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand)
+{
+ if (FPU_IS_NAN(FirstOperand) || FPU_IS_NAN(SecondOperand))
+ {
+ if (FPU_IS_POS_INF(FirstOperand) && FPU_IS_NEG_INF(SecondOperand))
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else if (FPU_IS_NEG_INF(FirstOperand) && FPU_IS_POS_INF(SecondOperand))
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = TRUE;
+ State->FpuStatus.Code3 = TRUE;
+ }
+ }
+ else
+ {
+ FAST486_FPU_DATA_REG TempResult;
+
+ Fast486FpuSubtract(State, FirstOperand, SecondOperand, &TempResult);
+
+ if (FPU_IS_ZERO(&TempResult))
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = TRUE;
+ }
+ else if (TempResult.Sign)
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ }
+}
+
+static VOID Fast486FpuMultiply(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+ {
+ /* Denormalized */
+ State->FpuStatus.De = TRUE;
+ }
+
+ UnsignedMult128(FirstOperand->Mantissa,
+ SecondOperand->Mantissa,
+ &TempResult.Mantissa);
+
+ TempResult.Exponent = FirstOperand->Exponent + SecondOperand->Exponent;
+ TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
+
+ /* Normalize the result */
+ Fast486FpuNormalize(State, &TempResult);
+ *Result = TempResult;
+}
+
+static VOID Fast486FpuDivide(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (FPU_IS_ZERO(SecondOperand))
+ {
+ /* Division by zero */
+ State->FpuStatus.Ze = TRUE;
+ return;
+ }
+
+ TempResult.Exponent = FirstOperand->Exponent - SecondOperand->Exponent;
+ TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;