Author: aandrejevic
Date: Mon May 4 19:14:23 2015
New Revision: 67545
URL:
http://svn.reactos.org/svn/reactos?rev=67545&view=rev
Log:
[FAST486]
- Implement call gates.
- Fix Fast486InterruptInternal and get rid of ugly hacks.
- Fix IRET (CS loaded too early).
- Add a structure definition for the 16-bit TSS (not supported yet).
Modified:
trunk/reactos/include/reactos/libs/fast486/fast486.h
trunk/reactos/lib/fast486/common.c
trunk/reactos/lib/fast486/common.h
trunk/reactos/lib/fast486/common.inl
trunk/reactos/lib/fast486/opcodes.c
Modified: trunk/reactos/include/reactos/libs/fast486/fast486.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fast4…
==============================================================================
--- trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] Mon May 4 19:14:23
2015
@@ -75,15 +75,18 @@
#define FAST486_DR4_RESERVED 0xFFFF1FF0
#define FAST486_DR5_RESERVED 0x0000DC00
-#define FAST486_LDT_SIGNATURE 0x02
-#define FAST486_TASK_GATE_SIGNATURE 0x05
-#define FAST486_IDT_INT_GATE 0x06
-#define FAST486_IDT_TRAP_GATE 0x07
-#define FAST486_TSS_SIGNATURE 0x09
-#define FAST486_BUSY_TSS_SIGNATURE 0x0B
-#define FAST486_CALL_GATE_SIGNATURE 0x0C
-#define FAST486_IDT_INT_GATE_32 0x0E
-#define FAST486_IDT_TRAP_GATE_32 0x0F
+#define FAST486_TSS_16_SIGNATURE 0x01
+#define FAST486_LDT_SIGNATURE 0x02
+#define FAST486_BUSY_TSS_16_SIGNATURE 0x03
+#define FAST486_CALL_GATE_16_SIGNATURE 0x04
+#define FAST486_TASK_GATE_SIGNATURE 0x05
+#define FAST486_IDT_INT_GATE 0x06
+#define FAST486_IDT_TRAP_GATE 0x07
+#define FAST486_TSS_SIGNATURE 0x09
+#define FAST486_BUSY_TSS_SIGNATURE 0x0B
+#define FAST486_CALL_GATE_SIGNATURE 0x0C
+#define FAST486_IDT_INT_GATE_32 0x0E
+#define FAST486_IDT_TRAP_GATE_32 0x0F
#define FAST486_PREFIX_SEG (1 << 0)
#define FAST486_PREFIX_OPSIZE (1 << 1)
@@ -353,44 +356,6 @@
/* Verify the structure size */
C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG));
-
-#include <poppack.h>
-
-typedef struct _FAST486_TABLE_REG
-{
- USHORT Size;
- ULONG Address;
-} FAST486_TABLE_REG, *PFAST486_TABLE_REG;
-
-typedef union _FAST486_FLAGS_REG
-{
- USHORT LowWord;
- ULONG Long;
-
- struct
- {
- ULONG Cf : 1;
- ULONG AlwaysSet : 1;
- ULONG Pf : 1;
- ULONG Reserved0 : 1;
- ULONG Af : 1;
- ULONG Reserved1 : 1;
- ULONG Zf : 1;
- ULONG Sf : 1;
- ULONG Tf : 1;
- ULONG If : 1;
- ULONG Df : 1;
- ULONG Of : 1;
- ULONG Iopl : 2;
- ULONG Nt : 1;
- ULONG Reserved2 : 1;
- ULONG Rf : 1;
- ULONG Vm : 1;
- ULONG Ac : 1;
-
- // ULONG Reserved : 13;
- };
-} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG;
typedef struct _FAST486_TSS
{
@@ -421,6 +386,70 @@
ULONG Ldtr;
ULONG IopbOffset;
} FAST486_TSS, *PFAST486_TSS;
+
+typedef struct _FAST486_LEGACY_TSS
+{
+ USHORT Link;
+ USHORT Sp0;
+ USHORT Ss0;
+ USHORT Sp1;
+ USHORT Ss1;
+ USHORT Sp2;
+ USHORT Ss2;
+ USHORT Ip;
+ USHORT Flags;
+ USHORT Ax;
+ USHORT Cx;
+ USHORT Dx;
+ USHORT Bx;
+ USHORT Sp;
+ USHORT Bp;
+ USHORT Si;
+ USHORT Di;
+ USHORT Es;
+ USHORT Cs;
+ USHORT Ss;
+ USHORT Ds;
+ USHORT Ldtr;
+} FAST486_LEGACY_TSS, *PFAST486_LEGACY_TSS;
+
+#include <poppack.h>
+
+typedef struct _FAST486_TABLE_REG
+{
+ USHORT Size;
+ ULONG Address;
+} FAST486_TABLE_REG, *PFAST486_TABLE_REG;
+
+typedef union _FAST486_FLAGS_REG
+{
+ USHORT LowWord;
+ ULONG Long;
+
+ struct
+ {
+ ULONG Cf : 1;
+ ULONG AlwaysSet : 1;
+ ULONG Pf : 1;
+ ULONG Reserved0 : 1;
+ ULONG Af : 1;
+ ULONG Reserved1 : 1;
+ ULONG Zf : 1;
+ ULONG Sf : 1;
+ ULONG Tf : 1;
+ ULONG If : 1;
+ ULONG Df : 1;
+ ULONG Of : 1;
+ ULONG Iopl : 2;
+ ULONG Nt : 1;
+ ULONG Reserved2 : 1;
+ ULONG Rf : 1;
+ ULONG Vm : 1;
+ ULONG Ac : 1;
+
+ // ULONG Reserved : 13;
+ };
+} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG;
typedef struct _FAST486_FPU_DATA_REG
{
Modified: trunk/reactos/lib/fast486/common.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.c?rev=6…
==============================================================================
--- trunk/reactos/lib/fast486/common.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.c [iso-8859-1] Mon May 4 19:14:23 2015
@@ -292,38 +292,30 @@
BOOLEAN PushErrorCode,
ULONG ErrorCode)
{
- USHORT SegmentSelector = IdtEntry->Selector;
- ULONG Offset = MAKELONG(IdtEntry->Offset, IdtEntry->OffsetHigh);
- ULONG GateType = IdtEntry->Type;
- BOOLEAN GateSize = (GateType == FAST486_IDT_INT_GATE_32) ||
- (GateType == FAST486_IDT_TRAP_GATE_32);
-
- BOOLEAN Success = FALSE;
- ULONG OldPrefixFlags = State->PrefixFlags;
+ BOOLEAN GateSize = (IdtEntry->Type == FAST486_IDT_INT_GATE_32) ||
+ (IdtEntry->Type == FAST486_IDT_TRAP_GATE_32);
+ USHORT OldCs = State->SegmentRegs[FAST486_REG_CS].Selector;
+ ULONG OldEip = State->InstPtr.Long;
+ ULONG OldFlags = State->Flags.Long;
+ UCHAR OldCpl = State->Cpl;
/* Check for protected mode */
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
{
- FAST486_TSS Tss;
USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
- if (GateType == FAST486_TASK_GATE_SIGNATURE)
+ if (IdtEntry->Type == FAST486_TASK_GATE_SIGNATURE)
{
/* Task call */
return Fast486TaskSwitch(State, FAST486_TASK_CALL, IdtEntry->Selector);
}
- if (GateSize != (State->SegmentRegs[FAST486_REG_CS].Size))
- {
- /* The gate size doesn't match the current operand size, so set the
OPSIZE flag. */
- State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
- }
-
/* Check if the interrupt handler is more privileged or if we're in V86 mode
*/
- if ((Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
- || State->Flags.Vm)
- {
+ if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || State->Flags.Vm)
+ {
+ FAST486_TSS Tss;
+
/* Read the TSS */
if (!Fast486ReadLinearMemory(State,
State->TaskReg.Base,
@@ -331,29 +323,11 @@
sizeof(Tss)))
{
/* Exception occurred */
- goto Cleanup;
+ return FALSE;
}
/* Switch to the new privilege level */
- State->Cpl = GET_SEGMENT_RPL(SegmentSelector);
-
- if (State->Flags.Vm)
- {
- /* Clear the VM flag */
- State->Flags.Vm = FALSE;
-
- /* Push GS, FS, DS and ES */
- if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_GS].Selector)) goto Cleanup;
- if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_FS].Selector)) goto Cleanup;
- if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_DS].Selector)) goto Cleanup;
- if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_ES].Selector)) goto Cleanup;
-
- /* Now load them with NULL selectors, since they are useless in protected
mode */
- if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) goto Cleanup;
- if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) goto Cleanup;
- if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) goto Cleanup;
- if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) goto Cleanup;
- }
+ State->Cpl = GET_SEGMENT_RPL(IdtEntry->Selector);
/* Check the new (higher) privilege level */
switch (State->Cpl)
@@ -363,7 +337,7 @@
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0))
{
/* Exception occurred */
- goto Cleanup;
+ return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0;
@@ -375,7 +349,7 @@
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1))
{
/* Exception occurred */
- goto Cleanup;
+ return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1;
@@ -387,7 +361,7 @@
if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2))
{
/* Exception occurred */
- goto Cleanup;
+ return FALSE;
}
State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2;
@@ -400,73 +374,90 @@
ASSERT(FALSE);
}
}
+ }
+
+ /* Load new CS */
+ if (!Fast486LoadSegment(State, FAST486_REG_CS, IdtEntry->Selector))
+ {
+ /* An exception occurred during the jump */
+ return FALSE;
+ }
+
+ if (GateSize)
+ {
+ /* 32-bit code segment, use EIP */
+ State->InstPtr.Long = MAKELONG(IdtEntry->Offset,
IdtEntry->OffsetHigh);
+ }
+ else
+ {
+ /* 16-bit code segment, use IP */
+ State->InstPtr.LowWord = IdtEntry->Offset;
+ }
+
+ /* Check if the interrupt handler is more privileged or we're in VM86 mode
(again) */
+ if ((OldCpl > GET_SEGMENT_RPL(IdtEntry->Selector)) || State->Flags.Vm)
+ {
+ if (State->Flags.Vm)
+ {
+ /* Clear the VM flag */
+ State->Flags.Vm = FALSE;
+
+ /* Push GS, FS, DS and ES */
+ if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_GS].Selector)) return FALSE;
+ if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_FS].Selector)) return FALSE;
+ if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_DS].Selector)) return FALSE;
+ if (!Fast486StackPush(State,
State->SegmentRegs[FAST486_REG_ES].Selector)) return FALSE;
+
+ /* Now load them with NULL selectors, since they are useless in protected
mode */
+ if (!Fast486LoadSegment(State, FAST486_REG_GS, 0)) return FALSE;
+ if (!Fast486LoadSegment(State, FAST486_REG_FS, 0)) return FALSE;
+ if (!Fast486LoadSegment(State, FAST486_REG_DS, 0)) return FALSE;
+ if (!Fast486LoadSegment(State, FAST486_REG_ES, 0)) return FALSE;
+ }
/* Push SS selector */
- if (!Fast486StackPush(State, OldSs)) goto Cleanup;
-
- /* Push stack pointer */
- if (!Fast486StackPush(State, OldEsp)) goto Cleanup;
+ if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
+
+ /* Push the stack pointer */
+ if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
}
}
else
{
- if (State->SegmentRegs[FAST486_REG_CS].Size)
- {
- /* Set OPSIZE, because INT always pushes 16-bit values in real mode */
- State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
- }
+ /* Load new CS */
+ if (!Fast486LoadSegment(State, FAST486_REG_CS, IdtEntry->Selector))
+ {
+ /* An exception occurred during the jump */
+ return FALSE;
+ }
+
+ /* Set the new IP */
+ State->InstPtr.LowWord = IdtEntry->Offset;
}
/* Push EFLAGS */
- if (!Fast486StackPush(State, State->Flags.Long)) goto Cleanup;
+ if (!Fast486StackPushInternal(State, GateSize, OldFlags)) return FALSE;
/* Push CS selector */
- if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) goto
Cleanup;
+ if (!Fast486StackPushInternal(State, GateSize, OldCs)) return FALSE;
/* Push the instruction pointer */
- if (!Fast486StackPush(State, State->InstPtr.Long)) goto Cleanup;
+ if (!Fast486StackPushInternal(State, GateSize, OldEip)) return FALSE;
if (PushErrorCode)
{
/* Push the error code */
- if (!Fast486StackPush(State, ErrorCode))
- {
- /* An exception occurred */
- goto Cleanup;
- }
- }
-
- if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
+ if (!Fast486StackPushInternal(State, GateSize, ErrorCode)) return FALSE;
+ }
+
+ if ((IdtEntry->Type == FAST486_IDT_INT_GATE)
+ || (IdtEntry->Type == FAST486_IDT_INT_GATE_32))
{
/* Disable interrupts after a jump to an interrupt gate handler */
State->Flags.If = FALSE;
}
- /* Load new CS */
- if (!Fast486LoadSegment(State, FAST486_REG_CS, SegmentSelector))
- {
- /* An exception occurred during the jump */
- goto Cleanup;
- }
-
- if (GateSize)
- {
- /* 32-bit code segment, use EIP */
- State->InstPtr.Long = Offset;
- }
- else
- {
- /* 16-bit code segment, use IP */
- State->InstPtr.LowWord = LOWORD(Offset);
- }
-
- Success = TRUE;
-
-Cleanup:
- /* Restore the prefix flags */
- State->PrefixFlags = OldPrefixFlags;
-
- return Success;
+ return TRUE;
}
BOOLEAN
@@ -876,4 +867,180 @@
return TRUE;
}
+BOOLEAN
+FASTCALL
+Fast486CallGate(PFAST486_STATE State,
+ PFAST486_CALL_GATE Gate,
+ BOOLEAN Call)
+{
+ BOOLEAN Valid;
+ FAST486_GDT_ENTRY NewCodeSegment;
+ BOOLEAN GateSize = (Gate->Type == FAST486_CALL_GATE_SIGNATURE);
+ FAST486_TSS Tss;
+ USHORT OldCs = State->SegmentRegs[FAST486_REG_CS].Selector;
+ ULONG OldEip = State->InstPtr.Long;
+ USHORT OldCpl = State->Cpl;
+ USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
+ ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
+ ULONG ParamBuffer[32]; /* Maximum possible size - 32 DWORDs */
+ PULONG LongParams = (PULONG)ParamBuffer;
+ PUSHORT ShortParams = (PUSHORT)ParamBuffer;
+
+ if (!Gate->Selector)
+ {
+ /* The code segment is NULL */
+ Fast486Exception(State, FAST486_EXCEPTION_GP);
+ return FALSE;
+ }
+
+ if (!Fast486ReadDescriptorEntry(State, Gate->Selector, &Valid,
&NewCodeSegment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (!Valid || (NewCodeSegment.Dpl > Fast486GetCurrentPrivLevel(State)))
+ {
+ /* Code segment invalid */
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Gate->Selector);
+ return FALSE;
+ }
+
+ if (Call && Gate->ParamCount)
+ {
+ /* Read the parameters */
+ if (!Fast486ReadMemory(State,
+ FAST486_REG_SS,
+ OldEsp,
+ FALSE,
+ ParamBuffer,
+ Gate->ParamCount * sizeof(ULONG)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Check if the new code segment is more privileged */
+ if (NewCodeSegment.Dpl < OldCpl)
+ {
+ if (Call)
+ {
+ /* Read the TSS */
+ if (!Fast486ReadLinearMemory(State,
+ State->TaskReg.Base,
+ &Tss,
+ sizeof(Tss)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Switch to the new privilege level */
+ State->Cpl = NewCodeSegment.Dpl;
+
+ /* Check the new (higher) privilege level */
+ switch (State->Cpl)
+ {
+ case 0:
+ {
+ if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss0))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp0;
+
+ break;
+ }
+
+ case 1:
+ {
+ if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss1))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp1;
+
+ break;
+ }
+
+ case 2:
+ {
+ if (!Fast486LoadSegment(State, FAST486_REG_SS, Tss.Ss2))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ State->GeneralRegs[FAST486_REG_ESP].Long = Tss.Esp2;
+
+ break;
+ }
+
+ default:
+ {
+ /* Should never reach here! */
+ ASSERT(FALSE);
+ }
+ }
+ }
+ else if (!NewCodeSegment.DirConf)
+ {
+ /* This is not allowed for jumps */
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP,
Gate->Selector);
+ return FALSE;
+ }
+ }
+
+ /* Load new CS */
+ if (!Fast486LoadSegment(State, FAST486_REG_CS, Gate->Selector))
+ {
+ /* An exception occurred during the jump */
+ return FALSE;
+ }
+
+ /* Set the instruction pointer */
+ if (GateSize) State->InstPtr.Long = MAKELONG(Gate->Offset,
Gate->OffsetHigh);
+ else State->InstPtr.Long = Gate->Offset;
+
+ if (Call)
+ {
+ INT i;
+
+ /* Check if the new code segment is more privileged (again) */
+ if (NewCodeSegment.Dpl < OldCpl)
+ {
+ /* Push SS selector */
+ if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
+
+ /* Push stack pointer */
+ if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
+ }
+
+ /* Push the parameters in reverse order */
+ for (i = Gate->ParamCount - 1; i >= 0; i--)
+ {
+ if (!Fast486StackPushInternal(State,
+ GateSize,
+ GateSize ? LongParams[i] : ShortParams[i]))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Push the parameter count */
+ if (!Fast486StackPushInternal(State, GateSize, Gate->ParamCount)) return
FALSE;
+
+ /* Push CS selector */
+ if (!Fast486StackPushInternal(State, GateSize, OldCs)) return FALSE;
+
+ /* Push the instruction pointer */
+ if (!Fast486StackPushInternal(State, GateSize, OldEip)) return FALSE;
+ }
+
+ return TRUE;
+}
+
/* EOF */
Modified: trunk/reactos/lib/fast486/common.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.h?rev=6…
==============================================================================
--- trunk/reactos/lib/fast486/common.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.h [iso-8859-1] Mon May 4 19:14:23 2015
@@ -183,6 +183,15 @@
USHORT Selector
);
+BOOLEAN
+FASTCALL
+Fast486CallGate
+(
+ PFAST486_STATE State,
+ PFAST486_CALL_GATE Gate,
+ BOOLEAN Call
+);
+
/* INLINED FUNCTIONS **********************************************************/
#include "common.inl"
Modified: trunk/reactos/lib/fast486/common.inl
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev…
==============================================================================
--- trunk/reactos/lib/fast486/common.inl [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.inl [iso-8859-1] Mon May 4 19:14:23 2015
@@ -297,19 +297,12 @@
FORCEINLINE
BOOLEAN
FASTCALL
-Fast486StackPush(PFAST486_STATE State,
- ULONG Value)
-{
- BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+Fast486StackPushInternal(PFAST486_STATE State, BOOLEAN Size, ULONG Value)
+{
ULONG StackPointer = State->GeneralRegs[FAST486_REG_ESP].Long;
- /* The OPSIZE prefix toggles the size */
- TOGGLE_OPSIZE(Size);
-
if (Size)
{
- /* 32-bit size */
-
/* Check if ESP is between 1 and 3 */
if (State->GeneralRegs[FAST486_REG_ESP].Long >= 1
&& State->GeneralRegs[FAST486_REG_ESP].Long <= 3)
@@ -344,9 +337,6 @@
}
else
{
- /* 16-bit size */
- USHORT ShortValue = LOWORD(Value);
-
/* Check if SP is 1 */
if (State->GeneralRegs[FAST486_REG_ESP].LowWord == 1)
{
@@ -360,7 +350,7 @@
State->SegmentRegs[FAST486_REG_SS].Size
? StackPointer - sizeof(USHORT)
: LOWORD(StackPointer - sizeof(USHORT)),
- &ShortValue,
+ &Value,
sizeof(USHORT)))
{
/* Exception occurred */
@@ -380,6 +370,20 @@
}
return TRUE;
+}
+
+FORCEINLINE
+BOOLEAN
+FASTCALL
+Fast486StackPush(PFAST486_STATE State, ULONG Value)
+{
+ BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+
+ /* The OPSIZE prefix toggles the size */
+ TOGGLE_OPSIZE(Size);
+
+ /* Call the internal function */
+ return Fast486StackPushInternal(State, Size, Value);
}
FORCEINLINE
@@ -778,12 +782,25 @@
return FALSE;
}
+ case FAST486_CALL_GATE_16_SIGNATURE:
case FAST486_CALL_GATE_SIGNATURE:
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- Fast486Exception(State, FAST486_EXCEPTION_UD);
+ if ((Descriptor.Dpl < Fast486GetCurrentPrivLevel(State))
+ && (Descriptor.Dpl < GET_SEGMENT_RPL(Selector)))
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
+ return FALSE;
+ }
+
+ if (!Descriptor.Present)
+ {
+ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
+ return FALSE;
+ }
+
+ Fast486CallGate(State, (PFAST486_CALL_GATE)&Descriptor, Call);
+
+ /* The gate has been processed here, so return FALSE */
return FALSE;
}
Modified: trunk/reactos/lib/fast486/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opcodes.c?rev=…
==============================================================================
--- trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] Mon May 4 19:14:23 2015
@@ -4707,17 +4707,6 @@
return;
}
- /* Load the new CS */
- if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
- {
- /* Exception occurred */
- return;
- }
-
- /* Set EIP */
- if (Size) State->InstPtr.Long = InstPtr;
- else State->InstPtr.LowWord = LOWORD(InstPtr);
-
if (GET_SEGMENT_RPL(CodeSel) > OldCpl)
{
/* Pop ESP */
@@ -4734,6 +4723,17 @@
return;
}
}
+
+ /* Load the new CS */
+ if (!Fast486LoadSegment(State, FAST486_REG_CS, CodeSel))
+ {
+ /* Exception occurred */
+ return;
+ }
+
+ /* Set EIP */
+ if (Size) State->InstPtr.Long = InstPtr;
+ else State->InstPtr.LowWord = LOWORD(InstPtr);
/* Update the CPL */
State->Cpl = GET_SEGMENT_RPL(CodeSel);