Author: aandrejevic
Date: Sat Dec 14 02:13:01 2013
New Revision: 61268
URL:
http://svn.reactos.org/svn/reactos?rev=61268&view=rev
Log:
[FAST486]
Fix the emulation of the Local Descriptor Table.
Modified:
branches/ntvdm/include/reactos/libs/fast486/fast486.h
branches/ntvdm/lib/fast486/common.inl
branches/ntvdm/lib/fast486/opgroups.c
Modified: branches/ntvdm/include/reactos/libs/fast486/fast486.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/libs/fast…
==============================================================================
--- branches/ntvdm/include/reactos/libs/fast486/fast486.h [iso-8859-1] (original)
+++ branches/ntvdm/include/reactos/libs/fast486/fast486.h [iso-8859-1] Sat Dec 14 02:13:01
2013
@@ -81,6 +81,7 @@
#define FAST486_IDT_INT_GATE_32 0xE
#define FAST486_IDT_TRAP_GATE_32 0xF
+#define FAST486_LDT_SIGNATURE 0x02
#define FAST486_TSS_SIGNATURE 0x09
#define FAST486_PREFIX_SEG (1 << 0)
@@ -261,6 +262,13 @@
USHORT Selector;
ULONG Base;
ULONG Limit;
+} FAST486_LDT_REG;
+
+typedef struct
+{
+ USHORT Selector;
+ ULONG Base;
+ ULONG Limit;
BOOLEAN Busy;
} FAST486_TASK_REG, *PFAST486_TASK_REG;
@@ -302,10 +310,10 @@
ULONG Reserved : 2;
ULONG Granularity : 1;
ULONG BaseHigh : 8;
-} FAST486_TSS_DESCRIPTOR, *PFAST486_TSS_DESCRIPTOR;
+} FAST486_SYSTEM_DESCRIPTOR, *PFAST486_SYSTEM_DESCRIPTOR;
/* Verify the structure size */
-C_ASSERT(sizeof(FAST486_TSS_DESCRIPTOR) == sizeof(ULONGLONG));
+C_ASSERT(sizeof(FAST486_SYSTEM_DESCRIPTOR) == sizeof(ULONGLONG));
typedef struct
{
@@ -467,7 +475,8 @@
FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS];
FAST486_REG InstPtr, SavedInstPtr;
FAST486_FLAGS_REG Flags;
- FAST486_TABLE_REG Gdtr, Idtr, Ldtr;
+ FAST486_TABLE_REG Gdtr, Idtr;
+ FAST486_LDT_REG Ldtr;
FAST486_TASK_REG TaskReg;
UCHAR Cpl;
ULONG ControlRegisters[FAST486_NUM_CTRL_REGS];
Modified: branches/ntvdm/lib/fast486/common.inl
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/common.inl?re…
==============================================================================
--- branches/ntvdm/lib/fast486/common.inl [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/common.inl [iso-8859-1] Sat Dec 14 02:13:01 2013
@@ -420,7 +420,7 @@
else
{
/* Make sure the LDT contains the entry */
- if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Size + 1))
+ if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
{
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
return FALSE;
@@ -428,7 +428,7 @@
/* Read the LDT */
if (!Fast486ReadLinearMemory(State,
- State->Ldtr.Address
+ State->Ldtr.Base
+ GET_SEGMENT_INDEX(Selector),
&GdtEntry,
sizeof(GdtEntry)))
Modified: branches/ntvdm/lib/fast486/opgroups.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/opgroups.c?re…
==============================================================================
--- branches/ntvdm/lib/fast486/opgroups.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/opgroups.c [iso-8859-1] Sat Dec 14 02:13:01 2013
@@ -1702,10 +1702,8 @@
FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F00)
{
- 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);
@@ -1716,36 +1714,23 @@
return FALSE;
}
- /* Check for the segment override */
- if (State->PrefixFlags & FAST486_PREFIX_SEG)
- {
- /* Use the override segment instead */
- Segment = State->SegmentOverride;
- }
-
/* Check which operation this is */
switch (ModRegRm.Register)
{
/* SLDT */
case 0:
{
- if (!ModRegRm.Memory)
- {
- /* The second operand must be a memory location */
+ /* 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 FALSE;
- }
-
- /* Fill the 6-byte table register */
- RtlCopyMemory(TableReg, &State->Ldtr.Size, sizeof(USHORT));
- RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Ldtr.Address,
sizeof(ULONG));
-
- /* Store the LDTR */
- return Fast486WriteMemory(State,
- Segment,
- ModRegRm.MemoryAddress,
- TableReg,
- sizeof(TableReg));
+ }
+
+ return Fast486WriteModrmWordOperands(State,
+ &ModRegRm,
+ FALSE,
+ State->Ldtr.Selector);
}
/* STR */
@@ -1767,6 +1752,16 @@
/* 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)
{
@@ -1774,28 +1769,57 @@
return FALSE;
}
- if (!ModRegRm.Memory)
- {
- /* The second operand must be a memory location */
- Fast486Exception(State, FAST486_EXCEPTION_UD);
- return FALSE;
- }
-
- /* Read the new LDTR */
- if (!Fast486ReadMemory(State,
- Segment,
- ModRegRm.MemoryAddress,
- FALSE,
- TableReg,
- sizeof(TableReg)))
- {
- /* Exception occurred */
- return FALSE;
- }
-
- /* Load the new LDT */
- State->Ldtr.Size = *((PUSHORT)TableReg);
- State->Ldtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
+ 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;
}
@@ -1804,7 +1828,7 @@
case 3:
{
USHORT Selector;
- FAST486_TSS_DESCRIPTOR GdtEntry;
+ FAST486_SYSTEM_DESCRIPTOR GdtEntry;
/* Not recognized in real mode or virtual 8086 mode */
if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
@@ -1930,7 +1954,7 @@
else
{
/* Make sure the LDT contains the entry */
- if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Size + 1))
+ if (GET_SEGMENT_INDEX(Selector) >= (State->Ldtr.Limit + 1))
{
/* Clear ZF */
State->Flags.Zf = FALSE;
@@ -1939,7 +1963,7 @@
/* Read the LDT */
if (!Fast486ReadLinearMemory(State,
- State->Ldtr.Address
+ State->Ldtr.Base
+ GET_SEGMENT_INDEX(Selector),
&GdtEntry,
sizeof(GdtEntry)))