ReactOS  0.4.13-dev-651-g5dbc677
cpu.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/cpu/cpu.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 #include "ntvdm.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include "emulator.h"
17 #include "cpu.h"
18 
19 #include "memory.h"
20 #include "callback.h"
21 #include "bop.h"
22 #include <isvbop.h>
23 
24 #include "clock.h"
25 #include "bios/rom.h"
26 #include "hardware/cmos.h"
27 #include "hardware/keyboard.h"
28 #include "hardware/mouse.h"
29 #include "hardware/pic.h"
30 #include "hardware/ps2.h"
31 #include "hardware/sound/speaker.h"
32 #include "hardware/pit.h"
33 #include "hardware/video/svga.h"
34 
35 #include "io.h"
36 
37 /* PRIVATE VARIABLES **********************************************************/
38 
39 FAST486_STATE EmulatorContext;
41 
42 /* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */
43 static const INT MaxCpuCallLevel = 32;
44 static INT CpuCallLevel = 0; // == 0: CPU stopped; >= 1: CPU running or halted
45 
46 #if 0
48 {
49  L"Division By Zero",
50  L"Debug",
51  L"Unexpected Error",
52  L"Breakpoint",
53  L"Integer Overflow",
54  L"Bound Range Exceeded",
55  L"Invalid Opcode",
56  L"FPU Not Available"
57 };
58 #endif
59 
60 // /* BOP Identifiers */
61 // #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
62 
63 /* PRIVATE FUNCTIONS **********************************************************/
64 
65 #if 0
66 VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
67 {
68  WORD CodeSegment, InstructionPointer;
69  PBYTE Opcode;
70 
71  ASSERT(ExceptionNumber < 8);
72 
73  /* Get the CS:IP */
74  InstructionPointer = Stack[STACK_IP];
75  CodeSegment = Stack[STACK_CS];
76  Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
77 
78  /* Display a message to the user */
79  DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
80  L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
81  ExceptionName[ExceptionNumber],
82  CodeSegment,
83  InstructionPointer,
84  Opcode[0],
85  Opcode[1],
86  Opcode[2],
87  Opcode[3],
88  Opcode[4],
89  Opcode[5],
90  Opcode[6],
91  Opcode[7],
92  Opcode[8],
93  Opcode[9]);
94 
95  /* Stop the VDM */
97  return;
98 }
99 #endif
100 
101 // FIXME: This function assumes 16-bit mode!!!
103 {
104  /* Tell Fast486 to move the instruction pointer */
106 }
107 
109 {
110  /* Dump the state for debugging purposes */
111  // Fast486DumpState(&EmulatorContext);
112 
113  /* Execute the next instruction */
115 }
116 
118 {
119  /* Get the exception record */
120  PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
121 
122  switch (ExceptionRecord->ExceptionCode)
123  {
124  /* We only handle access violations so far */
126  {
127  BOOLEAN Writing = (ExceptionRecord->ExceptionInformation[0] == 1);
128 
129  /* Retrieve the address to which a read or write attempt was made */
130  ULONG_PTR Address = ExceptionRecord->ExceptionInformation[1];
131 
132  /*
133  * Check whether the access exception was done inside the virtual memory space
134  * (caused by an emulated app) or outside (casued by a bug in ourselves).
135  */
136  if (Address < (ULONG_PTR)BaseAddress ||
138  {
139  DPRINT1("NTVDM: %s access violation at 0x%p outside the virtual memory space!\n",
140  (Writing ? "Write" : "Read"), Address);
142  }
143 
144  /* We are good to go, dispatch to our memory handlers */
145 
146  /* Fix the CPU state */
148 
149  /* Call the memory handler */
151 
152  /* The execution of the CPU opcode handler MUST NOT continue */
154  }
155 
156  default:
157  {
158  DPRINT1("NTVDM: Exception 0x%08lx not handled!\n", ExceptionRecord->ExceptionCode);
159  break;
160  }
161  }
162 
163  /* Continue to search for a handler */
165 }
166 
168 {
170  {
171  DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)",
173 
174  /* Stop the VDM */
176  return;
177  }
178  CpuCallLevel++;
179  DPRINT("CpuSimulate --> Level %d\n", CpuCallLevel);
180 
181  CpuRunning = TRUE;
182  while (VdmRunning && CpuRunning)
183  {
184  _SEH2_TRY
185  {
186  while (VdmRunning && CpuRunning) ClockUpdate();
187  }
189  {
190  DPRINT("VDM exception handler called\n");
191  }
192  _SEH2_END;
193  }
194 
195  DPRINT("CpuSimulate <-- Level %d\n", CpuCallLevel);
196  CpuCallLevel--;
197  if (!VdmRunning || CpuCallLevel < 0) CpuCallLevel = 0;
198 
199  /* This takes into account for reentrance */
200  if (VdmRunning && (CpuCallLevel > 0)) CpuRunning = TRUE;
201 }
202 
204 {
205  /* Stop simulation */
206  CpuRunning = FALSE;
207 }
208 
210 {
211  CpuUnsimulate();
212 }
213 
214 /* PUBLIC FUNCTIONS ***********************************************************/
215 
217 {
218  // /* Initialize the internal clock */
219  // if (!ClockInitialize())
220  // {
221  // wprintf(L"FATAL: Failed to initialize the clock\n");
222  // return FALSE;
223  // }
224 
225  /* Initialize the CPU */
233  EmulatorFpu,
234  NULL /* TODO: Use a TLB */);
235 
236  /* Initialize the software callback system and register the emulator BOPs */
237  // RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
239 
240  return TRUE;
241 }
242 
244 {
245  // Fast486Cleanup();
246 }
247 
248 /* EOF */
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
_In_ PVOID _In_ ULONG Opcode
Definition: hubbusif.h:330
VOID FASTCALL EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
Definition: bop.c:34
BOOLEAN CpuRunning
Definition: cpu.c:40
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
VOID RegisterBop(BYTE BopCode, EMULATOR_BOP_PROC BopHandler)
Definition: bop.c:29
#define EXCEPTION_ACCESS_VIOLATION
Definition: winbase.h:308
static INT CpuCallLevel
Definition: cpu.c:44
#define BOP_UNSIMULATE
Definition: isvbop.h:31
#define PHYS_TO_REAL(ptr)
Definition: emulator.h:34
VOID FASTCALL EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: memory.c:183
static const INT MaxCpuCallLevel
Definition: cpu.c:43
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
int32_t INT
Definition: typedefs.h:56
VOID CpuSimulate(VOID)
Definition: cpu.c:167
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define MAX_ADDRESS
VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
Definition: emulator.c:85
DWORD ExceptionCode
Definition: compat.h:196
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
long LONG
Definition: pedump.c:60
VOID NTAPI Fast486Rewind(PFAST486_STATE State)
Definition: fast486.c:252
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
void DPRINT(...)
Definition: polytest.cpp:61
_Inout_ PVOID Segment
Definition: exfuncs.h:893
LONG CpuExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
Definition: cpu.c:117
UCHAR FASTCALL EmulatorIntAcknowledge(PFAST486_STATE State)
Definition: emulator.c:71
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:201
VOID NTAPI Fast486StepInto(PFAST486_STATE State)
Definition: debug.c:248
#define WINAPI
Definition: msvc.h:8
unsigned short WORD
Definition: ntddk_ex.h:93
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VOID CpuUnsimulate(VOID)
Definition: cpu.c:203
VOID NTAPI Fast486Initialize(PFAST486_STATE State, FAST486_MEM_READ_PROC MemReadCallback, FAST486_MEM_WRITE_PROC MemWriteCallback, FAST486_IO_READ_PROC IoReadCallback, FAST486_IO_WRITE_PROC IoWriteCallback, FAST486_BOP_PROC BopCallback, FAST486_INT_ACK_PROC IntAckCallback, FAST486_FPU_PROC FpuCallback, PULONG Tlb)
Definition: fast486.c:103
BOOLEAN CpuInitialize(VOID)
Definition: cpu.c:216
LPCWSTR ExceptionName[]
Definition: emulator.c:54
VOID CpuExecute(WORD Segment, WORD Offset)
Definition: cpu.c:102
static const WCHAR L[]
Definition: oid.c:1250
VOID MemExceptionHandler(ULONG FaultAddress, BOOLEAN Writing)
Definition: memory.c:283
unsigned char BYTE
Definition: mem.h:68
VOID FASTCALL EmulatorWriteIo(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: io.c:424
#define STACK_CS
Definition: int32.h:34
VOID EmulatorTerminate(VOID)
Definition: emulator.c:503
struct _EXCEPTION_RECORD * ExceptionRecord
Definition: compat.h:198
uint16_t * LPWORD
Definition: typedefs.h:54
VOID NTAPI Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset)
Definition: fast486.c:212
_SEH2_END
Definition: create.c:4424
VOID FASTCALL EmulatorFpu(PFAST486_STATE State)
Definition: emulator.c:79
static VOID WINAPI CpuUnsimulateBop(LPWORD Stack)
Definition: cpu.c:209
FAST486_STATE EmulatorContext
Definition: cpu.c:39
#define DPRINT1
Definition: precomp.h:8
VOID ClockUpdate(VOID)
Definition: clock.c:76
#define ULONG_PTR
Definition: config.h:101
VOID CpuStep(VOID)
Definition: cpu.c:108
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
VOID FASTCALL EmulatorReadIo(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
Definition: io.c:349
BOOLEAN VdmRunning
Definition: emulator.c:49
void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
Definition: regsvr32.c:239
#define STACK_IP
Definition: int32.h:33
BYTE * PBYTE
Definition: pedump.c:66
VOID FASTCALL EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
Definition: memory.c:139
VOID CpuCleanup(VOID)
Definition: cpu.c:243