Changed INSTR_EmulateInstruction to use a CONTEXT86 instead of a
SIGCONTEXT.
This commit is contained in:
parent
352c04c6a9
commit
b375678277
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
509
memory/instr.c
509
memory/instr.c
|
@ -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,8 +242,8 @@ 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;
|
||||||
BYTE *regmodrm = instr + 1 + (*instr == 0x0f);
|
BYTE *regmodrm = instr + 1 + (*instr == 0x0f);
|
||||||
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue