[FAST486]
[reactos.git] / lib / fast486 / opgroups.c
index 5b9ec0a..be4d701 100644 (file)
@@ -43,7 +43,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
 {
     ULONG Result;
     ULONG SignFlag = 1 << (Bits - 1);
-    ULONG MaxValue = (1 << Bits) - 1;
+    ULONG MaxValue = (SignFlag - 1) | SignFlag;
 
     /* Make sure the values don't exceed the maximum for their size */
     FirstValue &= MaxValue;
@@ -61,7 +61,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
             State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
             State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
                               && ((FirstValue & SignFlag) != (Result & SignFlag));
-            State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
+            State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
 
             break;
         }
@@ -85,8 +85,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
                               || ((Result < FirstValue) && (Result < (SecondValue + Carry)));
             State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
                               && ((FirstValue & SignFlag) != (Result & SignFlag));
-            State->Flags.Af = (((FirstValue & 0x0F) + ((SecondValue + Carry) & 0x0F)) & 0x10)
-                              ? TRUE : FALSE;
+            State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
 
             break;
         }
@@ -99,10 +98,12 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
             Result = (FirstValue - SecondValue - Carry) & MaxValue;
 
             /* Update CF, OF and AF */
-            State->Flags.Cf = FirstValue < (SecondValue + Carry);
+            State->Flags.Cf = Carry
+                              ? (FirstValue <= SecondValue)
+                              : (FirstValue < SecondValue);
             State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
                               && ((FirstValue & SignFlag) != (Result & SignFlag));
-            State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
+            State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
 
             break;
         }
@@ -121,7 +122,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
             Result = (FirstValue - SecondValue) & MaxValue;
 
             /* Update CF, OF and AF */
-            State->Flags.Cf = FirstValue < SecondValue;
+            State->Flags.Cf = (FirstValue < SecondValue);
             State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
                               && ((FirstValue & SignFlag) != (Result & SignFlag));
             State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
@@ -144,8 +145,8 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
     }
 
     /* Update ZF, SF and PF */
-    State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-    State->Flags.Sf = (Result & SignFlag) ? TRUE : FALSE;
+    State->Flags.Zf = (Result == 0);
+    State->Flags.Sf = ((Result & SignFlag) != 0);
     State->Flags.Pf = Fast486CalculateParity(LOBYTE(Result));
 
     /* Return the result */
@@ -162,18 +163,16 @@ Fast486RotateOperation(PFAST486_STATE State,
                        UCHAR Count)
 {
     ULONG HighestBit = 1 << (Bits - 1);
+    ULONG MaxValue = HighestBit | (HighestBit - 1);
     ULONG Result;
 
-    if ((Operation != 2) && (Operation != 3))
-    {
-        /* Mask the count */
-        Count &= Bits - 1;
-    }
-    else
-    {
-        /* For RCL and RCR, the CF is included in the value */
-        Count %= Bits + 1;
-    }
+    /* Normalize the count */
+    Count &= 0x1F;
+
+    if ((Operation == 2) || (Operation == 3)) Count %= Bits + 1;
+
+    /* If the count is zero, do nothing */
+    if (Count == 0) return Value;
 
     /* Check which operation is this */
     switch (Operation)
@@ -181,12 +180,13 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* ROL */
         case 0:
         {
+            Count %= Bits;
             Result = (Value << Count) | (Value >> (Bits - Count));
 
             /* Update CF and OF */
             State->Flags.Cf = Result & 1;
-            if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
-                                              ^ State->Flags.Cf;
+            if (Count == 1) State->Flags.Of = State->Flags.Cf
+                                              ^ ((Result & HighestBit) != 0);
 
             break;
         }
@@ -194,13 +194,13 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* ROR */
         case 1:
         {
+            Count %= Bits;
             Result = (Value >> Count) | (Value << (Bits - Count));
 
             /* Update CF and OF */
-            State->Flags.Cf = (Result & HighestBit) ? TRUE : FALSE;
+            State->Flags.Cf = ((Result & HighestBit) != 0);
             if (Count == 1) State->Flags.Of = State->Flags.Cf
-                                              ^ ((Result & (HighestBit >> 1))
-                                              ? TRUE : FALSE);
+                                              ^ ((Result & (HighestBit >> 1)) != 0);
 
             break;
         }
@@ -208,14 +208,14 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* RCL */
         case 2:
         {
-            Result = (Value << Count)
-                     | (State->Flags.Cf << (Count - 1))
-                     | (Value >> (Bits - Count + 1));
+            Result = (Value << Count) | (State->Flags.Cf << (Count - 1));
+            
+            /* Complete the calculation, but make sure we don't shift by too much */
+            if ((Bits - Count) < 31) Result |= Value >> (Bits - Count + 1);
 
             /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
-            if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
-                                              ^ State->Flags.Cf;
+            State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Result & HighestBit) != 0);
 
             break;
         }
@@ -223,15 +223,16 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* RCR */
         case 3:
         {
-            Result = (Value >> Count)
-                     | (State->Flags.Cf << (Bits - Count))
-                     | (Value << (Bits - Count + 1));
+            /* Update OF */
+            if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Value & HighestBit) != 0);
 
-            /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
-            if (Count == 1) State->Flags.Of = State->Flags.Cf
-                                              ^ ((Result & (HighestBit >> 1))
-                                              ? TRUE : FALSE);
+            Result = (Value >> Count) | (State->Flags.Cf << (Bits - Count));
+
+            /* Complete the calculation, but make sure we don't shift by too much */
+            if ((Bits - Count) < 31) Result |= Value << (Bits - Count + 1);
+
+            /* Update CF */
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
 
             break;
         }
@@ -243,9 +244,9 @@ Fast486RotateOperation(PFAST486_STATE State,
             Result = Value << Count;
 
             /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
-            if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
-                                              ^ (State->Flags.Cf ? TRUE : FALSE);
+            State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf
+                                              ^ ((Result & HighestBit) != 0);
 
             break;
         }
@@ -256,8 +257,8 @@ Fast486RotateOperation(PFAST486_STATE State,
             Result = Value >> Count;
 
             /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Count - 1))) ? TRUE : FALSE;
-            if (Count == 1) State->Flags.Of = (Value & HighestBit) ? TRUE : FALSE;
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
+            if (Count == 1) State->Flags.Of = ((Value & HighestBit) != 0);
 
             break;
         }
@@ -271,17 +272,20 @@ Fast486RotateOperation(PFAST486_STATE State,
             if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count);
 
             /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Count - 1))) ? TRUE : FALSE;
+            State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
             if (Count == 1) State->Flags.Of = FALSE;
 
             break;
         }
     }
 
-    /* Update ZF, SF and PF */
-    State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-    State->Flags.Sf = (Result & HighestBit) ? TRUE : FALSE;
-    State->Flags.Pf = Fast486CalculateParity(Result);
+    if (Operation >= 4)
+    {
+        /* Update ZF, SF and PF */
+        State->Flags.Zf = ((Result & MaxValue) == 0);
+        State->Flags.Sf = ((Result & HighestBit) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
 
     /* Return the result */
     return Result;
@@ -291,7 +295,7 @@ Fast486RotateOperation(PFAST486_STATE State,
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
 {
-    UCHAR Immediate, Dummy, Value;
+    UCHAR Immediate, Value;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -311,7 +315,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -325,7 +329,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
     {
         return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
     }
-    
+
     return TRUE;
 }
 
@@ -333,7 +337,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -347,7 +351,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
 
     if (OperandSize)
     {
-        ULONG Immediate, Value, Dummy;
+        ULONG Immediate, Value;
 
         /* Fetch the immediate operand */
         if (!Fast486FetchDword(State, &Immediate))
@@ -357,7 +361,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
         }
 
         /* Read the operands */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -374,7 +378,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
     }
     else
     {
-        USHORT Immediate, Value, Dummy;
+        USHORT Immediate, Value;
 
         /* Fetch the immediate operand */
         if (!Fast486FetchWord(State, &Immediate))
@@ -384,7 +388,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
         }
 
         /* Read the operands */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -408,7 +412,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83)
     CHAR ImmByte;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -430,10 +434,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83)
     if (OperandSize)
     {
         ULONG Immediate = (ULONG)((LONG)ImmByte); // Sign extend
-        ULONG Value, Dummy;
+        ULONG Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -451,10 +455,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83)
     else
     {
         USHORT Immediate = (USHORT)((SHORT)ImmByte); // Sign extend
-        USHORT Value, Dummy;
+        USHORT Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -478,29 +482,32 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F)
     ULONG Value;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
     TOGGLE_ADSIZE(AddressSize);
 
-    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    /* Pop a value from the stack - this must be done first */
+    if (!Fast486StackPop(State, &Value))
     {
         /* Exception occurred */
         return FALSE;
     }
 
-    if (ModRegRm.Register != 0)
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
     {
-        /* Invalid */
-        Fast486Exception(State, FAST486_EXCEPTION_UD);
+        /* Exception occurred - restore SP */
+        if (OperandSize) State->GeneralRegs[FAST486_REG_ESP].Long -= sizeof(ULONG);
+        else State->GeneralRegs[FAST486_REG_ESP].LowWord -= sizeof(USHORT);
+
         return FALSE;
     }
 
-    /* Pop a value from the stack */
-    if (!Fast486StackPop(State, &Value))
+    if (ModRegRm.Register != 0)
     {
-        /* Exception occurred */
+        /* Invalid */
+        Fast486Exception(State, FAST486_EXCEPTION_UD);
         return FALSE;
     }
 
@@ -522,7 +529,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0)
 {
-    UCHAR Dummy, Value, Count;
+    UCHAR Value, Count;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -542,7 +549,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -567,7 +574,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1)
     UCHAR Count;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -588,10 +595,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1)
 
     if (OperandSize)
     {
-        ULONG Dummy, Value;
+        ULONG Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -609,10 +616,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1)
     }
     else
     {
-        USHORT Dummy, Value;
+        USHORT Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -723,7 +730,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0)
 {
-    UCHAR Dummy, Value;
+    UCHAR Value;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -736,7 +743,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -757,7 +764,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -771,10 +778,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
 
     if (OperandSize)
     {
-        ULONG Dummy, Value;
+        ULONG Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -788,10 +795,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
     }
     else
     {
-        USHORT Dummy, Value;
+        USHORT Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -807,7 +814,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2)
 {
-    UCHAR Dummy, Value;
+    UCHAR Value;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -820,7 +827,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -844,7 +851,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -858,10 +865,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
 
     if (OperandSize)
     {
-        ULONG Dummy, Value;
+        ULONG Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -879,10 +886,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
     }
     else
     {
-        USHORT Dummy, Value;
+        USHORT Value;
 
         /* Read the operands */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -902,7 +909,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
 {
-    UCHAR Dummy, Value = 0;
+    UCHAR Value = 0;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -915,7 +922,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -942,8 +949,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             /* Update the flags */
             State->Flags.Cf = FALSE;
             State->Flags.Of = FALSE;
-            State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-            State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
             State->Flags.Pf = Fast486CalculateParity(Result);
 
             break;
@@ -963,11 +970,11 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             UCHAR Result = -Value;
 
             /* Update the flags */
-            State->Flags.Cf = (Value != 0) ? TRUE : FALSE;
+            State->Flags.Cf = (Value != 0);
             State->Flags.Of = (Value & SIGN_FLAG_BYTE) && (Result & SIGN_FLAG_BYTE);
-            State->Flags.Af = ((Value & 0x0F) != 0) ? TRUE : FALSE;
-            State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-            State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
+            State->Flags.Af = ((Value & 0x0F) != 0);
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
             State->Flags.Pf = Fast486CalculateParity(Result);
 
             /* Write back the result */
@@ -980,7 +987,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             USHORT Result = (USHORT)Value * (USHORT)State->GeneralRegs[FAST486_REG_EAX].LowByte;
 
             /* Update the flags */
-            State->Flags.Cf = State->Flags.Of = HIBYTE(Result) ? TRUE : FALSE;
+            State->Flags.Cf = State->Flags.Of = (HIBYTE(Result) != 0);
 
             /* Write back the result */
             State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
@@ -994,8 +1001,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             SHORT Result = (SHORT)((CHAR)Value) * (SHORT)((CHAR)State->GeneralRegs[FAST486_REG_EAX].LowByte);
 
             /* Update the flags */
-            State->Flags.Cf = State->Flags.Of =
-            ((Result < -128) || (Result > 127)) ? TRUE : FALSE;
+            State->Flags.Cf = State->Flags.Of = ((Result < -128) || (Result > 127));
 
             /* Write back the result */
             State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Result;
@@ -1006,8 +1012,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
         /* DIV */
         case 6:
         {
-            UCHAR Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value;
-            UCHAR Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value;
+            UCHAR Quotient, Remainder;
+
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value;
+            Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value;
 
             /* Write back the results */
             State->GeneralRegs[FAST486_REG_EAX].LowByte = Quotient;
@@ -1019,8 +1034,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
         /* IDIV */
         case 7:
         {
-            CHAR Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value;
-            CHAR Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value;
+            CHAR Quotient, Remainder;
+
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
+            Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value;
+            Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value;
 
             /* Write back the results */
             State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient;
@@ -1035,10 +1059,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
 {
-    ULONG Dummy, Value = 0, SignFlag;
+    ULONG Value = 0, SignFlag;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1058,7 +1082,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
     if (OperandSize)
     {
         /* 32-bit */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -1067,7 +1091,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
     else
     {
         /* 16-bit */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, (PUSHORT)&Dummy, (PUSHORT)&Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -1107,8 +1131,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
             /* Update the flags */
             State->Flags.Cf = FALSE;
             State->Flags.Of = FALSE;
-            State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-            State->Flags.Sf = (Result & SignFlag) ? TRUE : FALSE;
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SignFlag) != 0);
             State->Flags.Pf = Fast486CalculateParity(Result);
 
             break;
@@ -1138,11 +1162,11 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
             if (!OperandSize) Result &= 0xFFFF;
 
             /* Update the flags */
-            State->Flags.Cf = (Value != 0) ? TRUE : FALSE;
+            State->Flags.Cf = (Value != 0);
             State->Flags.Of = (Value & SignFlag) && (Result & SignFlag);
-            State->Flags.Af = ((Value & 0x0F) != 0) ? TRUE : FALSE;
-            State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
-            State->Flags.Sf = (Result & SignFlag) ? TRUE : FALSE;
+            State->Flags.Af = ((Value & 0x0F) != 0);
+            State->Flags.Zf = (Result == 0);
+            State->Flags.Sf = ((Result & SignFlag) != 0);
             State->Flags.Pf = Fast486CalculateParity(Result);
 
             /* Write back the result */
@@ -1166,8 +1190,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
                 ULONGLONG Result = (ULONGLONG)Value * (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long;
 
                 /* Update the flags */
-                State->Flags.Cf = State->Flags.Of =
-                (Result & 0xFFFFFFFF00000000ULL) ? TRUE : FALSE;
+                State->Flags.Cf = State->Flags.Of = ((Result & 0xFFFFFFFF00000000ULL) != 0);
 
                 /* Write back the result */
                 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
@@ -1178,7 +1201,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
                 ULONG Result = (ULONG)Value * (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord;
 
                 /* Update the flags */
-                State->Flags.Cf = State->Flags.Of = HIWORD(Result) ? TRUE : FALSE;
+                State->Flags.Cf = State->Flags.Of = (HIWORD(Result) != 0);
 
                 /* Write back the result */
                 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
@@ -1196,8 +1219,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
                 LONGLONG Result = (LONGLONG)((LONG)Value) * (LONGLONG)((LONG)State->GeneralRegs[FAST486_REG_EAX].Long);
 
                 /* Update the flags */
-                State->Flags.Cf = State->Flags.Of =
-                ((Result < -2147483648LL) || (Result > 2147483647LL)) ? TRUE : FALSE;
+                State->Flags.Cf = State->Flags.Of = ((Result < -2147483648LL) || (Result > 2147483647LL));
 
                 /* Write back the result */
                 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
@@ -1208,8 +1230,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
                 LONG Result = (LONG)((SHORT)Value) * (LONG)((SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord);
 
                 /* Update the flags */
-                State->Flags.Cf = State->Flags.Of =
-                ((Result < -32768) || (Result > 32767)) ? TRUE : FALSE;
+                State->Flags.Cf = State->Flags.Of = ((Result < -32768) || (Result > 32767));
 
                 /* Write back the result */
                 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
@@ -1222,6 +1243,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
         /* DIV */
         case 6:
         {
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
             if (OperandSize)
             {
                 ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
@@ -1251,6 +1279,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
         /* IDIV */
         case 7:
         {
+            if (Value == 0)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return FALSE;
+            }
+
             if (OperandSize)
             {
                 LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
@@ -1283,7 +1318,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
 {
-    UCHAR Dummy, Value;
+    UCHAR Value;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
@@ -1303,7 +1338,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
     }
 
     /* Read the operands */
-    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+    if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
     {
         /* Exception occurred */
         return FALSE;
@@ -1313,20 +1348,20 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
     {
         /* Increment and update OF and AF */
         Value++;
-        State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
+        State->Flags.Of = (Value == SIGN_FLAG_BYTE);
         State->Flags.Af = ((Value & 0x0F) == 0);
     }
     else
     {
         /* Decrement and update OF and AF */
-        State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
+        State->Flags.Of = (Value == SIGN_FLAG_BYTE);
         Value--;
         State->Flags.Af = ((Value & 0x0F) == 0x0F);
     }
 
     /* Update flags */
-    State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
-    State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Value);
 
     /* Write back the result */
@@ -1340,7 +1375,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1362,9 +1397,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     /* Read the operands */
     if (OperandSize)
     {
-        ULONG Dummy, Value;
+        ULONG Value;
 
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -1374,13 +1409,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         {
             /* Increment and update OF and AF */
             Value++;
-            State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
+            State->Flags.Of = (Value == SIGN_FLAG_LONG);
             State->Flags.Af = ((Value & 0x0F) == 0);
         }
         else if (ModRegRm.Register == 1)
         {
             /* Decrement and update OF and AF */
-            State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
+            State->Flags.Of = (Value == SIGN_FLAG_LONG);
             Value--;
             State->Flags.Af = ((Value & 0x0F) == 0x0F);
         }
@@ -1399,7 +1434,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         else if (ModRegRm.Register == 3)
         {
             USHORT Selector;
-            INT Segment = FAST486_REG_DS;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
 
             /* Check for the segment override */
             if (State->PrefixFlags & FAST486_PREFIX_SEG)
@@ -1452,7 +1487,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         else if (ModRegRm.Register == 5)
         {
             USHORT Selector;
-            INT Segment = FAST486_REG_DS;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
 
             /* Check for the segment override */
             if (State->PrefixFlags & FAST486_PREFIX_SEG)
@@ -1492,8 +1527,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         if (ModRegRm.Register <= 1)
         {
             /* Update flags */
-            State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
-            State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
+            State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
+            State->Flags.Zf = (Value == 0);
             State->Flags.Pf = Fast486CalculateParity(Value);
 
             /* Write back the result */
@@ -1505,9 +1540,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     }
     else
     {
-        USHORT Dummy, Value;
+        USHORT Value;
 
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -1517,13 +1552,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         {
             /* Increment and update OF */
             Value++;
-            State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
+            State->Flags.Of = (Value == SIGN_FLAG_WORD);
             State->Flags.Af = ((Value & 0x0F) == 0);
         }
         else if (ModRegRm.Register == 1)
         {
             /* Decrement and update OF */
-            State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
+            State->Flags.Of = (Value == SIGN_FLAG_WORD);
             Value--;
             State->Flags.Af = ((Value & 0x0F) == 0x0F);
         }
@@ -1538,11 +1573,14 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
 
             /* Set the IP to the address */
             State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
         }
         else if (ModRegRm.Register == 3)
         {
             USHORT Selector;
-            INT Segment = FAST486_REG_DS;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
 
             /* Check for the segment override */
             if (State->PrefixFlags & FAST486_PREFIX_SEG)
@@ -1587,6 +1625,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
             /* Set the IP to the address */
             State->InstPtr.LowWord = Value;
 
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
         }
         else if (ModRegRm.Register == 4)
         {
@@ -1596,7 +1636,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         else if (ModRegRm.Register == 5)
         {
             USHORT Selector;
-            INT Segment = FAST486_REG_DS;
+            FAST486_SEG_REGS Segment = FAST486_REG_DS;
 
             /* Check for the segment override */
             if (State->PrefixFlags & FAST486_PREFIX_SEG)
@@ -1626,6 +1666,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
 
             /* Set the IP to the address */
             State->InstPtr.LowWord = Value;
+
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
         }
         else if (ModRegRm.Register == 6)
         {
@@ -1642,8 +1685,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
         if (ModRegRm.Register <= 1)
         {
             /* Update flags */
-            State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
-            State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
+            State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
+            State->Flags.Zf = (Value == 0);
             State->Flags.Pf = Fast486CalculateParity(Value);
 
             /* Write back the result */
@@ -1657,6 +1700,312 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     return TRUE;
 }
 
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
+{
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check which operation this is */
+    switch (ModRegRm.Register)
+    {
+        /* SLDT */
+        case 0:
+        {
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 State->Ldtr.Selector);
+        }
+
+        /* STR */
+        case 1:
+        {
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 State->TaskReg.Selector);
+        }
+
+        /* LLDT */
+        case 2:
+        {
+            USHORT Selector;
+            FAST486_SYSTEM_DESCRIPTOR GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Make sure the GDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the GDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Gdtr.Address
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                return FALSE;
+            }
+
+            if (GdtEntry.Signature != FAST486_LDT_SIGNATURE)
+            {
+                /* This is not a LDT descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Update the LDTR */
+            State->Ldtr.Selector = Selector;
+            State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
+            State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+            if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+            return TRUE;
+        }
+
+        /* LTR */
+        case 3:
+        {
+            USHORT Selector;
+            FAST486_SYSTEM_DESCRIPTOR GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Make sure the GDT contains the entry */
+            if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Read the GDT */
+            if (!Fast486ReadLinearMemory(State,
+                                         State->Gdtr.Address
+                                         + GET_SEGMENT_INDEX(Selector),
+                                         &GdtEntry,
+                                         sizeof(GdtEntry)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+                return FALSE;
+            }
+
+            if (GdtEntry.Signature != FAST486_TSS_SIGNATURE)
+            {
+                /* This is not a TSS descriptor */
+                Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+                return FALSE;
+            }
+
+            /* Update the TR */
+            State->TaskReg.Selector = Selector;
+            State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
+            State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+            if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12;
+            State->TaskReg.Busy = TRUE;
+
+            return TRUE;
+        }
+
+        /* VERR/VERW */
+        case 4:
+        case 5:
+        {
+            USHORT Selector;
+            FAST486_GDT_ENTRY GdtEntry;
+
+            /* Not recognized in real mode or virtual 8086 mode */
+            if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                || State->Flags.Vm)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+            }
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!Fast486ReadModrmWordOperands(State,
+                                              &ModRegRm,
+                                              NULL,
+                                              &Selector))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            if (!(Selector & SEGMENT_TABLE_INDICATOR))
+            {
+                /* Make sure the GDT contains the entry */
+                if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+                {
+                    /* Clear ZF */
+                    State->Flags.Zf = FALSE;
+                    return TRUE;
+                }
+
+                /* Read the GDT */
+                if (!Fast486ReadLinearMemory(State,
+                                             State->Gdtr.Address
+                                             + GET_SEGMENT_INDEX(Selector),
+                                             &GdtEntry,
+                                             sizeof(GdtEntry)))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+            else
+            {
+                /* Make sure the LDT contains the entry */
+                if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
+                {
+                    /* Clear ZF */
+                    State->Flags.Zf = FALSE;
+                    return TRUE;
+                }
+
+                /* Read the LDT */
+                if (!Fast486ReadLinearMemory(State,
+                                             State->Ldtr.Base
+                                             + GET_SEGMENT_INDEX(Selector),
+                                             &GdtEntry,
+                                             sizeof(GdtEntry)))
+                {
+                    /* Exception occurred */
+                    return FALSE;
+                }
+            }
+
+            /* Set ZF if it is valid and accessible */
+            State->Flags.Zf = GdtEntry.Present // must be present
+                               && GdtEntry.SystemType // must be a segment
+                               && (((ModRegRm.Register == 4)
+                               /* code segments are only readable if the RW bit is set */
+                               && (!GdtEntry.Executable || GdtEntry.ReadWrite))
+                               || ((ModRegRm.Register == 5)
+                               /* code segments are never writable, data segments are writable when RW is set */
+                               && (!GdtEntry.Executable && GdtEntry.ReadWrite)))
+                               /*
+                                * for segments other than conforming code segments,
+                                * both RPL and CPL must be less than or equal to DPL
+                                */
+                               && ((!GdtEntry.Executable || !GdtEntry.DirConf)
+                               && ((GET_SEGMENT_RPL(Selector) <= GdtEntry.Dpl)
+                               && (Fast486GetCurrentPrivLevel(State) <= GdtEntry.Dpl)))
+                               /* for conforming code segments, DPL must be less than or equal to CPL */
+                               && ((GdtEntry.Executable && GdtEntry.DirConf)
+                               && (GdtEntry.Dpl <= Fast486GetCurrentPrivLevel(State)));
+
+
+            return TRUE;
+        }
+
+        /* Invalid */
+        default:
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+            return FALSE;
+        }
+    }
+}
+
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
 {
     UCHAR TableReg[6];
@@ -1667,6 +2016,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
     NO_LOCK_PREFIX();
     TOGGLE_ADSIZE(AddressSize);
 
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
     /* Check for the segment override */
     if (State->PrefixFlags & FAST486_PREFIX_SEG)
     {
@@ -1674,12 +2029,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
         Segment = State->SegmentOverride;
     }
 
-    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
-    {
-        /* Exception occurred */
-        return FALSE;
-    }
-
     /* Check which operation this is */
     switch (ModRegRm.Register)
     {
@@ -1802,7 +2151,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
         /* SMSW */
         case 4:
         {
-            /* Store the lower 16 bits of CR0 */
+            /* Store the lower 16 bits (Machine Status Word) of CR0 */
             return Fast486WriteModrmWordOperands(State,
                                                  &ModRegRm,
                                                  FALSE,
@@ -1812,7 +2161,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
         /* LMSW */
         case 6:
         {
-            USHORT MasterStatusWord, Dummy;
+            USHORT MachineStatusWord;
 
             /* This is a privileged instruction */
             if (Fast486GetCurrentPrivLevel(State) != 0)
@@ -1821,8 +2170,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
                 return FALSE;
             }
 
-            /* Read the new master status word */
-            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &MasterStatusWord))
+            /* Read the new Machine Status Word */
+            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &MachineStatusWord))
             {
                 /* Exception occurred */
                 return FALSE;
@@ -1830,7 +2179,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
 
             /* This instruction cannot be used to return to real mode */
             if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
-                && !(MasterStatusWord & FAST486_CR0_PE))
+                && !(MachineStatusWord & FAST486_CR0_PE))
             {
                 Fast486Exception(State, FAST486_EXCEPTION_GP);
                 return FALSE;
@@ -1838,7 +2187,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
 
             /* Set the lowest 4 bits */
             State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF0;
-            State->ControlRegisters[FAST486_REG_CR0] |= MasterStatusWord & 0x0F;
+            State->ControlRegisters[FAST486_REG_CR0] |= MachineStatusWord & 0x0F;
 
             return TRUE;
         }
@@ -1883,7 +2232,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
     BOOLEAN OperandSize, AddressSize;
     UINT DataSize;
     UCHAR BitNumber;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1923,14 +2272,14 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
     }
 
     /* Normalize the bit number */
-    BitNumber &= (1 << DataSize) - 1;
+    BitNumber %= DataSize;
 
     if (OperandSize)
     {
-        ULONG Dummy, Value;
+        ULONG Value;
 
         /* Read the value */
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -1967,10 +2316,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
     }
     else
     {
-        USHORT Dummy, Value;
+        USHORT Value;
 
         /* Read the value */
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
         {
             /* Exception occurred */
             return FALSE;
@@ -2008,9 +2357,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
 
     /* Return success */
     return TRUE;
-
-    return TRUE;
 }
 
 /* EOF */
-