Alexandre Julliard : ntoskrnl: Add emulation of CRn and DRn registers on x86-64.
Alexandre Julliard
julliard at winehq.org
Tue Apr 3 15:39:06 CDT 2018
Module: wine
Branch: master
Commit: ce09790d29630a6a4c0cd49459afc2097700ad10
URL: https://source.winehq.org/git/wine.git/?a=commit;h=ce09790d29630a6a4c0cd49459afc2097700ad10
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Apr 3 11:46:01 2018 +0200
ntoskrnl: Add emulation of CRn and DRn registers on x86-64.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntoskrnl.exe/instr.c | 112 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 103 insertions(+), 9 deletions(-)
diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c
index fdbe8bd..b2dac58 100644
--- a/dlls/ntoskrnl.exe/instr.c
+++ b/dlls/ntoskrnl.exe/instr.c
@@ -594,6 +594,8 @@ static BYTE *INSTR_GetOperandAddr( CONTEXT *context, BYTE *instr,
*/
static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
{
+ static const char *reg_names[16] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
int prefix, segprefix, prefixlen, len, long_op, long_addr, rex;
BYTE *instr;
@@ -635,21 +637,34 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
case 0x67:
long_addr = !long_addr; /* addr size prefix */
break;
+ case 0x40: /* rex */
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ rex = *instr;
+ break;
case 0xf0: /* lock */
- break;
+ break;
case 0xf2: /* repne */
- break;
+ break;
case 0xf3: /* repe */
break;
default:
prefix = 0; /* no more prefixes */
break;
}
- if (*instr >= 0x40 && *instr < 0x50) /* rex */
- {
- rex = *instr;
- prefix = TRUE;
- }
if (prefix)
{
instr++;
@@ -664,6 +679,84 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
case 0x0f: /* extended instruction */
switch(instr[1])
{
+ case 0x20: /* mov crX, Rd */
+ {
+ int reg = REGMODRM_REG( instr[2], rex );
+ int rm = REGMODRM_RM( instr[2], rex );
+ DWORD64 *data = get_int_reg( context, rm );
+ TRACE( "mov cr%u,%s at %lx\n", reg, reg_names[rm], context->Rip );
+ switch (reg)
+ {
+ case 0: *data = 0x10; break; /* FIXME: set more bits ? */
+ case 2: *data = 0; break;
+ case 3: *data = 0; break;
+ case 4: *data = 0; break;
+ case 8: *data = 0; break;
+ default: return ExceptionContinueSearch;
+ }
+ context->Rip += prefixlen + 3;
+ return ExceptionContinueExecution;
+ }
+ case 0x21: /* mov drX, Rd */
+ {
+ int reg = REGMODRM_REG( instr[2], rex );
+ int rm = REGMODRM_RM( instr[2], rex );
+ DWORD64 *data = get_int_reg( context, rm );
+ TRACE( "mov dr%u,%s at %lx\n", reg, reg_names[rm], context->Rip );
+ switch (reg)
+ {
+ case 0: *data = context->Dr0; break;
+ case 1: *data = context->Dr1; break;
+ case 2: *data = context->Dr2; break;
+ case 3: *data = context->Dr3; break;
+ case 4: /* dr4 and dr5 are obsolete aliases for dr6 and dr7 */
+ case 6: *data = context->Dr6; break;
+ case 5:
+ case 7: *data = 0x400; break;
+ default: return ExceptionContinueSearch;
+ }
+ context->Rip += prefixlen + 3;
+ return ExceptionContinueExecution;
+ }
+ case 0x22: /* mov Rd, crX */
+ {
+ int reg = REGMODRM_REG( instr[2], rex );
+ int rm = REGMODRM_RM( instr[2], rex );
+ DWORD64 *data = get_int_reg( context, rm );
+ TRACE( "mov %s,cr%u at %lx, %s=%lx\n", reg_names[rm], reg, context->Rip, reg_names[rm], *data );
+ switch (reg)
+ {
+ case 0: break;
+ case 2: break;
+ case 3: break;
+ case 4: break;
+ case 8: break;
+ default: return ExceptionContinueSearch;
+ }
+ context->Rip += prefixlen + 3;
+ return ExceptionContinueExecution;
+ }
+ case 0x23: /* mov Rd, drX */
+ {
+ int reg = REGMODRM_REG( instr[2], rex );
+ int rm = REGMODRM_RM( instr[2], rex );
+ DWORD64 *data = get_int_reg( context, rm );
+ TRACE( "mov %s,dr%u at %lx, %s=%lx\n", reg_names[rm], reg, context->Rip, reg_names[rm], *data );
+ switch (reg)
+ {
+ case 0: context->Dr0 = *data; break;
+ case 1: context->Dr1 = *data; break;
+ case 2: context->Dr2 = *data; break;
+ case 3: context->Dr3 = *data; break;
+ case 4: /* dr4 and dr5 are obsolete aliases for dr6 and dr7 */
+ case 6: context->Dr6 = *data; break;
+ case 5:
+ case 7: context->Dr7 = *data; break;
+ default: return ExceptionContinueSearch;
+ }
+ context->Rip += prefixlen + 3;
+ return ExceptionContinueExecution;
+ }
case 0xb6: /* movzx Eb, Gv */
case 0xb7: /* movzx Ew, Gv */
{
@@ -738,8 +831,9 @@ LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs )
EXCEPTION_RECORD *record = ptrs->ExceptionRecord;
CONTEXT *context = ptrs->ContextRecord;
- if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
- record->ExceptionInformation[0] == EXCEPTION_READ_FAULT)
+ if (record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION ||
+ (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
+ record->ExceptionInformation[0] == EXCEPTION_READ_FAULT))
{
if (emulate_instruction( record, context ) == ExceptionContinueExecution)
{
More information about the wine-cvs
mailing list