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 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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue