Add support for interrupts in 32-bit code. Remove some unnecessary code from 16-bit interrupt emulation.
diff --git a/include/miscemu.h b/include/miscemu.h index 8c8367e..31464f8 100644 --- a/include/miscemu.h +++ b/include/miscemu.h
@@ -171,8 +171,16 @@ WORD xms_seg; WORD dpmi_seg; WORD dpmi_sel; + WORD int48_seg; + WORD int48_sel; }; +/* 48-bit segmented pointers for DOS DPMI32 */ +typedef struct { + WORD selector; + DWORD offset; +} SEGPTR48, FARPROC48; + extern struct DPMI_segments DOSMEM_dpmi_segments; extern const struct DPMI_segments *DOSMEM_GetDPMISegments(void); @@ -194,6 +202,8 @@ typedef void (WINAPI *INTPROC)(CONTEXT86*); extern FARPROC16 INT_GetPMHandler( BYTE intnum ); extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler ); +extern FARPROC48 INT_GetPMHandler48( BYTE intnum ); +extern void INT_SetPMHandler48( BYTE intnum, FARPROC48 handler ); /* msdos/ioports.c */ extern DWORD IO_inport( int port, int count );
diff --git a/memory/instr.c b/memory/instr.c index f1a30d2..dc1c459 100644 --- a/memory/instr.c +++ b/memory/instr.c
@@ -686,19 +686,22 @@ case 0xcd: /* int <XX> */ if (long_op) { - ERR("int xx from 32-bit code is not supported.\n"); - break; /* Unable to emulate it */ + FARPROC48 addr = INT_GetPMHandler48( instr[1] ); + DWORD *stack = get_stack( context ); + /* Push the flags and return address on the stack */ + *(--stack) = context->EFlags; + *(--stack) = context->SegCs; + *(--stack) = context->Eip + prefixlen + 2; + add_stack(context, -3 * sizeof(DWORD)); + /* Jump to the interrupt handler */ + context->SegCs = addr.selector; + context->Eip = addr.offset; + return TRUE; } else { FARPROC16 addr = INT_GetPMHandler( instr[1] ); WORD *stack = get_stack( context ); - if (!addr) - { - FIXME("no handler for interrupt %02x, ignoring it\n", instr[1]); - context->Eip += prefixlen + 2; - return TRUE; - } /* Push the flags and return address on the stack */ *(--stack) = LOWORD(context->EFlags); *(--stack) = context->SegCs;
diff --git a/msdos/dosmem.c b/msdos/dosmem.c index 8b361fc..c4685c4 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c
@@ -161,6 +161,7 @@ static void DOSMEM_InitDPMI(void) { LPSTR ptr; + int i; static const char wrap_code[]={ 0xCD,0x31, /* int $0x31 */ @@ -210,6 +211,20 @@ ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_segments.dpmi_seg ); memcpy( ptr, enter_pm, sizeof(enter_pm) ); DOSMEM_dpmi_segments.dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), WINE_LDT_FLAGS_CODE ); + + ptr = DOSMEM_GetBlock( 4 * 256, &DOSMEM_dpmi_segments.int48_seg ); + for(i=0; i<256; i++) { + /* + * Each 32-bit interrupt handler is 4 bytes: + * 0xCD,<i> = int <i> (nested 16-bit interrupt) + * 0x66,0xCF = iretd (32-bit interrupt return) + */ + ptr[i * 4 + 0] = 0xCD; + ptr[i * 4 + 1] = i; + ptr[i * 4 + 2] = 0x66; + ptr[i * 4 + 3] = 0xCF; + } + DOSMEM_dpmi_segments.int48_sel = SELECTOR_AllocBlock( ptr, 4 * 256, WINE_LDT_FLAGS_CODE ); } static BIOSDATA * DOSMEM_BiosData(void)
diff --git a/msdos/interrupts.c b/msdos/interrupts.c index 27e75c6..0802c69 100644 --- a/msdos/interrupts.c +++ b/msdos/interrupts.c
@@ -29,6 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(int); static FARPROC16 INT_Vectors[256]; +static FARPROC48 INT_Vectors48[256]; /* Ordinal number for interrupt 0 handler in WPROCS.DLL */ #define FIRST_INTERRUPT 100 @@ -77,6 +78,37 @@ /********************************************************************** + * INT_GetPMHandler48 + * + * Return the protected mode interrupt vector for a given interrupt. + * Used to get 48-bit pointer for 32-bit interrupt handlers in DPMI32. + */ +FARPROC48 INT_GetPMHandler48( BYTE intnum ) +{ + if (!INT_Vectors48[intnum].selector) + { + INT_Vectors48[intnum].selector = DOSMEM_dpmi_segments.int48_sel; + INT_Vectors48[intnum].offset = 4 * intnum; + } + return INT_Vectors48[intnum]; +} + + +/********************************************************************** + * INT_SetPMHandler48 + * + * Set the protected mode interrupt handler for a given interrupt. + * Used to set 48-bit pointer for 32-bit interrupt handlers in DPMI32. + */ +void INT_SetPMHandler48( BYTE intnum, FARPROC48 handler ) +{ + TRACE("Set 32-bit protected mode interrupt vector %02x <- %04x:%08x\n", + intnum, handler.selector, handler.offset ); + INT_Vectors48[intnum] = handler; +} + + +/********************************************************************** * INT_DefaultHandler (WPROCS.356) * * Default interrupt handler.