mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 18:35:32 +00:00
[SOFT386]
Implement instruction fetch functions. Implement CPU exception system. svn path=/branches/ntvdm/; revision=59782
This commit is contained in:
parent
2672ec8ee5
commit
6f769d6314
|
@ -28,6 +28,12 @@
|
||||||
#define SOFT386_CR0_CD (1 << 30)
|
#define SOFT386_CR0_CD (1 << 30)
|
||||||
#define SOFT386_CR0_PG (1 << 31)
|
#define SOFT386_CR0_PG (1 << 31)
|
||||||
|
|
||||||
|
#define SOFT386_IDT_TASK_GATE 0x5
|
||||||
|
#define SOFT386_IDT_INT_GATE 0x6
|
||||||
|
#define SOFT386_IDT_TRAP_GATE 0x7
|
||||||
|
#define SOFT386_IDT_INT_GATE_32 0xE
|
||||||
|
#define SOFT386_IDT_TRAP_GATE_32 0xF
|
||||||
|
|
||||||
struct _SOFT386_STATE;
|
struct _SOFT386_STATE;
|
||||||
typedef struct _SOFT386_STATE SOFT386_STATE, *PSOFT386_STATE;
|
typedef struct _SOFT386_STATE SOFT386_STATE, *PSOFT386_STATE;
|
||||||
|
|
||||||
|
@ -77,6 +83,26 @@ enum _SOFT386_DBG_REGS
|
||||||
SOFT386_REG_DR7
|
SOFT386_REG_DR7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum _SOFT386_EXCEPTIONS
|
||||||
|
{
|
||||||
|
SOFT386_EXCEPTION_DE = 0x00,
|
||||||
|
SOFT386_EXCEPTION_DB = 0x01,
|
||||||
|
SOFT386_EXCEPTION_BP = 0x03,
|
||||||
|
SOFT386_EXCEPTION_OF = 0x04,
|
||||||
|
SOFT386_EXCEPTION_BR = 0x05,
|
||||||
|
SOFT386_EXCEPTION_UD = 0x06,
|
||||||
|
SOFT386_EXCEPTION_NM = 0x07,
|
||||||
|
SOFT386_EXCEPTION_DF = 0x08,
|
||||||
|
SOFT386_EXCEPTION_TS = 0x0A,
|
||||||
|
SOFT386_EXCEPTION_NP = 0x0B,
|
||||||
|
SOFT386_EXCEPTION_SS = 0x0C,
|
||||||
|
SOFT386_EXCEPTION_GP = 0x0D,
|
||||||
|
SOFT386_EXCEPTION_PF = 0x0E,
|
||||||
|
SOFT386_EXCEPTION_MF = 0x10,
|
||||||
|
SOFT386_EXCEPTION_AC = 0x11,
|
||||||
|
SOFT386_EXCEPTION_MC = 0x12
|
||||||
|
};
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
(NTAPI *SOFT386_MEM_READ_PROC)
|
(NTAPI *SOFT386_MEM_READ_PROC)
|
||||||
|
@ -162,7 +188,7 @@ typedef struct
|
||||||
ULONG Size : 1;
|
ULONG Size : 1;
|
||||||
ULONG Granularity : 1;
|
ULONG Granularity : 1;
|
||||||
ULONG BaseHigh : 8;
|
ULONG BaseHigh : 8;
|
||||||
} SOFT386_GDT_ENTRY;
|
} SOFT386_GDT_ENTRY, *PSOFT386_GDT_ENTRY;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -174,12 +200,12 @@ typedef struct
|
||||||
ULONG Dpl : 2;
|
ULONG Dpl : 2;
|
||||||
ULONG Present : 1;
|
ULONG Present : 1;
|
||||||
ULONG OffsetHigh : 16;
|
ULONG OffsetHigh : 16;
|
||||||
} SOFT386_IDT_ENTRY;
|
} SOFT386_IDT_ENTRY, *PSOFT386_IDT_ENTRY;
|
||||||
|
|
||||||
typedef struct _SOFT386_TABLE_REG
|
typedef struct _SOFT386_TABLE_REG
|
||||||
{
|
{
|
||||||
USHORT Size;
|
USHORT Size;
|
||||||
ULONG Address;
|
ULONG Address;
|
||||||
} SOFT386_TABLE_REG, *PSOFT386_TABLE_REG;
|
} SOFT386_TABLE_REG, *PSOFT386_TABLE_REG;
|
||||||
|
|
||||||
typedef union _SOFT386_FLAGS_REG
|
typedef union _SOFT386_FLAGS_REG
|
||||||
|
@ -255,6 +281,7 @@ struct _SOFT386_STATE
|
||||||
ULONGLONG TimeStampCounter;
|
ULONGLONG TimeStampCounter;
|
||||||
ULONG ControlRegisters[SOFT386_NUM_CTRL_REGS];
|
ULONG ControlRegisters[SOFT386_NUM_CTRL_REGS];
|
||||||
ULONG DebugRegisters[SOFT386_NUM_DBG_REGS];
|
ULONG DebugRegisters[SOFT386_NUM_DBG_REGS];
|
||||||
|
ULONG ExceptionCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
|
@ -50,7 +50,7 @@ Soft386ReadMemory(PSOFT386_STATE State,
|
||||||
if ((Offset + Size) >= CachedDescriptor->Limit)
|
if ((Offset + Size) >= CachedDescriptor->Limit)
|
||||||
{
|
{
|
||||||
/* Read beyond limit */
|
/* Read beyond limit */
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -62,13 +62,13 @@ Soft386ReadMemory(PSOFT386_STATE State,
|
||||||
|
|
||||||
if (!CachedDescriptor->Present)
|
if (!CachedDescriptor->Present)
|
||||||
{
|
{
|
||||||
// TODO: Generate exception #NP
|
Soft386Exception(State, SOFT386_EXCEPTION_NP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
||||||
{
|
{
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ Soft386ReadMemory(PSOFT386_STATE State,
|
||||||
{
|
{
|
||||||
/* Data segment not executable */
|
/* Data segment not executable */
|
||||||
|
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ Soft386ReadMemory(PSOFT386_STATE State,
|
||||||
{
|
{
|
||||||
/* Code segment not readable */
|
/* Code segment not readable */
|
||||||
|
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ Soft386WriteMemory(PSOFT386_STATE State,
|
||||||
if ((Offset + Size) >= CachedDescriptor->Limit)
|
if ((Offset + Size) >= CachedDescriptor->Limit)
|
||||||
{
|
{
|
||||||
/* Write beyond limit */
|
/* Write beyond limit */
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -145,13 +145,13 @@ Soft386WriteMemory(PSOFT386_STATE State,
|
||||||
|
|
||||||
if (!CachedDescriptor->Present)
|
if (!CachedDescriptor->Present)
|
||||||
{
|
{
|
||||||
// TODO: Generate exception #NP
|
Soft386Exception(State, SOFT386_EXCEPTION_NP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
||||||
{
|
{
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,14 +159,14 @@ Soft386WriteMemory(PSOFT386_STATE State,
|
||||||
{
|
{
|
||||||
/* Code segment not writable */
|
/* Code segment not writable */
|
||||||
|
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (!CachedDescriptor->ReadWrite)
|
else if (!CachedDescriptor->ReadWrite)
|
||||||
{
|
{
|
||||||
/* Data segment not writeable */
|
/* Data segment not writeable */
|
||||||
|
|
||||||
// TODO: Generate exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ Soft386StackPush(PSOFT386_STATE State, ULONG Value)
|
||||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long >= 1
|
if (State->GeneralRegs[SOFT386_REG_ESP].Long >= 1
|
||||||
&& State->GeneralRegs[SOFT386_REG_ESP].Long <= 3)
|
&& State->GeneralRegs[SOFT386_REG_ESP].Long <= 3)
|
||||||
{
|
{
|
||||||
// TODO: Exception #SS
|
Soft386Exception(State, SOFT386_EXCEPTION_SS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ Soft386StackPush(PSOFT386_STATE State, ULONG Value)
|
||||||
/* Check if SP is 1 */
|
/* Check if SP is 1 */
|
||||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 1)
|
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 1)
|
||||||
{
|
{
|
||||||
// TODO: Exception #SS
|
Soft386Exception(State, SOFT386_EXCEPTION_SS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ Soft386StackPop(PSOFT386_STATE State, PULONG Value)
|
||||||
/* Check if ESP is 0xFFFFFFFF */
|
/* Check if ESP is 0xFFFFFFFF */
|
||||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 0xFFFFFFFF)
|
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
// TODO: Exception #SS
|
Soft386Exception(State, SOFT386_EXCEPTION_SS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ Soft386StackPop(PSOFT386_STATE State, PULONG Value)
|
||||||
/* Check if SP is 0xFFFF */
|
/* Check if SP is 0xFFFF */
|
||||||
if (State->GeneralRegs[SOFT386_REG_ESP].LowWord == 0xFFFF)
|
if (State->GeneralRegs[SOFT386_REG_ESP].LowWord == 0xFFFF)
|
||||||
{
|
{
|
||||||
// TODO: Exception #SS
|
Soft386Exception(State, SOFT386_EXCEPTION_SS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ Soft386StackPop(PSOFT386_STATE State, PULONG Value)
|
||||||
|
|
||||||
inline
|
inline
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
|
Soft386LoadSegment(PSOFT386_STATE State, INT Segment, USHORT Selector)
|
||||||
{
|
{
|
||||||
PSOFT386_SEG_REG CachedDescriptor;
|
PSOFT386_SEG_REG CachedDescriptor;
|
||||||
SOFT386_GDT_ENTRY GdtEntry;
|
SOFT386_GDT_ENTRY GdtEntry;
|
||||||
|
@ -335,7 +335,7 @@ Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
|
||||||
/* 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))
|
||||||
{
|
{
|
||||||
// TODO: Exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,26 +362,26 @@ Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
|
||||||
{
|
{
|
||||||
if (GET_SEGMENT_INDEX(Selector) == 0)
|
if (GET_SEGMENT_INDEX(Selector) == 0)
|
||||||
{
|
{
|
||||||
// TODO: Exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GdtEntry.Executable || !GdtEntry.ReadWrite)
|
if (GdtEntry.Executable || !GdtEntry.ReadWrite)
|
||||||
{
|
{
|
||||||
// TODO: Exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((GET_SEGMENT_RPL(Selector) != Soft386GetCurrentPrivLevel(State))
|
if ((GET_SEGMENT_RPL(Selector) != Soft386GetCurrentPrivLevel(State))
|
||||||
|| (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl))
|
|| (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl))
|
||||||
{
|
{
|
||||||
// TODO: Exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GdtEntry.Present)
|
if (!GdtEntry.Present)
|
||||||
{
|
{
|
||||||
// TODO: Exception #SS
|
Soft386Exception(State, SOFT386_EXCEPTION_SS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,13 +390,13 @@ Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
|
||||||
if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
|
if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
|
||||||
&& (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl))
|
&& (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl))
|
||||||
{
|
{
|
||||||
// TODO: Exception #GP
|
Soft386Exception(State, SOFT386_EXCEPTION_GP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GdtEntry.Present)
|
if (!GdtEntry.Present)
|
||||||
{
|
{
|
||||||
// TODO: Exception #NP
|
Soft386Exception(State, SOFT386_EXCEPTION_NP);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,4 +427,329 @@ Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchByte(PSOFT386_STATE State, PUCHAR Data)
|
||||||
|
{
|
||||||
|
PSOFT386_SEG_REG CachedDescriptor;
|
||||||
|
|
||||||
|
/* Get the cached descriptor of CS */
|
||||||
|
CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS];
|
||||||
|
|
||||||
|
/* Read from memory */
|
||||||
|
if (!Soft386ReadMemory(State,
|
||||||
|
SOFT386_REG_CS,
|
||||||
|
(CachedDescriptor->Size) ? State->InstPtr.Long
|
||||||
|
: State->InstPtr.LowWord,
|
||||||
|
TRUE,
|
||||||
|
Data,
|
||||||
|
sizeof(UCHAR)))
|
||||||
|
{
|
||||||
|
/* Exception occurred during instruction fetch */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance the instruction pointer */
|
||||||
|
if (CachedDescriptor->Size) State->InstPtr.Long++;
|
||||||
|
else State->InstPtr.LowWord++;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchWord(PSOFT386_STATE State, PUSHORT Data)
|
||||||
|
{
|
||||||
|
PSOFT386_SEG_REG CachedDescriptor;
|
||||||
|
|
||||||
|
/* Get the cached descriptor of CS */
|
||||||
|
CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS];
|
||||||
|
|
||||||
|
/* Read from memory */
|
||||||
|
// FIXME: Fix byte order on big-endian machines
|
||||||
|
if (!Soft386ReadMemory(State,
|
||||||
|
SOFT386_REG_CS,
|
||||||
|
(CachedDescriptor->Size) ? State->InstPtr.Long
|
||||||
|
: State->InstPtr.LowWord,
|
||||||
|
TRUE,
|
||||||
|
Data,
|
||||||
|
sizeof(USHORT)))
|
||||||
|
{
|
||||||
|
/* Exception occurred during instruction fetch */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance the instruction pointer */
|
||||||
|
if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(USHORT);
|
||||||
|
else State->InstPtr.LowWord += sizeof(USHORT);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchDword(PSOFT386_STATE State, PULONG Data)
|
||||||
|
{
|
||||||
|
PSOFT386_SEG_REG CachedDescriptor;
|
||||||
|
|
||||||
|
/* Get the cached descriptor of CS */
|
||||||
|
CachedDescriptor = &State->SegmentRegs[SOFT386_REG_CS];
|
||||||
|
|
||||||
|
/* Read from memory */
|
||||||
|
// FIXME: Fix byte order on big-endian machines
|
||||||
|
if (!Soft386ReadMemory(State,
|
||||||
|
SOFT386_REG_CS,
|
||||||
|
(CachedDescriptor->Size) ? State->InstPtr.Long
|
||||||
|
: State->InstPtr.LowWord,
|
||||||
|
TRUE,
|
||||||
|
Data,
|
||||||
|
sizeof(ULONG)))
|
||||||
|
{
|
||||||
|
/* Exception occurred during instruction fetch */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance the instruction pointer */
|
||||||
|
if (CachedDescriptor->Size) State->InstPtr.Long += sizeof(ULONG);
|
||||||
|
else State->InstPtr.LowWord += sizeof(ULONG);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386InterruptInternal(PSOFT386_STATE State,
|
||||||
|
USHORT SegmentSelector,
|
||||||
|
ULONG Offset,
|
||||||
|
BOOLEAN InterruptGate)
|
||||||
|
{
|
||||||
|
/* Check for protected mode */
|
||||||
|
if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
|
||||||
|
{
|
||||||
|
SOFT386_TSS Tss;
|
||||||
|
USHORT OldSs = State->SegmentRegs[SOFT386_REG_SS].Selector;
|
||||||
|
ULONG OldEsp = State->GeneralRegs[SOFT386_REG_ESP].Long;
|
||||||
|
|
||||||
|
/* Check if the interrupt handler is more privileged */
|
||||||
|
if (Soft386GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
|
||||||
|
{
|
||||||
|
/* Read the TSS */
|
||||||
|
// FIXME: This code is only correct when paging is disabled!!!
|
||||||
|
if (State->MemReadCallback)
|
||||||
|
{
|
||||||
|
State->MemReadCallback(State,
|
||||||
|
State->Tss.Address,
|
||||||
|
&Tss,
|
||||||
|
sizeof(Tss));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlMoveMemory(&Tss, (PVOID)State->Tss.Address, sizeof(Tss));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the new (higher) privilege level */
|
||||||
|
switch (GET_SEGMENT_RPL(SegmentSelector))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_SS, Tss.Ss0))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
State->GeneralRegs[SOFT386_REG_ESP].Long = Tss.Esp0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_SS, Tss.Ss1))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
State->GeneralRegs[SOFT386_REG_ESP].Long = Tss.Esp1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_SS, Tss.Ss2))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
State->GeneralRegs[SOFT386_REG_ESP].Long = Tss.Esp2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Should never reach here! */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push SS selector */
|
||||||
|
if (!Soft386StackPush(State, OldSs)) return FALSE;
|
||||||
|
|
||||||
|
/* Push stack pointer */
|
||||||
|
if (Soft386StackPush(State, OldEsp)) return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push EFLAGS */
|
||||||
|
if (!Soft386StackPush(State, State->Flags.Long)) return FALSE;
|
||||||
|
|
||||||
|
/* Push CS selector */
|
||||||
|
if (!Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector)) return FALSE;
|
||||||
|
|
||||||
|
/* Push the instruction pointer */
|
||||||
|
if (!Soft386StackPush(State, State->InstPtr.Long)) return FALSE;
|
||||||
|
|
||||||
|
if (InterruptGate)
|
||||||
|
{
|
||||||
|
/* Disable interrupts after a jump to an interrupt gate handler */
|
||||||
|
State->Flags.If = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load new CS */
|
||||||
|
if (!Soft386LoadSegment(State, SOFT386_REG_CS, SegmentSelector))
|
||||||
|
{
|
||||||
|
/* An exception occurred during the jump */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State->SegmentRegs[SOFT386_REG_CS].Size)
|
||||||
|
{
|
||||||
|
/* 32-bit code segment, use EIP */
|
||||||
|
State->InstPtr.Long = Offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 16-bit code segment, use IP */
|
||||||
|
State->InstPtr.LowWord = LOWORD(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386GetIntVector(PSOFT386_STATE State,
|
||||||
|
UCHAR Number,
|
||||||
|
PSOFT386_IDT_ENTRY IdtEntry)
|
||||||
|
{
|
||||||
|
ULONG FarPointer;
|
||||||
|
|
||||||
|
/* Check for protected mode */
|
||||||
|
if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
|
||||||
|
{
|
||||||
|
/* Read from the IDT */
|
||||||
|
// FIXME: This code is only correct when paging is disabled!!!
|
||||||
|
if (State->MemReadCallback)
|
||||||
|
{
|
||||||
|
State->MemReadCallback(State,
|
||||||
|
State->Idtr.Address
|
||||||
|
+ Number * sizeof(*IdtEntry),
|
||||||
|
IdtEntry,
|
||||||
|
sizeof(*IdtEntry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlMoveMemory(IdtEntry,
|
||||||
|
(PVOID)(State->Idtr.Address
|
||||||
|
+ Number * sizeof(*IdtEntry)),
|
||||||
|
sizeof(*IdtEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Read from the real-mode IVT */
|
||||||
|
|
||||||
|
/* Paging is always disabled in real mode */
|
||||||
|
if (State->MemReadCallback)
|
||||||
|
{
|
||||||
|
State->MemReadCallback(State,
|
||||||
|
State->Idtr.Address
|
||||||
|
+ Number * sizeof(FarPointer),
|
||||||
|
&FarPointer,
|
||||||
|
sizeof(FarPointer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RtlMoveMemory(IdtEntry,
|
||||||
|
(PVOID)(State->Idtr.Address
|
||||||
|
+ Number * sizeof(FarPointer)),
|
||||||
|
sizeof(FarPointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill a fake IDT entry */
|
||||||
|
IdtEntry->Offset = LOWORD(FarPointer);
|
||||||
|
IdtEntry->Selector = HIWORD(FarPointer);
|
||||||
|
IdtEntry->Zero = 0;
|
||||||
|
IdtEntry->Type = SOFT386_IDT_INT_GATE;
|
||||||
|
IdtEntry->Storage = FALSE;
|
||||||
|
IdtEntry->Dpl = 0;
|
||||||
|
IdtEntry->Present = TRUE;
|
||||||
|
IdtEntry->OffsetHigh = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once paging support is implemented this function
|
||||||
|
* will not always return true
|
||||||
|
*/
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
__fastcall
|
||||||
|
Soft386Exception(PSOFT386_STATE State, INT ExceptionCode)
|
||||||
|
{
|
||||||
|
SOFT386_IDT_ENTRY IdtEntry;
|
||||||
|
|
||||||
|
/* Increment the exception count */
|
||||||
|
State->ExceptionCount++;
|
||||||
|
|
||||||
|
/* Check if the exception occurred more than once */
|
||||||
|
if (State->ExceptionCount > 1)
|
||||||
|
{
|
||||||
|
/* Then this is a double fault */
|
||||||
|
ExceptionCode = SOFT386_EXCEPTION_DF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is a triple fault */
|
||||||
|
if (State->ExceptionCount == 3)
|
||||||
|
{
|
||||||
|
/* Reset the CPU */
|
||||||
|
Soft386Reset(State);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Soft386GetIntVector(State, ExceptionCode, &IdtEntry))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If this function failed, that means Soft386Exception
|
||||||
|
* was called again, so just return in this case.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the interrupt */
|
||||||
|
if (!Soft386InterruptInternal(State,
|
||||||
|
IdtEntry.Selector,
|
||||||
|
MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
|
||||||
|
IdtEntry.Type))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If this function failed, that means Soft386Exception
|
||||||
|
* was called again, so just return in this case.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -61,7 +61,58 @@ Soft386LoadSegment
|
||||||
(
|
(
|
||||||
PSOFT386_STATE State,
|
PSOFT386_STATE State,
|
||||||
INT Segment,
|
INT Segment,
|
||||||
WORD Selector
|
USHORT Selector
|
||||||
|
);
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchByte
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
PUCHAR Data
|
||||||
|
);
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchWord
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
PUSHORT Data
|
||||||
|
);
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386FetchDword
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
PULONG Data
|
||||||
|
);
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386InterruptInternal
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
USHORT SegmentSelector,
|
||||||
|
ULONG Offset,
|
||||||
|
BOOLEAN InterruptGate
|
||||||
|
);
|
||||||
|
|
||||||
|
inline
|
||||||
|
BOOLEAN
|
||||||
|
Soft386GetIntVector
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
UCHAR Number,
|
||||||
|
PSOFT386_IDT_ENTRY IdtEntry
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
__fastcall
|
||||||
|
Soft386Exception
|
||||||
|
(
|
||||||
|
PSOFT386_STATE State,
|
||||||
|
INT ExceptionCode
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif // _COMMON_H_
|
#endif // _COMMON_H_
|
||||||
|
|
Loading…
Reference in a new issue