[FAST486]
[reactos.git] / lib / fast486 / opgroups.c
index a721c89..754a9d8 100644 (file)
@@ -161,17 +161,16 @@ Fast486RotateOperation(PFAST486_STATE State,
                        UCHAR Count)
 {
     ULONG HighestBit = 1 << (Bits - 1);
+    ULONG MaxValue = HighestBit | (HighestBit - 1);
     ULONG Result;
 
     /* Normalize the count */
     Count &= 0x1F;
 
+    if ((Operation == 2) || (Operation == 3)) Count %= Bits + 1;
+
     /* If the count is zero, do nothing */
-    if (Count == 0)
-    {
-        Result = Value;
-        goto SetFlags;
-    }
+    if (Count == 0) return Value;
 
     /* Check which operation is this */
     switch (Operation)
@@ -179,6 +178,7 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* ROL */
         case 0:
         {
+            Count %= Bits;
             Result = (Value << Count) | (Value >> (Bits - Count));
 
             /* Update CF and OF */
@@ -192,6 +192,7 @@ Fast486RotateOperation(PFAST486_STATE State,
         /* ROR */
         case 1:
         {
+            Count %= Bits;
             Result = (Value >> Count) | (Value << (Bits - Count));
 
             /* Update CF and OF */
@@ -205,14 +206,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))) != 0);
-            if (Count == 1) State->Flags.Of = State->Flags.Cf
-                                              ^ ((Result & HighestBit) != 0);
+            if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Result & HighestBit) != 0);
 
             break;
         }
@@ -220,14 +221,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))) != 0);
-            if (Count == 1) State->Flags.Of = State->Flags.Cf
-                                              ^ ((Result & (HighestBit >> 1)) != 0);
+            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;
         }
@@ -274,11 +277,10 @@ Fast486RotateOperation(PFAST486_STATE State,
         }
     }
 
-SetFlags:
     if (Operation >= 4)
     {
         /* Update ZF, SF and PF */
-        State->Flags.Zf = (Result == 0);
+        State->Flags.Zf = ((Result & MaxValue) == 0);
         State->Flags.Sf = ((Result & HighestBit) != 0);
         State->Flags.Pf = Fast486CalculateParity(Result);
     }
@@ -484,23 +486,26 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F)
     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;
     }
 
@@ -1919,7 +1924,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
     }
 
     /* Normalize the bit number */
-    BitNumber &= (1 << DataSize) - 1;
+    BitNumber %= DataSize;
 
     if (OperandSize)
     {