{
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 & 0x0F) + ((SecondValue + Carry) & 0x0F)) & 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 */
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 */
/* 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;
}
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;
}
| (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;
}
| (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;
}
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);
+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;
{
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);
CHAR ImmByte;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
ULONG Value;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
UCHAR Count;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
/* 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;
ULONG Dummy, Value = 0, SignFlag;
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN OperandSize, AddressSize;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
/* 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);
{
/* 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);
{
/* 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);
}
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 */
{
/* 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);
}
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(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;
BOOLEAN OperandSize, AddressSize;
UINT DataSize;
UCHAR BitNumber;
-
+
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
TOGGLE_OPSIZE(OperandSize);
/* Return success */
return TRUE;
-
- return TRUE;
}
/* EOF */
-