Commit 4c6e36fa authored by Jukka Heinonen's avatar Jukka Heinonen Committed by Alexandre Julliard

Move real mode interrupt emulation code to file interrupts.c.

Remove last wrapper check from int31 handler. Move RM/PM hardware interrupt emulation code to separate functions.
parent 2918ee6b
......@@ -93,7 +93,6 @@ extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVO
extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
extern void WINAPI DOSVM_SetTimer( UINT ticks );
extern UINT WINAPI DOSVM_GetTimer( void );
extern void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
/* devices.c */
extern void DOSDEV_InstallDOSDevices(void);
......@@ -198,6 +197,7 @@ extern BOOL DOSVM_IsDos32(void);
extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC);
extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int);
extern BOOL DOSVM_CheckWrappers(CONTEXT86*);
/* int33.c */
extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
......@@ -218,13 +218,17 @@ extern void WINAPI DOSVM_Int67Handler(CONTEXT86*);
extern void WINAPI EMS_Ioctl_Handler(CONTEXT86*);
/* interrupts.c */
extern FARPROC16 DOSVM_GetRMHandler( BYTE intnum );
extern void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler );
extern FARPROC16 DOSVM_GetPMHandler16( BYTE intnum );
extern void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler );
extern FARPROC48 DOSVM_GetPMHandler48( BYTE intnum );
extern void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler );
extern INTPROC DOSVM_GetBuiltinHandler( BYTE intnum );
extern void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *, BYTE );
extern void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *, BYTE );
extern BOOL WINAPI DOSVM_EmulateInterruptRM( CONTEXT86 *, BYTE );
extern FARPROC16 DOSVM_GetPMHandler16( BYTE );
extern FARPROC48 DOSVM_GetPMHandler48( BYTE );
extern FARPROC16 DOSVM_GetRMHandler( BYTE );
extern void DOSVM_HardwareInterruptPM( CONTEXT86 *, BYTE );
extern void DOSVM_HardwareInterruptRM( CONTEXT86 *, BYTE );
extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 );
extern void DOSVM_SetPMHandler48( BYTE, FARPROC48 );
extern void DOSVM_SetRMHandler( BYTE, FARPROC16 );
/* relay.c */
void DOSVM_RelayHandler( CONTEXT86 * );
......
......@@ -92,53 +92,6 @@ static int sig_sent;
static HANDLE event_notifier;
static CONTEXT86 *current_context;
static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine )
{
FARPROC16 handler=DOSVM_GetRMHandler(vect);
/* check for our real-mode hooks */
if (vect==0x31) {
if (context->SegCs==DOSVM_dpmi_segments->wrap_seg) {
/* exit from real-mode wrapper */
return -1;
}
/* we could probably move some other dodgy stuff here too from dpmi.c */
}
/* check if the call is from our fake BIOS interrupt stubs */
if ((context->SegCs==0xf000) && !inwine) {
if (vect != (context->Eip/4)) {
TRACE("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
}
TRACE("builtin interrupt %02x has been branched to\n", vect);
DOSVM_RealModeInterrupt(vect, context);
}
/* check if the call goes to an unhooked interrupt */
else if (SELECTOROF(handler)==0xf000) {
/* if so, call it directly */
TRACE("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
DOSVM_RealModeInterrupt(OFFSETOF(handler)/4, context);
}
/* the interrupt is hooked, simulate interrupt in DOS space */
else {
WORD*stack= PTR_REAL_TO_LIN( context->SegSs, context->Esp );
WORD flag=LOWORD(context->EFlags);
TRACE_(int)("invoking hooked interrupt %02x at %04x:%04x\n", vect,
SELECTOROF(handler), OFFSETOF(handler));
if (IF_ENABLED(context)) flag|=IF_MASK;
else flag&=~IF_MASK;
*(--stack)=flag;
*(--stack)=context->SegCs;
*(--stack)=LOWORD(context->Eip);
context->Esp-=6;
context->SegCs=SELECTOROF(handler);
context->Eip=OFFSETOF(handler);
IF_CLR(context);
}
return 0;
}
#define SHOULD_PEND(x) \
(x && ((!current_event) || (x->priority < current_event->priority)))
......@@ -157,7 +110,8 @@ static void DOSVM_SendQueuedEvent(CONTEXT86 *context)
TRACE("dispatching IRQ %d\n",event->irq);
/* note that if DOSVM_SimulateInt calls an internal interrupt directly,
* current_event might be cleared (and event freed) in this very call! */
DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,TRUE);
DOSVM_HardwareInterruptRM( context, (event->irq < 8) ?
(event->irq + 8) : (event->irq - 8 + 0x70) );
} else {
/* callback event */
TRACE("dispatching callback event\n");
......@@ -440,7 +394,8 @@ static WINE_EXCEPTION_FILTER(exception_handler)
{
EXCEPTION_RECORD *rec = GetExceptionInformation()->ExceptionRecord;
CONTEXT *context = GetExceptionInformation()->ContextRecord;
int ret, arg = rec->ExceptionInformation[0];
int arg = rec->ExceptionInformation[0];
BOOL ret;
switch(rec->ExceptionCode) {
case EXCEPTION_VM86_INTx:
......@@ -454,7 +409,7 @@ static WINE_EXCEPTION_FILTER(exception_handler)
context->Ebp, context->Esp, context->SegDs, context->SegEs,
context->SegFs, context->SegGs, context->EFlags );
}
ret = DOSVM_SimulateInt(arg, context, FALSE);
ret = DOSVM_EmulateInterruptRM( context, arg );
if (TRACE_ON(relay)) {
DPRINTF("Ret DOS int 0x%02x ret=%04lx:%04lx\n",
arg, context->SegCs, context->Eip );
......@@ -465,7 +420,7 @@ static WINE_EXCEPTION_FILTER(exception_handler)
context->Ebp, context->Esp, context->SegDs, context->SegEs,
context->SegFs, context->SegGs, context->EFlags );
}
return ret ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION;
return ret ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
case EXCEPTION_VM86_STI:
/* case EXCEPTION_VM86_PICRETURN: */
......@@ -627,17 +582,6 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
#endif
/**********************************************************************
* DOSVM_RealModeInterrupt
*
* Handle real mode interrupts
*/
void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
{
INTPROC proc = DOSVM_GetBuiltinHandler( intnum );
proc(context);
}
/**********************************************************************
* DllMain (DOSVM.Init)
......
......@@ -387,7 +387,7 @@ callrmproc_again:
/* shortcut for chaining to internal interrupt handlers */
if ((context->SegCs == 0xF000) && iret)
{
DOSVM_RealModeInterrupt( LOWORD(context->Eip)/4, context);
DOSVM_CallBuiltinHandler( context, LOWORD(context->Eip)/4 );
return 0;
}
......@@ -475,7 +475,7 @@ void WINAPI DOSVM_CallRMInt( CONTEXT86 *context )
RESET_CFLAG(context);
/* use the IP we have instead of BL_reg, in case some apps
decide to move interrupts around for whatever reason... */
DOSVM_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx );
DOSVM_CallBuiltinHandler( &realmode_ctx, LOWORD(rm_int)/4 );
}
INT_SetRealModeContext( call, &realmode_ctx );
}
......@@ -744,14 +744,9 @@ void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT86 *context )
* DOSVM_CheckWrappers
*
* Check if this was really a wrapper call instead of an interrupt.
* FIXME: Protected mode stuff does not work in 32-bit DPMI.
* FIXME: If int31 is called asynchronously (unlikely)
* wrapper checks are wrong (CS/IP must not be used).
*/
static BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
{
/* check if it's our wrapper */
TRACE("called from real mode\n");
if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) {
/* This is the protected mode switch */
StartPM(context);
......@@ -788,9 +783,6 @@ static BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
*/
void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
{
if (ISV86(context) && DOSVM_CheckWrappers(context))
return;
RESET_CFLAG(context);
switch(AX_reg(context))
{
......
......@@ -22,6 +22,19 @@
#include "wine/debug.h"
#include "wine/winbase16.h"
#ifdef HAVE_SYS_VM86_H
# include <sys/vm86.h>
#endif
#ifndef IF_MASK
#define IF_MASK 0x00000200
#endif
#ifndef VIF_MASK
#define VIF_MASK 0x00080000
#endif
WINE_DEFAULT_DEBUG_CHANNEL(int);
static FARPROC16 DOSVM_Vectors16[256];
......@@ -69,6 +82,24 @@ void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context )
/**********************************************************************
* DOSVM_GetBuiltinHandler
*
* Return Wine interrupt handler procedure for a given interrupt.
*/
static INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
{
if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
INTPROC proc = DOSVM_VectorsBuiltin[intnum];
if (proc)
return proc;
}
WARN("int%x not implemented, returning dummy handler\n", intnum );
return DOSVM_DefaultHandler;
}
/**********************************************************************
* DOSVM_IntProcRelay
*
* Simple DOSRELAY that interprets its argument as INTPROC and calls it.
......@@ -173,7 +204,24 @@ void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum )
DOSVM_IntProcRelay,
DOSVM_GetBuiltinHandler(intnum) );
}
else if(DOSVM_IsDos32())
else
{
DOSVM_HardwareInterruptPM( context, intnum );
}
}
/**********************************************************************
* DOSVM_HardwareInterruptPM
*
* Emulate call to interrupt handler in 16-bit or 32-bit protected mode.
*
* Pushes interrupt frame to stack and changes instruction
* pointer to interrupt handler.
*/
void DOSVM_HardwareInterruptPM( CONTEXT86 *context, BYTE intnum )
{
if(DOSVM_IsDos32())
{
FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
......@@ -235,6 +283,100 @@ void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum )
}
}
/**********************************************************************
* DOSVM_EmulateInterruptRM
*
* Emulate software interrupt in real mode.
* Called from VM86 emulation when intXX opcode is executed.
*
* Either calls directly builtin handler or pushes interrupt frame to
* stack and changes instruction pointer to interrupt handler.
*
* Returns FALSE if this interrupt was caused by return
* from real mode wrapper.
*/
BOOL WINAPI DOSVM_EmulateInterruptRM( CONTEXT86 *context, BYTE intnum )
{
/* check for our real-mode hooks */
if (intnum == 0x31)
{
/* is this exit from real-mode wrapper */
if (context->SegCs == DOSVM_dpmi_segments->wrap_seg)
return FALSE;
if (DOSVM_CheckWrappers( context ))
return TRUE;
}
/* check if the call is from our fake BIOS interrupt stubs */
if (context->SegCs==0xf000)
{
if (intnum != (context->Eip/4))
TRACE( "something fishy going on here (interrupt stub is %02lx)\n",
context->Eip/4 );
TRACE( "builtin interrupt %02x has been branched to\n", intnum );
DOSVM_CallBuiltinHandler( context, intnum );
}
else
{
DOSVM_HardwareInterruptRM( context, intnum );
}
return TRUE;
}
/**********************************************************************
* DOSVM_HardwareInterruptRM
*
* Emulate call to interrupt handler in real mode.
*
* Either calls directly builtin handler or pushes interrupt frame to
* stack and changes instruction pointer to interrupt handler.
*/
void DOSVM_HardwareInterruptRM( CONTEXT86 *context, BYTE intnum )
{
FARPROC16 handler = DOSVM_GetRMHandler( intnum );
/* check if the call goes to an unhooked interrupt */
if (SELECTOROF(handler) == 0xf000)
{
/* if so, call it directly */
TRACE( "builtin interrupt %02x has been invoked (through vector %02x)\n",
OFFSETOF(handler)/4, intnum );
DOSVM_CallBuiltinHandler( context, OFFSETOF(handler)/4 );
}
else
{
/* the interrupt is hooked, simulate interrupt in DOS space */
WORD* stack = PTR_REAL_TO_LIN( context->SegSs, context->Esp );
WORD flag = LOWORD( context->EFlags );
TRACE_(int)( "invoking hooked interrupt %02x at %04x:%04x\n",
intnum, SELECTOROF(handler), OFFSETOF(handler) );
/* Copy virtual interrupt flag to pushed interrupt flag. */
if (context->EFlags & VIF_MASK)
flag |= IF_MASK;
else
flag &= ~IF_MASK;
*(--stack) = flag;
*(--stack) = context->SegCs;
*(--stack) = LOWORD( context->Eip );
context->Esp -= 6;
context->SegCs = SELECTOROF( handler );
context->Eip = OFFSETOF( handler );
/* Clear virtual interrupt flag. */
context->EFlags &= ~VIF_MASK;
}
}
/**********************************************************************
* DOSVM_GetRMHandler
*
......@@ -316,22 +458,6 @@ void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler )
DOSVM_Vectors48[intnum] = handler;
}
/**********************************************************************
* DOSVM_GetBuiltinHandler
*
* Return Wine interrupt handler procedure for a given interrupt.
*/
INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
{
if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
INTPROC proc = DOSVM_VectorsBuiltin[intnum];
if(proc)
return proc;
}
WARN("int%x not implemented, returning dummy handler\n", intnum );
return DOSVM_DefaultHandler;
}
/**********************************************************************
* DOSVM_CallBuiltinHandler
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment