mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:03:00 +00:00
[NTVDM]
Code reorganization: Move CPU code to specific files for modularity (prepares ground for some future work). We reintroduce also int32.c in which all the int32 handling code is moved to. Part 1/2 svn path=/trunk/; revision=64429
This commit is contained in:
parent
87ad3a5ac5
commit
e9190ef591
28 changed files with 662 additions and 593 deletions
|
@ -14,6 +14,9 @@ list(APPEND SOURCE
|
||||||
bios/kbdbios.c
|
bios/kbdbios.c
|
||||||
bios/rom.c
|
bios/rom.c
|
||||||
bios/vidbios.c
|
bios/vidbios.c
|
||||||
|
cpu/bop.c
|
||||||
|
cpu/callback.c
|
||||||
|
cpu/cpu.c
|
||||||
hardware/cmos.c
|
hardware/cmos.c
|
||||||
hardware/keyboard.c
|
hardware/keyboard.c
|
||||||
hardware/mouse.c
|
hardware/mouse.c
|
||||||
|
@ -27,10 +30,9 @@ list(APPEND SOURCE
|
||||||
dos/dos32krnl/dosfiles.c
|
dos/dos32krnl/dosfiles.c
|
||||||
dos/mouse32.c
|
dos/mouse32.c
|
||||||
dos/dem.c
|
dos/dem.c
|
||||||
bop.c
|
|
||||||
callback.c
|
|
||||||
clock.c
|
clock.c
|
||||||
emulator.c
|
emulator.c
|
||||||
|
int32.c
|
||||||
io.c
|
io.c
|
||||||
registers.c
|
registers.c
|
||||||
utils.c
|
utils.c
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/callback.h"
|
||||||
#include "bop.h"
|
#include "cpu/bop.h"
|
||||||
|
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "bios32/bios32.h"
|
#include "bios32/bios32.h"
|
||||||
|
|
|
@ -14,8 +14,9 @@
|
||||||
#include <reactos/buildno.h>
|
#include <reactos/buildno.h>
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
|
||||||
#include "bop.h"
|
#include "int32.h"
|
||||||
|
// #include "bop.h"
|
||||||
|
|
||||||
#include "../bios.h"
|
#include "../bios.h"
|
||||||
#include "../rom.h"
|
#include "../rom.h"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "ntvdm.h"
|
#include "ntvdm.h"
|
||||||
#include "../bios.h"
|
#include "../bios.h"
|
||||||
|
|
||||||
/**/ #include "callback.h" /**/
|
/**/ #include "int32.h" /**/
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/cpu.h" // for EMULATOR_FLAG_ZF
|
||||||
|
#include "int32.h"
|
||||||
|
|
||||||
#include "kbdbios32.h"
|
#include "kbdbios32.h"
|
||||||
#include "../kbdbios.h"
|
#include "../kbdbios.h"
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
|
||||||
|
|
||||||
#include "moubios32.h"
|
#include "moubios32.h"
|
||||||
#include "bios32p.h"
|
#include "bios32p.h"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "int32.h"
|
||||||
|
|
||||||
#include "vidbios32.h"
|
#include "vidbios32.h"
|
||||||
#include "../vidbios.h"
|
#include "../vidbios.h"
|
||||||
|
|
|
@ -11,8 +11,7 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/bop.h"
|
||||||
#include "bop.h"
|
|
||||||
|
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
// #include "kbdbios.h"
|
// #include "kbdbios.h"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/callback.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/cpu.h"
|
||||||
#include "bop.h"
|
#include "cpu/bop.h"
|
||||||
|
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
// #include "vidbios.h"
|
// #include "vidbios.h"
|
||||||
|
|
|
@ -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 <theflash AT sdf DOT lonestar DOT org>
|
|
||||||
* 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 <isvbop.h>
|
|
||||||
|
|
||||||
/* 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 */
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
// #include "clock.h"
|
// #include "clock.h"
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ UINT Irq12Counter = 0;
|
||||||
|
|
||||||
VOID ClockUpdate(VOID)
|
VOID ClockUpdate(VOID)
|
||||||
{
|
{
|
||||||
extern BOOLEAN CpuSimulate;
|
extern BOOLEAN CpuRunning;
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
#ifdef WORKING_TIMER
|
#ifdef WORKING_TIMER
|
||||||
|
@ -137,9 +138,9 @@ VOID ClockUpdate(VOID)
|
||||||
VgaHorizontalRetrace();
|
VgaHorizontalRetrace();
|
||||||
|
|
||||||
/* Continue CPU emulation */
|
/* 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
|
#ifdef IPS_DISPLAY
|
||||||
Cycles++;
|
Cycles++;
|
||||||
#endif
|
#endif
|
||||||
|
|
143
reactos/subsystems/ntvdm/cpu/callback.c
Normal file
143
reactos/subsystems/ntvdm/cpu/callback.c
Normal file
|
@ -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 <theflash AT sdf DOT lonestar DOT org>
|
||||||
|
* 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 <isvbop.h>
|
||||||
|
|
||||||
|
/* 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 */
|
|
@ -12,8 +12,14 @@
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
/* 32-bit Interrupt Identifiers */
|
#define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num)
|
||||||
#define EMULATOR_MAX_INT32_NUM 0xFF + 1
|
#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
|
typedef struct _CALLBACK16
|
||||||
{
|
{
|
||||||
|
@ -23,11 +29,23 @@ typedef struct _CALLBACK16
|
||||||
USHORT NextOffset;
|
USHORT NextOffset;
|
||||||
} CALLBACK16, *PCALLBACK16;
|
} 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 ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
|
VOID
|
||||||
|
InitializeContextEx(IN PCALLBACK16 Context,
|
||||||
|
IN ULONG TrampolineSize,
|
||||||
|
IN USHORT Segment,
|
||||||
|
IN USHORT Offset);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
InitializeContext(IN PCALLBACK16 Context,
|
InitializeContext(IN PCALLBACK16 Context,
|
||||||
|
@ -38,36 +56,16 @@ VOID
|
||||||
Call16(IN USHORT Segment,
|
Call16(IN USHORT Segment,
|
||||||
IN USHORT Offset);
|
IN USHORT Offset);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
RunCallback16(IN PCALLBACK16 Context,
|
||||||
|
IN ULONG FarPtr);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
RegisterCallback16(IN ULONG FarPtr,
|
RegisterCallback16(IN ULONG FarPtr,
|
||||||
IN LPBYTE CallbackCode,
|
IN LPBYTE CallbackCode,
|
||||||
IN SIZE_T CallbackSize,
|
IN SIZE_T CallbackSize,
|
||||||
OUT PSIZE_T CodeSize OPTIONAL);
|
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_
|
#endif // _CALLBACK_H_
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
191
reactos/subsystems/ntvdm/cpu/cpu.c
Normal file
191
reactos/subsystems/ntvdm/cpu/cpu.c
Normal file
|
@ -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 <theflash AT sdf DOT lonestar DOT org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
#include "emulator.h"
|
||||||
|
#include "callback.h"
|
||||||
|
#include "bop.h"
|
||||||
|
#include <isvbop.h>
|
||||||
|
|
||||||
|
#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 */
|
79
reactos/subsystems/ntvdm/cpu/cpu.h
Normal file
79
reactos/subsystems/ntvdm/cpu/cpu.h
Normal file
|
@ -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 <theflash AT sdf DOT lonestar DOT org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CPU_H_
|
||||||
|
#define _CPU_H_
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#include "ntvdm.h"
|
||||||
|
#include <fast486.h>
|
||||||
|
|
||||||
|
/* 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 */
|
|
@ -18,7 +18,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "dem.h"
|
#include "dem.h"
|
||||||
#include "bop.h"
|
#include "cpu/bop.h"
|
||||||
|
|
||||||
#include "bios/bios.h"
|
#include "bios/bios.h"
|
||||||
#include "mouse32.h"
|
#include "mouse32.h"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "int32.h"
|
||||||
|
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include "ntvdm.h"
|
#include "ntvdm.h"
|
||||||
|
|
||||||
/**/ #include "callback.h" /**/
|
/**/ #include "int32.h" /**/
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
#include "cpu/cpu.h"
|
||||||
|
#include "int32.h"
|
||||||
|
|
||||||
#include "mouse32.h"
|
#include "mouse32.h"
|
||||||
#include "bios/bios.h"
|
#include "bios/bios.h"
|
||||||
|
|
|
@ -11,7 +11,13 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "callback.h"
|
|
||||||
|
#include "cpu/callback.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
#include "cpu/bop.h"
|
||||||
|
#include <isvbop.h>
|
||||||
|
|
||||||
|
#include "int32.h"
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "bios/rom.h"
|
#include "bios/rom.h"
|
||||||
|
@ -24,21 +30,11 @@
|
||||||
#include "hardware/timer.h"
|
#include "hardware/timer.h"
|
||||||
#include "hardware/vga.h"
|
#include "hardware/vga.h"
|
||||||
|
|
||||||
#include "bop.h"
|
|
||||||
#include "vddsup.h"
|
#include "vddsup.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
#include <isvbop.h>
|
|
||||||
|
|
||||||
/* PRIVATE VARIABLES **********************************************************/
|
/* 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;
|
LPVOID BaseAddress = NULL;
|
||||||
BOOLEAN VdmRunning = TRUE;
|
BOOLEAN VdmRunning = TRUE;
|
||||||
|
|
||||||
|
@ -176,51 +172,6 @@ VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
|
||||||
return;
|
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)
|
VOID EmulatorTerminate(VOID)
|
||||||
{
|
{
|
||||||
/* Stop the VDM */
|
/* Stop the VDM */
|
||||||
|
@ -250,11 +201,6 @@ static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
|
||||||
DebugBreak();
|
DebugBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID WINAPI EmulatorUnsimulateBop(LPWORD Stack)
|
|
||||||
{
|
|
||||||
EmulatorUnsimulate();
|
|
||||||
}
|
|
||||||
|
|
||||||
static BYTE WINAPI Port61hRead(ULONG Port)
|
static BYTE WINAPI Port61hRead(ULONG Port)
|
||||||
{
|
{
|
||||||
return Port61hState;
|
return Port61hState;
|
||||||
|
@ -559,6 +505,8 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
||||||
/* Initialize I/O ports */
|
/* Initialize I/O ports */
|
||||||
/* Initialize RAM */
|
/* Initialize RAM */
|
||||||
|
|
||||||
|
/* Initialize the CPU */
|
||||||
|
|
||||||
/* Initialize the internal clock */
|
/* Initialize the internal clock */
|
||||||
if (!ClockInitialize())
|
if (!ClockInitialize())
|
||||||
{
|
{
|
||||||
|
@ -567,15 +515,16 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the CPU */
|
/* Initialize the CPU */
|
||||||
Fast486Initialize(&EmulatorContext,
|
CpuInitialize();
|
||||||
EmulatorReadMemory,
|
// Fast486Initialize(&EmulatorContext,
|
||||||
EmulatorWriteMemory,
|
// EmulatorReadMemory,
|
||||||
EmulatorReadIo,
|
// EmulatorWriteMemory,
|
||||||
EmulatorWriteIo,
|
// EmulatorReadIo,
|
||||||
NULL,
|
// EmulatorWriteIo,
|
||||||
EmulatorBiosOperation,
|
// NULL,
|
||||||
EmulatorIntAcknowledge,
|
// EmulatorBiosOperation,
|
||||||
NULL /* TODO: Use a TLB */);
|
// EmulatorIntAcknowledge,
|
||||||
|
// NULL /* TODO: Use a TLB */);
|
||||||
|
|
||||||
/* Initialize DMA */
|
/* Initialize DMA */
|
||||||
|
|
||||||
|
@ -626,9 +575,9 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the software callback system and register the emulator BOPs */
|
/* Initialize the software callback system and register the emulator BOPs */
|
||||||
InitializeCallbacks();
|
InitializeInt32();
|
||||||
RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
|
RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
|
||||||
RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop);
|
// RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
|
||||||
|
|
||||||
/* Initialize VDD support */
|
/* Initialize VDD support */
|
||||||
VDDSupInitialize();
|
VDDSupInitialize();
|
||||||
|
@ -651,7 +600,7 @@ VOID EmulatorCleanup(VOID)
|
||||||
// PitCleanup();
|
// PitCleanup();
|
||||||
// PicCleanup();
|
// PicCleanup();
|
||||||
|
|
||||||
// Fast486Cleanup();
|
CpuCleanup();
|
||||||
|
|
||||||
/* Free the memory allocated for the 16-bit address space */
|
/* Free the memory allocated for the 16-bit address space */
|
||||||
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
|
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
|
||||||
|
@ -663,7 +612,7 @@ VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
VDDSimulate16(VOID)
|
VDDSimulate16(VOID)
|
||||||
{
|
{
|
||||||
EmulatorSimulate();
|
CpuSimulate();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -16,35 +16,6 @@
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* 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 */
|
/* Basic Memory Management */
|
||||||
#define MEM_ALIGN_UP(ptr, align) MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align))
|
#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))
|
#define MEM_ALIGN_DOWN(ptr, align) (PVOID)((ULONG_PTR)(ptr) & ~((align) - 1l))
|
||||||
|
@ -92,7 +63,7 @@ enum
|
||||||
EMULATOR_EXCEPTION_PAGE_FAULT
|
EMULATOR_EXCEPTION_PAGE_FAULT
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FAST486_STATE EmulatorContext;
|
// extern FAST486_STATE EmulatorContext;
|
||||||
extern LPVOID BaseAddress;
|
extern LPVOID BaseAddress;
|
||||||
extern BOOLEAN VdmRunning;
|
extern BOOLEAN VdmRunning;
|
||||||
|
|
||||||
|
@ -123,10 +94,6 @@ UCHAR WINAPI EmulatorIntAcknowledge
|
||||||
|
|
||||||
VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack);
|
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 EmulatorTerminate(VOID);
|
||||||
|
|
||||||
VOID EmulatorInterrupt(BYTE Number);
|
VOID EmulatorInterrupt(BYTE Number);
|
||||||
|
|
|
@ -14,25 +14,55 @@
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "int32.h"
|
#include "int32.h"
|
||||||
|
|
||||||
#include "bop.h"
|
#include "cpu/bop.h"
|
||||||
|
#include <isvbop.h>
|
||||||
|
|
||||||
/* PRIVATE VARIABLES **********************************************************/
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the list of registered 32-bit Interrupt handlers.
|
* 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 */
|
/* BOP Identifiers */
|
||||||
#define BOP_CONTROL 0xFF // Control BOP Handler
|
#define BOP_CONTROL 0xFF // Control BOP Handler
|
||||||
#define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function
|
#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 INT16_TRAMPOLINE_SIZE sizeof(ULONGLONG) // == TRAMPOLINE_SIZE
|
||||||
#define BOP_CONTROL_INT32 0xFF
|
|
||||||
|
/* 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 ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
VOID WINAPI Int32Dispatch(LPWORD Stack)
|
static VOID WINAPI Int32Dispatch(LPWORD Stack)
|
||||||
{
|
{
|
||||||
/* Get the interrupt number */
|
/* Get the interrupt number */
|
||||||
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
|
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
|
||||||
|
@ -41,88 +71,127 @@ VOID WINAPI Int32Dispatch(LPWORD Stack)
|
||||||
if (Int32Proc[IntNum] != NULL)
|
if (Int32Proc[IntNum] != NULL)
|
||||||
Int32Proc[IntNum](Stack);
|
Int32Proc[IntNum](Stack);
|
||||||
else
|
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 */
|
/* Get the Function Number and skip it */
|
||||||
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
|
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
|
||||||
setIP(getIP() + 1);
|
setIP(getIP() + 1);
|
||||||
|
|
||||||
if (FuncNum == BOP_CONTROL_INT32)
|
switch (FuncNum)
|
||||||
Int32Dispatch(Stack);
|
{
|
||||||
else
|
case BOP_CONTROL_INT32:
|
||||||
DPRINT("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
|
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)
|
||||||
{
|
{
|
||||||
//
|
/* Get a pointer to the IVT and set the corresponding entry (far pointer) */
|
||||||
// WARNING WARNING!!
|
LPDWORD IntVecTable = (LPDWORD)SEG_OFF_TO_PTR(0x0000, 0x0000);
|
||||||
//
|
IntVecTable[IntNumber] = FarPtr;
|
||||||
// If you modify the code stubs here, think also
|
|
||||||
// about updating them in callback.c too!!
|
|
||||||
//
|
|
||||||
|
|
||||||
LPDWORD IntVecTable = (LPDWORD)BaseAddress;
|
/* Register the 16-bit callback */
|
||||||
LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
|
return RegisterCallback16(FarPtr,
|
||||||
USHORT i;
|
CallbackCode,
|
||||||
WORD BopSeqOffset, Offset = 0;
|
CallbackSize,
|
||||||
|
CodeSize);
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate ISR stubs and fill the IVT */
|
ULONG
|
||||||
for (i = 0x00; i <= 0xFF; i++)
|
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);
|
DPRINT1("RegisterInt32: Interrupt 0x%02X already registered!\n", IntNumber);
|
||||||
IntVecTable[i] = MAKELONG(Offset, BiosSegment);
|
return 0;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Write the common stub code */
|
/* Register the 32-bit interrupt handler */
|
||||||
Offset = COMMON_STUB_OFFSET;
|
Int32Proc[IntNumber] = IntHandler;
|
||||||
|
|
||||||
// BOP_SEQ:
|
/* Copy the generic 16-bit interrupt callback and patch it */
|
||||||
BiosCode[Offset++] = 0xF8; // clc
|
RtlCopyMemory(IntCallback, Int16To32, sizeof(Int16To32));
|
||||||
|
IntCallback[2] = IntNumber;
|
||||||
|
|
||||||
BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
|
/* Register the 16-bit interrupt callback */
|
||||||
BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
|
return RegisterInt16(FarPtr,
|
||||||
BiosCode[Offset++] = BOP_CONTROL; // Control BOP
|
IntNumber,
|
||||||
BiosCode[Offset++] = BOP_CONTROL_INT32; // 32-bit Interrupt dispatcher
|
IntCallback,
|
||||||
|
sizeof(IntCallback),
|
||||||
|
CodeSize);
|
||||||
|
}
|
||||||
|
|
||||||
BiosCode[Offset++] = 0x73; // jnc EXIT (offset +4)
|
VOID
|
||||||
BiosCode[Offset++] = 0x04;
|
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!
|
DPRINT("Int32Call(0x%02X)\n", IntNumber);
|
||||||
BiosCode[Offset++] = 0x90; // nop
|
|
||||||
|
|
||||||
BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -11)
|
ASSERT(Context->TrampolineSize == INT16_TRAMPOLINE_SIZE);
|
||||||
BiosCode[Offset++] = 0xF5;
|
|
||||||
|
|
||||||
// EXIT:
|
/* Save the old trampoline */
|
||||||
BiosCode[Offset++] = 0x44; // inc sp
|
((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
|
||||||
BiosCode[Offset++] = 0x44; // inc sp
|
|
||||||
|
|
||||||
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 */
|
/* Register the Control BOP */
|
||||||
RegisterBop(BOP_CONTROL, ControlBop);
|
RegisterBop(BOP_CONTROL, ControlBop);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
|
|
||||||
{
|
|
||||||
Int32Proc[IntNumber] = IntHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -10,21 +10,39 @@
|
||||||
#ifndef _INT32_H_
|
#ifndef _INT32_H_
|
||||||
#define _INT32_H_
|
#define _INT32_H_
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#include "cpu/callback.h"
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
/* 32-bit Interrupt Identifiers */
|
/* 32-bit Interrupt Identifiers */
|
||||||
#define EMULATOR_MAX_INT32_NUM 0xFF + 1
|
#define EMULATOR_MAX_INT32_NUM 0xFF + 1
|
||||||
|
|
||||||
#define INT_HANDLER_OFFSET 0x1000
|
extern const ULONG Int16To32StubSize;
|
||||||
#define COMMON_STUB_OFFSET 0x2000
|
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
|
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
|
||||||
|
|
||||||
VOID WINAPI Int32Dispatch(LPWORD Stack);
|
ULONG
|
||||||
VOID InitializeInt32(WORD BiosSegment);
|
RegisterInt16(IN ULONG FarPtr,
|
||||||
VOID RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
|
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_
|
#endif // _INT32_H_
|
||||||
|
|
||||||
|
|
|
@ -11,24 +11,10 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* 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)
|
VOID EmulatorSetStack(WORD Segment, DWORD Offset)
|
||||||
{
|
{
|
||||||
Fast486SetStack(&EmulatorContext, Segment, Offset);
|
Fast486SetStack(&EmulatorContext, Segment, Offset);
|
||||||
|
@ -405,7 +391,7 @@ VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setEIP(ULONG Value)
|
setEIP(ULONG Value)
|
||||||
{
|
{
|
||||||
EmulatorExecute(getCS(), Value);
|
CpuExecute(getCS(), Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
USHORT
|
USHORT
|
||||||
|
@ -419,7 +405,7 @@ VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setIP(USHORT Value)
|
setIP(USHORT Value)
|
||||||
{
|
{
|
||||||
EmulatorExecute(getCS(), Value);
|
CpuExecute(getCS(), Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -514,136 +500,112 @@ ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getCF(VOID)
|
getCF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_CF);
|
return EmulatorContext.Flags.Cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setCF(ULONG Flag)
|
setCF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Cf = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_CF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_CF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getPF(VOID)
|
getPF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_PF);
|
return EmulatorContext.Flags.Pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setPF(ULONG Flag)
|
setPF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Pf = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_PF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_PF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getAF(VOID)
|
getAF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_AF);
|
return EmulatorContext.Flags.Af;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setAF(ULONG Flag)
|
setAF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Af = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_AF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_AF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getZF(VOID)
|
getZF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_ZF);
|
return EmulatorContext.Flags.Zf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setZF(ULONG Flag)
|
setZF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Zf = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_ZF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_ZF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getSF(VOID)
|
getSF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_SF);
|
return EmulatorContext.Flags.Sf;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setSF(ULONG Flag)
|
setSF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Sf = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_SF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_SF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getIF(VOID)
|
getIF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_IF);
|
return EmulatorContext.Flags.If;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setIF(ULONG Flag)
|
setIF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.If = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_IF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_IF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getDF(VOID)
|
getDF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_DF);
|
return EmulatorContext.Flags.Df;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setDF(ULONG Flag)
|
setDF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Df = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_DF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_DF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
WINAPI
|
WINAPI
|
||||||
getOF(VOID)
|
getOF(VOID)
|
||||||
{
|
{
|
||||||
return EmulatorGetFlag(EMULATOR_FLAG_OF);
|
return EmulatorContext.Flags.Of;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
WINAPI
|
WINAPI
|
||||||
setOF(ULONG Flag)
|
setOF(ULONG Flag)
|
||||||
{
|
{
|
||||||
if (Flag & 1)
|
EmulatorContext.Flags.Of = !!(Flag & 1);
|
||||||
EmulatorSetFlag(EMULATOR_FLAG_OF);
|
|
||||||
else
|
|
||||||
EmulatorClearFlag(EMULATOR_FLAG_OF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "vddsup.h"
|
#include "vddsup.h"
|
||||||
|
|
||||||
#include "bop.h"
|
#include "cpu/bop.h"
|
||||||
|
|
||||||
#include <isvbop.h>
|
#include <isvbop.h>
|
||||||
|
|
||||||
typedef VOID (WINAPI *VDD_PROC)(VOID);
|
typedef VOID (WINAPI *VDD_PROC)(VOID);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue