Skip to content

Commit

Permalink
fix 64b-mode XCHG with r8w/r8d/r8 as an operand.
Browse files Browse the repository at this point in the history
  * oddity of how NOP & XCHG are defined. If we have a REX.B on xchg
    with SRM=0, then it is not 'xchg eax,eax" (aka NOP), but "xchg
    r8d,eax" (or one of the other widths if 66 or REX.W) are supplied.

  * removed one unused argument from generated enc2 functions  for
    this flavor of xchg.

(cherry picked from commit 6f847f5ecb40ae0ebdbe90e68e7b699567538e19)
  • Loading branch information
mjcharne committed Nov 6, 2020
1 parent 7573e4b commit b1bf9cb
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 15 deletions.
1 change: 1 addition & 0 deletions datafiles/xed-isa.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7130,6 +7130,7 @@ ISA_SET : I86
PATTERN : 0b1001_0 SRM[rrr] SRM!=0
OPERANDS : REG0=GPRv_SB():rw REG1=OrAX():rw:IMPL

# This is strange. REG0 is r8w, r8d or r8 depending on the EOSZ. mode64
PATTERN : 0b1001_0 SRM[rrr] SRM=0 not_refining_f3 rexb_prefix
OPERANDS : REG0=GPRv_SB():rw REG1=OrAX():rw:IMPL
}
Expand Down
2 changes: 1 addition & 1 deletion include/private/xed-enc2-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static XED_INLINE xed_uint_t get_rm(xed_enc2_req_t* r) {
static XED_INLINE void set_srm(xed_enc2_req_t* r, xed_uint_t v) {
r->s.opcode_srm = v;
}
static XED_INLINE xed_uint_t get_opcode_srm(xed_enc2_req_t* r) {
static XED_INLINE xed_uint_t get_srm(xed_enc2_req_t* r) {
return r->s.opcode_srm;
}

Expand Down
58 changes: 44 additions & 14 deletions pysrc/enc2gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ def make_function_object(env, ii, fname, return_value='void', asz=None):
return fo


def make_opnd_signature(env, ii, using_width=None, broadcasting=False):
def make_opnd_signature(env, ii, using_width=None, broadcasting=False, special_xchg=False):
'''This is the heart of the naming conventions for the encode
functions. If using_width is present, it is used for GPRv and
GPRy operations to specify a width. '''
Expand All @@ -912,10 +912,17 @@ def _translate_rax_name(w):
rax_names = { 16: 'ax', 32:'eax', 64:'rax' }
osz = _translate_width_int(w)
return rax_names[osz]

def _translate_eax_name(w):
eax_names = { 16: 'ax', 32:'eax', 64:'eax' }
osz = _translate_width_int(w)
return eax_names[osz]

def _translate_r8_name(w):
# uppercase to try to differentiate r8 (generic 8b reg) from R8 64b reg
r8_names = { 16: 'R8W', 32:'R8D', 64:'R8' }
osz = _translate_width_int(w)
return r8_names[osz]

def _translate_width_int(w):
if w in [8,16,32,64]:
Expand Down Expand Up @@ -988,7 +995,10 @@ def _convert_to_osz(w):
elif op_gpr64(op):
s.append('r64') #FIXME something else
elif op_gprv(op):
s.append('r' + _translate_width(using_width))
if special_xchg:
s.append(_translate_r8_name(using_width))
else:
s.append('r' + _translate_width(using_width))
elif op_gprz(op):
s.append('r' + _translate_width_z(using_width))
elif op_gpry(op):
Expand Down Expand Up @@ -1092,19 +1102,39 @@ def create_legacy_one_scalable_gpr(env,ii,osz_values,oc2):
for osz in osz_values:
if env.mode != 64 and osz == 64:
continue

special_xchg = False
if ii.partial_opcode:
if ii.rm_required != 'unspecified':
if ii.iclass == 'XCHG':
if env.mode != 64:
continue
# This is a strange XCHG that takes r8w, r8d or r8
# depending on the EOSZ. REX.B is required & 64b mode obviously.
# And no register specifier is required.
special_xchg = True

opsig = make_opnd_signature(env,ii,osz)
opsig = make_opnd_signature(env, ii, osz, special_xchg=special_xchg)
fname = "{}_{}_{}".format(enc_fn_prefix,
ii.iclass.lower(),
opsig)

fo = make_function_object(env,ii,fname)
fo.add_comment("created by create_legacy_one_scalable_gpr")
if special_xchg:
fo.add_comment("special xchg using R8W/R8D/R8")
fo.add_arg(arg_request,'req')
fo.add_arg(arg_reg0, gprv_names[osz])

if not special_xchg:
fo.add_arg(arg_reg0, gprv_names[osz])
emit_required_legacy_prefixes(ii,fo)

rexw_forced = False
rex_forced = False

if special_xchg:
fo.add_code_eol('set_rexb(r,1)')
rex_forced = True


if env.mode == 64 and osz == 16:
if ii.eosz == 'osznot16':
Expand All @@ -1118,7 +1148,7 @@ def create_legacy_one_scalable_gpr(env,ii,osz_values,oc2):
warn("SKIPPING 64b version for: {} / {}".format(ii.iclass, ii.iform))
continue # skip 64b version for this instruction
fo.add_code_eol('set_rexw(r)')
rexw_forced = True
rex_forced = True
elif env.mode == 32 and osz == 16:
if ii.eosz == 'osznot16':
warn("SKIPPING 16b version for: {} / {}".format(ii.iclass, ii.iform))
Expand Down Expand Up @@ -1152,14 +1182,14 @@ def create_legacy_one_scalable_gpr(env,ii,osz_values,oc2):
ii.encoder_skipped = True
return
else:
# we have soem XCHG opcodes encoded as partia register
# we have some XCHG opcodes encoded as partial register
# instructions but have fixed RM fields.
fo.add_code_eol('set_rm(r,{})'.format(ii.rm_required))
fo.add_code_eol('set_srm(r,{})'.format(ii.rm_required))

#dump_fields(ii)
#die("SHOULD NOT HAVE A VALUE FOR PARTIAL OPCODES HERE {} / {}".format(ii.iclass, ii.iform))

emit_rex(env,fo,rexw_forced)
emit_rex(env, fo, rex_forced)
emit_required_legacy_map_escapes(ii,fo)

if ii.partial_opcode:
Expand Down Expand Up @@ -1782,9 +1812,9 @@ def cond_add_imm_args(ii,fo):
fo.add_arg(arg_imm8_2,'int8')


def emit_rex(env, fo, rexw_forced):
def emit_rex(env, fo, rex_forced):
if env.mode == 64:
if rexw_forced:
if rex_forced:
fo.add_code_eol('emit_rex(r)')
else:
fo.add_code_eol('emit_rex_if_needed(r)')
Expand Down Expand Up @@ -2410,7 +2440,7 @@ def create_legacy_gprv_immv(env,ii,imm=False):

def emit_partial_opcode_variable_srm(ii,fo):
opcode = "0x{:02X}".format(ii.opcode_base10)
fo.add_code_eol('emit(r,{} | get_opcode_srm(r))'.format(opcode),
fo.add_code_eol('emit(r,{} | get_srm(r))'.format(opcode),
'partial opcode, variable srm')

def emit_partial_opcode_fixed_srm(ii,fo):
Expand Down Expand Up @@ -3512,7 +3542,7 @@ def create_legacy_umonitor(env,ii):
fo.add_code_eol('set_mod(r,{})'.format(ii.mod_required))

emit_required_legacy_prefixes(ii,fo)
emit_rex(env,fo,rexw_forced=False)
emit_rex(env,fo,rex_forced=False)
emit_required_legacy_map_escapes(ii,fo)
emit_opcode(ii,fo)
emit_modrm(fo)
Expand Down Expand Up @@ -3570,7 +3600,7 @@ def create_legacy_ArAX_implicit(env,ii):
fo.add_code_eol('set_mod(r,{})'.format(ii.mod_required))

emit_required_legacy_prefixes(ii,fo)
#emit_rex(env,fo,rexw_forced=False)
#emit_rex(env,fo,rex_forced=False)
emit_required_legacy_map_escapes(ii,fo)
emit_opcode(ii,fo)
emit_modrm(fo)
Expand Down

0 comments on commit b1bf9cb

Please sign in to comment.