Paul Gofman : ntoskrnl.exe: Support 'or Ev, Gv' opcode for x86_64.
Alexandre Julliard
julliard at winehq.org
Fri May 22 13:51:09 CDT 2020
Module: wine
Branch: master
Commit: e7778dd9f925b498994c26aec23a483dd2588583
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e7778dd9f925b498994c26aec23a483dd2588583
Author: Paul Gofman <pgofman at codeweavers.com>
Date: Fri May 22 15:37:50 2020 +0300
ntoskrnl.exe: Support 'or Ev, Gv' opcode for x86_64.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntoskrnl.exe/instr.c | 53 ++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 7 deletions(-)
diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c
index dad4e5d660..848a566d02 100644
--- a/dlls/ntoskrnl.exe/instr.c
+++ b/dlls/ntoskrnl.exe/instr.c
@@ -35,6 +35,12 @@
#define KSHARED_USER_DATA_PAGE_SIZE 0x1000
+enum instr_op
+{
+ INSTR_OP_MOV,
+ INSTR_OP_OR,
+};
+
#ifdef __i386__
WINE_DEFAULT_DEBUG_CHANNEL(int);
@@ -503,20 +509,42 @@ static inline int get_op_size( int long_op, int rex )
}
/* store an operand into a register */
-static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex )
+static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex,
+ enum instr_op op )
{
int index = REGMODRM_REG( regmodrm, rex );
BYTE *reg = (BYTE *)get_int_reg( context, index );
- memcpy( reg, addr, get_op_size( long_op, rex ) );
+ int op_size = get_op_size( long_op, rex );
+ int i;
+
+ switch (op)
+ {
+ case INSTR_OP_MOV:
+ memcpy( reg, addr, op_size );
+ break;
+ case INSTR_OP_OR:
+ for (i = 0; i < op_size; ++i)
+ reg[i] |= addr[i];
+ break;
+ }
}
/* store an operand into a byte register */
-static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex )
+static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex, enum instr_op op )
{
int index = REGMODRM_REG( regmodrm, rex );
BYTE *reg = (BYTE *)get_int_reg( context, index );
if (!rex && index >= 4 && index < 8) reg -= (4 * sizeof(DWORD64) - 1); /* special case: ah, ch, dh, bh */
- *reg = *addr;
+
+ switch (op)
+ {
+ case INSTR_OP_MOV:
+ *reg = *addr;
+ break;
+ case INSTR_OP_OR:
+ *reg |= *addr;
+ break;
+ }
}
/***********************************************************************
@@ -798,7 +826,7 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip);
memcpy( &temp, wine_user_shared_data + offset, data_size );
- store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex );
+ store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex, INSTR_OP_MOV );
context->Rip += prefixlen + len + 2;
return ExceptionContinueExecution;
}
@@ -809,6 +837,7 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
case 0x8a: /* mov Eb, Gb */
case 0x8b: /* mov Ev, Gv */
+ case 0x0b: /* or Ev, Gv */
{
BYTE *data = INSTR_GetOperandAddr( context, instr + 1, prefixlen + 1, long_addr,
rex, segprefix, &len );
@@ -820,8 +849,18 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip);
switch (*instr)
{
- case 0x8a: store_reg_byte( context, instr[1], wine_user_shared_data + offset, rex ); break;
- case 0x8b: store_reg_word( context, instr[1], wine_user_shared_data + offset, long_op, rex ); break;
+ case 0x8a:
+ store_reg_byte( context, instr[1], wine_user_shared_data + offset,
+ rex, INSTR_OP_MOV );
+ break;
+ case 0x8b:
+ store_reg_word( context, instr[1], wine_user_shared_data + offset,
+ long_op, rex, INSTR_OP_MOV );
+ break;
+ case 0x0b:
+ store_reg_word( context, instr[1], wine_user_shared_data + offset,
+ long_op, rex, INSTR_OP_OR );
+ break;
}
context->Rip += prefixlen + len + 1;
return ExceptionContinueExecution;
More information about the wine-cvs
mailing list