From 005e1f0559223e65c3ec1a72e3c23e31affdba09 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Fri, 16 Aug 2013 19:21:02 +0000 Subject: [PATCH] [SOFT386] Start implementing a new emulator library to provide 386/486 emulation support to NTVDM and perhaps other components aswell. svn path=/branches/ntvdm/; revision=59752 --- include/reactos/libs/soft386/soft386.h | 294 +++++++++++++++++++++++++ lib/CMakeLists.txt | 1 + lib/soft386/CMakeLists.txt | 6 + lib/soft386/soft386.c | 118 ++++++++++ subsystems/ntvdm/CMakeLists.txt | 3 +- 5 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 include/reactos/libs/soft386/soft386.h create mode 100644 lib/soft386/CMakeLists.txt create mode 100644 lib/soft386/soft386.c diff --git a/include/reactos/libs/soft386/soft386.h b/include/reactos/libs/soft386/soft386.h new file mode 100644 index 00000000000..4b2974248f4 --- /dev/null +++ b/include/reactos/libs/soft386/soft386.h @@ -0,0 +1,294 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: 386/486 CPU Emulation Library + * FILE: soft386.h + * PURPOSE: Header file for Soft386. + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _SOFT386_H_ +#define _SOFT386_H_ + +/* INCLUDES *******************************************************************/ + +#include +#include + +/* DEFINES ********************************************************************/ + +#define SOFT386_NUM_GEN_REGS 8 +#define SOFT386_NUM_SEG_REGS 6 +#define SOFT386_NUM_CTRL_REGS 8 +#define SOFT386_NUM_DBG_REGS 8 + +#define SOFT386_CR0_PE (1 << 0) +#define SOFT386_CR0_MP (1 << 1) +#define SOFT386_CR0_EM (1 << 2) +#define SOFT386_CR0_TS (1 << 3) +#define SOFT386_CR0_ET (1 << 4) +#define SOFT386_CR0_NE (1 << 5) +#define SOFT386_CR0_WP (1 << 16) +#define SOFT386_CR0_AM (1 << 18) +#define SOFT386_CR0_NW (1 << 29) +#define SOFT386_CR0_CD (1 << 30) +#define SOFT386_CR0_PG (1 << 31) + +struct _SOFT386_STATE; +typedef struct _SOFT386_STATE SOFT386_STATE; +typedef struct _SOFT386_STATE *PSOFT386_STATE; + +enum _SOFT386_GEN_REGS +{ + SOFT386_REG_EAX, + SOFT386_REG_ECX, + SOFT386_REG_EDX, + SOFT386_REG_EBX, + SOFT386_REG_ESP, + SOFT386_REG_EBP, + SOFT386_REG_ESI, + SOFT386_REG_EDI +}; + +enum _SOFT386_SEG_REGS +{ + SOFT386_REG_ES, + SOFT386_REG_CS, + SOFT386_REG_SS, + SOFT386_REG_DS, + SOFT386_REG_FS, + SOFT386_REG_GS +}; + +enum _SOFT386_CTRL_REGS +{ + SOFT386_REG_CR0, + SOFT386_REG_CR1, + SOFT386_REG_CR2, + SOFT386_REG_CR3, + SOFT386_REG_CR4, + SOFT386_REG_CR5, + SOFT386_REG_CR6, + SOFT386_REG_CR7 +}; + +enum _SOFT386_DBG_REGS +{ + SOFT386_REG_DR0, + SOFT386_REG_DR1, + SOFT386_REG_DR2, + SOFT386_REG_DR3, + SOFT386_REG_DR4, + SOFT386_REG_DR5, + SOFT386_REG_DR6, + SOFT386_REG_DR7 +}; + +typedef +BOOLEAN +(NTAPI *SOFT386_MEM_READ_PROC) +( + PSOFT386_STATE State, + ULONG Address, + LPVOID Buffer, + ULONG Size +); + +typedef +BOOLEAN +(NTAPI *SOFT386_MEM_WRITE_PROC) +( + PSOFT386_STATE State, + ULONG Address, + LPVOID Buffer, + ULONG Size +); + +typedef +VOID +(NTAPI *SOFT386_IO_READ_PROC) +( + PSOFT386_STATE State, + ULONG Port, + LPVOID Buffer, + ULONG Size +); + +typedef +VOID +(NTAPI *SOFT386_IO_WRITE_PROC) +( + PSOFT386_STATE State, + ULONG Port, + LPVOID Buffer, + ULONG Size +); + +typedef union _SOFT386_REG +{ + struct + { + UCHAR LowByte; + UCHAR HighByte; + }; + USHORT LowWord; + ULONG Long; +} SOFT386_REG, *PSOFT386_REG; + +typedef struct _SOFT386_SEG_REG +{ + USHORT Selector; + + /* Descriptor cache */ + ULONG Accessed : 1; + ULONG ReadWrite : 1; + ULONG DirConf : 1; + ULONG Executable : 1; + ULONG SystemType : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG Size : 1; + ULONG Limit; + ULONG Base; +} SOFT386_SEG_REG, *PSOFT386_SEG_REG; + +typedef struct +{ + ULONG Limit : 16; + ULONG Base : 24; + ULONG Accessed : 1; + ULONG ReadWrite : 1; + ULONG DirConf : 1; + ULONG Executable : 1; + ULONG SystemType : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG LimitHigh : 4; + ULONG Avl : 1; + ULONG Reserved : 1; + ULONG Size : 1; + ULONG Granularity : 1; + ULONG BaseHigh : 8; +} SOFT386_GDT_ENTRY; + +typedef struct +{ + ULONG Offset : 16; + ULONG Selector : 16; + ULONG Zero : 8; + ULONG Type : 4; + ULONG Storage : 1; + ULONG Dpl : 2; + ULONG Present : 1; + ULONG OffsetHigh : 16; +} SOFT386_IDT_ENTRY; + +typedef struct _SOFT386_TABLE_REG +{ + USHORT Size; + ULONG Address; +} SOFT386_TABLE_REG, *PSOFT386_TABLE_REG; + +typedef union _SOFT386_FLAGS_REG +{ + ULONG Long; + struct + { + ULONG Cf : 1; + ULONG AlwaysSet : 1; + ULONG Pf : 1; + ULONG Reserved0 : 1; + ULONG Af : 1; + ULONG Reserved1 : 1; + ULONG Zf : 1; + ULONG Sf : 1; + ULONG Tf : 1; + ULONG If : 1; + ULONG Df : 1; + ULONG Of : 1; + ULONG Iopl : 2; + ULONG Nt : 1; + ULONG Reserved2 : 1; + ULONG Rf : 1; + ULONG Vm : 1; + ULONG Ac : 1; + ULONG Vif : 1; + ULONG Vip : 1; + ULONG Id : 1; + }; +} SOFT386_FLAGS_REG, *PSOFT386_FLAGS_REG; + +typedef struct _SOFT386_TSS +{ + ULONG Link; + ULONG Esp0; + ULONG Ss0; + ULONG Esp1; + ULONG Ss1; + ULONG Esp2; + ULONG Ss2; + ULONG Cr3; + ULONG Eip; + ULONG Eflags; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + ULONG Es; + ULONG Cs; + ULONG Ss; + ULONG Ds; + ULONG Fs; + ULONG Gs; + ULONG Ldtr; + ULONG IopbOffset; +} SOFT386_TSS, *PSOFT386_TSS; + +struct _SOFT386_STATE +{ + SOFT386_MEM_READ_PROC MemReadCallback; + SOFT386_MEM_WRITE_PROC MemWriteCallback; + SOFT386_IO_READ_PROC IoReadCallback; + SOFT386_IO_WRITE_PROC IoWriteCallback; + SOFT386_REG GeneralRegs[SOFT386_NUM_GEN_REGS]; + SOFT386_SEG_REG SegmentRegs[SOFT386_NUM_SEG_REGS]; + SOFT386_REG InstPtr; + SOFT386_FLAGS_REG Flags; + SOFT386_TABLE_REG Gdtr, Idtr, Ldtr, Tss; + ULONGLONG TimeStampCounter; + ULONG ControlRegisters[SOFT386_NUM_CTRL_REGS]; + ULONG DebugRegisters[SOFT386_NUM_DBG_REGS]; +}; + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +Soft386Continue(PSOFT386_STATE State); + +VOID +NTAPI +Soft386StepInto(PSOFT386_STATE State); + +VOID +NTAPI +Soft386StepOver(PSOFT386_STATE State); + +VOID +NTAPI +Soft386StepOut(PSOFT386_STATE State); + +VOID +NTAPI +Soft386DumpState(PSOFT386_STATE State); + +VOID +NTAPI +Soft386Reset(PSOFT386_STATE State); + +#endif // _SOFT386_H_ + +/* EOF */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3109a56f339..e977631c18f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(rtl) add_subdirectory(sdk) add_subdirectory(smlib) add_subdirectory(tdilib) +add_subdirectory(soft386) else() diff --git a/lib/soft386/CMakeLists.txt b/lib/soft386/CMakeLists.txt new file mode 100644 index 00000000000..06a0f09eaf8 --- /dev/null +++ b/lib/soft386/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/soft386) + +list(APPEND SOURCE + soft386.c) + +add_library(soft386 ${SOURCE}) diff --git a/lib/soft386/soft386.c b/lib/soft386/soft386.c new file mode 100644 index 00000000000..54d934c0b56 --- /dev/null +++ b/lib/soft386/soft386.c @@ -0,0 +1,118 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: 386/486 CPU Emulation Library + * FILE: soft386.c + * PURPOSE: Functions meant for use by the host. + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#include "soft386.h" + +/* DEFINES ********************************************************************/ + +typedef enum +{ + SOFT386_STEP_INTO, + SOFT386_STEP_OVER, + SOFT386_STEP_OUT, + SOFT386_CONTINUE +} SOFT386_EXEC_CMD; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static +VOID +NTAPI +Soft386ExecutionControl(PSOFT386_STATE State, INT Command) +{ + // TODO: NOT IMPLEMENTED!!! + UNIMPLEMENTED; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +NTAPI +Soft386Continue(PSOFT386_STATE State) +{ + /* Call the internal function */ + Soft386ExecutionControl(State, SOFT386_CONTINUE); +} + +VOID +NTAPI +Soft386StepInto(PSOFT386_STATE State) +{ + /* Call the internal function */ + Soft386ExecutionControl(State, SOFT386_STEP_INTO); +} + +VOID +NTAPI +Soft386StepOver(PSOFT386_STATE State) +{ + /* Call the internal function */ + Soft386ExecutionControl(State, SOFT386_STEP_OVER); +} + +VOID +NTAPI +Soft386StepOut(PSOFT386_STATE State) +{ + /* Call the internal function */ + Soft386ExecutionControl(State, SOFT386_STEP_OUT); +} + +VOID +NTAPI +Soft386DumpState(PSOFT386_STATE State) +{ + // TODO: NOT IMPLEMENTED!!! + UNIMPLEMENTED; +} + +VOID +NTAPI +Soft386Reset(PSOFT386_STATE State) +{ + INT i; + SOFT386_MEM_READ_PROC MemReadCallback = State->MemReadCallback; + SOFT386_MEM_WRITE_PROC MemWriteCallback = State->MemWriteCallback; + SOFT386_IO_READ_PROC IoReadCallback = State->IoReadCallback; + SOFT386_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback; + + /* Clear the entire structure */ + RtlZeroMemory(State, sizeof(*State)); + + /* Initialize the registers */ + State->Flags.AlwaysSet = 1; + State->InstPtr.LowWord = 0xFFF0; + + /* Initialize segments */ + for (i = 0; i < SOFT386_NUM_SEG_REGS; i++) + { + /* Set the selector, base and limit, other values don't apply in real mode */ + State->SegmentRegs[i].Selector = 0; + State->SegmentRegs[i].Base = 0; + State->SegmentRegs[i].Limit = 0xFFFF; + } + + /* Initialize the code segment */ + State->SegmentRegs[SOFT386_REG_CS].Selector = 0xF000; + State->SegmentRegs[SOFT386_REG_CS].Base = 0xFFFF0000; + + /* Initialize the IDT */ + State->Idtr.Size = 0x3FF; + State->Idtr.Address = 0; + + /* Initialize CR0 */ + State->ControlRegisters[0] |= SOFT386_CR0_ET; + + /* Restore the callbacks */ + State->MemReadCallback = MemReadCallback; + State->MemWriteCallback = MemWriteCallback; + State->IoReadCallback = IoReadCallback; + State->IoWriteCallback = IoWriteCallback; +} diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index 7693f6446f9..2c992d5dc01 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -1,5 +1,6 @@ include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/softx86) +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/soft386) spec2def(ntvdm.exe ntvdm.spec) @@ -18,7 +19,7 @@ list(APPEND SOURCE add_executable(ntvdm ${SOURCE}) set_module_type(ntvdm win32cui UNICODE) -target_link_libraries(ntvdm softx86 softx87) +target_link_libraries(ntvdm softx86 softx87 soft386) add_importlibs(ntvdm msvcrt user32 gdi32 kernel32 ntdll) add_dependencies(ntvdm softx86 softx87) add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all)