From 2b44713a108ca0134648a2c038703c73de73db4b Mon Sep 17 00:00:00 2001 From: Mark Charney Date: Thu, 6 Feb 2020 16:11:27 -0500 Subject: [PATCH] Fixes for enc2 & testing * vpermil2ps (XOP) has a imm8 value and a reg encoded in the imm8 upper bits. I had to support merging the values from the imm8 and the register encoding and only emit one imm8. For now, I 'OR' the two values together. If the test generator generates a large imm8 value for this instr, then the register bits will likely get corrupted. * RCL and ROR with implicit one operands were getting imm8's appended their output. Had to improve test for gpr8_imm8 and gprv_imm8. * Bad luck cased the test for XCHG to use EAX,EAX and it decoded as a NOP and failed. I excluded EAX from the test register list for gpr32 in 32b mode. Change-Id: If62f212f1bbc6e929b7cb12f8210da2fc28a81ce (cherry picked from commit 45bedfe2a0306b52156e3b16bff5e4c77f417335) --- include/private/xed-enc2-private.h | 6 ++++++ pysrc/enc2gen.py | 31 +++++++++++++++++++++++------- pysrc/enc2test.py | 1 + src/enc2/xed-encode-direct.c | 13 +++++++++++++ src/enc2test/test.c | 26 +++++++++++++++++-------- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/include/private/xed-enc2-private.h b/include/private/xed-enc2-private.h index bbfbb471..76b1796f 100644 --- a/include/private/xed-enc2-private.h +++ b/include/private/xed-enc2-private.h @@ -469,6 +469,12 @@ void enc_imm8_reg_xmm(xed_enc2_req_t* r, xed_reg_enum_t dst); void enc_imm8_reg_ymm(xed_enc2_req_t* r, xed_reg_enum_t dst); +void enc_imm8_reg_xmm_and_imm(xed_enc2_req_t* r, + xed_reg_enum_t dst, + xed_uint_t imm); +void enc_imm8_reg_ymm_and_imm(xed_enc2_req_t* r, + xed_reg_enum_t dst, + xed_uint_t imm); // CRs and DRs, SEG regs diff --git a/pysrc/enc2gen.py b/pysrc/enc2gen.py index 149e8f18..34fa4103 100755 --- a/pysrc/enc2gen.py +++ b/pysrc/enc2gen.py @@ -536,6 +536,8 @@ def two_scalable_regs(ii): # allow optional imm8, immz, allow one implicit GPR return n==2 and i <= 1 and implicit <= 1 def op_implicit(op): return op.visibility == 'IMPLICIT' +def op_implicit_or_suppressed(op): + return op.visibility in ['IMPLICIT','SUPPRESSED'] def one_x87_reg(ii): n = 0 @@ -657,8 +659,11 @@ def op_immv(op): def op_imm8(op): if op.name == 'IMM0': if op.oc2 == 'b': + if op_implicit_or_suppressed(op): + return False return True return False + def op_imm16(op): if op.name == 'IMM0': if op.oc2 == 'w': @@ -2073,36 +2078,42 @@ def create_legacy_one_x87_reg(env,ii): def gpr8_imm8(ii): + reg,imm=0,0 for i,op in enumerate(_gen_opnds(ii)): if i == 0: if op.name == 'REG0' and op_luf_start(op,'GPR8'): - continue + reg = reg + 1 else: return False elif i == 1: if op.name == 'IMM0' and op.oc2 == 'b': - continue + if op_implicit_or_suppressed(op): + return False + imm = imm + 1 else: return False else: return False - return True + return reg == 1 and imm == 1 def gprv_imm8(ii): + reg,imm=0,0 for i,op in enumerate(_gen_opnds(ii)): if i == 0: if op.name == 'REG0' and op_luf_start(op,'GPRv'): - continue + reg = reg + 1 else: return False elif i == 1: if op.name == 'IMM0' and op.oc2 == 'b': - continue + if op_implicit_or_suppressed(op): + return False + imm = imm + 1 else: return False else: return False - return True + return reg == 1 and imm == 1 def gprv_immz(ii): for i,op in enumerate(_gen_opnds(ii)): @@ -3925,10 +3936,16 @@ def create_vex_regs_mem(env,ii): fo.add_code_eol('set_rm(r,{})'.format(ii.rm_required)) if var_se: - fo.add_code_eol('enc_imm8_reg_{}(r,{})'.format(sz_se, var_se)) + if immw: + immw=0 + fo.add_code_eol('enc_imm8_reg_{}_and_imm(r,{},{})'.format(sz_se, var_se, var_imm8)) + else: + fo.add_code_eol('enc_imm8_reg_{}(r,{})'.format(sz_se, var_se)) encode_mem_operand(env, ii, fo, use_index, dispsz) emit_vex_prefix(env, ii,fo,register_only=False) + + finish_memop(env, ii, fo, dispsz, immw, space='vex') if var_se: fo.add_code_eol('emit_se_imm8_reg(r)') diff --git a/pysrc/enc2test.py b/pysrc/enc2test.py index c5139a4a..9c4dbf4b 100644 --- a/pysrc/enc2test.py +++ b/pysrc/enc2test.py @@ -45,6 +45,7 @@ def _add_test_function(ii,fo): gpr64_index = "RAX RCX RDX RBX RSI RDI RBP R8 R9 R10 R11 R12 R13 R14 R15".split() gpr32_not64 = "EAX ECX EDX EBX ESI EDI EBP ESP".split() +gpr32_not64 = "ECX EDX EBX ESI EDI EBP ESP".split() # omit EAX for XCHG EAX,EAX vs NOP issue gpr32_index_not64 = "EAX ECX EDX EBX ESI EDI EBP".split() gpr16_not64 = "AX CX DX BX SI DI BP SP".split() diff --git a/src/enc2/xed-encode-direct.c b/src/enc2/xed-encode-direct.c index 279089b6..0a884697 100644 --- a/src/enc2/xed-encode-direct.c +++ b/src/enc2/xed-encode-direct.c @@ -433,6 +433,19 @@ void enc_imm8_reg_ymm(xed_enc2_req_t* r, // _SE imm8 reg set_imm8_reg(r, offset<<4); } +void enc_imm8_reg_xmm_and_imm(xed_enc2_req_t* r, // _SE imm8 reg + xed_reg_enum_t dst, + xed_uint_t imm) { + xed_uint_t offset = dst-XED_REG_XMM_FIRST; + set_imm8_reg(r, (offset<<4)|imm); +} +void enc_imm8_reg_ymm_and_imm(xed_enc2_req_t* r, // _SE imm8 reg + xed_reg_enum_t dst, + xed_uint_t imm) { + xed_uint_t offset = dst-XED_REG_YMM_FIRST; + set_imm8_reg(r, (offset<<4)|imm); +} + // CRs and DRs, SEG regs void enc_modrm_reg_cr(xed_enc2_req_t* r, diff --git a/src/enc2test/test.c b/src/enc2test/test.c index 4c139130..99838d94 100644 --- a/src/enc2test/test.c +++ b/src/enc2test/test.c @@ -53,9 +53,18 @@ static void dump(xed_uint8_t* buf, xed_uint32_t len) { printf("%02x ",buf[i]); } } +static void dump_comment(xed_uint8_t* buf, xed_uint32_t len) { + xed_uint_t i; + printf("// "); + for(i=0;i0) @@ -67,6 +76,7 @@ static void dump_emit_byte(xed_uint8_t* buf, xed_uint32_t len) { static void dump_emit(xed_uint8_t* buf, xed_uint32_t len) { xed_uint_t i; + dump_comment(buf,len); for(i=0;i