mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +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/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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
#include <reactos/buildno.h>
|
||||
|
||||
#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"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "ntvdm.h"
|
||||
#include "../bios.h"
|
||||
|
||||
/**/ #include "callback.h" /**/
|
||||
/**/ #include "int32.h" /**/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "callback.h"
|
||||
|
||||
#include "moubios32.h"
|
||||
#include "bios32p.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "callback.h"
|
||||
#include "int32.h"
|
||||
|
||||
#include "vidbios32.h"
|
||||
#include "../vidbios.h"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "callback.h"
|
||||
#include "cpu/callback.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "rom.h"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
#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
|
||||
|
|
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 ********************************************************************/
|
||||
|
||||
/* 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 */
|
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 "dem.h"
|
||||
#include "bop.h"
|
||||
#include "cpu/bop.h"
|
||||
|
||||
#include "bios/bios.h"
|
||||
#include "mouse32.h"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#define NDEBUG
|
||||
|
||||
#include "emulator.h"
|
||||
#include "callback.h"
|
||||
#include "int32.h"
|
||||
|
||||
#include "dos.h"
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "ntvdm.h"
|
||||
|
||||
/**/ #include "callback.h" /**/
|
||||
/**/ #include "int32.h" /**/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 <isvbop.h>
|
||||
|
||||
#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 <isvbop.h>
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -14,25 +14,55 @@
|
|||
#include "emulator.h"
|
||||
#include "int32.h"
|
||||
|
||||
#include "bop.h"
|
||||
#include "cpu/bop.h"
|
||||
#include <isvbop.h>
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -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_
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
#include "emulator.h"
|
||||
#include "vddsup.h"
|
||||
|
||||
#include "bop.h"
|
||||
|
||||
#include "cpu/bop.h"
|
||||
#include <isvbop.h>
|
||||
|
||||
typedef VOID (WINAPI *VDD_PROC)(VOID);
|
||||
|
|
Loading…
Reference in a new issue