[FAST486]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 2 Jan 2015 21:19:31 +0000 (21:19 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 2 Jan 2015 21:19:31 +0000 (21:19 +0000)
Implement the FWAIT instruction.
Fix FPU exception handling. Implement exception masking.
Fix several other bugs and wrong definitions.

svn path=/trunk/; revision=65942

reactos/lib/fast486/fpu.c
reactos/lib/fast486/fpu.h
reactos/lib/fast486/opcodes.c

index 5d236e2..598f9c1 100644 (file)
@@ -107,8 +107,16 @@ Fast486FpuToInteger(PFAST486_STATE State,
     if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value)
         || (UnbiasedExp < 0) || (UnbiasedExp > 63))
     {
-        State->FpuStatus.Ie = TRUE;
-        return FALSE;
+        if (State->FpuControl.Im)
+        {
+            *Result = 0LL;
+            return TRUE;
+        }
+        else
+        {
+            State->FpuStatus.Ie = TRUE;
+            return FALSE;
+        }
     }
 
     Bits = 63 - UnbiasedExp;
@@ -223,22 +231,42 @@ Fast486FpuToDoubleReal(PFAST486_STATE State,
 
     if (FPU_IS_NAN(Value))
     {
-        *Result |= 0x3FF0000000000000ULL;
+        *Result |= 0x7FFULL << 52;
         goto SetSign;
     }
 
     /* Check for underflow */
     if (!FPU_IS_NORMALIZED(Value) || (UnbiasedExp < -1023))
     {
-        State->FpuStatus.Ue = TRUE;
-        return FALSE;
+        if (State->FpuControl.Um)
+        {
+            /* The result is zero due to underflow */
+            *Result = 0ULL;
+            return TRUE;
+        }
+        else
+        {
+            /* Raise the underflow exception */
+            State->FpuStatus.Ue = TRUE;
+            return FALSE;
+        }
     }
 
     /* Check for overflow */
     if (UnbiasedExp > 1023)
     {
-        State->FpuStatus.Oe = TRUE;
-        return FALSE;
+        if (State->FpuControl.Om)
+        {
+            /* The result is infinity due to overflow */
+            *Result = FPU_REAL8_INFINITY;
+            goto SetSign;
+        }
+        else
+        {
+            /* Raise the overflow exception */
+            State->FpuStatus.Oe = TRUE;
+            return FALSE;
+        }
     }
 
     /* Calculate the remainder */
@@ -291,7 +319,7 @@ SetSign:
     return TRUE;
 }
 
-static inline BOOLEAN FASTCALL
+static inline VOID FASTCALL
 Fast486FpuFromPackedBcd(PFAST486_STATE State,
                         PUCHAR Value,
                         PFAST486_FPU_DATA_REG Result)
@@ -301,13 +329,6 @@ Fast486FpuFromPackedBcd(PFAST486_STATE State,
 
     for (i = 8; i >= 0; i--)
     {
-        if (((Value[i] & 0x0F) > 9) || ((Value[i] >> 4) > 9))
-        {
-            /* Invalid BCD */
-            State->FpuStatus.Ie = TRUE;
-            return FALSE;
-        }
-
         IntVal *= 100LL;
         IntVal += (Value[i] >> 4) * 10 + (Value[i] & 0x0F);
     }
@@ -317,7 +338,6 @@ Fast486FpuFromPackedBcd(PFAST486_STATE State,
 
     /* Now convert the integer to FP80 */
     Fast486FpuFromInteger(State, IntVal, Result);
-    return TRUE;
 }
 
 static inline BOOLEAN FASTCALL
@@ -356,10 +376,12 @@ Fast486FpuAdd(PFAST486_STATE State,
     FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand;
     FAST486_FPU_DATA_REG TempResult;
 
-    if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+    if (!State->FpuControl.Dm
+        && (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
     {
-        /* Denormalized */
+        /* Raise the denormalized exception */
         State->FpuStatus.De = TRUE;
+        return;
     }
 
     /* Find the largest exponent */
@@ -405,12 +427,18 @@ Fast486FpuAdd(PFAST486_STATE State,
     {
         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;
+            if (State->FpuControl.Om)
+            {
+                /* Total overflow, return infinity */
+                TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT;
+                TempResult.Exponent = FPU_MAX_EXPONENT + 1;
+            }
+            else
+            {
+                /* Raise the overflow exception */
+                State->FpuStatus.Oe = TRUE;
+                return;
+            }
         }
         else
         {
@@ -438,7 +466,7 @@ Fast486FpuSubtract(PFAST486_STATE State,
     NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign;
 
     /* And perform an addition instead */
-    Fast486FpuAdd(State, Result, FirstOperand, &NegativeSecondOperand);
+    Fast486FpuAdd(State, FirstOperand, &NegativeSecondOperand, Result);
 }
 
 static inline VOID FASTCALL
@@ -502,10 +530,12 @@ Fast486FpuMultiply(PFAST486_STATE State,
 {
     FAST486_FPU_DATA_REG TempResult;
 
-    if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+    if (!State->FpuControl.Dm
+        && (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand)))
     {
-        /* Denormalized */
+        /* Raise the denormalized exception */
         State->FpuStatus.De = TRUE;
+        return;
     }
 
     UnsignedMult128(FirstOperand->Mantissa,
@@ -530,9 +560,19 @@ Fast486FpuDivide(PFAST486_STATE State,
 
     if (FPU_IS_ZERO(SecondOperand))
     {
-        /* Division by zero */
-        State->FpuStatus.Ze = TRUE;
-        return;
+        if (State->FpuControl.Zm)
+        {
+            /* Return infinity */
+            Result->Sign = FirstOperand->Sign;
+            Result->Exponent = FPU_MAX_EXPONENT + 1;
+            Result->Mantissa = FPU_MANTISSA_HIGH_BIT;
+        }
+        else
+        {
+            /* Raise the division by zero exception */
+            State->FpuStatus.Ze = TRUE;
+            return;
+        }
     }
 
     TempResult.Exponent = FirstOperand->Exponent - SecondOperand->Exponent;
@@ -631,10 +671,26 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
 
 #ifndef FAST486_NO_FPU
 
+    /* The destination operand is ST0 */
+    DestOperand = &FPU_ST(0);
+
     if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
     {
-        /* Invalid operation */
-        State->FpuStatus.Ie = TRUE;
+        if (State->FpuControl.Im)
+        {
+            /* Return the indefinite NaN */
+            DestOperand->Sign = TRUE;
+            DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+            DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+            FPU_SET_TAG(0, FPU_TAG_SPECIAL);
+        }
+        else
+        {
+            /* Raise the invalid operation exception */
+            State->FpuStatus.Ie = TRUE;
+        }
+
         return;
     }
 
@@ -651,24 +707,31 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
 
         Fast486FpuFromSingleReal(State, Value, &MemoryData);
         SourceOperand = &MemoryData;
-
-        /* The destination operand is ST0 */
-        DestOperand = &FPU_ST(0);
     }
     else
     {
         if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
         {
-            /* Invalid operation */
-            State->FpuStatus.Ie = TRUE;
+            if (State->FpuControl.Im)
+            {
+                /* Return the indefinite NaN */
+                DestOperand->Sign = TRUE;
+                DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+                DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+                FPU_SET_TAG(0, FPU_TAG_SPECIAL);
+            }
+            else
+            {
+                /* Raise the invalid operation exception */
+                State->FpuStatus.Ie = TRUE;
+            }
+
             return;
         }
 
         /* Load the source operand from an FPU register */
         SourceOperand = &FPU_ST(ModRegRm.SecondRegister);
-
-        /* The destination operand is ST0 */
-        DestOperand = &FPU_ST(0);
     }
 
     /* Perform the requested operation */
@@ -695,18 +758,34 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
 
 #ifndef FAST486_NO_FPU
 
-    if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
-    {
-        /* Invalid operation */
-        State->FpuStatus.Ie = TRUE;
-        return;
-    }
-
     if (ModRegRm.Memory)
     {
-        /* Load the source operand from memory */
         ULONGLONG Value;
 
+        /* The destination operand is ST0 */
+        DestOperand = &FPU_ST(0);
+
+        if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+        {
+            if (State->FpuControl.Im)
+            {
+                /* Return the indefinite NaN */
+                DestOperand->Sign = TRUE;
+                DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+                DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+                FPU_SET_TAG(0, FPU_TAG_SPECIAL);
+            }
+            else
+            {
+                /* Raise the invalid operation exception */
+                State->FpuStatus.Ie = TRUE;
+            }
+
+            return;
+        }
+
+        /* Load the source operand from memory */
         if (!Fast486ReadMemory(State,
                                (State->PrefixFlags & FAST486_PREFIX_SEG)
                                ? State->SegmentOverride : FAST486_REG_DS,
@@ -721,24 +800,35 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
 
         Fast486FpuFromDoubleReal(State, Value, &MemoryData);
         SourceOperand = &MemoryData;
-
-        /* The destination operand is ST0 */
-        DestOperand = &FPU_ST(0);
     }
     else
     {
-        if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
-        {
-            /* Invalid operation */
-            State->FpuStatus.Ie = TRUE;
-            return;
-        }
-
         /* The source operand is ST0 */
         SourceOperand = &FPU_ST(0);
 
         /* Load the destination operand from an FPU register */
         DestOperand = &FPU_ST(ModRegRm.SecondRegister);
+
+        if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+            || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
+        {
+            if (State->FpuControl.Im)
+            {
+                /* Return the indefinite NaN */
+                DestOperand->Sign = TRUE;
+                DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+                DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+                FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_SPECIAL);
+            }
+            else
+            {
+                /* Raise the invalid operation exception */
+                State->FpuStatus.Ie = TRUE;
+            }
+
+            return;
+        }
     }
 
     /* Perform the requested operation */
@@ -800,8 +890,8 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
 
         if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY))
         {
-            /* FPU Exception */
-            State->FpuStatus.Ie = TRUE;
+            /* Raise the invalid operation exception, if unmasked */
+            if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
             return;
         }
 
@@ -822,22 +912,35 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
         return;
     }
 
-    Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
-    SourceOperand = &MemoryData;
-
     /* The destination operand is always ST0 */
     DestOperand = &FPU_ST(0);
 
     if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
     {
-        /* Invalid operation */
-        State->FpuStatus.Ie = TRUE;
+        if (State->FpuControl.Im)
+        {
+            /* Return the indefinite NaN */
+            DestOperand->Sign = TRUE;
+            DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+            DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+            FPU_SET_TAG(0, FPU_TAG_SPECIAL);
+        }
+        else
+        {
+            /* Raise the invalid operation exception */
+            State->FpuStatus.Ie = TRUE;
+        }
+
         return;
     }
 
+    Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
+    SourceOperand = &MemoryData;
+
     /* Perform the requested operation */
     Fast486FpuArithmeticOperation(State, ModRegRm.Register, SourceOperand, DestOperand); 
-    
+
 #endif
 }
 
@@ -884,16 +987,18 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
             /* FISTP */
             case 3:
             {
-                LONGLONG Temp;
+                LONGLONG Temp = 0;
 
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
                 {
-                    /* Fail */
-                    State->FpuStatus.Ie = TRUE;
-                    return;
+                    if (!State->FpuControl.Im)
+                    {
+                        /* Raise the invalid operation exception */
+                        State->FpuStatus.Ie = TRUE;
+                        return;
+                    }
                 }
-
-                if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
+                else if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
                 {
                     /* Exception occurred */
                     return;
@@ -952,15 +1057,26 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
             {
                 UCHAR Buffer[10];
 
-                if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+                if (FPU_GET_TAG(0) != FPU_TAG_EMPTY)
                 {
-                    /* 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);
+                }
+                else
+                {
+                    if (State->FpuControl.Im)
+                    {
+                        *((PULONGLONG)Buffer) = FPU_INDEFINITE_MANTISSA;
+                        *((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = 0x8000 | (FPU_MAX_EXPONENT + 1);
+                    }
+                    else
+                    {
+                        /* Raise the invalid operation exception */
+                        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)
@@ -981,6 +1097,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
             default:
             {
                 Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return;
             }
         }
     }
@@ -1030,6 +1147,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
             default:
             {
                 Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return;
             }
         }
     }
@@ -1086,16 +1204,18 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
             /* FSTP */
             case 3:
             {
-                ULONGLONG Value;
+                ULONGLONG Value = FPU_REAL8_INDEFINITE;
 
                 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
                 {
-                    /* Fail */
-                    State->FpuStatus.Ie = TRUE;
-                    return;
+                    if (!State->FpuControl.Im)
+                    {
+                        /* Raise the invalid operation exception */
+                        State->FpuStatus.Ie = TRUE;
+                        return;
+                    }
                 }
-
-                if (!Fast486FpuToDoubleReal(State, &FPU_ST(0), &Value))
+                else if (!Fast486FpuToDoubleReal(State, &FPU_ST(0), &Value))
                 {
                     /* Exception occurred */
                     return;
@@ -1167,7 +1287,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
                     || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
                 {
-                    State->FpuStatus.Ie = TRUE;
+                    if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
                     break;
                 }
 
@@ -1202,7 +1322,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
                     || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
                 {
-                    State->FpuStatus.Ie = TRUE;
+                    if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
                     return;
                 }
 
@@ -1228,7 +1348,6 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
     PFAST486_FPU_DATA_REG SourceOperand, DestOperand;
-    BOOLEAN PopStack = FALSE;
 
     /* Get the operands */
     if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
@@ -1241,18 +1360,34 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
 
 #ifndef FAST486_NO_FPU
 
-    if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
-    {
-        /* Invalid operation */
-        State->FpuStatus.Ie = TRUE;
-        return;
-    }
-
     if (ModRegRm.Memory)
     {
         SHORT Value;
         FAST486_FPU_DATA_REG MemoryData;
 
+        /* The destination operand is ST0 */
+        DestOperand = &FPU_ST(0);
+
+        if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+        {
+            if (State->FpuControl.Im)
+            {
+                /* Return the indefinite NaN */
+                DestOperand->Sign = TRUE;
+                DestOperand->Exponent = FPU_MAX_EXPONENT + 1;
+                DestOperand->Mantissa = FPU_INDEFINITE_MANTISSA;
+
+                FPU_SET_TAG(0, FPU_TAG_SPECIAL);
+            }
+            else
+            {
+                /* Raise the invalid operation exception */
+                State->FpuStatus.Ie = TRUE;
+            }
+
+            return;
+        }
+
         /* Load the source operand from memory */
         if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
         {
@@ -1262,9 +1397,6 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
 
         Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
         SourceOperand = &MemoryData;
-
-        /* The destination operand is ST0 */
-        DestOperand = &FPU_ST(0);
     }
     else
     {
@@ -1282,19 +1414,19 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
         /* Load the destination operand from a register */
         DestOperand = &FPU_ST(ModRegRm.SecondRegister);
 
-        if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
+        if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+            || (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY))
         {
-            /* Invalid operation */
-            State->FpuStatus.Ie = TRUE;
+            /* Raise the invalid operation exception, if unmasked */
+            if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
+
             return;
         }
-
-        PopStack = TRUE;
     }
 
     /* Perform the requested operation */
     Fast486FpuArithmeticOperation(State, ModRegRm.Register, SourceOperand, DestOperand);  
-    if (PopStack) Fast486FpuPop(State);
+    if (!ModRegRm.Memory) Fast486FpuPop(State);
 
 #endif
 }
@@ -1342,16 +1474,18 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
             /* FISTP */
             case 3:
             {
-                LONGLONG Temp;
+                LONGLONG Temp = 0LL;
 
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
                 {
-                    /* Fail */
-                    State->FpuStatus.Ie = TRUE;
-                    return;
+                    if (!State->FpuControl.Im)
+                    {
+                        /* Raise the invalid operation exception */
+                        State->FpuStatus.Ie = TRUE;
+                        return;
+                    }
                 }
-
-                if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
+                else if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
                 {
                     /* Exception occurred */
                     return;
@@ -1397,13 +1531,9 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
                     return;
                 }
 
-                if (!Fast486FpuFromPackedBcd(State, Buffer, &Value))
-                {
-                    /* Exception occurred */
-                    return;
-                }
+                Fast486FpuFromPackedBcd(State, Buffer, &Value);
+                Fast486FpuPush(State, &Value);
 
-                Fast486FpuPush(State, &Value); 
                 break;
             }
 
@@ -1434,16 +1564,18 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
             /* FBSTP */
             case 6:
             {
-                UCHAR Buffer[10];
+                UCHAR Buffer[10] = {0};
 
                 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
                 {
-                    /* Fail */
-                    State->FpuStatus.Ie = TRUE;
-                    return;
+                    if (!State->FpuControl.Im)
+                    {
+                        /* Raise the invalid operation exception */
+                        State->FpuStatus.Ie = TRUE;
+                        return;
+                    }
                 }
-
-                if (!Fast486FpuToPackedBcd(State, &FPU_ST(0), Buffer))
+                else if (!Fast486FpuToPackedBcd(State, &FPU_ST(0), Buffer))
                 {
                     /* Exception occurred */
                     return;
@@ -1467,16 +1599,18 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
             /* FISTP (64-bit int) */
             case 7:
             {
-                LONGLONG Temp;
+                LONGLONG Temp = 0LL;
 
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
                 {
-                    /* Fail */
-                    State->FpuStatus.Ie = TRUE;
-                    return;
+                    if (!State->FpuControl.Im)
+                    {
+                        /* Raise the invalid operation exception */
+                        State->FpuStatus.Ie = TRUE;
+                        return;
+                    }
                 }
-
-                if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
+                else if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp))
                 {
                     /* Exception occurred */
                     return;
@@ -1527,7 +1661,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
                 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY)
                     || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
                 {
-                    State->FpuStatus.Ie = TRUE;
+                    if (!State->FpuControl.Im) State->FpuStatus.Ie = TRUE;
                     break;
                 }
 
index a1afe60..83f4a82 100644 (file)
                             }
 #define FPU_UPDATE_TAG(i)   FPU_SET_TAG((i), Fast486GetValueTag(&FPU_ST(i)))
 
-#define FPU_REAL4_BIAS 0x7F
-#define FPU_REAL8_BIAS 0x3FF
-#define FPU_REAL10_BIAS 0x3FFF
-#define FPU_MAX_EXPONENT 0x7FFE
-#define FPU_MANTISSA_HIGH_BIT 0x8000000000000000ULL
+#define FPU_REAL4_BIAS          0x7F
+#define FPU_REAL8_BIAS          0x3FF
+#define FPU_REAL10_BIAS         0x3FFF
+#define FPU_MAX_EXPONENT        0x7FFE
+#define FPU_MANTISSA_HIGH_BIT   0x8000000000000000ULL
+#define FPU_INDEFINITE_MANTISSA 0xC000000000000000ULL
+#define FPU_REAL4_INFINITY      0x7F800000
+#define FPU_REAL4_INDEFINITE    0xFFC00000
+#define FPU_REAL8_INFINITY      0x7FF0000000000000ULL
+#define FPU_REAL8_INDEFINITE    0xFFF8000000000000ULL
 
-#define FPU_IS_NORMALIZED(x) (!FPU_IS_ZERO(x) && (((x)->Mantissa & FPU_MANTISSA_HIGH_BIT) != 0ULL))
-#define FPU_IS_ZERO(x) ((x)->Mantissa == 0ULL)
-#define FPU_IS_NAN(x) ((x)->Exponent == (FPU_MAX_EXPONENT + 1))
-#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_NORMALIZED(x)    (!FPU_IS_ZERO(x) && (((x)->Mantissa & FPU_MANTISSA_HIGH_BIT) != 0ULL))
+#define FPU_IS_ZERO(x)          ((x)->Mantissa == 0ULL)
+#define FPU_IS_NAN(x)           ((x)->Exponent == (FPU_MAX_EXPONENT + 1))
+#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)
 
 enum
 {
index cd24015..662a5fb 100644 (file)
@@ -4116,8 +4116,20 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeCallAbs)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeWait)
 {
-    // TODO: NOT IMPLEMENTED
-    UNIMPLEMENTED;
+#ifndef FAST486_NO_FPU
+
+    if ((!State->FpuControl.Pm && State->FpuStatus.Pe)
+        || (!State->FpuControl.Um && State->FpuStatus.Ue)
+        || (!State->FpuControl.Om && State->FpuStatus.Oe)
+        || (!State->FpuControl.Zm && State->FpuStatus.Ze)
+        || (!State->FpuControl.Dm && State->FpuStatus.De)
+        || (!State->FpuControl.Im && State->FpuStatus.Ie))
+    {
+        /* Call the #MF handler */
+        Fast486Exception(State, FAST486_EXCEPTION_MF);
+    }
+
+#endif
 }
 
 FAST486_OPCODE_HANDLER(Fast486OpcodePushFlags)