[SOFT386]

Implement Soft386ReadMemory, Soft386WriteMemory, Soft386StackPush and Soft386StackPop.


svn path=/branches/ntvdm/; revision=59760
This commit is contained in:
Aleksandar Andrejevic 2013-08-17 15:20:47 +00:00
parent fb158ecbe1
commit c7b66d26f6
4 changed files with 371 additions and 2 deletions

View file

@ -1,6 +1,7 @@
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/soft386) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/soft386)
list(APPEND SOURCE list(APPEND SOURCE
soft386.c) soft386.c
common.c)
add_library(soft386 ${SOURCE}) add_library(soft386 ${SOURCE})

302
lib/soft386/common.c Normal file
View 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
View 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 */

View file

@ -8,7 +8,7 @@
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
#include "soft386.h" #include "common.h"
/* DEFINES ********************************************************************/ /* DEFINES ********************************************************************/
@ -23,6 +23,7 @@ typedef enum
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
static static
inline
VOID VOID
NTAPI NTAPI
Soft386ExecutionControl(PSOFT386_STATE State, INT Command) Soft386ExecutionControl(PSOFT386_STATE State, INT Command)
@ -210,3 +211,5 @@ Soft386Interrupt(PSOFT386_STATE State, UCHAR Number)
// TODO: NOT IMPLEMENTED!!! // TODO: NOT IMPLEMENTED!!!
UNIMPLEMENTED; UNIMPLEMENTED;
} }
/* EOF */