From b3756782778236b769357dfb1616b2e4f1160f30 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 1 Aug 1999 12:15:12 +0000 Subject: [PATCH] Changed INSTR_EmulateInstruction to use a CONTEXT86 instead of a SIGCONTEXT. --- dlls/ntdll/exception.c | 26 ++- include/miscemu.h | 3 + include/sig_context.h | 3 - include/windef.h | 8 + loader/dos/dosvm.c | 24 +- memory/instr.c | 509 +++++++++++++++++++---------------------- 6 files changed, 277 insertions(+), 296 deletions(-) diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index ca540377b35..e3728f300d5 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -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 ); } diff --git a/include/miscemu.h b/include/miscemu.h index b27c070a7cd..16d98b240e3 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -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); diff --git a/include/sig_context.h b/include/sig_context.h index a851ed10e7e..933c432b1e0 100644 --- a/include/sig_context.h +++ b/include/sig_context.h @@ -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 */ diff --git a/include/windef.h b/include/windef.h index f115e4740b3..8ff77373a40 100644 --- a/include/windef.h +++ b/include/windef.h @@ -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 diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c index 78bcbcbceca..60a002424ee 100644 --- a/loader/dos/dosvm.c +++ b/loader/dos/dosvm.c @@ -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) { diff --git a/memory/instr.c b/memory/instr.c index ac173b9e088..4aa6b522d93 100644 --- a/memory/instr.c +++ b/memory/instr.c @@ -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 */