diff --git a/reactos/subsystems/ntvdm/CMakeLists.txt b/reactos/subsystems/ntvdm/CMakeLists.txt index 92b03b43a82..2793b0b5415 100644 --- a/reactos/subsystems/ntvdm/CMakeLists.txt +++ b/reactos/subsystems/ntvdm/CMakeLists.txt @@ -14,6 +14,9 @@ list(APPEND SOURCE bios/kbdbios.c bios/rom.c bios/vidbios.c + cpu/bop.c + cpu/callback.c + cpu/cpu.c hardware/cmos.c hardware/keyboard.c hardware/mouse.c @@ -27,10 +30,9 @@ list(APPEND SOURCE dos/dos32krnl/dosfiles.c dos/mouse32.c dos/dem.c - bop.c - callback.c clock.c emulator.c + int32.c io.c registers.c utils.c diff --git a/reactos/subsystems/ntvdm/bios/bios.c b/reactos/subsystems/ntvdm/bios/bios.c index accd3f1cc5e..ad04e48fbb2 100644 --- a/reactos/subsystems/ntvdm/bios/bios.c +++ b/reactos/subsystems/ntvdm/bios/bios.c @@ -11,8 +11,8 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" -#include "bop.h" +#include "cpu/callback.h" +#include "cpu/bop.h" #include "bios.h" #include "bios32/bios32.h" diff --git a/reactos/subsystems/ntvdm/bios/bios32/bios32.c b/reactos/subsystems/ntvdm/bios/bios32/bios32.c index f6138d92792..46d139f5f36 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/bios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/bios32.c @@ -14,8 +14,9 @@ #include #include "emulator.h" -#include "callback.h" -#include "bop.h" +#include "cpu/cpu.h" // for EMULATOR_FLAG_CF +#include "int32.h" +// #include "bop.h" #include "../bios.h" #include "../rom.h" diff --git a/reactos/subsystems/ntvdm/bios/bios32/bios32p.h b/reactos/subsystems/ntvdm/bios/bios32/bios32p.h index 3ffd39d4c28..060f0f71d76 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/bios32p.h +++ b/reactos/subsystems/ntvdm/bios/bios32/bios32p.h @@ -14,7 +14,7 @@ #include "ntvdm.h" #include "../bios.h" -/**/ #include "callback.h" /**/ +/**/ #include "int32.h" /**/ /* DEFINES ********************************************************************/ diff --git a/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c b/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c index 7ef9a8b2502..db9ba5aa59d 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/kbdbios32.c @@ -11,7 +11,8 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" +#include "cpu/cpu.h" // for EMULATOR_FLAG_ZF +#include "int32.h" #include "kbdbios32.h" #include "../kbdbios.h" diff --git a/reactos/subsystems/ntvdm/bios/bios32/moubios32.c b/reactos/subsystems/ntvdm/bios/bios32/moubios32.c index 720182cd70c..235709ed539 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/moubios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/moubios32.c @@ -11,7 +11,6 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" #include "moubios32.h" #include "bios32p.h" diff --git a/reactos/subsystems/ntvdm/bios/bios32/vidbios32.c b/reactos/subsystems/ntvdm/bios/bios32/vidbios32.c index 732776c2db6..97783815f3a 100644 --- a/reactos/subsystems/ntvdm/bios/bios32/vidbios32.c +++ b/reactos/subsystems/ntvdm/bios/bios32/vidbios32.c @@ -13,7 +13,7 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" +#include "int32.h" #include "vidbios32.h" #include "../vidbios.h" diff --git a/reactos/subsystems/ntvdm/bios/kbdbios.c b/reactos/subsystems/ntvdm/bios/kbdbios.c index 72550869f9d..007d2566100 100644 --- a/reactos/subsystems/ntvdm/bios/kbdbios.c +++ b/reactos/subsystems/ntvdm/bios/kbdbios.c @@ -11,8 +11,7 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" -#include "bop.h" +#include "cpu/bop.h" #include "bios.h" // #include "kbdbios.h" diff --git a/reactos/subsystems/ntvdm/bios/rom.c b/reactos/subsystems/ntvdm/bios/rom.c index e4dbc6bf5f6..52864c1efbd 100644 --- a/reactos/subsystems/ntvdm/bios/rom.c +++ b/reactos/subsystems/ntvdm/bios/rom.c @@ -11,7 +11,7 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" +#include "cpu/callback.h" #include "utils.h" #include "rom.h" diff --git a/reactos/subsystems/ntvdm/bios/vidbios.c b/reactos/subsystems/ntvdm/bios/vidbios.c index 444e7e1a8a5..b7ccc17e21b 100644 --- a/reactos/subsystems/ntvdm/bios/vidbios.c +++ b/reactos/subsystems/ntvdm/bios/vidbios.c @@ -12,8 +12,8 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" -#include "bop.h" +#include "cpu/cpu.h" +#include "cpu/bop.h" #include "bios.h" // #include "vidbios.h" diff --git a/reactos/subsystems/ntvdm/callback.c b/reactos/subsystems/ntvdm/callback.c deleted file mode 100644 index 47bacbb3314..00000000000 --- a/reactos/subsystems/ntvdm/callback.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * COPYRIGHT: GPL - See COPYING in the top level directory - * PROJECT: ReactOS Virtual DOS Machine - * FILE: callback.c - * PURPOSE: 16 and 32-bit Callbacks Support - * PROGRAMMERS: Aleksandar Andrejevic - * Hermes Belusca-Maito (hermes.belusca@sfr.fr) - */ - -/******************************************************************************\ -| WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! -| -| Callbacks support supposes implicitely that the callbacks are used -| in the SAME thread as the CPU thread, otherwise messing in parallel -| with the CPU registers is 100% prone to bugs!! -\******************************************************************************/ - -/* INCLUDES *******************************************************************/ - -#define NDEBUG - -#include "emulator.h" -#include "callback.h" - -#include "bop.h" -#include - -/* PRIVATE VARIABLES **********************************************************/ - -/* - * This is the list of registered 32-bit Interrupt handlers. - */ -static EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; - -/* BOP Identifiers */ -#define BOP_CONTROL 0xFF // Control BOP Handler - #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function - #define BOP_CONTROL_INT32 0xFF // 32-bit Interrupt dispatcher - // function code for the Control BOP Handler - -#define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num) -#define UnSimulate16(trap) \ -do { \ - *(PUSHORT)(trap) = EMULATOR_BOP; \ - (trap) += sizeof(USHORT); \ - *(trap) = BOP_UNSIMULATE; \ -} while(0) -// #define UnSimulate16 MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE) - -#define CALL16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG)) -#define INT16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG)) - -// -// WARNING WARNING!! -// -// If you modify the code stubs here, think also -// about updating them in int32.c too!! -// - -/* 16-bit generic interrupt code for calling a 32-bit interrupt handler */ -static BYTE Int16To32[] = -{ - 0xFA, // cli - - /* Push the value of the interrupt to be called */ - 0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum) - - /* The BOP Sequence */ -// BOP_SEQ: - 0xF8, // clc - BOP(BOP_CONTROL), // Control BOP - BOP_CONTROL_INT32, // 32-bit Interrupt dispatcher - - 0x73, 0x04, // jnc EXIT (offset +4) - - 0xFB, // sti - - // HACK: The following instruction should be HLT! - 0x90, // nop - - 0xEB, 0xF5, // jmp BOP_SEQ (offset -11) - -// EXIT: - 0x44, 0x44, // inc sp, inc sp - 0xCF, // iret -}; -const ULONG Int16To32StubSize = sizeof(Int16To32); - -/* PUBLIC FUNCTIONS ***********************************************************/ - -VOID -InitializeContext(IN PCALLBACK16 Context, - IN USHORT Segment, - IN USHORT Offset) -{ - Context->TrampolineFarPtr = MAKELONG(Offset, Segment); - Context->TrampolineSize = max(CALL16_TRAMPOLINE_SIZE, - INT16_TRAMPOLINE_SIZE); - Context->Segment = Segment; - Context->NextOffset = Offset + Context->TrampolineSize; -} - -VOID -Call16(IN USHORT Segment, - IN USHORT Offset) -{ - /* Save CS:IP */ - USHORT OrgCS = getCS(); - USHORT OrgIP = getIP(); - - /* Set the new CS:IP */ - setCS(Segment); - setIP(Offset); - - DPRINT("Call16(%04X:%04X)\n", Segment, Offset); - - /* Start CPU simulation */ - EmulatorSimulate(); - - /* Restore CS:IP */ - setCS(OrgCS); - setIP(OrgIP); -} - - - -ULONG -RegisterCallback16(IN ULONG FarPtr, - IN LPBYTE CallbackCode, - IN SIZE_T CallbackSize, - OUT PSIZE_T CodeSize OPTIONAL) -{ - LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr); - LPBYTE Code = CodeStart; - - SIZE_T OurCodeSize = CallbackSize; - - if (CallbackCode == NULL) CallbackSize = 0; - - if (CallbackCode) - { - /* 16-bit interrupt code */ - RtlCopyMemory(Code, CallbackCode, CallbackSize); - Code += CallbackSize; - } - - /* Return the real size of the code if needed */ - if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart; - - // /* Return the entry-point address for 32-bit calls */ - // return (ULONG_PTR)(CodeStart + CallbackSize); - return OurCodeSize; -} - -VOID -RunCallback16(IN PCALLBACK16 Context, - IN ULONG FarPtr) -{ - PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); - PUCHAR Trampoline = TrampolineBase; - UCHAR OldTrampoline[CALL16_TRAMPOLINE_SIZE]; - - /* Save the old trampoline */ - ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; - - DPRINT1("RunCallback16(0x%p)\n", FarPtr); - - /* Build the generic entry-point for 16-bit far calls */ - *Trampoline++ = 0x9A; // Call far seg:off - *(PULONG)Trampoline = FarPtr; - Trampoline += sizeof(ULONG); - UnSimulate16(Trampoline); - - /* Perform the call */ - Call16(HIWORD(Context->TrampolineFarPtr), - LOWORD(Context->TrampolineFarPtr)); - - /* Restore the old trampoline */ - ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; -} - - - -ULONG -RegisterInt16(IN ULONG FarPtr, - IN BYTE IntNumber, - IN LPBYTE CallbackCode, - IN SIZE_T CallbackSize, - OUT PSIZE_T CodeSize OPTIONAL) -{ - /* Get a pointer to the IVT and set the corresponding entry (far pointer) */ - LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000); - IntVecTable[IntNumber] = FarPtr; - - /* Register the 16-bit callback */ - return RegisterCallback16(FarPtr, - CallbackCode, - CallbackSize, - CodeSize); -} - -ULONG -RegisterInt32(IN ULONG FarPtr, - IN BYTE IntNumber, - IN EMULATOR_INT32_PROC IntHandler, - OUT PSIZE_T CodeSize OPTIONAL) -{ - /* Array for holding our copy of the 16-bit interrupt callback */ - BYTE IntCallback[sizeof(Int16To32)/sizeof(BYTE)]; - - /* Check whether the 32-bit interrupt was already registered */ -#if 0 - if (Int32Proc[IntNumber] != NULL) - { - DPRINT1("RegisterInt32: Interrupt 0x%02X already registered!\n", IntNumber); - return 0; - } -#endif - - /* Register the 32-bit interrupt handler */ - Int32Proc[IntNumber] = IntHandler; - - /* Copy the generic 16-bit interrupt callback and patch it */ - RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32)); - IntCallback[2] = IntNumber; - - /* Register the 16-bit interrupt callback */ - return RegisterInt16(FarPtr, - IntNumber, - IntCallback, - sizeof(IntCallback), - CodeSize); -} - -VOID -Int32Call(IN PCALLBACK16 Context, - IN BYTE IntNumber) -{ - PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); - PUCHAR Trampoline = TrampolineBase; - UCHAR OldTrampoline[INT16_TRAMPOLINE_SIZE]; - - DPRINT("Int32Call(0x%02X)\n", IntNumber); - - /* Save the old trampoline */ - ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; - - /* Build the generic entry-point for 16-bit calls */ - if (IntNumber == 0x03) - { - /* We are redefining for INT 03h */ - *Trampoline++ = 0xCC; // Call INT 03h - /** *Trampoline++ = 0x90; // nop **/ - } - else - { - /* Normal interrupt */ - *Trampoline++ = 0xCD; // Call INT XXh - *Trampoline++ = IntNumber; - } - UnSimulate16(Trampoline); - - /* Perform the call */ - Call16(HIWORD(Context->TrampolineFarPtr), - LOWORD(Context->TrampolineFarPtr)); - - /* Restore the old trampoline */ - ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; -} - - - -VOID WINAPI Int32Dispatch(LPWORD Stack) -{ - /* Get the interrupt number */ - BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); - - /* Call the 32-bit Interrupt handler */ - if (Int32Proc[IntNum] != NULL) - Int32Proc[IntNum](Stack); - else - DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX()); -} - -static VOID WINAPI ControlBop(LPWORD Stack) -{ - /* Get the Function Number and skip it */ - BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); - setIP(getIP() + 1); - - switch (FuncNum) - { - case BOP_CONTROL_INT32: - Int32Dispatch(Stack); - break; - - default: - // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum); - DisplayMessage(L"Unassigned Control BOP Function: 0x%02X", FuncNum); - break; - } -} - -VOID InitializeCallbacks(VOID) -{ - /* Register the Control BOP */ - RegisterBop(BOP_CONTROL, ControlBop); -} - -/* EOF */ diff --git a/reactos/subsystems/ntvdm/clock.c b/reactos/subsystems/ntvdm/clock.c index c283d325388..46241f40db4 100644 --- a/reactos/subsystems/ntvdm/clock.c +++ b/reactos/subsystems/ntvdm/clock.c @@ -12,6 +12,7 @@ #define NDEBUG #include "emulator.h" +#include "cpu/cpu.h" // #include "clock.h" @@ -62,7 +63,7 @@ UINT Irq12Counter = 0; VOID ClockUpdate(VOID) { - extern BOOLEAN CpuSimulate; + extern BOOLEAN CpuRunning; UINT i; #ifdef WORKING_TIMER @@ -137,9 +138,9 @@ VOID ClockUpdate(VOID) VgaHorizontalRetrace(); /* Continue CPU emulation */ - for (i = 0; VdmRunning && CpuSimulate && (i < STEPS_PER_CYCLE); i++) + for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++) { - EmulatorStep(); + CpuStep(); #ifdef IPS_DISPLAY Cycles++; #endif diff --git a/reactos/subsystems/ntvdm/bop.c b/reactos/subsystems/ntvdm/cpu/bop.c similarity index 100% rename from reactos/subsystems/ntvdm/bop.c rename to reactos/subsystems/ntvdm/cpu/bop.c diff --git a/reactos/subsystems/ntvdm/bop.h b/reactos/subsystems/ntvdm/cpu/bop.h similarity index 100% rename from reactos/subsystems/ntvdm/bop.h rename to reactos/subsystems/ntvdm/cpu/bop.h diff --git a/reactos/subsystems/ntvdm/cpu/callback.c b/reactos/subsystems/ntvdm/cpu/callback.c new file mode 100644 index 00000000000..0a71e88bf4f --- /dev/null +++ b/reactos/subsystems/ntvdm/cpu/callback.c @@ -0,0 +1,143 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: callback.c + * PURPOSE: 16 and 32-bit Callbacks Support + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/******************************************************************************\ +| WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! +| +| Callbacks support supposes implicitely that the callbacks are used +| in the SAME thread as the CPU thread, otherwise messing in parallel +| with the CPU registers is 100% prone to bugs!! +\******************************************************************************/ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "cpu.h" +#include "callback.h" +#include "emulator.h" + +#include "bop.h" +#include + +/* PRIVATE VARIABLES **********************************************************/ + +#define TRAMPOLINE_SIZE sizeof(ULONGLONG) + +static BYTE Yield[] = +{ + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // 13x nop + BOP(BOP_UNSIMULATE), // UnSimulate16 BOP +}; +C_ASSERT(sizeof(Yield) == 16 * sizeof(BYTE)); + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID +InitializeContextEx(IN PCALLBACK16 Context, + IN ULONG TrampolineSize, + IN USHORT Segment, + IN USHORT Offset) +{ + Context->TrampolineFarPtr = MAKELONG(Offset, Segment); + Context->TrampolineSize = max(TRAMPOLINE_SIZE, TrampolineSize); + Context->Segment = Segment; + Context->NextOffset = Offset + Context->TrampolineSize; +} + +VOID +InitializeContext(IN PCALLBACK16 Context, + IN USHORT Segment, + IN USHORT Offset) +{ + InitializeContextEx(Context, + TRAMPOLINE_SIZE, + Segment, + Offset); +} + +VOID +Call16(IN USHORT Segment, + IN USHORT Offset) +{ + /* Save CS:IP */ + USHORT OrgCS = getCS(); + USHORT OrgIP = getIP(); + + /* Set the new CS:IP */ + setCS(Segment); + setIP(Offset); + + DPRINT("Call16(%04X:%04X)\n", Segment, Offset); + + /* Start CPU simulation */ + CpuSimulate(); + + /* Restore CS:IP */ + setCS(OrgCS); + setIP(OrgIP); +} + +VOID +RunCallback16(IN PCALLBACK16 Context, + IN ULONG FarPtr) +{ + PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); + PUCHAR Trampoline = TrampolineBase; + UCHAR OldTrampoline[TRAMPOLINE_SIZE]; + + /* Save the old trampoline */ + ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; + + DPRINT("RunCallback16(0x%p)\n", FarPtr); + + /* Build the generic entry-point for 16-bit far calls */ + *Trampoline++ = 0x9A; // Call far seg:off + *(PULONG)Trampoline = FarPtr; + Trampoline += sizeof(ULONG); + UnSimulate16(Trampoline); + + /* Perform the call */ + Call16(HIWORD(Context->TrampolineFarPtr), + LOWORD(Context->TrampolineFarPtr)); + + /* Restore the old trampoline */ + ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; +} + +ULONG +RegisterCallback16(IN ULONG FarPtr, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL) +{ + LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr); + LPBYTE Code = CodeStart; + + SIZE_T OurCodeSize = CallbackSize; + + if (CallbackCode == NULL) CallbackSize = 0; + + if (CallbackCode) + { + /* 16-bit interrupt code */ + RtlCopyMemory(Code, CallbackCode, CallbackSize); + Code += CallbackSize; + } + + /* Return the real size of the code if needed */ + if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart; + + // /* Return the entry-point address for 32-bit calls */ + // return (ULONG_PTR)(CodeStart + CallbackSize); + return OurCodeSize; +} + +/* EOF */ diff --git a/reactos/subsystems/ntvdm/callback.h b/reactos/subsystems/ntvdm/cpu/callback.h similarity index 61% rename from reactos/subsystems/ntvdm/callback.h rename to reactos/subsystems/ntvdm/cpu/callback.h index 264e67fe6d0..265669f3611 100644 --- a/reactos/subsystems/ntvdm/callback.h +++ b/reactos/subsystems/ntvdm/cpu/callback.h @@ -12,8 +12,14 @@ /* DEFINES ********************************************************************/ -/* 32-bit Interrupt Identifiers */ -#define EMULATOR_MAX_INT32_NUM 0xFF + 1 +#define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num) +#define UnSimulate16(trap) \ +do { \ + *(PUSHORT)(trap) = EMULATOR_BOP; \ + (trap) += sizeof(USHORT); \ + *(trap) = BOP_UNSIMULATE; \ +} while(0) +// #define UnSimulate16 MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE) typedef struct _CALLBACK16 { @@ -23,11 +29,23 @@ typedef struct _CALLBACK16 USHORT NextOffset; } CALLBACK16, *PCALLBACK16; -extern const ULONG Int16To32StubSize; +// +// WARNING WARNING!! +// If you're changing the indices here, you then need to +// also fix the BOP code in callback.c !!!!!!!!!!!!!!!!! +// +#define STACK_INT_NUM 0 +#define STACK_IP 1 +#define STACK_CS 2 +#define STACK_FLAGS 3 /* FUNCTIONS ******************************************************************/ -typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); +VOID +InitializeContextEx(IN PCALLBACK16 Context, + IN ULONG TrampolineSize, + IN USHORT Segment, + IN USHORT Offset); VOID InitializeContext(IN PCALLBACK16 Context, @@ -38,36 +56,16 @@ VOID Call16(IN USHORT Segment, IN USHORT Offset); +VOID +RunCallback16(IN PCALLBACK16 Context, + IN ULONG FarPtr); + ULONG RegisterCallback16(IN ULONG FarPtr, IN LPBYTE CallbackCode, IN SIZE_T CallbackSize, OUT PSIZE_T CodeSize OPTIONAL); -VOID -RunCallback16(IN PCALLBACK16 Context, - IN ULONG FarPtr); - -ULONG -RegisterInt16(IN ULONG FarPtr, - IN BYTE IntNumber, - IN LPBYTE CallbackCode, - IN SIZE_T CallbackSize, - OUT PSIZE_T CodeSize OPTIONAL); - -ULONG -RegisterInt32(IN ULONG FarPtr, - IN BYTE IntNumber, - IN EMULATOR_INT32_PROC IntHandler, - OUT PSIZE_T CodeSize OPTIONAL); - -VOID -Int32Call(IN PCALLBACK16 Context, - IN BYTE IntNumber); - -VOID WINAPI Int32Dispatch(LPWORD Stack); -VOID InitializeCallbacks(VOID); - #endif // _CALLBACK_H_ /* EOF */ diff --git a/reactos/subsystems/ntvdm/cpu/cpu.c b/reactos/subsystems/ntvdm/cpu/cpu.c new file mode 100644 index 00000000000..bd744093c43 --- /dev/null +++ b/reactos/subsystems/ntvdm/cpu/cpu.c @@ -0,0 +1,191 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.c + * PURPOSE: Minimal x86 machine emulator for the VDM + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "cpu.h" + +#include "emulator.h" +#include "callback.h" +#include "bop.h" +#include + +#include "clock.h" +#include "bios/rom.h" +#include "hardware/cmos.h" +#include "hardware/keyboard.h" +#include "hardware/mouse.h" +#include "hardware/pic.h" +#include "hardware/ps2.h" +#include "hardware/speaker.h" +#include "hardware/timer.h" +#include "hardware/vga.h" + +#include "io.h" + +/* PRIVATE VARIABLES **********************************************************/ + +FAST486_STATE EmulatorContext; +BOOLEAN CpuRunning = FALSE; + +/* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */ +static const INT MaxCpuCallLevel = 32; +static INT CpuCallLevel = 0; + +// BOOLEAN VdmRunning = TRUE; + +#if 0 +LPCWSTR ExceptionName[] = +{ + L"Division By Zero", + L"Debug", + L"Unexpected Error", + L"Breakpoint", + L"Integer Overflow", + L"Bound Range Exceeded", + L"Invalid Opcode", + L"FPU Not Available" +}; +#endif + +// /* BOP Identifiers */ +// #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app + +/* PRIVATE FUNCTIONS **********************************************************/ + +#if 0 +VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack) +{ + WORD CodeSegment, InstructionPointer; + PBYTE Opcode; + + ASSERT(ExceptionNumber < 8); + + /* Get the CS:IP */ + InstructionPointer = Stack[STACK_IP]; + CodeSegment = Stack[STACK_CS]; + Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer); + + /* Display a message to the user */ + DisplayMessage(L"Exception: %s occured at %04X:%04X\n" + L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + ExceptionName[ExceptionNumber], + CodeSegment, + InstructionPointer, + Opcode[0], + Opcode[1], + Opcode[2], + Opcode[3], + Opcode[4], + Opcode[5], + Opcode[6], + Opcode[7], + Opcode[8], + Opcode[9]); + + /* Stop the VDM */ + EmulatorTerminate(); + return; +} +#endif + +// FIXME: This function assumes 16-bit mode!!! +VOID CpuExecute(WORD Segment, WORD Offset) +{ + /* Tell Fast486 to move the instruction pointer */ + Fast486ExecuteAt(&EmulatorContext, Segment, Offset); +} + +VOID CpuStep(VOID) +{ + /* Dump the state for debugging purposes */ + // Fast486DumpState(&EmulatorContext); + + /* Execute the next instruction */ + Fast486StepInto(&EmulatorContext); +} + +VOID CpuSimulate(VOID) +{ + if (CpuCallLevel > MaxCpuCallLevel) + { + DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)", + CpuCallLevel, MaxCpuCallLevel); + + /* Stop the VDM */ + EmulatorTerminate(); + return; + } + CpuCallLevel++; + + CpuRunning = TRUE; + while (VdmRunning && CpuRunning) ClockUpdate(); + + CpuCallLevel--; + if (CpuCallLevel < 0) CpuCallLevel = 0; + + /* This takes into account for reentrance */ + CpuRunning = TRUE; +} + +VOID CpuUnsimulate(VOID) +{ + /* Stop simulation */ + CpuRunning = FALSE; +} + +static VOID WINAPI CpuUnsimulateBop(LPWORD Stack) +{ + CpuUnsimulate(); +} + +#if 0 +VOID EmulatorTerminate(VOID) +{ + /* Stop the VDM */ + VdmRunning = FALSE; +} +#endif + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN CpuInitialize(VOID) +{ + // /* Initialize the internal clock */ + // if (!ClockInitialize()) + // { + // wprintf(L"FATAL: Failed to initialize the clock\n"); + // return FALSE; + // } + + /* Initialize the CPU */ + Fast486Initialize(&EmulatorContext, + EmulatorReadMemory, + EmulatorWriteMemory, + EmulatorReadIo, + EmulatorWriteIo, + NULL, + EmulatorBiosOperation, + EmulatorIntAcknowledge, + NULL /* TODO: Use a TLB */); + + /* Initialize the software callback system and register the emulator BOPs */ + // RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop); + RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop); + + return TRUE; +} + +VOID CpuCleanup(VOID) +{ + // Fast486Cleanup(); +} + +/* EOF */ diff --git a/reactos/subsystems/ntvdm/cpu/cpu.h b/reactos/subsystems/ntvdm/cpu/cpu.h new file mode 100644 index 00000000000..fd51b49da4c --- /dev/null +++ b/reactos/subsystems/ntvdm/cpu/cpu.h @@ -0,0 +1,79 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.h + * PURPOSE: Minimal x86 machine emulator for the VDM + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _CPU_H_ +#define _CPU_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" +#include + +/* DEFINES ********************************************************************/ + +/* FLAGS */ +#define EMULATOR_FLAG_CF (1 << 0) +#define EMULATOR_FLAG_PF (1 << 2) +#define EMULATOR_FLAG_AF (1 << 4) +#define EMULATOR_FLAG_ZF (1 << 6) +#define EMULATOR_FLAG_SF (1 << 7) +#define EMULATOR_FLAG_TF (1 << 8) +#define EMULATOR_FLAG_IF (1 << 9) +#define EMULATOR_FLAG_DF (1 << 10) +#define EMULATOR_FLAG_OF (1 << 11) +#define EMULATOR_FLAG_NT (1 << 14) +#define EMULATOR_FLAG_RF (1 << 16) +#define EMULATOR_FLAG_VM (1 << 17) +#define EMULATOR_FLAG_AC (1 << 18) +#define EMULATOR_FLAG_VIF (1 << 19) +#define EMULATOR_FLAG_VIP (1 << 20) +#define EMULATOR_FLAG_ID (1 << 21) + +#if 0 +enum +{ + EMULATOR_EXCEPTION_DIVISION_BY_ZERO, + EMULATOR_EXCEPTION_DEBUG, + EMULATOR_EXCEPTION_NMI, + EMULATOR_EXCEPTION_BREAKPOINT, + EMULATOR_EXCEPTION_OVERFLOW, + EMULATOR_EXCEPTION_BOUND, + EMULATOR_EXCEPTION_INVALID_OPCODE, + EMULATOR_EXCEPTION_NO_FPU, + EMULATOR_EXCEPTION_DOUBLE_FAULT, + EMULATOR_EXCEPTION_FPU_SEGMENT, + EMULATOR_EXCEPTION_INVALID_TSS, + EMULATOR_EXCEPTION_NO_SEGMENT, + EMULATOR_EXCEPTION_STACK_SEGMENT, + EMULATOR_EXCEPTION_GPF, + EMULATOR_EXCEPTION_PAGE_FAULT +}; +#endif +extern FAST486_STATE EmulatorContext; +// extern BOOLEAN VdmRunning; + +/* FUNCTIONS ******************************************************************/ + +#if 0 +VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack); +#endif + +VOID CpuExecute(WORD Segment, WORD Offset); +VOID CpuStep(VOID); +VOID CpuSimulate(VOID); +VOID CpuUnsimulate(VOID); +#if 0 +VOID EmulatorTerminate(VOID); +#endif + +BOOLEAN CpuInitialize(VOID); +VOID CpuCleanup(VOID); + +#endif // _CPU_H_ + +/* EOF */ diff --git a/reactos/subsystems/ntvdm/dos/dem.c b/reactos/subsystems/ntvdm/dos/dem.c index 4b75d85c69e..9e58d72c6ae 100644 --- a/reactos/subsystems/ntvdm/dos/dem.c +++ b/reactos/subsystems/ntvdm/dos/dem.c @@ -18,7 +18,7 @@ #include "utils.h" #include "dem.h" -#include "bop.h" +#include "cpu/bop.h" #include "bios/bios.h" #include "mouse32.h" diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c b/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c index b70be3b2be7..428807e0699 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/bios.c @@ -11,7 +11,7 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" +#include "int32.h" #include "dos.h" diff --git a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h index abbef7e142d..7e6e3c457b1 100644 --- a/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h +++ b/reactos/subsystems/ntvdm/dos/dos32krnl/dos.h @@ -13,7 +13,7 @@ #include "ntvdm.h" -/**/ #include "callback.h" /**/ +/**/ #include "int32.h" /**/ /* DEFINES ********************************************************************/ diff --git a/reactos/subsystems/ntvdm/dos/mouse32.c b/reactos/subsystems/ntvdm/dos/mouse32.c index e825dfe2c52..5b0a526844e 100644 --- a/reactos/subsystems/ntvdm/dos/mouse32.c +++ b/reactos/subsystems/ntvdm/dos/mouse32.c @@ -11,7 +11,8 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" +#include "cpu/cpu.h" +#include "int32.h" #include "mouse32.h" #include "bios/bios.h" diff --git a/reactos/subsystems/ntvdm/emulator.c b/reactos/subsystems/ntvdm/emulator.c index 06d1e234676..84e41bd6942 100644 --- a/reactos/subsystems/ntvdm/emulator.c +++ b/reactos/subsystems/ntvdm/emulator.c @@ -11,7 +11,13 @@ #define NDEBUG #include "emulator.h" -#include "callback.h" + +#include "cpu/callback.h" +#include "cpu/cpu.h" +#include "cpu/bop.h" +#include + +#include "int32.h" #include "clock.h" #include "bios/rom.h" @@ -24,21 +30,11 @@ #include "hardware/timer.h" #include "hardware/vga.h" -#include "bop.h" #include "vddsup.h" #include "io.h" -#include - /* PRIVATE VARIABLES **********************************************************/ -FAST486_STATE EmulatorContext; -BOOLEAN CpuSimulate = FALSE; - -/* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */ -static const INT MaxCpuCallLevel = 32; -static INT CpuCallLevel = 0; - LPVOID BaseAddress = NULL; BOOLEAN VdmRunning = TRUE; @@ -176,51 +172,6 @@ VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack) return; } -// FIXME: This function assumes 16-bit mode!!! -VOID EmulatorExecute(WORD Segment, WORD Offset) -{ - /* Tell Fast486 to move the instruction pointer */ - Fast486ExecuteAt(&EmulatorContext, Segment, Offset); -} - -VOID EmulatorStep(VOID) -{ - /* Dump the state for debugging purposes */ - // Fast486DumpState(&EmulatorContext); - - /* Execute the next instruction */ - Fast486StepInto(&EmulatorContext); -} - -VOID EmulatorSimulate(VOID) -{ - if (CpuCallLevel > MaxCpuCallLevel) - { - DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)", - CpuCallLevel, MaxCpuCallLevel); - - /* Stop the VDM */ - EmulatorTerminate(); - return; - } - CpuCallLevel++; - - CpuSimulate = TRUE; - while (VdmRunning && CpuSimulate) ClockUpdate(); - - CpuCallLevel--; - if (CpuCallLevel < 0) CpuCallLevel = 0; - - /* This takes into account for reentrance */ - CpuSimulate = TRUE; -} - -VOID EmulatorUnsimulate(VOID) -{ - /* Stop simulation */ - CpuSimulate = FALSE; -} - VOID EmulatorTerminate(VOID) { /* Stop the VDM */ @@ -250,11 +201,6 @@ static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack) DebugBreak(); } -static VOID WINAPI EmulatorUnsimulateBop(LPWORD Stack) -{ - EmulatorUnsimulate(); -} - static BYTE WINAPI Port61hRead(ULONG Port) { return Port61hState; @@ -559,6 +505,8 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) /* Initialize I/O ports */ /* Initialize RAM */ + /* Initialize the CPU */ + /* Initialize the internal clock */ if (!ClockInitialize()) { @@ -567,15 +515,16 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) } /* Initialize the CPU */ - Fast486Initialize(&EmulatorContext, - EmulatorReadMemory, - EmulatorWriteMemory, - EmulatorReadIo, - EmulatorWriteIo, - NULL, - EmulatorBiosOperation, - EmulatorIntAcknowledge, - NULL /* TODO: Use a TLB */); + CpuInitialize(); + // Fast486Initialize(&EmulatorContext, + // EmulatorReadMemory, + // EmulatorWriteMemory, + // EmulatorReadIo, + // EmulatorWriteIo, + // NULL, + // EmulatorBiosOperation, + // EmulatorIntAcknowledge, + // NULL /* TODO: Use a TLB */); /* Initialize DMA */ @@ -626,9 +575,9 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) } /* Initialize the software callback system and register the emulator BOPs */ - InitializeCallbacks(); + InitializeInt32(); RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop); - RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop); + // RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop); /* Initialize VDD support */ VDDSupInitialize(); @@ -651,7 +600,7 @@ VOID EmulatorCleanup(VOID) // PitCleanup(); // PicCleanup(); - // Fast486Cleanup(); + CpuCleanup(); /* Free the memory allocated for the 16-bit address space */ if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress); @@ -663,7 +612,7 @@ VOID WINAPI VDDSimulate16(VOID) { - EmulatorSimulate(); + CpuSimulate(); } VOID diff --git a/reactos/subsystems/ntvdm/emulator.h b/reactos/subsystems/ntvdm/emulator.h index b405c00355e..4b4928e3313 100644 --- a/reactos/subsystems/ntvdm/emulator.h +++ b/reactos/subsystems/ntvdm/emulator.h @@ -16,35 +16,6 @@ /* DEFINES ********************************************************************/ -/* FLAGS */ -#define EMULATOR_FLAG_CF (1 << 0) -#define EMULATOR_FLAG_PF (1 << 2) -#define EMULATOR_FLAG_AF (1 << 4) -#define EMULATOR_FLAG_ZF (1 << 6) -#define EMULATOR_FLAG_SF (1 << 7) -#define EMULATOR_FLAG_TF (1 << 8) -#define EMULATOR_FLAG_IF (1 << 9) -#define EMULATOR_FLAG_DF (1 << 10) -#define EMULATOR_FLAG_OF (1 << 11) -#define EMULATOR_FLAG_NT (1 << 14) -#define EMULATOR_FLAG_RF (1 << 16) -#define EMULATOR_FLAG_VM (1 << 17) -#define EMULATOR_FLAG_AC (1 << 18) -#define EMULATOR_FLAG_VIF (1 << 19) -#define EMULATOR_FLAG_VIP (1 << 20) -#define EMULATOR_FLAG_ID (1 << 21) - -// -// WARNING WARNING!! -// If you're changing the indices here, you then need to -// also fix the BOP code in callback.c !!!!!!!!!!!!!!!!! -// -#define STACK_INT_NUM 0 -#define STACK_IP 1 -#define STACK_CS 2 -#define STACK_FLAGS 3 - - /* Basic Memory Management */ #define MEM_ALIGN_UP(ptr, align) MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align)) #define MEM_ALIGN_DOWN(ptr, align) (PVOID)((ULONG_PTR)(ptr) & ~((align) - 1l)) @@ -92,7 +63,7 @@ enum EMULATOR_EXCEPTION_PAGE_FAULT }; -extern FAST486_STATE EmulatorContext; +// extern FAST486_STATE EmulatorContext; extern LPVOID BaseAddress; extern BOOLEAN VdmRunning; @@ -123,10 +94,6 @@ UCHAR WINAPI EmulatorIntAcknowledge VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack); -VOID EmulatorExecute(WORD Segment, WORD Offset); -VOID EmulatorStep(VOID); -VOID EmulatorSimulate(VOID); -VOID EmulatorUnsimulate(VOID); VOID EmulatorTerminate(VOID); VOID EmulatorInterrupt(BYTE Number); diff --git a/reactos/subsystems/ntvdm/int32.c b/reactos/subsystems/ntvdm/int32.c index e139c85d44f..72386ad8733 100644 --- a/reactos/subsystems/ntvdm/int32.c +++ b/reactos/subsystems/ntvdm/int32.c @@ -14,25 +14,55 @@ #include "emulator.h" #include "int32.h" -#include "bop.h" +#include "cpu/bop.h" +#include /* PRIVATE VARIABLES **********************************************************/ /* * This is the list of registered 32-bit Interrupt handlers. */ -EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; +static EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; /* BOP Identifiers */ #define BOP_CONTROL 0xFF // Control BOP Handler #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function + #define BOP_CONTROL_INT32 0xFF // 32-bit Interrupt dispatcher -/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */ -#define BOP_CONTROL_INT32 0xFF +#define INT16_TRAMPOLINE_SIZE sizeof(ULONGLONG) // == TRAMPOLINE_SIZE + +/* 16-bit generic interrupt code for calling a 32-bit interrupt handler */ +static BYTE Int16To32[] = +{ + 0xFA, // cli + + /* Push the value of the interrupt to be called */ + 0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum) + + /* The BOP Sequence */ +// BOP_SEQ: + 0xF8, // clc + BOP(BOP_CONTROL), // Control BOP + BOP_CONTROL_INT32, // 32-bit Interrupt dispatcher + + 0x73, 0x04, // jnc EXIT (offset +4) + + 0xFB, // sti + + // HACK: The following instruction should be HLT! + 0x90, // nop + + 0xEB, 0xF5, // jmp BOP_SEQ (offset -11) + +// EXIT: + 0x44, 0x44, // inc sp, inc sp + 0xCF, // iret +}; +const ULONG Int16To32StubSize = sizeof(Int16To32); /* PUBLIC FUNCTIONS ***********************************************************/ -VOID WINAPI Int32Dispatch(LPWORD Stack) +static VOID WINAPI Int32Dispatch(LPWORD Stack) { /* Get the interrupt number */ BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]); @@ -41,88 +71,127 @@ VOID WINAPI Int32Dispatch(LPWORD Stack) if (Int32Proc[IntNum] != NULL) Int32Proc[IntNum](Stack); else - DPRINT("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX()); + DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum, getAX()); } -VOID WINAPI ControlBop(LPWORD Stack) +static VOID WINAPI ControlBop(LPWORD Stack) { /* Get the Function Number and skip it */ BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); setIP(getIP() + 1); - if (FuncNum == BOP_CONTROL_INT32) - Int32Dispatch(Stack); - else - DPRINT("Unassigned Control BOP Function: 0x%02X\n", FuncNum); + switch (FuncNum) + { + case BOP_CONTROL_INT32: + Int32Dispatch(Stack); + break; + + default: + // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum); + DisplayMessage(L"Unassigned Control BOP Function: 0x%02X", FuncNum); + break; + } } -VOID InitializeInt32(WORD BiosSegment) +ULONG +RegisterInt16(IN ULONG FarPtr, + IN BYTE IntNumber, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL) { - // - // WARNING WARNING!! - // - // If you modify the code stubs here, think also - // about updating them in callback.c too!! - // + /* Get a pointer to the IVT and set the corresponding entry (far pointer) */ + LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000); + IntVecTable[IntNumber] = FarPtr; - LPDWORD IntVecTable = (LPDWORD)BaseAddress; - LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0); - USHORT i; - WORD BopSeqOffset, Offset = 0; + /* Register the 16-bit callback */ + return RegisterCallback16(FarPtr, + CallbackCode, + CallbackSize, + CodeSize); +} - /* Generate ISR stubs and fill the IVT */ - for (i = 0x00; i <= 0xFF; i++) +ULONG +RegisterInt32(IN ULONG FarPtr, + IN BYTE IntNumber, + IN EMULATOR_INT32_PROC IntHandler, + OUT PSIZE_T CodeSize OPTIONAL) +{ + /* Array for holding our copy of the 16-bit interrupt callback */ + BYTE IntCallback[sizeof(Int16To32)/sizeof(BYTE)]; + + /* Check whether the 32-bit interrupt was already registered */ +#if 0 + if (Int32Proc[IntNumber] != NULL) { - Offset = INT_HANDLER_OFFSET + (i << 4); - IntVecTable[i] = MAKELONG(Offset, BiosSegment); - - BiosCode[Offset++] = 0xFA; // cli - - BiosCode[Offset++] = 0x6A; // push i - BiosCode[Offset++] = (UCHAR)i; - - BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3); - - BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ - BiosCode[Offset++] = LOBYTE(BopSeqOffset); - BiosCode[Offset++] = HIBYTE(BopSeqOffset); + DPRINT1("RegisterInt32: Interrupt 0x%02X already registered!\n", IntNumber); + return 0; } +#endif - /* Write the common stub code */ - Offset = COMMON_STUB_OFFSET; + /* Register the 32-bit interrupt handler */ + Int32Proc[IntNumber] = IntHandler; -// BOP_SEQ: - BiosCode[Offset++] = 0xF8; // clc + /* Copy the generic 16-bit interrupt callback and patch it */ + RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32)); + IntCallback[2] = IntNumber; - BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence - BiosCode[Offset++] = HIBYTE(EMULATOR_BOP); - BiosCode[Offset++] = BOP_CONTROL; // Control BOP - BiosCode[Offset++] = BOP_CONTROL_INT32; // 32-bit Interrupt dispatcher + /* Register the 16-bit interrupt callback */ + return RegisterInt16(FarPtr, + IntNumber, + IntCallback, + sizeof(IntCallback), + CodeSize); +} - BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4) - BiosCode[Offset++] = 0x04; +VOID +Int32Call(IN PCALLBACK16 Context, + IN BYTE IntNumber) +{ + /* + * TODO: This function has almost the same code as RunCallback16. + * Something that may be nice is to have a common interface to + * build the trampoline... + */ - BiosCode[Offset++] = 0xFB; // sti + PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr); + PUCHAR Trampoline = TrampolineBase; + UCHAR OldTrampoline[INT16_TRAMPOLINE_SIZE]; - // HACK: The following instruction should be HLT! - BiosCode[Offset++] = 0x90; // nop + DPRINT("Int32Call(0x%02X)\n", IntNumber); - BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11) - BiosCode[Offset++] = 0xF5; + ASSERT(Context->TrampolineSize == INT16_TRAMPOLINE_SIZE); -// EXIT: - BiosCode[Offset++] = 0x44; // inc sp - BiosCode[Offset++] = 0x44; // inc sp + /* Save the old trampoline */ + ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0]; - BiosCode[Offset++] = 0xCF; // iret + /* Build the generic entry-point for 16-bit calls */ + if (IntNumber == 0x03) + { + /* We are redefining for INT 03h */ + *Trampoline++ = 0xCC; // Call INT 03h + /** *Trampoline++ = 0x90; // nop **/ + } + else + { + /* Normal interrupt */ + *Trampoline++ = 0xCD; // Call INT XXh + *Trampoline++ = IntNumber; + } + UnSimulate16(Trampoline); + /* Perform the call */ + Call16(HIWORD(Context->TrampolineFarPtr), + LOWORD(Context->TrampolineFarPtr)); + + /* Restore the old trampoline */ + ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0]; +} + +VOID InitializeInt32(VOID) +{ /* Register the Control BOP */ RegisterBop(BOP_CONTROL, ControlBop); } -VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler) -{ - Int32Proc[IntNumber] = IntHandler; -} - /* EOF */ diff --git a/reactos/subsystems/ntvdm/int32.h b/reactos/subsystems/ntvdm/int32.h index d6cced23348..d9dc9f8c774 100644 --- a/reactos/subsystems/ntvdm/int32.h +++ b/reactos/subsystems/ntvdm/int32.h @@ -10,21 +10,39 @@ #ifndef _INT32_H_ #define _INT32_H_ +/* INCLUDES *******************************************************************/ + +#include "cpu/callback.h" + /* DEFINES ********************************************************************/ /* 32-bit Interrupt Identifiers */ #define EMULATOR_MAX_INT32_NUM 0xFF + 1 -#define INT_HANDLER_OFFSET 0x1000 -#define COMMON_STUB_OFFSET 0x2000 +extern const ULONG Int16To32StubSize; /* FUNCTIONS ******************************************************************/ typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); -VOID WINAPI Int32Dispatch(LPWORD Stack); -VOID InitializeInt32(WORD BiosSegment); -VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler); +ULONG +RegisterInt16(IN ULONG FarPtr, + IN BYTE IntNumber, + IN LPBYTE CallbackCode, + IN SIZE_T CallbackSize, + OUT PSIZE_T CodeSize OPTIONAL); + +ULONG +RegisterInt32(IN ULONG FarPtr, + IN BYTE IntNumber, + IN EMULATOR_INT32_PROC IntHandler, + OUT PSIZE_T CodeSize OPTIONAL); + +VOID +Int32Call(IN PCALLBACK16 Context, + IN BYTE IntNumber); + +VOID InitializeInt32(VOID); #endif // _INT32_H_ diff --git a/reactos/subsystems/ntvdm/registers.c b/reactos/subsystems/ntvdm/registers.c index d3d5ce16675..57aca7faae4 100644 --- a/reactos/subsystems/ntvdm/registers.c +++ b/reactos/subsystems/ntvdm/registers.c @@ -11,24 +11,10 @@ #define NDEBUG #include "emulator.h" +#include "cpu/cpu.h" /* PUBLIC FUNCTIONS ***********************************************************/ -static inline BOOLEAN EmulatorGetFlag(ULONG Flag) -{ - return (EmulatorContext.Flags.Long & Flag) ? TRUE : FALSE; -} - -static inline VOID EmulatorSetFlag(ULONG Flag) -{ - EmulatorContext.Flags.Long |= Flag; -} - -static inline VOID EmulatorClearFlag(ULONG Flag) -{ - EmulatorContext.Flags.Long &= ~Flag; -} - VOID EmulatorSetStack(WORD Segment, DWORD Offset) { Fast486SetStack(&EmulatorContext, Segment, Offset); @@ -405,7 +391,7 @@ VOID WINAPI setEIP(ULONG Value) { - EmulatorExecute(getCS(), Value); + CpuExecute(getCS(), Value); } USHORT @@ -419,7 +405,7 @@ VOID WINAPI setIP(USHORT Value) { - EmulatorExecute(getCS(), Value); + CpuExecute(getCS(), Value); } @@ -514,136 +500,112 @@ ULONG WINAPI getCF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_CF); + return EmulatorContext.Flags.Cf; } VOID WINAPI setCF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_CF); - else - EmulatorClearFlag(EMULATOR_FLAG_CF); + EmulatorContext.Flags.Cf = !!(Flag & 1); } ULONG WINAPI getPF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_PF); + return EmulatorContext.Flags.Pf; } VOID WINAPI setPF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_PF); - else - EmulatorClearFlag(EMULATOR_FLAG_PF); + EmulatorContext.Flags.Pf = !!(Flag & 1); } ULONG WINAPI getAF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_AF); + return EmulatorContext.Flags.Af; } VOID WINAPI setAF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_AF); - else - EmulatorClearFlag(EMULATOR_FLAG_AF); + EmulatorContext.Flags.Af = !!(Flag & 1); } ULONG WINAPI getZF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_ZF); + return EmulatorContext.Flags.Zf; } VOID WINAPI setZF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_ZF); - else - EmulatorClearFlag(EMULATOR_FLAG_ZF); + EmulatorContext.Flags.Zf = !!(Flag & 1); } ULONG WINAPI getSF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_SF); + return EmulatorContext.Flags.Sf; } VOID WINAPI setSF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_SF); - else - EmulatorClearFlag(EMULATOR_FLAG_SF); + EmulatorContext.Flags.Sf = !!(Flag & 1); } ULONG WINAPI getIF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_IF); + return EmulatorContext.Flags.If; } VOID WINAPI setIF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_IF); - else - EmulatorClearFlag(EMULATOR_FLAG_IF); + EmulatorContext.Flags.If = !!(Flag & 1); } ULONG WINAPI getDF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_DF); + return EmulatorContext.Flags.Df; } VOID WINAPI setDF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_DF); - else - EmulatorClearFlag(EMULATOR_FLAG_DF); + EmulatorContext.Flags.Df = !!(Flag & 1); } ULONG WINAPI getOF(VOID) { - return EmulatorGetFlag(EMULATOR_FLAG_OF); + return EmulatorContext.Flags.Of; } VOID WINAPI setOF(ULONG Flag) { - if (Flag & 1) - EmulatorSetFlag(EMULATOR_FLAG_OF); - else - EmulatorClearFlag(EMULATOR_FLAG_OF); + EmulatorContext.Flags.Of = !!(Flag & 1); } diff --git a/reactos/subsystems/ntvdm/vddsup.c b/reactos/subsystems/ntvdm/vddsup.c index 92a0ff1ac3b..0997216c08a 100644 --- a/reactos/subsystems/ntvdm/vddsup.c +++ b/reactos/subsystems/ntvdm/vddsup.c @@ -13,8 +13,7 @@ #include "emulator.h" #include "vddsup.h" -#include "bop.h" - +#include "cpu/bop.h" #include typedef VOID (WINAPI *VDD_PROC)(VOID);