This almost trivial patch adds support for interrupts in 32-bit code. DOS DPMI32 programs require this. Interrupt handlers would still need to be modified to properly support DPMI32 and I still have to figure out why dos4gw fails to start... Also, the patch removes an unnecessary check from 16-bit interrupt emulation (interrupts always have handlers even though handlers may be dummy handlers). Changelog: Add support for interrupts in 32-bit code. Remove some unnecessary code from 16-bit interrupt emulation. Index: include/miscemu.h =================================================================== RCS file: /home/wine/wine/include/miscemu.h,v retrieving revision 1.53 diff -u -r1.53 miscemu.h --- include/miscemu.h 4 Sep 2002 18:52:22 -0000 1.53 +++ include/miscemu.h 6 Oct 2002 12:41:47 -0000 @@ -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 ); Index: memory/instr.c =================================================================== RCS file: /home/wine/wine/memory/instr.c,v retrieving revision 1.17 diff -u -r1.17 instr.c --- memory/instr.c 17 Aug 2002 01:22:59 -0000 1.17 +++ memory/instr.c 6 Oct 2002 12:42:07 -0000 @@ -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; Index: msdos/interrupts.c =================================================================== RCS file: /home/wine/wine/msdos/interrupts.c,v retrieving revision 1.22 diff -u -r1.22 interrupts.c --- msdos/interrupts.c 10 Mar 2002 00:18:35 -0000 1.22 +++ msdos/interrupts.c 6 Oct 2002 12:42:21 -0000 @@ -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 @@ -73,6 +74,37 @@ TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n", intnum, HIWORD(handler), LOWORD(handler) ); INT_Vectors[intnum] = handler; +} + + +/********************************************************************** + * 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; } Index: msdos/dosmem.c =================================================================== RCS file: /home/wine/wine/msdos/dosmem.c,v retrieving revision 1.42 diff -u -r1.42 dosmem.c --- msdos/dosmem.c 4 Sep 2002 18:52:22 -0000 1.42 +++ msdos/dosmem.c 6 Oct 2002 12:42:46 -0000 @@ -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) -- Jukka Heinonen <http://www.iki.fi/jhei/>