Changed INSTR_EmulateInstruction to use a CONTEXT86 instead of a

SIGCONTEXT.
This commit is contained in:
Alexandre Julliard 1999-08-01 12:15:12 +00:00
parent 352c04c6a9
commit b375678277
6 changed files with 277 additions and 296 deletions

View File

@ -432,6 +432,16 @@ static HANDLER_DEF(EXC_segv)
HANDLER_INIT(); HANDLER_INIT();
#if defined(TRAP_sig) && defined(CR2_sig)
/* we want the page-fault case to be fast */
if (TRAP_sig(HANDLER_CONTEXT) == 14)
if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return;
#endif
EXC_SaveContext( &context, HANDLER_CONTEXT );
rec.ExceptionRecord = NULL;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionAddress = GET_IP(&context);
rec.NumberParameters = 0; rec.NumberParameters = 0;
#ifdef TRAP_sig #ifdef TRAP_sig
@ -451,12 +461,11 @@ static HANDLER_DEF(EXC_segv)
break; break;
case 11: /* Segment not present exception */ case 11: /* Segment not present exception */
case 13: /* General protection fault */ case 13: /* General protection fault */
if (INSTR_EmulateInstruction( HANDLER_CONTEXT )) return; if (INSTR_EmulateInstruction( &context )) goto restore;
rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION; rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
break; break;
case 14: /* Page fault */ case 14: /* Page fault */
#ifdef CR2_sig #ifdef CR2_sig
if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return;
rec.NumberParameters = 2; rec.NumberParameters = 2;
#ifdef ERROR_sig #ifdef ERROR_sig
rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0; rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
@ -469,11 +478,11 @@ static HANDLER_DEF(EXC_segv)
break; break;
case 17: /* Alignment check exception */ case 17: /* Alignment check exception */
/* FIXME: pass through exception handler first? */ /* FIXME: pass through exception handler first? */
if (EFL_sig(HANDLER_CONTEXT) & 0x00040000) if (EFL_reg(&context) & 0x00040000)
{ {
/* Disable AC flag, return */ /* Disable AC flag, return */
EFL_sig(HANDLER_CONTEXT) &= ~0x00040000; EFL_reg(&context) &= ~0x00040000;
return; goto restore;
} }
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break; break;
@ -492,16 +501,13 @@ static HANDLER_DEF(EXC_segv)
} }
#else /* TRAP_sig */ #else /* TRAP_sig */
# ifdef __i386 # ifdef __i386
if (INSTR_EmulateInstruction( HANDLER_CONTEXT )) return; if (INSTR_EmulateInstruction( &context )) return;
# endif # endif
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; /* generic error */ rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; /* generic error */
#endif /* TRAP_sig */ #endif /* TRAP_sig */
EXC_SaveContext( &context, HANDLER_CONTEXT );
rec.ExceptionRecord = NULL;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.ExceptionAddress = GET_IP(&context);
REGS_FUNC(RtlRaiseException)( &rec, &context ); REGS_FUNC(RtlRaiseException)( &rec, &context );
restore:
EXC_RestoreContext( &context, HANDLER_CONTEXT ); EXC_RestoreContext( &context, HANDLER_CONTEXT );
} }

View File

@ -101,6 +101,9 @@ extern LPVOID DOSMEM_MapRealToLinear(DWORD); /* real-mode to linear */
extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */ extern LPVOID DOSMEM_MapDosToLinear(UINT); /* linear DOS to Wine */
extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
/* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
/* msdos/devices.c */ /* msdos/devices.c */
extern void DOSDEV_InstallDOSDevices(void); extern void DOSDEV_InstallDOSDevices(void);

View File

@ -284,7 +284,4 @@ typedef DWORD SIGCONTEXT;
#define HANDLER_CONTEXT 0 #define HANDLER_CONTEXT 0
#endif #endif
/* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( SIGCONTEXT * );
#endif /* __WINE_SIG_CONTEXT_H */ #endif /* __WINE_SIG_CONTEXT_H */

View File

@ -358,6 +358,14 @@ typedef LRESULT (CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
#define SELECTOROF(ptr) (HIWORD(ptr)) #define SELECTOROF(ptr) (HIWORD(ptr))
#define OFFSETOF(ptr) (LOWORD(ptr)) #define OFFSETOF(ptr) (LOWORD(ptr))
#ifdef __WINE__
/* macros to set parts of a DWORD (not in the Windows API) */
#define SET_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD(val))
#define SET_LOBYTE(dw,val) ((dw) = ((dw) & 0xffffff00) | LOBYTE(val))
#define SET_HIBYTE(dw,val) ((dw) = ((dw) & 0xffff00ff) | (LOWORD(val) & 0xff00))
#define ADD_LOWORD(dw,val) ((dw) = ((dw) & 0xffff0000) | LOWORD((DWORD)(dw)+(val)))
#endif
/* Macros to access unaligned or wrong-endian WORDs and DWORDs. */ /* Macros to access unaligned or wrong-endian WORDs and DWORDs. */
/* Note: These macros are semantically broken, at least for wrc. wrc /* Note: These macros are semantically broken, at least for wrc. wrc
spits out data in the platform's current binary format, *not* in spits out data in the platform's current binary format, *not* in

View File

@ -20,7 +20,6 @@
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "winuser.h" #include "winuser.h"
#include "winnt.h" #include "winnt.h"
#include "sig_context.h"
#include "msdos.h" #include "msdos.h"
#include "file.h" #include "file.h"
#include "miscemu.h" #include "miscemu.h"
@ -128,18 +127,18 @@ static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask
/* if internal interrupt, call it directly */ /* if internal interrupt, call it directly */
INT_RealModeInterrupt(vect,context); INT_RealModeInterrupt(vect,context);
} else { } else {
WORD*stack=(WORD*)(V86BASE(context)+(((DWORD)SS_reg(context))<<4)+SP_reg(context)); WORD*stack=(WORD*)(V86BASE(context)+(((DWORD)SS_reg(context))<<4)+LOWORD(ESP_reg(context)));
WORD flag=FL_reg(context); WORD flag=LOWORD(EFL_reg(context));
if (IF_ENABLED(context)) flag|=IF_MASK; if (IF_ENABLED(context)) flag|=IF_MASK;
else flag&=~IF_MASK; else flag&=~IF_MASK;
*(--stack)=flag; *(--stack)=flag;
*(--stack)=CS_reg(context); *(--stack)=CS_reg(context);
*(--stack)=IP_reg(context); *(--stack)=LOWORD(EIP_reg(context));
SP_reg(context)-=6; ESP_reg(context)-=6;
CS_reg(context)=SELECTOROF(handler); CS_reg(context)=SELECTOROF(handler);
IP_reg(context)=OFFSETOF(handler); EIP_reg(context)=OFFSETOF(handler);
IF_CLR(context); IF_CLR(context);
} }
} }
@ -229,25 +228,20 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
struct vm86plus_struct*VM86 ) struct vm86plus_struct*VM86 )
{ {
SIGCONTEXT sigcontext;
CONTEXT86 context; CONTEXT86 context;
int ret=0; int ret=0;
if (VM86_TYPE(fn)==VM86_UNKNOWN) { #define CP(x,y) y##_reg(&context) = VM86->regs.x
/* INSTR_EmulateInstruction needs a SIGCONTEXT, not a CONTEXT... */
#define CP(x,y) y##_sig(&sigcontext) = VM86->regs.x
CV; CV;
#undef CP #undef CP
ret=INSTR_EmulateInstruction(&sigcontext); if (VM86_TYPE(fn)==VM86_UNKNOWN) {
#define CP(x,y) VM86->regs.x = y##_sig(&sigcontext) ret=INSTR_EmulateInstruction(&context);
#define CP(x,y) VM86->regs.x = y##_reg(&context)
CV; CV;
#undef CP #undef CP
if (ret) return 0; if (ret) return 0;
ret=0; ret=0;
} }
#define CP(x,y) y##_reg(&context) = VM86->regs.x
CV;
#undef CP
(void*)V86BASE(&context)=lpDosTask->img; (void*)V86BASE(&context)=lpDosTask->img;
#ifdef TRY_PICRETURN #ifdef TRY_PICRETURN
if (VM86->vm86plus.force_return_for_pic) { if (VM86->vm86plus.force_return_for_pic) {

View File

@ -10,7 +10,6 @@
#include "module.h" #include "module.h"
#include "dosexe.h" #include "dosexe.h"
#include "miscemu.h" #include "miscemu.h"
#include "sig_context.h"
#include "selectors.h" #include "selectors.h"
#include "debugtools.h" #include "debugtools.h"
@ -19,29 +18,28 @@ DECLARE_DEBUG_CHANNEL(io)
#ifdef __i386__ #ifdef __i386__
#define IS_V86(context) (EFL_sig(context)&V86_FLAG)
#define IS_SEL_32(context,seg) \ #define IS_SEL_32(context,seg) \
(IS_V86(context) ? FALSE : IS_SELECTOR_32BIT(seg)) (ISV86(context) ? FALSE : IS_SELECTOR_32BIT(seg))
#define STACK_sig(context) \ #define STACK_reg(context) \
(IS_SEL_32(context,SS_sig(context)) ? ESP_sig(context) : (DWORD)SP_sig(context)) (IS_SEL_32(context,SS_reg(context)) ? ESP_reg(context) : (DWORD)LOWORD(ESP_reg(context)))
#define ADD_STACK_sig(context,offset) \ #define ADD_STACK_reg(context,offset) \
do { if (IS_SEL_32(context,SS_sig(context))) ESP_sig(context) += (offset); \ do { if (IS_SEL_32(context,SS_reg(context))) ESP_reg(context) += (offset); \
else SP_sig(context) += (offset); } while(0) else ADD_LOWORD(ESP_reg(context),(offset)); } while(0)
#define MAKE_PTR(seg,off) \ #define MAKE_PTR(seg,off) \
(IS_SELECTOR_SYSTEM(seg) ? (void *)(off) : PTR_SEG_OFF_TO_LIN(seg,off)) (IS_SELECTOR_SYSTEM(seg) ? (void *)(off) : PTR_SEG_OFF_TO_LIN(seg,off))
#define MK_PTR(context,seg,off) \ #define MK_PTR(context,seg,off) \
(IS_V86(context) ? DOSMEM_MapRealToLinear(MAKELONG(off,seg)) \ (ISV86(context) ? DOSMEM_MapRealToLinear(MAKELONG(off,seg)) \
: MAKE_PTR(seg,off)) : MAKE_PTR(seg,off))
#define STACK_PTR(context) \ #define STACK_PTR(context) \
(IS_V86(context) ? DOSMEM_MapRealToLinear(MAKELONG(SP_sig(context),SS_sig(context))) : \ (ISV86(context) ? \
(IS_SELECTOR_SYSTEM(SS_sig(context)) ? (void *)ESP_sig(context) : \ DOSMEM_MapRealToLinear(MAKELONG(LOWORD(ESP_reg(context)),SS_reg(context))) : \
(PTR_SEG_OFF_TO_LIN(SS_sig(context),STACK_sig(context))))) (IS_SELECTOR_SYSTEM(SS_reg(context)) ? (void *)ESP_reg(context) : \
(PTR_SEG_OFF_TO_LIN(SS_reg(context),STACK_reg(context)))))
/*********************************************************************** /***********************************************************************
* INSTR_ReplaceSelector * INSTR_ReplaceSelector
@ -54,13 +52,13 @@ DECLARE_DEBUG_CHANNEL(io)
* *
* See Undocumented Windows, Chapter 5, __0040. * See Undocumented Windows, Chapter 5, __0040.
*/ */
static BOOL INSTR_ReplaceSelector( SIGCONTEXT *context, WORD *sel ) static BOOL INSTR_ReplaceSelector( CONTEXT86 *context, WORD *sel )
{ {
extern char Call16_Start, Call16_End; extern char Call16_Start, Call16_End;
if (IS_SELECTOR_SYSTEM(CS_sig(context))) if (IS_SELECTOR_SYSTEM(CS_reg(context)))
if ( (char *)EIP_sig(context) >= &Call16_Start if ( (char *)EIP_reg(context) >= &Call16_Start
&& (char *)EIP_sig(context) < &Call16_End ) && (char *)EIP_reg(context) < &Call16_End )
{ {
/* Saved selector may have become invalid when the relay code */ /* Saved selector may have become invalid when the relay code */
/* tries to restore it. We simply clear it. */ /* tries to restore it. We simply clear it. */
@ -87,7 +85,7 @@ static BOOL INSTR_ReplaceSelector( SIGCONTEXT *context, WORD *sel )
* *
* Return the address of an instruction operand (from the mod/rm byte). * Return the address of an instruction operand (from the mod/rm byte).
*/ */
static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr, static BYTE *INSTR_GetOperandAddr( CONTEXT86 *context, BYTE *instr,
int long_addr, int segprefix, int *len ) int long_addr, int segprefix, int *len )
{ {
int mod, rm, base, index = 0, ss = 0, seg = 0, off; int mod, rm, base, index = 0, ss = 0, seg = 0, off;
@ -104,14 +102,14 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
{ {
switch(rm) switch(rm)
{ {
case 0: return (BYTE *)&EAX_sig(context); case 0: return (BYTE *)&EAX_reg(context);
case 1: return (BYTE *)&ECX_sig(context); case 1: return (BYTE *)&ECX_reg(context);
case 2: return (BYTE *)&EDX_sig(context); case 2: return (BYTE *)&EDX_reg(context);
case 3: return (BYTE *)&EBX_sig(context); case 3: return (BYTE *)&EBX_reg(context);
case 4: return (BYTE *)&ESP_sig(context); case 4: return (BYTE *)&ESP_reg(context);
case 5: return (BYTE *)&EBP_sig(context); case 5: return (BYTE *)&EBP_reg(context);
case 6: return (BYTE *)&ESI_sig(context); case 6: return (BYTE *)&ESI_reg(context);
case 7: return (BYTE *)&EDI_sig(context); case 7: return (BYTE *)&EDI_reg(context);
} }
} }
@ -125,27 +123,27 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
ss = sib >> 6; ss = sib >> 6;
switch(sib >> 3) switch(sib >> 3)
{ {
case 0: index = EAX_sig(context); break; case 0: index = EAX_reg(context); break;
case 1: index = ECX_sig(context); break; case 1: index = ECX_reg(context); break;
case 2: index = EDX_sig(context); break; case 2: index = EDX_reg(context); break;
case 3: index = EBX_sig(context); break; case 3: index = EBX_reg(context); break;
case 4: index = 0; break; case 4: index = 0; break;
case 5: index = EBP_sig(context); break; case 5: index = EBP_reg(context); break;
case 6: index = ESI_sig(context); break; case 6: index = ESI_reg(context); break;
case 7: index = EDI_sig(context); break; case 7: index = EDI_reg(context); break;
} }
} }
switch(rm) switch(rm)
{ {
case 0: base = EAX_sig(context); seg = DS_sig(context); break; case 0: base = EAX_reg(context); seg = DS_reg(context); break;
case 1: base = ECX_sig(context); seg = DS_sig(context); break; case 1: base = ECX_reg(context); seg = DS_reg(context); break;
case 2: base = EDX_sig(context); seg = DS_sig(context); break; case 2: base = EDX_reg(context); seg = DS_reg(context); break;
case 3: base = EBX_sig(context); seg = DS_sig(context); break; case 3: base = EBX_reg(context); seg = DS_reg(context); break;
case 4: base = ESP_sig(context); seg = SS_sig(context); break; case 4: base = ESP_reg(context); seg = SS_reg(context); break;
case 5: base = EBP_sig(context); seg = SS_sig(context); break; case 5: base = EBP_reg(context); seg = SS_reg(context); break;
case 6: base = ESI_sig(context); seg = DS_sig(context); break; case 6: base = ESI_reg(context); seg = DS_reg(context); break;
case 7: base = EDI_sig(context); seg = DS_sig(context); break; case 7: base = EDI_reg(context); seg = DS_reg(context); break;
} }
switch (mod) switch (mod)
{ {
@ -153,7 +151,7 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
if (rm == 5) /* special case: ds:(disp32) */ if (rm == 5) /* special case: ds:(disp32) */
{ {
GET_VAL( &base, DWORD ); GET_VAL( &base, DWORD );
seg = DS_sig(context); seg = DS_reg(context);
} }
break; break;
@ -173,36 +171,36 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
switch(rm) switch(rm)
{ {
case 0: /* ds:(bx,si) */ case 0: /* ds:(bx,si) */
base = BX_sig(context) + SI_sig(context); base = LOWORD(EBX_reg(context)) + LOWORD(ESI_reg(context));
seg = DS_sig(context); seg = DS_reg(context);
break; break;
case 1: /* ds:(bx,di) */ case 1: /* ds:(bx,di) */
base = BX_sig(context) + DI_sig(context); base = LOWORD(EBX_reg(context)) + LOWORD(EDI_reg(context));
seg = DS_sig(context); seg = DS_reg(context);
break; break;
case 2: /* ss:(bp,si) */ case 2: /* ss:(bp,si) */
base = BP_sig(context) + SI_sig(context); base = LOWORD(EBP_reg(context)) + LOWORD(ESI_reg(context));
seg = SS_sig(context); seg = SS_reg(context);
break; break;
case 3: /* ss:(bp,di) */ case 3: /* ss:(bp,di) */
base = BP_sig(context) + DI_sig(context); base = LOWORD(EBP_reg(context)) + LOWORD(EDI_reg(context));
seg = SS_sig(context); seg = SS_reg(context);
break; break;
case 4: /* ds:(si) */ case 4: /* ds:(si) */
base = SI_sig(context); base = LOWORD(ESI_reg(context));
seg = DS_sig(context); seg = DS_reg(context);
break; break;
case 5: /* ds:(di) */ case 5: /* ds:(di) */
base = DI_sig(context); base = LOWORD(EDI_reg(context));
seg = DS_sig(context); seg = DS_reg(context);
break; break;
case 6: /* ss:(bp) */ case 6: /* ss:(bp) */
base = BP_sig(context); base = LOWORD(EBP_reg(context));
seg = SS_sig(context); seg = SS_reg(context);
break; break;
case 7: /* ds:(bx) */ case 7: /* ds:(bx) */
base = BX_sig(context); base = LOWORD(EBX_reg(context));
seg = DS_sig(context); seg = DS_reg(context);
break; break;
} }
@ -212,7 +210,7 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
if (rm == 6) /* special case: ds:(disp16) */ if (rm == 6) /* special case: ds:(disp16) */
{ {
GET_VAL( &base, WORD ); GET_VAL( &base, WORD );
seg = DS_sig(context); seg = DS_reg(context);
} }
break; break;
@ -244,7 +242,7 @@ static BYTE *INSTR_GetOperandAddr( SIGCONTEXT *context, BYTE *instr,
* *
* Emulate the LDS (and LES,LFS,etc.) instruction. * Emulate the LDS (and LES,LFS,etc.) instruction.
*/ */
static BOOL INSTR_EmulateLDS( SIGCONTEXT *context, BYTE *instr, int long_op, static BOOL INSTR_EmulateLDS( CONTEXT86 *context, BYTE *instr, int long_op,
int long_addr, int segprefix, int *len ) int long_addr, int segprefix, int *len )
{ {
WORD seg; WORD seg;
@ -263,36 +261,36 @@ static BOOL INSTR_EmulateLDS( SIGCONTEXT *context, BYTE *instr, int long_op,
switch((*regmodrm >> 3) & 7) switch((*regmodrm >> 3) & 7)
{ {
case 0: case 0:
if (long_op) EAX_sig(context) = *(DWORD *)addr; if (long_op) EAX_reg(context) = *(DWORD *)addr;
else AX_sig(context) = *(WORD *)addr; else SET_LOWORD(EAX_reg(context),*(WORD *)addr);
break; break;
case 1: case 1:
if (long_op) ECX_sig(context) = *(DWORD *)addr; if (long_op) ECX_reg(context) = *(DWORD *)addr;
else CX_sig(context) = *(WORD *)addr; else SET_LOWORD(ECX_reg(context),*(WORD *)addr);
break; break;
case 2: case 2:
if (long_op) EDX_sig(context) = *(DWORD *)addr; if (long_op) EDX_reg(context) = *(DWORD *)addr;
else DX_sig(context) = *(WORD *)addr; else SET_LOWORD(EDX_reg(context),*(WORD *)addr);
break; break;
case 3: case 3:
if (long_op) EBX_sig(context) = *(DWORD *)addr; if (long_op) EBX_reg(context) = *(DWORD *)addr;
else BX_sig(context) = *(WORD *)addr; else SET_LOWORD(EBX_reg(context),*(WORD *)addr);
break; break;
case 4: case 4:
if (long_op) ESP_sig(context) = *(DWORD *)addr; if (long_op) ESP_reg(context) = *(DWORD *)addr;
else SP_sig(context) = *(WORD *)addr; else SET_LOWORD(ESP_reg(context),*(WORD *)addr);
break; break;
case 5: case 5:
if (long_op) EBP_sig(context) = *(DWORD *)addr; if (long_op) EBP_reg(context) = *(DWORD *)addr;
else BP_sig(context) = *(WORD *)addr; else SET_LOWORD(EBP_reg(context),*(WORD *)addr);
break; break;
case 6: case 6:
if (long_op) ESI_sig(context) = *(DWORD *)addr; if (long_op) ESI_reg(context) = *(DWORD *)addr;
else SI_sig(context) = *(WORD *)addr; else SET_LOWORD(ESI_reg(context),*(WORD *)addr);
break; break;
case 7: case 7:
if (long_op) EDI_sig(context) = *(DWORD *)addr; if (long_op) EDI_reg(context) = *(DWORD *)addr;
else DI_sig(context) = *(WORD *)addr; else SET_LOWORD(EDI_reg(context),*(WORD *)addr);
break; break;
} }
@ -300,17 +298,13 @@ static BOOL INSTR_EmulateLDS( SIGCONTEXT *context, BYTE *instr, int long_op,
switch(*instr) switch(*instr)
{ {
case 0xc4: ES_sig(context) = seg; break; /* les */ case 0xc4: ES_reg(context) = seg; break; /* les */
case 0xc5: DS_sig(context) = seg; break; /* lds */ case 0xc5: DS_reg(context) = seg; break; /* lds */
case 0x0f: switch(instr[1]) case 0x0f: switch(instr[1])
{ {
case 0xb2: SS_sig(context) = seg; break; /* lss */ case 0xb2: SS_reg(context) = seg; break; /* lss */
#ifdef FS_sig case 0xb4: FS_reg(context) = seg; break; /* lfs */
case 0xb4: FS_sig(context) = seg; break; /* lfs */ case 0xb5: GS_reg(context) = seg; break; /* lgs */
#endif
#ifdef GS_sig
case 0xb5: GS_sig(context) = seg; break; /* lgs */
#endif
} }
break; break;
} }
@ -321,20 +315,78 @@ static BOOL INSTR_EmulateLDS( SIGCONTEXT *context, BYTE *instr, int long_op,
return TRUE; return TRUE;
} }
/***********************************************************************
* INSTR_inport
*
* input on a I/O port
*/
static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context )
{
DWORD res = IO_inport( port, size );
if (TRACE_ON(io))
{
switch(size)
{
case 1:
DPRINTF( "0x%x < %02x @ %04x:%04x\n", port, LOBYTE(res),
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
case 2:
DPRINTF( "0x%x < %04x @ %04x:%04x\n", port, LOWORD(res),
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
case 4:
DPRINTF( "0x%x < %08lx @ %04x:%04x\n", port, res,
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
}
}
return res;
}
/***********************************************************************
* INSTR_outport
*
* output on a I/O port
*/
static void INSTR_outport( WORD port, int size, DWORD val, CONTEXT86 *context )
{
IO_outport( port, size, val );
if (TRACE_ON(io))
{
switch(size)
{
case 1:
DPRINTF("0x%x > %02x @ %04x:%04x\n", port, LOBYTE(val),
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
case 2:
DPRINTF("0x%x > %04x @ %04x:%04x\n", port, LOWORD(val),
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
case 4:
DPRINTF("0x%x > %08lx @ %04x:%04x\n", port, val,
(WORD)CS_reg(context), LOWORD(EIP_reg(context)));
break;
}
}
}
/*********************************************************************** /***********************************************************************
* INSTR_EmulateInstruction * INSTR_EmulateInstruction
* *
* Emulate a priviledged instruction. Returns TRUE if emulation successful. * Emulate a priviledged instruction. Returns TRUE if emulation successful.
*/ */
BOOL INSTR_EmulateInstruction( SIGCONTEXT *context ) BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
{ {
int prefix, segprefix, prefixlen, len, repX, long_op, long_addr; int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
SEGPTR gpHandler; SEGPTR gpHandler;
BYTE *instr; BYTE *instr;
long_op = long_addr = IS_SEL_32(context,CS_sig(context)); long_op = long_addr = IS_SEL_32(context,CS_reg(context));
instr = (BYTE *)MK_PTR(context,CS_sig(context),EIP_sig(context)); instr = (BYTE *)MK_PTR(context,CS_reg(context),EIP_reg(context));
if (!instr) return FALSE; if (!instr) return FALSE;
/* First handle any possible prefix */ /* First handle any possible prefix */
@ -348,27 +400,23 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
switch(*instr) switch(*instr)
{ {
case 0x2e: case 0x2e:
segprefix = CS_sig(context); segprefix = CS_reg(context);
break; break;
case 0x36: case 0x36:
segprefix = SS_sig(context); segprefix = SS_reg(context);
break; break;
case 0x3e: case 0x3e:
segprefix = DS_sig(context); segprefix = DS_reg(context);
break; break;
case 0x26: case 0x26:
segprefix = ES_sig(context); segprefix = ES_reg(context);
break; break;
#ifdef FS_sig
case 0x64: case 0x64:
segprefix = FS_sig(context); segprefix = FS_reg(context);
break; break;
#endif
#ifdef GS_sig
case 0x65: case 0x65:
segprefix = GS_sig(context); segprefix = GS_reg(context);
break; break;
#endif
case 0x66: case 0x66:
long_op = !long_op; /* opcode size prefix */ long_op = !long_op; /* opcode size prefix */
break; break;
@ -407,12 +455,12 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
{ {
switch(*instr) switch(*instr)
{ {
case 0x07: ES_sig(context) = seg; break; case 0x07: ES_reg(context) = seg; break;
case 0x17: SS_sig(context) = seg; break; case 0x17: SS_reg(context) = seg; break;
case 0x1f: DS_sig(context) = seg; break; case 0x1f: DS_reg(context) = seg; break;
} }
ADD_STACK_sig(context, long_op ? 4 : 2); ADD_STACK_reg(context, long_op ? 4 : 2);
EIP_sig(context) += prefixlen + 1; EIP_reg(context) += prefixlen + 1;
return TRUE; return TRUE;
} }
} }
@ -425,9 +473,9 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
switch (instr[2]) { switch (instr[2]) {
case 0xc0: case 0xc0:
fprintf(stderr,"mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n", fprintf(stderr,"mov eax,cr0 at 0x%08lx, EAX=0x%08lx\n",
EIP_sig(context),EAX_sig(context) EIP_reg(context),EAX_reg(context)
); );
EIP_sig(context) += prefixlen+3; EIP_reg(context) += prefixlen+3;
return TRUE; return TRUE;
default: default:
break; /*fallthrough to bad instruction handling */ break; /*fallthrough to bad instruction handling */
@ -447,61 +495,51 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
* bit 7: PGE Enable global pages * bit 7: PGE Enable global pages
* bit 8: PCE Enable performance counters at IPL3 * bit 8: PCE Enable performance counters at IPL3
*/ */
fprintf(stderr,"mov cr4,eax at 0x%08lx\n",EIP_sig(context)); fprintf(stderr,"mov cr4,eax at 0x%08lx\n",EIP_reg(context));
EAX_sig(context) = 0; EAX_reg(context) = 0;
EIP_sig(context) += prefixlen+3; EIP_reg(context) += prefixlen+3;
return TRUE; return TRUE;
case 0xc0: /* mov cr0, eax */ case 0xc0: /* mov cr0, eax */
fprintf(stderr,"mov cr0,eax at 0x%08lx\n",EIP_sig(context)); fprintf(stderr,"mov cr0,eax at 0x%08lx\n",EIP_reg(context));
EAX_sig(context) = 0x10; /* FIXME: set more bits ? */ EAX_reg(context) = 0x10; /* FIXME: set more bits ? */
EIP_sig(context) += prefixlen+3; EIP_reg(context) += prefixlen+3;
return TRUE; return TRUE;
default: /* fallthrough to illegal instruction */ default: /* fallthrough to illegal instruction */
break; break;
} }
/* fallthrough to illegal instruction */ /* fallthrough to illegal instruction */
break; break;
#ifdef FS_sig
case 0xa1: /* pop fs */ case 0xa1: /* pop fs */
{ {
WORD seg = *(WORD *)STACK_PTR( context ); WORD seg = *(WORD *)STACK_PTR( context );
if (INSTR_ReplaceSelector( context, &seg )) if (INSTR_ReplaceSelector( context, &seg ))
{ {
FS_sig(context) = seg; FS_reg(context) = seg;
ADD_STACK_sig(context, long_op ? 4 : 2); ADD_STACK_reg(context, long_op ? 4 : 2);
EIP_sig(context) += prefixlen + 2; EIP_reg(context) += prefixlen + 2;
return TRUE; return TRUE;
} }
} }
break; break;
#endif /* FS_sig */
#ifdef GS_sig
case 0xa9: /* pop gs */ case 0xa9: /* pop gs */
{ {
WORD seg = *(WORD *)STACK_PTR( context ); WORD seg = *(WORD *)STACK_PTR( context );
if (INSTR_ReplaceSelector( context, &seg )) if (INSTR_ReplaceSelector( context, &seg ))
{ {
GS_sig(context) = seg; GS_reg(context) = seg;
ADD_STACK_sig(context, long_op ? 4 : 2); ADD_STACK_reg(context, long_op ? 4 : 2);
EIP_sig(context) += prefixlen + 2; EIP_reg(context) += prefixlen + 2;
return TRUE; return TRUE;
} }
} }
break; break;
#endif /* GS_sig */
case 0xb2: /* lss addr,reg */ case 0xb2: /* lss addr,reg */
#ifdef FS_sig
case 0xb4: /* lfs addr,reg */ case 0xb4: /* lfs addr,reg */
#endif
#ifdef GS_sig
case 0xb5: /* lgs addr,reg */ case 0xb5: /* lgs addr,reg */
#endif
if (INSTR_EmulateLDS( context, instr, long_op, if (INSTR_EmulateLDS( context, instr, long_op,
long_addr, segprefix, &len )) long_addr, segprefix, &len ))
{ {
EIP_sig(context) += prefixlen + len; EIP_reg(context) += prefixlen + len;
return TRUE; return TRUE;
} }
break; break;
@ -516,10 +554,10 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
int typ = *instr; /* Just in case it's overwritten. */ int typ = *instr; /* Just in case it's overwritten. */
int outp = (typ >= 0x6e); int outp = (typ >= 0x6e);
unsigned long count = repX ? unsigned long count = repX ?
(long_addr ? ECX_sig(context) : CX_sig(context)) : 1; (long_addr ? ECX_reg(context) : LOWORD(ECX_reg(context))) : 1;
int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1; int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1;
int step = (EFL_sig(context) & 0x400) ? -opsize : +opsize; int step = (EFL_reg(context) & 0x400) ? -opsize : +opsize;
int seg = outp ? DS_sig(context) : ES_sig(context); /* FIXME: is this right? */ int seg = outp ? DS_reg(context) : ES_reg(context); /* FIXME: is this right? */
if (outp) if (outp)
/* FIXME: Check segment readable. */ /* FIXME: Check segment readable. */
@ -530,73 +568,52 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
if (repX) if (repX)
{ {
if (long_addr) if (long_addr) ECX_reg(context) = 0;
ECX_sig(context) = 0; else SET_LOWORD(ECX_reg(context),0);
else
CX_sig(context) = 0;
} }
while (count-- > 0) while (count-- > 0)
{ {
void *data; void *data;
WORD dx = LOWORD(EDX_reg(context));
if (outp) if (outp)
{ {
data = MK_PTR(context, seg, data = MK_PTR(context, seg,
long_addr ? ESI_sig(context) : SI_sig(context)); long_addr ? ESI_reg(context) : LOWORD(ESI_reg(context)));
if (long_addr) ESI_sig(context) += step; if (long_addr) ESI_reg(context) += step;
else SI_sig(context) += step; else ADD_LOWORD(ESI_reg(context),step);
} }
else else
{ {
data = MK_PTR(context, seg, data = MK_PTR(context, seg,
long_addr ? EDI_sig(context) : DI_sig(context)); long_addr ? EDI_reg(context) : LOWORD(EDI_reg(context)));
if (long_addr) EDI_sig(context) += step; if (long_addr) EDI_reg(context) += step;
else DI_sig(context) += step; else ADD_LOWORD(EDI_reg(context),step);
} }
switch (typ) switch (typ)
{ {
case 0x6c: case 0x6c:
*((BYTE *)data) = IO_inport( DX_sig(context), 1); *(BYTE *)data = INSTR_inport( dx, 1, context );
TRACE_(io)("0x%x < %02x @ %04x:%04x\n", DX_sig(context),
*((BYTE *)data), CS_sig(context), IP_sig(context));
break; break;
case 0x6d: case 0x6d:
if (long_op) if (long_op)
{ *(DWORD *)data = INSTR_inport( dx, 4, context );
*((DWORD *)data) = IO_inport( DX_sig(context), 4);
TRACE_(io)("0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
*((DWORD *)data), CS_sig(context), IP_sig(context));
}
else else
{ *(WORD *)data = INSTR_inport( dx, 2, context );
*((WORD *)data) = IO_inport( DX_sig(context), 2);
TRACE_(io)("0x%x < %04x @ %04x:%04x\n", DX_sig(context),
*((WORD *)data), CS_sig(context), IP_sig(context));
}
break; break;
case 0x6e: case 0x6e:
IO_outport( DX_sig(context), 1, *((BYTE *)data)); INSTR_outport( dx, 1, *(BYTE *)data, context );
TRACE_(io)("0x%x > %02x @ %04x:%04x\n", DX_sig(context),
*((BYTE *)data), CS_sig(context), IP_sig(context));
break; break;
case 0x6f: case 0x6f:
if (long_op) if (long_op)
{ INSTR_outport( dx, 4, *(DWORD *)data, context );
IO_outport( DX_sig(context), 4, *((DWORD *)data));
TRACE_(io)("0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
*((DWORD *)data), CS_sig(context), IP_sig(context));
}
else else
{ INSTR_outport( dx, 2, *(WORD *)data, context );
IO_outport( DX_sig(context), 2, *((WORD *)data));
TRACE_(io)("0x%x > %04x @ %04x:%04x\n", DX_sig(context),
*((WORD *)data), CS_sig(context), IP_sig(context));
}
break; break;
} }
} }
EIP_sig(context) += prefixlen + 1; EIP_reg(context) += prefixlen + 1;
} }
return TRUE; return TRUE;
@ -614,31 +631,27 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
switch((instr[1] >> 3) & 7) switch((instr[1] >> 3) & 7)
{ {
case 0: case 0:
ES_sig(context) = seg; ES_reg(context) = seg;
EIP_sig(context) += prefixlen + len + 1; EIP_reg(context) += prefixlen + len + 1;
return TRUE; return TRUE;
case 1: /* cs */ case 1: /* cs */
break; break;
case 2: case 2:
SS_sig(context) = seg; SS_reg(context) = seg;
EIP_sig(context) += prefixlen + len + 1; EIP_reg(context) += prefixlen + len + 1;
return TRUE; return TRUE;
case 3: case 3:
DS_sig(context) = seg; DS_reg(context) = seg;
EIP_sig(context) += prefixlen + len + 1; EIP_reg(context) += prefixlen + len + 1;
return TRUE; return TRUE;
#ifdef FS_sig
case 4: case 4:
FS_sig(context) = seg; FS_reg(context) = seg;
EIP_sig(context) += prefixlen + len + 1; EIP_reg(context) += prefixlen + len + 1;
return TRUE; return TRUE;
#endif
#ifdef GS_sig
case 5: case 5:
GS_sig(context) = seg; GS_reg(context) = seg;
EIP_sig(context) += prefixlen + len + 1; EIP_reg(context) += prefixlen + len + 1;
return TRUE; return TRUE;
#endif
case 6: /* unused */ case 6: /* unused */
case 7: /* unused */ case 7: /* unused */
break; break;
@ -651,7 +664,7 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
if (INSTR_EmulateLDS( context, instr, long_op, if (INSTR_EmulateLDS( context, instr, long_op,
long_addr, segprefix, &len )) long_addr, segprefix, &len ))
{ {
EIP_sig(context) += prefixlen + len; EIP_reg(context) += prefixlen + len;
return TRUE; return TRUE;
} }
break; /* Unable to emulate it */ break; /* Unable to emulate it */
@ -667,13 +680,13 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
FARPROC16 addr = INT_GetPMHandler( instr[1] ); FARPROC16 addr = INT_GetPMHandler( instr[1] );
WORD *stack = (WORD *)STACK_PTR( context ); WORD *stack = (WORD *)STACK_PTR( context );
/* Push the flags and return address on the stack */ /* Push the flags and return address on the stack */
*(--stack) = FL_sig(context); *(--stack) = LOWORD(EFL_reg(context));
*(--stack) = CS_sig(context); *(--stack) = CS_reg(context);
*(--stack) = IP_sig(context) + prefixlen + 2; *(--stack) = LOWORD(EIP_reg(context)) + prefixlen + 2;
ADD_STACK_sig(context, -3 * sizeof(WORD)); ADD_STACK_reg(context, -3 * sizeof(WORD));
/* Jump to the interrupt handler */ /* Jump to the interrupt handler */
CS_sig(context) = HIWORD(addr); CS_reg(context) = HIWORD(addr);
EIP_sig(context) = LOWORD(addr); EIP_reg(context) = LOWORD(addr);
} }
return TRUE; return TRUE;
@ -681,135 +694,95 @@ BOOL INSTR_EmulateInstruction( SIGCONTEXT *context )
if (long_op) if (long_op)
{ {
DWORD *stack = (DWORD *)STACK_PTR( context ); DWORD *stack = (DWORD *)STACK_PTR( context );
EIP_sig(context) = *stack++; EIP_reg(context) = *stack++;
CS_sig(context) = *stack++; CS_reg(context) = *stack++;
EFL_sig(context) = *stack; EFL_reg(context) = *stack;
ADD_STACK_sig(context, 3*sizeof(DWORD)); /* Pop the return address and flags */ ADD_STACK_reg(context, 3*sizeof(DWORD)); /* Pop the return address and flags */
} }
else else
{ {
WORD *stack = (WORD *)STACK_PTR( context ); WORD *stack = (WORD *)STACK_PTR( context );
EIP_sig(context) = *stack++; EIP_reg(context) = *stack++;
CS_sig(context) = *stack++; CS_reg(context) = *stack++;
FL_sig(context) = *stack; SET_LOWORD(EFL_reg(context),*stack);
ADD_STACK_sig(context, 3*sizeof(WORD)); /* Pop the return address and flags */ ADD_STACK_reg(context, 3*sizeof(WORD)); /* Pop the return address and flags */
} }
return TRUE; return TRUE;
case 0xe4: /* inb al,XX */ case 0xe4: /* inb al,XX */
AL_sig(context) = IO_inport( instr[1], 1 ); SET_LOBYTE(EAX_reg(context),INSTR_inport( instr[1], 1, context ));
TRACE_(io)("0x%x < %02x @ %04x:%04x\n", instr[1], EIP_reg(context) += prefixlen + 2;
AL_sig(context), CS_sig(context), IP_sig(context));
EIP_sig(context) += prefixlen + 2;
return TRUE; return TRUE;
case 0xe5: /* in (e)ax,XX */ case 0xe5: /* in (e)ax,XX */
if (long_op) if (long_op)
{ EAX_reg(context) = INSTR_inport( instr[1], 4, context );
EAX_sig(context) = IO_inport( instr[1], 4 );
TRACE_(io)("0x%x < %08lx @ %04x:%04x\n", instr[1],
EAX_sig(context), CS_sig(context), IP_sig(context));
}
else else
{ SET_LOWORD(EAX_reg(context), INSTR_inport( instr[1], 2, context ));
AX_sig(context) = IO_inport( instr[1], 2 ); EIP_reg(context) += prefixlen + 2;
TRACE_(io)("0x%x < %04x @ %04x:%04x\n", instr[1],
AX_sig(context), CS_sig(context), IP_sig(context));
}
EIP_sig(context) += prefixlen + 2;
return TRUE; return TRUE;
case 0xe6: /* outb XX,al */ case 0xe6: /* outb XX,al */
IO_outport( instr[1], 1, AL_sig(context) ); INSTR_outport( instr[1], 1, LOBYTE(EAX_reg(context)), context );
TRACE_(io)("0x%x > %02x @ %04x:%04x\n", instr[1], EIP_reg(context) += prefixlen + 2;
AL_sig(context), CS_sig(context), IP_sig(context));
EIP_sig(context) += prefixlen + 2;
return TRUE; return TRUE;
case 0xe7: /* out XX,(e)ax */ case 0xe7: /* out XX,(e)ax */
if (long_op) if (long_op)
{ INSTR_outport( instr[1], 4, EAX_reg(context), context );
IO_outport( instr[1], 4, EAX_sig(context) );
TRACE_(io)("0x%x > %08lx @ %04x:%04x\n", instr[1],
EAX_sig(context), CS_sig(context), IP_sig(context));
}
else else
{ INSTR_outport( instr[1], 2, LOWORD(EAX_reg(context)), context );
IO_outport( instr[1], 2, AX_sig(context) ); EIP_reg(context) += prefixlen + 2;
TRACE_(io)("0x%x > %04x @ %04x:%04x\n", instr[1],
AX_sig(context), CS_sig(context), IP_sig(context));
}
EIP_sig(context) += prefixlen + 2;
return TRUE; return TRUE;
case 0xec: /* inb al,dx */ case 0xec: /* inb al,dx */
AL_sig(context) = IO_inport( DX_sig(context), 1 ); SET_LOBYTE(EAX_reg(context), INSTR_inport( LOWORD(EDX_reg(context)), 1, context ) );
TRACE_(io)("0x%x < %02x @ %04x:%04x\n", DX_sig(context), EIP_reg(context) += prefixlen + 1;
AL_sig(context), CS_sig(context), IP_sig(context));
EIP_sig(context) += prefixlen + 1;
return TRUE; return TRUE;
case 0xed: /* in (e)ax,dx */ case 0xed: /* in (e)ax,dx */
if (long_op) if (long_op)
{ EAX_reg(context) = INSTR_inport( LOWORD(EDX_reg(context)), 4, context );
EAX_sig(context) = IO_inport( DX_sig(context), 4 );
TRACE_(io)("0x%x < %08lx @ %04x:%04x\n", DX_sig(context),
EAX_sig(context), CS_sig(context), IP_sig(context));
}
else else
{ SET_LOWORD(EAX_reg(context), INSTR_inport( LOWORD(EDX_reg(context)), 2, context ));
AX_sig(context) = IO_inport( DX_sig(context), 2 ); EIP_reg(context) += prefixlen + 1;
TRACE_(io)("0x%x < %04x @ %04x:%04x\n", DX_sig(context),
AX_sig(context), CS_sig(context), IP_sig(context));
}
EIP_sig(context) += prefixlen + 1;
return TRUE; return TRUE;
case 0xee: /* outb dx,al */ case 0xee: /* outb dx,al */
IO_outport( DX_sig(context), 1, AL_sig(context) ); INSTR_outport( LOWORD(EDX_reg(context)), 1, LOBYTE(EAX_reg(context)), context );
TRACE_(io)("0x%x > %02x @ %04x:%04x\n", DX_sig(context), EIP_reg(context) += prefixlen + 1;
AL_sig(context), CS_sig(context), IP_sig(context));
EIP_sig(context) += prefixlen + 1;
return TRUE; return TRUE;
case 0xef: /* out dx,(e)ax */ case 0xef: /* out dx,(e)ax */
if (long_op) if (long_op)
{ INSTR_outport( LOWORD(EDX_reg(context)), 4, EAX_reg(context), context );
IO_outport( DX_sig(context), 4, EAX_sig(context) );
TRACE_(io)("0x%x > %08lx @ %04x:%04x\n", DX_sig(context),
EAX_sig(context), CS_sig(context), IP_sig(context));
}
else else
{ INSTR_outport( LOWORD(EDX_reg(context)), 2, LOWORD(EAX_reg(context)), context );
IO_outport( DX_sig(context), 2, AX_sig(context) ); EIP_reg(context) += prefixlen + 1;
TRACE_(io)("0x%x > %04x @ %04x:%04x\n", DX_sig(context),
AX_sig(context), CS_sig(context), IP_sig(context));
}
EIP_sig(context) += prefixlen + 1;
return TRUE; return TRUE;
case 0xfa: /* cli, ignored */ case 0xfa: /* cli, ignored */
EIP_sig(context) += prefixlen + 1; EIP_reg(context) += prefixlen + 1;
return TRUE; return TRUE;
case 0xfb: /* sti, ignored */ case 0xfb: /* sti, ignored */
EIP_sig(context) += prefixlen + 1; EIP_reg(context) += prefixlen + 1;
return TRUE; return TRUE;
} }
/* Check for Win16 __GP handler */ /* Check for Win16 __GP handler */
gpHandler = HasGPHandler16( PTR_SEG_OFF_TO_SEGPTR( CS_sig(context), gpHandler = HasGPHandler16( PTR_SEG_OFF_TO_SEGPTR( CS_reg(context),
EIP_sig(context) ) ); EIP_reg(context) ) );
if (gpHandler) if (gpHandler)
{ {
WORD *stack = (WORD *)STACK_PTR( context ); WORD *stack = (WORD *)STACK_PTR( context );
*--stack = CS_sig(context); *--stack = CS_reg(context);
*--stack = EIP_sig(context); *--stack = EIP_reg(context);
ADD_STACK_sig(context, -2*sizeof(WORD)); ADD_STACK_reg(context, -2*sizeof(WORD));
CS_sig(context) = SELECTOROF( gpHandler ); CS_reg(context) = SELECTOROF( gpHandler );
EIP_sig(context) = OFFSETOF( gpHandler ); EIP_reg(context) = OFFSETOF( gpHandler );
return TRUE; return TRUE;
} }
return FALSE; /* Unable to emulate it */ return FALSE; /* Unable to emulate it */