[FAST486]
[reactos.git] / lib / fast486 / opgroups.c
index 0c5690a..a721c89 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 & 0x0F) + ((SecondValue + Carry) & 0x0F)) & 0x10) != 0);
 
             break;
         }
@@ -121,7 +120,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 +143,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 */
@@ -164,15 +163,14 @@ Fast486RotateOperation(PFAST486_STATE State,
     ULONG HighestBit = 1 << (Bits - 1);
     ULONG Result;
 
-    if ((Operation != 2) && (Operation != 3))
-    {
-        /* Mask the count */
-        Count &= Bits - 1;
-    }
-    else
+    /* Normalize the count */
+    Count &= 0x1F;
+
+    /* If the count is zero, do nothing */
+    if (Count == 0)
     {
-        /* For RCL and RCR, the CF is included in the value */
-        Count %= Bits + 1;
+        Result = Value;
+        goto SetFlags;
     }
 
     /* Check which operation is this */
@@ -185,8 +183,8 @@ Fast486RotateOperation(PFAST486_STATE State,
 
             /* 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;
         }
@@ -197,10 +195,9 @@ Fast486RotateOperation(PFAST486_STATE State,
             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;
         }
@@ -213,9 +210,9 @@ Fast486RotateOperation(PFAST486_STATE State,
                      | (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;
         }
@@ -228,10 +225,9 @@ Fast486RotateOperation(PFAST486_STATE State,
                      | (Value << (Bits - Count + 1));
 
             /* Update CF and OF */
-            State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
+            State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
             if (Count == 1) State->Flags.Of = State->Flags.Cf
-                                              ^ ((Result & (HighestBit >> 1))
-                                              ? TRUE : FALSE);
+                                              ^ ((Result & (HighestBit >> 1)) != 0);
 
             break;
         }
@@ -243,9 +239,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 +252,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 +267,21 @@ 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);
+SetFlags:
+    if (Operation >= 4)
+    {
+        /* Update ZF, SF and PF */
+        State->Flags.Zf = (Result == 0);
+        State->Flags.Sf = ((Result & HighestBit) != 0);
+        State->Flags.Pf = Fast486CalculateParity(Result);
+    }
 
     /* Return the result */
     return Result;
@@ -325,7 +325,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
     {
         return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
     }
-    
+
     return TRUE;
 }
 
@@ -333,7 +333,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -408,7 +408,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);
@@ -478,7 +478,7 @@ 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);
@@ -567,7 +567,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);
@@ -757,7 +757,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -844,7 +844,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -942,8 +942,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 +963,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 +980,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 +994,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;
@@ -1038,7 +1037,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
     ULONG Dummy, Value = 0, SignFlag;
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1107,8 +1106,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 +1137,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 +1165,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 +1176,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 +1194,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 +1205,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);
@@ -1313,20 +1309,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 +1336,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
 {
     FAST486_MOD_REG_RM ModRegRm;
     BOOLEAN OperandSize, AddressSize;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1374,13 +1370,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);
         }
@@ -1492,8 +1488,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 */
@@ -1517,13 +1513,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);
         }
@@ -1642,8 +1638,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 +1653,208 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     return TRUE;
 }
 
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
+{
+    UCHAR TableReg[6];
+    FAST486_MOD_REG_RM ModRegRm;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+    FAST486_SEG_REGS Segment = FAST486_REG_DS;
+
+    NO_LOCK_PREFIX();
+    TOGGLE_ADSIZE(AddressSize);
+
+    /* Check for the segment override */
+    if (State->PrefixFlags & FAST486_PREFIX_SEG)
+    {
+        /* Use the override segment instead */
+        Segment = State->SegmentOverride;
+    }
+
+    if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+    {
+        /* Exception occurred */
+        return FALSE;
+    }
+
+    /* Check which operation this is */
+    switch (ModRegRm.Register)
+    {
+        /* SGDT */
+        case 0:
+        {
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Fill the 6-byte table register */
+            RtlCopyMemory(TableReg, &State->Gdtr.Size, sizeof(USHORT));
+            RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Gdtr.Address, sizeof(ULONG));
+
+            /* Store the GDTR */
+            return Fast486WriteMemory(State,
+                                      Segment,
+                                      ModRegRm.MemoryAddress,
+                                      TableReg,
+                                      sizeof(TableReg));
+        }
+
+        /* SIDT */
+        case 1:
+        {
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Fill the 6-byte table register */
+            RtlCopyMemory(TableReg, &State->Idtr.Size, sizeof(USHORT));
+            RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Idtr.Address, sizeof(ULONG));
+
+            /* Store the IDTR */
+            return Fast486WriteMemory(State,
+                                      Segment,
+                                      ModRegRm.MemoryAddress,
+                                      TableReg,
+                                      sizeof(TableReg));
+        }
+
+        /* LGDT */
+        case 2:
+        {
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Read the new GDTR */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress,
+                                   FALSE,
+                                   TableReg,
+                                   sizeof(TableReg)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new GDT */
+            State->Gdtr.Size = *((PUSHORT)TableReg);
+            State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
+
+            return TRUE;
+        }
+
+        /* LIDT */
+        case 3:
+        {
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            if (!ModRegRm.Memory)
+            {
+                /* The second operand must be a memory location */
+                Fast486Exception(State, FAST486_EXCEPTION_UD);
+                return FALSE;
+            }
+
+            /* Read the new IDTR */
+            if (!Fast486ReadMemory(State,
+                                   Segment,
+                                   ModRegRm.MemoryAddress,
+                                   FALSE,
+                                   TableReg,
+                                   sizeof(TableReg)))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* Load the new IDT */
+            State->Idtr.Size = *((PUSHORT)TableReg);
+            State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
+
+            return TRUE;
+        }
+
+        /* SMSW */
+        case 4:
+        {
+            /* Store the lower 16 bits of CR0 */
+            return Fast486WriteModrmWordOperands(State,
+                                                 &ModRegRm,
+                                                 FALSE,
+                                                 LOWORD(State->ControlRegisters[FAST486_REG_CR0]));
+        }
+
+        /* LMSW */
+        case 6:
+        {
+            USHORT MasterStatusWord, Dummy;
+
+            /* This is a privileged instruction */
+            if (Fast486GetCurrentPrivLevel(State) != 0)
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            /* Read the new master status word */
+            if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &MasterStatusWord))
+            {
+                /* Exception occurred */
+                return FALSE;
+            }
+
+            /* This instruction cannot be used to return to real mode */
+            if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
+                && !(MasterStatusWord & FAST486_CR0_PE))
+            {
+                Fast486Exception(State, FAST486_EXCEPTION_GP);
+                return FALSE;
+            }
+
+            /* Set the lowest 4 bits */
+            State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF0;
+            State->ControlRegisters[FAST486_REG_CR0] |= MasterStatusWord & 0x0F;
+
+            return TRUE;
+        }
+
+        /* INVLPG */
+        case 7:
+        {
+            UNIMPLEMENTED;
+            return FALSE;
+        }
+
+        /* Invalid */
+        default:
+        {
+            Fast486Exception(State, FAST486_EXCEPTION_UD);
+            return FALSE;
+        }
+    }
+}
+
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
 {
     FAST486_MOD_REG_RM ModRegRm;
@@ -1681,7 +1879,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
     BOOLEAN OperandSize, AddressSize;
     UINT DataSize;
     UCHAR BitNumber;
-    
+
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(OperandSize);
@@ -1806,9 +2004,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
 
     /* Return success */
     return TRUE;
-
-    return TRUE;
 }
 
 /* EOF */
-