Author: aandrejevic
Date: Thu Jan  1 04:25:09 2015
New Revision: 65927

URL: http://svn.reactos.org/svn/reactos?rev=65927&view=rev
Log:
[FAST486]
Finish implementing FPU opcode 0xDB (FILD, FIST, FISTP, FLD, FSTP).


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=65927&r1=65926&r2=65927&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c     [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c     [iso-8859-1] Thu Jan  1 04:25:09 2015
@@ -67,9 +67,105 @@
 }
 
 static VOID
-Fast486FpuGetSingleReal(PFAST486_STATE State,
-                        ULONG Value,
-                        PFAST486_FPU_DATA_REG Result)
+Fast486FpuFromInteger(PFAST486_STATE State,
+                      LONGLONG Value,
+                      PFAST486_FPU_DATA_REG Result)
+{
+    ULONG ZeroCount;
+
+    Result->Sign = Result->Exponent = Result->Mantissa = 0;
+    if (Value == 0LL) return;
+
+    if (Value < 0LL)
+    {
+        Result->Sign = 1;
+        Value = -Value;
+    }
+
+    Result->Mantissa = (ULONGLONG)Value;
+    ZeroCount = CountLeadingZeros64(Result->Mantissa);
+    
+    Result->Mantissa <<= ZeroCount;
+    Result->Exponent = FPU_REAL10_BIAS + 63 - ZeroCount;
+}
+
+static BOOLEAN
+Fast486FpuToInteger(PFAST486_STATE State,
+                    PFAST486_FPU_DATA_REG Value,
+                    PLONGLONG Result)
+{
+    ULONG Bits;
+    ULONGLONG Remainder;
+    SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
+
+    if (FPU_IS_ZERO(Value))
+    {
+        Result = 0LL;
+        return TRUE;
+    }
+    
+    if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value)
+        || (UnbiasedExp < 0) || (UnbiasedExp > 63))
+    {
+        State->FpuStatus.Ie = TRUE;
+        return FALSE;
+    }
+
+    Bits = 63 - UnbiasedExp;
+
+    /* Calculate the result and the remainder */
+    *Result = (LONGLONG)(Value->Mantissa >> Bits);
+    Remainder = Value->Mantissa & ((1 << Bits) - 1);
+
+    /* 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 */
+        }
+    }
+
+    if (Value->Sign) *Result = -*Result;
+    return TRUE;
+}
+
+static VOID
+Fast486FpuFromSingleReal(PFAST486_STATE State,
+                         ULONG Value,
+                         PFAST486_FPU_DATA_REG Result)
 {
     /* Extract the sign, exponent and mantissa */
     Result->Sign = (UCHAR)(Value >> 31);
@@ -88,9 +184,9 @@
 }
 
 static VOID
-Fast486FpuGetDoubleReal(PFAST486_STATE State,
-                        ULONGLONG Value,
-                        PFAST486_FPU_DATA_REG Result)
+Fast486FpuFromDoubleReal(PFAST486_STATE State,
+                         ULONGLONG Value,
+                         PFAST486_FPU_DATA_REG Result)
 {
     /* Extract the sign, exponent and mantissa */
     Result->Sign = (UCHAR)(Value >> 63);
@@ -347,7 +443,7 @@
                 return;
             }
 
-            Fast486FpuGetDoubleReal(State, Value, &MemoryData);
+            Fast486FpuFromDoubleReal(State, Value, &MemoryData);
         }
         else
         {
@@ -359,7 +455,7 @@
                 return;
             }
 
-            Fast486FpuGetSingleReal(State, Value, &MemoryData);
+            Fast486FpuFromSingleReal(State, Value, &MemoryData);
         }
 
         SourceOperand = &MemoryData;
@@ -509,8 +605,130 @@
 
     if (ModRegRm.Memory)
     {
-        // TODO: NOT IMPLEMENTED
-        UNIMPLEMENTED;
+        switch (ModRegRm.Register)
+        {
+            /* FILD */
+            case 0:
+            {
+                LONG Value;
+                FAST486_FPU_DATA_REG Temp;
+
+                if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, 
(PULONG)&Value))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp);
+                Fast486FpuPush(State, &Temp);
+
+                break;
+            }
+
+            /* FIST */
+            case 2:
+            /* FISTP */
+            case 3:
+            {
+                LONGLONG Temp;
+
+                if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == 
FPU_TAG_SPECIAL))
+                {
+                    /* Fail */
+                    State->FpuStatus.Ie = TRUE;
+                    return;
+                }
+
+                if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                /* Check if it can fit in a signed 32-bit integer */
+                if ((((ULONGLONG)Temp >> 31) + 1ULL) > 1ULL)
+                {
+                    State->FpuStatus.Ie = TRUE;
+                    return;
+                }
+
+                if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, 
(ULONG)((LONG)Temp)))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                if (ModRegRm.Register == 3)
+                {
+                    /* Pop the FPU stack too */
+                    Fast486FpuPop(State);
+                }
+
+                break;
+            }
+
+            /* FLD */
+            case 5:
+            {
+                FAST486_FPU_DATA_REG Value;
+                UCHAR Buffer[10];
+
+                if (!Fast486ReadMemory(State,
+                                       (State->PrefixFlags & 
FAST486_PREFIX_SEG)
+                                       ? State->SegmentOverride : 
FAST486_REG_DS,
+                                       ModRegRm.MemoryAddress,
+                                       FALSE,
+                                       Buffer,
+                                       sizeof(Buffer)))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                Value.Mantissa = *((PULONGLONG)Buffer);
+                Value.Exponent = *((PUSHORT)&Buffer[8]) & (FPU_MAX_EXPONENT + 
1);
+                Value.Sign = *((PUCHAR)&Buffer[9]) >> 7;
+
+                Fast486FpuPush(State, &Value); 
+                break;
+            }
+
+            /* FSTP */
+            case 7:
+            {
+                UCHAR Buffer[10];
+
+                if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == 
FPU_TAG_SPECIAL))
+                {
+                    /* Fail */
+                    State->FpuStatus.Ie = TRUE;
+                    return;
+                }
+
+                *((PULONGLONG)Buffer) = FPU_ST(0).Mantissa;
+                *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = FPU_ST(0).Exponent | 
(FPU_ST(0).Sign ? 0x8000 : 0);
+
+                if (!Fast486WriteMemory(State,
+                                        (State->PrefixFlags & 
FAST486_PREFIX_SEG)
+                                        ? State->SegmentOverride : 
FAST486_REG_DS,
+                                        ModRegRm.MemoryAddress,
+                                        Buffer,
+                                        sizeof(Buffer)))
+                {
+                    /* Exception occurred */
+                    return;
+                }
+
+                Fast486FpuPop(State); 
+                break;
+            }
+
+            /* Invalid */
+            default:
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+        }
     }
     else
     {

Modified: trunk/reactos/lib/fast486/fpu.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=65927&r1=65926&r2=65927&view=diff
==============================================================================
--- trunk/reactos/lib/fast486/fpu.h     [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.h     [iso-8859-1] Thu Jan  1 04:25:09 2015
@@ -68,6 +68,14 @@
     FPU_TAG_EMPTY = 3
 };
 
+enum
+{
+    FPU_ROUND_NEAREST = 0,
+    FPU_ROUND_DOWN = 1,
+    FPU_ROUND_UP = 2,
+    FPU_ROUND_TRUNCATE = 3
+};
+
 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC);
 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);


Reply via email to