Author: aandrejevic
Date: Sat Jan  3 03:26:31 2015
New Revision: 65945

URL: http://svn.reactos.org/svn/reactos?rev=65945&view=rev
Log:
[FAST486]
Halfplement floating point division.
Halfplement opcode 0xD9.


Modified:
    trunk/reactos/lib/fast486/common.inl
    trunk/reactos/lib/fast486/fpu.c
    trunk/reactos/lib/fast486/fpu.h

Modified: trunk/reactos/lib/fast486/common.inl
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev=65945&r1=65944&r2=65945&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/common.inl        [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.inl        [iso-8859-1] Sat Jan  3 
03:26:31 2015
@@ -1528,12 +1528,17 @@
     }
     else
     {
-        /* Make it denormalized */
-        Data->Mantissa <<= Data->Exponent - 1;
-        Data->Exponent = 1;
-
-        /* Underflow */
-        State->FpuStatus.Ue = TRUE;
+        if (State->FpuControl.Um)
+        {
+            /* Make it denormalized */
+            Data->Mantissa <<= Data->Exponent - 1;
+            Data->Exponent = 1;
+        }
+        else
+        {
+            /* Raise the underflow exception */
+            State->FpuStatus.Ue = TRUE;
+        }
     }
 }
 
@@ -1560,7 +1565,7 @@
         FPU_ST(0) = *Data;
         FPU_SET_TAG(0, Fast486GetValueTag(Data));
     }
-    else State->FpuStatus.Ie = TRUE;
+    else State->FpuStatus.Sf = TRUE;
 }
 
 FORCEINLINE
@@ -1573,7 +1578,7 @@
         FPU_SET_TAG(0, FPU_TAG_EMPTY);
         State->FpuStatus.Top++;
     }
-    else State->FpuStatus.Ie = TRUE;
+    else State->FpuStatus.Sf = TRUE;
 }
 
 #endif

Modified: trunk/reactos/lib/fast486/fpu.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=65945&r1=65944&r2=65945&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c     [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c     [iso-8859-1] Sat Jan  3 03:26:31 2015
@@ -66,6 +66,77 @@
     return LowProduct;
 }
 
+static ULONGLONG
+UnsignedDivMod128(ULONGLONG DividendLow,
+                  ULONGLONG DividendHigh,
+                  ULONGLONG Divisor,
+                  PULONGLONG QuotientLow,
+                  PULONGLONG QuotientHigh)
+{
+    ULONGLONG ValueLow = DividendLow;
+    ULONGLONG ValueHigh = DividendHigh;
+    ULONGLONG CurrentLow = 0ULL;
+    ULONGLONG CurrentHigh = Divisor;
+    ULONG Bits;
+
+    ASSERT(Divisor != 0ULL);
+
+    /* Initialize the quotient */
+    *QuotientLow = *QuotientHigh = 0ULL;
+
+    /* Normalize the current divisor */
+    Bits = CountLeadingZeros64(CurrentHigh);
+    CurrentHigh <<= Bits;
+
+    /* Loop while the value is higher than or equal to the original divisor */
+    while ((ValueHigh > 0ULL) || (ValueLow >= Divisor))
+    {
+        /* Shift the quotient left by one bit */
+        *QuotientHigh <<= 1;
+        *QuotientHigh |= *QuotientLow >> 63;
+        *QuotientLow <<= 1;
+
+        /* Check if the value is higher than or equal to the current divisor */
+        if ((ValueHigh > CurrentHigh)
+            || ((ValueHigh == CurrentHigh) && (ValueLow >= CurrentLow)))
+        {
+            BOOLEAN Carry = ValueLow < CurrentLow;
+
+            /* Subtract the current divisor from the value */
+            ValueHigh -= CurrentHigh;
+            ValueLow -= CurrentLow;
+            if (Carry) ValueHigh--;
+
+            /* Set the lowest bit of the quotient */
+            *QuotientLow |= 1;
+        }
+
+        /* Shift the current divisor right by one bit */
+        CurrentLow >>= 1;
+        CurrentLow |= (CurrentHigh & 1) << 63;
+        CurrentHigh >>= 1;
+    }
+
+    /*
+     * Calculate the number of significant bits the current
+     * divisor has more than the original divisor
+     */
+    Bits = CountLeadingZeros64(Divisor) + 64;
+    Bits -= (CurrentHigh > 0ULL) ? CountLeadingZeros64(CurrentHigh) : 64;
+    Bits -= (CurrentLow > 0ULL) ? CountLeadingZeros64(CurrentLow) : 64;
+
+    if (Bits)
+    {
+        /* Shift the quotient left by that amount */
+        *QuotientHigh <<= Bits;
+        *QuotientHigh |= *QuotientLow >> (64 - Bits);
+        *QuotientLow <<= Bits;
+    }
+
+    /* Return the remainder */
+    return ValueLow;
+}
+
 static inline VOID FASTCALL
 Fast486FpuFromInteger(PFAST486_STATE State,
                       LONGLONG Value,
@@ -557,8 +628,31 @@
                  PFAST486_FPU_DATA_REG Result)
 {
     FAST486_FPU_DATA_REG TempResult;
-
-    if (FPU_IS_ZERO(SecondOperand))
+    ULONGLONG QuotientLow, QuotientHigh, Remainder;
+    LONG Exponent;
+
+    if (FPU_IS_INDEFINITE(FirstOperand)
+        || FPU_IS_INDEFINITE(SecondOperand)
+        || (FPU_IS_INFINITY(FirstOperand) && FPU_IS_INFINITY(SecondOperand))
+        || (FPU_IS_ZERO(FirstOperand) && FPU_IS_ZERO(SecondOperand)))
+    {
+        if (State->FpuControl.Im)
+        {
+            /* Return the indefinite NaN */ 
+            Result->Sign = TRUE;
+            Result->Exponent = FPU_MAX_EXPONENT + 1;
+            Result->Mantissa = FPU_INDEFINITE_MANTISSA;
+        }
+        else
+        {
+            /* Raise the invalid operation exception */
+            State->FpuStatus.Ie = TRUE;
+        }
+
+        return;
+    }
+
+    if (FPU_IS_ZERO(SecondOperand) || FPU_IS_INFINITY(FirstOperand))
     {
         if (State->FpuControl.Zm)
         {
@@ -571,16 +665,75 @@
         {
             /* Raise the division by zero exception */
             State->FpuStatus.Ze = TRUE;
+        }
+
+        return;
+    }
+
+    /* Calculate the sign of the result */
+    TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
+
+    if (FPU_IS_ZERO(FirstOperand) || FPU_IS_INFINITY(SecondOperand))
+    {
+        /* Return zero */
+        Result->Sign = TempResult.Sign;
+        Result->Mantissa = 0ULL;
+        Result->Exponent = 0;
+        return;
+    }
+
+    /* Calculate the exponent of the result */
+    Exponent = (LONG)FirstOperand->Exponent - (LONG)SecondOperand->Exponent - 
64;
+
+    /* Divide the two mantissas */
+    Remainder = UnsignedDivMod128(0ULL,
+                                  /* Notice the 64 above - this is the high 
part */
+                                  FirstOperand->Mantissa, 
+                                  SecondOperand->Mantissa,
+                                  &QuotientLow,
+                                  &QuotientHigh);
+    UNREFERENCED_PARAMETER(Remainder); // TODO: Rounding
+
+    TempResult.Mantissa = QuotientLow;
+
+    if (QuotientHigh > 0ULL)
+    {
+        ULONG BitsToShift = 64 - CountLeadingZeros64(QuotientHigh);
+
+        if (!State->FpuControl.Pm)
+        {
+            /* Raise the precision expection */
+            State->FpuStatus.Pe = TRUE;
             return;
         }
-    }
-
-    TempResult.Exponent = FirstOperand->Exponent - SecondOperand->Exponent;
-    TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
-
-    // TODO: NOT IMPLEMENTED
-    UNREFERENCED_PARAMETER(TempResult);
-    UNIMPLEMENTED;
+
+        TempResult.Mantissa >>= BitsToShift;
+        TempResult.Mantissa |= QuotientHigh << (64 - BitsToShift);
+        Exponent += BitsToShift;
+
+        // TODO: Rounding
+    }
+
+    if (Exponent < -FPU_REAL10_BIAS)
+    {
+        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
+    }
+
+    TempResult.Exponent = (USHORT)(Exponent + FPU_REAL10_BIAS);
+
+    /* Normalize the result */
+    Fast486FpuNormalize(State, &TempResult);
+    *Result = TempResult;
 }
 
 static inline VOID FASTCALL
@@ -853,10 +1006,86 @@
     FPU_CHECK();
 
 #ifndef FAST486_NO_FPU
-    // TODO: NOT IMPLEMENTED
-    UNIMPLEMENTED;
-#else
-    /* Do nothing */
+
+    if (ModRegRm.Memory)
+    {
+        switch (ModRegRm.Register)
+        {
+            /* FLD */
+            case 0:
+            {
+                ULONG Value;
+                FAST486_FPU_DATA_REG MemoryData;
+
+                if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, 
&Value))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                Fast486FpuFromSingleReal(State, Value, &MemoryData);
+                Fast486FpuPush(State, &MemoryData);
+
+                break;
+            }
+
+            /* FST */
+            case 2:
+            /* FSTP */
+            case 3:
+            {
+                // TODO: NOT IMPLEMENTED
+                UNIMPLEMENTED;
+
+                break;
+            }
+
+            /* FLDENV */
+            case 4:
+            {
+                // TODO: NOT IMPLEMENTED
+                UNIMPLEMENTED;
+
+                break;
+            }
+
+            /* FLDCW */
+            case 5:
+            {
+                Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, 
&State->FpuControl.Value);
+                break;
+            }
+
+            /* FSTENV */
+            case 6:
+            {
+                // TODO: NOT IMPLEMENTED
+                UNIMPLEMENTED;
+
+                break;
+            }
+
+            /* FSTCW */
+            case 7:
+            {
+                Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, 
State->FpuControl.Value);
+                break;
+            }
+
+            /* Invalid */
+            default:
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return;
+            }
+        }
+    }
+    else
+    {
+        // TODO: NOT IMPLEMENTED
+        UNIMPLEMENTED;
+    }
+
 #endif
 }
 

Modified: trunk/reactos/lib/fast486/fpu.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=65945&r1=65944&r2=65945&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/fpu.h     [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.h     [iso-8859-1] Sat Jan  3 03:26:31 2015
@@ -59,6 +59,7 @@
 #define FPU_IS_INFINITY(x)      (FPU_IS_NAN(x) && ((x)->Mantissa == 
FPU_MANTISSA_HIGH_BIT))
 #define FPU_IS_POS_INF(x)       (FPU_IS_INFINITY(x) && !(x)->Sign)
 #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))
 
 enum
 {


Reply via email to