mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 11:57:01 +00:00
[SOFT386]
Implement Soft386ReadMemory, Soft386WriteMemory, Soft386StackPush and Soft386StackPop. svn path=/branches/ntvdm/; revision=59760
This commit is contained in:
parent
fb158ecbe1
commit
c7b66d26f6
4 changed files with 371 additions and 2 deletions
|
@ -1,6 +1,7 @@
|
|||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/soft386)
|
||||
|
||||
list(APPEND SOURCE
|
||||
soft386.c)
|
||||
soft386.c
|
||||
common.c)
|
||||
|
||||
add_library(soft386 ${SOURCE})
|
||||
|
|
302
lib/soft386/common.c
Normal file
302
lib/soft386/common.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* PROJECT: 386/486 CPU Emulation Library
|
||||
* FILE: common.c
|
||||
* PURPOSE: Common functions used internally by Soft386.
|
||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386ReadMemory(PSOFT386_STATE State,
|
||||
INT SegmentReg,
|
||||
ULONG Offset,
|
||||
BOOLEAN InstFetch,
|
||||
PVOID Buffer,
|
||||
ULONG Size)
|
||||
{
|
||||
ULONG LinearAddress;
|
||||
PSOFT386_SEG_REG CachedDescriptor;
|
||||
|
||||
ASSERT(SegmentReg < SOFT386_NUM_SEG_REGS);
|
||||
|
||||
/* Get the cached descriptor */
|
||||
CachedDescriptor = &State->SegmentRegs[SegmentReg];
|
||||
|
||||
if ((Offset + Size) >= CachedDescriptor->Limit)
|
||||
{
|
||||
/* Read beyond limit */
|
||||
// TODO: Generate exception #GP
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check for protected mode */
|
||||
if (State->ControlRegisters[0] & SOFT386_CR0_PE)
|
||||
{
|
||||
/* Privilege checks */
|
||||
|
||||
if (!CachedDescriptor->Present)
|
||||
{
|
||||
// TODO: Generate exception #NP
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
||||
{
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (InstFetch)
|
||||
{
|
||||
if (!CachedDescriptor->Executable)
|
||||
{
|
||||
/* Data segment not executable */
|
||||
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CachedDescriptor->Executable && (!CachedDescriptor->ReadWrite))
|
||||
{
|
||||
/* Code segment not readable */
|
||||
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the linear address */
|
||||
LinearAddress = CachedDescriptor->Base + Offset;
|
||||
|
||||
// TODO: Paging support!
|
||||
|
||||
/* Did the host provide a memory hook? */
|
||||
if (State->MemReadCallback)
|
||||
{
|
||||
/* Yes, call the host */
|
||||
State->MemReadCallback(State, LinearAddress, Buffer, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the memory directly */
|
||||
RtlMoveMemory(Buffer, (LPVOID)LinearAddress, Size);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386WriteMemory(PSOFT386_STATE State,
|
||||
INT SegmentReg,
|
||||
ULONG Offset,
|
||||
PVOID Buffer,
|
||||
ULONG Size)
|
||||
{
|
||||
ULONG LinearAddress;
|
||||
PSOFT386_SEG_REG CachedDescriptor;
|
||||
|
||||
ASSERT(SegmentReg < SOFT386_NUM_SEG_REGS);
|
||||
|
||||
/* Get the cached descriptor */
|
||||
CachedDescriptor = &State->SegmentRegs[SegmentReg];
|
||||
|
||||
if ((Offset + Size) >= CachedDescriptor->Limit)
|
||||
{
|
||||
/* Write beyond limit */
|
||||
// TODO: Generate exception #GP
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check for protected mode */
|
||||
if (State->ControlRegisters[0] & SOFT386_CR0_PE)
|
||||
{
|
||||
/* Privilege checks */
|
||||
|
||||
if (!CachedDescriptor->Present)
|
||||
{
|
||||
// TODO: Generate exception #NP
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
||||
{
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (CachedDescriptor->Executable)
|
||||
{
|
||||
/* Code segment not writable */
|
||||
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
else if (!CachedDescriptor->ReadWrite)
|
||||
{
|
||||
/* Data segment not writeable */
|
||||
|
||||
// TODO: Generate exception #GP
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the linear address */
|
||||
LinearAddress = CachedDescriptor->Base + Offset;
|
||||
|
||||
// TODO: Paging support!
|
||||
|
||||
/* Did the host provide a memory hook? */
|
||||
if (State->MemWriteCallback)
|
||||
{
|
||||
/* Yes, call the host */
|
||||
State->MemWriteCallback(State, LinearAddress, Buffer, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write the memory directly */
|
||||
RtlMoveMemory((LPVOID)LinearAddress, Buffer, Size);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386StackPush(PSOFT386_STATE State, ULONG Value)
|
||||
{
|
||||
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
|
||||
|
||||
// TODO: Handle OPSIZE prefix.
|
||||
|
||||
if (Size)
|
||||
{
|
||||
/* 32-bit size */
|
||||
|
||||
/* Check if ESP is between 1 and 3 */
|
||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long >= 1
|
||||
&& State->GeneralRegs[SOFT386_REG_ESP].Long <= 3)
|
||||
{
|
||||
// TODO: Exception #SS
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Subtract ESP by 4 */
|
||||
State->GeneralRegs[SOFT386_REG_ESP].Long -= 4;
|
||||
|
||||
/* Store the value in SS:ESP */
|
||||
return Soft386WriteMemory(State,
|
||||
SOFT386_REG_SS,
|
||||
State->GeneralRegs[SOFT386_REG_ESP].Long,
|
||||
&Value,
|
||||
sizeof(ULONG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16-bit size */
|
||||
USHORT ShortValue = LOWORD(Value);
|
||||
|
||||
/* Check if SP is 1 */
|
||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 1)
|
||||
{
|
||||
// TODO: Exception #SS
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Subtract SP by 2 */
|
||||
State->GeneralRegs[SOFT386_REG_ESP].LowWord -= 2;
|
||||
|
||||
/* Store the value in SS:SP */
|
||||
return Soft386WriteMemory(State,
|
||||
SOFT386_REG_SS,
|
||||
State->GeneralRegs[SOFT386_REG_ESP].LowWord,
|
||||
&ShortValue,
|
||||
sizeof(USHORT));
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386StackPop(PSOFT386_STATE State, PULONG Value)
|
||||
{
|
||||
ULONG LongValue;
|
||||
USHORT ShortValue;
|
||||
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
|
||||
|
||||
// TODO: Handle OPSIZE prefix.
|
||||
|
||||
if (Size)
|
||||
{
|
||||
/* 32-bit size */
|
||||
|
||||
/* Check if ESP is 0xFFFFFFFF */
|
||||
if (State->GeneralRegs[SOFT386_REG_ESP].Long == 0xFFFFFFFF)
|
||||
{
|
||||
// TODO: Exception #SS
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read the value from SS:ESP */
|
||||
if (!Soft386ReadMemory(State,
|
||||
SOFT386_REG_SS,
|
||||
State->GeneralRegs[SOFT386_REG_ESP].Long,
|
||||
FALSE,
|
||||
&LongValue,
|
||||
sizeof(LongValue)))
|
||||
{
|
||||
/* An exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Increment ESP by 4 */
|
||||
State->GeneralRegs[SOFT386_REG_ESP].Long += 4;
|
||||
|
||||
/* Store the value in the result */
|
||||
*Value = LongValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 16-bit size */
|
||||
|
||||
/* Check if SP is 0xFFFF */
|
||||
if (State->GeneralRegs[SOFT386_REG_ESP].LowWord == 0xFFFF)
|
||||
{
|
||||
// TODO: Exception #SS
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read the value from SS:SP */
|
||||
if (!Soft386ReadMemory(State,
|
||||
SOFT386_REG_SS,
|
||||
State->GeneralRegs[SOFT386_REG_ESP].LowWord,
|
||||
FALSE,
|
||||
&ShortValue,
|
||||
sizeof(ShortValue)))
|
||||
{
|
||||
/* An exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Increment SP by 2 */
|
||||
State->GeneralRegs[SOFT386_REG_ESP].Long += 2;
|
||||
|
||||
/* Store the value in the result */
|
||||
*Value = ShortValue;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
63
lib/soft386/common.h
Normal file
63
lib/soft386/common.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||
* PROJECT: 386/486 CPU Emulation Library
|
||||
* FILE: common.h
|
||||
* PURPOSE: Common functions used internally by Soft386 (header file).
|
||||
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <soft386.h>
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
#define GET_SEGMENT_DPL(s) ((s) & 3)
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386ReadMemory
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
INT SegmentReg,
|
||||
ULONG Offset,
|
||||
BOOLEAN InstFetch,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386WriteMemory
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
INT SegmentReg,
|
||||
ULONG Offset,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386StackPush
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
ULONG Value
|
||||
);
|
||||
|
||||
inline
|
||||
BOOLEAN
|
||||
Soft386StackPop
|
||||
(
|
||||
PSOFT386_STATE State,
|
||||
PULONG Value
|
||||
);
|
||||
|
||||
#endif // _COMMON_H_
|
||||
|
||||
/* EOF */
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "soft386.h"
|
||||
#include "common.h"
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
|
@ -23,6 +23,7 @@ typedef enum
|
|||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static
|
||||
inline
|
||||
VOID
|
||||
NTAPI
|
||||
Soft386ExecutionControl(PSOFT386_STATE State, INT Command)
|
||||
|
@ -210,3 +211,5 @@ Soft386Interrupt(PSOFT386_STATE State, UCHAR Number)
|
|||
// TODO: NOT IMPLEMENTED!!!
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue