mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:56:31 +00:00
[SOFT386]
Halfplement the IRET instruction (everything except task switching). svn path=/branches/ntvdm/; revision=60392
This commit is contained in:
parent
e05e583e56
commit
78e8653765
3 changed files with 217 additions and 4 deletions
|
@ -18,6 +18,8 @@
|
||||||
#define SIGN_FLAG_BYTE 0x80
|
#define SIGN_FLAG_BYTE 0x80
|
||||||
#define SIGN_FLAG_WORD 0x8000
|
#define SIGN_FLAG_WORD 0x8000
|
||||||
#define SIGN_FLAG_LONG 0x80000000
|
#define SIGN_FLAG_LONG 0x80000000
|
||||||
|
#define REAL_MODE_FLAGS_MASK 0x17FD5
|
||||||
|
#define PROT_MODE_FLAGS_MASK 0x10DD5
|
||||||
|
|
||||||
#define GET_SEGMENT_RPL(s) ((s) & 3)
|
#define GET_SEGMENT_RPL(s) ((s) & 3)
|
||||||
#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
|
#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
|
||||||
|
|
|
@ -162,7 +162,7 @@ Soft386LoadSegment(PSOFT386_STATE State,
|
||||||
CachedDescriptor = &State->SegmentRegs[Segment];
|
CachedDescriptor = &State->SegmentRegs[Segment];
|
||||||
|
|
||||||
/* Check for protected mode */
|
/* Check for protected mode */
|
||||||
if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
|
if ((State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE) && !State->Flags.Vm)
|
||||||
{
|
{
|
||||||
/* Make sure the GDT contains the entry */
|
/* Make sure the GDT contains the entry */
|
||||||
if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
|
if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
|
||||||
|
|
|
@ -4690,10 +4690,221 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeInt)
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
INT i;
|
||||||
UNIMPLEMENTED;
|
ULONG InstPtr, CodeSel, StackPtr, StackSel;
|
||||||
|
SOFT386_FLAGS_REG NewFlags;
|
||||||
|
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
|
||||||
|
|
||||||
return FALSE;
|
/* Make sure this is the right instruction */
|
||||||
|
ASSERT(Opcode == 0xCF);
|
||||||
|
|
||||||
|
if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
|
||||||
|
{
|
||||||
|
/* Invalid prefix */
|
||||||
|
Soft386Exception(State, SOFT386_EXCEPTION_UD);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
|
||||||
|
{
|
||||||
|
/* The OPSIZE prefix toggles the size */
|
||||||
|
Size = !Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop EIP */
|
||||||
|
if (!Soft386StackPop(State, &InstPtr))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop CS */
|
||||||
|
if (!Soft386StackPop(State, &CodeSel))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop EFLAGS */
|
||||||
|
if (!Soft386StackPop(State, &NewFlags.Long))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for protected mode */
|
||||||
|
if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
|
||||||
|
{
|
||||||
|
INT Cpl = Soft386GetCurrentPrivLevel(State);
|
||||||
|
|
||||||
|
if (State->Flags.Vm)
|
||||||
|
{
|
||||||
|
/* Return from VM86 mode */
|
||||||
|
|
||||||
|
/* Check the IOPL */
|
||||||
|
if (State->Flags.Iopl == 3)
|
||||||
|
{
|
||||||
|
/* Set new EIP */
|
||||||
|
State->InstPtr.Long = LOWORD(InstPtr);
|
||||||
|
|
||||||
|
/* Load new CS */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new flags */
|
||||||
|
if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
|
||||||
|
else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
|
||||||
|
State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
|
||||||
|
State->Flags.Iopl = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Call the VM86 monitor */
|
||||||
|
Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State->Flags.Nt)
|
||||||
|
{
|
||||||
|
/* Nested task return */
|
||||||
|
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewFlags.Vm)
|
||||||
|
{
|
||||||
|
/* Return to VM86 mode */
|
||||||
|
ULONG Es, Ds, Fs, Gs;
|
||||||
|
|
||||||
|
/* Pop ESP, SS, ES, FS, GS */
|
||||||
|
if (!Soft386StackPop(State, &StackPtr)) return FALSE;
|
||||||
|
if (!Soft386StackPop(State, &StackSel)) return FALSE;
|
||||||
|
if (!Soft386StackPop(State, &Es)) return FALSE;
|
||||||
|
if (!Soft386StackPop(State, &Ds)) return FALSE;
|
||||||
|
if (!Soft386StackPop(State, &Fs)) return FALSE;
|
||||||
|
if (!Soft386StackPop(State, &Gs)) return FALSE;
|
||||||
|
|
||||||
|
/* Load the new segments */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel)) return FALSE;
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_SS, StackSel)) return FALSE;
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_ES, Es)) return FALSE;
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_DS, Ds)) return FALSE;
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_FS, Fs)) return FALSE;
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_GS, Gs)) return FALSE;
|
||||||
|
|
||||||
|
/* Set the new IP */
|
||||||
|
State->InstPtr.Long = LOWORD(InstPtr);
|
||||||
|
|
||||||
|
/* Set the new flags */
|
||||||
|
if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
|
||||||
|
else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
|
||||||
|
State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the new CS */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set EIP */
|
||||||
|
if (Size) State->InstPtr.Long = InstPtr;
|
||||||
|
else State->InstPtr.LowWord = LOWORD(InstPtr);
|
||||||
|
|
||||||
|
if (GET_SEGMENT_RPL(CodeSel) > Cpl)
|
||||||
|
{
|
||||||
|
/* Pop ESP */
|
||||||
|
if (!Soft386StackPop(State, &StackPtr))
|
||||||
|
{
|
||||||
|
/* Exception */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop SS */
|
||||||
|
if (!Soft386StackPop(State, &StackSel))
|
||||||
|
{
|
||||||
|
/* Exception */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load new SS */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_SS, StackSel))
|
||||||
|
{
|
||||||
|
/* Exception */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set ESP */
|
||||||
|
if (Size) State->GeneralRegs[SOFT386_REG_ESP].Long = StackPtr;
|
||||||
|
else State->GeneralRegs[SOFT386_REG_ESP].LowWord = LOWORD(StackPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new flags */
|
||||||
|
if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
|
||||||
|
else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
|
||||||
|
State->Flags.AlwaysSet = TRUE;
|
||||||
|
|
||||||
|
/* Set additional flags */
|
||||||
|
if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
|
||||||
|
if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
|
||||||
|
|
||||||
|
if (GET_SEGMENT_RPL(CodeSel) > Cpl)
|
||||||
|
{
|
||||||
|
/* Update the CPL */
|
||||||
|
Cpl = Soft386GetCurrentPrivLevel(State);
|
||||||
|
|
||||||
|
/* Check segment security */
|
||||||
|
for (i = 0; i <= SOFT386_NUM_SEG_REGS; i++)
|
||||||
|
{
|
||||||
|
/* Don't check CS or SS */
|
||||||
|
if ((i == SOFT386_REG_CS) || (i == SOFT386_REG_SS)) continue;
|
||||||
|
|
||||||
|
if ((Cpl > State->SegmentRegs[i].Dpl)
|
||||||
|
&& (!State->SegmentRegs[i].Executable
|
||||||
|
|| !State->SegmentRegs[i].DirConf))
|
||||||
|
{
|
||||||
|
/* Load the NULL descriptor in the segment */
|
||||||
|
if (!Soft386LoadSegment(State, i, 0)) return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Size && (InstPtr & 0xFFFF0000))
|
||||||
|
{
|
||||||
|
/* Invalid */
|
||||||
|
Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set new EIP */
|
||||||
|
State->InstPtr.Long = InstPtr;
|
||||||
|
|
||||||
|
/* Load new CS */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the new flags */
|
||||||
|
if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
|
||||||
|
else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
|
||||||
|
State->Flags.AlwaysSet = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeAam)
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeAam)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue