[FAST486][NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 1 Nov 2013 00:01:07 +0000 (00:01 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 1 Nov 2013 00:01:07 +0000 (00:01 +0000)
BOP numbers are 1 byte and map to a function (over 255). But one can pass additional "parameters" to those functions by adding extra bytes, however such functions must advance "by hand" the instruction pointer.

[NTVDM]
- Take into account our previous remark for the BIOS interrupt stubs, and comment them.
- Rework EmulatorBiosOperation (move almost all of its existing code into subfunctions in bop.c) so that one can call many other BOP functions in the future (WIP). The BOP number (still called) EMULATOR_INT_BOP (of value 0xFF) is used for internal 16 --> 32 bit switching for our 32bit bios.
- It appears that the IoRead/WriteCallback and IdleCallback must not be NULL for using fast486. I'm committing a temporary fix that I will definitely fix in a subsequent commit.

svn path=/branches/ntvdm/; revision=60812

include/reactos/libs/fast486/fast486.h
lib/fast486/opcodes.c
subsystems/ntvdm/CMakeLists.txt
subsystems/ntvdm/bios.c
subsystems/ntvdm/bios.h
subsystems/ntvdm/bop.c [new file with mode: 0644]
subsystems/ntvdm/bop.h [new file with mode: 0644]
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h
subsystems/ntvdm/ntvdm.c

index 61d176e..6076e66 100644 (file)
@@ -210,7 +210,7 @@ VOID
 (NTAPI *FAST486_BOP_PROC)
 (
     PFAST486_STATE State,
-    USHORT BopCode
+    UCHAR BopCode
 );
 
 typedef
index 7eb974f..81848a9 100644 (file)
@@ -4331,10 +4331,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes)
             && (ModRegRm.SecondRegister == FAST486_REG_ESP)
             && (State->BopCallback != NULL))
         {
-            USHORT BopCode;
+            UCHAR BopCode;
 
             /* Fetch the BOP code */
-            if (!Fast486FetchWord(State, &BopCode))
+            if (!Fast486FetchByte(State, &BopCode))
             {
                 /* Exception occurred */
                 return FALSE;
index accf3f7..eff132b 100644 (file)
@@ -5,6 +5,7 @@ spec2def(ntvdm.exe ntvdm.spec)
 
 list(APPEND SOURCE
     bios.c
+    bop.c
     dos.c
     emulator.c
     pic.c
index f040147..13343c6 100644 (file)
@@ -453,7 +453,7 @@ BOOLEAN BiosSetVideoPage(BYTE PageNumber)
 
 BOOLEAN BiosInitialize(VOID)
 {
-    INT i;
+    USHORT i;
     WORD Offset = 0;
     LPWORD IntVecTable = (LPWORD)BaseAddress;
     LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0);
@@ -465,7 +465,7 @@ BOOLEAN BiosInitialize(VOID)
     Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
 
     /* Generate ISR stubs and fill the IVT */
-    for (i = 0; i < 256; i++)
+    for (i = 0x00; i <= 0xFF; i++)
     {
         IntVecTable[i * 2] = Offset;
         IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
@@ -473,27 +473,28 @@ BOOLEAN BiosInitialize(VOID)
         BiosCode[Offset++] = 0xFB; // sti
 
         BiosCode[Offset++] = 0x6A; // push i
-        BiosCode[Offset++] = (BYTE)i;
+        BiosCode[Offset++] = (UCHAR)i;
 
         BiosCode[Offset++] = 0x6A; // push 0
         BiosCode[Offset++] = 0x00;
 
+// BOP_SEQ:
         BiosCode[Offset++] = 0xF8; // clc
 
         BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
         BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
-        BiosCode[Offset++] = LOBYTE(EMULATOR_INT_BOP);
-        BiosCode[Offset++] = HIBYTE(EMULATOR_INT_BOP);
+        BiosCode[Offset++] = EMULATOR_INT_BOP;
 
-        BiosCode[Offset++] = 0x73; // jnc +3
+        BiosCode[Offset++] = 0x73; // jnc EXIT (offset +3)
         BiosCode[Offset++] = 0x03;
 
         // HACK: The following instruction should be HLT!
         BiosCode[Offset++] = 0x90; // nop
 
-        BiosCode[Offset++] = 0xEB; // jmp -10
-        BiosCode[Offset++] = 0xF6;
+        BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9)
+        BiosCode[Offset++] = 0xF7;
 
+// EXIT:
         BiosCode[Offset++] = 0x83; // add sp, 4
         BiosCode[Offset++] = 0xC4;
         BiosCode[Offset++] = 0x04;
index 27e2578..e661c2e 100644 (file)
 #define ROM_AREA_START 0xE0000
 #define ROM_AREA_END 0xFFFFF
 #define BDA_SEGMENT 0x40
+
 #define BIOS_PIC_MASTER_INT 0x08
-#define BIOS_PIC_SLAVE_INT 0x70
+#define BIOS_PIC_SLAVE_INT  0x70
+
 #define BIOS_SEGMENT 0xF000
 
 #define BIOS_VIDEO_INTERRUPT 0x10
diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c
new file mode 100644 (file)
index 0000000..41d9510
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bop.c
+ * PURPOSE:         BIOS Operation Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "emulator.h"
+#include "bios.h"
+#include "dos.h"
+#include "vga.h"
+#include "pic.h"
+#include "ps2.h"
+#include "timer.h"
+
+
+LPCWSTR ExceptionName[] =
+{
+    L"Division By Zero",
+    L"Debug",
+    L"Unexpected Error",
+    L"Breakpoint",
+    L"Integer Overflow",
+    L"Bound Range Exceeded",
+    L"Invalid Opcode",
+    L"FPU Not Available"
+};
+
+VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
+{
+    WORD CodeSegment, InstructionPointer;
+
+    ASSERT(ExceptionNumber < 8);
+
+    /* Get the CS:IP */
+    InstructionPointer = Stack[STACK_IP];
+    CodeSegment = Stack[STACK_CS];
+
+    /* Display a message to the user */
+    DisplayMessage(L"Exception: %s occured at %04X:%04X",
+                   ExceptionName[ExceptionNumber],
+                   CodeSegment,
+                   InstructionPointer);
+
+    /* Stop the VDM */
+    VdmRunning = FALSE;
+    return;
+}
+
+// VOID WINAPI IrqDispatch(BYTE IrqNumber, LPWORD Stack)
+// {
+    // /* Check if this was an PIC IRQ */
+    // if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
+    // {
+        // /* It was an IRQ from the master PIC */
+        // BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
+    // }
+    // else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
+    // {
+        // /* It was an IRQ from the slave PIC */
+        // BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
+    // }
+
+    // return;
+// }
+
+// VOID WINAPI BiosInt(BYTE IntNumber, LPWORD Stack)
+// {
+// }
+
+VOID WINAPI IntDispatch(LPWORD Stack)
+{
+    BYTE IntNum;
+
+    /* Get the interrupt number */
+    IntNum = LOBYTE(Stack[STACK_INT_NUM]);
+
+    /* Check if this was an exception */
+    if (IntNum < 8)
+    {
+        Exception(IntNum, Stack);
+        return;
+    }
+
+    /* Check if this was an PIC IRQ */
+    if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
+    {
+        /* It was an IRQ from the master PIC */
+        BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
+        return;
+    }
+    else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
+    {
+        /* It was an IRQ from the slave PIC */
+        BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
+        return;
+    }
+
+    switch (IntNum)
+    {
+        case BIOS_VIDEO_INTERRUPT:
+        {
+            /* This is the video BIOS interrupt, call the BIOS */
+            BiosVideoService(Stack);
+            break;
+        }
+        case BIOS_EQUIPMENT_INTERRUPT:
+        {
+            /* This is the BIOS "get equipment" command, call the BIOS */
+            BiosEquipmentService(Stack);
+            break;
+        }
+        case BIOS_KBD_INTERRUPT:
+        {
+            /* This is the keyboard BIOS interrupt, call the BIOS */
+            BiosKeyboardService(Stack);
+            break;
+        }
+        case BIOS_TIME_INTERRUPT:
+        {
+            /* This is the time BIOS interrupt, call the BIOS */
+            BiosTimeService(Stack);
+            break;
+        }
+        case BIOS_SYS_TIMER_INTERRUPT:
+        {
+            /* BIOS timer update */
+            BiosSystemTimerInterrupt(Stack);
+            break;
+        }
+        case 0x20:
+        {
+            DosInt20h(Stack);
+            break;
+        }
+        case 0x21:
+        {
+            DosInt21h(Stack);
+            break;
+        }
+        case 0x23:
+        {
+            DosBreakInterrupt(Stack);
+            break;
+        }
+        default:
+        {
+            DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum);
+            break;
+        }
+    }
+}
+
+VOID WINAPI ControlBop(LPWORD Stack)
+{
+    IntDispatch(Stack);
+}
+
+/* EOF */
diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h
new file mode 100644 (file)
index 0000000..38a39e7
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * PROJECT:         ReactOS Virtual DOS Machine
+ * FILE:            bop.h
+ * PURPOSE:         BIOS Operation Handlers
+ * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* EOF */
index 601da01..1b5f4df 100644 (file)
@@ -225,10 +225,10 @@ static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffe
     }
 }
 
-static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, USHORT BopCode)
+VOID WINAPI ControlBop(LPWORD Stack);
+static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
 {
-    WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
-    BYTE IntNum;
+    WORD StackSegment, StackPointer;
     LPWORD Stack;
 
     /* Get the SS:SP */
@@ -238,99 +238,22 @@ static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, USHORT BopCode)
     /* Get the stack */
     Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
 
-    if (BopCode == EMULATOR_INT_BOP)
+    switch (BopCode)
     {
-        /* Get the interrupt number */
-        IntNum = LOBYTE(Stack[STACK_INT_NUM]);
-
-        /* Get the CS:IP */
-        InstructionPointer = Stack[STACK_IP];
-        CodeSegment = Stack[STACK_CS];
-
-        /* Check if this was an exception */
-        if (IntNum < 8)
-        {
-            /* Display a message to the user */
-            DisplayMessage(L"Exception: %s occured at %04X:%04X",
-                           ExceptionName[IntNum],
-                           CodeSegment,
-                           InstructionPointer);
-
-            /* Stop the VDM */
-            VdmRunning = FALSE;
-            return;
-        }
-
-        /* Check if this was an PIC IRQ */
-        if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
-        {
-            /* It was an IRQ from the master PIC */
-            BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
-            return;
-        }
-        else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
-        {
-            /* It was an IRQ from the slave PIC */
-            BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
-            return;
-        }
+        case EMULATOR_INT_BOP:
+            ControlBop(Stack);
+            break;
 
-        switch (IntNum)
-        {
-            case BIOS_VIDEO_INTERRUPT:
-            {
-                /* This is the video BIOS interrupt, call the BIOS */
-                BiosVideoService(Stack);
-                break;
-            }
-            case BIOS_EQUIPMENT_INTERRUPT:
-            {
-                /* This is the BIOS "get equipment" command, call the BIOS */
-                BiosEquipmentService(Stack);
-                break;
-            }
-            case BIOS_KBD_INTERRUPT:
-            {
-                /* This is the keyboard BIOS interrupt, call the BIOS */
-                BiosKeyboardService(Stack);
-                break;
-            }
-            case BIOS_TIME_INTERRUPT:
-            {
-                /* This is the time BIOS interrupt, call the BIOS */
-                BiosTimeService(Stack);
-                break;
-            }
-            case BIOS_SYS_TIMER_INTERRUPT:
-            {
-                /* BIOS timer update */
-                BiosSystemTimerInterrupt(Stack);
-                break;
-            }
-            case 0x20:
-            {
-                DosInt20h(Stack);
-                break;
-            }
-            case 0x21:
-            {
-                DosInt21h(Stack);
-                break;
-            }
-            case 0x23:
-            {
-                DosBreakInterrupt(Stack);
-                break;
-            }
-            default:
-            {
-                DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum);
-                break;
-            }
-        }
+        default:
+            DPRINT1("Invalid BOP code %u\n", BopCode);
+            break;
     }
 }
 
+static VOID WINAPI EmulatorIdle(PFAST486_STATE State)
+{
+}
+
 static UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
 {
     UNREFERENCED_PARAMETER(State);
@@ -350,8 +273,9 @@ BOOLEAN EmulatorInitialize()
     /* Set the callbacks */
     EmulatorContext.MemReadCallback  = EmulatorReadMemory;
     EmulatorContext.MemWriteCallback = EmulatorWriteMemory;
-    EmulatorContext.IoReadCallback   = EmulatorReadIo;
-    EmulatorContext.IoWriteCallback  = EmulatorWriteIo;
+    EmulatorContext.IoReadCallback   = EmulatorReadIo;  // Must be != NULL
+    EmulatorContext.IoWriteCallback  = EmulatorWriteIo; // Must be != NULL
+    EmulatorContext.IdleCallback     = EmulatorIdle;    // Must be != NULL
     EmulatorContext.BopCallback      = EmulatorBiosOperation;
     EmulatorContext.IntAckCallback   = EmulatorIntAcknowledge;
 
index fcfb071..b0d8a28 100644 (file)
 #define EMULATOR_FLAG_ID (1 << 21)
 
 /* Common definitions */
-#define EMULATOR_BOP 0xC4C4
-#define EMULATOR_INT_BOP 0xBEEF
-#define STACK_COUNTER 0
-#define STACK_INT_NUM 1
-#define STACK_IP 2
-#define STACK_CS 3
-#define STACK_FLAGS 4
+#define EMULATOR_BOP        0xC4C4
+#define EMULATOR_INT_BOP    0xFF
+
+#define STACK_COUNTER   0
+#define STACK_INT_NUM   1
+#define STACK_IP        2
+#define STACK_CS        3
+#define STACK_FLAGS     4
 
 enum
 {
index b919c81..c1efd21 100644 (file)
 
 BOOLEAN VdmRunning = TRUE;
 LPVOID BaseAddress = NULL;
-LPCWSTR ExceptionName[] =
-{
-    L"Division By Zero",
-    L"Debug",
-    L"Unexpected Error",
-    L"Breakpoint",
-    L"Integer Overflow",
-    L"Bound Range Exceeded",
-    L"Invalid Opcode",
-    L"FPU Not Available"
-};
 
 /* PUBLIC FUNCTIONS ***********************************************************/