Start my work on modularizing registration of "32-bit" interrupts, i.e.
interrupts that are implemented in 32-bit mode, but are stubbed with 16-bit
code (so that 16-bit apps can call them).
The 16-bit stub code uses a BOP call to our Control BOP function (BOP 0xFF) which
can handle in theory many sub-functions (as the BOP 0x58 documented here: http://www.ragestorm.net/tutorial?id=27)
specified as an additional BYTE in the call:
0xC4 0xC4 bop_code <optional_bop_subfunction>
Here, for calling 32-bit interrupts we use our BOP 0xFF, subfunction 0xFF.
The final aim would be to generate the 16-bit stub code when one calls the RegisterInt32 helper function
(contrary to what's happening now, that is, the 16-bit stub code is generated for all of the interrupts
at BIOS initialization time, and we use it for BIOS and DOS interrupts).

svn path=/branches/ntvdm/; revision=60907
This commit is contained in:
Hermès Bélusca-Maïto 2013-11-09 22:15:40 +00:00
parent bf61aa1278
commit 6da6a5ce56
8 changed files with 390 additions and 131 deletions

View file

@ -10,8 +10,10 @@
#define NDEBUG
#include "bios.h"
#include "emulator.h"
#include "bop.h"
#include "bios.h"
#include "vga.h"
#include "pic.h"
#include "ps2.h"
@ -461,7 +463,7 @@ BOOLEAN BiosInitialize(VOID)
{
USHORT i;
WORD Offset = 0;
LPWORD IntVecTable = (LPWORD)BaseAddress;
LPDWORD IntVecTable = (LPDWORD)BaseAddress;
LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0);
/* Initialize the BDA */
@ -480,8 +482,7 @@ BOOLEAN BiosInitialize(VOID)
/* Generate ISR stubs and fill the IVT */
for (i = 0x00; i <= 0xFF; i++)
{
IntVecTable[i * 2] = Offset;
IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT);
BiosCode[Offset++] = 0xFB; // sti
@ -494,9 +495,10 @@ BOOLEAN BiosInitialize(VOID)
// BOP_SEQ:
BiosCode[Offset++] = 0xF8; // clc
BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
BiosCode[Offset++] = EMULATOR_INT_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;
@ -504,8 +506,8 @@ BOOLEAN BiosInitialize(VOID)
// HACK: The following instruction should be HLT!
BiosCode[Offset++] = 0x90; // nop
BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9)
BiosCode[Offset++] = 0xF7;
BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10)
BiosCode[Offset++] = 0xF6;
// EXIT:
BiosCode[Offset++] = 0x83; // add sp, 4
@ -514,6 +516,12 @@ BOOLEAN BiosInitialize(VOID)
BiosCode[Offset++] = 0xCF; // iret
}
RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService );
RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
RegisterInt32(BIOS_KBD_INTERRUPT , BiosKeyboardService );
RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
/* Get the input handle to the real console, and check for success */
BiosConsoleInput = CreateFileW(L"CONIN$",
@ -818,7 +826,7 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
BiosSetCursorPosition(Row, Column, Page);
}
VOID BiosVideoService(LPWORD Stack)
VOID WINAPI BiosVideoService(LPWORD Stack)
{
switch (getAH())
{
@ -1194,19 +1202,19 @@ VOID BiosVideoService(LPWORD Stack)
}
}
VOID BiosEquipmentService(LPWORD Stack)
VOID WINAPI BiosEquipmentService(LPWORD Stack)
{
/* Return the equipment list */
setAX(Bda->EquipmentList);
}
VOID BiosGetMemorySize(LPWORD Stack)
VOID WINAPI BiosGetMemorySize(LPWORD Stack)
{
/* Return the conventional memory size in kB, typically 640 kB */
setAX(Bda->MemorySize);
}
VOID BiosKeyboardService(LPWORD Stack)
VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
@ -1288,7 +1296,7 @@ VOID BiosKeyboardService(LPWORD Stack)
}
}
VOID BiosTimeService(LPWORD Stack)
VOID WINAPI BiosTimeService(LPWORD Stack)
{
switch (getAH())
{
@ -1326,7 +1334,7 @@ VOID BiosTimeService(LPWORD Stack)
}
}
VOID BiosSystemTimerInterrupt(LPWORD Stack)
VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
{
/* Increase the system tick count */
Bda->TickCounter++;

View file

@ -159,13 +159,6 @@ WORD BiosPeekCharacter(VOID);
WORD BiosGetCharacter(VOID);
VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page);
VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page);
VOID BiosVideoService(LPWORD Stack);
VOID BiosEquipmentService(LPWORD Stack);
VOID BiosGetMemorySize(LPWORD Stack);
VOID BiosKeyboardService(LPWORD Stack);
VOID BiosTimeService(LPWORD Stack);
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
VOID BiosSystemTimerInterrupt(LPWORD Stack);
VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page);
BOOLEAN BiosScrollWindow(
INT Direction,
@ -175,6 +168,15 @@ BOOLEAN BiosScrollWindow(
BYTE FillAttribute
);
VOID WINAPI BiosVideoService(LPWORD Stack);
VOID WINAPI BiosEquipmentService(LPWORD Stack);
VOID WINAPI BiosGetMemorySize(LPWORD Stack);
VOID WINAPI BiosKeyboardService(LPWORD Stack);
VOID WINAPI BiosTimeService(LPWORD Stack);
VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack);
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
#endif // _BIOS_H_
/* EOF */

View file

@ -12,13 +12,10 @@
#define NDEBUG
#include "emulator.h"
#include "bios.h"
#include "bop.h"
#include "bios.h"
#include "dos.h"
//#include "vga.h"
//#include "pic.h"
//#include "ps2.h"
//#include "timer.h"
#include "registers.h"
LPCWSTR ExceptionName[] =
@ -33,6 +30,9 @@ LPCWSTR ExceptionName[] =
L"FPU Not Available"
};
/*
* This is the list of registered BOP handlers.
*/
EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] =
{
NULL,
@ -293,6 +293,271 @@ 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;
@ -344,11 +609,7 @@ VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
// return;
// }
// VOID WINAPI BiosInt(BYTE IntNumber, LPWORD Stack)
// {
// }
VOID WINAPI IntDispatch(LPWORD Stack)
VOID WINAPI Int32Dispatch(LPWORD Stack)
{
BYTE IntNum;
@ -376,77 +637,48 @@ VOID WINAPI IntDispatch(LPWORD 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_MEMORY_SIZE:
{
/* This is the BIOS "get memory size" command, call the BIOS */
BiosGetMemorySize(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;
}
case 0x2F:
{
DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
getAH(), getAL());
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
}
default:
{
DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum);
break;
}
}
/* 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)
{
IntDispatch(Stack);
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
if (FuncNum == CTRL_BOP_INT32)
Int32Dispatch(Stack);
else
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;
LPWORD Stack;
/* Get the SS:SP */
StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
/* Get the stack */
Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
/* Call the BOP handler */
if (BopProc[BopCode] != NULL)
BopProc[BopCode](Stack);
else
DPRINT1("Invalid BOP code: 0x%02X\n", BopCode);
}
/* EOF */

View file

@ -7,10 +7,33 @@
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack);
#ifndef _BOP_H_
#define _BOP_H_
extern EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM];
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define EMULATOR_BOP 0xC4C4
#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_
/* EOF */

View file

@ -10,9 +10,11 @@
#define NDEBUG
#include "emulator.h"
#include "bop.h"
#include "dos.h"
#include "bios.h"
#include "emulator.h"
#include "registers.h"
@ -1393,13 +1395,13 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
}
}
VOID DosInt20h(LPWORD Stack)
VOID WINAPI DosInt20h(LPWORD Stack)
{
/* This is the exit interrupt */
DosTerminateProcess(Stack[STACK_CS], 0);
}
VOID DosInt21h(LPWORD Stack)
VOID WINAPI DosInt21h(LPWORD Stack)
{
BYTE Character;
SYSTEMTIME SystemTime;
@ -2415,13 +2417,20 @@ VOID DosInt21h(LPWORD Stack)
}
}
VOID DosBreakInterrupt(LPWORD Stack)
VOID WINAPI DosBreakInterrupt(LPWORD Stack)
{
UNREFERENCED_PARAMETER(Stack);
VdmRunning = FALSE;
}
VOID WINAPI DosInt2Fh(LPWORD Stack)
{
DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
getAH(), getAL());
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
BOOLEAN DosInitialize(VOID)
{
BYTE i;
@ -2561,6 +2570,12 @@ BOOLEAN DosInitialize(VOID)
DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE);
DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE);
/* Register the DOS-32 Interrupts */
RegisterInt32(0x20, DosInt20h );
RegisterInt32(0x21, DosInt21h );
RegisterInt32(0x23, DosBreakInterrupt);
RegisterInt32(0x2F, DosInt2Fh );
return TRUE;
}

View file

@ -136,9 +136,12 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
CHAR DosReadCharacter(VOID);
VOID DosPrintCharacter(CHAR Character);
BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
VOID DosInt20h(LPWORD Stack);
VOID DosInt21h(LPWORD Stack);
VOID DosBreakInterrupt(LPWORD Stack);
VOID WINAPI DosInt20h(LPWORD Stack);
VOID WINAPI DosInt21h(LPWORD Stack);
VOID WINAPI DosBreakInterrupt(LPWORD Stack);
VOID WINAPI DosInt2Fh(LPWORD Stack);
BOOLEAN DosInitialize(VOID);
#endif // _DOS_H_

View file

@ -272,24 +272,6 @@ VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULON
}
}
VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
{
WORD StackSegment, StackPointer;
LPWORD Stack;
/* Get the SS:SP */
StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector;
StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord;
/* Get the stack */
Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
if (BopProc[BopCode] != NULL)
BopProc[BopCode](Stack);
else
DPRINT1("Invalid BOP code %u\n", BopCode);
}
UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
{
UNREFERENCED_PARAMETER(State);

View file

@ -120,12 +120,6 @@ VOID WINAPI EmulatorWriteIo
UCHAR DataSize
);
VOID WINAPI EmulatorBiosOperation
(
PFAST486_STATE State,
UCHAR BopCode
);
UCHAR WINAPI EmulatorIntAcknowledge
(
PFAST486_STATE State