Пример #1
0
    def action_instr(toks):
        i = instruction(b"")
        i.mnemonic = toks[0].upper()
        # Remove prefixes
        if i.mnemonic in ("REP", "REPZ", "REPNZ", "REPE", "REPNE", "LOCK"):
            if i.mnemonic in ("REP", "REPZ", "REPE"):
                i.misc.update({"pfx": ["rep", None, None, None], "rep": True})
            if i.mnemonic in ("REPNZ", "REPNE"):
                i.misc.update({
                    "pfx": ["repne", None, None, None],
                    "repne": True
                })
            if i.mnemonic in ("LOCK", ):
                i.misc.update({
                    "pfx": ["lock", None, None, None],
                    "lock": True
                })
            del toks[0]  # toks.pop(0) is broken for pyparsing 2.0.2
            # https://bugs.launchpad.net/ubuntu/+source/pyparsing/+bug/1381564
            i.mnemonic = toks[0].upper()
        # Get operands
        if len(toks) > 1:
            i.operands = list(reversed(toks[1][0:]))
        # Convert mnemonics, set operand sizes
        if i.mnemonic in (
                "CALLL",
                "CALLQ",
                "JMPL",
                "JMPQ",
                "RETL",
                "RETQ",
                "BSWAPL",
                "BSWAPQ",
                "FUCOMPI",
        ):
            # clang on MacOS X
            if i.mnemonic[-1] in ("L", "Q"):
                i.mnemonic = i.mnemonic[:-1]
            else:
                i.mnemonic = "FUCOMIP"
        mnemo = i.mnemonic.lower()
        if i.mnemonic in ("CALL", "JMP"):
            if len(i.operands) == 2 and i.operands[1] == "*":
                i.operands.pop()
                if not i.operands[0]._is_mem and not i.operands[0]._is_reg:
                    i.operands[0] = expressions.mem(i.operands[0],
                                                    cpu_addrsize)
            else:
                if i.operands[0]._is_mem:
                    i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
        elif i.mnemonic.startswith(("J", "SET", "CMOV")):
            for pfx in ("J", "SET", "CMOV"):
                if i.mnemonic.startswith(pfx):
                    break
            for i.cond in CONDITION_CODES.values():
                if i.mnemonic[len(pfx):] in i.cond[0].split("/"):
                    break
            else:
                if pfx == "CMOV" and i.mnemonic[-1] in ("W", "L", "Q"):
                    # clang on MacOS X
                    for i.cond in CONDITION_CODES.values():
                        if i.mnemonic[len(pfx):-1] in i.cond[0].split("/"):
                            break
                    else:
                        NEVER
                elif pfx == "SET" and i.mnemonic[-1] == "B":
                    # gcc 3.2.3
                    for i.cond in CONDITION_CODES.values():
                        if i.mnemonic[len(pfx):-1] in i.cond[0].split("/"):
                            break
                    else:
                        NEVER
                else:
                    NEVER
            i.mnemonic = pfx + "cc"
            if pfx == "J":
                i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
            if pfx == "CMOV":
                if i.operands[0]._is_mem:
                    i.operands[0].size = i.operands[1].size
                if i.operands[1]._is_mem:
                    i.operands[1].size = i.operands[0].size
        elif mnemo in att_mnemo_correspondance:
            i.mnemonic = att_mnemo_correspondance[mnemo].upper()
            if i.mnemonic in ("CBW", "CWD", "IRET"):
                i.misc.update({
                    "opdsz": 16,
                    "pfx": [None, None, "opdsz", None]
                })
        elif mnemo[-1] == "w" and mnemo[:-1] in mnemo_string_rep:
            i.misc.update({"opdsz": 16, "pfx": [None, None, "opdsz", None]})
        elif i.mnemonic == "CMPSD" and len(i.operands) == 0:
            # String cmpsd, different from the SSE cmp*sd, has no arguments
            pass
        elif i.mnemonic == "MOVSL":
            # String movsd, different from the SSE movsd
            # Has no arguments
            i.mnemonic = "MOVSD"
            assert len(i.operands) == 0
        elif i.mnemonic[:-2] in ("MOVS", "MOVZ"):
            i.misc["opdsz"], sz = {
                "BW": (8, 16),
                "BL": (8, 32),
                "BQ": (8, 64),
                "WL": (16, 32),
                "WQ": (16, 64),
                "LQ": (32, 64),
            }[i.mnemonic[-2:]]
            if i.operands[1]._is_mem:
                i.operands[1].size = i.misc["opdsz"]
            assert i.operands[0].size == sz
            i.mnemonic = i.mnemonic[:-2] + "X"
        elif i.mnemonic == "MOVD":
            pass
        elif i.mnemonic in (
                "FLDCW",
                "FSTCW",
                "FNSTCW",
        ):
            assert i.operands[0]._is_mem
            i.operands[0].size = 16
        elif i.mnemonic == "CMPXCHG":
            if i.operands[0]._is_mem:
                i.operands[0].size = i.operands[1].size
        elif i.mnemonic == "CMPXCHG8B":
            if i.operands[0]._is_mem:
                i.operands[0].size = 64
        elif i.mnemonic == "CMPXCHG16B":
            if i.operands[0]._is_mem:
                i.operands[0].size = 128
        elif i.mnemonic in mmx_with_suffix2 and len(i.operands):
            if i.mnemonic.endswith("SS"):
                if i.operands[1]._is_mem:
                    i.operands[1].size = 32
            elif i.mnemonic.endswith("SD"):
                if i.operands[0]._is_mem:
                    i.operands[0].size = 64
                if i.operands[1]._is_mem:
                    i.operands[1].size = 64
            else:
                if i.operands[1]._is_mem:
                    i.operands[1].size = 128
        elif i.mnemonic in (
                "CVTSI2SS",
                "CVTSI2SD",
                "CVTTSS2SI",
                "CVTTSS2SIL",
                "CVTTSS2SIQ",
        ):
            if i.operands[1]._is_mem:
                i.operands[1].size = 32
            # gcc 4.9.2 generates cvttss2siq %xmm0, %r15
            # which is useless, because the size of the output is
            # determined by the output register
            if i.mnemonic[-1] in "LQ":
                i.mnemonic = i.mnemonic[:-1]
        elif i.mnemonic in (
                "MOVLPD",
                "MOVLPS",
                "MOVHPD",
                "MOVHPS",
                "MOVDDUP",
                "PSHUFW",
                "CVTSD2SS",
                "CVTSD2SI",
                "CVTTSD2SI",
                "CVTTSD2SIL",
                "CVTTSD2SIQ",
                "CVTPI2PD",
                "CVTPI2PS",
                "CVTPS2PI",
                "CVTPS2PD",
                "CVTDQ2PD",
        ):
            if i.operands[0]._is_mem:
                i.operands[0].size = 64
            if i.operands[1]._is_mem:
                i.operands[1].size = 64
            if i.mnemonic[-1] in "LQ":
                i.mnemonic = i.mnemonic[:-1]
        elif i.mnemonic in (
                "PSHUFD",
                "PSHUFLW",
                "PSHUFHW",
                "MOVDQA",
                "MOVDQU",
                "MOVSLDUP",
                "MOVSHDUP",
                "MOVAPD",
                "MOVAPS",
                "MOVUPD",
                "MOVUPS",
                "CVTPD2PS",
                "CVTPD2PI",
                "CVTPD2DQ",
                "CVTTPD2DQ",
                "CVTTPD2PI",
                "CVTPS2DQ",
                "CVTTPS2PI",
                "CVTTPS2DQ",
                "CVTDQ2PS",
                "PUNPCKHQDQ",
        ):
            if i.operands[0]._is_mem:
                i.operands[0].size = 128
            if i.operands[1]._is_mem:
                i.operands[1].size = 128
        elif i.mnemonic in mmx_with_suffix1 or i.mnemonic in (
                "PSHUFB",
                "PAND",
                "PANDN",
                "POR",
                "PXOR",
        ):
            if i.operands[1]._is_mem:
                i.operands[1].size = i.operands[0].size
        elif i.mnemonic == "MOVABSQ":
            # gcc generates 'movabsq $cst, %reg' instead of 'movq $cst, %reg'
            i.mnemonic = "MOV"
            for _ in i.operands:
                if _._is_mem:
                    _.size = 64
                if _._is_cst:
                    _.size = 64
                    _.v &= _.mask
                if _._is_lab:
                    _.size = 64
        else:
            for _ in att_mnemo_suffix_one_ptr:
                if mnemo[:-1] != _:
                    continue
                # Detect MMX MOVQ instruction, not 64-bit register MOV for x64
                if (i.mnemonic == "MOVQ" and i.operands[1]._is_reg
                        and "mm" in i.operands[1].ref):
                    if i.operands[0]._is_mem:
                        i.operands[0].size = 64
                    break
                if (i.mnemonic == "MOVQ" and i.operands[0]._is_reg
                        and "mm" in i.operands[0].ref):
                    if i.operands[1]._is_mem:
                        i.operands[1].size = 64
                    break
                i.mnemonic = _.upper()
                sz = {"b": 8, "w": 16, "l": 32, "q": 64}[mnemo[-1]]
                if "q" == mnemo[-1]:
                    i.misc.update({"REX": (1, 0, 0, 0)})
                if "w" == mnemo[-1]:
                    i.misc.update({
                        "opdsz": 16,
                        "pfx": [None, None, "opdsz", None]
                    })

                def set_size(e, sz):
                    if e._is_mem:
                        e.size = sz
                    if e._is_cst:
                        e.size = sz
                        e.v &= e.mask
                    if e._is_lab:
                        e.size = sz
                    if e._is_eqn:
                        e.size = sz
                        if e.l is not None:
                            set_size(e.l, sz)
                        set_size(e.r, sz)

                for _ in i.operands:
                    set_size(_, sz)
            for _ in att_mnemo_suffix_one_iflt:
                if mnemo[:-1] != _:
                    continue
                i.mnemonic = _.upper()
                sz = {"s": 16, "l": 32, "q": 64}[mnemo[-1]]
                for _ in i.operands:
                    if _._is_mem:
                        _.size = sz
            if mnemo[-2:] == "ll" and mnemo[:-2] in att_mnemo_suffix_one_iflt:
                # clang on MacOS X
                i.mnemonic = mnemo[:-2].upper()
                for _ in i.operands:
                    if _._is_mem:
                        _.size = 64
            for _ in att_mnemo_float_optional_suffix:
                if mnemo[:-1] != _:
                    continue
                if mnemo[-1] in ("i", "p", "r", "z", "1"):
                    continue
                i.mnemonic = _.upper()
                sz = {"s": 32, "l": 64, "t": 80}[mnemo[-1]]
                for _ in i.operands:
                    if _._is_mem:
                        _.size = sz
        # Implicit operands
        if i.mnemonic in ("AAD", "AAM"):
            if len(i.operands) == 0:
                i.operands.append(expressions.cst(10, 8))
            else:
                i.operands[0].size = 8
        elif (i.mnemonic in ("SAL", "SAR", "SHL", "SHR", "ROR", "ROL")
              and len(i.operands) == 1):
            i.operands.append(expressions.cst(1, 32))
        elif i.mnemonic in ("SHLD", "SHRD") and len(i.operands) == 2:
            i.operands.append(env.__dict__["cl"])
        elif (i.mnemonic.startswith("CMP") and i.mnemonic.endswith(
            ("PS", "PD", "SD", "SS")) and len(i.operands)):
            idx = mnemo_sse_cmp_predicate.index(i.mnemonic[3:-2].lower())
            i.operands.append(expressions.cst(idx))
            i.mnemonic = i.mnemonic[:3] + i.mnemonic[-2:]
        elif (i.mnemonic in (
                "FADD",
                "FSUB",
                "FSUBR",
                "FMUL",
                "FDIV",
                "FDIVR",
                "FCOMI",
                "FCOMIP",
                "FUCOMI",
                "FUCOMIP",
        ) and len(i.operands) == 1 and not i.operands[0]._is_mem):
            i.operands.insert(0, env.st(0))
        elif (i.mnemonic in (
                "FADDP",
                "FSUBP",
                "FSUBRP",
                "FMULP",
                "FDIVP",
                "FDIVRP",
        ) and len(i.operands) == 1 and not i.operands[0]._is_mem):
            i.operands.append(env.st(0))
        elif (i.mnemonic in (
                "FCOM",
                "FCOMP",
                "FUCOM",
                "FUCOMP",
        ) and len(i.operands) == 0):
            i.operands.append(env.st(1))
        return i
Пример #2
0
 def action_instr(toks):
     i = instruction('')
     i.mnemonic = toks[0].upper()
     # Remove prefixes
     if i.mnemonic in ('REP','REPZ','REPNZ','REPE','REPNE'):
         if i.mnemonic in ('REP','REPZ','REPE'):
             i.misc.update({'pfx':['rep',   None,None,None], 'rep':True})
         if i.mnemonic in ('REPNZ','REPNE'):
             i.misc.update({'pfx':['repne',None,None, None], 'repne':True})
         toks.pop(0)
         i.mnemonic = toks[0].upper()
     # Get operands
     if len(toks) > 1:
         i.operands = list(reversed(toks[1][0:]))
     # Convert mnemonics, set operand sizes
     if i.mnemonic in ('CALLL','CALLQ','JMPL','JMPQ','RETL','RETQ',
                       'BSWAPL','FUCOMPI'):
         # clang on MacOS X
         if i.mnemonic[-1] in ('L','Q'):
             i.mnemonic = i.mnemonic[:-1]
         else:
             i.mnemonic = 'FUCOMIP'
     mnemo = i.mnemonic.lower()
     if i.mnemonic in ('CALL','JMP'):
         if len(i.operands) == 2 and i.operands[1] == '*':
             i.operands.pop()
             if not i.operands[0]._is_mem and \
                not i.operands[0]._is_reg:
                 i.operands[0] = expressions.mem(i.operands[0],att_syntax.cpu_addrsize)
         else:
             if i.operands[0]._is_mem:
                 i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
     elif i.mnemonic.startswith(('J','SET','CMOV')):
         for pfx in ('J','SET','CMOV'):
             if i.mnemonic.startswith(pfx): break
         for i.cond in att_syntax.CONDITION_CODES.values():
             if i.mnemonic[len(pfx):] in i.cond[0].split('/'): break
         else:
             if pfx == 'CMOV' and i.mnemonic[-1] in ('W','L','Q'):
                 # clang on MacOS X
                 for i.cond in att_syntax.CONDITION_CODES.values():
                     if i.mnemonic[len(pfx):-1] in i.cond[0].split('/'):
                         break
                 else:
                     NEVER
             elif pfx == 'SET' and i.mnemonic[-1] == 'B':
                 # gcc 3.2.3
                 for i.cond in att_syntax.CONDITION_CODES.values():
                     if i.mnemonic[len(pfx):-1] in i.cond[0].split('/'):
                         break
                 else:
                     NEVER
             else:
                 NEVER
         i.mnemonic = pfx+'cc'
         if pfx == 'J':
             i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
         if pfx == 'CMOV':
             if i.operands[0]._is_mem: i.operands[0].size = i.operands[1].size
             if i.operands[1]._is_mem: i.operands[1].size = i.operands[0].size
     elif mnemo in att_mnemo_correspondance:
         i.mnemonic = att_mnemo_correspondance[mnemo].upper()
         if i.mnemonic in ('CBW','CWD','IRET'):
             i.misc.update({'opdsz':16, 'pfx':[None, None, 'opdsz', None]})
     elif mnemo[-1] == 'w' and mnemo[:-1] in mnemo_string_rep:
         i.misc.update({'opdsz':16, 'pfx':[None, None, 'opdsz', None]})
     elif i.mnemonic == 'CMPSD' and len(i.operands) == 0:
         # String cmpsd, different from the SSE cmp*sd, has no arguments
         pass
     elif i.mnemonic == 'MOVSL':
         # String movsd, different from the SSE movsd
         # Has no arguments
         i.mnemonic = 'MOVSD'
         assert len(i.operands) == 0
     elif i.mnemonic[:-2] in ('MOVS','MOVZ'):
         i.misc['opdsz'], sz = {
             'BW': ( 8,16),
             'BL': ( 8,32),
             'BQ': ( 8,64),
             'WL': (16,32),
             'WQ': (16,64),
             'LQ': (32,64),
             }[i.mnemonic[-2:]]
         if i.operands[1]._is_mem:
             i.operands[1].size = i.misc['opdsz']
         assert i.operands[0].size == sz
         i.mnemonic = i.mnemonic[:-2] + 'X'
     elif i.mnemonic == 'MOVD':
         pass
     elif i.mnemonic in (
         'FLDCW', 'FSTCW', 'FNSTCW',
         ):
         assert i.operands[0]._is_mem
         i.operands[0].size = 16
     elif i.mnemonic in att_syntax.mmx_with_suffix2 and len(i.operands):
         if i.mnemonic.endswith('SS'):
             if i.operands[1]._is_mem: i.operands[1].size = 32
         elif i.mnemonic.endswith('SD'):
             if i.operands[0]._is_mem: i.operands[0].size = 64
             if i.operands[1]._is_mem: i.operands[1].size = 64
         else:
             if i.operands[1]._is_mem: i.operands[1].size = 128
     elif i.mnemonic in (
         'CVTSI2SS',
         ):
         if i.operands[1]._is_mem: i.operands[1].size = 32
     elif i.mnemonic in (
         'MOVLPD','MOVLPS','MOVHPD','MOVHPS',
         'MOVDDUP', 'PSHUFW',
         'CVTSD2SS','CVTSD2SI','CVTTSD2SI',
         'CVTPI2PD','CVTPI2PS','CVTPS2PI','CVTPS2PD','CVTDQ2PD',
         ):
         if i.operands[0]._is_mem: i.operands[0].size = 64
         if i.operands[1]._is_mem: i.operands[1].size = 64
     elif i.mnemonic in (
         'PSHUFD','PSHUFLW','PSHUFHW',
         'MOVDQA','MOVDQU','MOVSLDUP','MOVSHDUP',
         'MOVAPD','MOVAPS','MOVUPD','MOVUPS',
         'CVTPD2PS','CVTPD2PI','CVTPD2DQ','CVTTPD2DQ','CVTTPD2PI',
         'CVTPS2DQ','CVTTPS2PI','CVTTPS2DQ','CVTDQ2PS',
         'PUNPCKHQDQ',
         ):
         if i.operands[0]._is_mem: i.operands[0].size = 128
         if i.operands[1]._is_mem: i.operands[1].size = 128
     elif i.mnemonic in att_syntax.mmx_with_suffix1 or i.mnemonic in (
         'PSHUFB',
         'PAND','PANDN','POR','PXOR',
         ):
         if i.operands[1]._is_mem: i.operands[1].size = i.operands[0].size
     elif i.mnemonic == 'MOVABSQ':
         # gcc generates 'movabsq $cst, %reg' instead of 'movq $cst, %reg'
         i.mnemonic = 'MOV'
         for _ in i.operands:
             if _._is_mem: _.size = 64
             if _._is_cst: _.size = 64; _.v &= _.mask
             if _._is_lab: _.size = 64
     else:
         for _ in att_mnemo_suffix_one_ptr:
             if mnemo[:-1] != _: continue
             # Detect MMX MOVQ instruction, not 64-bit register MOV for x64
             if i.mnemonic == 'MOVQ' \
                     and i.operands[1]._is_reg \
                     and 'mm' in i.operands[1].ref:
                 if i.operands[0]._is_mem: i.operands[0].size = 64
                 break
             if i.mnemonic == 'MOVQ' \
                     and i.operands[0]._is_reg \
                     and 'mm' in i.operands[0].ref:
                 if i.operands[1]._is_mem: i.operands[1].size = 64
                 break
             i.mnemonic = _.upper()
             sz = {'b':8, 'w':16, 'l':32, 'q':64}[mnemo[-1]]
             for _ in i.operands:
                 if _._is_mem: _.size = sz
                 if _._is_cst: _.size = sz; _.v &= _.mask
                 if _._is_lab: _.size = sz
         for _ in att_mnemo_suffix_one_iflt:
             if mnemo[:-1] != _: continue
             i.mnemonic = _.upper()
             sz = {'s':16, 'l':32, 'q':64}[mnemo[-1]]
             for _ in i.operands:
                 if _._is_mem: _.size = sz
         if mnemo[-2:] == 'll' and mnemo[:-2] in att_mnemo_suffix_one_iflt:
             # clang on MacOS X
             i.mnemonic = mnemo[:-2].upper()
             for _ in i.operands:
                 if _._is_mem: _.size = 64
         for _ in att_mnemo_float_optional_suffix:
             if mnemo[:-1] != _: continue
             if mnemo[-1] in ('p','r','z','1'): continue
             i.mnemonic = _.upper()
             sz = {'s':32, 'l':64, 't':80}[mnemo[-1]]
             for _ in i.operands:
                 if _._is_mem: _.size = sz
     # Implicit operands
     if i.mnemonic in ('AAD','AAM'):
         if len(i.operands) == 0:
             i.operands.append(expressions.cst(10,8))
         else:
             i.operands[0].size = 8
     elif i.mnemonic in ('SAL','SAR','SHL','SHR','ROR','ROL') \
             and len(i.operands) == 1:
         i.operands.append(expressions.cst(1,32))
     elif i.mnemonic.startswith('CMP') \
             and i.mnemonic.endswith(('PS','PD','SD','SS')) \
             and len(i.operands):
         idx = mnemo_sse_cmp_predicate.index(i.mnemonic[3:-2].lower())
         i.operands.append(expressions.cst(idx))
         i.mnemonic = i.mnemonic[:3] + i.mnemonic[-2:]
     return i
Пример #3
0
    def action_instr(toks):
        i = instruction(b'')
        i.mnemonic = toks[0].upper()
        # Remove prefixes
        if i.mnemonic in ('REP', 'REPZ', 'REPNZ', 'REPE', 'REPNE', 'LOCK'):
            if i.mnemonic in ('REP', 'REPZ', 'REPE'):
                i.misc.update({'pfx': ['rep', None, None, None], 'rep': True})
            if i.mnemonic in ('REPNZ', 'REPNE'):
                i.misc.update({
                    'pfx': ['repne', None, None, None],
                    'repne': True
                })
            if i.mnemonic in ('LOCK', ):
                i.misc.update({
                    'pfx': ['lock', None, None, None],
                    'lock': True
                })
            del toks[0]  # toks.pop(0) is broken for pyparsing 2.0.2
            # https://bugs.launchpad.net/ubuntu/+source/pyparsing/+bug/1381564
            i.mnemonic = toks[0].upper()
        # Get operands
        if len(toks) > 1:
            i.operands = list(reversed(toks[1][0:]))
        # Convert mnemonics, set operand sizes
        if i.mnemonic in ('CALLL', 'CALLQ', 'JMPL', 'JMPQ', 'RETL', 'RETQ',
                          'BSWAPL', 'BSWAPQ', 'FUCOMPI'):
            # clang on MacOS X
            if i.mnemonic[-1] in ('L', 'Q'):
                i.mnemonic = i.mnemonic[:-1]
            else:
                i.mnemonic = 'FUCOMIP'
        mnemo = i.mnemonic.lower()
        if i.mnemonic in ('CALL', 'JMP'):
            if len(i.operands) == 2 and i.operands[1] == '*':
                i.operands.pop()
                if not i.operands[0]._is_mem and \
                   not i.operands[0]._is_reg:
                    i.operands[0] = expressions.mem(i.operands[0],
                                                    cpu_addrsize)
            else:
                if i.operands[0]._is_mem:
                    i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
        elif i.mnemonic.startswith(('J', 'SET', 'CMOV')):
            for pfx in ('J', 'SET', 'CMOV'):
                if i.mnemonic.startswith(pfx): break
            for i.cond in CONDITION_CODES.values():
                if i.mnemonic[len(pfx):] in i.cond[0].split('/'): break
            else:
                if pfx == 'CMOV' and i.mnemonic[-1] in ('W', 'L', 'Q'):
                    # clang on MacOS X
                    for i.cond in CONDITION_CODES.values():
                        if i.mnemonic[len(pfx):-1] in i.cond[0].split('/'):
                            break
                    else:
                        NEVER
                elif pfx == 'SET' and i.mnemonic[-1] == 'B':
                    # gcc 3.2.3
                    for i.cond in CONDITION_CODES.values():
                        if i.mnemonic[len(pfx):-1] in i.cond[0].split('/'):
                            break
                    else:
                        NEVER
                else:
                    NEVER
            i.mnemonic = pfx + 'cc'
            if pfx == 'J':
                i.operands[0] = i.operands[0].a.base + i.operands[0].a.disp
            if pfx == 'CMOV':
                if i.operands[0]._is_mem:
                    i.operands[0].size = i.operands[1].size
                if i.operands[1]._is_mem:
                    i.operands[1].size = i.operands[0].size
        elif mnemo in att_mnemo_correspondance:
            i.mnemonic = att_mnemo_correspondance[mnemo].upper()
            if i.mnemonic in ('CBW', 'CWD', 'IRET'):
                i.misc.update({
                    'opdsz': 16,
                    'pfx': [None, None, 'opdsz', None]
                })
        elif mnemo[-1] == 'w' and mnemo[:-1] in mnemo_string_rep:
            i.misc.update({'opdsz': 16, 'pfx': [None, None, 'opdsz', None]})
        elif i.mnemonic == 'CMPSD' and len(i.operands) == 0:
            # String cmpsd, different from the SSE cmp*sd, has no arguments
            pass
        elif i.mnemonic == 'MOVSL':
            # String movsd, different from the SSE movsd
            # Has no arguments
            i.mnemonic = 'MOVSD'
            assert len(i.operands) == 0
        elif i.mnemonic[:-2] in ('MOVS', 'MOVZ'):
            i.misc['opdsz'], sz = {
                'BW': (8, 16),
                'BL': (8, 32),
                'BQ': (8, 64),
                'WL': (16, 32),
                'WQ': (16, 64),
                'LQ': (32, 64),
            }[i.mnemonic[-2:]]
            if i.operands[1]._is_mem:
                i.operands[1].size = i.misc['opdsz']
            assert i.operands[0].size == sz
            i.mnemonic = i.mnemonic[:-2] + 'X'
        elif i.mnemonic == 'MOVD':
            pass
        elif i.mnemonic in (
                'FLDCW',
                'FSTCW',
                'FNSTCW',
        ):
            assert i.operands[0]._is_mem
            i.operands[0].size = 16
        elif i.mnemonic == 'CMPXCHG':
            if i.operands[0]._is_mem: i.operands[0].size = i.operands[1].size
        elif i.mnemonic == 'CMPXCHG8B':
            if i.operands[0]._is_mem: i.operands[0].size = 64
        elif i.mnemonic == 'CMPXCHG16B':
            if i.operands[0]._is_mem: i.operands[0].size = 128
        elif i.mnemonic in mmx_with_suffix2 and len(i.operands):
            if i.mnemonic.endswith('SS'):
                if i.operands[1]._is_mem: i.operands[1].size = 32
            elif i.mnemonic.endswith('SD'):
                if i.operands[0]._is_mem: i.operands[0].size = 64
                if i.operands[1]._is_mem: i.operands[1].size = 64
            else:
                if i.operands[1]._is_mem: i.operands[1].size = 128
        elif i.mnemonic in (
                'CVTSI2SS',
                'CVTSI2SD',
                'CVTTSS2SI',
                'CVTTSS2SIL',
                'CVTTSS2SIQ',
        ):
            if i.operands[1]._is_mem: i.operands[1].size = 32
            # gcc 4.9.2 generates cvttss2siq %xmm0, %r15
            # which is useless, because the size of the output is
            # determined by the output register
            if i.mnemonic[-1] in 'LQ': i.mnemonic = i.mnemonic[:-1]
        elif i.mnemonic in (
                'MOVLPD',
                'MOVLPS',
                'MOVHPD',
                'MOVHPS',
                'MOVDDUP',
                'PSHUFW',
                'CVTSD2SS',
                'CVTSD2SI',
                'CVTTSD2SI',
                'CVTTSD2SIL',
                'CVTTSD2SIQ',
                'CVTPI2PD',
                'CVTPI2PS',
                'CVTPS2PI',
                'CVTPS2PD',
                'CVTDQ2PD',
        ):
            if i.operands[0]._is_mem: i.operands[0].size = 64
            if i.operands[1]._is_mem: i.operands[1].size = 64
            if i.mnemonic[-1] in 'LQ': i.mnemonic = i.mnemonic[:-1]
        elif i.mnemonic in (
                'PSHUFD',
                'PSHUFLW',
                'PSHUFHW',
                'MOVDQA',
                'MOVDQU',
                'MOVSLDUP',
                'MOVSHDUP',
                'MOVAPD',
                'MOVAPS',
                'MOVUPD',
                'MOVUPS',
                'CVTPD2PS',
                'CVTPD2PI',
                'CVTPD2DQ',
                'CVTTPD2DQ',
                'CVTTPD2PI',
                'CVTPS2DQ',
                'CVTTPS2PI',
                'CVTTPS2DQ',
                'CVTDQ2PS',
                'PUNPCKHQDQ',
        ):
            if i.operands[0]._is_mem: i.operands[0].size = 128
            if i.operands[1]._is_mem: i.operands[1].size = 128
        elif i.mnemonic in mmx_with_suffix1 or i.mnemonic in (
                'PSHUFB',
                'PAND',
                'PANDN',
                'POR',
                'PXOR',
        ):
            if i.operands[1]._is_mem: i.operands[1].size = i.operands[0].size
        elif i.mnemonic == 'MOVABSQ':
            # gcc generates 'movabsq $cst, %reg' instead of 'movq $cst, %reg'
            i.mnemonic = 'MOV'
            for _ in i.operands:
                if _._is_mem: _.size = 64
                if _._is_cst:
                    _.size = 64
                    _.v &= _.mask
                if _._is_lab: _.size = 64
        else:
            for _ in att_mnemo_suffix_one_ptr:
                if mnemo[:-1] != _: continue
                # Detect MMX MOVQ instruction, not 64-bit register MOV for x64
                if i.mnemonic == 'MOVQ' \
                        and i.operands[1]._is_reg \
                        and 'mm' in i.operands[1].ref:
                    if i.operands[0]._is_mem: i.operands[0].size = 64
                    break
                if i.mnemonic == 'MOVQ' \
                        and i.operands[0]._is_reg \
                        and 'mm' in i.operands[0].ref:
                    if i.operands[1]._is_mem: i.operands[1].size = 64
                    break
                i.mnemonic = _.upper()
                sz = {'b': 8, 'w': 16, 'l': 32, 'q': 64}[mnemo[-1]]
                if 'q' == mnemo[-1]:
                    i.misc.update({'REX': (1, 0, 0, 0)})
                if 'w' == mnemo[-1]:
                    i.misc.update({
                        'opdsz': 16,
                        'pfx': [None, None, 'opdsz', None]
                    })

                def set_size(e, sz):
                    if e._is_mem: e.size = sz
                    if e._is_cst:
                        e.size = sz
                        e.v &= e.mask
                    if e._is_lab: e.size = sz
                    if e._is_eqn:
                        e.size = sz
                        if e.l is not None: set_size(e.l, sz)
                        set_size(e.r, sz)

                for _ in i.operands:
                    set_size(_, sz)
            for _ in att_mnemo_suffix_one_iflt:
                if mnemo[:-1] != _: continue
                i.mnemonic = _.upper()
                sz = {'s': 16, 'l': 32, 'q': 64}[mnemo[-1]]
                for _ in i.operands:
                    if _._is_mem: _.size = sz
            if mnemo[-2:] == 'll' and mnemo[:-2] in att_mnemo_suffix_one_iflt:
                # clang on MacOS X
                i.mnemonic = mnemo[:-2].upper()
                for _ in i.operands:
                    if _._is_mem: _.size = 64
            for _ in att_mnemo_float_optional_suffix:
                if mnemo[:-1] != _: continue
                if mnemo[-1] in ('i', 'p', 'r', 'z', '1'): continue
                i.mnemonic = _.upper()
                sz = {'s': 32, 'l': 64, 't': 80}[mnemo[-1]]
                for _ in i.operands:
                    if _._is_mem: _.size = sz
        # Implicit operands
        if i.mnemonic in ('AAD', 'AAM'):
            if len(i.operands) == 0:
                i.operands.append(expressions.cst(10, 8))
            else:
                i.operands[0].size = 8
        elif i.mnemonic in ('SAL','SAR','SHL','SHR','ROR','ROL') \
                and len(i.operands) == 1:
            i.operands.append(expressions.cst(1, 32))
        elif i.mnemonic in ('SHLD','SHRD') \
                and len(i.operands) == 2:
            i.operands.append(env.__dict__['cl'])
        elif i.mnemonic.startswith('CMP') \
                and i.mnemonic.endswith(('PS','PD','SD','SS')) \
                and len(i.operands):
            idx = mnemo_sse_cmp_predicate.index(i.mnemonic[3:-2].lower())
            i.operands.append(expressions.cst(idx))
            i.mnemonic = i.mnemonic[:3] + i.mnemonic[-2:]
        elif i.mnemonic in ('FADD','FSUB','FSUBR',
                            'FMUL','FDIV','FDIVR',
                            'FCOMI','FCOMIP','FUCOMI','FUCOMIP',
                           ) \
                and len(i.operands) == 1 \
                and not i.operands[0]._is_mem:
            i.operands.insert(0, env.st(0))
        elif i.mnemonic in ('FADDP','FSUBP','FSUBRP',
                            'FMULP','FDIVP','FDIVRP',
                           ) \
                and len(i.operands) == 1 \
                and not i.operands[0]._is_mem:
            i.operands.append(env.st(0))
        elif i.mnemonic in ('FCOM','FCOMP','FUCOM','FUCOMP',
                           ) \
                and len(i.operands) == 0:
            i.operands.append(env.st(1))
        return i