[FAST486]
[reactos.git] / lib / fast486 / opcodes.c
index 67432a8..539b8fe 100644 (file)
@@ -31,6 +31,7 @@
 #include "opgroups.h"
 #include "extraops.h"
 #include "common.h"
+#include "fpu.h"
 
 /* PUBLIC VARIABLES ***********************************************************/
 
@@ -253,14 +254,14 @@ Fast486OpcodeHandlers[FAST486_NUM_OPCODE_HANDLERS] =
     Fast486OpcodeAad,
     Fast486OpcodeSalc,
     Fast486OpcodeXlat,
-    NULL, // TODO: OPCODE 0xD8 NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xD9 NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDA NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDB NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDC NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDD NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDE NOT SUPPORTED
-    NULL, // TODO: OPCODE 0xDF NOT SUPPORTED
+    Fast486FpuOpcodeD8,
+    Fast486FpuOpcodeD9,
+    Fast486FpuOpcodeDA,
+    Fast486FpuOpcodeDB,
+    Fast486FpuOpcodeDC,
+    Fast486FpuOpcodeDD,
+    Fast486FpuOpcodeDE,
+    Fast486FpuOpcodeDF,
     Fast486OpcodeLoop,
     Fast486OpcodeLoop,
     Fast486OpcodeLoop,
@@ -540,7 +541,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePushReg)
 FAST486_OPCODE_HANDLER(Fast486OpcodePopReg)
 {
     ULONG Value;
-    BOOLEAN Size = State->SegmentRegs[FAST486_REG_SS].Size;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
 
     TOGGLE_OPSIZE(Size);
     NO_LOCK_PREFIX();
@@ -606,10 +607,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp)
 {
     BOOLEAN Jump = FALSE;
     CHAR Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
 
     /* Make sure this is the right instruction */
     ASSERT((Opcode & 0xF0) == 0x70);
 
+    TOGGLE_OPSIZE(Size);
+
     /* Fetch the offset */
     if (!Fast486FetchByte(State, (PUCHAR)&Offset))
     {
@@ -686,6 +690,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp)
     {
         /* Move the instruction pointer */
         State->InstPtr.Long += Offset;
+
+        if (!Size)
+        {
+            /* Clear the top half of EIP */
+            State->InstPtr.Long &= 0xFFFF;
+        }
     }
 
     /* Return success */
@@ -1058,6 +1068,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOut)
 FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump)
 {
     CHAR Offset = 0;
+    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+    TOGGLE_OPSIZE(Size);
 
     /* Make sure this is the right instruction */
     ASSERT(Opcode == 0xEB);
@@ -1072,6 +1085,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump)
     /* Move the instruction pointer */
     State->InstPtr.Long += Offset;
 
+    if (!Size)
+    {
+        /* Clear the top half of EIP */
+        State->InstPtr.Long &= 0xFFFF;
+    }
+
     return TRUE;
 }
 
@@ -2465,7 +2484,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm)
     State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
     State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
                       && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
-    State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
     State->Flags.Zf = (Result == 0);
     State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2522,7 +2541,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm)
         State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
         State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
                           && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
-        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2557,7 +2576,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm)
         State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
         State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
                           && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
-        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2603,7 +2622,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl)
     State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
     State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
                       && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
-    State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
     State->Flags.Zf = (Result == 0);
     State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2646,7 +2665,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax)
         State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
         State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
                           && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
-        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2676,7 +2695,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax)
         State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
         State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
                           && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
-        State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2747,10 +2766,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm)
     Result = FirstValue - SecondValue - Carry;
 
     /* Update the flags */
-    State->Flags.Cf = FirstValue < (SecondValue + 1);
+    State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
     State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
                       && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
-    State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
     State->Flags.Zf = (Result == 0);
     State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2808,10 +2827,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm)
         Result = FirstValue - SecondValue - Carry;
 
         /* Update the flags */
-        State->Flags.Cf = FirstValue < (SecondValue + Carry);
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
         State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
                           && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
-        State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2846,10 +2865,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm)
         Result = FirstValue - SecondValue - Carry;
 
         /* Update the flags */
-        State->Flags.Cf = FirstValue < (SecondValue + Carry);
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
         State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
                           && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
-        State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2888,10 +2907,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl)
     Result = FirstValue - SecondValue - Carry;
 
     /* Update the flags */
-    State->Flags.Cf = FirstValue < (SecondValue + Carry);
+    State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
     State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
                       && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
-    State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
+    State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
     State->Flags.Zf = (Result == 0);
     State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2929,10 +2948,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax)
         Result = FirstValue - SecondValue - Carry;
 
         /* Update the flags */
-        State->Flags.Cf = FirstValue < (SecondValue + Carry);
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
         State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
                           && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
-        State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_LONG) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -2955,10 +2974,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax)
         Result = FirstValue - SecondValue - Carry;
 
         /* Update the flags */
-        State->Flags.Cf = FirstValue < (SecondValue + Carry);
+        State->Flags.Cf = Carry ? (FirstValue <= SecondValue) : (FirstValue < SecondValue);
         State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
                           && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
-        State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
+        State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0;
         State->Flags.Zf = (Result == 0);
         State->Flags.Sf = ((Result & SIGN_FLAG_WORD) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
@@ -3024,6 +3043,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeDaa)
         State->Flags.Cf = TRUE;
     }
 
+    Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /* Update the flags */
+    State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
     return TRUE;
 }
 
@@ -3356,6 +3382,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeDas)
         State->Flags.Cf = TRUE;
     }
 
+    Value = State->GeneralRegs[FAST486_REG_EAX].LowByte;
+
+    /* Update the flags */
+    State->Flags.Sf = (Value & SIGN_FLAG_BYTE) != 0;
+    State->Flags.Zf = (Value == 0);
+    State->Flags.Pf = Fast486CalculateParity(Value);
+
     return TRUE;
 }
 
@@ -3370,7 +3403,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAaa)
     if (((Value & 0x0F) > 9) || State->Flags.Af)
     {
         /* Correct it */
-        State->GeneralRegs[FAST486_REG_EAX].LowByte += 0x06;
+        State->GeneralRegs[FAST486_REG_EAX].LowWord += 0x06;
         State->GeneralRegs[FAST486_REG_EAX].HighByte++;
 
         /* Set CF and AF */
@@ -3399,7 +3432,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAas)
     if (((Value & 0x0F) > 9) || State->Flags.Af)
     {
         /* Correct it */
-        State->GeneralRegs[FAST486_REG_EAX].LowByte -= 0x06;
+        State->GeneralRegs[FAST486_REG_EAX].LowWord -= 0x06;
         State->GeneralRegs[FAST486_REG_EAX].HighByte--;
 
         /* Set CF and AF */
@@ -3951,9 +3984,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg)
 
     if (OperandSize)
     {
-        ULONG Dummy, Selector;
+        ULONG Selector;
 
-        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Selector))
+        if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Selector))
         {
             /* Exception occurred */
             return FALSE;
@@ -3963,9 +3996,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovLoadSeg)
     }
     else
     {
-        USHORT Dummy, Selector;
+        USHORT Selector;
 
-        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Selector))
+        if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Selector))
         {
             /* Exception occurred */
             return FALSE;
@@ -4131,121 +4164,37 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePopFlags)
 {
     BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
     INT Cpl = Fast486GetCurrentPrivLevel(State);
-    ULONG NewFlags;
+    FAST486_FLAGS_REG NewFlags;
 
     NO_LOCK_PREFIX();
     TOGGLE_OPSIZE(Size);
 
     /* Pop the new flags */
-    if (!Fast486StackPop(State, &NewFlags))
+    if (!Fast486StackPop(State, &NewFlags.Long))
     {
         /* Exception occurred */
         return FALSE;
     }
 
-    if (!State->Flags.Vm)
+    if (State->Flags.Vm && (State->Flags.Iopl != 3))
     {
-        /* Check the current privilege level */
-        if (Cpl == 0)
-        {
-            /* Supervisor */
-
-            /* Set the flags */
-            if (Size)
-            {
-                /* Memorize the old state of RF */
-                BOOLEAN OldRf = State->Flags.Rf;
-
-                State->Flags.Long = NewFlags;
-
-                /* Restore VM and RF */
-                State->Flags.Vm = FALSE;
-                State->Flags.Rf = OldRf;
-
-                /* Clear VIF and VIP */
-                State->Flags.Vif = State->Flags.Vip = FALSE;
-            }
-            else State->Flags.LowWord = LOWORD(NewFlags);
-
-            /* Restore the reserved bits */
-            State->Flags.AlwaysSet = TRUE;
-            State->Flags.Reserved0 = FALSE;
-            State->Flags.Reserved1 = FALSE;
-        }
-        else
-        {
-            /* User */
-
-            /* Memorize the old state of IF and IOPL */
-            BOOLEAN OldIf = State->Flags.If;
-            UINT OldIopl = State->Flags.Iopl;
-
-            /* Set the flags */
-            if (Size)
-            {
-                /* Memorize the old state of RF */
-                BOOLEAN OldRf = State->Flags.Rf;
-
-                State->Flags.Long = NewFlags;
-
-                /* Restore VM and RF */
-                State->Flags.Vm = FALSE;
-                State->Flags.Rf = OldRf;
-
-                /* Clear VIF and VIP */
-                State->Flags.Vif = State->Flags.Vip = FALSE;
-            }
-            else State->Flags.LowWord = LOWORD(NewFlags);
-
-            /* Restore the reserved bits and IOPL */
-            State->Flags.AlwaysSet = TRUE;
-            State->Flags.Reserved0 = FALSE;
-            State->Flags.Reserved1 = FALSE;
-            State->Flags.Iopl = OldIopl;
-
-            /* Check if the user doesn't have the privilege to change IF */
-            if (Cpl > State->Flags.Iopl)
-            {
-                /* Restore IF */
-                State->Flags.If = OldIf;
-            }
-        }
+        /* Call the VM86 monitor */
+        Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
+        return TRUE;
     }
-    else
-    {
-        /* Check the IOPL */
-        if (State->Flags.Iopl == 3)
-        {
-            if (Size)
-            {
-                /* Memorize the old state of RF, VIF and VIP */
-                BOOLEAN OldRf = State->Flags.Rf;
-                BOOLEAN OldVif = State->Flags.Vif;
-                BOOLEAN OldVip = State->Flags.Vip;
-
-                State->Flags.Long = NewFlags;
-
-                /* Restore VM, RF, VIF and VIP */
-                State->Flags.Vm = TRUE;
-                State->Flags.Rf = OldRf;
-                State->Flags.Vif = OldVif;
-                State->Flags.Vip = OldVip;
-            }
-            else State->Flags.LowWord = LOWORD(NewFlags);
 
-            /* Restore the reserved bits and IOPL */
-            State->Flags.AlwaysSet = TRUE;
-            State->Flags.Reserved0 = FALSE;
-            State->Flags.Reserved1 = FALSE;
-            State->Flags.Iopl = 3;
-        }
-        else
-        {
-            /* Call the VM86 monitor */
-            Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, 0);
-        }
+    State->Flags.Cf = NewFlags.Cf;
+    State->Flags.Pf = NewFlags.Pf;
+    State->Flags.Af = NewFlags.Af;
+    State->Flags.Zf = NewFlags.Zf;
+    State->Flags.Sf = NewFlags.Sf;
+    State->Flags.Tf = NewFlags.Tf;
+    State->Flags.Df = NewFlags.Df;
+    State->Flags.Of = NewFlags.Of;
+    State->Flags.Nt = NewFlags.Nt;
 
-    }
+    if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
+    if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
 
     return TRUE;
 }
@@ -4858,6 +4807,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAam)
     State->GeneralRegs[FAST486_REG_EAX].LowByte = Value %= Base;
 
     /* Update flags */
+    State->Flags.Af = FALSE;
     State->Flags.Zf = (Value == 0);
     State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Value);
@@ -4881,9 +4831,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeAad)
 
     /* Adjust */
     Value += State->GeneralRegs[FAST486_REG_EAX].HighByte * Base;
-    State->GeneralRegs[FAST486_REG_EAX].LowByte = Value;
+    State->GeneralRegs[FAST486_REG_EAX].LowWord = Value;
 
     /* Update flags */
+    State->Flags.Af = FALSE;
     State->Flags.Zf = (Value == 0);
     State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
     State->Flags.Pf = Fast486CalculateParity(Value);
@@ -4901,8 +4852,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeXlat)
     /* Read a byte from DS:[(E)BX + AL] */
     if (!Fast486ReadMemory(State,
                            FAST486_REG_DS,
-                           AddressSize ? State->GeneralRegs[FAST486_REG_EBX].Long
-                                       : State->GeneralRegs[FAST486_REG_EBX].LowWord
+                           (AddressSize ? State->GeneralRegs[FAST486_REG_EBX].Long
+                                        : State->GeneralRegs[FAST486_REG_EBX].LowWord)
                            + State->GeneralRegs[FAST486_REG_EAX].LowByte,
                            FALSE,
                            &Value,
@@ -5087,7 +5038,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeJmp)
         }
 
         /* Move the instruction pointer */
-        State->InstPtr.LowWord += Offset;
+        State->InstPtr.Long += Offset;
+
+        /* Clear the top half of EIP */
+        State->InstPtr.Long &= 0xFFFF;
     }
 
     return TRUE;
@@ -5137,9 +5091,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs)
         return FALSE;
     }
 
-    /* Load new (E)IP */
-    if (Size) State->InstPtr.Long = Offset;
-    else State->InstPtr.LowWord = LOWORD(Offset);
+    /* Load new EIP */
+    State->InstPtr.Long = Offset;
 
     return TRUE;
 }
@@ -5417,7 +5370,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
     if (State->PrefixFlags & FAST486_PREFIX_REP)
     {
         UCHAR Block[STRING_BLOCK_SIZE];
-        ULONG Count = OperandSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
                                   : State->GeneralRegs[FAST486_REG_ECX].LowWord;
 
         /* Clear the memory block */
@@ -5468,7 +5421,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
                                    Processed * DataSize))
             {
                 /* Set ECX */
-                if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
                 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
 
                 /* Exception occurred */
@@ -5484,7 +5437,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
                                     Processed * DataSize))
             {
                 /* Set ECX */
-                if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
                 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
 
                 /* Exception occurred */
@@ -5511,7 +5464,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
         }
 
         /* Clear ECX */
-        if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
         else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
     }
     else
@@ -5542,7 +5495,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
         }
 
         /* Increment/decrement ESI and EDI */
-        if (OperandSize)
+        if (AddressSize)
         {
             if (!State->Flags.Df)
             {
@@ -5600,8 +5553,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeCmps)
     else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
 
     /* Calculate the mask and sign flag */
-    DataMask = (1 << (DataSize * 8)) - 1;
     SignFlag = 1 << ((DataSize * 8) - 1);
+    DataMask = SignFlag | (SignFlag - 1);
 
     /* Read from the first source operand */
     if (!Fast486ReadMemory(State,
@@ -5644,7 +5597,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeCmps)
     State->Flags.Pf = Fast486CalculateParity(Result);
 
     /* Increment/decrement ESI and EDI */
-    if (OperandSize)
+    if (AddressSize)
     {
         if (!State->Flags.Df)
         {
@@ -5677,7 +5630,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeCmps)
     {
         BOOLEAN Repeat = TRUE;
 
-        if (OperandSize)
+        if (AddressSize)
         {
             if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
             {
@@ -5732,7 +5685,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeStos)
     if (State->PrefixFlags & FAST486_PREFIX_REP)
     {
         UCHAR Block[STRING_BLOCK_SIZE];
-        ULONG Count = OperandSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
                                   : State->GeneralRegs[FAST486_REG_ECX].LowWord;
 
         /* Fill the memory block with the data */
@@ -5789,7 +5742,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeStos)
                                     Processed * DataSize))
             {
                 /* Set ECX */
-                if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
                 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
 
                 /* Exception occurred */
@@ -5808,7 +5761,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeStos)
         }
 
         /* Clear ECX */
-        if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
         else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
     }
     else
@@ -5826,7 +5779,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeStos)
         }
 
         /* Increment/decrement EDI */
-        if (OperandSize)
+        if (AddressSize)
         {
             if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
             else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
@@ -5868,7 +5821,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLods)
 
     if (State->PrefixFlags & FAST486_PREFIX_REP)
     {
-        ULONG Count = OperandSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
                                   : State->GeneralRegs[FAST486_REG_ECX].LowWord;
 
         /* If the count is 0, do nothing */
@@ -5886,17 +5839,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLods)
             else State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Count - 1) * DataSize;
         }
 
-        /* Update registers */
-        if (OperandSize)
-        {
-            State->GeneralRegs[FAST486_REG_ECX].Long = 0;
-            State->GeneralRegs[FAST486_REG_ESI].Long += (Count - 1) * DataSize;
-        }
-        else
-        {
-            State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
-            State->GeneralRegs[FAST486_REG_ESI].LowWord += (Count - 1) * DataSize;
-        }
+        /* Clear ECX */
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
     }
 
     /* Read from the source operand */
@@ -5913,7 +5858,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLods)
     }
 
     /* Increment/decrement ESI */
-    if (OperandSize)
+    if (AddressSize)
     {
         if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
         else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
@@ -5949,8 +5894,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeScas)
     else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
 
     /* Calculate the mask and sign flag */
-    DataMask = (1 << (DataSize * 8)) - 1;
     SignFlag = 1 << ((DataSize * 8) - 1);
+    DataMask = SignFlag | (SignFlag - 1);
 
     /* Read from the source operand */
     if (!Fast486ReadMemory(State,
@@ -5980,7 +5925,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeScas)
     State->Flags.Pf = Fast486CalculateParity(Result);
 
     /* Increment/decrement EDI */
-    if (OperandSize)
+    if (AddressSize)
     {
         if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
         else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
@@ -5997,7 +5942,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeScas)
     {
         BOOLEAN Repeat = TRUE;
 
-        if (OperandSize)
+        if (AddressSize)
         {
             if ((--State->GeneralRegs[FAST486_REG_ECX].Long) == 0)
             {
@@ -6052,7 +5997,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
     if (State->PrefixFlags & FAST486_PREFIX_REP)
     {
         UCHAR Block[STRING_BLOCK_SIZE];
-        ULONG Count = OperandSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
                                   : State->GeneralRegs[FAST486_REG_ECX].LowWord;
 
         /* Clear the memory block */
@@ -6111,7 +6056,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
                                     Processed * DataSize))
             {
                 /* Set ECX */
-                if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
                 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
 
                 /* Exception occurred */
@@ -6130,7 +6075,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
         }
 
         /* Clear ECX */
-        if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
         else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
     }
     else
@@ -6157,7 +6102,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIns)
         }
 
         /* Increment/decrement EDI */
-        if (OperandSize)
+        if (AddressSize)
         {
             if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
             else State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
@@ -6193,7 +6138,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
     if (State->PrefixFlags & FAST486_PREFIX_REP)
     {
         UCHAR Block[STRING_BLOCK_SIZE];
-        ULONG Count = OperandSize ? State->GeneralRegs[FAST486_REG_ECX].Long
+        ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
                                   : State->GeneralRegs[FAST486_REG_ECX].LowWord;
 
         /* Clear the memory block */
@@ -6225,7 +6170,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
                                    Processed * DataSize))
             {
                 /* Set ECX */
-                if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
+                if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
                 else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
 
                 /* Exception occurred */
@@ -6272,7 +6217,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
         }
 
         /* Clear ECX */
-        if (OperandSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+        if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
         else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
     }
     else
@@ -6300,7 +6245,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeOuts)
                                DataSize);
 
         /* Increment/decrement ESI */
-        if (OperandSize)
+        if (AddressSize)
         {
             if (!State->Flags.Df) State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
             else State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;