Skip to content

Commit

Permalink
encoder cleanup removing "massive hack" using legacy map0 for vex/evex
Browse files Browse the repository at this point in the history
  * removed a lot of code that worked (but not all) with hard-coded
    legacy maps.

  * removed the "massive hack" where the code used legacy MAP0 in the
    encoder iform instruction table to avoid emitting legacy map
    encoding bytes for VEX/EVEX instructions (as well as legacy MAP0).

  * Starting to use the map_info_t records in the encoder.

(cherry picked from commit 67c6284fcbd8ad4cc26ea8e0a227f4ad8559e28e)
  • Loading branch information
mjcharne authored and markcharney committed Nov 3, 2020
1 parent 4b53423 commit a23e816
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 95 deletions.
8 changes: 0 additions & 8 deletions include/private/xed-encode-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ xed_encoder_get_encoder_iform(const xed_encoder_request_t* r){
return xed_encode_iform_db + iform_index;
}

void
xed_encoder_request_emit_legacy_map(xed_encoder_request_t* q);

void
xed_encoder_request_emit_bytes(xed_encoder_request_t* q,
Expand Down Expand Up @@ -150,12 +148,6 @@ xed_encoder_get_nominal_opcode(const xed_encoder_request_t* p){
return enc_iform->_nom_opcode;
}

static XED_INLINE xed_uint8_t
xed_encoder_get_map(const xed_encoder_request_t* p){
//FIXME:2019-10-03 Misnamed. really legacy map. Used for emitting legacy escape/map
const xed_encoder_iform_t* enc_iform = xed_encoder_get_encoder_iform(p);
return enc_iform->_legacy_map;
}

static XED_INLINE xed_uint16_t
xed_encoder_get_fb_values_index(const xed_encoder_request_t* p){
Expand Down
1 change: 0 additions & 1 deletion include/private/xed-encode-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ typedef struct xed_encoder_iform_s{
xed_uint8_t _emit_ptrn_index;

xed_uint8_t _nom_opcode;
xed_uint8_t _legacy_map;

//start index of the field values in xed_encode_fb_values_table
xed_uint16_t _fb_values_index;
Expand Down
61 changes: 29 additions & 32 deletions pysrc/ins_emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,19 @@ def get_values(self,encoder_config):

encoder_config.ins_groups = self.instruction_groups


def _emit_legacy_map(self, fo, iform):
# obj_str is the function parameters for the emit function
def _xemit(bits, v):
fo.add_code_eol('xed_encoder_request_emit_bytes({},{},0x{:02x})'.format(
encutil.enc_strings['obj_str'], bits, v))

if iform.legacy_map.legacy_escape != 'N/A':
bits = 8
_xemit(bits, iform.legacy_map.legacy_escape_int)
if iform.legacy_map.legacy_opcode != 'N/A':
_xemit(bits, iform.legacy_map.legacy_opcode_int)


def _make_emit_fo(self, iform, i):
''' create the function object for this emit pattern
Expand All @@ -291,13 +303,17 @@ def _make_emit_fo(self, iform, i):
# for VEX/EVEX/XOP instr (see
# _identify_map_and_nominal_opcode() ) to avoid emitting
# any escape/map bytes at runtime.

if action.field_name and action.field_name == 'MAP':
# FIXME: could directly emit the legacy escapes (0F,0F38,0F3A,0F0F)
if action.field_name == 'MAP':
if iform.encspace == 0: # legacy
emit_map = 'xed_encoder_request_emit_legacy_map'
code = " %s(%s)" % (emit_map,obj_str)
fo.add_code_eol(code)
genutil.die("Should not see MAP here: {}".format(iform.iclass))
pass
elif action.field_name and action.field_name in ['LEGACY_MAP1',
'LEGACY_MAP2',
'LEGACY_MAP3',
'LEGACY_MAP3DNOW']:
if iform.encspace != 0: # legacy
genutil.die("This should only occur for legacy instr")
self._emit_legacy_map(fo, iform)

elif action.field_name and action.field_name == 'NOM_OPCODE':
code = ''
Expand Down Expand Up @@ -497,30 +513,14 @@ def _identify_map_and_nominal_opcode(self,iform):
if vv:
# all VEX/EVEX/XOP instr have an explicit map

# disabled this (and later code) because of MAP0
# hack to avoid emitting legacy escapes
if 0:
mapno = 0
for action in iform.rule.actions:
if action.is_field_binding() and action.field_name == 'MAP':
mapno = action.int_value
break
#this action represents the opcode
iform.nominal_opcode = first.int_value
iform.nom_opcode_bits = first.nbits
iform.map = 'XED_ILD_LEGACY_MAP0' # MASSIVE HACK used to avoid emitting legacy escapes
# see above "disabled" comment
if 0:
if mapno < 8:
iform.map = 'XED_ILD_LEGACY_MAP{}'.format(mapno)
else:
iform.map = 'XED_ILD_AMD_XOP{}'.format(hex(mapno)[-1].upper())
iform.rule.actions[i] = actions.dummy_emit(first,'NOM_OPCODE') # replace opcode
elif first.int_value != 0x0F:
elif first.int_value != 0x0F: # map 0
#this action represents the opcode
iform.nominal_opcode = first.int_value
iform.nom_opcode_bits = first.nbits
iform.map = 'XED_ILD_LEGACY_MAP0'
iform.rule.actions[i] = actions.dummy_emit(first,'NOM_OPCODE') # replace opcode

else: #first byte == 0x0F and we are legacy space
Expand All @@ -539,10 +539,9 @@ def _identify_map_and_nominal_opcode(self,iform):
amd3dnow_opcode_action = iform.rule.actions[-1]
iform.nominal_opcode = amd3dnow_opcode_action.int_value
iform.nom_opcode_bits = 8
iform.map = 'XED_ILD_AMD_3DNOW'
iform.rule.actions[-1] = actions.dummy_emit(amd3dnow_opcode_action,
'NOM_OPCODE')
iform.rule.actions[i] = actions.dummy_emit(first,'MAP') # replace first 0xF
iform.rule.actions[i] = actions.dummy_emit(first,'LEGACY_MAP3DNOW') # replace first 0xF
# the second 0x0F byte that describes the map is not needed, remove it
iform.rule.actions.remove(second)

Expand All @@ -558,19 +557,18 @@ def _identify_map_and_nominal_opcode(self,iform):
iform.nominal_opcode = third.int_value
iform.nom_opcode_bits = third.nbits
if second.int_value==0x38:
iform.map = 'XED_ILD_LEGACY_MAP2'
xmap = 'LEGACY_MAP2'
else:
iform.map = 'XED_ILD_LEGACY_MAP3'
iform.rule.actions[i+1] = actions.dummy_emit(second,'MAP') # replace the 0x38 or 0x3A
xmap = 'LEGACY_MAP3'
iform.rule.actions[i+1] = actions.dummy_emit(second,xmap) # replace the 0x38 or 0x3A
iform.rule.actions[i+2] = actions.dummy_emit(third,
'NOM_OPCODE') # replace opcode
iform.rule.actions.remove(first) # remove the 0x0F

else: # legacy map1 0f prefix only, 2nd byte is opcode
iform.nominal_opcode = second.int_value
iform.nom_opcode_bits = second.nbits
iform.map = 'XED_ILD_LEGACY_MAP1'
iform.rule.actions[i] = actions.dummy_emit(first,'MAP') # replace 0x0F
iform.rule.actions[i] = actions.dummy_emit(first,'LEGACY_MAP1') # replace 0x0F
iform.rule.actions[i+1] = actions.dummy_emit(second, # replace opcode
'NOM_OPCODE')

Expand Down Expand Up @@ -747,7 +745,6 @@ def _print_log(self):
emit_fo.function_name))

print("NOM_OPCODE: %d" % iform.nominal_opcode)
print("MAP: %s" % iform.map)
fbs_values = [ x.int_value for x in iform.fbs]
print("FB values: %s" % fbs_values)
print("\n\n")
Expand Down
8 changes: 8 additions & 0 deletions pysrc/map_info_rdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ def _parse_map_line(s):
setattr(mi,fld,t[i])
# this gets used in function names so must only be legal characters
mi.map_name = re.sub('-', '_', mi.map_name)
if mi.space == 'legacy':
if mi.legacy_escape != 'N/A':
mi.legacy_escape_int = int(mi.legacy_escape,16)
if mi.legacy_opcode != 'N/A':
mi.legacy_opcode_int = int(mi.legacy_opcode,16)
else:
mi.legacy_opcode_int = None

mi.map_id_fixup=False

if mi.space not in ['legacy','vex','evex', 'xop']:
Expand Down
47 changes: 37 additions & 10 deletions pysrc/read-encfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def remove_file(fn):
os.unlink(fn)

class blot_t(object):
"""A blot_t is a fragment of a decoder pattern"""
"""A blot_t is make a fragment of a decoder pattern"""
def __init__(self,type=None):
self.type = type # 'bits', 'letters', 'nt', "od" (operand decider)
self.nt = None # name of a nonterminal
Expand Down Expand Up @@ -1072,7 +1072,8 @@ def get_all_nts(self):

class iform_t(object):
"""One form of an instruction"""
def __init__(self, iclass, enc_conditions, enc_actions, modal_patterns, uname=None):
def __init__(self, map_info,
iclass, enc_conditions, enc_actions, modal_patterns, uname=None):
self.iclass = iclass
self.uname = uname
self.enc_conditions = enc_conditions # [ operand_t ]
Expand All @@ -1087,8 +1088,38 @@ def __init__(self, iclass, enc_conditions, enc_actions, modal_patterns, uname=No
self.fb_ptrn = None

self._fixup_vex_conditions()
self._find_legacy_map(map_info)
self.rule = self.make_rule()


def _find_legacy_map(self, map_info):
"""Set self.legacy_map to the map_info_t record that best matches"""
if self.encspace == 0:
s = []
self.legacy_map = None
for act in self.enc_actions:
if act.type == 'bits':
s.append(act.value)
if s:
found = False
default_map = None
for m in map_info:
if m.space == 'legacy':
if m.legacy_escape == 'N/A': # 1B map (map 0)
default_map = m
elif m.legacy_escape_int == s[0]:
if m.legacy_opcode == 'N/A': # 2B maps (map-1 like)
found = True
self.legacy_map = m
break
elif len(s)>=2 and m.legacy_opcode_int == s[1]: # 3B maps
self.legacy_map = m
found = True
break
if not found:
self.legacy_map = default_map
if not self.legacy_map:
genutil.die("Could not set legacy map.")

def _fixup_vex_conditions(self):
"""if action has VEXVALID=1, add modal_pattern MUST_USE_AVX512=0.
The modal_patterns become conditions later on."""
Expand Down Expand Up @@ -2203,13 +2234,14 @@ def finalize_decode_conversion(self,iclass, operands, ipattern, uname=None):
die("No iclass for " + operands)
# the encode conditions are the decode operands (as [ operand_t ])
# the encode actions are the decode patterns (as [ blot_t ])
# the modal_patterns are things that should become encode conditions
(conditions, actions, modal_patterns) = \
self.parse_one_decode_rule(iclass, operands, ipattern)
if vfinalize():
self.print_iclass_info(iclass, operands, ipattern, conditions,
actions, modal_patterns)
# FIXME do something with the operand/conditions and patterns/actions
iform = iform_t(iclass, conditions, actions, modal_patterns, uname)
iform = iform_t(self.map_info, iclass, conditions, actions, modal_patterns, uname)

if uname == 'NOP0F1F':
# We have many fat NOPS, 0F1F is the preferred one so we
Expand Down Expand Up @@ -3020,25 +3052,20 @@ def emit_encoder_iform_table(self):
fe.add_header('xed-ild-enum.h')
fe.start()

ptrn = ("/*(%4d)%20s*/ {%4d, %4d, %4s," +
" XED_STATIC_CAST(xed_uint8_t,%15s), %4d}")
ptrn = ("/*(%4d)%20s*/ {%4d, %4d, %4s, %4d}")
iform_definitions = []
for iform in self.all_iforms:#iforms:
iform_init = ptrn % (iform.rule.iform_id,
iform.iclass,
iform.bind_func_index,
iform.emit_func_index,
hex(iform.nominal_opcode),
iform.map,
iform.fb_index)
iform_definitions.append(iform_init)

self._emit_functions_lu_table(fe, 'xed_encoder_iform_t',
iform_definitions, 'xed_encode_iform_db',
'XED_ENCODE_MAX_IFORMS')



fe.close()
output_file_emitters.append(fe)

Expand Down
44 changes: 0 additions & 44 deletions src/enc/xed-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,50 +33,6 @@ END_LEGAL */



// Emitting the legacy map bytes.
// Need to convert from xed_ild_map_enum_t to the actual bytes.
// called from generated code (in OBJDIR/xed-enc-patterns.c)
void xed_encoder_request_emit_legacy_map(xed_encoder_request_t* q)
{
xed_uint8_t bits;
xed_uint16_t value;
xed_ild_map_enum_t map;
map = XED_STATIC_CAST(xed_ild_map_enum_t,xed_encoder_get_map(q));

switch(map) {
case XED_ILD_LEGACY_MAP0:
// FIXME: this case is also used to avoid emitting anything for VEX/EVEX/XOP maps
return;

case XED_ILD_LEGACY_MAP1:
value = 0x0F;
bits = 8;
break;

case XED_ILD_LEGACY_MAP2:
value = 0x380F; //need to convert big to little endian
bits = 16;
break;

case XED_ILD_LEGACY_MAP3:
value = 0x3A0F; //need to convert big to little endian
bits = 16;
break;
#if defined(XED_AMD_ENABLED)
case XED_ILD_AMD_3DNOW:
value = 0x0F0F;
bits = 16;
break;
#endif

default:
xed3_operand_set_error(q,XED_ERROR_GENERAL_ERROR);
return;

}
xed_encoder_request_emit_bytes(q,bits,value);
}

void xed_encoder_request_emit_bytes(xed_encoder_request_t* q,
const xed_uint8_t bits,
const xed_uint64_t value){
Expand Down

0 comments on commit a23e816

Please sign in to comment.