[SOFT386]
[reactos.git] / subsystems / ntvdm / emulator.c
index c0915ce..1c99b57 100644 (file)
 softx86_ctx EmulatorContext;
 softx87_ctx FpuEmulatorContext;
 #else
-EMULATOR_CONTEXT EmulatorContext;
+SOFT386_STATE EmulatorContext;
 #endif
 
 static BOOLEAN A20Line = FALSE;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-#ifndef NEW_EMULATOR
-
-static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
+static VOID NTVDMCALL EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
 {
     UNREFERENCED_PARAMETER(Context);
 
@@ -58,7 +56,7 @@ static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT S
     }
 }
 
-static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
+static VOID NTVDMCALL EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
 {
     UNREFERENCED_PARAMETER(Context);
 
@@ -86,7 +84,7 @@ static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT
     }
 }
 
-static VOID EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
+static VOID NTVDMCALL EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
 {
     UNREFERENCED_PARAMETER(Context);
     UNREFERENCED_PARAMETER(Size);
@@ -154,7 +152,7 @@ static VOID EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
     }
 }
 
-static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
+static VOID NTVDMCALL EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
 {
     BYTE Byte = *Buffer;
 
@@ -241,8 +239,8 @@ static VOID EmulatorBop(WORD Code)
     StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
     StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
 #else
-    StackSegment = EmulatorContext.Registers[EMULATOR_REG_SS].LowWord;
-    StackPointer = EmulatorContext.Registers[EMULATOR_REG_SP].LowWord;
+    StackSegment = EmulatorContext.SegmentRegs[SOFT386_REG_SS].Selector;
+    StackPointer = EmulatorContext.GeneralRegs[SOFT386_REG_ESP].LowWord;
 #endif
 
     /* Get the stack */
@@ -341,6 +339,21 @@ static VOID EmulatorBop(WORD Code)
     }
 }
 
+#ifdef NEW_EMULATOR
+static VOID WINAPI EmulatorBiosOperation(PSOFT386_STATE State, WORD Code)
+{
+    /*
+     * HACK: To maintain softx86 compatbility, just call the old EmulatorBop here.
+     * Later on, when softx86 is no longer needed, the code from EmulatorBop should
+     * be moved here and should use the "State" variable.
+     */
+    EmulatorBop(Code);
+}
+
+#endif
+
+#ifndef NEW_EMULATOR
+
 static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
 {
     UNREFERENCED_PARAMETER(Context);
@@ -407,7 +420,15 @@ BOOLEAN EmulatorInitialize()
     /* Connect the emulated FPU to the emulated CPU */
     softx87_connect_to_CPU(&EmulatorContext, &FpuEmulatorContext);
 #else
-    // TODO: NOT IMPLEMENTED
+    /* Set the callbacks */
+    EmulatorContext.MemReadCallback = (SOFT386_MEM_READ_PROC)EmulatorReadMemory;
+    EmulatorContext.MemWriteCallback = (SOFT386_MEM_WRITE_PROC)EmulatorWriteMemory;
+    EmulatorContext.IoReadCallback = (SOFT386_IO_READ_PROC)EmulatorReadIo;
+    EmulatorContext.IoWriteCallback = (SOFT386_IO_WRITE_PROC)EmulatorWriteIo;
+    EmulatorContext.BopCallback = (SOFT386_BOP_PROC)EmulatorBiosOperation;
+
+    /* Reset the CPU */
+    Soft386Reset(&EmulatorContext);
 #endif
 
     /* Enable interrupts */
@@ -416,28 +437,31 @@ BOOLEAN EmulatorInitialize()
     return TRUE;
 }
 
-VOID EmulatorSetStack(WORD Segment, WORD Offset)
+VOID EmulatorSetStack(WORD Segment, DWORD Offset)
 {
 #ifndef NEW_EMULATOR
     /* Call the softx86 API */
     softx86_set_stack_ptr(&EmulatorContext, Segment, Offset);
 #else
-    // TODO: NOT IMPLEMENTED
+    Soft386SetStack(&EmulatorContext, Segment, Offset);
 #endif
 }
 
+// FIXME: This function assumes 16-bit mode!!!
 VOID EmulatorExecute(WORD Segment, WORD Offset)
 {
 #ifndef NEW_EMULATOR
     /* Call the softx86 API */
     softx86_set_instruction_ptr(&EmulatorContext, Segment, Offset);
 #else
-    // TODO: NOT IMPLEMENTED
+    /* Tell Soft386 to move the instruction pointer */
+    Soft386ExecuteAt(&EmulatorContext, Segment, Offset);
 #endif
 }
 
 VOID EmulatorInterrupt(BYTE Number)
 {
+#ifndef NEW_EMULATOR
     LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
     UINT Segment, Offset;
 
@@ -445,13 +469,11 @@ VOID EmulatorInterrupt(BYTE Number)
     Segment = HIWORD(IntVecTable[Number]);
     Offset = LOWORD(IntVecTable[Number]);
 
-#ifndef NEW_EMULATOR
     /* Call the softx86 API */
     softx86_make_simple_interrupt_call(&EmulatorContext, &Segment, &Offset);
 #else
-    UNREFERENCED_PARAMETER(Segment);
-    UNREFERENCED_PARAMETER(Offset);
-    // TODO: NOT IMPLEMENTED
+    /* Call the Soft386 API */
+    Soft386Interrupt(&EmulatorContext, Number);
 #endif
 }
 
@@ -460,6 +482,9 @@ VOID EmulatorExternalInterrupt(BYTE Number)
 #ifndef NEW_EMULATOR
     /* Call the softx86 API */
     softx86_ext_hw_signal(&EmulatorContext, Number);
+#else
+    /* Call the Soft386 API */
+    Soft386Interrupt(&EmulatorContext, Number);
 #endif
 }
 
@@ -475,23 +500,46 @@ ULONG EmulatorGetRegister(ULONG Register)
         return EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val;
     }
 #else
-    return EmulatorContext.Registers[Register].Long;
+    if (Register < EMULATOR_REG_ES)
+    {
+        return EmulatorContext.GeneralRegs[Register].Long;
+    }
+    else
+    {
+        return EmulatorContext.SegmentRegs[Register - EMULATOR_REG_ES].Selector;
+    }
+#endif
+}
+
+ULONG EmulatorGetProgramCounter(VOID)
+{
+#ifndef NEW_EMULATOR
+    return EmulatorContext.state->reg_ip;
+#else
+    return EmulatorContext.InstPtr.Long;
 #endif
 }
 
 VOID EmulatorSetRegister(ULONG Register, ULONG Value)
 {
 #ifndef NEW_EMULATOR
-    if (Register < EMULATOR_REG_CS)
+    if (Register < EMULATOR_REG_ES)
     {
         EmulatorContext.state->general_reg[Register].val = Value;
     }
     else
     {
-        EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = (WORD)Value;
+        EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = (USHORT)Value;
     }
 #else
-    // TODO: NOT IMPLEMENTED
+    if (Register < EMULATOR_REG_ES)
+    {
+        EmulatorContext.GeneralRegs[Register].Long = Value;
+    }
+    else
+    {
+        Soft386SetSegment(&EmulatorContext, Register - EMULATOR_REG_ES, (USHORT)Value);
+    }
 #endif
 }
 
@@ -524,9 +572,9 @@ VOID EmulatorClearFlag(ULONG Flag)
 
 VOID EmulatorStep(VOID)
 {
+#ifndef NEW_EMULATOR
     LPWORD Instruction;
 
-#ifndef NEW_EMULATOR
     /* Print the current position - useful for debugging */
     DPRINT("Executing at CS:IP = %04X:%04X\n",
            EmulatorGetRegister(EMULATOR_REG_CS),
@@ -556,7 +604,11 @@ VOID EmulatorStep(VOID)
         EmulatorInterrupt(EMULATOR_EXCEPTION_INVALID_OPCODE);
     }
 #else
-    // TODO: NOT IMPLEMENTED
+    /* Dump the state for debugging purposes */
+    // Soft386DumpState(&EmulatorContext);
+
+    /* Execute the next instruction */
+    Soft386StepInto(&EmulatorContext);
 #endif
 }