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