[SOFT386]

Start implementing call gate support.
Implement the direct far call opcode (0x9A).


svn path=/branches/ntvdm/; revision=60685
This commit is contained in:
Aleksandar Andrejevic 2013-10-16 00:41:24 +00:00
parent 2f4594cf30
commit 4b14d9a672
3 changed files with 106 additions and 4 deletions

View file

@ -228,6 +228,19 @@ typedef struct
ULONG BaseHigh : 8;
} SOFT386_GDT_ENTRY, *PSOFT386_GDT_ENTRY;
typedef struct
{
ULONG Offset : 16;
ULONG Selector : 16;
ULONG ParamCount : 5;
ULONG Reserved : 3;
ULONG Type : 4;
ULONG SystemType : 1;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG OffsetHigh : 16;
} SOFT386_CALL_GATE, *PSOFT386_CALL_GATE;
typedef struct
{
ULONG Offset : 16;

View file

@ -202,15 +202,23 @@ Soft386LoadSegment(PSOFT386_STATE State,
sizeof(GdtEntry));
}
/* Check if we are loading SS */
if (Segment == SOFT386_REG_SS)
{
/* Loading the stack segment */
if (GET_SEGMENT_INDEX(Selector) == 0)
{
Soft386Exception(State, SOFT386_EXCEPTION_GP);
return FALSE;
}
if (!GdtEntry.SystemType)
{
/* This is a special descriptor */
Soft386Exception(State, SOFT386_EXCEPTION_GP);
return FALSE;
}
if (GdtEntry.Executable || !GdtEntry.ReadWrite)
{
Soft386Exception(State, SOFT386_EXCEPTION_GP);
@ -230,8 +238,22 @@ Soft386LoadSegment(PSOFT386_STATE State,
return FALSE;
}
}
else if (Segment == SOFT386_REG_CS)
{
/* Loading the code segment */
// TODO: NOT IMPLEMENTED
}
else
{
/* Loading a data segment */
if (!GdtEntry.SystemType)
{
/* This is a special descriptor */
Soft386Exception(State, SOFT386_EXCEPTION_GP);
return FALSE;
}
if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
&& (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl))
{

View file

@ -4612,10 +4612,77 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq)
SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
{
// TODO: NOT IMPLEMENTED
UNIMPLEMENTED;
USHORT Segment = 0;
ULONG Offset = 0;
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
return FALSE;
/* Make sure this is the right instruction */
ASSERT(Opcode == 0x9A);
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
return FALSE;
}
/* Fetch the offset */
if (Size)
{
if (!Soft386FetchDword(State, &Offset))
{
/* Exception occurred */
return FALSE;
}
}
else
{
if (!Soft386FetchWord(State, (PUSHORT)&Offset))
{
/* Exception occurred */
return FALSE;
}
}
/* Fetch the segment */
if (!Soft386FetchWord(State, &Segment))
{
/* Exception occurred */
return FALSE;
}
/* Push the current code segment selector */
if (!Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector))
{
/* Exception occurred */
return FALSE;
}
/* Push the current value of the instruction pointer */
if (!Soft386StackPush(State, State->InstPtr.Long))
{
/* Exception occurred */
return FALSE;
}
/* Load the new CS */
if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
{
/* Exception occurred */
return FALSE;
}
/* Load new (E)IP */
if (Size) State->InstPtr.Long = Offset;
else State->InstPtr.LowWord = LOWORD(Offset);
return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)