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/fast48... ============================================================================== --- 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=67... ============================================================================== --- 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=67... ============================================================================== --- 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=6... ============================================================================== --- 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);