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
bios.c
bop.c
cmos.c
dos.c
emulator.c
int32.c
pic.c
registers.c
timer.c
ps2.c
registers.c
speaker.c
timer.c
vga.c
cmos.c
ntvdm.c
ntvdm.rc
${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def)

View file

@ -11,14 +11,14 @@
#define NDEBUG
#include "emulator.h"
#include "bop.h"
#include "bios.h"
#include "vga.h"
#include "pic.h"
#include "ps2.h"
#include "timer.h"
#include "int32.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
@ -461,11 +461,6 @@ BOOLEAN BiosSetVideoPage(BYTE PageNumber)
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 */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
@ -479,43 +474,10 @@ BOOLEAN BiosInitialize(VOID)
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
/* Generate ISR stubs and fill the IVT */
for (i = 0x00; i <= 0xFF; i++)
{
IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT);
/* Initialize the 32-bit Interrupt system */
InitializeInt32(BIOS_SEGMENT);
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
}
/* Register the BIOS 32-bit Interrupts */
RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService );
RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );

View file

@ -14,21 +14,10 @@
#include "emulator.h"
#include "bop.h"
#include "bios.h"
#include "dos.h"
#include "int32.h"
#include "registers.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"
};
/* PRIVATE VARIABLES **********************************************************/
/*
* This is the list of registered BOP handlers.
@ -293,356 +282,7 @@ EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] =
ControlBop
};
/*
* 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);
}
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI ControlBop(LPWORD Stack)
{
@ -656,12 +296,6 @@ VOID WINAPI ControlBop(LPWORD Stack)
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)
{
WORD StackSegment, StackPointer;

View file

@ -17,21 +17,14 @@
#define EMULATOR_CTRL_BOP 0xFF // Control BOP Handler
#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
/* 32-bit Interrupt Identifiers */
#define EMULATOR_MAX_INT_NUM 0xFF + 1
/* FUNCTIONS ******************************************************************/
typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);
VOID WINAPI ControlBop(LPWORD Stack);
VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler);
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode);
#endif // _BOP_H_

View file

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

View file

@ -34,11 +34,6 @@
#define EMULATOR_FLAG_VIP (1 << 20)
#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_INT_NUM 1
#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 BOOLEAN VdmRunning;
extern LPCWSTR ExceptionName[];
VOID DisplayMessage(LPCWSTR Format, ...);