mirror of
https://github.com/reactos/reactos.git
synced 2025-04-04 20:50:41 +00:00
[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). svn path=/trunk/; revision=67545
This commit is contained in:
parent
866f04e377
commit
ac4f5ac401
5 changed files with 368 additions and 146 deletions
|
@ -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)
|
||||
|
@ -354,6 +357,62 @@ typedef struct
|
|||
/* Verify the structure size */
|
||||
C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG));
|
||||
|
||||
typedef struct _FAST486_TSS
|
||||
{
|
||||
ULONG Link;
|
||||
ULONG Esp0;
|
||||
ULONG Ss0;
|
||||
ULONG Esp1;
|
||||
ULONG Ss1;
|
||||
ULONG Esp2;
|
||||
ULONG Ss2;
|
||||
ULONG Cr3;
|
||||
ULONG Eip;
|
||||
ULONG Eflags;
|
||||
ULONG Eax;
|
||||
ULONG Ecx;
|
||||
ULONG Edx;
|
||||
ULONG Ebx;
|
||||
ULONG Esp;
|
||||
ULONG Ebp;
|
||||
ULONG Esi;
|
||||
ULONG Edi;
|
||||
ULONG Es;
|
||||
ULONG Cs;
|
||||
ULONG Ss;
|
||||
ULONG Ds;
|
||||
ULONG Fs;
|
||||
ULONG Gs;
|
||||
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
|
||||
|
@ -392,36 +451,6 @@ typedef union _FAST486_FLAGS_REG
|
|||
};
|
||||
} FAST486_FLAGS_REG, *PFAST486_FLAGS_REG;
|
||||
|
||||
typedef struct _FAST486_TSS
|
||||
{
|
||||
ULONG Link;
|
||||
ULONG Esp0;
|
||||
ULONG Ss0;
|
||||
ULONG Esp1;
|
||||
ULONG Ss1;
|
||||
ULONG Esp2;
|
||||
ULONG Ss2;
|
||||
ULONG Cr3;
|
||||
ULONG Eip;
|
||||
ULONG Eflags;
|
||||
ULONG Eax;
|
||||
ULONG Ecx;
|
||||
ULONG Edx;
|
||||
ULONG Ebx;
|
||||
ULONG Esp;
|
||||
ULONG Ebp;
|
||||
ULONG Esi;
|
||||
ULONG Edi;
|
||||
ULONG Es;
|
||||
ULONG Cs;
|
||||
ULONG Ss;
|
||||
ULONG Ds;
|
||||
ULONG Fs;
|
||||
ULONG Gs;
|
||||
ULONG Ldtr;
|
||||
ULONG IopbOffset;
|
||||
} FAST486_TSS, *PFAST486_TSS;
|
||||
|
||||
typedef struct _FAST486_FPU_DATA_REG
|
||||
{
|
||||
ULONGLONG Mantissa;
|
||||
|
|
|
@ -292,38 +292,30 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
|||
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;
|
||||
if (!Fast486StackPushInternal(State, GateSize, OldSs)) return FALSE;
|
||||
|
||||
/* Push stack pointer */
|
||||
if (!Fast486StackPush(State, OldEsp)) goto Cleanup;
|
||||
/* Push the stack pointer */
|
||||
if (!Fast486StackPushInternal(State, GateSize, OldEsp)) return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State->SegmentRegs[FAST486_REG_CS].Size)
|
||||
/* Load new CS */
|
||||
if (!Fast486LoadSegment(State, FAST486_REG_CS, IdtEntry->Selector))
|
||||
{
|
||||
/* Set OPSIZE, because INT always pushes 16-bit values in real mode */
|
||||
State->PrefixFlags |= FAST486_PREFIX_OPSIZE;
|
||||
/* 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 (!Fast486StackPushInternal(State, GateSize, ErrorCode)) return FALSE;
|
||||
}
|
||||
|
||||
if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
|
||||
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 @@ Fast486TaskSwitch(PFAST486_STATE State, FAST486_TASK_SWITCH_TYPE Type, USHORT Se
|
|||
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 */
|
||||
|
|
|
@ -183,6 +183,15 @@ Fast486TaskSwitch
|
|||
USHORT Selector
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
Fast486CallGate
|
||||
(
|
||||
PFAST486_STATE State,
|
||||
PFAST486_CALL_GATE Gate,
|
||||
BOOLEAN Call
|
||||
);
|
||||
|
||||
/* INLINED FUNCTIONS **********************************************************/
|
||||
|
||||
#include "common.inl"
|
||||
|
|
|
@ -297,19 +297,12 @@ Fast486Exception(PFAST486_STATE State,
|
|||
FORCEINLINE
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
Fast486StackPush(PFAST486_STATE State,
|
||||
ULONG Value)
|
||||
Fast486StackPushInternal(PFAST486_STATE State, BOOLEAN Size, ULONG Value)
|
||||
{
|
||||
BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
|
||||
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 @@ Fast486StackPush(PFAST486_STATE State,
|
|||
}
|
||||
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 @@ Fast486StackPush(PFAST486_STATE State,
|
|||
State->SegmentRegs[FAST486_REG_SS].Size
|
||||
? StackPointer - sizeof(USHORT)
|
||||
: LOWORD(StackPointer - sizeof(USHORT)),
|
||||
&ShortValue,
|
||||
&Value,
|
||||
sizeof(USHORT)))
|
||||
{
|
||||
/* Exception occurred */
|
||||
|
@ -382,6 +372,20 @@ Fast486StackPush(PFAST486_STATE State,
|
|||
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
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
|
@ -778,12 +782,25 @@ Fast486ProcessGate(PFAST486_STATE State, USHORT Selector, ULONG Offset, BOOLEAN
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
case FAST486_CALL_GATE_16_SIGNATURE:
|
||||
case FAST486_CALL_GATE_SIGNATURE:
|
||||
{
|
||||
// TODO: NOT IMPLEMENTED
|
||||
UNIMPLEMENTED;
|
||||
if ((Descriptor.Dpl < Fast486GetCurrentPrivLevel(State))
|
||||
&& (Descriptor.Dpl < GET_SEGMENT_RPL(Selector)))
|
||||
{
|
||||
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Fast486Exception(State, FAST486_EXCEPTION_UD);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -4707,17 +4707,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
|
|||
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 */
|
||||
|
@ -4735,6 +4724,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeIret)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue