2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: Minimal x86 machine emulator for the VDM
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
20 #include <pseh/pseh2.h>
24 #include "hardware/cmos.h"
25 #include "hardware/keyboard.h"
26 #include "hardware/mouse.h"
27 #include "hardware/pic.h"
28 #include "hardware/ps2.h"
29 #include "hardware/sound/speaker.h"
30 #include "hardware/pit.h"
31 #include "hardware/video/vga.h"
35 /* PRIVATE VARIABLES **********************************************************/
37 FAST486_STATE EmulatorContext
;
38 BOOLEAN CpuRunning
= FALSE
;
40 /* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */
41 static const INT MaxCpuCallLevel
= 32;
42 static INT CpuCallLevel
= 0; // == 0: CPU stopped; >= 1: CPU running or halted
45 LPCWSTR ExceptionName
[] =
52 L
"Bound Range Exceeded",
58 // /* BOP Identifiers */
59 // #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
61 /* PRIVATE FUNCTIONS **********************************************************/
64 VOID
EmulatorException(BYTE ExceptionNumber
, LPWORD Stack
)
66 WORD CodeSegment
, InstructionPointer
;
69 ASSERT(ExceptionNumber
< 8);
72 InstructionPointer
= Stack
[STACK_IP
];
73 CodeSegment
= Stack
[STACK_CS
];
74 Opcode
= (PBYTE
)SEG_OFF_TO_PTR(CodeSegment
, InstructionPointer
);
76 /* Display a message to the user */
77 DisplayMessage(L
"Exception: %s occured at %04X:%04X\n"
78 L
"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
79 ExceptionName
[ExceptionNumber
],
99 // FIXME: This function assumes 16-bit mode!!!
100 VOID
CpuExecute(WORD Segment
, WORD Offset
)
102 /* Tell Fast486 to move the instruction pointer */
103 Fast486ExecuteAt(&EmulatorContext
, Segment
, Offset
);
108 /* Dump the state for debugging purposes */
109 // Fast486DumpState(&EmulatorContext);
111 /* Execute the next instruction */
112 Fast486StepInto(&EmulatorContext
);
115 VOID
CpuSimulate(VOID
)
117 EXCEPTION_RECORD LocalExceptionRecord
;
119 if (CpuCallLevel
> MaxCpuCallLevel
)
121 DisplayMessage(L
"Too many CPU levels of recursion (%d, expected maximum %d)",
122 CpuCallLevel
, MaxCpuCallLevel
);
129 DPRINT("CpuSimulate --> Level %d\n", CpuCallLevel
);
132 while (VdmRunning
&& CpuRunning
)
136 while (VdmRunning
&& CpuRunning
) ClockUpdate();
138 _SEH2_EXCEPT(LocalExceptionRecord
= *_SEH2_GetExceptionInformation()->ExceptionRecord
,
139 EXCEPTION_EXECUTE_HANDLER
)
141 BOOLEAN Writing
= (LocalExceptionRecord
.ExceptionInformation
[0] == 1);
142 ULONG FaultAddress
= (ULONG
)LocalExceptionRecord
.ExceptionInformation
[1];
144 /* Make sure this was an access violation */
145 ASSERT(LocalExceptionRecord
.ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
);
147 /* Fix the CPU state */
148 Fast486Rewind(&EmulatorContext
);
150 /* Call the handler */
151 MemExceptionHandler(FaultAddress
, Writing
);
156 DPRINT("CpuSimulate <-- Level %d\n", CpuCallLevel
);
158 if (!VdmRunning
|| CpuCallLevel
< 0) CpuCallLevel
= 0;
160 /* This takes into account for reentrance */
161 if (VdmRunning
&& (CpuCallLevel
> 0)) CpuRunning
= TRUE
;
164 VOID
CpuUnsimulate(VOID
)
166 /* Stop simulation */
170 static VOID WINAPI
CpuUnsimulateBop(LPWORD Stack
)
175 /* PUBLIC FUNCTIONS ***********************************************************/
177 BOOLEAN
CpuInitialize(VOID
)
179 // /* Initialize the internal clock */
180 // if (!ClockInitialize())
182 // wprintf(L"FATAL: Failed to initialize the clock\n");
186 /* Initialize the CPU */
187 Fast486Initialize(&EmulatorContext
,
192 EmulatorBiosOperation
,
193 EmulatorIntAcknowledge
,
195 NULL
/* TODO: Use a TLB */);
197 /* Initialize the software callback system and register the emulator BOPs */
198 // RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
199 RegisterBop(BOP_UNSIMULATE
, CpuUnsimulateBop
);
204 VOID
CpuCleanup(VOID
)