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();
#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;
#ifdef TRAP_sig
@ -451,12 +461,11 @@ static HANDLER_DEF(EXC_segv)
break;
case 11: /* Segment not present exception */
case 13: /* General protection fault */
if (INSTR_EmulateInstruction( HANDLER_CONTEXT )) return;
if (INSTR_EmulateInstruction( &context )) goto restore;
rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
break;
case 14: /* Page fault */
#ifdef CR2_sig
if (VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) )) return;
rec.NumberParameters = 2;
#ifdef ERROR_sig
rec.ExceptionInformation[0] = (ERROR_sig(HANDLER_CONTEXT) & 2) != 0;
@ -469,11 +478,11 @@ static HANDLER_DEF(EXC_segv)
break;
case 17: /* Alignment check exception */
/* FIXME: pass through exception handler first? */
if (EFL_sig(HANDLER_CONTEXT) & 0x00040000)
if (EFL_reg(&context) & 0x00040000)
{
/* Disable AC flag, return */
EFL_sig(HANDLER_CONTEXT) &= ~0x00040000;
return;
EFL_reg(&context) &= ~0x00040000;
goto restore;
}
rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
break;
@ -492,16 +501,13 @@ static HANDLER_DEF(EXC_segv)
}
#else /* TRAP_sig */
# ifdef __i386
if (INSTR_EmulateInstruction( HANDLER_CONTEXT )) return;
if (INSTR_EmulateInstruction( &context )) return;
# endif
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; /* generic error */
#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 );
restore:
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 UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
/* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
/* msdos/devices.c */
extern void DOSDEV_InstallDOSDevices(void);

View file

@ -284,7 +284,4 @@ typedef DWORD SIGCONTEXT;
#define HANDLER_CONTEXT 0
#endif
/* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( SIGCONTEXT * );
#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 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. */
/* Note: These macros are semantically broken, at least for wrc. wrc
spits out data in the platform's current binary format, *not* in

View file

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

View file

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