#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;
/* 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);
}
/* 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)
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.
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;
}
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;
wprintf(L"FATAL: Failed to allocate VDM memory.\n");
return FALSE;
}
- // For diagnostics purposes!!
- FillMemory(BaseAddress, MAX_ADDRESS, 0xFF);
+ /*
+ * For diagnostics purposes, we fill the memory with INT 0x03 codes
+ * so that if a program wants to execute random code in memory, we can
+ * retrieve the exact CS:IP where the problem happens.
+ */
+ RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
/* Initialize I/O ports */
/* Initialize RAM */
+ /* Initialize the CPU */
+
/* Initialize the internal clock */
if (!ClockInitialize())
{
}
/* 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 */
}
/* 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();
// PitCleanup();
// PicCleanup();
- // Fast486Cleanup();
+ CpuCleanup();
/* Free the memory allocated for the 16-bit address space */
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
WINAPI
VDDSimulate16(VOID)
{
- EmulatorSimulate();
+ CpuSimulate();
}
VOID