Finish my Interruption revamp.
- Move interrupt-related code from bop.c to int32.c
- Introduce InitializeInt32 helper so that one can initialize all the needed 16-bit stubs for the 32-bit interrupts.
- Remove unneeded defines in emulator.h and an exported variable in ntvdm.h.

svn path=/branches/ntvdm/; revision=60908
This commit is contained in:
Hermès Bélusca-Maïto 2013-11-09 23:01:11 +00:00
parent 6da6a5ce56
commit dd9dafc7ff
9 changed files with 227 additions and 432 deletions

View file

@ -6,15 +6,16 @@ spec2def(ntvdm.exe ntvdm.spec)
list(APPEND SOURCE list(APPEND SOURCE
bios.c bios.c
bop.c bop.c
cmos.c
dos.c dos.c
emulator.c emulator.c
int32.c
pic.c pic.c
registers.c
timer.c
ps2.c ps2.c
registers.c
speaker.c speaker.c
timer.c
vga.c vga.c
cmos.c
ntvdm.c ntvdm.c
ntvdm.rc ntvdm.rc
${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def) ${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def)

View file

@ -11,14 +11,14 @@
#define NDEBUG #define NDEBUG
#include "emulator.h" #include "emulator.h"
#include "bop.h"
#include "bios.h" #include "bios.h"
#include "vga.h" #include "vga.h"
#include "pic.h" #include "pic.h"
#include "ps2.h" #include "ps2.h"
#include "timer.h" #include "timer.h"
#include "int32.h"
#include "registers.h" #include "registers.h"
/* PRIVATE VARIABLES **********************************************************/ /* PRIVATE VARIABLES **********************************************************/
@ -461,11 +461,6 @@ BOOLEAN BiosSetVideoPage(BYTE PageNumber)
BOOLEAN BiosInitialize(VOID) BOOLEAN BiosInitialize(VOID)
{ {
USHORT i;
WORD Offset = 0;
LPDWORD IntVecTable = (LPDWORD)BaseAddress;
LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0);
/* Initialize the BDA */ /* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0); Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST; Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
@ -479,43 +474,10 @@ BOOLEAN BiosInitialize(VOID)
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer); Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD); Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
/* Generate ISR stubs and fill the IVT */ /* Initialize the 32-bit Interrupt system */
for (i = 0x00; i <= 0xFF; i++) InitializeInt32(BIOS_SEGMENT);
{
IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT);
BiosCode[Offset++] = 0xFB; // sti /* Register the BIOS 32-bit Interrupts */
BiosCode[Offset++] = 0x6A; // push 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++] = EMULATOR_CTRL_BOP; // Control BOP
BiosCode[Offset++] = CTRL_BOP_INT32; // 32-bit Interrupt dispatcher
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 BOP_SEQ (offset -10)
BiosCode[Offset++] = 0xF6;
// EXIT:
BiosCode[Offset++] = 0x83; // add sp, 4
BiosCode[Offset++] = 0xC4;
BiosCode[Offset++] = 0x04;
BiosCode[Offset++] = 0xCF; // iret
}
RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService ); RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService );
RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );

View file

@ -14,21 +14,10 @@
#include "emulator.h" #include "emulator.h"
#include "bop.h" #include "bop.h"
#include "bios.h" #include "int32.h"
#include "dos.h"
#include "registers.h" #include "registers.h"
LPCWSTR ExceptionName[] = /* PRIVATE VARIABLES **********************************************************/
{
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"
};
/* /*
* This is the list of registered BOP handlers. * This is the list of registered BOP handlers.
@ -293,356 +282,7 @@ EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] =
ControlBop ControlBop
}; };
/* /* PUBLIC FUNCTIONS ***********************************************************/
* This is the list of registered 32-bit Interrupt handlers.
*/
EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT_NUM] =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
{
WORD CodeSegment, InstructionPointer;
PBYTE Opcode;
ASSERT(ExceptionNumber < 8);
/* Get the CS:IP */
InstructionPointer = Stack[STACK_IP];
CodeSegment = Stack[STACK_CS];
Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
/* Display a message to the user */
DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
ExceptionName[ExceptionNumber],
CodeSegment,
InstructionPointer,
Opcode[0],
Opcode[1],
Opcode[2],
Opcode[3],
Opcode[4],
Opcode[5],
Opcode[6],
Opcode[7],
Opcode[8],
Opcode[9]);
/* 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 Int32Dispatch(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;
}
/* Call the 32-bit Interrupt handler */
if (Int32Proc[IntNum] != NULL)
Int32Proc[IntNum](Stack);
else
DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum);
}
VOID WINAPI ControlBop(LPWORD Stack) VOID WINAPI ControlBop(LPWORD Stack)
{ {
@ -656,12 +296,6 @@ VOID WINAPI ControlBop(LPWORD Stack)
DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum); DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
} }
VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
{
Int32Proc[IntNumber] = IntHandler;
}
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode) VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
{ {
WORD StackSegment, StackPointer; WORD StackSegment, StackPointer;

View file

@ -17,21 +17,14 @@
#define EMULATOR_CTRL_BOP 0xFF // Control BOP Handler #define EMULATOR_CTRL_BOP 0xFF // Control BOP Handler
#define CTRL_BOP_DEFLT 0x00 // Default Control BOP Function #define CTRL_BOP_DEFLT 0x00 // Default Control BOP Function
#define CTRL_BOP_INT32 0xFF // 32-bit Interrupt dispatcher
#define EMULATOR_MAX_BOP_NUM 0xFF + 1 #define EMULATOR_MAX_BOP_NUM 0xFF + 1
/* 32-bit Interrupt Identifiers */
#define EMULATOR_MAX_INT_NUM 0xFF + 1
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack); typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
VOID WINAPI ControlBop(LPWORD Stack); VOID WINAPI ControlBop(LPWORD Stack);
VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode); VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode);
#endif // _BOP_H_ #endif // _BOP_H_

View file

@ -11,11 +11,10 @@
#define NDEBUG #define NDEBUG
#include "emulator.h" #include "emulator.h"
#include "bop.h"
#include "dos.h" #include "dos.h"
#include "bios.h"
#include "bios.h"
#include "int32.h"
#include "registers.h" #include "registers.h"
/* PRIVATE VARIABLES **********************************************************/ /* PRIVATE VARIABLES **********************************************************/
@ -2570,7 +2569,7 @@ BOOLEAN DosInitialize(VOID)
DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE); DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE);
DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE); DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE);
/* Register the DOS-32 Interrupts */ /* Register the DOS 32-bit Interrupts */
RegisterInt32(0x20, DosInt20h ); RegisterInt32(0x20, DosInt20h );
RegisterInt32(0x21, DosInt21h ); RegisterInt32(0x21, DosInt21h );
RegisterInt32(0x23, DosBreakInterrupt); RegisterInt32(0x23, DosBreakInterrupt);

View file

@ -34,11 +34,6 @@
#define EMULATOR_FLAG_VIP (1 << 20) #define EMULATOR_FLAG_VIP (1 << 20)
#define EMULATOR_FLAG_ID (1 << 21) #define EMULATOR_FLAG_ID (1 << 21)
/* Common definitions */
#define EMULATOR_BOP 0xC4C4
#define EMULATOR_INT_BOP 0xFF
#define EMULATOR_MAX_BOP_NUM 0xFF + 1
#define STACK_COUNTER 0 #define STACK_COUNTER 0
#define STACK_INT_NUM 1 #define STACK_INT_NUM 1
#define STACK_IP 2 #define STACK_IP 2

181
subsystems/ntvdm/int32.c Normal file
View file

@ -0,0 +1,181 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: int32.c
* PURPOSE: 32-bit Interrupt 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 "int32.h"
#include "bop.h"
#include "bios.h"
/* PRIVATE VARIABLES **********************************************************/
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"
};
/*
* This is the list of registered 32-bit Interrupt handlers.
*/
EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
{
WORD CodeSegment, InstructionPointer;
PBYTE Opcode;
ASSERT(ExceptionNumber < 8);
/* Get the CS:IP */
InstructionPointer = Stack[STACK_IP];
CodeSegment = Stack[STACK_CS];
Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
/* Display a message to the user */
DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
ExceptionName[ExceptionNumber],
CodeSegment,
InstructionPointer,
Opcode[0],
Opcode[1],
Opcode[2],
Opcode[3],
Opcode[4],
Opcode[5],
Opcode[6],
Opcode[7],
Opcode[8],
Opcode[9]);
/* Stop the VDM */
VdmRunning = FALSE;
return;
}
#if 0
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;
}
#endif
VOID WINAPI Int32Dispatch(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;
}
/* Call the 32-bit Interrupt handler */
if (Int32Proc[IntNum] != NULL)
Int32Proc[IntNum](Stack);
else
DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum);
}
VOID WINAPI InitializeInt32(WORD BiosSegment)
{
USHORT i;
WORD Offset = 0;
LPDWORD IntVecTable = (LPDWORD)BaseAddress;
LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
/* Generate ISR stubs and fill the IVT */
for (i = 0x00; i <= 0xFF; i++)
{
IntVecTable[i] = MAKELONG(Offset, BiosSegment);
BiosCode[Offset++] = 0xFB; // sti
BiosCode[Offset++] = 0x6A; // push 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++] = EMULATOR_CTRL_BOP; // Control BOP
BiosCode[Offset++] = CTRL_BOP_INT32; // 32-bit Interrupt dispatcher
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 BOP_SEQ (offset -10)
BiosCode[Offset++] = 0xF6;
// EXIT:
BiosCode[Offset++] = 0x83; // add sp, 4
BiosCode[Offset++] = 0xC4;
BiosCode[Offset++] = 0x04;
BiosCode[Offset++] = 0xCF; // iret
}
}
VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
{
Int32Proc[IntNumber] = IntHandler;
}
/* EOF */

31
subsystems/ntvdm/int32.h Normal file
View file

@ -0,0 +1,31 @@
/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: int32.h
* PURPOSE: 32-bit Interrupt Handlers
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
#ifndef _INT32_H_
#define _INT32_H_
/* DEFINES ********************************************************************/
/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
#define CTRL_BOP_INT32 0xFF
/* 32-bit Interrupt Identifiers */
#define EMULATOR_MAX_INT32_NUM 0xFF + 1
/* FUNCTIONS ******************************************************************/
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
VOID WINAPI Int32Dispatch(LPWORD Stack);
VOID WINAPI InitializeInt32(WORD BiosSegment);
VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
#endif // _INT32_H_
/* EOF */

View file

@ -39,7 +39,6 @@
extern LPVOID BaseAddress; extern LPVOID BaseAddress;
extern BOOLEAN VdmRunning; extern BOOLEAN VdmRunning;
extern LPCWSTR ExceptionName[];
VOID DisplayMessage(LPCWSTR Format, ...); VOID DisplayMessage(LPCWSTR Format, ...);