diff --git a/examples/xed-enc2-1.c b/examples/xed-enc2-1.c index a55d0d0f..b34a4e6b 100644 --- a/examples/xed-enc2-1.c +++ b/examples/xed-enc2-1.c @@ -41,8 +41,26 @@ static xed_uint32_t test_0_xed_enc_lea_rm_q_bisd32_a64(xed_uint8_t* output_buffe return xed_enc2_encoded_length(r); } +xed_uint32_t test_0_xed_enc_vpblendvb_xxxx(xed_uint8_t* output_buffer) +{ + xed_enc2_req_t* r; + xed_reg_enum_t reg0; + xed_reg_enum_t reg1; + xed_reg_enum_t reg2; + xed_reg_enum_t reg3; + xed_enc2_req_t request; + xed_enc2_req_t_init(&request, output_buffer); + r = &request; + reg0 = XED_REG_XMM6; + reg1 = XED_REG_XMM7; + reg2 = XED_REG_XMM8; + reg3 = XED_REG_XMM9; + xed_enc_vpblendvb_xxxx(r /*req*/,reg0 /*xmm*/,reg1 /*xmm*/,reg2 /*xmm*/,reg3 /*xmm*/); + return xed_enc2_encoded_length(r); +} + // The decoder drags in a lot of stuff to the final executable. -//#define DECO +#define DECO #if defined(DECO) static void disassemble(xed_decoded_inst_t* xedd) @@ -64,6 +82,25 @@ static void disassemble(xed_decoded_inst_t* xedd) else printf("Disassembly: %%ERROR%%\n"); } + +static int decode(xed_uint8_t* buf, xed_uint32_t len) { + xed_decoded_inst_t xedd; + xed_error_enum_t err; + xed_state_t dstate; + + xed_tables_init(); + xed_state_zero(&dstate); + dstate.mmode=XED_MACHINE_MODE_LONG_64; + + xed_decoded_inst_zero_set_mode(&xedd, &dstate); + err = xed_decode(&xedd, buf, len); + if (err == XED_ERROR_NONE) { + disassemble(&xedd); + return 0; + } + printf("ERROR: %s\n", xed_error_enum_t2str(err)); + return 1; +} #endif static void dump(xed_uint8_t* buf, xed_uint32_t len) { @@ -72,37 +109,31 @@ static void dump(xed_uint8_t* buf, xed_uint32_t len) { printf("%02x ",buf[i]); } - int main(int argc, char** argv) { -#if defined(DECO) - xed_decoded_inst_t xedd; - xed_error_enum_t err; - xed_state_t dstate; -#endif xed_uint8_t output_buffer[XED_MAX_INSTRUCTION_BYTES]; xed_uint32_t enclen; + int retval=0, r=0; + enclen = test_0_xed_enc_lea_rm_q_bisd32_a64(output_buffer); + printf("Encoded: "); + dump(output_buffer, enclen); + printf("\n"); #if defined(DECO) - xed_tables_init(); - xed_state_zero(&dstate); - dstate.mmode=XED_MACHINE_MODE_LONG_64; + r = decode(output_buffer, enclen); + retval += r; + printf("decode returned %d\n",r); #endif - enclen = test_0_xed_enc_lea_rm_q_bisd32_a64(output_buffer); - + enclen = test_0_xed_enc_vpblendvb_xxxx(output_buffer); printf("Encoded: "); dump(output_buffer, enclen); printf("\n"); - #if defined(DECO) - xed_decoded_inst_zero_set_mode(&xedd, &dstate); - err = xed_decode(&xedd, output_buffer, enclen); - if (err == XED_ERROR_NONE) { - disassemble(&xedd); - return 0; - } - printf("ERROR: %s\n", xed_error_enum_t2str(err)); - return 1; + r = decode(output_buffer, enclen); + retval += r; + printf("decode returned %d\n",r); #endif + + return retval; (void)argc; (void)argv; } diff --git a/include/private/xed-enc2-private.h b/include/private/xed-enc2-private.h index 736951c3..d612cfbf 100644 --- a/include/private/xed-enc2-private.h +++ b/include/private/xed-enc2-private.h @@ -59,28 +59,28 @@ static XED_INLINE void set_has_sib(xed_enc2_req_t* r) { static XED_INLINE void set_rexw(xed_enc2_req_t* r) { - r->s.u.s.rexw = 1; + r->s.rexw = 1; } static XED_INLINE void set_rexr(xed_enc2_req_t* r, xed_uint_t v) { - r->s.u.s.rexr = v; + r->s.rexr = v; } static XED_INLINE void set_rexb(xed_enc2_req_t* r, xed_uint_t v) { - r->s.u.s.rexb = v; + r->s.rexb = v; } static XED_INLINE void set_rexx(xed_enc2_req_t* r, xed_uint_t v) { - r->s.u.s.rexx = v; + r->s.rexx = v; } static XED_INLINE xed_uint_t get_rexw(xed_enc2_req_t* r) { - return r->s.u.s.rexw; + return r->s.rexw; } static XED_INLINE xed_uint_t get_rexx(xed_enc2_req_t* r) { - return r->s.u.s.rexx; + return r->s.rexx; } static XED_INLINE xed_uint_t get_rexr(xed_enc2_req_t* r) { - return r->s.u.s.rexr; + return r->s.rexr; } static XED_INLINE xed_uint_t get_rexb(xed_enc2_req_t* r) { - return r->s.u.s.rexb; + return r->s.rexb; } static XED_INLINE void set_mod(xed_enc2_req_t* r, xed_uint_t v) { @@ -295,7 +295,7 @@ static XED_INLINE void set_need_rex(xed_enc2_req_t* r) { r->s.need_rex = 1; } static XED_INLINE void emit_rex_if_needed(xed_enc2_req_t* r) { - if (r->s.u.rex || r->s.need_rex) + if (r->s.rexw || r->s.rexr || r->s.rexb || r->s.rexx || r->s.need_rex) emit_rex(r); } diff --git a/include/public/xed/xed-encode-direct.h b/include/public/xed/xed-encode-direct.h index e458e089..5fff2705 100644 --- a/include/public/xed/xed-encode-direct.h +++ b/include/public/xed/xed-encode-direct.h @@ -26,63 +26,59 @@ END_LEGAL */ #include typedef struct { - xed_uint8_t* itext; - xed_uint32_t cursor; + xed_uint8_t* itext; // supplied by user during init + xed_uint32_t cursor; // where we write next byte xed_uint32_t has_sib:1; xed_uint32_t has_disp8:1; xed_uint32_t has_disp16:1; xed_uint32_t has_disp32:1; - xed_uint32_t need_rex:1; // for SIL,DIL,BPL,SPL - union { - struct { - xed_uint32_t rexw:1; // and vex, evex - xed_uint32_t rexr:1; // and vex, evex - xed_uint32_t rexx:1; // and vex, evex - xed_uint32_t rexb:1; // and vex, evex - } s; - xed_uint32_t rex; - } u; - + xed_uint32_t rexw:1; // and vex, evex + xed_uint32_t rexr:1; // and vex, evex + xed_uint32_t rexx:1; // and vex, evex + xed_uint32_t rexb:1; // and vex, evex + + xed_uint32_t need_rex:1; // for SIL,DIL,BPL,SPL xed_uint32_t evexrr:1; - xed_uint32_t vvvv:4; - xed_uint32_t map:3; - xed_uint32_t vexpp:3; // and evex - xed_uint32_t vexl:1; - xed_uint32_t evexll:2; // also rc bits in some case + xed_uint32_t vexl:1; xed_uint32_t evexb:1; // also sae enabler for reg-only & vl=512 + xed_uint32_t evexvv:1; xed_uint32_t evexz:1; - xed_uint32_t evexaaa:3; - - xed_uint32_t opcode_srm:3; /// for "partial opcode" instructions + xed_uint32_t evexll:2; // also rc bits in some case + xed_uint32_t mod:2; xed_uint32_t reg:3; xed_uint32_t rm:3; xed_uint32_t sibscale:2; xed_uint32_t sibindex:3; xed_uint32_t sibbase:3; + xed_uint32_t evexaaa:3; + xed_uint32_t map:3; + xed_uint32_t vexpp:3; // and evex + xed_uint32_t vvvv:4; + xed_uint32_t opcode_srm:3; /// for "partial opcode" instructions xed_uint8_t imm8_reg; // for _SE imm8-specified registers. -} xed_enc2_req_payload_t; - +} xed_enc2_req_payload_t; typedef union { xed_enc2_req_payload_t s; - xed_uint32_t flat[sizeof(xed_enc2_req_payload_t)/sizeof(xed_uint32_t)]; + xed_uint32_t flat[(sizeof(xed_enc2_req_payload_t)+3)/sizeof(xed_uint32_t)]; } xed_enc2_req_t; - +/// Zero out a #xed_enc2_req_t structure and set the output pointer. +/// Required before calling and any ENC2 encoding function. static XED_INLINE void xed_enc2_req_t_init(xed_enc2_req_t* r, xed_uint8_t* output_buffer) { xed_uint32_t i; - for(i=0;iflat)/sizeof(xed_uint32_t);i++) r->flat[i] = 0; r->s.itext = output_buffer; } -/// To find out how many bytes were used for the encoding +/// Returns the number of bytes that were used for the encoding. static XED_INLINE xed_uint32_t xed_enc2_encoded_length(xed_enc2_req_t* r) { return r->s.cursor; } @@ -98,7 +94,6 @@ typedef void (xed_user_abort_handler_t)(const char* format, va_list args); /// Set a function taking a variable-number-of-arguments (stdarg) to handle /// the errors and die. The argument are like printf with a format string /// followed by a varaible number of arguments. - XED_DLL_EXPORT void xed_enc2_set_error_handler(xed_user_abort_handler_t* fn); diff --git a/pysrc/enc2test.py b/pysrc/enc2test.py index 8393f323..67f9152e 100644 --- a/pysrc/enc2test.py +++ b/pysrc/enc2test.py @@ -76,9 +76,14 @@ def _add_test_function(ii,fo): x87 = [ 'ST{}'.format(i) for i in range(0,8)] kreg = [ 'K{}'.format(i) for i in range(0,8)] kreg_not0 = [ 'K{}'.format(i) for i in range(1,8)] -xmm_m64 = [ 'XMM{}'.format(i) for i in range(0,32)] -ymm_m64 = [ 'YMM{}'.format(i) for i in range(0,32)] -zmm_m64 = [ 'ZMM{}'.format(i) for i in range(0,32)] + +xmm_vex_m64 = [ 'XMM{}'.format(i) for i in range(0,16)] +ymm_vex_m64 = [ 'YMM{}'.format(i) for i in range(0,16)] + +xmm_evex_m64 = [ 'XMM{}'.format(i) for i in range(0,32)] +ymm_evex_m64 = [ 'YMM{}'.format(i) for i in range(0,32)] +zmm_evex_m64 = [ 'ZMM{}'.format(i) for i in range(0,32)] + xmm_not64 = [ 'XMM{}'.format(i) for i in range(0,8)] ymm_not64 = [ 'YMM{}'.format(i) for i in range(0,8)] zmm_not64 = [ 'ZMM{}'.format(i) for i in range(0,8)] @@ -114,9 +119,13 @@ def set_test_gen_counters(env): #'kreg': kreg, 'kreg': kreg_not0, 'kreg!0': kreg_not0, - 'xmm': xmm_m64 if env.mode==64 else xmm_not64, - 'ymm': ymm_m64 if env.mode==64 else ymm_not64, - 'zmm': zmm_m64 if env.mode==64 else zmm_not64, + + 'xmm': xmm_vex_m64 if env.mode==64 else xmm_not64, + 'ymm': ymm_vex_m64 if env.mode==64 else ymm_not64, + + 'xmm_evex': xmm_evex_m64 if env.mode==64 else xmm_not64, + 'ymm_evex': ymm_evex_m64 if env.mode==64 else ymm_not64, + 'zmm_evex': zmm_evex_m64 if env.mode==64 else zmm_not64, # FIXME: avoiding CS because of MOV SEG limitation #'seg': seg, 'seg': seg_no_cs, @@ -133,7 +142,8 @@ def set_test_gen_counters(env): # the xmm,ymm,zmm regs have the same limit. Just using zmm to get # a limit value - env.test_gen_reg_limit['simd_unified'] = len(env.test_gen_regs['zmm']) + env.test_gen_reg_limit['simd_unified'] = len(env.test_gen_regs['xmm']) + env.test_gen_reg_limit['simd_unified_evex'] = len(env.test_gen_regs['zmm_evex']) @@ -149,17 +159,24 @@ def get_bump(env, regkind): return testreg -def get_bump_unified(env,regkind): +def get_bump_unified(env,regkind,evex): '''Gathers require that we use different regs for the simd registers but often gathers use different vector length reg for the different things if addresses and data are different sizes. So we make a common counter that gathers can use to avoid accidental independent counters lining up for xmm,ymm and zmm... which does happen.''' - - special_regkind = 'simd_unified' + + if evex: + special_regkind = 'simd_unified_evex' + else: + special_regkind = 'simd_unified' v = env.test_gen_counters[special_regkind] - testreg = env.test_gen_regs[regkind][v] # use regkind to get the register name + try: + testreg = env.test_gen_regs[regkind][v] # use regkind to get the register name + except: + sys.stderr.write("ERROR: EVEX={} REGKIND={} V={}\n".format(evex,regkind,v)) + sys.exit(1) # increment and roll the counter based on the limits for tht reg kind n = v + 1 @@ -170,8 +187,8 @@ def get_bump_unified(env,regkind): -def gen_reg_simd_unified(env,regkind): - return 'XED_REG_{}'.format(get_bump_unified(env,regkind)) +def gen_reg_simd_unified(env,regkind, evex=True): + return 'XED_REG_{}'.format(get_bump_unified(env,regkind,evex)) def gen_reg(env,regkind): return 'XED_REG_{}'.format(get_bump(env,regkind)) @@ -204,16 +221,29 @@ def is_gather(ii): def get_xmm(env, ii): if is_gather(ii): - return gen_reg_simd_unified(env,'xmm') + if ii.space == 'evex': + return gen_reg_simd_unified(env,'xmm_evex', True) + return gen_reg_simd_unified(env,'xmm', False) + + if ii.space == 'evex': + return gen_reg(env,'xmm_evex') return gen_reg(env,'xmm') + + def get_ymm(env, ii): if is_gather(ii): - return gen_reg_simd_unified(env,'ymm') + if ii.space == 'evex': + return gen_reg_simd_unified(env,'ymm_evex', True) + return gen_reg_simd_unified(env,'ymm', False) + + if ii.space == 'evex': + return gen_reg(env,'ymm_evex') return gen_reg(env,'ymm') + def get_zmm(env, ii): if is_gather(ii): - return gen_reg_simd_unified(env,'zmm') - return gen_reg(env,'zmm') + return gen_reg_simd_unified(env,'zmm_evex', True) + return gen_reg(env,'zmm_evex') def get_kreg(env, ii): return gen_reg(env,'kreg') diff --git a/src/enc2/xed-encode-direct.c b/src/enc2/xed-encode-direct.c index 523587b4..77d6a6eb 100644 --- a/src/enc2/xed-encode-direct.c +++ b/src/enc2/xed-encode-direct.c @@ -424,12 +424,12 @@ void enc_srm_gpr64(xed_enc2_req_t* r, void enc_imm8_reg_xmm(xed_enc2_req_t* r, // _SE imm8 reg xed_reg_enum_t dst) { xed_uint_t offset = dst-XED_REG_XMM_FIRST; - set_imm8_reg(r, offset); + set_imm8_reg(r, offset<<4); } void enc_imm8_reg_ymm(xed_enc2_req_t* r, // _SE imm8 reg xed_reg_enum_t dst) { xed_uint_t offset = dst-XED_REG_YMM_FIRST; - set_imm8_reg(r, offset); + set_imm8_reg(r, offset<<4); } // CRs and DRs, SEG regs