Author: aandrejevic Date: Sat Aug 17 15:20:47 2013 New Revision: 59760
URL: http://svn.reactos.org/svn/reactos?rev=59760&view=rev Log: [SOFT386] Implement Soft386ReadMemory, Soft386WriteMemory, Soft386StackPush and Soft386StackPop.
Added: branches/ntvdm/lib/soft386/common.c (with props) branches/ntvdm/lib/soft386/common.h (with props) Modified: branches/ntvdm/lib/soft386/CMakeLists.txt branches/ntvdm/lib/soft386/soft386.c
Modified: branches/ntvdm/lib/soft386/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/CMakeLists.txt... ============================================================================== --- branches/ntvdm/lib/soft386/CMakeLists.txt [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/CMakeLists.txt [iso-8859-1] Sat Aug 17 15:20:47 2013 @@ -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})
Added: branches/ntvdm/lib/soft386/common.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.c?rev=5... ============================================================================== --- branches/ntvdm/lib/soft386/common.c (added) +++ branches/ntvdm/lib/soft386/common.c [iso-8859-1] Sat Aug 17 15:20:47 2013 @@ -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 */
Propchange: branches/ntvdm/lib/soft386/common.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/ntvdm/lib/soft386/common.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.h?rev=5... ============================================================================== --- branches/ntvdm/lib/soft386/common.h (added) +++ branches/ntvdm/lib/soft386/common.h [iso-8859-1] Sat Aug 17 15:20:47 2013 @@ -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 */
Propchange: branches/ntvdm/lib/soft386/common.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/ntvdm/lib/soft386/soft386.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/soft386.c?rev=... ============================================================================== --- branches/ntvdm/lib/soft386/soft386.c [iso-8859-1] (original) +++ branches/ntvdm/lib/soft386/soft386.c [iso-8859-1] Sat Aug 17 15:20:47 2013 @@ -8,7 +8,7 @@
/* INCLUDES *******************************************************************/
-#include "soft386.h" +#include "common.h"
/* DEFINES ********************************************************************/
@@ -23,6 +23,7 @@ /* PRIVATE FUNCTIONS **********************************************************/
static +inline VOID NTAPI Soft386ExecutionControl(PSOFT386_STATE State, INT Command) @@ -210,3 +211,5 @@ // TODO: NOT IMPLEMENTED!!! UNIMPLEMENTED; } + +/* EOF */