diff options
| author | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
|---|---|---|
| committer | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
| commit | 579cf1d03fb932083e6317967d1613d5c2587fb6 (patch) | |
| tree | 629f039935382a2a7391bce9253f6c9968159049 /src/miasm/arch/x86/arch.py | |
| parent | 51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff) | |
| download | focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip | |
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/arch/x86/arch.py')
| -rw-r--r-- | src/miasm/arch/x86/arch.py | 4878 |
1 files changed, 4878 insertions, 0 deletions
diff --git a/src/miasm/arch/x86/arch.py b/src/miasm/arch/x86/arch.py new file mode 100644 index 00000000..5464a779 --- /dev/null +++ b/src/miasm/arch/x86/arch.py @@ -0,0 +1,4878 @@ +#-*- 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_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') + +MEMPREFIX2SIZE = {'BYTE': 8, 'WORD': 16, 'DWORD': 32, + 'QWORD': 64, 'TBYTE': 80, 'XMMWORD': 128} + +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) +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 +) + +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 = '<font color="%s">%s</font>' % (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_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 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): + 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 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 + + 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 + + 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) + 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_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_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") + + +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') + + +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)) + +## 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)) + +## 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 |