* Sync up to trunk head (r64921).
[reactos.git] / subsystems / ntvdm / emulator.c
index 06d1e23..b8a43b6 100644 (file)
 #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"
 #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;
 
@@ -64,6 +60,75 @@ LPCWSTR ExceptionName[] =
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+static inline VOID
+EmulatorMoveMemory(OUT VOID UNALIGNED *Destination,
+                   IN const VOID UNALIGNED *Source,
+                   IN SIZE_T Length)
+{
+#if 1
+    /*
+     * We use a switch here to detect small moves of memory, as these
+     * constitute the bulk of our moves.
+     * Using RtlMoveMemory for all these small moves would be slow otherwise.
+     */
+    switch (Length)
+    {
+        case 0:
+            return;
+
+        case sizeof(UCHAR):
+            *(PUCHAR)Destination = *(PUCHAR)Source;
+            return;
+
+        case sizeof(USHORT):
+            *(PUSHORT)Destination = *(PUSHORT)Source;
+            return;
+
+        case sizeof(ULONG):
+            *(PULONG)Destination = *(PULONG)Source;
+            return;
+
+        case sizeof(ULONGLONG):
+            *(PULONGLONG)Destination = *(PULONGLONG)Source;
+            return;
+
+        default:
+#if defined(__GNUC__)
+            __builtin_memmove(Destination, Source, Length);
+#else
+            RtlMoveMemory(Destination, Source, Length);
+#endif
+    }
+
+#else // defined(_MSC_VER)
+
+    PUCHAR Dest = (PUCHAR)Destination;
+    PUCHAR Src  = (PUCHAR)Source;
+
+    SIZE_T Count, NewSize = Length;
+
+    /* Move dword */
+    Count   = NewSize >> 2; // NewSize / sizeof(ULONG);
+    NewSize = NewSize  & 3; // NewSize % sizeof(ULONG);
+    __movsd(Dest, Src, Count);
+    Dest += Count << 2; // Count * sizeof(ULONG);
+    Src  += Count << 2;
+
+    /* Move word */
+    Count   = NewSize >> 1; // NewSize / sizeof(USHORT);
+    NewSize = NewSize  & 1; // NewSize % sizeof(USHORT);
+    __movsw(Dest, Src, Count);
+    Dest += Count << 1; // Count * sizeof(USHORT);
+    Src  += Count << 1;
+
+    /* Move byte */
+    Count   = NewSize; // NewSize / sizeof(UCHAR);
+    // NewSize = NewSize; // NewSize % sizeof(UCHAR);
+    __movsb(Dest, Src, Count);
+
+#endif
+}
+
 VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
 {
     UNREFERENCED_PARAMETER(State);
@@ -95,7 +160,7 @@ VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer
     }
 
     /* Read the data from the virtual address space and store it in the buffer */
-    RtlCopyMemory(Buffer, REAL_TO_PHYS(Address), Size);
+    EmulatorMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
 }
 
 VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
@@ -116,7 +181,7 @@ VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffe
     if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;
 
     /* Read the data from the buffer and store it in the virtual address space */
-    RtlCopyMemory(REAL_TO_PHYS(Address), Buffer, Size);
+    EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);
 
     /*
      * Check if we modified the VGA memory.
@@ -171,59 +236,17 @@ VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
                    Opcode[8],
                    Opcode[9]);
 
+    Fast486DumpState(&EmulatorContext);
+
     /* Stop the VDM */
     EmulatorTerminate();
     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 */
+    CpuUnsimulate(); // Halt the CPU
     VdmRunning = FALSE;
 }
 
@@ -250,17 +273,12 @@ static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
     DebugBreak();
 }
 
-static VOID WINAPI EmulatorUnsimulateBop(LPWORD Stack)
-{
-    EmulatorUnsimulate();
-}
-
-static BYTE WINAPI Port61hRead(ULONG Port)
+static BYTE WINAPI Port61hRead(USHORT Port)
 {
     return Port61hState;
 }
 
-static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
+static VOID WINAPI Port61hWrite(USHORT Port, BYTE Data)
 {
     // BOOLEAN SpeakerStateChange = FALSE;
     BYTE OldPort61hState = Port61hState;
@@ -559,6 +577,8 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
     /* Initialize I/O ports */
     /* Initialize RAM */
 
+    /* Initialize the CPU */
+
     /* Initialize the internal clock */
     if (!ClockInitialize())
     {
@@ -567,15 +587,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 +647,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 +672,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 +684,7 @@ VOID
 WINAPI
 VDDSimulate16(VOID)
 {
-    EmulatorSimulate();
+    CpuSimulate();
 }
 
 VOID