Skip to content

Commit

Permalink
wip: amx to enc2
Browse files Browse the repository at this point in the history
(cherry picked from commit 9d09faa8fad2282f268f18fd9f3bc280658cdaa4)
  • Loading branch information
mjcharne authored and markcharney committed Nov 3, 2020
1 parent 647c65b commit bae930f
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 4 deletions.
5 changes: 5 additions & 0 deletions include/private/xed-enc2-check.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ void xed_enc2_invalid_zmm(xed_uint_t mode, xed_reg_enum_t reg,const char* argnam
void xed_enc2_invalid_rcsae(xed_uint_t mode, xed_uint_t rcsae,const char* argname,const char* pfn);
void xed_enc2_invalid_scale(xed_uint_t mode, xed_uint_t scale,const char* argname,const char* pfn);
void xed_enc2_invalid_zeroing(xed_uint_t mode, xed_uint_t zeroing,const char* argname,const char* pfn);

# if defined(XED_REG_TREG_FIRST_DEFINED)
void xed_enc2_invalid_tmm(xed_uint_t mode, xed_reg_enum_t reg,
const char* argname, const char* pfn);
# endif
#endif
13 changes: 12 additions & 1 deletion include/private/xed-enc2-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,10 @@ void enc_vvvv_reg_gpr32(xed_enc2_req_t* r,
xed_reg_enum_t dst);
void enc_vvvv_reg_gpr64(xed_enc2_req_t* r,
xed_reg_enum_t dst);

#if defined(XED_REG_TMM_FIRST_DEFINED)
void enc_vvvv_reg_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst);
#endif

void enc_modrm_rm_x87(xed_enc2_req_t* r,
xed_reg_enum_t dst);
Expand Down Expand Up @@ -726,4 +729,12 @@ xed_int32_t xed_chose_evex_scaled_disp(xed_enc2_req_t* r,
xed_int32_t xed_chose_evex_scaled_disp16(xed_enc2_req_t* r,
xed_int32_t requested_displacement,
xed_uint32_t reference_width_bytes);
# if defined(XED_REG_TREG_FIRST_DEFINED)
void enc_vvvv_reg_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst);
void enc_modrm_reg_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst);
void enc_modrm_rm_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst);
# endif
#endif
210 changes: 207 additions & 3 deletions pysrc/enc2gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ def op_agen(op): # LEA
if 'AGEN' in op.name:
return True
return False
def op_tmm(op):
if op.lookupfn_name:
if 'TMM' in op.lookupfn_name:
return True
return False
def op_xmm(op):
if op.lookupfn_name:
if 'XMM' in op.lookupfn_name:
Expand Down Expand Up @@ -960,7 +965,9 @@ def _convert_to_osz(w):
if op.name.startswith('INDEX'):
continue

if op_xmm(op):
if op_tmm(op):
s.append('t')
elif op_xmm(op):
s.append('x')
elif op_ymm(op):
s.append('y')
Expand Down Expand Up @@ -1009,7 +1016,9 @@ def _convert_to_osz(w):
s.append('m' + _translate_width_z(using_width))
else:
osz = _convert_to_osz(using_width) if using_width else 0
if op.oc2 == 'vv':
if op.oc2 == 'tv' or op.oc2.startswith('tm'):
bits = 'tv'
elif op.oc2 == 'vv':
# read_xed_db figures out the memop width for
# no-broadcast and broadcasting cases for EVEX
# memops.
Expand Down Expand Up @@ -1856,6 +1865,8 @@ def get_opnd_types(env, ii, osz=0):
elif op_implicit_specific_reg(op):
pass # ignore

elif op_tmm(op):
s.append('tmm')
elif op_xmm(op):
s.append('xmm')
elif op_ymm(op):
Expand Down Expand Up @@ -4098,7 +4109,196 @@ def create_vex_all_mask_reg(env,ii):
if ii.has_imm8:
cond_emit_imm8(ii,fo)
add_enc_func(ii,fo)

def vex_amx_mem(ii):
if 'AMX' in ii.isa_set:
for op in _gen_opnds(ii):
if op_mem(op):
return True
return False

def vex_amx_reg(ii):
if 'AMX' in ii.isa_set:
for op in _gen_opnds(ii):
if op_mem(op):
return False
return True
return False

def create_vex_amx_reg(env,ii): # FIXME: XXX
global enc_fn_prefix, arg_request
global arg_reg0, var_reg0
global arg_reg1, var_reg1
global arg_reg2, var_reg2
global arg_reg3, var_reg3

nopnds = count_operands(ii) # not imm8
opnd_sig = make_opnd_signature(env,ii)
fname = "{}_{}_{}".format(enc_fn_prefix,
ii.iclass.lower(),
opnd_sig)

fo = make_function_object(env,ii,fname)
fo.add_comment("created by create_vex_amx_reg opnd_sig={} nopnds={}".format(opnd_sig,nopnds))
fo.add_arg(arg_request,'req')
print("WORKING ON {}".format(ii.iclass))
opnd_types = get_opnd_types(env,ii)
if nopnds >= 1:
fo.add_arg(arg_reg0,opnd_types[0])
if nopnds >= 2:
fo.add_arg(arg_reg1, opnd_types[1])
if nopnds >= 3:
fo.add_arg(arg_reg2, opnd_types[2])
if nopnds >= 4:
fo.add_arg(arg_reg3, opnd_types[3])
cond_add_imm_args(ii,fo)

set_vex_pp(ii,fo)
fo.add_code_eol('set_map(r,{})'.format(ii.map))

if ii.vl == '256': # ZERO INIT OPTIMIZATION
fo.add_code_eol('set_vexl(r,1)')

fo.add_code_eol('set_mod(r,3)')

vars = [var_reg0, var_reg1, var_reg2, var_reg3]

var_r, var_b, var_n, var_se = None, None, None, None
for i,op in enumerate(_gen_opnds(ii)):
if op.lookupfn_name:
if op.lookupfn_name.endswith('_R'):
var_r,sz_r = vars[i], get_type_size(op)
elif op.lookupfn_name.endswith('_B'):
var_b,sz_b = vars[i], get_type_size(op)
elif op.lookupfn_name.endswith('_N'):
var_n,sz_n = vars[i], get_type_size(op)
else:
die("SHOULD NOT REACH HERE")
if ii.rexw_prefix == '1':
fo.add_code_eol('set_rexw(r)')

if var_n:
fo.add_code_eol('enc_vvvv_reg_{}(r,{})'.format(sz_n, var_n))
else:
fo.add_code_eol('set_vvvv(r,0xF)',"must be 1111")

if var_r:
fo.add_code_eol('enc_modrm_reg_{}(r,{})'.format(sz_r, var_r))
elif ii.reg_required != 'unspecified':
if ii.reg_required: # ZERO INIT OPTIMIZATION
fo.add_code_eol('set_reg(r,{})'.format(ii.reg_required))

if var_b:
fo.add_code_eol('enc_modrm_rm_{}(r,{})'.format(sz_b, var_b))
elif ii.rm_required != 'unspecified':
if ii.rm_required: # ZERO INIT OPTIMIZATION
fo.add_code_eol('set_rm(r,{})'.format(ii.rm_required))

emit_vex_prefix(env, ii,fo,register_only=True)
emit_opcode(ii,fo)
emit_modrm(fo)
if ii.has_imm8:
cond_emit_imm8(ii,fo)
elif var_se:
fo.add_code_eol('emit_se_imm8_reg(r)')
add_enc_func(ii,fo)


def create_vex_amx_mem(env,ii): # FIXME: XXX
global enc_fn_prefix, arg_request
global arg_reg0, var_reg0
global arg_reg1, var_reg1
global arg_reg2, var_reg2
global arg_reg3, var_reg3
global arg_imm8

nopnds = count_operands(ii) # skips imm8
op = first_opnd(ii)
width = op.oc2
opsig = make_opnd_signature(env,ii)
immw=0
if ii.has_imm8:
immw=8
dispsz_list = get_dispsz_list(env)
opnd_types_org = get_opnd_types(env,ii)
arg_regs = [ arg_reg0, arg_reg1, arg_reg2, arg_reg3 ]
var_regs = [ var_reg0, var_reg1, var_reg2, var_reg3 ]

ispace = itertools.product(get_index_vals(ii), dispsz_list)
for use_index, dispsz in ispace:
memaddrsig = get_memsig(env.asz, use_index, dispsz)

fname = "{}_{}_{}_{}".format(enc_fn_prefix,
ii.iclass.lower(),
opsig,
memaddrsig)

fo = make_function_object(env,ii,fname, asz=env.asz)
fo.add_comment("created by create_vex_amx_mem")
fo.add_arg(arg_request,'req')
opnd_types = copy.copy(opnd_types_org)

regn = 0
for i,optype in enumerate(opnd_types_org):
if optype in ['tmm','xmm','ymm','zmm', 'gpr32', 'gpr64', 'kreg']:
fo.add_arg(arg_regs[regn], opnd_types.pop(0))
regn += 1
elif optype in ['mem']:
add_memop_args(env, ii, fo, use_index, dispsz, immw=0)
opnd_types.pop(0)
elif optype in 'int8':
fo.add_arg(arg_imm8,'int8')
opnd_types.pop(0) # imm8 is last so we technically can skip this pop
else:
die("UNHANDLED ARG {} in {}".format(optype, ii.iclass))

set_vex_pp(ii,fo)
fo.add_code_eol('set_map(r,{})'.format(ii.map))

if ii.vl == '256': # Not setting VL=128 since that is ZERO OPTIMIZATION
fo.add_code_eol('set_vexl(r,1)')

# FIXME REFACTOR function-ize this
var_r, var_b, var_n, var_se = None,None,None,None
sz_r, sz_b, sz_n, sz_se = None,None,None,None
for i,op in enumerate(_gen_opnds_nomem(ii)): # use no mem version to skip memop if a store-type op
if op.lookupfn_name:
if op.lookupfn_name.endswith('_R'):
var_r,sz_r = var_regs[i],get_type_size(op)
elif op.lookupfn_name.endswith('_B'):
var_b,sz_b = var_regs[i],get_type_size(op)
elif op.lookupfn_name.endswith('_N'):
var_n,sz_n = var_regs[i],get_type_size(op)
else:
die("SHOULD NOT REACH HERE")

if ii.rexw_prefix == '1':
fo.add_code_eol('set_rexw(r)')

if var_n == None:
fo.add_code_eol('set_vvvv(r,0xF)',"must be 1111")
else:
fo.add_code_eol('enc_vvvv_reg_{}(r,{})'.format(sz_n, var_n))

if var_r:
fo.add_code_eol('enc_modrm_reg_{}(r,{})'.format(sz_r, var_r))
elif ii.reg_required != 'unspecified':
if ii.reg_required: # ZERO INIT OPTIMIZATION
fo.add_code_eol('set_reg(r,{})'.format(ii.reg_required))

if var_b:
fo.add_code_eol('enc_modrm_rm_{}(r,{})'.format(sz_b, var_b))
elif ii.rm_required != 'unspecified':
if ii.rm_required: # ZERO INIT OPTIMIZATION
fo.add_code_eol('set_rm(r,{})'.format(ii.rm_required))

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')
add_enc_func(ii,fo)


def _enc_vex(env,ii):
if several_xymm_gpr_imm8(ii):
create_vex_simd_reg(env,ii)
Expand All @@ -4108,9 +4308,13 @@ def _enc_vex(env,ii):
create_vex_all_mask_reg(env,ii)
elif vex_one_mask_reg_and_one_gpr(ii):
create_vex_one_mask_reg_and_one_gpr(env,ii)

elif vex_vzero(ii):
create_vex_vzero(env,ii)
elif vex_amx_reg(ii):
create_vex_amx_reg(env,ii)
elif vex_amx_mem(ii):
create_vex_amx_mem(env,ii)


def vex_vzero(ii):
return ii.iclass.startswith('VZERO')
Expand Down
7 changes: 7 additions & 0 deletions pysrc/enc2test.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ def _add_test_function(ii,fo):
ymm_not64 = [ 'YMM{}'.format(i) for i in range(0,8)]
zmm_not64 = [ 'ZMM{}'.format(i) for i in range(0,8)]

tmm = [ 'TMM{}'.format(i) for i in range(0,8)]

seg = 'ES CS SS DS FS GS'.split()
seg_no_cs = 'ES SS DS FS GS'.split()
cr_64 = 'CR0 CR2 CR3 CR4 CR8'.split()
Expand Down Expand Up @@ -109,6 +111,7 @@ def set_test_gen_counters(env):

'xmm': xmm_vex_m64 if env.mode==64 else xmm_not64,
'ymm': ymm_vex_m64 if env.mode==64 else ymm_not64,
'tmm': tmm if env.mode==64 else [],

'xmm_evex': xmm_evex_m64 if env.mode==64 else xmm_not64,
'ymm_evex': ymm_evex_m64 if env.mode==64 else ymm_not64,
Expand Down Expand Up @@ -232,6 +235,9 @@ def get_zmm(env, ii):
return gen_reg_simd_unified(env,'zmm_evex', True)
return gen_reg(env,'zmm_evex')

def get_tmm(env, ii):
return gen_reg(env,'tmm')

def get_kreg(env, ii):
return gen_reg(env,'kreg')
def get_kreg_not0(env, ii):
Expand Down Expand Up @@ -311,6 +317,7 @@ def get_disp64(env, ii):
'xmm': get_xmm,
'ymm': get_ymm,
'zmm': get_zmm,
'tmm': get_tmm,
'kreg': get_kreg,
'kreg!0': get_kreg_not0,
'x87': get_x87,
Expand Down
23 changes: 23 additions & 0 deletions src/enc2/xed-encode-direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,29 @@ void enc_vvvv_reg_ymm(xed_enc2_req_t* r,
set_vvvv(r, ~(offset & 15));
}

#if defined(XED_REG_TREG_FIRST_DEFINED)
void enc_vvvv_reg_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst) {
xed_uint_t offset = dst-XED_REG_TREG_FIRST;
set_vvvv(r, 8|(~(offset & 7)));
}

void enc_modrm_reg_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst) {
xed_uint_t offset = dst-XED_REG_TREG_FIRST;
set_reg(r, offset & 7);
//set_rexr(r,0); // zero init optimization
}

void enc_modrm_rm_tmm(xed_enc2_req_t* r,
xed_reg_enum_t dst) {
xed_uint_t offset = dst-XED_REG_TREG_FIRST;
set_rm(r, offset & 7);
//set_rexb(r,0); // zero init optimization
}

#endif

void enc_vvvv_reg_gpr32(xed_enc2_req_t* r,
xed_reg_enum_t dst) {
xed_uint_t offset = dst-XED_REG_GPR32_FIRST;
Expand Down
12 changes: 12 additions & 0 deletions src/enc2chk/xed-enc2-check.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,15 @@ xed_bool_t xed_enc2_check_args = 1;
void xed_enc2_set_check_args(xed_bool_t on) {
xed_enc2_check_args = on;
}


#if defined(XED_REG_TREG_FIRST_DEFINED)
void xed_enc2_invalid_tmm(xed_uint_t mode, xed_reg_enum_t reg,
const char* argname, const char* pfn)
{
if (reg < XED_REG_TREG_FIRST || reg > XED_REG_TREG_LAST)
xed_enc2_error("Bad TMM reg %s arg_name %s in function %s", xed_reg_enum_t2str(reg), argname, pfn);
if (mode != 64)
xed_enc2_error("Non-64b-mode TMM reg %s arg_name %s in function %s", xed_reg_enum_t2str(reg), argname, pfn);
}
#endif

0 comments on commit bae930f

Please sign in to comment.