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.