Skip to content

Commit

Permalink
fix imm8-se regs, limit avx regs to 0..15, flatten rex bit storage.
Browse files Browse the repository at this point in the history
Change-Id: Icc0072d2dcdae915da10ebaef4e1e4b2a68bbf37
(cherry picked from commit 885563e33d9189d4e64636d0bb55e79fc66f2634)
  • Loading branch information
mjcharne authored and markcharney committed Aug 9, 2019
1 parent 7737065 commit 0c2d97d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 77 deletions.
73 changes: 52 additions & 21 deletions examples/xed-enc2-1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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;
}
18 changes: 9 additions & 9 deletions include/private/xed-enc2-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

Expand Down
51 changes: 23 additions & 28 deletions include/public/xed/xed-encode-direct.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,63 +26,59 @@ END_LEGAL */
#include <stdarg.h>

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;i<sizeof(xed_enc2_req_t)/sizeof(xed_uint32_t);i++)
for(i=0;i<sizeof(r->flat)/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;
}
Expand All @@ -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);


Expand Down
64 changes: 47 additions & 17 deletions pysrc/enc2test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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,
Expand All @@ -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'])



Expand All @@ -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
Expand All @@ -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))
Expand Down Expand Up @@ -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')
Expand Down
4 changes: 2 additions & 2 deletions src/enc2/xed-encode-direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 0c2d97d

Please sign in to comment.