DOS DPMI32, interrupt handlers in 32-bit code

Jukka Heinonen jhei at iki.fi
Sun Oct 6 08:07:03 CDT 2002


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/>



More information about the wine-patches mailing list