/* INCLUDES *******************************************************************/
-// #define WIN32_NO_STATUS
-// #define _INC_WINDOWS
#include <windef.h>
// #define NDEBUG
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
- if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
- {
- /* The OPSIZE prefix toggles the size */
- OperandSize = !OperandSize;
- }
-
- if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
- {
- /* The ADSIZE prefix toggles the size */
- AddressSize = !AddressSize;
- }
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
{
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 AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+ TOGGLE_ADSIZE(AddressSize);
+
+ if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* All of them are reserved (UD2) */
+ Fast486Exception(State, FAST486_EXCEPTION_UD);
+ return FALSE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
+{
+ FAST486_MOD_REG_RM ModRegRm;
+ BOOLEAN OperandSize, AddressSize;
+ UINT DataSize;
+ UCHAR BitNumber;
+
+ OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+ TOGGLE_OPSIZE(OperandSize);
+ TOGGLE_ADSIZE(AddressSize);
+
+ /* Get the number of bits */
+ if (OperandSize) DataSize = 32;
+ else DataSize = 16;
+
+ if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (ModRegRm.Register < 4)
+ {
+ /* Invalid */
+ Fast486Exception(State, FAST486_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ /* Get the bit number */
+ if (!Fast486FetchByte(State, &BitNumber))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (ModRegRm.Memory)
+ {
+ /*
+ * For memory operands, add the bit offset divided by
+ * the data size to the address
+ */
+ ModRegRm.MemoryAddress += BitNumber / DataSize;
+ }
+
+ /* Normalize the bit number */
+ BitNumber &= (1 << DataSize) - 1;
+
+ if (OperandSize)
+ {
+ ULONG Dummy, Value;
+
+ /* Read the value */
+ if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Set CF to the bit value */
+ State->Flags.Cf = (Value >> BitNumber) & 1;
+
+ if (ModRegRm.Register == 5)
+ {
+ /* BTS */
+ Value |= 1 << BitNumber;
+ }
+ else if (ModRegRm.Register == 6)
+ {
+ /* BTR */
+ Value &= ~(1 << BitNumber);
+ }
+ else if (ModRegRm.Register == 7)
+ {
+ /* BTC */
+ Value ^= 1 << BitNumber;
+ }
+
+ if (ModRegRm.Register >= 5)
+ {
+ /* Write back the result */
+ if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ USHORT Dummy, Value;
+
+ /* Read the value */
+ if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Set CF to the bit value */
+ State->Flags.Cf = (Value >> BitNumber) & 1;
+
+ if (ModRegRm.Register == 5)
+ {
+ /* BTS */
+ Value |= 1 << BitNumber;
+ }
+ else if (ModRegRm.Register == 6)
+ {
+ /* BTR */
+ Value &= ~(1 << BitNumber);
+ }
+ else if (ModRegRm.Register == 7)
+ {
+ /* BTC */
+ Value ^= 1 << BitNumber;
+ }
+
+ if (ModRegRm.Register >= 5)
+ {
+ /* Write back the result */
+ if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ }
+
+ /* Return success */
+ return TRUE;
+
+ return TRUE;
+}
+
/* EOF */