d9c3940b894e58385d15f0d5dc65ec7a8ff5cc46
[reactos.git] / reactos / subsystems / ntvdm / cpu / cpu.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: emulator.c
5 * PURPOSE: Minimal x86 machine emulator for the VDM
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "cpu.h"
14
15 #include "emulator.h"
16 #include "callback.h"
17 #include "bop.h"
18 #include <isvbop.h>
19
20 #include "clock.h"
21 #include "bios/rom.h"
22 #include "hardware/cmos.h"
23 #include "hardware/keyboard.h"
24 #include "hardware/mouse.h"
25 #include "hardware/pic.h"
26 #include "hardware/ps2.h"
27 #include "hardware/speaker.h"
28 #include "hardware/timer.h"
29 #include "hardware/vga.h"
30
31 #include "io.h"
32
33 /* PRIVATE VARIABLES **********************************************************/
34
35 FAST486_STATE EmulatorContext;
36 BOOLEAN CpuRunning = FALSE;
37
38 /* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */
39 static const INT MaxCpuCallLevel = 32;
40 static INT CpuCallLevel = 0; // == 0: CPU stopped; >= 1: CPU running or halted
41
42 #if 0
43 LPCWSTR ExceptionName[] =
44 {
45 L"Division By Zero",
46 L"Debug",
47 L"Unexpected Error",
48 L"Breakpoint",
49 L"Integer Overflow",
50 L"Bound Range Exceeded",
51 L"Invalid Opcode",
52 L"FPU Not Available"
53 };
54 #endif
55
56 // /* BOP Identifiers */
57 // #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
58
59 /* PRIVATE FUNCTIONS **********************************************************/
60
61 #if 0
62 VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
63 {
64 WORD CodeSegment, InstructionPointer;
65 PBYTE Opcode;
66
67 ASSERT(ExceptionNumber < 8);
68
69 /* Get the CS:IP */
70 InstructionPointer = Stack[STACK_IP];
71 CodeSegment = Stack[STACK_CS];
72 Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
73
74 /* Display a message to the user */
75 DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
76 L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
77 ExceptionName[ExceptionNumber],
78 CodeSegment,
79 InstructionPointer,
80 Opcode[0],
81 Opcode[1],
82 Opcode[2],
83 Opcode[3],
84 Opcode[4],
85 Opcode[5],
86 Opcode[6],
87 Opcode[7],
88 Opcode[8],
89 Opcode[9]);
90
91 /* Stop the VDM */
92 EmulatorTerminate();
93 return;
94 }
95 #endif
96
97 // FIXME: This function assumes 16-bit mode!!!
98 VOID CpuExecute(WORD Segment, WORD Offset)
99 {
100 /* Tell Fast486 to move the instruction pointer */
101 Fast486ExecuteAt(&EmulatorContext, Segment, Offset);
102 }
103
104 VOID CpuStep(VOID)
105 {
106 /* Dump the state for debugging purposes */
107 // Fast486DumpState(&EmulatorContext);
108
109 /* Execute the next instruction */
110 Fast486StepInto(&EmulatorContext);
111 }
112
113 VOID CpuSimulate(VOID)
114 {
115 if (CpuCallLevel > MaxCpuCallLevel)
116 {
117 DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)",
118 CpuCallLevel, MaxCpuCallLevel);
119
120 /* Stop the VDM */
121 EmulatorTerminate();
122 return;
123 }
124 CpuCallLevel++;
125 DPRINT("CpuSimulate --> Level %d\n", CpuCallLevel);
126
127 CpuRunning = TRUE;
128 while (VdmRunning && CpuRunning) ClockUpdate();
129
130 DPRINT("CpuSimulate <-- Level %d\n", CpuCallLevel);
131 CpuCallLevel--;
132 if (!VdmRunning || CpuCallLevel < 0) CpuCallLevel = 0;
133
134 /* This takes into account for reentrance */
135 if (VdmRunning && (CpuCallLevel > 0)) CpuRunning = TRUE;
136 }
137
138 VOID CpuUnsimulate(VOID)
139 {
140 /* Stop simulation */
141 CpuRunning = FALSE;
142 }
143
144 static VOID WINAPI CpuUnsimulateBop(LPWORD Stack)
145 {
146 CpuUnsimulate();
147 }
148
149 /* PUBLIC FUNCTIONS ***********************************************************/
150
151 BOOLEAN CpuInitialize(VOID)
152 {
153 // /* Initialize the internal clock */
154 // if (!ClockInitialize())
155 // {
156 // wprintf(L"FATAL: Failed to initialize the clock\n");
157 // return FALSE;
158 // }
159
160 /* Initialize the CPU */
161 Fast486Initialize(&EmulatorContext,
162 EmulatorReadMemory,
163 EmulatorWriteMemory,
164 EmulatorReadIo,
165 EmulatorWriteIo,
166 NULL,
167 EmulatorBiosOperation,
168 EmulatorIntAcknowledge,
169 NULL /* TODO: Use a TLB */);
170
171 /* Initialize the software callback system and register the emulator BOPs */
172 // RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
173 RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
174
175 return TRUE;
176 }
177
178 VOID CpuCleanup(VOID)
179 {
180 // Fast486Cleanup();
181 }
182
183 /* EOF */