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)
/* ROL */
case 0:
{
+ Count %= Bits;
Result = (Value << Count) | (Value >> (Bits - Count));
/* Update CF and OF */
/* ROR */
case 1:
{
+ Count %= Bits;
Result = (Value >> Count) | (Value << (Bits - Count));
/* Update CF and OF */
/* 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;
}
/* 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;
}
}
}
-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);
}
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;
}
}
/* Normalize the bit number */
- BitNumber &= (1 << DataSize) - 1;
+ BitNumber %= DataSize;
if (OperandSize)
{