Add support for interrupts in 32-bit code.

Remove some unnecessary code from 16-bit interrupt emulation.
This commit is contained in:
Jukka Heinonen 2002-10-08 00:35:03 +00:00 committed by Alexandre Julliard
parent 783bab61de
commit d25e0399ba
4 changed files with 68 additions and 8 deletions

View File

@ -171,8 +171,16 @@ struct DPMI_segments
WORD xms_seg; WORD xms_seg;
WORD dpmi_seg; WORD dpmi_seg;
WORD dpmi_sel; 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 struct DPMI_segments DOSMEM_dpmi_segments;
extern const struct DPMI_segments *DOSMEM_GetDPMISegments(void); extern const struct DPMI_segments *DOSMEM_GetDPMISegments(void);
@ -194,6 +202,8 @@ extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
typedef void (WINAPI *INTPROC)(CONTEXT86*); typedef void (WINAPI *INTPROC)(CONTEXT86*);
extern FARPROC16 INT_GetPMHandler( BYTE intnum ); extern FARPROC16 INT_GetPMHandler( BYTE intnum );
extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler ); 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 */ /* msdos/ioports.c */
extern DWORD IO_inport( int port, int count ); extern DWORD IO_inport( int port, int count );

View File

@ -686,19 +686,22 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
case 0xcd: /* int <XX> */ case 0xcd: /* int <XX> */
if (long_op) if (long_op)
{ {
ERR("int xx from 32-bit code is not supported.\n"); FARPROC48 addr = INT_GetPMHandler48( instr[1] );
break; /* Unable to emulate it */ 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 else
{ {
FARPROC16 addr = INT_GetPMHandler( instr[1] ); FARPROC16 addr = INT_GetPMHandler( instr[1] );
WORD *stack = get_stack( context ); 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 */ /* Push the flags and return address on the stack */
*(--stack) = LOWORD(context->EFlags); *(--stack) = LOWORD(context->EFlags);
*(--stack) = context->SegCs; *(--stack) = context->SegCs;

View File

@ -161,6 +161,7 @@ static void DOSMEM_MakeIsrStubs(void)
static void DOSMEM_InitDPMI(void) static void DOSMEM_InitDPMI(void)
{ {
LPSTR ptr; LPSTR ptr;
int i;
static const char wrap_code[]={ static const char wrap_code[]={
0xCD,0x31, /* int $0x31 */ 0xCD,0x31, /* int $0x31 */
@ -210,6 +211,20 @@ static void DOSMEM_InitDPMI(void)
ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_segments.dpmi_seg ); ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_segments.dpmi_seg );
memcpy( ptr, enter_pm, sizeof(enter_pm) ); memcpy( ptr, enter_pm, sizeof(enter_pm) );
DOSMEM_dpmi_segments.dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), WINE_LDT_FLAGS_CODE ); 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) static BIOSDATA * DOSMEM_BiosData(void)

View File

@ -29,6 +29,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(int); WINE_DEFAULT_DEBUG_CHANNEL(int);
static FARPROC16 INT_Vectors[256]; static FARPROC16 INT_Vectors[256];
static FARPROC48 INT_Vectors48[256];
/* Ordinal number for interrupt 0 handler in WPROCS.DLL */ /* Ordinal number for interrupt 0 handler in WPROCS.DLL */
#define FIRST_INTERRUPT 100 #define FIRST_INTERRUPT 100
@ -76,6 +77,37 @@ void INT_SetPMHandler( BYTE intnum, FARPROC16 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;
}
/********************************************************************** /**********************************************************************
* INT_DefaultHandler (WPROCS.356) * INT_DefaultHandler (WPROCS.356)
* *