Add support for interrupts in 32-bit code.
Remove some unnecessary code from 16-bit interrupt emulation.
This commit is contained in:
parent
783bab61de
commit
d25e0399ba
|
@ -171,8 +171,16 @@ struct DPMI_segments
|
|||
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 @@ extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
|
|||
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 );
|
||||
|
|
|
@ -686,19 +686,22 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
|||
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;
|
||||
|
|
|
@ -161,6 +161,7 @@ static void DOSMEM_MakeIsrStubs(void)
|
|||
static void DOSMEM_InitDPMI(void)
|
||||
{
|
||||
LPSTR ptr;
|
||||
int i;
|
||||
|
||||
static const char wrap_code[]={
|
||||
0xCD,0x31, /* int $0x31 */
|
||||
|
@ -210,6 +211,20 @@ static void DOSMEM_InitDPMI(void)
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
@ -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)
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue