{
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;
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;
}
|| ((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;
}
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;
}
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);
}
/* 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 */
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)
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
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;
}
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;
}
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;
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
{
- UCHAR Immediate, Dummy, Value;
+ UCHAR Immediate, Value;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
{
return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
}
-
+
return TRUE;
}
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
if (OperandSize)
{
- ULONG Immediate, Value, Dummy;
+ ULONG Immediate, Value;
/* Fetch the immediate operand */
if (!Fast486FetchDword(State, &Immediate))
}
/* Read the operands */
- if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
}
else
{
- USHORT Immediate, Value, Dummy;
+ USHORT Immediate, Value;
/* Fetch the immediate operand */
if (!Fast486FetchWord(State, &Immediate))
}
/* Read the operands */
- if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
CHAR ImmByte;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
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;
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;
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;
}
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0)
{
- UCHAR Dummy, Value, Count;
+ UCHAR Value, Count;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
UCHAR Count;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
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;
}
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;
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0)
{
- UCHAR Dummy, Value;
+ UCHAR Value;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
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;
}
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;
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2)
{
- UCHAR Dummy, Value;
+ UCHAR Value;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
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;
}
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;
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
{
- UCHAR Dummy, Value = 0;
+ UCHAR Value = 0;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
/* 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;
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 */
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;
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;
/* 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;
/* 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;
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);
if (OperandSize)
{
/* 32-bit */
- if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
else
{
/* 16-bit */
- if (!Fast486ReadModrmWordOperands(State, &ModRegRm, (PUSHORT)&Dummy, (PUSHORT)&Value))
+ if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value))
{
/* Exception occurred */
return FALSE;
/* 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;
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 */
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;
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);
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;
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);
/* 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
/* 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
FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
{
- UCHAR Dummy, Value;
+ UCHAR Value;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
}
/* Read the operands */
- if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
{
/* 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 */
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
/* 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;
{
/* 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);
}
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)
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)
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 */
}
else
{
- USHORT Dummy, Value;
+ USHORT Value;
- if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+ if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value))
{
/* Exception occurred */
return FALSE;
{
/* 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);
}
/* 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)
/* 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)
{
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)
/* 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)
{
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 */
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];
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)
{
Segment = State->SegmentOverride;
}
- if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
- {
- /* Exception occurred */
- return FALSE;
- }
-
/* Check which operation this is */
switch (ModRegRm.Register)
{
/* 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,
/* LMSW */
case 6:
{
- USHORT MasterStatusWord, Dummy;
+ USHORT MachineStatusWord;
/* This is a privileged instruction */
if (Fast486GetCurrentPrivLevel(State) != 0)
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;
/* 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;
/* 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;
}
BOOLEAN OperandSize, AddressSize;
UINT DataSize;
UCHAR BitNumber;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
}
/* 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;
}
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;
/* Return success */
return TRUE;
-
- return TRUE;
}
/* EOF */
-