Move interrupt emulation code from INSTR_EmulateInstruction to winedos
dll. Make CTX_SEG_OFF_TO_LIN work with 32-bit segmented pointers common in DPMI32. Fix winedos initialization so that DOSMEM_Init(TRUE) is only called when DOS executable is started.
This commit is contained in:
parent
5a1ede3345
commit
eca6182749
|
@ -25,6 +25,7 @@ C_SRCS = \
|
||||||
int31.c \
|
int31.c \
|
||||||
int33.c \
|
int33.c \
|
||||||
int67.c \
|
int67.c \
|
||||||
|
interrupts.c \
|
||||||
ioports.c \
|
ioports.c \
|
||||||
module.c \
|
module.c \
|
||||||
soundblaster.c \
|
soundblaster.c \
|
||||||
|
|
|
@ -115,6 +115,7 @@ extern void WINAPI DOSVM_Int29Handler(CONTEXT86*);
|
||||||
|
|
||||||
/* int31.c */
|
/* int31.c */
|
||||||
extern void WINAPI DOSVM_Int31Handler(CONTEXT86*);
|
extern void WINAPI DOSVM_Int31Handler(CONTEXT86*);
|
||||||
|
extern BOOL WINAPI DOSVM_IsDos32();
|
||||||
|
|
||||||
/* int33.c */
|
/* int33.c */
|
||||||
extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
|
extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
|
||||||
|
|
|
@ -696,10 +696,6 @@ BOOL WINAPI DOSVM_Init( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved
|
||||||
|
|
||||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
/* initialize the memory */
|
|
||||||
TRACE("Initializing DOS memory structures\n");
|
|
||||||
DOSMEM_Init( TRUE );
|
|
||||||
DOSDEV_InstallDOSDevices();
|
|
||||||
DOSVM_dpmi_segments = DOSMEM_GetDPMISegments();
|
DOSVM_dpmi_segments = DOSMEM_GetDPMISegments();
|
||||||
|
|
||||||
#ifdef MZ_SUPPORTED
|
#ifdef MZ_SUPPORTED
|
||||||
|
|
|
@ -64,6 +64,17 @@ typedef struct tagRMCB {
|
||||||
static RMCB *FirstRMCB = NULL;
|
static RMCB *FirstRMCB = NULL;
|
||||||
static WORD dpmi_flag;
|
static WORD dpmi_flag;
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* DOSVM_IsDos32
|
||||||
|
*
|
||||||
|
* Return TRUE if we are in 32-bit protected mode DOS process.
|
||||||
|
*/
|
||||||
|
BOOL DOSVM_IsDos32()
|
||||||
|
{
|
||||||
|
return (dpmi_flag & 1) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* INT_GetRealModeContext
|
* INT_GetRealModeContext
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Interrupt emulation
|
||||||
|
*
|
||||||
|
* Copyright 2002 Jukka Heinonen
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dosexe.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(int);
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* DOSVM_EmulateInterruptPM
|
||||||
|
*
|
||||||
|
* Emulate software interrupt in 16-bit or 32-bit protected mode.
|
||||||
|
* Called from signal handler when intXX opcode is executed.
|
||||||
|
*
|
||||||
|
* Pushes interrupt frame to stack and changes instruction
|
||||||
|
* pointer to interrupt handler.
|
||||||
|
*/
|
||||||
|
void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum )
|
||||||
|
{
|
||||||
|
BOOL islong;
|
||||||
|
|
||||||
|
if(context->SegCs == DOSVM_dpmi_segments->int48_sel)
|
||||||
|
islong = FALSE;
|
||||||
|
else if(DOSVM_IsDos32())
|
||||||
|
islong = TRUE;
|
||||||
|
else if(IS_SELECTOR_32BIT(context->SegCs)) {
|
||||||
|
WARN("Interrupt in 32-bit code and mode is not DPMI32\n");
|
||||||
|
islong = TRUE;
|
||||||
|
} else
|
||||||
|
islong = FALSE;
|
||||||
|
|
||||||
|
/* FIXME: Remove this check when DPMI32 support has been added */
|
||||||
|
if(islong) {
|
||||||
|
ERR("Interrupts not supported in 32-bit DPMI\n");
|
||||||
|
islong = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(islong)
|
||||||
|
{
|
||||||
|
FARPROC48 addr = {0,0}; /* FIXME: INT_GetPMHandler48( intnum ); */
|
||||||
|
DWORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
|
||||||
|
/* Push the flags and return address on the stack */
|
||||||
|
*(--stack) = context->EFlags;
|
||||||
|
*(--stack) = context->SegCs;
|
||||||
|
*(--stack) = context->Eip;
|
||||||
|
/* Jump to the interrupt handler */
|
||||||
|
context->SegCs = addr.selector;
|
||||||
|
context->Eip = addr.offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FARPROC16 addr = INT_GetPMHandler( intnum );
|
||||||
|
WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
|
||||||
|
/* Push the flags and return address on the stack */
|
||||||
|
*(--stack) = LOWORD(context->EFlags);
|
||||||
|
*(--stack) = context->SegCs;
|
||||||
|
*(--stack) = LOWORD(context->Eip);
|
||||||
|
/* Jump to the interrupt handler */
|
||||||
|
context->SegCs = HIWORD(addr);
|
||||||
|
context->Eip = LOWORD(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_SELECTOR_32BIT(context->SegSs))
|
||||||
|
context->Esp += islong ? -12 : -6;
|
||||||
|
else
|
||||||
|
ADD_LOWORD( context->Esp, islong ? -12 : -6 );
|
||||||
|
}
|
|
@ -198,6 +198,7 @@ static BOOL MZ_InitMemory(void)
|
||||||
/* initialize the memory */
|
/* initialize the memory */
|
||||||
TRACE("Initializing DOS memory structures\n");
|
TRACE("Initializing DOS memory structures\n");
|
||||||
DOSMEM_Init(TRUE);
|
DOSMEM_Init(TRUE);
|
||||||
|
DOSDEV_InstallDOSDevices();
|
||||||
|
|
||||||
MZ_InitHandlers();
|
MZ_InitHandlers();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
init DOSVM_Init
|
init DOSVM_Init
|
||||||
|
|
||||||
@ stdcall LoadDosExe(str long) MZ_LoadImage
|
@ stdcall LoadDosExe(str long) MZ_LoadImage
|
||||||
|
@ stdcall EmulateInterruptPM(ptr long) DOSVM_EmulateInterruptPM
|
||||||
|
|
||||||
# DPMI functions
|
# DPMI functions
|
||||||
@ stdcall CallRMInt(ptr) DOSVM_CallRMInt
|
@ stdcall CallRMInt(ptr) DOSVM_CallRMInt
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (WINAPI *LoadDosExe)( LPCSTR filename, HANDLE hFile );
|
void (WINAPI *LoadDosExe)( LPCSTR filename, HANDLE hFile );
|
||||||
|
void (WINAPI *EmulateInterruptPM)( CONTEXT86 *context, BYTE intnum );
|
||||||
|
|
||||||
/* DPMI functions */
|
/* DPMI functions */
|
||||||
void (WINAPI *CallRMInt)( CONTEXT86 *context );
|
void (WINAPI *CallRMInt)( CONTEXT86 *context );
|
||||||
|
|
|
@ -270,8 +270,9 @@ extern char IO_pp_init(void);
|
||||||
#define PTR_REAL_TO_LIN(seg,off) \
|
#define PTR_REAL_TO_LIN(seg,off) \
|
||||||
((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
|
((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
|
||||||
|
|
||||||
/* NOTE: Interrupts might get called from three modes: real mode, 16-bit, and
|
/* NOTE: Interrupts might get called from four modes: real mode, 16-bit,
|
||||||
* (via DeviceIoControl) 32-bit. For automatic conversion of pointer
|
* 32-bit segmented (DPMI32) and 32-bit linear (via DeviceIoControl).
|
||||||
|
* For automatic conversion of pointer
|
||||||
* parameters, interrupt handlers should use CTX_SEG_OFF_TO_LIN with
|
* parameters, interrupt handlers should use CTX_SEG_OFF_TO_LIN with
|
||||||
* the contents of a segment register as second and the contents of
|
* the contents of a segment register as second and the contents of
|
||||||
* a *32-bit* general register as third parameter, e.g.
|
* a *32-bit* general register as third parameter, e.g.
|
||||||
|
@ -279,15 +280,21 @@ extern char IO_pp_init(void);
|
||||||
* This will generate a linear pointer in all three cases:
|
* This will generate a linear pointer in all three cases:
|
||||||
* Real-Mode: Seg*16 + LOWORD(Offset)
|
* Real-Mode: Seg*16 + LOWORD(Offset)
|
||||||
* 16-bit: convert (Seg, LOWORD(Offset)) to linear
|
* 16-bit: convert (Seg, LOWORD(Offset)) to linear
|
||||||
* 32-bit: use Offset as linear address (DeviceIoControl!)
|
* 32-bit segmented: convert (Seg, Offset) to linear
|
||||||
|
* 32-bit linear: use Offset as linear address (DeviceIoControl!)
|
||||||
*
|
*
|
||||||
* Real-mode is recognized by checking the V86 bit in the flags register,
|
* Real-mode is recognized by checking the V86 bit in the flags register,
|
||||||
* 32-bit mode is recognized by checking whether 'seg' is a system selector
|
* 32-bit linear mode is recognized by checking whether 'seg' is
|
||||||
* (0 counts also as 32-bit segment).
|
* a system selector (0 counts also as 32-bit segment) and 32-bit
|
||||||
|
* segmented mode is recognized by checking whether 'seg' is 32-bit
|
||||||
|
* selector which is neither system selector nor zero.
|
||||||
*/
|
*/
|
||||||
#define CTX_SEG_OFF_TO_LIN(context,seg,off) \
|
#define CTX_SEG_OFF_TO_LIN(context,seg,off) \
|
||||||
(ISV86(context) ? PTR_REAL_TO_LIN((seg),(off)) : \
|
(ISV86(context) ? PTR_REAL_TO_LIN((seg),(off)) : \
|
||||||
(!seg || IS_SELECTOR_SYSTEM(seg))? (void *)(ULONG_PTR)(off) : MapSL(MAKESEGPTR((seg),(off))))
|
(!seg || IS_SELECTOR_SYSTEM(seg))? (void *)(ULONG_PTR)(off) : \
|
||||||
|
(IS_SELECTOR_32BIT(seg) ? \
|
||||||
|
(void *)((off) + (char*)MapSL(MAKESEGPTR((seg),0))) : \
|
||||||
|
MapSL(MAKESEGPTR((seg),(off)))))
|
||||||
|
|
||||||
#define INT_BARF(context,num) \
|
#define INT_BARF(context,num) \
|
||||||
ERR( "int%x: unknown/not implemented parameters:\n" \
|
ERR( "int%x: unknown/not implemented parameters:\n" \
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "miscemu.h"
|
#include "miscemu.h"
|
||||||
#include "selectors.h"
|
#include "selectors.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "callback.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(int);
|
WINE_DEFAULT_DEBUG_CHANNEL(int);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(io);
|
WINE_DECLARE_DEBUG_CHANNEL(io);
|
||||||
|
@ -684,34 +685,14 @@ BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
|
||||||
break; /* Unable to emulate it */
|
break; /* Unable to emulate it */
|
||||||
|
|
||||||
case 0xcd: /* int <XX> */
|
case 0xcd: /* int <XX> */
|
||||||
if (long_op)
|
if(!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem())
|
||||||
{
|
ERR("could not initialize interrupt handling\n");
|
||||||
FARPROC48 addr = INT_GetPMHandler48( instr[1] );
|
else {
|
||||||
DWORD *stack = get_stack( context );
|
context->Eip += prefixlen + 2;
|
||||||
/* Push the flags and return address on the stack */
|
Dosvm.EmulateInterruptPM( context, instr[1] );
|
||||||
*(--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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
break; /* Unable to emulate it */
|
||||||
{
|
|
||||||
FARPROC16 addr = INT_GetPMHandler( instr[1] );
|
|
||||||
WORD *stack = get_stack( context );
|
|
||||||
/* Push the flags and return address on the stack */
|
|
||||||
*(--stack) = LOWORD(context->EFlags);
|
|
||||||
*(--stack) = context->SegCs;
|
|
||||||
*(--stack) = LOWORD(context->Eip) + prefixlen + 2;
|
|
||||||
add_stack(context, -3 * sizeof(WORD));
|
|
||||||
/* Jump to the interrupt handler */
|
|
||||||
context->SegCs = HIWORD(addr);
|
|
||||||
context->Eip = LOWORD(addr);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case 0xcf: /* iret */
|
case 0xcf: /* iret */
|
||||||
if (long_op)
|
if (long_op)
|
||||||
|
|
|
@ -74,6 +74,7 @@ BOOL DPMI_LoadDosSystem(void)
|
||||||
GET_ADDR(inport);
|
GET_ADDR(inport);
|
||||||
GET_ADDR(outport);
|
GET_ADDR(outport);
|
||||||
GET_ADDR(ASPIHandler);
|
GET_ADDR(ASPIHandler);
|
||||||
|
GET_ADDR(EmulateInterruptPM);
|
||||||
#undef GET_ADDR
|
#undef GET_ADDR
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue