Remove the old "INT 0xFF" hack and instead use an invalid opcode sequence for emulator operations.
Fix the flags register update bug.


svn path=/branches/ntvdm/; revision=59565
This commit is contained in:
Aleksandar Andrejevic 2013-07-23 19:31:00 +00:00
parent 7bcfe7b2a8
commit 6be35ef0bb
3 changed files with 57 additions and 31 deletions

View file

@ -374,20 +374,19 @@ BOOLEAN BiosInitialize()
IntVecTable[i * 2] = Offset; IntVecTable[i * 2] = Offset;
IntVecTable[i * 2 + 1] = BIOS_SEGMENT; IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
if (i != SPECIAL_INT_NUM) BiosCode[Offset++] = 0xFA; // cli
{
BiosCode[Offset++] = 0xFA; // cli
BiosCode[Offset++] = 0x6A; // push i BiosCode[Offset++] = 0x6A; // push i
BiosCode[Offset++] = (BYTE)i; BiosCode[Offset++] = (BYTE)i;
BiosCode[Offset++] = 0xCD; // int SPECIAL_INT_NUM BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
BiosCode[Offset++] = SPECIAL_INT_NUM; BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
BiosCode[Offset++] = LOBYTE(EMULATOR_INT_BOP);
BiosCode[Offset++] = HIBYTE(EMULATOR_INT_BOP);
BiosCode[Offset++] = 0x83; // add sp, 2 BiosCode[Offset++] = 0x83; // add sp, 2
BiosCode[Offset++] = 0xC4; BiosCode[Offset++] = 0xC4;
BiosCode[Offset++] = 0x02; BiosCode[Offset++] = 0x02;
}
BiosCode[Offset++] = 0xCF; // iret BiosCode[Offset++] = 0xCF; // iret
} }

View file

@ -165,34 +165,32 @@ static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size
} }
} }
static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number) static VOID EmulatorBop(WORD Code)
{ {
WORD StackSegment, StackPointer, CodeSegment, InstructionPointer; WORD StackSegment, StackPointer, CodeSegment, InstructionPointer;
BYTE IntNum; BYTE IntNum;
LPWORD Stack;
/* Check if this is the special interrupt */ /* Get the SS:SP */
if (Number == SPECIAL_INT_NUM)
{
/* Get the SS:SP */
#ifndef NEW_EMULATOR #ifndef NEW_EMULATOR
StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val; StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val; StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
#else #else
StackSegment = EmulatorContext.Registers[EMULATOR_REG_SS].LowWord; StackSegment = EmulatorContext.Registers[EMULATOR_REG_SS].LowWord;
StackPointer = EmulatorContext.Registers[EMULATOR_REG_SP].LowWord; StackPointer = EmulatorContext.Registers[EMULATOR_REG_SP].LowWord;
#endif #endif
/* Get the interrupt number */ /* Get the stack */
IntNum = *(LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(StackSegment, StackPointer)); Stack = (LPWORD)((ULONG_PTR)BaseAddress + TO_LINEAR(StackSegment, StackPointer));
/* Move the stack pointer forward one word to skip the interrupt number */ if (Code == EMULATOR_INT_BOP)
StackPointer += sizeof(WORD); {
/* Get the interrupt number */
IntNum = LOBYTE(Stack[0]);
/* Get the CS:IP */ /* Get the CS:IP */
InstructionPointer = *(LPWORD)((ULONG_PTR)BaseAddress InstructionPointer = Stack[1];
+ TO_LINEAR(StackSegment, StackPointer)); CodeSegment = Stack[2];
CodeSegment = *(LPWORD)((ULONG_PTR)BaseAddress
+ TO_LINEAR(StackSegment, StackPointer + sizeof(WORD)));
/* Check if this was an exception */ /* Check if this was an exception */
if (IntNum < 8) if (IntNum < 8)
@ -275,9 +273,21 @@ static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
break; break;
} }
} }
/* Update the flags on the stack */
#ifndef NEW_EMULATOR
Stack[3] = EmulatorContext.state->reg_flags.val;
#else
Stack[3] = EmulatorContext.Flags.LowWord;
#endif
} }
} }
static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
{
/* Do nothing */
}
static VOID EmulatorHardwareInt(PVOID Context, BYTE Number) static VOID EmulatorHardwareInt(PVOID Context, BYTE Number)
{ {
/* Do nothing */ /* Do nothing */
@ -445,14 +455,30 @@ VOID EmulatorClearFlag(ULONG Flag)
#endif #endif
} }
VOID EmulatorStep() VOID EmulatorStep(VOID)
{ {
LPWORD Instruction;
#ifndef NEW_EMULATOR #ifndef NEW_EMULATOR
/* Print the current position - useful for debugging */ /* Print the current position - useful for debugging */
DPRINT("Executing at CS:IP = %04X:%04X\n", DPRINT("Executing at CS:IP = %04X:%04X\n",
EmulatorGetRegister(EMULATOR_REG_CS), EmulatorGetRegister(EMULATOR_REG_CS),
EmulatorContext.state->reg_ip); EmulatorContext.state->reg_ip);
Instruction = (LPWORD)((ULONG_PTR)BaseAddress
+ TO_LINEAR(EmulatorGetRegister(EMULATOR_REG_CS),
EmulatorContext.state->reg_ip));
/* Check for the BIOS operation (BOP) sequence */
if (Instruction[0] == EMULATOR_BOP)
{
/* Skip the opcodes */
EmulatorContext.state->reg_ip += 4;
/* Call the BOP handler */
EmulatorBop(Instruction[1]);
}
/* Call the softx86 API */ /* Call the softx86 API */
if (!softx86_step(&EmulatorContext)) if (!softx86_step(&EmulatorContext))
{ {
@ -464,7 +490,7 @@ VOID EmulatorStep()
#endif #endif
} }
VOID EmulatorCleanup() VOID EmulatorCleanup(VOID)
{ {
/* Free the memory allocated for the 16-bit address space */ /* Free the memory allocated for the 16-bit address space */
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress); if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);

View file

@ -70,7 +70,8 @@
#define EMULATOR_NUM_CONTROL_REGS 8 #define EMULATOR_NUM_CONTROL_REGS 8
#define EMULATOR_NUM_DEBUG_REGS 8 #define EMULATOR_NUM_DEBUG_REGS 8
#define MAX_GDT_ENTRIES 8192 #define MAX_GDT_ENTRIES 8192
#define SPECIAL_INT_NUM 0xFF #define EMULATOR_BOP 0xC4C4
#define EMULATOR_INT_BOP 0xBEEF
enum enum
{ {