#-*- coding:utf-8 -*- from __future__ import print_function from builtins import range import re from future.utils import viewitems from miasm.core import utils from miasm.expression.expression import * from pyparsing import * from miasm.core.cpu import * from collections import defaultdict import miasm.arch.x86.regs as regs_module from miasm.arch.x86.regs import * from miasm.core.asm_ast import AstNode, AstInt, AstId, AstMem, AstOp from miasm.ir.ir import color_expr_html from miasm.core.utils import BRACKET_O, BRACKET_C log = logging.getLogger("x86_arch") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.WARN) conditional_branch = ["JO", "JNO", "JB", "JAE", "JZ", "JNZ", "JBE", "JA", "JS", "JNS", "JPE", "JNP", #"L", "NL", "NG", "G"] "JL", "JGE", "JLE", "JG", "JCXZ", "JECXZ", "JRCXZ"] unconditional_branch = ['JMP', 'JMPF'] f_isad = "AD" f_s08 = "S08" f_u08 = "U08" f_s16 = "S16" f_u16 = "U16" f_s32 = "S32" f_u32 = "U32" f_s64 = "S64" f_u64 = "U64" f_imm = 'IMM' f_imm2size = {f_s08: 8, f_s16: 16, f_s32: 32, f_s64: 64, f_u08: 8, f_u16: 16, f_u32: 32, f_u64: 64} size2gpregs = {8: gpregs08, 16: gpregs16, 32: gpregs32, 64: gpregs64} replace_regs64 = { AL: RAX[:8], CL: RCX[:8], DL: RDX[:8], BL: RBX[:8], AH: RAX[8:16], CH: RCX[8:16], DH: RDX[8:16], BH: RBX[8:16], SPL: RSP[0:8], BPL: RBP[0:8], SIL: RSI[0:8], DIL: RDI[0:8], R8B: R8[0:8], R9B: R9[0:8], R10B: R10[0:8], R11B: R11[0:8], R12B: R12[0:8], R13B: R13[0:8], R14B: R14[0:8], R15B: R15[0:8], AX: RAX[:16], CX: RCX[:16], DX: RDX[:16], BX: RBX[:16], SP: RSP[:16], BP: RBP[:16], SI: RSI[:16], DI: RDI[:16], R8W: R8[:16], R9W: R9[:16], R10W: R10[:16], R11W: R11[:16], R12W: R12[:16], R13W: R13[:16], R14W: R14[:16], R15W: R15[:16], EAX: RAX[:32], ECX: RCX[:32], EDX: RDX[:32], EBX: RBX[:32], ESP: RSP[:32], EBP: RBP[:32], ESI: RSI[:32], EDI: RDI[:32], R8D: R8[:32], R9D: R9[:32], R10D: R10[:32], R11D: R11[:32], R12D: R12[:32], R13D: R13[:32], R14D: R14[:32], R15D: R15[:32], IP: RIP[:16], EIP: RIP[:32], ExprId("ST", 64): float_st0, ExprId("ST(0)", 64): float_st0, ExprId("ST(1)", 64): float_st1, ExprId("ST(2)", 64): float_st2, ExprId("ST(3)", 64): float_st3, ExprId("ST(4)", 64): float_st4, ExprId("ST(5)", 64): float_st5, ExprId("ST(6)", 64): float_st6, ExprId("ST(7)", 64): float_st7, } replace_regs32 = { AL: EAX[:8], CL: ECX[:8], DL: EDX[:8], BL: EBX[:8], AH: EAX[8:16], CH: ECX[8:16], DH: EDX[8:16], BH: EBX[8:16], AX: EAX[:16], CX: ECX[:16], DX: EDX[:16], BX: EBX[:16], SP: ESP[:16], BP: EBP[:16], SI: ESI[:16], DI: EDI[:16], IP: EIP[:16], ExprId("ST", 64): float_st0, ExprId("ST(0)", 64): float_st0, ExprId("ST(1)", 64): float_st1, ExprId("ST(2)", 64): float_st2, ExprId("ST(3)", 64): float_st3, ExprId("ST(4)", 64): float_st4, ExprId("ST(5)", 64): float_st5, ExprId("ST(6)", 64): float_st6, ExprId("ST(7)", 64): float_st7, } replace_regs16 = { AL: AX[:8], CL: CX[:8], DL: DX[:8], BL: BX[:8], AH: AX[8:16], CH: CX[8:16], DH: DX[8:16], BH: BX[8:16], AX: AX[:16], CX: CX[:16], DX: DX[:16], BX: BX[:16], SP: SP[:16], BP: BP[:16], SI: SI[:16], DI: DI[:16], ExprId("ST", 64): float_st0, ExprId("ST(0)", 64): float_st0, ExprId("ST(1)", 64): float_st1, ExprId("ST(2)", 64): float_st2, ExprId("ST(3)", 64): float_st3, ExprId("ST(4)", 64): float_st4, ExprId("ST(5)", 64): float_st5, ExprId("ST(6)", 64): float_st6, ExprId("ST(7)", 64): float_st7, } replace_regs = {16: replace_regs16, 32: replace_regs32, 64: replace_regs64} segm2enc = {CS: 1, SS: 2, DS: 3, ES: 4, FS: 5, GS: 6} enc2segm = dict((value, key) for key, value in viewitems(segm2enc)) segm_info = reg_info_dct(enc2segm) enc2crx = { 0: cr0, 1: cr1, 2: cr2, 3: cr3, 4: cr4, 5: cr5, 6: cr6, 7: cr7, } crx_info = reg_info_dct(enc2crx) enc2drx = { 0: dr0, 1: dr1, 2: dr2, 3: dr3, 4: dr4, 5: dr5, 6: dr6, 7: dr7, } drx_info = reg_info_dct(enc2drx) # parser helper ########### PLUS = Suppress("+") MULT = Suppress("*") COLON = Suppress(":") LBRACK = Suppress("[") RBRACK = Suppress("]") gpreg = ( gpregs08.parser | gpregs08_64.parser | gpregs16.parser | gpregs32.parser | gpregs64.parser | gpregs_xmm.parser | gpregs_mm.parser | gpregs_ymm.parser | gpregs_bnd.parser ) def is_op_segm(expr): """Returns True if is ExprOp and op == 'segm'""" return expr.is_op('segm') def is_mem_segm(expr): """Returns True if is ExprMem and ptr is_op_segm""" return expr.is_mem() and is_op_segm(expr.ptr) def cb_deref_segmoff(tokens): assert len(tokens) == 2 return AstOp('segm', tokens[0], tokens[1]) def cb_deref_base_expr(tokens): tokens = tokens[0] assert isinstance(tokens, AstNode) addr = tokens return addr deref_mem_ad = (LBRACK + base_expr + RBRACK).setParseAction(cb_deref_base_expr) deref_ptr = (base_expr + COLON + base_expr).setParseAction(cb_deref_segmoff) PTR = Suppress('PTR') FAR = Suppress('FAR') BYTE = Literal('BYTE') WORD = Literal('WORD') DWORD = Literal('DWORD') QWORD = Literal('QWORD') TBYTE = Literal('TBYTE') XMMWORD = Literal('XMMWORD') YMMWORD = Literal('YMMWORD') MEMPREFIX2SIZE = {'BYTE': 8, 'WORD': 16, 'DWORD': 32, 'QWORD': 64, 'TBYTE': 80, 'XMMWORD': 128, 'YMMWORD': 256} SIZE2MEMPREFIX = dict((value, key) for key, value in viewitems(MEMPREFIX2SIZE)) def cb_deref_mem(tokens): if len(tokens) == 2: s, ptr = tokens assert isinstance(ptr, AstNode) return AstMem(ptr, MEMPREFIX2SIZE[s]) elif len(tokens) == 3: s, segm, ptr = tokens return AstMem(AstOp('segm', segm, ptr), MEMPREFIX2SIZE[s]) raise ValueError('len(tokens) > 3') mem_size = (BYTE | DWORD | QWORD | WORD | TBYTE | XMMWORD | YMMWORD) deref_mem = (mem_size + PTR + Optional((base_expr + COLON))+ deref_mem_ad).setParseAction(cb_deref_mem) rmarg = ( gpregs08.parser | gpregs08_64.parser | gpregs16.parser | gpregs32.parser | gpregs64.parser | gpregs_mm.parser | gpregs_xmm.parser | gpregs_bnd.parser | gpregs_ymm.parser ) rmarg |= deref_mem mem_far = FAR + deref_mem cl_or_imm = r08_ecx.parser cl_or_imm |= base_expr class x86_arg(m_arg): def asm_ast_to_expr(self, value, loc_db, size_hint=None, fixed_size=None): if size_hint is None: size_hint = self.parent.mode if fixed_size is None: fixed_size = set() if isinstance(value, AstId): if value.name in all_regs_ids_byname: reg = all_regs_ids_byname[value.name] fixed_size.add(reg.size) return reg if isinstance(value.name, ExprId): fixed_size.add(value.name.size) return value.name if value.name in MEMPREFIX2SIZE: return None if value.name in ["FAR"]: return None loc_key = loc_db.get_or_create_name_location(value.name) return ExprLoc(loc_key, size_hint) if isinstance(value, AstOp): # First pass to retrieve fixed_size if value.op == "segm": segm = self.asm_ast_to_expr(value.args[0], loc_db) ptr = self.asm_ast_to_expr(value.args[1], loc_db, None, fixed_size) return ExprOp('segm', segm, ptr) args = [self.asm_ast_to_expr(arg, loc_db, None, fixed_size) for arg in value.args] if len(fixed_size) == 0: # No fixed size pass elif len(fixed_size) == 1: # One fixed size, regen all size = list(fixed_size)[0] args = [self.asm_ast_to_expr(arg, loc_db, size, fixed_size) for arg in value.args] else: raise ValueError("Size conflict") if None in args: return None return ExprOp(value.op, *args) if isinstance(value, AstInt): if 1 << size_hint < value.value: size_hint *= 2 return ExprInt(value.value, size_hint) if isinstance(value, AstMem): fixed_size.add(value.size) ptr = self.asm_ast_to_expr(value.ptr, loc_db, None, set()) if ptr is None: return None return ExprMem(ptr, value.size) return None class r_al(reg_noarg, x86_arg): reg_info = r08_eax parser = reg_info.parser class r_ax(reg_noarg, x86_arg): reg_info = r16_eax parser = reg_info.parser class r_dx(reg_noarg, x86_arg): reg_info = r16_edx parser = reg_info.parser class r_eax(reg_noarg, x86_arg): reg_info = r32_eax parser = reg_info.parser class r_rax(reg_noarg, x86_arg): reg_info = r64_eax parser = reg_info.parser class r_cl(reg_noarg, x86_arg): reg_info = r08_ecx parser = reg_info.parser invmode = {16: 32, 32: 16} def opmode_prefix(mode): size, opmode, admode = mode if size in [16, 32]: if opmode: return invmode[size] else: return size elif size == 64: if opmode: return 16 else: return 32 raise NotImplementedError('not fully functional') def admode_prefix(mode): size, opmode, admode = mode if size in [16, 32]: if admode: return invmode[size] else: return size elif size == 64: return 64 raise NotImplementedError('not fully functional') def v_opmode_info(size, opmode, rex_w, stk): if size in [16, 32]: if opmode: return invmode[size] else: return size elif size == 64: # Rex has the maximum priority # Then opmode # Then stacker if rex_w == 1: return 64 elif opmode == 1: return 16 elif stk: return 64 else: return 32 def v_opmode(p): stk = hasattr(p, 'stk') return v_opmode_info(p.mode, p.opmode, p.rex_w.value, stk) def v_admode_info(size, admode): if size in [16, 32]: if admode: return invmode[size] else: return size elif size == 64: if admode == 1: return 32 return 64 def v_admode(p): return v_admode_info(p.mode, p.admode) def offsize(p): if p.opmode: return 16 else: return p.mode def get_prefix(s): g = re.search(r'(\S+)(\s+)', s) if not g: return None, s prefix, b = g.groups() return prefix, s[len(prefix) + len(b):] repeat_mn = ["INS", "OUTS", "MOVSB", "MOVSW", "MOVSD", "MOVSQ", "SCASB", "SCASW", "SCASD", "SCASQ", "LODSB", "LODSW", "LODSD", "LODSQ", "STOSB", "STOSW", "STOSD", "STOSQ", "CMPSB", "CMPSW", "CMPSD", "CMPSQ", ] class group(object): def __init__(self): self.value = None class additional_info(object): def __init__(self): self.except_on_instr = False self.g1 = group() self.g2 = group() self.vopmode = None self.stk = False self.v_opmode = None self.v_admode = None self.prefixed = b'' class instruction_x86(instruction): __slots__ = [] def __init__(self, *args, **kargs): super(instruction_x86, self).__init__(*args, **kargs) def v_opmode(self): return self.additional_info.v_opmode def v_admode(self): return self.additional_info.v_admode def dstflow(self): if self.name in conditional_branch + unconditional_branch: return True if self.name.startswith('LOOP'): return True return self.name in ['CALL'] def dstflow2label(self, loc_db): if self.additional_info.g1.value & 14 and self.name in repeat_mn: return expr = self.args[0] if not expr.is_int(): return addr = (int(expr) + int(self.offset)) & int(expr.mask) loc_key = loc_db.get_or_create_offset_location(addr) self.args[0] = ExprLoc(loc_key, expr.size) def breakflow(self): if self.name in conditional_branch + unconditional_branch: return True if self.name.startswith('LOOP'): return True if self.name.startswith('RET'): return True if self.name.startswith('INT'): return True if self.name.startswith('SYS'): return True return self.name in ['CALL', 'HLT', 'IRET', 'IRETD', 'IRETQ', 'ICEBP', 'UD2'] def splitflow(self): if self.name in conditional_branch: return True if self.name in unconditional_branch: return False if self.name.startswith('LOOP'): return True if self.name.startswith('INT'): return True if self.name.startswith('SYS'): return True return self.name in ['CALL'] def setdstflow(self, a): return def is_subcall(self): return self.name in ['CALL'] def getdstflow(self, loc_db): if self.additional_info.g1.value & 14 and self.name in repeat_mn: addr = int(self.offset) loc_key = loc_db.get_or_create_offset_location(addr) return [ExprLoc(loc_key, self.v_opmode())] return [self.args[0]] def get_symbol_size(self, symbol, loc_db): return self.mode def fixDstOffset(self): expr = self.args[0] if self.offset is None: raise ValueError('symbol not resolved %s' % l) if not isinstance(expr, ExprInt): log.warning('dynamic dst %r', expr) return self.args[0] = ExprInt(int(expr) - self.offset, self.mode) def get_info(self, c): self.additional_info.g1.value = c.g1.value self.additional_info.g2.value = c.g2.value self.additional_info.stk = hasattr(c, 'stk') self.additional_info.v_opmode = c.v_opmode() self.additional_info.v_admode = c.v_admode() self.additional_info.prefix = c.prefix self.additional_info.prefixed = getattr(c, "prefixed", b"") def __str__(self): return self.to_string() def to_string(self, loc_db=None): o = super(instruction_x86, self).to_string(loc_db) if self.additional_info.g1.value & 1: o = "LOCK %s" % o if self.additional_info.g1.value & 2: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF2": o = "REPNE %s" % o if self.additional_info.g1.value & 8: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF3": o = "REP %s" % o elif self.additional_info.g1.value & 4: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF3": o = "REPE %s" % o return o def to_html(self, loc_db=None): o = super(instruction_x86, self).to_html(loc_db) if self.additional_info.g1.value & 1: text = utils.set_html_text_color("LOCK", utils.COLOR_MNEMO) o = "%s %s" % (text, o) if self.additional_info.g1.value & 2: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF2": text = utils.set_html_text_color("REPNE", utils.COLOR_MNEMO) o = "%s %s" % (text, o) if self.additional_info.g1.value & 8: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF3": text = utils.set_html_text_color("REP", utils.COLOR_MNEMO) o = "%s %s" % (text, o) elif self.additional_info.g1.value & 4: if getattr(self.additional_info.prefixed, 'default', b"") != b"\xF3": text = utils.set_html_text_color("REPE", utils.COLOR_MNEMO) o = "%s %s" % (text, o) return o def get_args_expr(self): args = [] for a in self.args: a = a.replace_expr(replace_regs[self.mode]) args.append(a) return args @staticmethod def arg2str(expr, index=None, loc_db=None): if expr.is_id() or expr.is_int(): o = str(expr) elif expr.is_loc(): if loc_db is not None: o = loc_db.pretty_str(expr.loc_key) else: o = str(expr) elif ((isinstance(expr, ExprOp) and expr.op == 'far' and isinstance(expr.args[0], ExprMem)) or isinstance(expr, ExprMem)): if isinstance(expr, ExprOp): prefix, expr = "FAR ", expr.args[0] else: prefix = "" sz = SIZE2MEMPREFIX[expr.size] segm = "" if is_mem_segm(expr): segm = "%s:" % expr.ptr.args[0] expr = expr.ptr.args[1] else: expr = expr.ptr if isinstance(expr, ExprOp): s = str(expr).replace('(', '').replace(')', '') else: s = str(expr) o = prefix + sz + ' PTR ' + str(segm) + '[%s]' % s elif isinstance(expr, ExprOp) and expr.op == 'segm': o = "%s:%s" % (expr.args[0], expr.args[1]) else: raise ValueError('check this %r' % expr) return "%s" % o @staticmethod def arg2html(expr, index=None, loc_db=None): if expr.is_id() or expr.is_int() or expr.is_loc(): o = color_expr_html(expr, loc_db) elif ((isinstance(expr, ExprOp) and expr.op == 'far' and isinstance(expr.args[0], ExprMem)) or isinstance(expr, ExprMem)): if isinstance(expr, ExprOp): prefix, expr = "FAR ", expr.args[0] else: prefix = "" sz = SIZE2MEMPREFIX[expr.size] sz = '%s' % (utils.COLOR_MEM, sz) segm = "" if is_mem_segm(expr): segm = "%s:" % expr.ptr.args[0] expr = expr.ptr.args[1] else: expr = expr.ptr if isinstance(expr, ExprOp): s = color_expr_html(expr, loc_db)#.replace('(', '').replace(')', '') else: s = color_expr_html(expr, loc_db) o = prefix + sz + ' PTR ' + str(segm) + BRACKET_O + str(s) + BRACKET_C elif isinstance(expr, ExprOp) and expr.op == 'segm': o = "%s:%s" % ( color_expr_html(expr.args[0], loc_db), color_expr_html(expr.args[1], loc_db) ) else: raise ValueError('check this %r' % expr) return "%s" % o class mn_x86(cls_mn): name = "x86" prefix_op_size = False prefix_ad_size = False regs = regs_module all_mn = [] all_mn_mode = defaultdict(list) all_mn_name = defaultdict(list) all_mn_inst = defaultdict(list) bintree = {} num = 0 delayslot = 0 pc = {16: IP, 32: EIP, 64: RIP} sp = {16: SP, 32: ESP, 64: RSP} instruction = instruction_x86 max_instruction_len = 15 @classmethod def getpc(cls, attrib): return cls.pc[attrib] @classmethod def getsp(cls, attrib): return cls.sp[attrib] def v_opmode(self): if hasattr(self, 'stk'): stk = 1 else: stk = 0 return v_opmode_info(self.mode, self.opmode, self.rex_w.value, stk) def v_admode(self): size, opmode, admode = self.mode, self.opmode, self.admode if size in [16, 32]: if admode: return invmode[size] else: return size elif size == 64: if admode == 1: return 32 return 64 def additional_info(self): info = additional_info() info.g1.value = self.g1.value info.g2.value = self.g2.value info.stk = hasattr(self, 'stk') info.v_opmode = self.v_opmode() info.prefixed = b"" if hasattr(self, 'prefixed'): info.prefixed = self.prefixed.default return info @classmethod def check_mnemo(cls, fields): pass @classmethod def getmn(cls, name): return name.upper() @classmethod def mod_fields(cls, fields): prefix = [d_g1, d_g2, d_rex_p, d_rex_w, d_rex_r, d_rex_x, d_rex_b, d_vex, d_vex_l, d_vex_p, d_vex_v, d_vex_m] return prefix + fields @classmethod def gen_modes(cls, subcls, name, bases, dct, fields): dct['mode'] = None return [(subcls, name, bases, dct, fields)] @classmethod def fromstring(cls, text, loc_db, mode): pref = 0 prefix, new_s = get_prefix(text) if prefix == "LOCK": pref |= 1 text = new_s elif prefix == "REPNE" or prefix == "REPNZ": pref |= 2 text = new_s elif prefix == "REPE" or prefix == "REPZ": pref |= 4 text = new_s elif prefix == "REP": pref |= 8 text = new_s c = super(mn_x86, cls).fromstring(text, loc_db, mode) c.additional_info.g1.value = pref return c @classmethod def pre_dis(cls, v, mode, offset): offset_o = offset pre_dis_info = {'opmode': 0, 'admode': 0, 'g1': 0, 'g2': 0, 'rex_p': 0, 'rex_w': 0, 'rex_r': 0, 'rex_x': 0, 'rex_b': 0, 'vex_l': 0, 'vex_p': 0, 'vex_v': 0, 'vex_m': 0, 'vex' : 0, 'prefix': b"", 'prefixed': b"", } while True: c = v.getbytes(offset) if c == b'\x66': pre_dis_info['opmode'] = 1 elif c == b'\x67': pre_dis_info['admode'] = 1 elif c == b'\xf0': pre_dis_info['g1'] = 1 elif c == b'\xf2': pre_dis_info['g1'] = 2 elif c == b'\xf3': pre_dis_info['g1'] = 12 elif c == b'\x2e': pre_dis_info['g2'] = 1 elif c == b'\x36': pre_dis_info['g2'] = 2 elif c == b'\x3e': pre_dis_info['g2'] = 3 elif c == b'\x26': pre_dis_info['g2'] = 4 elif c == b'\x64': pre_dis_info['g2'] = 5 elif c == b'\x65': pre_dis_info['g2'] = 6 else: break pre_dis_info['prefix'] += c offset += 1 vex3_prefix = b'\xc4' vex2_prefix = b'\xc5' rex_prefixes = b'@ABCDEFGHIJKLMNO' if mode == 64 and c in rex_prefixes: while c in rex_prefixes: # multiple REX prefixes case - use last REX prefix x = ord(c) offset += 1 c = v.getbytes(offset) pre_dis_info['rex_p'] = 1 pre_dis_info['rex_w'] = (x >> 3) & 1 pre_dis_info['rex_r'] = (x >> 2) & 1 pre_dis_info['rex_x'] = (x >> 1) & 1 pre_dis_info['rex_b'] = (x >> 0) & 1 elif mode == 64 and c == vex3_prefix: offset += 1 c = ord(v.getbytes(offset)) pre_dis_info['vex'] = 1 pre_dis_info['rex_r'] = ((c >> 7) ^ 1) & 1 pre_dis_info['rex_x'] = ((c >> 6) ^ 1) & 1 pre_dis_info['rex_b'] = ((c >> 5) ^ 1) & 1 pre_dis_info['vex_m'] = (c & int('0b11111', 2)) offset += 1 c = ord(v.getbytes(offset)) pre_dis_info['rex_w'] = (c >> 7) & 1 pre_dis_info['vex_v'] = ((c >> 3) ^ 15) & 15 pre_dis_info['vex_l'] = (c >> 2) & 1 pre_dis_info['vex_p'] = c & int('0b11', 2) offset += 1 if pre_dis_info['vex_p'] == 1: pre_dis_info['opmode'] = 1 elif pre_dis_info['vex_p'] == 3: pre_dis_info['g1'] = 2 elif pre_dis_info['vex_p'] == 2: pre_dis_info['g1'] = 12 elif mode == 64 and c == vex2_prefix and v.getlen() > 2: offset += 1 c = ord(v.getbytes(offset)) pre_dis_info['vex'] = 1 pre_dis_info['rex_r'] = ((c >> 7) ^ 1) & 1 pre_dis_info['rex_x'] = 0 pre_dis_info['rex_b'] = 0 pre_dis_info['rex_w'] = 0 pre_dis_info['vex_m'] = 1 pre_dis_info['vex_l'] = (c >> 2) & 1 pre_dis_info['vex_p'] = c & int('0b11', 2) offset += 1 if pre_dis_info['vex_p'] == 1: pre_dis_info['opmode'] = 1 pre_dis_info['prefix'] += b'\x66' elif pre_dis_info['vex_p'] == 3: pre_dis_info['g1'] = 2 pre_dis_info['prefix'] += b'\xf2' elif pre_dis_info['vex_p'] == 2: pre_dis_info['g1'] = 12 pre_dis_info['prefix'] += b'\xf3' elif pre_dis_info.get('g1', None) == 12 and c in [b'\xa6', b'\xa7', b'\xae', b'\xaf']: pre_dis_info['g1'] = 4 return pre_dis_info, v, mode, offset, offset - offset_o @classmethod def get_cls_instance(cls, cc, mode, infos=None): for opmode in [0, 1]: for admode in [0, 1]: c = cc() c.init_class() c.reset_class() c.add_pre_dis_info() c.dup_info(infos) c.mode = mode c.opmode = opmode c.admode = admode if not hasattr(c, 'stk') and hasattr(c, "fopmode") and c.fopmode.mode == 64: c.rex_w.value = 1 yield c def post_dis(self): if self.g2.value: for a in self.args: if not isinstance(a.expr, ExprMem): continue m = a.expr a.expr = ExprMem( ExprOp('segm', enc2segm[self.g2.value], m.ptr), m.size) return self def dup_info(self, infos): if infos is not None: self.g1.value = infos.g1.value self.g2.value = infos.g2.value def reset_class(self): super(mn_x86, self).reset_class() if hasattr(self, "opmode"): del(self.opmode) if hasattr(self, "admode"): del(self.admode) def add_pre_dis_info(self, pre_dis_info=None): if pre_dis_info is None: return True if hasattr(self, "prefixed") and self.prefixed.default == b"\x66": pre_dis_info['opmode'] = 0 self.opmode = pre_dis_info['opmode'] self.admode = pre_dis_info['admode'] if hasattr(self, 'no_xmm_pref') and\ pre_dis_info['prefix'] and\ pre_dis_info['prefix'][-1] in b'\x66\xf2\xf3': return False if (hasattr(self, "prefixed") and not pre_dis_info['prefix'].endswith(self.prefixed.default)): return False if (self.rex_w.value is not None and self.rex_w.value != pre_dis_info['rex_w']): return False else: self.rex_w.value = pre_dis_info['rex_w'] self.rex_r.value = pre_dis_info['rex_r'] self.rex_b.value = pre_dis_info['rex_b'] self.rex_x.value = pre_dis_info['rex_x'] self.rex_p.value = pre_dis_info['rex_p'] self.vex.value = pre_dis_info['vex'] self.vex_l.value = pre_dis_info['vex_l'] self.vex_p.value = pre_dis_info['vex_p'] self.vex_v.value = pre_dis_info['vex_v'] self.vex_m.value = pre_dis_info['vex_m'] if hasattr(self, 'no_rex') and\ (self.rex_r.value or self.rex_b.value or self.rex_x.value or self.rex_p.value): return False if self.vex.value == 0 and (hasattr(self, 'pref_0f') or hasattr(self, 'pref_0f38') or hasattr(self, 'pref_0f3a')): return False if hasattr(self, 'no_rep') and b'\xf3' in pre_dis_info['prefix']: return False if self.vex_m.value == 1 and not hasattr(self, 'pref_0f'): return False if self.vex_m.value == 2 and not hasattr(self, 'pref_0f38'): return False if self.vex_m.value == 3 and not hasattr(self, 'pref_0f3a'): return False self.g1.value = pre_dis_info['g1'] self.g2.value = pre_dis_info['g2'] self.prefix = pre_dis_info['prefix'] return True def post_asm(self, v): return v def gen_prefix(self): v = b"" rex = 0x40 if self.g1.value is None: self.g1.value = 0 if self.g2.value is None: self.g2.value = 0 if self.rex_w.value: rex |= 0x8 if self.rex_r.value: rex |= 0x4 if self.rex_x.value: rex |= 0x2 if self.rex_b.value: rex |= 0x1 if (rex != 0x40 and not self.vex.value) or self.rex_p.value == 1: v = utils.int_to_byte(rex) + v if hasattr(self, 'no_rex'): return None vex_byte1 = 0xc4 vex_byte2 = 0x00 vex_byte3 = 0x00 m_prefix = [field.fname for field in self.fields_order if 'pref_0f' in field.fname] if m_prefix: if m_prefix[0] == 'pref_0f': vex_byte2 |= 0x01 elif m_prefix[0] == 'pref_0f38': vex_byte2 |= 0x02 elif m_prefix[0] == 'pref_0f3a': vex_byte2 |= 0x03 # TODO: L and p if m_prefix and m_prefix[0] == 'pref_0f' and not self.rex_w.value and not self.rex_b.value and ((hasattr(self, 'mod') and self.mod.value == 3) or not self.rex_x.value): # VEX2 print("test") vex_version = 2 vex_byte1 = 0x00 vex_byte2 = 0xc5 if not hasattr(self, 'reg') or not self.rex_r.value: vex_byte3 |= 0x80 else: vex_version = 3 if not hasattr(self, 'reg') or not self.rex_r.value: vex_byte2 |= 0x80 if (hasattr(self, 'mod') and self.mod.value == 3) or not self.rex_x.value: vex_byte2 |= 0x40 if not self.rex_b.value: vex_byte2 |= 0x20 if self.rex_w.value: vex_byte3 |= 0x80 if self.vex.value == 1: vex_byte3 |= ((15 - self.vex_v.value) << 3) vex = (vex_byte1 << 16) | (vex_byte2 << 8) | vex_byte3 v = vex.to_bytes(vex_version, 'big') + v if hasattr(self, 'prefixed'): v = self.prefixed.default + v if self.g1.value & 1: v = b"\xf0" + v if self.g1.value & 2: if hasattr(self, 'no_xmm_pref'): return None v = b"\xf2" + v if self.g1.value & 12: if hasattr(self, 'no_xmm_pref'): return None v = b"\xf3" + v if self.g2.value: v = { 1: b'\x2e', 2: b'\x36', 3: b'\x3e', 4: b'\x26', 5: b'\x64', 6: b'\x65' }[self.g2.value] + v # mode prefix if hasattr(self, "admode") and self.admode: v = b"\x67" + v if hasattr(self, "opmode") and self.opmode: if hasattr(self, 'no_xmm_pref'): return None v = b"\x66" + v return v def encodefields(self, decoded): v = super(mn_x86, self).encodefields(decoded) prefix = self.gen_prefix() if prefix is None: return None return prefix + v def getnextflow(self, loc_db): raise NotImplementedError('not fully functional') def ir_pre_instruction(self): return [ExprAssign(mRIP[self.mode], ExprInt(self.offset + self.l, mRIP[self.mode].size))] @classmethod def filter_asm_candidates(cls, instr, candidates): cand_same_mode = [] cand_diff_mode = [] out = [] for c, v in candidates: if (hasattr(c, 'no_xmm_pref') and (c.g1.value & 2 or c.g1.value & 4 or c.g1.value & 8 or c.opmode)): continue if hasattr(c, "fopmode") and v_opmode(c) != c.fopmode.mode: continue if hasattr(c, "fadmode") and v_admode(c) != c.fadmode.mode: continue # relative dstflow must not have opmode set # (assign IP instead of EIP for instance) if (instr.dstflow() and instr.name not in ["JCXZ", "JECXZ", "JRCXZ"] and len(instr.args) == 1 and isinstance(instr.args[0], ExprInt) and c.opmode): continue out.append((c, v)) candidates = out for c, v in candidates: if v_opmode(c) == instr.mode: cand_same_mode += v for c, v in candidates: if v_opmode(c) != instr.mode: cand_diff_mode += v cand_same_mode.sort(key=len) cand_diff_mode.sort(key=len) return cand_same_mode + cand_diff_mode class bs_modname_size(bs_divert): prio = 1 def divert(self, i, candidates): out = [] for candidate in candidates: cls, name, bases, dct, fields = candidate fopmode = opmode_prefix( (dct['mode'], dct['opmode'], dct['admode'])) mode = dct['mode'] size, opmode, admode = dct['mode'], dct['opmode'], dct['admode'] # no mode64 exinstance in name means no 64bit version of mnemo if mode == 64: if mode in self.args['name']: nfields = fields[:] f, i = getfieldindexby_name(nfields, 'rex_w') f = bs("1", l=0, cls=(bs_fbit,), fname="rex_w") osize = v_opmode_info(size, opmode, 1, 0) nfields[i] = f nfields = nfields[:-1] ndct = dict(dct) if osize in self.args['name']: ndct['name'] = self.args['name'][osize] out.append((cls, ndct['name'], bases, ndct, nfields)) nfields = fields[:] nfields = nfields[:-1] f, i = getfieldindexby_name(nfields, 'rex_w') f = bs("0", l=0, cls=(bs_fbit,), fname="rex_w") osize = v_opmode_info(size, opmode, 0, 0) nfields[i] = f ndct = dict(dct) if osize in self.args['name']: ndct['name'] = self.args['name'][osize] out.append((cls, ndct['name'], bases, ndct, nfields)) else: l = opmode_prefix((dct['mode'], dct['opmode'], dct['admode'])) osize = v_opmode_info(size, opmode, None, 0) nfields = fields[:-1] ndct = dict(dct) if osize in self.args['name']: ndct['name'] = self.args['name'][osize] out.append((cls, ndct['name'], bases, ndct, nfields)) return out class bs_modname_jecx(bs_divert): prio = 1 def divert(self, i, candidates): out = [] for candidate in candidates: cls, name, bases, dct, fields = candidate fopmode = opmode_prefix( (dct['mode'], dct['opmode'], dct['admode'])) mode = dct['mode'] size, opmode, admode = dct['mode'], dct['opmode'], dct['admode'] nfields = fields[:] nfields = nfields[:-1] args = dict(self.args) ndct = dict(dct) if mode == 64: if admode: ndct['name'] = "JECXZ" else: ndct['name'] = "JRCXZ" elif mode == 32: if admode: ndct['name'] = "JCXZ" else: ndct['name'] = "JECXZ" elif mode == 16: if admode: ndct['name'] = "JECXZ" else: ndct['name'] = "JCXZ" else: raise ValueError('unhandled mode') out.append((cls, ndct['name'], bases, ndct, nfields)) return out class bs_modname_mode(bs_divert): prio = 1 def divert(self, i, candidates): out = [] for candidate in candidates: cls, name, bases, dct, fields = candidate fopmode = opmode_prefix( (dct['mode'], dct['opmode'], dct['admode'])) size, opmode, admode = dct['mode'], dct['opmode'], dct['admode'] mode = dct['mode'] l = opmode_prefix((dct['mode'], dct['opmode'], dct['admode'])) osize = v_opmode_info(size, opmode, None, 0) nfields = fields[:-1] args = dict(self.args) ndct = dict(dct) if mode == 64 or osize == 32: ndct['name'] = self.args['name'][mode] else: ndct['name'] = self.args['name'][16] out.append((cls, ndct['name'], bases, ndct, nfields)) return out class x86_imm(imm_noarg): parser = base_expr def decodeval(self, v): return swap_uint(self.l, v) def encodeval(self, v): return swap_uint(self.l, v) class x86_imm_fix_08(imm_noarg): parser = base_expr intsize = 8 intmask = (1 << intsize) - 1 def decodeval(self, v): return self.ival def encode(self): v = self.expr2int(self.expr) if v != self.ival: return False self.value = 0 return True class x86_08(x86_imm): intsize = 8 intmask = (1 << intsize) - 1 class x86_16(x86_imm): intsize = 16 intmask = (1 << intsize) - 1 class x86_32(x86_imm): intsize = 32 intmask = (1 << intsize) - 1 class x86_64(x86_imm): intsize = 64 intmask = (1 << intsize) - 1 class x86_08_ne(x86_imm): intsize = 8 intmask = (1 << intsize) - 1 def encode(self): return True def decode(self, v): v = swap_uint(self.l, v) p = self.parent admode = p.v_admode() value = sign_ext(v, self.intsize, admode) self.expr = ExprInt(value, admode) return True class x86_16_ne(x86_08_ne): intsize = 16 intmask = (1 << intsize) - 1 class x86_32_ne(x86_08_ne): intsize = 32 intmask = (1 << intsize) - 1 class x86_64_ne(x86_08_ne): intsize = 64 intmask = (1 << intsize) - 1 class x86_s08to16(x86_imm): in_size = 8 out_size = 16 def myexpr(self, x): return ExprInt(x, 16) def int2expr(self, v): return self.myexpr(v) def expr2int(self, e): if not isinstance(e, ExprInt): return None v = int(e) if v & ~((1 << self.l) - 1) != 0: return None return v def decode(self, v): v = v & self.lmask v = self.decodeval(v) if self.parent.v_opmode() == 64: self.expr = ExprInt(sign_ext(v, self.in_size, 64), 64) else: if (1 << (self.l - 1)) & v: v = sign_ext(v, self.l, self.out_size) self.expr = self.myexpr(v) return True def encode(self): if not isinstance(self.expr, ExprInt): return False v = int(self.expr) opmode = self.parent.v_opmode() out_size = self.out_size if opmode != self.out_size: if opmode == 32 and self.out_size == 64: out_size = opmode if v == sign_ext( int(v & ((1 << self.in_size) - 1)), self.in_size, out_size): pass else: # test with rex_w self.parent.rex_w.value = 1 opmode = self.parent.v_opmode() out_size = opmode if (v != sign_ext( int(v & ((1 << self.in_size) - 1)), self.in_size, out_size)): return False if v != sign_ext( int(v & ((1 << self.in_size) - 1)), self.in_size, out_size): return False v = self.encodeval(v) self.value = (v & 0xffffffff) & self.lmask return True def decodeval(self, v): return swap_uint(self.l, v) def encodeval(self, v): return swap_sint(self.l, v) class x86_s08to32(x86_s08to16): in_size = 8 out_size = 32 def myexpr(self, x): return ExprInt(x, 32) def decode(self, v): v = v & self.lmask v = self.decodeval(v) if self.parent.rex_w.value == 1: v = ExprInt(sign_ext(v, self.in_size, 64), 64) else: v = ExprInt(sign_ext(v, self.in_size, 32), 32) self.expr = v return True class x86_s08to64(x86_s08to32): in_size = 8 out_size = 64 def myexpr(self, x): return ExprInt(x, 64) class x86_s32to64(x86_s08to32): in_size = 32 out_size = 64 def myexpr(self, x): return ExprInt(x, 64) class bs_eax(x86_arg): reg_info = r_eax_all rindex = 0 parser = reg_info.parser def decode(self, v): p = self.parent expr = None if hasattr(p, 'w8') and p.w8.value == 0: expr = regs08_expr[self.rindex] else: expr = size2gpregs[p.v_opmode()].expr[self.rindex] self.expr = expr return True def encode(self): self.value = 0 p = self.parent expr = self.expr osize = p.v_opmode() if hasattr(p, 'w8'): if p.w8.value is None: # XXX TODO: priority in w8 erase? if expr.size == 8: p.w8.value = 0 else: p.w8.value = 1 if hasattr(p, 'w8') and p.w8.value == 0: return expr == regs08_expr[self.rindex] elif p.mode in [16, 32]: return expr == size2gpregs[osize].expr[self.rindex] elif p.mode == 64: if expr == size2gpregs[64].expr[self.rindex]: p.rex_w.value = 1 return True elif expr == size2gpregs[osize].expr[self.rindex]: return True return False return False class bs_seg(x86_arg): reg_info = r_eax_all rindex = 0 parser = reg_info.parser def decode(self, v): self.expr = self.reg_info.expr[0] return True def encode(self): self.value = 0 return self.expr == self.reg_info.expr[0] class bs_edx(bs_eax): reg_info = r_edx_all rindex = 2 parser = reg_info.parser class bs_st(bs_eax): reg_info = r_st_all rindex = 0 parser = reg_info.parser class bs_cs(bs_seg): reg_info = r_cs_all rindex = 0 parser = reg_info.parser class bs_ds(bs_seg): reg_info = r_ds_all rindex = 0 parser = reg_info.parser class bs_es(bs_seg): reg_info = r_es_all rindex = 0 parser = reg_info.parser class bs_ss(bs_seg): reg_info = r_ss_all rindex = 0 parser = reg_info.parser class bs_fs(bs_seg): reg_info = r_fs_all rindex = 0 parser = reg_info.parser class bs_gs(bs_seg): reg_info = r_gs_all rindex = 0 parser = reg_info.parser class x86_reg_st(reg_noarg, x86_arg): reg_info = r_st_all parser = reg_info.parser class bs_sib_scale(bs_divert): bsname = "sib_scale" def divert(self, i, candidates): out = [] done = False for cls, name, bases, dct, fields in candidates: if (not (admode_prefix( (dct['mode'], dct['opmode'], dct['admode'])) != 16 and 'rm' in dct and dct['rm'] == 0b100 and 'mod' in dct and dct['mod'] != 0b11)): ndct = dict(dct) nfields = fields[:] nfields[i] = None ndct[self.args['fname']] = None out.append((cls, ndct['name'], bases, ndct, nfields)) continue nfields = fields[:] args = dict(self.args) ndct = dict(dct) f = bs(**args) nfields[i] = f ndct[self.args['fname']] = None out.append((cls, ndct['name'], bases, ndct, nfields)) return out class bs_sib_index(bs_sib_scale): pass class bs_sib_base(bs_sib_scale): pass class bs_disp(bs_divert): def divert(self, i, candidates): out = [] done = False for cls, name, bases, dct, fields in candidates: ndct = dict(dct) nfields = fields[:] if (admode_prefix( (dct['mode'], dct['opmode'], dct['admode'])) == 16): if 'mod' in dct and dct['mod'] == 0b00 and \ 'rm' in dct and dct['rm'] == 0b110: nfields[i] = bs( l=16, cls=(x86_16_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue elif 'mod' in dct and dct['mod'] == 0b01: nfields[i] = bs( l=8, cls=(x86_08_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue elif 'mod' in dct and dct['mod'] == 0b10: nfields[i] = bs( l=16, cls=(x86_16_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue else: if 'mod' in dct and dct['mod'] == 0b00 and \ 'rm' in dct and dct['rm'] == 0b101: nfields[i] = bs( l=32, cls=(x86_32_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue elif 'mod' in dct and dct['mod'] == 0b01: nfields[i] = bs( l=8, cls=(x86_08_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue elif 'mod' in dct and dct['mod'] == 0b10: nfields[i] = bs( l=32, cls=(x86_32_ne,), fname=self.args['fname']) ndct[self.args['fname']] = True out.append((cls, ndct['name'], bases, ndct, nfields)) continue nfields[i] = None ndct[self.args['fname']] = None out.append((cls, ndct['name'], bases, ndct, nfields)) return out def getmodrm(c): return (c >> 6) & 3, (c >> 3) & 7, c & 7 def setmodrm(mod, re, rm): return ((mod & 3) << 6) | ((re & 7) << 3) | (rm & 7) def sib(c): return modrm(c) db_afs_64 = [] sib_64_s08_ebp = [] def gen_modrm_form(): global db_afs_64, sib_64_s08_ebp ebp = 5 sib_s08_ebp = [{f_isad: True} for i in range(0x100)] sib_u32_ebp = [{f_isad: True} for i in range(0x100)] sib_u32 = [{f_isad: True} for i in range(0x100)] sib_u64 = [] for rex_x in range(2): o = [] for rex_b in range(2): x = [{f_isad: True} for i in range(0x100)] o.append(x) sib_u64.append(o) sib_u64_ebp = [] for rex_x in range(2): o = [] for rex_b in range(2): x = [{f_isad: True} for i in range(0x100)] o.append(x) sib_u64_ebp.append(o) sib_64_s08_ebp = [] for rex_x in range(2): o = [] for rex_b in range(2): x = [{f_isad: True} for i in range(0x100)] o.append(x) sib_64_s08_ebp.append(o) for sib_rez in [sib_s08_ebp, sib_u32_ebp, sib_u32, sib_64_s08_ebp, sib_u64_ebp, sib_u64, ]: for index in range(0x100): ss, i, b = getmodrm(index) if b == 0b101: if sib_rez == sib_s08_ebp: sib_rez[index][f_imm] = f_s08 sib_rez[index][ebp] = 1 elif sib_rez == sib_u32_ebp: sib_rez[index][f_imm] = f_u32 sib_rez[index][ebp] = 1 elif sib_rez == sib_u32: sib_rez[index][f_imm] = f_u32 elif sib_rez == sib_u64_ebp: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][f_imm] = f_u32 sib_rez[rex_x][rex_b][index][ebp + 8 * rex_b] = 1 elif sib_rez == sib_u64: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][f_imm] = f_u32 elif sib_rez == sib_64_s08_ebp: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][f_imm] = f_s08 sib_rez[rex_x][rex_b][index][ebp + 8 * rex_b] = 1 else: if sib_rez == sib_s08_ebp: sib_rez[index][b] = 1 sib_rez[index][f_imm] = f_s08 elif sib_rez == sib_u32_ebp: sib_rez[index][b] = 1 sib_rez[index][f_imm] = f_u32 elif sib_rez == sib_u32: sib_rez[index][b] = 1 elif sib_rez == sib_u64_ebp: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][b + 8 * rex_b] = 1 sib_rez[rex_x][rex_b][index][f_imm] = f_u32 elif sib_rez == sib_u64: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][b + 8 * rex_b] = 1 elif sib_rez == sib_64_s08_ebp: for rex_b in range(2): for rex_x in range(2): sib_rez[rex_x][rex_b][index][f_imm] = f_s08 sib_rez[rex_x][rex_b][index][b + 8 * rex_b] = 1 if i == 0b100 and sib_rez in [sib_s08_ebp, sib_u32_ebp, sib_u32]: continue if sib_rez in [sib_s08_ebp, sib_u32_ebp, sib_u32]: tmp = i if not tmp in sib_rez[index]: sib_rez[index][tmp] = 0 # 1 << ss sib_rez[index][tmp] += 1 << ss else: for rex_b in range(2): for rex_x in range(2): tmp = i + 8 * rex_x if i == 0b100 and rex_x == 0: continue if not tmp in sib_rez[rex_x][rex_b][index]: sib_rez[rex_x][rex_b][index][tmp] = 0 # 1 << ss sib_rez[rex_x][rex_b][index][tmp] += 1 << ss # 32bit db_afs_32 = [None for i in range(0x100)] for i in range(0x100): index = i mod, re, rm = getmodrm(i) if mod == 0b00: if rm == 0b100: db_afs_32[index] = sib_u32 elif rm == 0b101: db_afs_32[index] = {f_isad: True, f_imm: f_u32} else: db_afs_32[index] = {f_isad: True, rm: 1} elif mod == 0b01: if rm == 0b100: db_afs_32[index] = sib_s08_ebp continue tmp = {f_isad: True, rm: 1, f_imm: f_s08} db_afs_32[index] = tmp elif mod == 0b10: if rm == 0b100: db_afs_32[index] = sib_u32_ebp else: db_afs_32[index] = {f_isad: True, rm: 1, f_imm: f_u32} elif mod == 0b11: db_afs_32[index] = {f_isad: False, rm: 1} # 64bit db_afs_64 = [None for i in range(0x400)] for i in range(0x400): index = i rex_x = (index >> 9) & 1 rex_b = (index >> 8) & 1 mod, re, rm = getmodrm(i & 0xff) if mod == 0b00: if rm == 0b100: db_afs_64[i] = sib_u64[rex_x][rex_b] elif rm == 0b101: db_afs_64[i] = {f_isad: True, f_imm: f_u32, 16: 1} else: db_afs_64[i] = {f_isad: True, rm + 8 * rex_b: 1} elif mod == 0b01: if rm == 0b100: db_afs_64[i] = sib_64_s08_ebp[rex_x][rex_b] continue tmp = {f_isad: True, rm + 8 * rex_b: 1, f_imm: f_s08} db_afs_64[i] = tmp elif mod == 0b10: if rm == 0b100: db_afs_64[i] = sib_u64_ebp[rex_x][rex_b] else: db_afs_64[i] = {f_isad: True, rm + 8 * rex_b: 1, f_imm: f_u32} elif mod == 0b11: db_afs_64[i] = {f_isad: False, rm + 8 * rex_b: 1} # 16bit db_afs_16 = [None for i in range(0x100)] _si = 6 _di = 7 _bx = 3 _bp = 5 for i in range(0x100): index = i mod, re, rm = getmodrm(i) if mod == 0b00: if rm == 0b100: db_afs_16[index] = {f_isad: True, _si: 1} elif rm == 0b101: db_afs_16[index] = {f_isad: True, _di: 1} elif rm == 0b110: db_afs_16[index] = { f_isad: True, f_imm: f_u16} # {f_isad:True,_bp:1} elif rm == 0b111: db_afs_16[index] = {f_isad: True, _bx: 1} else: db_afs_16[index] = {f_isad: True, [_si, _di][rm % 2]: 1, [_bx, _bp][(rm >> 1) % 2]: 1} elif mod in [0b01, 0b10]: if mod == 0b01: my_imm = f_s08 else: my_imm = f_u16 if rm == 0b100: db_afs_16[index] = {f_isad: True, _si: 1, f_imm: my_imm} elif rm == 0b101: db_afs_16[index] = {f_isad: True, _di: 1, f_imm: my_imm} elif rm == 0b110: db_afs_16[index] = {f_isad: True, _bp: 1, f_imm: my_imm} elif rm == 0b111: db_afs_16[index] = {f_isad: True, _bx: 1, f_imm: my_imm} else: db_afs_16[index] = {f_isad: True, [_si, _di][rm % 2]: 1, [_bx, _bp][(rm >> 1) % 2]: 1, f_imm: my_imm} elif mod == 0b11: db_afs_16[index] = {f_isad: False, rm: 1} byte2modrm = {} byte2modrm[16] = db_afs_16 byte2modrm[32] = db_afs_32 byte2modrm[64] = db_afs_64 modrm2byte = {16: defaultdict(list), 32: defaultdict(list), 64: defaultdict(list), } for size, db_afs in viewitems(byte2modrm): for i, modrm in enumerate(db_afs): if not isinstance(modrm, list): # We only need sort for determinism modrm = tuple(sorted(viewitems(modrm), key=str)) modrm2byte[size][modrm].append(i) continue for j, modrm_f in enumerate(modrm): # We only need sort for determinism modrm_f = tuple(sorted(viewitems(modrm_f), key=str)) modrm2byte[size][modrm_f].append((i, j)) return byte2modrm, modrm2byte byte2modrm, modrm2byte = gen_modrm_form() # ret is modr; ret is displacement def exprfindmod(e, o=None): if o is None: o = {} if isinstance(e, ExprInt): return e if isinstance(e, ExprId): i = size2gpregs[e.size].expr.index(e) o[i] = 1 return None elif isinstance(e, ExprOp): out = None if e.op == '+': for a in e.args: r = exprfindmod(a, o) if out and r: raise ValueError('multiple displacement!') out = r return out elif e.op == "*": mul = int(e.args[1]) a = e.args[0] i = size2gpregs[a.size].expr.index(a) o[i] = mul else: raise ValueError('bad op') return None def test_addr_size(ptr, size): if isinstance(ptr, ExprInt): return int(ptr) < (1 << size) else: return ptr.size == size SIZE2XMMREG = {64:gpregs_mm, 128:gpregs_xmm} SIZE2BNDREG = {64:gpregs_mm, 128:gpregs_bnd} def parse_mem(expr, parent, w8, sx=0, xmm=0, mm=0, bnd=0): dct_expr = {} opmode = parent.v_opmode() if is_mem_segm(expr) and expr.ptr.args[0].is_int(): return None, None, False if is_mem_segm(expr): segm = expr.ptr.args[0] ptr = expr.ptr.args[1] else: segm = None ptr = expr.ptr dct_expr[f_isad] = True ad_size = ptr.size admode = parent.v_admode() if not test_addr_size(ptr, admode): return None, None, False if (w8 == 1 and expr.size != opmode and not sx and not (hasattr(parent, 'sd') or hasattr(parent, 'wd'))): return None, None, False if hasattr(parent, 'wd'): if expr.size == 16: parent.wd.value = 1 elif expr.size == 32: pass else: return None, None, False if (not isinstance(ptr, ExprInt) and parent.mode == 64 and ptr.size == 32 and parent.admode != 1): return None, None, False dct_expr = {f_isad: True} disp = exprfindmod(ptr, dct_expr) out = [] if disp is None: # add 0 disp disp = ExprInt(0, 32) if disp is not None: for signed, encoding, cast_size in [(True, f_s08, 8), (True, f_s16, 16), (True, f_s32, 32), (False, f_u08, 8), (False, f_u16, 16), (False, f_u32, 32)]: value = ExprInt(int(disp), cast_size) if admode < value.size: if signed: if int(disp) != sign_ext(int(value), admode, disp.size): continue else: if int(disp) != int(value): continue else: if int(disp) != sign_ext(int(value), value.size, admode): continue x1 = dict(dct_expr) x1[f_imm] = (encoding, value) out.append(x1) else: out = [dct_expr] return out, segm, True def expr2modrm(expr, parent, w8, sx=0, xmm=0, mm=0, bnd=0): dct_expr = {f_isad : False} if mm or xmm or bnd: if mm and expr.size != 64: return None, None, False elif xmm and expr.size != 128: return None, None, False elif bnd and expr.size != 128: return None, None, False if isinstance(expr, ExprId): if bnd: size2reg = SIZE2BNDREG else: size2reg = SIZE2XMMREG selreg = size2reg[expr.size] if not expr in selreg.expr: return None, None, False i = selreg.expr.index(expr) dct_expr[i] = 1 return [dct_expr], None, True else: return parse_mem(expr, parent, w8, sx, xmm, mm) elif expr.size == 64 and expr not in gpregs_mm.expr: if hasattr(parent, 'sd'): parent.sd.value = 1 elif hasattr(parent, 'wd'): pass elif hasattr(parent, 'stk'): pass else: parent.rex_w.value = 1 opmode = parent.v_opmode() if sx == 1: opmode = 16 if sx == 2: opmode = 32 if expr.size == 8 and w8 != 0: return None, None, False if w8 == 0 and expr.size != 8: return None, None, False if not isinstance(expr, ExprMem): dct_expr[f_isad] = False if xmm: if expr in gpregs_xmm.expr: i = gpregs_xmm.expr.index(expr) dct_expr[i] = 1 return [dct_expr], None, True else: return None, None, False if bnd: if expr in gpregs_bnd.expr: i = gpregs_bnd.expr.index(expr) dct_expr[i] = 1 return [dct_expr], None, True else: return None, None, False if mm: if expr in gpregs_mm.expr: i = gpregs_mm.expr.index(expr) dct_expr[i] = 1 return [dct_expr], None, True else: return None, None, False if w8 == 0: if parent.mode == 64 and expr in gpregs08_64.expr: r = gpregs08_64 parent.rex_p.value = 1 else: parent.rex_p.value = 0 parent.rex_x.value = 0 r = size2gpregs[8] if not expr in r.expr: return None, None, False i = r.expr.index(expr) dct_expr[i] = 1 return [dct_expr], None, True if opmode != expr.size: return None, None, False if not expr in size2gpregs[opmode].expr: return None, None, False i = size2gpregs[opmode].expr.index(expr) if i > 7: if parent.mode != 64: return None, None, False dct_expr[i] = 1 return [dct_expr], None, True return parse_mem(expr, parent, w8, sx, xmm, mm, bnd) def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0, bnd=0, ymm=0): o = [] if not modrm[f_isad]: modrm_k = [key for key, value in viewitems(modrm) if value == 1] if len(modrm_k) != 1: raise ValueError('strange reg encoding %r' % modrm) modrm_k = modrm_k[0] if w8 == 0: opmode = 8 elif sx == 1: opmode = 16 elif sx == 2: opmode = 32 else: opmode = parent.v_opmode() if xmm: expr = gpregs_xmm.expr[modrm_k] elif mm: expr = gpregs_mm.expr[modrm_k] elif bnd: expr = gpregs_bnd.expr[modrm_k] elif ymm: expr = gpregs_ymm.expr[modrm_k] elif opmode == 8 and (parent.v_opmode() == 64 or parent.rex_p.value == 1): expr = gpregs08_64.expr[modrm_k] else: expr = size2gpregs[opmode].expr[modrm_k] return expr admode = parent.v_admode() opmode = parent.v_opmode() for modrm_k, scale in viewitems(modrm): if isinstance(modrm_k, int): expr = size2gpregs[admode].expr[modrm_k] if scale != 1: expr = ExprInt(scale, admode) * expr o.append(expr) if f_imm in modrm: if parent.disp.value is None: return None o.append(ExprInt(int(parent.disp.expr), admode)) if len(o) == 1: expr = o[0] else: expr = ExprOp('+', *o) if w8 == 0: opmode = 8 elif sx == 1: opmode = 16 elif sx == 2: opmode = 32 if xmm: opmode = 128 elif mm: opmode = 64 elif bnd: opmode = 128 elif ymm: opmode = 256 expr = ExprMem(expr, size=opmode) return expr class x86_rm_arg(x86_arg): parser = rmarg def fromstring(self, text, loc_db, parser_result=None): start, stop = super(x86_rm_arg, self).fromstring(text, loc_db, parser_result) p = self.parent if start is None: return None, None return start, stop def get_modrm(self): p = self.parent admode = p.v_admode() if not admode in [16, 32, 64]: raise ValueError('strange admode %r', admode) v = setmodrm(p.mod.value, 0, p.rm.value) v |= p.rex_b.value << 8 v |= p.rex_x.value << 9 if p.mode == 64: # XXXx to check admode = 64 xx = byte2modrm[admode][v] if isinstance(xx, list): if not p.sib_scale: return False v = setmodrm(p.sib_scale.value, p.sib_index.value, p.sib_base.value) xx = xx[v] return xx def decode(self, v): p = self.parent xx = self.get_modrm() self.expr = modrm2expr(xx, p, 1) return self.expr is not None def gen_cand(self, v_cand, admode): if not admode in modrm2byte: # XXX TODO: 64bit return if not v_cand: return p = self.parent o_rex_x = p.rex_x.value o_rex_b = p.rex_b.value # add candidate without 0 imm new_v_cand = [] moddd = False for v in v_cand: new_v_cand.append(v) if f_imm in v and int(v[f_imm][1]) == 0: v = dict(v) del(v[f_imm]) new_v_cand.append(v) moddd = True v_cand = new_v_cand out_c = [] for v in v_cand: disp = None # patch value in modrm if f_imm in v: size, disp = v[f_imm] disp = int(disp) v[f_imm] = size vo = v # We only need sort for determinism v = tuple(sorted(viewitems(v), key=str)) admode = 64 if p.mode == 64 else admode if not v in modrm2byte[admode]: continue xx = modrm2byte[admode][v] # default case for x in xx: if type(x) == tuple: modrm, sib = x else: modrm = x sib = None # 16 bit cannot have sib if sib is not None and admode == 16: continue rex = modrm >> 8 # 0# XXX HACK REM temporary REX modrm>>8 if rex and admode != 64: continue p.rex_x.value = (rex >> 1) & 1 p.rex_b.value = rex & 1 if o_rex_x is not None and p.rex_x.value != o_rex_x: continue if o_rex_b is not None and p.rex_b.value != o_rex_b: continue mod, re, rm = getmodrm(modrm) # check re on parent if hasattr(p, 'reg') and re != p.reg.value: continue if sib is not None: s_scale, s_index, s_base = getmodrm(sib) else: s_scale, s_index, s_base = None, None, None p.mod.value = mod p.rm.value = rm p.sib_scale.value = s_scale p.sib_index.value = s_index p.sib_base.value = s_base p.disp.value = disp if disp is not None: p.disp.l = f_imm2size[vo[f_imm]] yield True return def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent admode = p.v_admode() mode = self.expr.size v_cand, segm, ok = expr2modrm(self.expr, p, 1) if segm: p.g2.value = segm2enc[segm] for x in self.gen_cand(v_cand, admode): yield x class x86_rm_mem(x86_rm_arg): def fromstring(self, text, loc_db, parser_result=None): self.expr = None start, stop = super(x86_rm_mem, self).fromstring(text, loc_db, parser_result) if not isinstance(self.expr, ExprMem): return None, None return start, stop class x86_rm_mem_far(x86_rm_arg): parser = mem_far def fromstring(self, text, loc_db, parser_result=None): self.expr = None start, stop = super(x86_rm_mem_far, self).fromstring(text, loc_db, parser_result) if not isinstance(self.expr, ExprMem): return None, None self.expr = ExprOp('far', self.expr) return start, stop def decode(self, v): ret = super(x86_rm_mem_far, self).decode(v) if not ret: return ret if isinstance(self.expr, m2_expr.ExprMem): self.expr = ExprOp('far', self.expr) return True def encode(self): if not (isinstance(self.expr, m2_expr.ExprOp) and self.expr.op == 'far'): return expr = self.expr.args[0] if isinstance(expr, ExprInt): return p = self.parent admode = p.v_admode() mode = expr.size v_cand, segm, ok = expr2modrm(expr, p, 1) if segm: p.g2.value = segm2enc[segm] for x in self.gen_cand(v_cand, admode): yield x class x86_rm_w8(x86_rm_arg): def decode(self, v): p = self.parent xx = self.get_modrm() self.expr = modrm2expr(xx, p, p.w8.value) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent if p.w8.value is None: if self.expr.size == 8: p.w8.value = 0 else: p.w8.value = 1 v_cand, segm, ok = expr2modrm(self.expr, p, p.w8.value) if segm: p.g2.value = segm2enc[segm] for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_sx(x86_rm_arg): def decode(self, v): p = self.parent xx = self.get_modrm() self.expr = modrm2expr(xx, p, p.w8.value, 1) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent if p.w8.value is None: if self.expr.size == 8: p.w8.value = 0 else: p.w8.value = 1 v_cand, segm, ok = expr2modrm(self.expr, p, p.w8.value, 1) if segm: p.g2.value = segm2enc[segm] for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_sxd(x86_rm_arg): def decode(self, v): p = self.parent xx = self.get_modrm() self.expr = modrm2expr(xx, p, 1, 2) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent v_cand, segm, ok = expr2modrm(self.expr, p, 1, 2) if segm: p.g2.value = segm2enc[segm] for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_sd(x86_rm_arg): out_size = 64 def get_s_value(self): return self.parent.sd.value def set_s_value(self, value): self.parent.sd.value = value def decode(self, v): p = self.parent xx = self.get_modrm() expr = modrm2expr(xx, p, 1) if not isinstance(expr, ExprMem): return False if self.get_s_value() == 0: expr = ExprMem(expr.ptr, 32) else: expr = ExprMem(expr.ptr, self.out_size) self.expr = expr return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent if not self.expr.size in [32, 64]: return self.set_s_value(0) v_cand, segm, ok = expr2modrm(self.expr, p, 1) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_wd(x86_rm_sd): out_size = 16 def get_s_value(self): return self.parent.wd.value def set_s_value(self, value): self.parent.wd.value = value def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent p.wd.value = 0 v_cand, segm, ok = expr2modrm(self.expr, p, 1) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_08(x86_rm_arg): msize = 8 def decode(self, v): p = self.parent xx = self.get_modrm() expr = modrm2expr(xx, p, 0) if not isinstance(expr, ExprMem): self.expr = expr return True self.expr = ExprMem(expr.ptr, self.msize) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent v_cand, segm, ok = expr2modrm(self.expr, p, 0, 0, 0, 0) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_reg_m08(x86_rm_arg): msize = 8 def decode(self, v): ret = x86_rm_arg.decode(self, v) if not ret: return ret if not isinstance(self.expr, ExprMem): return True self.expr = ExprMem(self.expr.ptr, self.msize) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent if isinstance(self.expr, ExprMem): expr = ExprMem(self.expr.ptr, 32) else: expr = self.expr v_cand, segm, ok = expr2modrm(expr, p, 1, 0, 0, 0) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_reg_m16(x86_rm_reg_m08): msize = 16 class x86_rm_m64(x86_rm_arg): msize = 64 def decode(self, v): p = self.parent xx = self.get_modrm() expr = modrm2expr(xx, p, 1) if not isinstance(expr, ExprMem): return False self.expr = ExprMem(expr.ptr, self.msize) return self.expr is not None def encode(self): if isinstance(self.expr, ExprInt): return p = self.parent v_cand, segm, ok = expr2modrm(self.expr, p, 0, 0, 0, 1) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_m80(x86_rm_m64): msize = 80 def encode(self): if isinstance(self.expr, ExprInt): return if not isinstance(self.expr, ExprMem) or self.expr.size != self.msize: return p = self.parent mode = p.mode if mode == 64: mode = 32 self.expr = ExprMem(self.expr.ptr, mode) v_cand, segm, ok = expr2modrm(self.expr, p, 1) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_m08(x86_rm_arg): msize = 8 def decode(self, v): p = self.parent xx = self.get_modrm() self.expr = modrm2expr(xx, p, 0) return self.expr is not None def encode(self): if self.expr.size != 8: return p = self.parent mode = p.mode v_cand, segm, ok = expr2modrm(self.expr, p, 0) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_m16(x86_rm_m80): msize = 16 class x86_rm_mm(x86_rm_m80): msize = 64 is_mm = True is_xmm = False is_bnd = False is_ymm = False def decode(self, v): p = self.parent xx = self.get_modrm() expr = modrm2expr(xx, p, 0, 0, self.is_xmm, self.is_mm, self.is_bnd, self.is_ymm) if isinstance(expr, ExprMem): if self.msize is None: return False if expr.size != self.msize: expr = ExprMem(expr.ptr, self.msize) self.expr = expr return True def encode(self): expr = self.expr if isinstance(expr, ExprInt): return if isinstance(expr, ExprMem) and expr.size != self.msize: return p = self.parent mode = p.mode if mode == 64: mode = 32 if isinstance(expr, ExprMem): if self.is_xmm: expr = ExprMem(expr.ptr, 128) elif self.is_mm: expr = ExprMem(expr.ptr, 64) v_cand, segm, ok = expr2modrm(expr, p, 0, 0, self.is_xmm, self.is_mm, self.is_bnd) for x in self.gen_cand(v_cand, p.v_admode()): yield x class x86_rm_mm_m64(x86_rm_mm): msize = 64 is_mm = True is_xmm = False class x86_rm_xmm(x86_rm_mm): msize = 128 is_mm = False is_xmm = True class x86_rm_xmm_m32(x86_rm_mm): msize = 32 is_mm = False is_xmm = True class x86_rm_xmm_m64(x86_rm_mm): msize = 64 is_mm = False is_xmm = True class x86_rm_xmm_m128(x86_rm_mm): msize = 128 is_mm = False is_xmm = True class x86_rm_ymm(x86_rm_mm): msize = 256 is_mm = False is_xmm = False is_ymm = True class x86_rm_xmm_reg(x86_rm_mm): msize = None is_mm = False is_xmm = True class x86_rm_mm_reg(x86_rm_mm): msize = None is_mm = True is_xmm = False class x86_rm_bnd(x86_rm_mm): msize = 128 is_mm = False is_xmm = False is_bnd = True class x86_rm_bnd_reg(x86_rm_mm): msize = None is_mm = False is_xmm = False is_bnd = True class x86_rm_bnd_m64(x86_rm_mm): msize = 64 is_mm = False is_xmm = False is_bnd = True class x86_rm_bnd_m128(x86_rm_mm): msize = 128 is_mm = False is_xmm = False is_bnd = True class x86_rm_reg_noarg(object): prio = default_prio + 1 parser = gpreg def fromstring(self, text, loc_db, parser_result=None): if not hasattr(self.parent, 'sx') and hasattr(self.parent, "w8"): self.parent.w8.value = 1 if parser_result: result, start, stop = parser_result[self.parser] if result == [None]: return None, None self.expr = result if self.expr.size == 8: if hasattr(self.parent, 'sx') or not hasattr(self.parent, 'w8'): return None, None self.parent.w8.value = 0 return start, stop try: result, start, stop = next(self.parser.scanString(text)) except StopIteration: return None, None expr = self.asm_ast_to_expr(result[0], loc_db) if expr is None: return None, None self.expr = expr if self.expr.size == 0: if hasattr(self.parent, 'sx') or not hasattr(self.parent, 'w8'): return None, None self.parent.w8.value = 0 return start, stop def getrexsize(self): return self.parent.rex_r.value def setrexsize(self, v): self.parent.rex_r.value = v def decode(self, v): v = v & self.lmask p = self.parent opmode = p.v_opmode() if not hasattr(p, 'sx') and (hasattr(p, 'w8') and p.w8.value == 0): opmode = 8 r = size2gpregs[opmode] if p.mode == 64 and self.getrexsize(): v |= 0x8 if p.v_opmode() == 64 or p.rex_p.value == 1: if not hasattr(p, 'sx') and (hasattr(p, 'w8') and p.w8.value == 0): r = gpregs08_64 elif p.rex_r.value == 1: v |= 8 self.expr = r.expr[v] return True def encode(self): if not isinstance(self.expr, ExprId): return False if self.expr in gpregs64.expr and not hasattr(self.parent, 'stk'): self.parent.rex_w.value = 1 opmode = self.parent.v_opmode() if not hasattr(self.parent, 'sx') and hasattr(self.parent, 'w8'): self.parent.w8.value = 1 if self.expr.size == 8: if hasattr(self.parent, 'sx') or not hasattr(self.parent, 'w8'): return False self.parent.w8.value = 0 opmode = 8 r = size2gpregs[opmode] if self.expr in r.expr: i = r.expr.index(self.expr) elif (opmode == 8 and self.parent.mode == 64 and self.expr in gpregs08_64.expr): i = gpregs08_64.expr.index(self.expr) self.parent.rex_p.value = 1 else: log.debug("cannot encode reg %r", self.expr) return False if self.parent.v_opmode() == 64: if i > 7: self.setrexsize(1) i -= 8 elif self.parent.mode == 64 and i > 7: i -= 8 self.setrexsize(1) self.value = i return True class x86_rm_reg_mm(x86_rm_reg_noarg, x86_arg): selreg = gpregs_mm def decode(self, v): if self.parent.mode == 64 and self.getrexsize(): v |= 0x8 self.expr = self.selreg.expr[v] return True def encode(self): if not isinstance(self.expr, ExprId): return False if self.expr not in self.selreg.expr: return False i = self.selreg.expr.index(self.expr) if self.parent.mode == 64 and i > 7: i -= 8 self.setrexsize(1) self.value = i return True class x86_rm_reg_xmm(x86_rm_reg_mm): selreg = gpregs_xmm class x86_rm_reg_ymm(x86_rm_reg_mm): selreg = gpregs_ymm class x86_rm_reg_bnd(x86_rm_reg_mm): selreg = gpregs_bnd class x86_rm_reg(x86_rm_reg_noarg, x86_arg): pass class x86_reg(x86_rm_reg): def getrexsize(self): return self.parent.rex_b.value def setrexsize(self, v): self.parent.rex_b.value = v class x86_vex_reg(x86_rm_reg): # self.lmask = 15 def decode(self, v): p = self.parent self.expr = size2gpregs[v_opmode(p)].expr[p.vex_v.value] return self.expr is not None def encode(self): opmode = self.parent.mode size = self.expr.size if opmode == 64 and size == 64: self.parent.rex_w.value = 1 else: self.parent.rex_w.value = 0 r = size2gpregs[size] if self.expr in r.expr: i = r.expr.index(self.expr) self.parent.vex_v.value = i self.parent.vex.value = 1 return True class x86_reg_modrm(x86_rm_reg): def getrexsize(self): return self.parent.rex_r.value def setrexsize(self, v): self.parent.rex_r.value = v class x86_reg_noarg(x86_rm_reg_noarg): def getrexsize(self): return self.parent.rex_b.value def setrexsize(self, v): self.parent.rex_b.value = v class x86_rm_segm(reg_noarg, x86_arg): prio = default_prio + 1 reg_info = segmreg parser = reg_info.parser class x86_rm_cr(reg_noarg, x86_arg): prio = default_prio + 1 reg_info = crregs parser = reg_info.parser class x86_rm_dr(reg_noarg, x86_arg): prio = default_prio + 1 reg_info = drregs parser = reg_info.parser class x86_rm_flt(reg_noarg, x86_arg): prio = default_prio + 1 reg_info = fltregs parser = reg_info.parser class bs_fbit(bsi): def decode(self, v): # value already decoded in pre_dis_info return True class bs_cl1(bsi, x86_arg): parser = cl_or_imm def decode(self, v): if v == 1: self.expr = regs08_expr[1] else: self.expr = ExprInt(1, 8) return True def encode(self): if self.expr == regs08_expr[1]: self.value = 1 elif isinstance(self.expr, ExprInt) and int(self.expr) == 1: self.value = 0 else: return False return True def sib_cond(cls, mode, v): if admode_prefix((mode, v["opmode"], v["admode"])) == 16: return None if v['mod'] == 0b11: return None elif v['rm'] == 0b100: return cls.ll else: return None return v['rm'] == 0b100 class bs_cond_scale(bs_cond): # cond must return field len ll = 2 @classmethod def flen(cls, mode, v): return sib_cond(cls, mode, v) def encode(self): if self.value is None: self.value = 0 self.l = 0 return True return super(bs_cond_scale, self).encode() def decode(self, v): self.value = v return True class bs_cond_index(bs_cond_scale): ll = 3 @classmethod def flen(cls, mode, v): return sib_cond(cls, mode, v) class bs_cond_disp(bs_cond): # cond must return field len @classmethod def flen(cls, mode, v): if admode_prefix((mode, v['opmode'], v['admode'])) == 16: if v['mod'] == 0b00: if v['rm'] == 0b110: return 16 else: return None elif v['mod'] == 0b01: return 8 elif v['mod'] == 0b10: return 16 return None # 32, 64 if 'sib_base' in v and v['sib_base'] == 0b101: if v['mod'] == 0b00: return 32 elif v['mod'] == 0b01: return 8 elif v['mod'] == 0b10: return 32 else: return None if v['mod'] == 0b00: if v['rm'] == 0b101: return 32 else: return None elif v['mod'] == 0b01: return 8 elif v['mod'] == 0b10: return 32 else: return None def encode(self): if self.value is None: self.value = 0 self.l = 0 return True self.value = swap_uint(self.l, self.value) return True def decode(self, v): admode = self.parent.v_admode() v = swap_uint(self.l, v) self.value = v v = sign_ext(v, self.l, admode) v = ExprInt(v, admode) self.expr = v return True class bs_cond_imm(bs_cond_scale, x86_arg): parser = base_expr max_size = 32 def fromstring(self, text, loc_db, parser_result=None): if parser_result: expr, start, stop = parser_result[self.parser] else: try: expr, start, stop = next(self.parser.scanString(text)) except StopIteration: expr = None self.expr = expr if len(self.parent.args) > 1: l = self.parent.args[0].expr.size else: l = self.parent.v_opmode() if isinstance(self.expr, ExprInt): v = int(self.expr) mask = ((1 << l) - 1) self.expr = ExprInt(v & mask, l) if self.expr is None: log.debug('cannot fromstring int %r', text) return None, None return start, stop @classmethod def flen(cls, mode, v): if 'w8' not in v or v['w8'] == 1: if 'se' in v and v['se'] == 1: return 8 else: osize = v_opmode_info(mode, v['opmode'], v['rex_w'], 0) osize = min(osize, cls.max_size) return osize return 8 def getmaxlen(self): return 32 def encode(self): if not isinstance(self.expr, ExprInt): return arg0_expr = self.parent.args[0].expr self.parent.rex_w.value = 0 # special case for push if len(self.parent.args) == 1: v = int(self.expr) l = self.parent.v_opmode() l = min(l, self.max_size) self.l = l mask = ((1 << self.l) - 1) if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True return # assume 2 args; use first arg to guess op size if arg0_expr.size == 64: self.parent.rex_w.value = 1 l = self.parent.v_opmode() v = int(self.expr) if arg0_expr.size == 8: if not hasattr(self.parent, 'w8'): return self.parent.w8.value = 0 l = 8 if hasattr(self.parent, 'se'): self.parent.se.value = 0 elif hasattr(self.parent, 'se'): if hasattr(self.parent, 'w8'): self.parent.w8.value = 1 # try to generate signed extended version if v == sign_ext(v & 0xFF, 8, arg0_expr.size): self.parent.se.value = 1 self.l = 8 self.value = v & 0xFF yield True self.parent.se.value = 0 else: if hasattr(self.parent, 'w8'): self.parent.w8.value = 1 if l == 64: self.l = self.getmaxlen() else: self.l = l mask = ((1 << self.l) - 1) if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): opmode = self.parent.v_opmode() v = swap_uint(self.l, v) self.value = v l_out = opmode if hasattr(self.parent, 'w8') and self.parent.w8.value == 0: l_out = 8 v = sign_ext(v, self.l, l_out) self.expr = ExprInt(v, l_out) return True class bs_cond_imm64(bs_cond_imm): max_size = 64 def getmaxlen(self): return 64 @classmethod def flen(cls, mode, v): if 'w8' not in v or v['w8'] == 1: if 'se' in v and v['se'] == 1: return 8 else: osize = v_opmode_info(mode, v['opmode'], v['rex_w'], 0) return osize else: return 8 class bs_rel_off(bs_cond_imm): parser = base_expr def fromstring(self, text, loc_db, parser_result=None): if parser_result: expr, start, stop = parser_result[self.parser] else: try: expr, start, stop = next(self.parser.scanString(text)) except StopIteration: expr = None self.expr = expr l = self.parent.mode if isinstance(self.expr, ExprInt): v = int(self.expr) mask = ((1 << l) - 1) self.expr = ExprInt(v & mask, l) return start, stop @classmethod def flen(cls, mode, v): osize = v_opmode_info(mode, v['opmode'], v['rex_w'], 0) if osize == 16: return 16 else: return 32 def encode(self): if not isinstance(self.expr, ExprInt): return arg0_expr = self.parent.args[0].expr if self.l == 0: l = self.parent.v_opmode() self.l = l l = offsize(self.parent) prefix = self.parent.gen_prefix() parent_len = len(prefix) * 8 + self.parent.l + self.l assert(parent_len % 8 == 0) v = int(self.expr) - parent_len // 8 if prefix is None: return mask = ((1 << self.l) - 1) if self.l > l: return if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): v = swap_uint(self.l, v) size = offsize(self.parent) v = sign_ext(v, self.l, size) v += self.parent.l self.expr = ExprInt(v, size) return True class bs_s08(bs_rel_off): parser = base_expr @classmethod def flen(cls, mode, v): return 8 def encode(self): if not isinstance(self.expr, ExprInt): return arg0_expr = self.parent.args[0].expr if self.l != 0: l = self.l else: l = self.parent.v_opmode() self.l = l l = offsize(self.parent) v = int(self.expr) mask = ((1 << self.l) - 1) if self.l > l: return if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): v = swap_uint(self.l, v) size = offsize(self.parent) v = sign_ext(v, self.l, size) self.expr = ExprInt(v, size) return True class bs_rel_off08(bs_rel_off): @classmethod def flen(cls, mode, v): return 8 class bs_moff(bsi): @classmethod def flen(cls, mode, v): osize = v_opmode_info(mode, v['opmode'], v['rex_w'], 0) if osize == 16: return 16 else: return 32 def encode(self): if not hasattr(self.parent, "mseg"): return m = self.parent.mseg.expr if not (isinstance(m, ExprOp) and m.op == 'segm'): return if not isinstance(m.args[1], ExprInt): return l = self.parent.v_opmode() if l == 16: self.l = 16 else: self.l = 32 v = int(m.args[1]) mask = ((1 << self.l) - 1) if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): opmode = self.parent.v_opmode() if opmode == 64: return False v = swap_uint(self.l, v) self.value = v v = sign_ext(v, self.l, opmode) self.expr = ExprInt(v, opmode) return True class bs_movoff(x86_arg): parser = deref_mem def fromstring(self, text, loc_db, parser_result=None): if parser_result: e, start, stop = parser_result[self.parser] if e is None: return None, None if not isinstance(e, ExprMem): return None, None self.expr = e if self.expr is None: return None, None return start, stop try: v, start, stop = next(self.parser.scanString(text)) except StopIteration: return None, None if not isinstance(e, ExprMem): return None, None self.expr = v[0] if self.expr is None: log.debug('cannot fromstring int %r', text) return None, None return start, stop @classmethod def flen(cls, mode, v): if mode == 64: if v['admode']: return 32 else: return 64 asize = v_admode_info(mode, v['admode']) return asize def encode(self): p = self.parent if not isinstance(self.expr, ExprMem) or not isinstance(self.expr.ptr, ExprInt): return self.l = p.v_admode() v = int(self.expr.ptr) mask = ((1 << self.l) - 1) if v != mask & v: return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): if self.parent.mode == 64: if self.parent.admode == 1: l = 32 else: l = 64 else: l = self.parent.v_admode() v = swap_uint(self.l, v) self.value = v v = sign_ext(v, self.l, l) v = ExprInt(v, l) size = self.parent.v_opmode() if self.parent.w8.value == 0: size = 8 self.expr = ExprMem(v, size) return True class bs_msegoff(x86_arg): parser = deref_ptr def fromstring(self, text, loc_db, parser_result=None): if parser_result: e, start, stop = parser_result[self.parser] if e is None: return None, None self.expr = e if self.expr is None: return None, None return start, stop try: v, start, stop = next(self.parser.scanString(text)) except StopIteration: return None, None self.expr = v[0] if self.expr is None: log.debug('cannot fromstring int %r', text) return None, None return start, stop def encode(self): if not (isinstance(self.expr, ExprOp) and self.expr.op == 'segm'): return if not isinstance(self.expr.args[0], ExprInt): return if not isinstance(self.expr.args[1], ExprInt): return l = self.parent.v_opmode() v = int(self.expr.args[0]) mask = ((1 << self.l) - 1) if v != sign_ext(v & mask, self.l, l): return self.value = swap_uint(self.l, v & ((1 << self.l) - 1)) yield True def decode(self, v): opmode = self.parent.v_opmode() v = swap_uint(self.l, v) self.value = v v = ExprInt(v, 16) self.expr = ExprOp('segm', v, self.parent.off.expr) return True d_rex_p = bs(l=0, cls=(bs_fbit,), fname="rex_p") d_rex_w = bs(l=0, cls=(bs_fbit,), fname="rex_w") d_rex_r = bs(l=0, cls=(bs_fbit,), fname="rex_r") d_rex_x = bs(l=0, cls=(bs_fbit,), fname="rex_x") d_rex_b = bs(l=0, cls=(bs_fbit,), fname="rex_b") d_vex = bs(l=0, cls=(bs_fbit,), fname="vex") d_vex_l = bs(l=0, cls=(bs_fbit,), fname="vex_l") d_vex_p = bs(l=0, cls=(bs_fbit,), fname="vex_p") d_vex_v = bs(l=0, cls=(bs_fbit,), fname="vex_v") d_vex_m = bs(l=0, cls=(bs_fbit,), fname="vex_m") pref_0f = bs(l=0, fname="pref_0f") pref_0f38 = bs(l=0, fname="pref_0f38") pref_0f3a = bs(l=0, fname="pref_0f3a") d_g1 = bs(l=0, cls=(bs_fbit,), fname="g1") d_g2 = bs(l=0, cls=(bs_fbit,), fname="g2") d_cl1 = bs(l=1, cls=(bs_cl1,), fname="cl1") w8 = bs(l=1, fname="w8") se = bs(l=1, fname="se") sx = bs(l=0, fname="sx") sxd = bs(l=0, fname="sx") xmmreg = bs(l=0, fname="xmmreg") mmreg = bs(l=0, fname="mmreg") pref_f2 = bs(l=0, fname="prefixed", default=b"\xf2") pref_f3 = bs(l=0, fname="prefixed", default=b"\xf3") pref_66 = bs(l=0, fname="prefixed", default=b"\x66") no_xmm_pref = bs(l=0, fname="no_xmm_pref") no_rex = bs(l=0, fname="no_rex") no_rep = bs(l=0, fname="no_rep") sib_scale = bs(l=2, cls=(bs_cond_scale,), fname = "sib_scale") sib_index = bs(l=3, cls=(bs_cond_index,), fname = "sib_index") sib_base = bs(l=3, cls=(bs_cond_index,), fname = "sib_base") disp = bs(l=0, cls=(bs_cond_disp,), fname = "disp") s08 = bs(l=8, cls=(bs_s08, )) u08 = bs(l=8, cls=(x86_08, x86_arg)) u07 = bs(l=7, cls=(x86_08, x86_arg)) u16 = bs(l=16, cls=(x86_16, x86_arg)) u32 = bs(l=32, cls=(x86_32, x86_arg)) s3264 = bs(l=32, cls=(x86_s32to64, x86_arg)) u08_3 = bs(l=0, cls=(x86_imm_fix_08, x86_arg), ival = 3) d0 = bs("000", fname='reg') d1 = bs("001", fname='reg') d2 = bs("010", fname='reg') d3 = bs("011", fname='reg') d4 = bs("100", fname='reg') d5 = bs("101", fname='reg') d6 = bs("110", fname='reg') d7 = bs("111", fname='reg') sd = bs(l=1, fname="sd") wd = bs(l=1, fname="wd") stk = bs(l=0, fname="stk") class field_size(object): prio = default_prio def __init__(self, d=None): if d is None: d = {} self.d = d def get(self, opm, adm=None): return self.d[opm] class bs_mem(object): def encode(self): return self.value != 0b11 def decode(self, v): self.value = v return v != 0b11 class bs_reg(object): def encode(self): return self.value == 0b11 def decode(self, v): self.value = v return v == 0b11 d_imm64 = bs(l=0, fname="imm64") d_eax = bs(l=0, cls=(bs_eax, ), fname='eax') d_edx = bs(l=0, cls=(bs_edx, ), fname='edx') d_st = bs(l=0, cls=(x86_reg_st, ), fname='st') d_imm = bs(l=0, cls=(bs_cond_imm,), fname="imm") d_imm64 = bs(l=0, cls=(bs_cond_imm64,), fname="imm") d_ax = bs(l=0, cls=(r_ax, ), fname='ax') d_dx = bs(l=0, cls=(r_dx, ), fname='dx') d_cl = bs(l=0, cls=(r_cl, ), fname='cl') d_cs = bs(l=0, cls=(bs_cs, ), fname='cs') d_ds = bs(l=0, cls=(bs_ds, ), fname='ds') d_es = bs(l=0, cls=(bs_es, ), fname='es') d_ss = bs(l=0, cls=(bs_ss, ), fname='ss') d_fs = bs(l=0, cls=(bs_fs, ), fname='fs') d_gs = bs(l=0, cls=(bs_gs, ), fname='gs') # Offset must be decoded in last position to have final instruction len rel_off = bs(l=0, cls=(bs_rel_off,), fname="off", order=-1) # Offset must be decoded in last position to have final instruction len rel_off08 = bs(l=8, cls=(bs_rel_off08,), fname="off", order=-1) moff = bs(l=0, cls=(bs_moff,), fname="off") msegoff = bs(l=16, cls=(bs_msegoff,), fname="mseg") movoff = bs(l=0, cls=(bs_movoff,), fname="off") mod = bs(l=2, fname="mod") mod_mem = bs(l=2, cls=(bs_mem,), fname="mod") mod_reg = bs(l=2, cls=(bs_reg,), fname="mod") rmreg = bs(l=3, cls=(x86_rm_reg, ), order =1, fname = "reg") reg = bs(l=3, cls=(x86_reg, ), order =1, fname = "reg") reg_modrm = bs(l=3, cls=(x86_reg_modrm, ), order =1, fname = "reg") vex_reg = bs(l=0, cls=(x86_vex_reg, ), order =1, fname = "vex_reg") regnoarg = bs(l=3, default_val="000", order=1, fname="reg") segm = bs(l=3, cls=(x86_rm_segm, ), order =1, fname = "reg") crreg = bs(l=3, cls=(x86_rm_cr, ), order =1, fname = "reg") drreg = bs(l=3, cls=(x86_rm_dr, ), order =1, fname = "reg") mm_reg = bs(l=3, cls=(x86_rm_reg_mm, ), order =1, fname = "reg") xmm_reg = bs(l=3, cls=(x86_rm_reg_xmm, ), order =1, fname = "reg") bnd_reg = bs(l=3, cls=(x86_rm_reg_bnd, ), order =1, fname = "reg") ymm_reg = bs(l=3, cls=(x86_rm_reg_ymm, ), order =1, fname = "reg") fltreg = bs(l=3, cls=(x86_rm_flt, ), order =1, fname = "reg") rm = bs(l=3, fname="rm") rm_arg = bs(l=0, cls=(x86_rm_arg,), fname='rmarg') rm_arg_w8 = bs(l=0, cls=(x86_rm_w8,), fname='rmarg') rm_arg_sx = bs(l=0, cls=(x86_rm_sx,), fname='rmarg') rm_arg_sxd = bs(l=0, cls=(x86_rm_sxd,), fname='rmarg') rm_arg_sd = bs(l=0, cls=(x86_rm_sd,), fname='rmarg') rm_arg_wd = bs(l=0, cls=(x86_rm_wd,), fname='rmarg') rm_arg_08 = bs(l=0, cls=(x86_rm_08,), fname='rmarg') rm_arg_reg_m08 = bs(l=0, cls=(x86_rm_reg_m08,), fname='rmarg') rm_arg_reg_m16 = bs(l=0, cls=(x86_rm_reg_m16,), fname='rmarg') rm_arg_m08 = bs(l=0, cls=(x86_rm_m08,), fname='rmarg') rm_arg_m64 = bs(l=0, cls=(x86_rm_m64,), fname='rmarg') rm_arg_m80 = bs(l=0, cls=(x86_rm_m80,), fname='rmarg') rm_arg_m16 = bs(l=0, cls=(x86_rm_m16,), fname='rmarg') rm_mem = bs(l=0, cls=(x86_rm_mem,), fname='rmarg') rm_mem_far = bs(l=0, cls=(x86_rm_mem_far,), fname='rmarg') rm_arg_mm = bs(l=0, cls=(x86_rm_mm,), fname='rmarg') rm_arg_mm_m64 = bs(l=0, cls=(x86_rm_mm_m64,), fname='rmarg') rm_arg_mm_reg = bs(l=0, cls=(x86_rm_mm_reg,), fname='rmarg') rm_arg_xmm = bs(l=0, cls=(x86_rm_xmm,), fname='rmarg') rm_arg_xmm_m32 = bs(l=0, cls=(x86_rm_xmm_m32,), fname='rmarg') rm_arg_xmm_m64 = bs(l=0, cls=(x86_rm_xmm_m64,), fname='rmarg') rm_arg_xmm_m128 = bs(l=0, cls=(x86_rm_xmm_m128,), fname='rmarg') rm_arg_xmm_reg = bs(l=0, cls=(x86_rm_xmm_reg,), fname='rmarg') rm_arg_bnd = bs(l=0, cls=(x86_rm_bnd,), fname='rmarg') rm_arg_bnd_m64 = bs(l=0, cls=(x86_rm_bnd_m64,), fname='rmarg') rm_arg_bnd_m128 = bs(l=0, cls=(x86_rm_bnd_m128,), fname='rmarg') rm_arg_bnd_reg = bs(l=0, cls=(x86_rm_bnd_reg,), fname='rmarg') rm_arg_ymm = bs(l=0, cls=(x86_rm_ymm,), fname='rmarg') swapargs = bs_swapargs(l=1, fname="swap", mn_mod=list(range(1 << 1))) class bs_op_mode(bsi): def decode(self, v): opmode = self.parent.v_opmode() return opmode == self.mode class bs_ad_mode(bsi): def decode(self, v): admode = self.parent.v_admode() return admode == self.mode class bs_op_mode_no64(bsi): def encode(self): if self.parent.mode == 64: return False return super(bs_op_mode_no64, self).encode() def decode(self, v): if self.parent.mode == 64: return False opmode = self.parent.v_opmode() return opmode == self.mode class bs_op_mode64(bsi): def encode(self): if self.parent.mode != 64: return False return super(bs_op_mode64, self).encode() def decode(self, v): if self.parent.mode != 64: return False return True class bs_op_modeno64(bsi): def encode(self): if self.parent.mode == 64: return False return super(bs_op_modeno64, self).encode() def decode(self, v): if self.parent.mode == 64: return False return True bs_opmode16 = bs(l=0, cls=(bs_op_mode,), mode = 16, fname="fopmode") bs_opmode32 = bs(l=0, cls=(bs_op_mode,), mode = 32, fname="fopmode") bs_opmode64 = bs(l=0, cls=(bs_op_mode,), mode = 64, fname="fopmode") bs_admode16 = bs(l=0, cls=(bs_ad_mode,), mode = 16, fname="fadmode") bs_admode32 = bs(l=0, cls=(bs_ad_mode,), mode = 32, fname="fadmode") bs_admode64 = bs(l=0, cls=(bs_ad_mode,), mode = 64, fname="fadmode") bs_opmode16_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 16, fname="fopmode") bs_opmode32_no64 = bs(l=0, cls=(bs_op_mode_no64,), mode = 32, fname="fopmode") bs_mode64 = bs(l=0, cls=(bs_op_mode64,)) bs_modeno64 = bs(l=0, cls=(bs_op_modeno64,)) cond_list = ["O", "NO", "B", "AE", "Z", "NZ", "BE", "A", "S", "NS", "PE", "NP", #"L", "NL", "NG", "G"] "L", "GE", "LE", "G"] cond = bs_mod_name(l=4, fname='cond', mn_mod=cond_list) def rmmod(r, rm_arg_x=rm_arg, modrm=mod): return [modrm, r, rm, sib_scale, sib_index, sib_base, disp, rm_arg_x] # # mode | reg | rm # # # # scale | index | base # # # # Prefix | REX prefix | Opcode | mod/rm | sib | displacement | immediate # # def addop(name, fields, args=None, alias=False): dct = {"fields": fields} dct["alias"] = alias if args is not None: dct['args'] = args type(name, (mn_x86,), dct) """ class ia32_aaa(mn_x86): fields = [bs8(0x37)] """ addop("aaa", [bs8(0x37)]) addop("aas", [bs8(0x3F)]) addop("aad", [bs8(0xd5), u08]) addop("aam", [bs8(0xd4), u08]) addop("adc", [bs("0001010"), w8, d_eax, d_imm]) addop("adc", [bs("100000"), se, w8] + rmmod(d2, rm_arg_w8) + [d_imm]) addop("adc", [bs("000100"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("add", [bs("0000010"), w8, d_eax, d_imm]) addop("add", [bs("100000"), se, w8] + rmmod(d0, rm_arg_w8) + [d_imm]) addop("add", [bs("000000"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("and", [bs("0010010"), w8, d_eax, d_imm]) addop("and", [bs("100000"), se, w8] + rmmod(d4, rm_arg_w8) + [d_imm]) addop("and", [bs("001000"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("bndmov", [bs8(0x0f), bs8(0x1a), pref_66, bs_modeno64] + rmmod(bnd_reg, rm_arg_bnd_m64), [bnd_reg, rm_arg_bnd_m64]) addop("bndmov", [bs8(0x0f), bs8(0x1a), pref_66, bs_mode64] + rmmod(bnd_reg, rm_arg_bnd_m128), [bnd_reg, rm_arg_bnd_m128]) addop("bndmov", [bs8(0x0f), bs8(0x1b), pref_66, bs_modeno64] + rmmod(bnd_reg, rm_arg_bnd_m64), [rm_arg_bnd_m64, bnd_reg]) addop("bndmov", [bs8(0x0f), bs8(0x1b), pref_66, bs_mode64] + rmmod(bnd_reg, rm_arg_bnd_m128), [rm_arg_bnd_m128, bnd_reg]) addop("bsf", [bs8(0x0f), bs8(0xbc), no_rep] + rmmod(rmreg)) addop("bsr", [bs8(0x0f), bs8(0xbd), mod, rmreg, rm, sib_scale, sib_index, sib_base, disp, rm_arg]) addop("bswap", [bs8(0x0f), bs('11001'), reg]) addop("bt", [bs8(0x0f), bs8(0xa3)] + rmmod(rmreg), [rm_arg, rmreg]) addop("bt", [bs8(0x0f), bs8(0xba)] + rmmod(d4) + [u08]) addop("btc", [bs8(0x0f), bs8(0xbb)] + rmmod(rmreg), [rm_arg, rmreg]) addop("btc", [bs8(0x0f), bs8(0xba)] + rmmod(d7) + [u08]) addop("btr", [bs8(0x0f), bs8(0xb3)] + rmmod(rmreg), [rm_arg, rmreg]) addop("btr", [bs8(0x0f), bs8(0xba)] + rmmod(d6) + [u08]) addop("bts", [bs8(0x0f), bs8(0xab)] + rmmod(rmreg), [rm_arg, rmreg]) addop("bts", [bs8(0x0f), bs8(0xba)] + rmmod(d5) + [u08]) addop("call", [bs8(0xe8), rel_off]) addop("call", [bs8(0xff), stk] + rmmod(d2)) addop("call", [bs8(0xff), stk] + rmmod(d3, rm_arg_x=rm_mem_far, modrm=mod_mem)) addop("call", [bs8(0x9a), bs_modeno64, moff, msegoff]) addop("cbw", [bs8(0x98), bs_opmode16]) addop("cwde", [bs8(0x98), bs_opmode32]) addop("cdqe", [bs8(0x98), bs_opmode64]) addop("clc", [bs8(0xf8)]) addop("cld", [bs8(0xfc)]) addop("cli", [bs8(0xfa)]) addop("clts", [bs8(0x0f), bs8(0x06)]) addop("cmc", [bs8(0xf5)]) addop("cmov", [bs8(0x0f), bs('0100'), cond] + rmmod(rmreg)) addop("cmp", [bs("0011110"), w8, d_eax, d_imm]) addop("cmp", [bs("100000"), se, w8] + rmmod(d7, rm_arg_w8) + [d_imm]) addop("cmp", [bs("001110"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("cmpsb", [bs8(0xa6)]) addop("cmpsw", [bs8(0xa7), bs_opmode16]) addop("cmpsd", [bs8(0xa7), bs_opmode32]) addop("cmpsq", [bs8(0xa7), bs_opmode64]) addop("cmpxchg", [bs8(0x0f), bs('1011000'), w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("cmpxchg8b", [bs8(0x0f), bs8(0xc7), bs_opmode16] + rmmod(d1, rm_arg_m64)) addop("cmpxchg8b", [bs8(0x0f), bs8(0xc7), bs_opmode32] + rmmod(d1, rm_arg_m64)) addop("cmpxchg16b", [bs8(0x0f), bs8(0xc7), bs_opmode64] + rmmod(d1, rm_arg_xmm_m128)) # XXX TODO CMPXCHG8/16 addop("comiss", [bs8(0x0f), bs8(0x2f), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m32), [xmm_reg, rm_arg_xmm_m32]) addop("comisd", [bs8(0x0f), bs8(0x2f), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m64), [xmm_reg, rm_arg_xmm_m64]) addop("cpuid", [bs8(0x0f), bs8(0xa2)]) addop("cwd", [bs8(0x99), bs_opmode16]) addop("cdq", [bs8(0x99), bs_opmode32]) addop("cqo", [bs8(0x99), bs_opmode64]) addop("daa", [bs8(0x27)]) addop("das", [bs8(0x2f)]) addop("dec", [bs('1111111'), w8] + rmmod(d1, rm_arg_w8)) addop("dec", [bs('01001'), reg, bs_modeno64]) addop("div", [bs('1111011'), w8] + rmmod(d6, rm_arg_w8)) addop("enter", [bs8(0xc8), u16, u08]) # float ##### addop("fwait", [bs8(0x9b)]) addop("f2xm1", [bs8(0xd9), bs8(0xf0)]) addop("fabs", [bs8(0xd9), bs8(0xe1)]) addop("fadd", [bs("11011"), sd, bs("00")] + rmmod(d0, rm_arg_sd)) addop("fadd", [bs("11011"), swapargs, bs("00"), bs("11000"), d_st, fltreg], [d_st, fltreg]) addop("faddp", [bs8(0xde), bs("11000"), fltreg, d_st]) addop("fiadd", [bs("11011"), wd, bs("10")] + rmmod(d0, rm_arg_wd)) addop("fbld", [bs8(0xdf)] + rmmod(d4, rm_arg_m80)) addop("fbldp", [bs8(0xdf)] + rmmod(d6, rm_arg_m80)) addop("fchs", [bs8(0xd9), bs8(0xe0)]) # addop("fclex", [bs8(0x9b), bs8(0xdb), bs8(0xe2)]) addop("fnclex", [bs8(0xdb), bs8(0xe2)]) addop("fcmovb", [bs8(0xda), bs("11000"), d_st, fltreg]) addop("fcmove", [bs8(0xda), bs("11001"), d_st, fltreg]) addop("fcmovbe", [bs8(0xda), bs("11010"), d_st, fltreg]) addop("fcmovu", [bs8(0xda), bs("11011"), d_st, fltreg]) addop("fcmovnb", [bs8(0xdb), bs("11000"), d_st, fltreg]) addop("fcmovne", [bs8(0xdb), bs("11001"), d_st, fltreg]) addop("fcmovnbe", [bs8(0xdb), bs("11010"), d_st, fltreg]) addop("fcmovnu", [bs8(0xdb), bs("11011"), d_st, fltreg]) addop("fcom", [bs("11011"), sd, bs("00")] + rmmod(d2, rm_arg_sd)) addop("fcom", [bs("11011"), swapargs, bs("00"), bs("11010"), d_st, fltreg], [d_st, fltreg]) addop("fcomp", [bs("11011"), sd, bs("00")] + rmmod(d3, rm_arg_sd)) addop("fcomp", [bs("11011"), swapargs, bs("00"), bs("11011"), d_st, fltreg], [d_st, fltreg]) addop("fcompp", [bs8(0xde), bs8(0xd9)]) addop("fcomi", [bs8(0xdb), bs("11110"), d_st, fltreg]) addop("fcomip", [bs8(0xdf), bs("11110"), d_st, fltreg]) addop("fucomi", [bs8(0xdb), bs("11101"), d_st, fltreg]) addop("fucomip", [bs8(0xdf), bs("11101"), d_st, fltreg]) addop("fcos", [bs8(0xd9), bs8(0xff)]) addop("fdecstp", [bs8(0xd9), bs8(0xf6)]) addop("fdiv", [bs("11011"), sd, bs("00")] + rmmod(d6, rm_arg_sd)) addop("fdiv", [bs8(0xd8), bs("11110"), d_st, fltreg]) addop("fdiv", [bs8(0xdc), bs("11111"), fltreg, d_st]) addop("fdivp", [bs8(0xde), bs("11111"), fltreg, d_st]) addop("fidiv", [bs("11011"), wd, bs("10")] + rmmod(d6, rm_arg_wd)) addop("fdivr", [bs("11011"), sd, bs("00")] + rmmod(d7, rm_arg_sd)) addop("fdivr", [bs8(0xd8), bs("11111"), d_st, fltreg]) addop("fdivr", [bs8(0xdc), bs("11110"), fltreg, d_st]) addop("fdivrp", [bs8(0xde), bs("11110"), fltreg, d_st]) addop("fidivr", [bs("11011"), wd, bs("10")] + rmmod(d7, rm_arg_wd)) addop("ffree", [bs8(0xdd), bs("11000"), fltreg]) addop("ficom", [bs("11011"), wd, bs("10")] + rmmod(d2, rm_arg_wd)) addop("ficomp", [bs("11011"), wd, bs("10")] + rmmod(d3, rm_arg_wd)) addop("fild", [bs("11011"), wd, bs("11")] + rmmod(d0, rm_arg_wd)) addop("fild", [bs8(0xdf)] + rmmod(d5, rm_arg_m64)) addop("fincstp", [bs8(0xd9), bs8(0xf7)]) addop("blsi", [pref_0f38, bs8(0xf3), vex_reg] + rmmod(bs("011"), rm_arg), [vex_reg, rm_arg]) addop("andn", [pref_0f38, bs8(0xf2), vex_reg] + rmmod(rmreg, rm_arg), [rmreg, vex_reg, rm_arg]) addop("bextr", [pref_0f38, bs8(0xf7), vex_reg] + rmmod(rmreg, rm_arg), [rmreg, rm_arg, vex_reg]) addop("blsmsk", [pref_0f38, bs8(0xf3), vex_reg] + rmmod(bs("010"), rm_arg), [vex_reg, rm_arg]) addop("blsr", [pref_0f38, bs8(0xf3), vex_reg] + rmmod(bs("001"), rm_arg), [vex_reg, rm_arg]) addop("bzhi", [pref_0f38, bs8(0xf5), vex_reg] + rmmod(rmreg, rm_arg), [rmreg, rm_arg, vex_reg]) addop("tzcnt", [bs8(0x0f), bs8(0xbc), pref_f3] + rmmod(rmreg, rm_arg), [rmreg, rm_arg]) # addop("finit", [bs8(0x9b), bs8(0xdb), bs8(0xe3)]) addop("fninit", [bs8(0xdb), bs8(0xe3)]) addop("fist", [bs("11011"), wd, bs("11")] + rmmod(d2, rm_arg_wd)) addop("fistp", [bs("11011"), wd, bs("11")] + rmmod(d3, rm_arg_wd)) addop("fistp", [bs8(0xdf)] + rmmod(d7, rm_arg_m64)) addop("fisttp", [bs("11011"), wd, bs("11")] + rmmod(d1, rm_arg_wd)) addop("fisttp", [bs8(0xdd)] + rmmod(d1, rm_arg_m64)) addop("fld", [bs("11011"), sd, bs("01")] + rmmod(d0, rm_arg_sd)) addop("fld", [bs8(0xdb)] + rmmod(d5, rm_arg_m80)) addop("fld", [bs8(0xd9), bs("11000"), fltreg]) addop("fld1", [bs8(0xd9), bs8(0xe8)]) addop("fldl2t", [bs8(0xd9), bs8(0xe9)]) addop("fldl2e", [bs8(0xd9), bs8(0xea)]) addop("fldpi", [bs8(0xd9), bs8(0xeb)]) addop("fldlg2", [bs8(0xd9), bs8(0xec)]) addop("fldln2", [bs8(0xd9), bs8(0xed)]) addop("fldz", [bs8(0xd9), bs8(0xee)]) addop("fldcw", [bs8(0xd9)] + rmmod(d5, rm_arg_m16)) addop("fldenv", [bs8(0xd9)] + rmmod(d4, rm_arg_m80)) # XXX TODO: m14? addop("fmul", [bs("11011"), sd, bs("00")] + rmmod(d1, rm_arg_sd)) addop("fmul", [bs("11011"), swapargs, bs("00"), bs("11001"), d_st, fltreg], [d_st, fltreg]) addop("fmulp", [bs8(0xde), bs("11001"), fltreg, d_st]) addop("fimul", [bs("11011"), wd, bs("10")] + rmmod(d1, rm_arg_wd)) addop("fnop", [bs8(0xd9), bs8(0xd0)]) addop("fpatan", [bs8(0xd9), bs8(0xf3)]) addop("fprem", [bs8(0xd9), bs8(0xf8)]) addop("fprem1", [bs8(0xd9), bs8(0xf5)]) addop("fptan", [bs8(0xd9), bs8(0xf2)]) addop("frndint", [bs8(0xd9), bs8(0xfc)]) addop("frstor", [bs8(0xdd)] + rmmod(d4, rm_arg_m80)) # XXX TODO: m94 ? # addop("fsave", [bs8(0x9b), bs8(0xdd)] + rmmod(d6, rm_arg_m80)) # XXX # TODO: m94 ? addop("fnsave", [bs8(0xdd)] + rmmod(d6, rm_arg_m80)) # XXX TODO: m94 ? addop("fscale", [bs8(0xd9), bs8(0xfd)]) addop("fsin", [bs8(0xd9), bs8(0xfe)]) addop("fsincos", [bs8(0xd9), bs8(0xfb)]) addop("fsqrt", [bs8(0xd9), bs8(0xfa)]) addop("fst", [bs("11011"), sd, bs("01")] + rmmod(d2, rm_arg_sd)) addop("fst", [bs8(0xdd), bs("11010"), fltreg]) addop("fstp", [bs("11011"), sd, bs("01")] + rmmod(d3, rm_arg_sd)) addop("fstp", [bs8(0xdb)] + rmmod(d7, rm_arg_m80)) addop("fstp", [bs8(0xdd), bs("11011"), fltreg]) # addop("fstcw", [bs8(0x9b), bs8(0xd9)] + rmmod(d7, rm_arg_m16)) addop("fnstcw", [bs8(0xd9)] + rmmod(d7, rm_arg_m16)) # addop("fstenv", [bs8(0x9b), bs8(0xd9)] + rmmod(d6, rm_arg_m80)) # XXX # TODO: m14? addop("fnstenv", [bs8(0xd9)] + rmmod(d6, rm_arg_m80)) # XXX TODO: m14? # addop("fstsw", [bs8(0x9b), bs8(0xdd)] + rmmod(d7, rm_arg_m16)) addop("fnstsw", [bs8(0xdd)] + rmmod(d7, rm_arg_m16)) # addop("fstsw", [bs8(0x9b), bs8(0xdf), bs8(0xe0), d_ax]) addop("fnstsw", [bs8(0xdf), bs8(0xe0), d_ax]) addop("fsub", [bs("11011"), sd, bs("00")] + rmmod(d4, rm_arg_sd)) addop("fsub", [bs8(0xd8), bs("11100"), d_st, fltreg]) addop("fsub", [bs8(0xdc), bs("11101"), fltreg, d_st]) addop("fsubp", [bs8(0xde), bs("11101"), fltreg, d_st]) addop("fisub", [bs("11011"), wd, bs("10")] + rmmod(d4, rm_arg_wd)) addop("fsubr", [bs("11011"), sd, bs("00")] + rmmod(d5, rm_arg_sd)) addop("fsubr", [bs8(0xd8), bs("11101"), d_st, fltreg]) addop("fsubr", [bs8(0xdc), bs("11100"), fltreg, d_st]) addop("fsubrp", [bs8(0xde), bs("11100"), fltreg, d_st]) addop("fisubr", [bs("11011"), wd, bs("10")] + rmmod(d5, rm_arg_wd)) addop("ftst", [bs8(0xd9), bs8(0xe4)]) addop("fucom", [bs8(0xdd), bs("11100"), fltreg]) addop("fucomp", [bs8(0xdd), bs("11101"), fltreg]) addop("fucompp", [bs8(0xda), bs8(0xe9)]) addop("fxam", [bs8(0xd9), bs8(0xe5)]) addop("fxch", [bs8(0xd9), bs("11001"), fltreg]) addop("fxrstor", [bs8(0x0f), bs8(0xae)] + rmmod(d1, rm_arg_m80)) # XXX TODO m512 addop("fxsave", [bs8(0x0f), bs8(0xae)] + rmmod(d0, rm_arg_m80)) # XXX TODO m512 addop("stmxcsr", [bs8(0x0f), bs8(0xae)] + rmmod(d3)) addop("ldmxcsr", [bs8(0x0f), bs8(0xae)] + rmmod(d2)) addop("fxtract", [bs8(0xd9), bs8(0xf4)]) addop("fyl2x", [bs8(0xd9), bs8(0xf1)]) addop("fyl2xp1", [bs8(0xd9), bs8(0xf9)]) addop("hlt", [bs8(0xf4)]) addop("icebp", [bs8(0xf1)]) addop("idiv", [bs('1111011'), w8] + rmmod(d7, rm_arg_w8)) addop("imul", [bs('1111011'), w8] + rmmod(d5, rm_arg_w8)) addop("imul", [bs8(0x0f), bs8(0xaf)] + rmmod(rmreg)) addop("imul", [bs("011010"), se, bs('1')] + rmmod(rmreg) + [d_imm]) addop("in", [bs("1110010"), w8, d_eax, u08]) addop("in", [bs("1110110"), w8, d_eax, d_edx]) addop("inc", [bs('1111111'), w8] + rmmod(d0, rm_arg_w8)) addop("inc", [bs('01000'), reg, bs_modeno64]) addop("insb", [bs8(0x6c)]) addop("insw", [bs8(0x6d), bs_opmode16]) addop("insd", [bs8(0x6d), bs_opmode32]) addop("insd", [bs8(0x6d), bs_opmode64]) addop("int", [bs8(0xcc), u08_3]) addop("int", [bs8(0xcd), u08]) addop("into", [bs8(0xce)]) addop("invd", [bs8(0x0f), bs8(0x08)]) addop("invlpg", [bs8(0x0f), bs8(0x01)] + rmmod(d7)) addop("iret", [bs8(0xcf), bs_opmode16]) addop("iretd", [bs8(0xcf), bs_opmode32]) addop("iretq", [bs8(0xcf), bs_opmode64]) addop("j", [bs('0111'), cond, rel_off08]) addop("jcxz", [bs8(0xe3), rel_off08, bs_admode16]) addop("jecxz", [bs8(0xe3), rel_off08, bs_admode32]) addop("jrcxz", [bs8(0xe3), rel_off08, bs_admode64]) addop("j", [bs8(0x0f), bs('1000'), cond, rel_off]) addop("jmp", [bs8(0xeb), rel_off08]) addop("jmp", [bs8(0xe9), rel_off]) # TODO XXX replace stk force64? addop("jmp", [bs8(0xff), stk] + rmmod(d4)) addop("jmp", [bs8(0xea), bs_modeno64, moff, msegoff]) addop("jmp", [bs8(0xff)] + rmmod(d5, rm_arg_x=rm_mem_far, modrm=mod_mem)) addop("lahf", [bs8(0x9f)]) addop("lar", [bs8(0x0f), bs8(0x02)] + rmmod(rmreg)) addop("lea", [bs8(0x8d)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("les", [bs8(0xc4)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("lds", [bs8(0xc5)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("lss", [bs8(0x0f), bs8(0xb2)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("lfs", [bs8(0x0f), bs8(0xb4)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("lgs", [bs8(0x0f), bs8(0xb5)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_mem)) addop("lgdt", [bs8(0x0f), bs8(0x01)] + rmmod(d2, modrm=mod_mem)) addop("lidt", [bs8(0x0f), bs8(0x01)] + rmmod(d3, modrm=mod_mem)) addop("lfence", [bs8(0x0f), bs8(0xae), bs8(0xe8), no_xmm_pref]) addop("mfence", [bs8(0x0f), bs8(0xae), bs8(0xf0)]) addop("sfence", [bs8(0x0f), bs8(0xae), bs8(0xf8)]) addop("leave", [bs8(0xc9), stk]) addop("lodsb", [bs8(0xac)]) addop("lodsw", [bs8(0xad), bs_opmode16]) addop("lodsd", [bs8(0xad), bs_opmode32]) addop("lodsq", [bs8(0xad), bs_opmode64]) addop("loop", [bs8(0xe2), rel_off08]) addop("loope", [bs8(0xe1), rel_off08]) addop("loopne", [bs8(0xe0), rel_off08]) addop("lsl", [bs8(0x0f), bs8(0x03)] + rmmod(rmreg)) addop("monitor", [bs8(0x0f), bs8(0x01), bs8(0xc8)]) addop("mov", [bs("100010"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("mov", [bs("100011"), swapargs, bs('0')] + rmmod(segm), [rm_arg, segm]) addop("mov", [bs("101000"), swapargs, w8, d_eax, movoff], [d_eax, movoff]) addop("mov", [bs("1011"), w8, reg, d_imm64]) addop("mov", [bs("1100011"), w8] + rmmod(d0, rm_arg_w8) + [d_imm]) addop("mov", [bs8(0x0f), bs("001000"), swapargs, bs('0')] + rmmod(crreg), [rm_arg, crreg]) addop("mov", [bs8(0x0f), bs("001000"), swapargs, bs('1')] + rmmod(drreg), [rm_arg, drreg]) addop("movsb", [bs8(0xa4)]) addop("movsw", [bs8(0xa5), bs_opmode16]) addop("movsd", [bs8(0xa5), bs_opmode32]) addop("movsq", [bs8(0xa5), bs_opmode64]) addop("movsx", [bs8(0x0f), bs("1011111"), w8, sx] + rmmod(rmreg, rm_arg_sx)) addop("movsxd", [bs8(0x63), sxd, bs_mode64] + rmmod(rmreg, rm_arg_sxd)) addop("movups", [bs8(0x0f), bs("0001000"), swapargs, no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("movsd", [bs8(0x0f), bs("0001000"), swapargs, pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64), [xmm_reg, rm_arg_xmm_m64]) addop("movss", [bs8(0x0f), bs("0001000"), swapargs, pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32), [xmm_reg, rm_arg_xmm_m32]) addop("movupd", [bs8(0x0f), bs8(0x10), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("movupd", [bs8(0x0f), bs8(0x11), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [rm_arg_xmm, xmm_reg]) addop("movd", [bs8(0x0f), bs('011'), swapargs, bs('1110'), no_xmm_pref] + rmmod(mm_reg, rm_arg), [mm_reg, rm_arg]) addop("movd", [bs8(0x0f), bs('011'), swapargs, bs('1110'), pref_66, bs_opmode32] + rmmod(xmm_reg, rm_arg), [xmm_reg, rm_arg]) addop("movq", [bs8(0x0f), bs('011'), swapargs, bs('1110'), pref_66, bs_opmode64] + rmmod(xmm_reg, rm_arg), [xmm_reg, rm_arg]) addop("movq", [bs8(0x0f), bs('011'), swapargs, bs('1111'), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64), [mm_reg, rm_arg_mm_m64]) addop("movq", [bs8(0x0f), bs8(0x7e), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m64), [xmm_reg, rm_arg_xmm_m64]) addop("movq", [bs8(0x0f), bs8(0xd6), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m64), [rm_arg_xmm_m64, xmm_reg]) addop("movmskps", [bs8(0x0f), bs8(0x50), no_xmm_pref] + rmmod(reg_modrm, rm_arg_xmm_reg)) addop("movmskpd", [bs8(0x0f), bs8(0x50), pref_66] + rmmod(reg_modrm, rm_arg_xmm_reg)) addop("movnti", [bs8(0x0f), bs8(0xc3)] + rmmod(rmreg), [rm_arg, rmreg]) addop("addss", [bs8(0x0f), bs8(0x58), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("addsd", [bs8(0x0f), bs8(0x58), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("subss", [bs8(0x0f), bs8(0x5c), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("subsd", [bs8(0x0f), bs8(0x5c), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("mulss", [bs8(0x0f), bs8(0x59), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("mulsd", [bs8(0x0f), bs8(0x59), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("divss", [bs8(0x0f), bs8(0x5e), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("divsd", [bs8(0x0f), bs8(0x5e), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("roundss", [bs8(0x0f), bs8(0x3a), bs8(0x0a), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m32) + [u08]) addop("roundsd", [bs8(0x0f), bs8(0x3a), bs8(0x0b), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m64) + [u08]) addop("pminsw", [bs8(0x0f), bs8(0xea), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pminsw", [bs8(0x0f), bs8(0xea), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("ucomiss", [bs8(0x0f), bs8(0x2e), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("ucomisd", [bs8(0x0f), bs8(0x2e), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("movzx", [bs8(0x0f), bs("1011011"), w8, sx] + rmmod(rmreg, rm_arg_sx)) addop("mul", [bs('1111011'), w8] + rmmod(d4, rm_arg_w8)) addop("neg", [bs('1111011'), w8] + rmmod(d3, rm_arg_w8)) addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d0, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d1, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d2, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d3, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d4, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d5, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d6, rm_arg)) # XXX TODO m512 addop("nop", [bs8(0x0f), bs8(0x1f)] + rmmod(d7, rm_arg)) # XXX TODO m512 addop("not", [bs('1111011'), w8] + rmmod(d2, rm_arg_w8)) addop("or", [bs("0000110"), w8, d_eax, d_imm]) addop("or", [bs("100000"), se, w8] + rmmod(d1, rm_arg_w8) + [d_imm]) addop("or", [bs("000010"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("out", [bs("1110011"), w8, u08, d_eax]) addop("out", [bs("1110111"), w8, d_edx, d_eax]) addop("outsb", [bs8(0x6e)]) addop("outsw", [bs8(0x6f), bs_opmode16]) addop("outsd", [bs8(0x6f), bs_opmode32]) addop("outsd", [bs8(0x6f), bs_opmode64]) addop("setalc", [bs8(0xD6)]) # addop("pause", [bs8(0xf3), bs8(0x90)]) addop("popw", [bs8(0x8f), stk, bs_opmode16] + rmmod(d0)) addop("popw", [bs("01011"), stk, reg, bs_opmode16]) addop("popw", [bs8(0x1f), stk, d_ds, bs_opmode16]) addop("popw", [bs8(0x07), stk, d_es, bs_opmode16]) addop("popw", [bs8(0x17), stk, d_ss, bs_opmode16]) addop("popw", [bs8(0x0f), stk, bs8(0xa1), d_fs, bs_opmode16]) addop("popw", [bs8(0x0f), stk, bs8(0xa9), d_gs, bs_opmode16]) addop("pop", [bs8(0x8f), stk, bs_opmode32] + rmmod(d0)) addop("pop", [bs("01011"), stk, reg, bs_opmode32]) addop("pop", [bs8(0x1f), stk, d_ds, bs_opmode32]) addop("pop", [bs8(0x07), stk, d_es, bs_opmode32]) addop("pop", [bs8(0x17), stk, d_ss, bs_opmode32]) addop("pop", [bs8(0x0f), stk, bs8(0xa1), d_fs, bs_opmode32]) addop("pop", [bs8(0x0f), stk, bs8(0xa9), d_gs, bs_opmode32]) addop("pop", [bs8(0x8f), stk, bs_opmode64] + rmmod(d0)) addop("pop", [bs("01011"), stk, reg, bs_opmode64]) addop("pop", [bs8(0x1f), stk, d_ds, bs_opmode64]) addop("pop", [bs8(0x07), stk, d_es, bs_opmode64]) addop("pop", [bs8(0x17), stk, d_ss, bs_opmode64]) addop("pop", [bs8(0x0f), stk, bs8(0xa1), d_fs, bs_opmode64]) addop("pop", [bs8(0x0f), stk, bs8(0xa9), d_gs, bs_opmode64]) addop("popa", [bs8(0x61), stk, bs_opmode16]) addop("popad", [bs8(0x61), stk, bs_opmode32]) addop("popfw", [bs8(0x9d), stk, bs_opmode16]) addop("popfd", [bs8(0x9d), stk, bs_opmode32]) addop("popfq", [bs8(0x9d), stk, bs_opmode64]) addop("prefetch0", [bs8(0x0f), bs8(0x18)] + rmmod(d1, rm_arg_m08)) addop("prefetch1", [bs8(0x0f), bs8(0x18)] + rmmod(d2, rm_arg_m08)) addop("prefetch2", [bs8(0x0f), bs8(0x18)] + rmmod(d3, rm_arg_m08)) addop("prefetchnta", [bs8(0x0f), bs8(0x18)] + rmmod(d0, rm_arg_m08)) addop("prefetchw", [bs8(0x0f), bs8(0x0d)] + rmmod(d1, rm_arg_m08)) addop("pushw", [bs8(0xff), stk, bs_opmode16] + rmmod(d6)) addop("pushw", [bs("01010"), stk, reg, bs_opmode16]) addop("pushw", [bs8(0x6a), s08, stk, bs_opmode16]) addop("pushw", [bs8(0x68), d_imm, stk, bs_opmode16]) addop("pushw", [bs8(0x0e), stk, d_cs, bs_opmode16]) addop("pushw", [bs8(0x16), stk, d_ss, bs_opmode16]) addop("pushw", [bs8(0x1e), stk, d_ds, bs_opmode16]) addop("pushw", [bs8(0x06), stk, d_es, bs_opmode16]) addop("pushw", [bs8(0x0f), stk, bs8(0xa0), d_fs, bs_opmode16]) addop("pushw", [bs8(0x0f), stk, bs8(0xa8), d_gs, bs_opmode16]) addop("push", [bs8(0xff), stk, bs_opmode32] + rmmod(d6)) addop("push", [bs("01010"), stk, reg, bs_opmode32]) addop("push", [bs8(0x6a), s08, stk, bs_opmode32]) addop("push", [bs8(0x68), d_imm, stk, bs_opmode32]) addop("push", [bs8(0x0e), stk, d_cs, bs_opmode32]) addop("push", [bs8(0x16), stk, d_ss, bs_opmode32]) addop("push", [bs8(0x1e), stk, d_ds, bs_opmode32]) addop("push", [bs8(0x06), stk, d_es, bs_opmode32]) addop("push", [bs8(0x0f), stk, bs8(0xa0), d_fs, bs_opmode32]) addop("push", [bs8(0x0f), stk, bs8(0xa8), d_gs, bs_opmode32]) addop("push", [bs8(0xff), stk, bs_opmode64] + rmmod(d6)) addop("push", [bs("01010"), stk, reg, bs_opmode64]) addop("push", [bs8(0x6a), s08, stk, bs_opmode64]) addop("push", [bs8(0x68), d_imm, stk, bs_opmode64]) addop("push", [bs8(0x0e), stk, d_cs, bs_opmode64]) addop("push", [bs8(0x16), stk, d_ss, bs_opmode64]) addop("push", [bs8(0x1e), stk, d_ds, bs_opmode64]) addop("push", [bs8(0x06), stk, d_es, bs_opmode64]) addop("push", [bs8(0x0f), stk, bs8(0xa0), d_fs, bs_opmode64]) addop("push", [bs8(0x0f), stk, bs8(0xa8), d_gs, bs_opmode64]) addop("pusha", [bs8(0x60), stk, bs_opmode16_no64]) addop("pushad", [bs8(0x60), stk, bs_opmode32_no64]) addop("pushfw", [bs8(0x9c), stk, bs_opmode16]) addop("pushfd", [bs8(0x9c), stk, bs_opmode32]) addop("pushfq", [bs8(0x9c), stk, bs_opmode64]) addop("rcl", [bs('110100'), d_cl1, w8] + rmmod(d2, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("rcl", [bs('1100000'), w8] + rmmod(d2, rm_arg_w8) + [u08]) addop("rcr", [bs('110100'), d_cl1, w8] + rmmod(d3, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("rcr", [bs('1100000'), w8] + rmmod(d3, rm_arg_w8) + [u08]) addop("rol", [bs('110100'), d_cl1, w8] + rmmod(d0, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("rol", [bs('1100000'), w8] + rmmod(d0, rm_arg_w8) + [u08]) addop("ror", [bs('110100'), d_cl1, w8] + rmmod(d1, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("ror", [bs('1100000'), w8] + rmmod(d1, rm_arg_w8) + [u08]) addop("rdmsr", [bs8(0x0f), bs8(0x32)]) addop("rdpmc", [bs8(0x0f), bs8(0x33)]) addop("rdtsc", [bs8(0x0f), bs8(0x31)]) addop("ret", [bs8(0xc3), stk]) addop("ret", [bs8(0xc2), stk, u16]) addop("retf", [bs8(0xcb), stk]) addop("retf", [bs8(0xca), stk, u16]) addop("rsm", [bs8(0x0f), bs8(0xaa)]) addop("sahf", [bs8(0x9e)]) # XXX tipo in doc: /4 instead of /6 addop("sal", [bs('110100'), d_cl1, w8] + rmmod(d6, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("sal", [bs('1100000'), w8] + rmmod(d6, rm_arg_w8) + [u08]) addop("sar", [bs('110100'), d_cl1, w8] + rmmod(d7, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("sar", [bs('1100000'), w8] + rmmod(d7, rm_arg_w8) + [u08]) addop("scasb", [bs8(0xae)]) addop("scasw", [bs8(0xaf), bs_opmode16]) addop("scasd", [bs8(0xaf), bs_opmode32]) addop("scasq", [bs8(0xaf), bs_opmode64]) addop("shl", [bs('110100'), d_cl1, w8] + rmmod(d4, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("shl", [bs('1100000'), w8] + rmmod(d4, rm_arg_w8) + [u08]) addop("shr", [bs('110100'), d_cl1, w8] + rmmod(d5, rm_arg_w8), [rm_arg_w8, d_cl1]) addop("shr", [bs('1100000'), w8] + rmmod(d5, rm_arg_w8) + [u08]) addop("sbb", [bs("0001110"), w8, d_eax, d_imm]) addop("sbb", [bs("100000"), se, w8] + rmmod(d3, rm_arg_w8) + [d_imm]) addop("sbb", [bs("000110"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("set", [bs8(0x0f), bs('1001'), cond] + rmmod(regnoarg, rm_arg_08)) addop("sgdt", [bs8(0x0f), bs8(0x01)] + rmmod(d0, modrm=mod_mem)) addop("shld", [bs8(0x0f), bs8(0xa4)] + rmmod(rmreg) + [u08], [rm_arg, rmreg, u08]) addop("shld", [bs8(0x0f), bs8(0xa5)] + rmmod(rmreg) + [d_cl], [rm_arg, rmreg, d_cl]) addop("shrd", [bs8(0x0f), bs8(0xac)] + rmmod(rmreg) + [u08], [rm_arg, rmreg, u08]) addop("shrd", [bs8(0x0f), bs8(0xad)] + rmmod(rmreg) + [d_cl], [rm_arg, rmreg, d_cl]) addop("sidt", [bs8(0x0f), bs8(0x01)] + rmmod(d1, modrm=mod_mem)) addop("sldt", [bs8(0x0f), bs8(0x00)] + rmmod(d0, rm_arg_x=rm_arg_reg_m16)) addop("smsw", [bs8(0x0f), bs8(0x01)] + rmmod(d4)) addop("stc", [bs8(0xf9)]) addop("std", [bs8(0xfd)]) addop("sti", [bs8(0xfb)]) addop("stosb", [bs8(0xaa)]) addop("stosw", [bs8(0xab), bs_opmode16]) addop("stosd", [bs8(0xab), bs_opmode32]) addop("stosq", [bs8(0xab), bs_opmode64]) addop("str", [bs8(0x0f), bs8(0x00)] + rmmod(d1)) addop("sub", [bs("0010110"), w8, d_eax, d_imm]) addop("sub", [bs("100000"), se, w8] + rmmod(d5, rm_arg_w8) + [d_imm]) addop("sub", [bs("001010"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("syscall", [bs8(0x0f), bs8(0x05)]) addop("sysenter", [bs8(0x0f), bs8(0x34)]) addop("sysexit", [bs8(0x0f), bs8(0x35)]) addop("sysret", [bs8(0x0f), bs8(0x07)]) addop("test", [bs("1010100"), w8, d_eax, d_imm]) addop("test", [bs("1111011"), w8] + rmmod(d0, rm_arg_w8) + [d_imm]) addop("test", [bs("1000010"), w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("ud2", [bs8(0x0f), bs8(0x0b)]) addop("verr", [bs8(0x0f), bs8(0x00)] + rmmod(d4)) addop("verw", [bs8(0x0f), bs8(0x00)] + rmmod(d5)) addop("wbinvd", [bs8(0x0f), bs8(0x09)]) addop("wrmsr", [bs8(0x0f), bs8(0x30)]) addop("xadd", [bs8(0x0f), bs("1100000"), w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("nop", [bs8(0x90), no_rex], alias=True) addop("xchg", [bs('10010'), d_eax, reg]) addop("xchg", [bs('1000011'), w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("xlat", [bs8(0xd7)]) addop("xor", [bs("0011010"), w8, d_eax, d_imm]) addop("xor", [bs("100000"), se, w8] + rmmod(d6, rm_arg_w8) + [d_imm]) addop("xor", [bs("001100"), swapargs, w8] + rmmod(rmreg, rm_arg_w8), [rm_arg_w8, rmreg]) addop("xgetbv", [bs8(0x0f), bs8(0x01), bs8(0xd0)]) #### MMX/SSE/AVX operations #### Categories are the same than here: https://software.intel.com/sites/landingpage/IntrinsicsGuide/ #### ### Arithmetic (integers) ### ## Move # SSE addop("movapd", [bs8(0x0f), bs("0010100"), swapargs] + rmmod(xmm_reg, rm_arg_xmm) + [bs_opmode16], [xmm_reg, rm_arg_xmm]) addop("movaps", [bs8(0x0f), bs("0010100"), swapargs] + rmmod(xmm_reg, rm_arg_xmm_m128) + [bs_opmode32], [xmm_reg, rm_arg_xmm_m128]) addop("movaps", [bs8(0x0f), bs("0010100"), swapargs] + rmmod(xmm_reg, rm_arg_xmm_m128) + [bs_opmode64], [xmm_reg, rm_arg_xmm_m128]) addop("movdqu", [bs8(0x0f), bs("011"), swapargs, bs("1111"), pref_f3] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("movdqa", [bs8(0x0f), bs("011"), swapargs, bs("1111"), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("movhpd", [bs8(0x0f), bs("0001011"), swapargs, pref_66] + rmmod(xmm_reg, rm_arg_m64), [xmm_reg, rm_arg_m64]) addop("movhps", [bs8(0x0f), bs("0001011"), swapargs, no_xmm_pref] + rmmod(xmm_reg, rm_arg_m64), [xmm_reg, rm_arg_m64]) addop("movlpd", [bs8(0x0f), bs("0001001"), swapargs, pref_66] + rmmod(xmm_reg, rm_arg_m64), [xmm_reg, rm_arg_m64]) addop("movlps", [bs8(0x0f), bs("0001001"), swapargs, no_xmm_pref] + rmmod(xmm_reg, rm_arg_m64), [xmm_reg, rm_arg_m64]) addop("movhlps", [bs8(0x0f), bs8(0x12), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_reg), [xmm_reg, rm_arg_xmm_reg]) addop("movlhps", [bs8(0x0f), bs8(0x16), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_reg), [xmm_reg, rm_arg_xmm_reg]) addop("movdq2q", [bs8(0x0f), bs8(0xd6), pref_f2] + rmmod(mm_reg, rm_arg_xmm_reg), [mm_reg, rm_arg_xmm_reg]) addop("movq2dq", [bs8(0x0f), bs8(0xd6), pref_f3] + rmmod(xmm_reg, rm_arg_mm)) # AVX addop("vmovdqu", [bs("011"), swapargs, bs("1111"), pref_f3, pref_0f] + rmmod(ymm_reg, rm_arg_ymm), [ymm_reg, rm_arg_ymm]) ## Additions # SSE addop("paddb", [bs8(0x0f), bs8(0xfc), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("paddw", [bs8(0x0f), bs8(0xfd), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("paddd", [bs8(0x0f), bs8(0xfe), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("paddq", [bs8(0x0f), bs8(0xd4), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("paddb", [bs8(0x0f), bs8(0xfc), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("paddw", [bs8(0x0f), bs8(0xfd), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("paddd", [bs8(0x0f), bs8(0xfe), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("paddq", [bs8(0x0f), bs8(0xd4), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) ## Substractions # SSE addop("psubb", [bs8(0x0f), bs8(0xf8), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("psubw", [bs8(0x0f), bs8(0xf9), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("psubd", [bs8(0x0f), bs8(0xfa), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("psubq", [bs8(0x0f), bs8(0xfb), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("psubb", [bs8(0x0f), bs8(0xf8), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("psubw", [bs8(0x0f), bs8(0xf9), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("psubd", [bs8(0x0f), bs8(0xfa), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("psubq", [bs8(0x0f), bs8(0xfb), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) ### Arithmetic (floating-point) ### ## Additions # SSE addop("addps", [bs8(0x0f), bs8(0x58), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("addpd", [bs8(0x0f), bs8(0x58), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## Substractions # SSE addop("subps", [bs8(0x0f), bs8(0x5c), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("subpd", [bs8(0x0f), bs8(0x5c), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## Additions + Subtractions # SSE addop("addsubps", [bs8(0x0f), bs8(0xd0), pref_f2] + rmmod(xmm_reg, rm_arg_xmm)) ## Multiplications # SSE addop("mulps", [bs8(0x0f), bs8(0x59), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("mulpd", [bs8(0x0f), bs8(0x59), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## Divisions # SSE addop("divps", [bs8(0x0f), bs8(0x5e), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("divpd", [bs8(0x0f), bs8(0x5e), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ### Logical (floating-point) ### ## XOR addop("xorps", [bs8(0x0f), bs8(0x57), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("xorpd", [bs8(0x0f), bs8(0x57), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## AND addop("andps", [bs8(0x0f), bs8(0x54), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("andpd", [bs8(0x0f), bs8(0x54), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("andnps", [bs8(0x0f), bs8(0x55), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("andnpd", [bs8(0x0f), bs8(0x55), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## OR addop("orps", [bs8(0x0f), bs8(0x56), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("orpd", [bs8(0x0f), bs8(0x56), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ## AND # MMX addop("pand", [bs8(0x0f), bs8(0xdb), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) # SSE addop("pand", [bs8(0x0f), bs8(0xdb), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) ## ANDN # MMX addop("pandn", [bs8(0x0f), bs8(0xdf), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) # SSE addop("pandn", [bs8(0x0f), bs8(0xdf), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) ## OR # MMX addop("por", [bs8(0x0f), bs8(0xeb), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) # SSE addop("por", [bs8(0x0f), bs8(0xeb), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) ## XOR # MMX addop("pxor", [bs8(0x0f), bs8(0xef), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) # MMX addop("pxor", [bs8(0x0f), bs8(0xef), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) ### Comparisons (floating-point) ### addop("minps", [bs8(0x0f), bs8(0x5d), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("minss", [bs8(0x0f), bs8(0x5d), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("minpd", [bs8(0x0f), bs8(0x5d), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("minsd", [bs8(0x0f), bs8(0x5d), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("maxps", [bs8(0x0f), bs8(0x5f), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("maxpd", [bs8(0x0f), bs8(0x5f), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("maxsd", [bs8(0x0f), bs8(0x5f), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("maxss", [bs8(0x0f), bs8(0x5f), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) for cond_name, value in [ ("eq", 0x00), ("lt", 0x01), ("le", 0x02), ("unord", 0x03), ("neq", 0x04), ("nlt", 0x05), ("nle", 0x06), ("ord", 0x07), ]: addop("cmp%sps" % cond_name, [bs8(0x0f), bs8(0xc2), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m64) + [bs8(value)]) addop("cmp%spd" % cond_name, [bs8(0x0f), bs8(0xc2), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m64) + [bs8(value)]) addop("cmp%sss" % cond_name, [bs8(0x0f), bs8(0xc2), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32) + [bs8(value)]) addop("cmp%ssd" % cond_name, [bs8(0x0f), bs8(0xc2), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m32) + [bs8(value)]) addop("pshufb", [bs8(0x0f), bs8(0x38), bs8(0x00), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pshufb", [bs8(0x0f), bs8(0x38), bs8(0x00), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pshufd", [bs8(0x0f), bs8(0x70), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128) + [u08]) addop("pshuflw", [bs8(0x0f), bs8(0x70), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m128) + [u08]) addop("pshufhw", [bs8(0x0f), bs8(0x70), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m128) + [u08]) ### Convert ### SS = single precision ### SD = double precision ### ## SS -> SD ## addop("cvtdq2pd", [bs8(0x0f), bs8(0xe6), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("cvtdq2ps", [bs8(0x0f), bs8(0x5b), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvtpd2dq", [bs8(0x0f), bs8(0xe6), pref_f2] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvtpd2pi", [bs8(0x0f), bs8(0x2d), pref_66] + rmmod(mm_reg, rm_arg_xmm)) addop("cvtpd2ps", [bs8(0x0f), bs8(0x5a), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvtpi2pd", [bs8(0x0f), bs8(0x2a), pref_66] + rmmod(xmm_reg, rm_arg_mm_m64)) addop("cvtpi2ps", [bs8(0x0f), bs8(0x2a), no_xmm_pref] + rmmod(xmm_reg, rm_arg_mm_m64)) addop("cvtps2dq", [bs8(0x0f), bs8(0x5b), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvtps2pd", [bs8(0x0f), bs8(0x5a), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("cvtps2pi", [bs8(0x0f), bs8(0x2d), no_xmm_pref] + rmmod(mm_reg, rm_arg_xmm_m64)) addop("cvtsd2si", [bs8(0x0f), bs8(0x2d), pref_f2] + rmmod(reg, rm_arg_xmm_m64)) addop("cvtsd2ss", [bs8(0x0f), bs8(0x5a), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("cvtsi2sd", [bs8(0x0f), bs8(0x2a), pref_f2] + rmmod(xmm_reg, rm_arg)) addop("cvtsi2ss", [bs8(0x0f), bs8(0x2a), xmmreg, pref_f3] + rmmod(xmm_reg, rm_arg)) addop("cvtss2sd", [bs8(0x0f), bs8(0x5a), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("cvtss2si", [bs8(0x0f), bs8(0x2d), pref_f3] + rmmod(rmreg, rm_arg_xmm_m32)) addop("cvttpd2pi",[bs8(0x0f), bs8(0x2c), pref_66] + rmmod(mm_reg, rm_arg_xmm)) addop("cvttpd2dq",[bs8(0x0f), bs8(0xe6), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvttps2dq",[bs8(0x0f), bs8(0x5b), pref_f3] + rmmod(xmm_reg, rm_arg_xmm)) addop("cvttps2pi",[bs8(0x0f), bs8(0x2c), no_xmm_pref] + rmmod(mm_reg, rm_arg_xmm_m64)) addop("cvttsd2si",[bs8(0x0f), bs8(0x2c), pref_f2] + rmmod(reg, rm_arg_xmm_m64)) addop("cvttss2si",[bs8(0x0f), bs8(0x2c), pref_f3] + rmmod(reg, rm_arg_xmm_m32)) addop("palignr", [bs8(0x0f), bs8(0x73), bs8(0x0f), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64) + [u08], [mm_reg, rm_arg_mm_m64, u08]) addop("palignr", [bs8(0x0f), bs8(0x3a), bs8(0x0f), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128) + [u08], [xmm_reg, rm_arg_xmm_m128, u08]) addop("psrlq", [bs8(0x0f), bs8(0x73), no_xmm_pref] + rmmod(d2, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("psrlq", [bs8(0x0f), bs8(0x73), pref_66] + rmmod(d2, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psrlq", [bs8(0x0f), bs8(0xd3), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) addop("psrlq", [bs8(0x0f), bs8(0xd3), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("psrld", [bs8(0x0f), bs8(0x72), no_xmm_pref] + rmmod(d2, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("psrld", [bs8(0x0f), bs8(0x72), pref_66] + rmmod(d2, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psrld", [bs8(0x0f), bs8(0xd2), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) addop("psrld", [bs8(0x0f), bs8(0xd2), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("psrldq", [bs8(0x0f), bs8(0x73), pref_66] + rmmod(d3, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psrlw", [bs8(0x0f), bs8(0x71), no_xmm_pref] + rmmod(d2, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("psrlw", [bs8(0x0f), bs8(0x71), pref_66] + rmmod(d2, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psrlw", [bs8(0x0f), bs8(0xd1), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64), [mm_reg, rm_arg_mm_m64]) addop("psrlw", [bs8(0x0f), bs8(0xd1), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128), [xmm_reg, rm_arg_xmm_m128]) addop("psraw", [bs8(0x0f), bs8(0xe1), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64), [mm_reg, rm_arg_mm_m64]) addop("psraw", [bs8(0x0f), bs8(0xe1), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128), [xmm_reg, rm_arg_xmm_m128]) addop("psraw", [bs8(0x0f), bs8(0x71), no_xmm_pref] + rmmod(d4, rm_arg_mm_m64) + [u08], [rm_arg_mm_m64, u08]) addop("psraw", [bs8(0x0f), bs8(0x71), pref_66] + rmmod(d4, rm_arg_xmm_m128) + [u08], [rm_arg_xmm_m128, u08]) addop("psrad", [bs8(0x0f), bs8(0xe2), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64), [mm_reg, rm_arg_mm_m64]) addop("psrad", [bs8(0x0f), bs8(0xe2), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128), [xmm_reg, rm_arg_xmm_m128]) addop("psrad", [bs8(0x0f), bs8(0x72), no_xmm_pref] + rmmod(d4, rm_arg_mm_m64) + [u08], [rm_arg_mm_m64, u08]) addop("psrad", [bs8(0x0f), bs8(0x72), pref_66] + rmmod(d4, rm_arg_xmm_m128) + [u08], [rm_arg_xmm_m128, u08]) addop("psllq", [bs8(0x0f), bs8(0x73), no_xmm_pref] + rmmod(d6, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("psllq", [bs8(0x0f), bs8(0x73), pref_66] + rmmod(d6, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psllq", [bs8(0x0f), bs8(0xf3), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) addop("psllq", [bs8(0x0f), bs8(0xf3), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("pslld", [bs8(0x0f), bs8(0x72), no_xmm_pref] + rmmod(d6, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("pslld", [bs8(0x0f), bs8(0x72), pref_66] + rmmod(d6, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("pslld", [bs8(0x0f), bs8(0xf2), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) addop("pslld", [bs8(0x0f), bs8(0xf2), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("psllw", [bs8(0x0f), bs8(0x71), no_xmm_pref] + rmmod(d6, rm_arg_mm) + [u08], [rm_arg_mm, u08]) addop("psllw", [bs8(0x0f), bs8(0x71), pref_66] + rmmod(d6, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("psllw", [bs8(0x0f), bs8(0xf1), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm), [mm_reg, rm_arg_mm]) addop("psllw", [bs8(0x0f), bs8(0xf1), pref_66] + rmmod(xmm_reg, rm_arg_xmm), [xmm_reg, rm_arg_xmm]) addop("pslldq", [bs8(0x0f), bs8(0x73), pref_66] + rmmod(d7, rm_arg_xmm) + [u08], [rm_arg_xmm, u08]) addop("pmaxub", [bs8(0x0f), bs8(0xde), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pmaxub", [bs8(0x0f), bs8(0xde), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pmaxuw", [bs8(0x0f), bs8(0x38), bs8(0x3e), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pmaxud", [bs8(0x0f), bs8(0x38), bs8(0x3f), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pmaxsw", [bs8(0x0f), bs8(0xee), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmaxsw", [bs8(0x0f), bs8(0xee), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pminub", [bs8(0x0f), bs8(0xda), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pminub", [bs8(0x0f), bs8(0xda), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pminuw", [bs8(0x0f), bs8(0x38), bs8(0x3a), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pminud", [bs8(0x0f), bs8(0x38), bs8(0x3b), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpeqb", [bs8(0x0f), bs8(0x74), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpeqb", [bs8(0x0f), bs8(0x74), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpeqw", [bs8(0x0f), bs8(0x75), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpeqw", [bs8(0x0f), bs8(0x75), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpeqd", [bs8(0x0f), bs8(0x76), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpeqd", [bs8(0x0f), bs8(0x76), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpgtb", [bs8(0x0f), bs8(0x64), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpgtb", [bs8(0x0f), bs8(0x64), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpgtw", [bs8(0x0f), bs8(0x65), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpgtw", [bs8(0x0f), bs8(0x65), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpgtd", [bs8(0x0f), bs8(0x66), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpgtd", [bs8(0x0f), bs8(0x66), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpeqq", [bs8(0x0f), bs8(0x38), bs8(0x29), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pcmpgtq", [bs8(0x0f), bs8(0x38), bs8(0x37), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpckhbw", [bs8(0x0f), bs8(0x68), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpckhbw", [bs8(0x0f), bs8(0x68), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpckhwd", [bs8(0x0f), bs8(0x69), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpckhwd", [bs8(0x0f), bs8(0x69), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpckhdq", [bs8(0x0f), bs8(0x6a), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpckhdq", [bs8(0x0f), bs8(0x6a), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpckhqdq", [bs8(0x0f), bs8(0x6d), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpcklbw", [bs8(0x0f), bs8(0x60), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpcklbw", [bs8(0x0f), bs8(0x60), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpcklwd", [bs8(0x0f), bs8(0x61), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpcklwd", [bs8(0x0f), bs8(0x61), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpckldq", [bs8(0x0f), bs8(0x62), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("punpckldq", [bs8(0x0f), bs8(0x62), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("punpcklqdq", [bs8(0x0f), bs8(0x6c), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("unpckhps", [bs8(0x0f), bs8(0x15), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("unpckhpd", [bs8(0x0f), bs8(0x15), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("unpcklps", [bs8(0x0f), bs8(0x14), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("unpcklpd", [bs8(0x0f), bs8(0x14), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("pinsrb", [bs8(0x0f), bs8(0x3a), bs8(0x20), pref_66] + rmmod(xmm_reg, rm_arg_reg_m08) + [u08]) addop("pinsrd", [bs8(0x0f), bs8(0x3a), bs8(0x22), pref_66, bs_opmode32] + rmmod(xmm_reg, rm_arg) + [u08]) addop("pinsrq", [bs8(0x0f), bs8(0x3a), bs8(0x22), pref_66] + rmmod(xmm_reg, rm_arg_m64) + [bs_opmode64] + [u08]) addop("pinsrw", [bs8(0x0f), bs8(0xc4), no_xmm_pref] + rmmod(mm_reg, rm_arg_reg_m16) + [u08]) addop("pinsrw", [bs8(0x0f), bs8(0xc4), pref_66] + rmmod(xmm_reg, rm_arg_reg_m16) + [u08]) addop("pextrb", [bs8(0x0f), bs8(0x3a), bs8(0x14), pref_66] + rmmod(xmm_reg, rm_arg_reg_m08) + [u08], [rm_arg_reg_m08, xmm_reg, u08]) addop("pextrd", [bs8(0x0f), bs8(0x3a), bs8(0x16), pref_66, bs_opmode32] + rmmod(xmm_reg, rm_arg) + [u08], [rm_arg, xmm_reg, u08]) addop("pextrq", [bs8(0x0f), bs8(0x3a), bs8(0x16), pref_66] + rmmod(xmm_reg, rm_arg_m64) + [bs_opmode64] + [u08], [rm_arg_m64, xmm_reg, u08]) addop("pextrw", [bs8(0x0f), bs8(0x3a), bs8(0x15), pref_66] + rmmod(xmm_reg, rm_arg_reg_m16) + [u08], [rm_arg_reg_m16, xmm_reg, u08]) addop("pextrw", [bs8(0x0f), bs8(0xc5), no_xmm_pref] + rmmod(rmreg, rm_arg_mm) + [u08], [rmreg, rm_arg_mm, u08]) addop("pextrw", [bs8(0x0f), bs8(0xc5), pref_66] + rmmod(rmreg, rm_arg_xmm) + [u08], [rmreg, rm_arg_xmm, u08]) addop("sqrtpd", [bs8(0x0f), bs8(0x51), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("sqrtps", [bs8(0x0f), bs8(0x51), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm)) addop("sqrtsd", [bs8(0x0f), bs8(0x51), pref_f2] + rmmod(xmm_reg, rm_arg_xmm_m64)) addop("sqrtss", [bs8(0x0f), bs8(0x51), pref_f3] + rmmod(xmm_reg, rm_arg_xmm_m32)) addop("pmovmskb", [bs8(0x0f), bs8(0xd7), no_xmm_pref] + rmmod(reg_modrm, rm_arg_mm_reg)) addop("pmovmskb", [bs8(0x0f), bs8(0xd7), pref_66] + rmmod(reg_modrm, rm_arg_xmm_reg)) addop("shufps", [bs8(0x0f), bs8(0xc6), no_xmm_pref] + rmmod(xmm_reg, rm_arg_xmm) + [u08]) addop("shufpd", [bs8(0x0f), bs8(0xc6), pref_66] + rmmod(xmm_reg, rm_arg_xmm) + [u08]) addop("aesenc", [bs8(0x0f), bs8(0x38), bs8(0xdc), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("aesdec", [bs8(0x0f), bs8(0x38), bs8(0xde), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("aesenclast", [bs8(0x0f), bs8(0x38), bs8(0xdd), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("aesdeclast", [bs8(0x0f), bs8(0x38), bs8(0xdf), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("packsswb", [bs8(0x0f), bs8(0x63), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("packsswb", [bs8(0x0f), bs8(0x63), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("packssdw", [bs8(0x0f), bs8(0x6b), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("packssdw", [bs8(0x0f), bs8(0x6b), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("packuswb", [bs8(0x0f), bs8(0x67), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("packuswb", [bs8(0x0f), bs8(0x67), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pmullw", [bs8(0x0f), bs8(0xd5), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmullw", [bs8(0x0f), bs8(0xd5), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pmulhuw", [bs8(0x0f), bs8(0xe4), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmulhuw", [bs8(0x0f), bs8(0xe4), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pmulhw", [bs8(0x0f), bs8(0xe5), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmulhw", [bs8(0x0f), bs8(0xe5), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pmuludq", [bs8(0x0f), bs8(0xf4), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmuludq", [bs8(0x0f), bs8(0xf4), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("psubusb", [bs8(0x0f), bs8(0xd8), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("psubusb", [bs8(0x0f), bs8(0xd8), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("psubusw", [bs8(0x0f), bs8(0xd9), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("psubusw", [bs8(0x0f), bs8(0xd9), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("psubsb", [bs8(0x0f), bs8(0xe8), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("psubsb", [bs8(0x0f), bs8(0xe8), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("psubsw", [bs8(0x0f), bs8(0xe9), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("psubsw", [bs8(0x0f), bs8(0xe9), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("paddusb", [bs8(0x0f), bs8(0xdc), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("paddusb", [bs8(0x0f), bs8(0xdc), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("paddusw", [bs8(0x0f), bs8(0xdd), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("paddusw", [bs8(0x0f), bs8(0xdd), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("paddsb", [bs8(0x0f), bs8(0xec), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("paddsb", [bs8(0x0f), bs8(0xec), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("paddsw", [bs8(0x0f), bs8(0xed), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("paddsw", [bs8(0x0f), bs8(0xed), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pmaddwd", [bs8(0x0f), bs8(0xf5), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pmaddwd", [bs8(0x0f), bs8(0xf5), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("psadbw", [bs8(0x0f), bs8(0xf6), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("psadbw", [bs8(0x0f), bs8(0xf6), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pavgb", [bs8(0x0f), bs8(0xe0), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pavgb", [bs8(0x0f), bs8(0xe0), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pavgw", [bs8(0x0f), bs8(0xe3), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_m64)) addop("pavgw", [bs8(0x0f), bs8(0xe3), pref_66] + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("maskmovq", [bs8(0x0f), bs8(0xf7), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm_reg)) addop("maskmovdqu", [bs8(0x0f), bs8(0xf7), pref_66] + rmmod(xmm_reg, rm_arg_xmm_reg)) addop("emms", [bs8(0x0f), bs8(0x77)]) addop("incssp", [pref_f3, bs8(0x0f), bs8(0xae)] + rmmod(d5)) addop("rdssp", [pref_f3, bs8(0x0f), bs8(0x1e)] + rmmod(d1, modrm=mod_reg)) addop("saveprevssp", [pref_f3, bs8(0x0f), bs8(0x01), bs8(0xea)]) addop("rstorssp", [pref_f3, bs8(0x0f), bs8(0x01)] + rmmod(d5, rm_arg_xmm, modrm=mod_mem)) addop("wrss", [bs8(0x0f), bs8(0x38), bs8(0xf6)] + rmmod(rmreg, rm_arg), [rm_arg, rmreg]) addop("wruss", [pref_66, bs8(0x0f), bs8(0x38), bs8(0xf5)] + rmmod(rmreg, rm_arg), [rm_arg, rmreg]) addop("setssbsy", [pref_f3, bs8(0x0f), bs8(0x01), bs8(0xe8)]) addop("clrssbsy", [pref_f3, bs8(0x0f), bs8(0xae)] + rmmod(d6, rm_arg_xmm)) addop("endbr64", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfa)]) addop("endbr32", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfb)]) mn_x86.bintree = factor_one_bit(mn_x86.bintree) # mn_x86.bintree = factor_fields_all(mn_x86.bintree) """ mod reg r/m XX XXX XXX """ def print_size(e): print(e, e.size) return e