[FAST486]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 1 Nov 2013 22:39:43 +0000 (22:39 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 1 Nov 2013 22:39:43 +0000 (22:39 +0000)
Implement opcode group 0x0F, 0x01 (SGDT, SIDT, LGDT, LIDT, SMSW and LMSW).
Only INVLPG is not implemented yet.

svn path=/branches/ntvdm/; revision=60824

lib/fast486/extraops.c
lib/fast486/opgroups.c
lib/fast486/opgroups.h

index fbb8c47..a7335d2 100644 (file)
@@ -38,7 +38,7 @@ FAST486_OPCODE_HANDLER_PROC
 Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
 {
     NULL, // TODO: OPCODE 0x00 NOT IMPLEMENTED
-    NULL, // TODO: OPCODE 0x01 NOT IMPLEMENTED
+    Fast486OpcodeGroup0F01,
     NULL, // TODO: OPCODE 0x02 NOT IMPLEMENTED
     NULL, // TODO: OPCODE 0x03 NOT IMPLEMENTED
     NULL, // TODO: OPCODE 0x04 NOT IMPLEMENTED
index 0c5690a..5b9ec0a 100644 (file)
@@ -1657,6 +1657,208 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
     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;
index a7ce707..fdd941f 100644 (file)
@@ -42,6 +42,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF);
+FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9);
 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA);