about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/arch.py108
-rw-r--r--miasm2/arch/x86/regs.py3
-rw-r--r--miasm2/arch/x86/sem.py46
-rw-r--r--test/arch/x86/arch.py11
4 files changed, 155 insertions, 13 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py
index 55dc653b..13c06ae6 100644
--- a/miasm2/arch/x86/arch.py
+++ b/miasm2/arch/x86/arch.py
@@ -134,7 +134,7 @@ RBRACK = Suppress("]")
 dbreg = Group(gpregs16.parser | gpregs32.parser | gpregs64.parser)
 gpreg = (gpregs08.parser | gpregs08_64.parser | gpregs16.parser   |
          gpregs32.parser | gpregs64.parser    | gpregs_xmm.parser |
-         gpregs_mm.parser)
+         gpregs_mm.parser | gpregs_bnd.parser)
 
 
 def reg2exprid(r):
@@ -304,7 +304,8 @@ rmarg = Group(gpregs08.parser |
               gpregs32.parser |
               gpregs64.parser |
               gpregs_mm.parser |
-              gpregs_xmm.parser
+              gpregs_xmm.parser |
+              gpregs_bnd.parser
               ).setParseAction(getreg)
 
 rmarg |= deref_mem
@@ -1712,8 +1713,10 @@ def test_addr_size(ptr, 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):
+def parse_mem(expr, parent, w8, sx=0, xmm=0, mm=0, bnd=0):
     dct_expr = {}
     opmode = parent.v_opmode()
     if expr.is_mem_segm() and expr.arg.args[0].is_int():
@@ -1780,17 +1783,23 @@ def parse_mem(expr, parent, w8, sx=0, xmm=0, mm=0):
         out = [dct_expr]
     return out, segm, True
 
-def expr2modrm(expr, parent, w8, sx=0, xmm=0, mm=0):
+def expr2modrm(expr, parent, w8, sx=0, xmm=0, mm=0, bnd=0):
     dct_expr = {f_isad : False}
 
-    if mm or xmm:
+    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):
-            selreg = SIZE2XMMREG[expr.size]
+            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)
@@ -1828,6 +1837,13 @@ def expr2modrm(expr, parent, w8, sx=0, xmm=0, mm=0):
                 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)
@@ -1858,9 +1874,9 @@ def expr2modrm(expr, parent, w8, sx=0, xmm=0, mm=0):
                 return None, None, False
         dct_expr[i] = 1
         return [dct_expr], None, True
-    return parse_mem(expr, parent, w8, sx, xmm, mm)
+    return parse_mem(expr, parent, w8, sx, xmm, mm, bnd)
 
-def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0):
+def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0, bnd=0):
     o = []
     if not modrm[f_isad]:
         modrm_k = [x[0] for x in modrm.iteritems() if x[1] == 1]
@@ -1879,6 +1895,8 @@ def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0):
             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:
@@ -1907,6 +1925,8 @@ def modrm2expr(modrm, parent, w8, sx=0, xmm=0, mm=0):
         opmode = 128
     elif mm:
         opmode = 64
+    elif bnd:
+        opmode = 128
 
     expr = ExprMem(expr, size=opmode)
     return expr
@@ -2326,11 +2346,12 @@ 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)
+        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
@@ -2356,7 +2377,8 @@ class x86_rm_mm(x86_rm_m80):
             elif self.is_mm:
                 expr = ExprMem(expr.arg, 64)
 
-        v_cand, segm, ok = expr2modrm(expr, p, 0, 0, self.is_xmm, self.is_mm)
+        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
 
@@ -2382,6 +2404,11 @@ class x86_rm_xmm_m64(x86_rm_mm):
     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
@@ -2393,6 +2420,35 @@ class x86_rm_mm_reg(x86_rm_mm):
     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
 
@@ -2511,6 +2567,9 @@ class x86_rm_reg_mm(x86_rm_reg_noarg, m_arg):
 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, m_arg):
     pass
 
@@ -3196,6 +3255,7 @@ 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")
@@ -3226,8 +3286,15 @@ 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=range(1 << 1))
 
 
@@ -3353,6 +3420,17 @@ 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)] + rmmod(rmreg))
 addop("bsr", [bs8(0x0f), bs8(0xbd), mod,
     rmreg, rm, sib_scale, sib_index, sib_base, disp, rm_arg])
@@ -4140,6 +4218,11 @@ addop("cvttsd2si",[bs8(0x0f), bs8(0x2c), pref_f2]
 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] +
@@ -4251,6 +4334,11 @@ addop("pcmpeqd", [bs8(0x0f), bs8(0x76), no_xmm_pref] +
 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("pcmpgtd", [bs8(0x0f), bs8(0x66), no_xmm_pref] +
       rmmod(mm_reg, rm_arg_mm))
 addop("pcmpgtd", [bs8(0x0f), bs8(0x66), pref_66] +
diff --git a/miasm2/arch/x86/regs.py b/miasm2/arch/x86/regs.py
index 5db75e37..cb7e0d7b 100644
--- a/miasm2/arch/x86/regs.py
+++ b/miasm2/arch/x86/regs.py
@@ -40,6 +40,8 @@ regs_xmm_expr = [ExprId(x, 128) for x in regs_xmm_str]
 regs_mm_str = ["MM%d" % i for i in xrange(16)]
 regs_mm_expr = [ExprId(x, 64) for x in regs_mm_str]
 
+regs_bnd_str = ["BND%d" % i for i in xrange(4)]
+regs_bnd_expr = [ExprId(x, 128) for x in regs_bnd_str]
 
 gpregs08 = reg_info(regs08_str, regs08_expr)
 gpregs08_64 = reg_info(regs08_64_str, regs08_64_expr)
@@ -49,6 +51,7 @@ gpregs64 = reg_info(regs64_str, regs64_expr)
 
 gpregs_xmm = reg_info(regs_xmm_str, regs_xmm_expr)
 gpregs_mm = reg_info(regs_mm_str, regs_mm_expr)
+gpregs_bnd = reg_info(regs_bnd_str, regs_bnd_expr)
 
 r08_eax = reg_info([regs08_str[0]], [regs08_expr[0]])
 r16_eax = reg_info([regs16_str[0]], [regs16_expr[0]])
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index f2b75d03..56aca1c2 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -2649,6 +2649,11 @@ def prefetchw(_, instr, src=None):
     # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
     return [], []
 
+def prefetchnta(_, instr, src=None):
+    # see 4-201 on this documentation
+    # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
+    return [], []
+
 
 def lfence(_, instr, src=None):
     # see 3-485 on this documentation
@@ -3788,6 +3793,16 @@ def pslldq(_, instr, dst, src):
         return [m2_expr.ExprAff(dst, dst << m2_expr.ExprInt(8 * count, dst.size))], []
 
 
+def psrldq(_, instr, dst, src):
+    assert src.is_int()
+    e = []
+    count = int(src)
+    if count > 15:
+        return [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))], []
+    else:
+        return [m2_expr.ExprAff(dst, dst >> m2_expr.ExprInt(8 * count, dst.size))], []
+
+
 def iret(ir, instr):
     """IRET implementation
     XXX: only support "no-privilege change"
@@ -4129,6 +4144,29 @@ def smsw(ir, instr, dst):
     return e, []
 
 
+def bndmov(ir, instr, dst, src):
+    # Implemented as a NOP, because BND side effects are not yet supported
+    return [], []
+
+def palignr(ir, instr, dst, src, imm):
+    # dst.src >> imm * 8 [:dst.size]
+
+    shift = int(imm) * 8
+    if shift == 0:
+        result = src
+    elif shift == src.size:
+        result = dst
+    elif shift > src.size:
+        result = dst >> m2_expr.ExprInt(shift - src.size, dst.size)
+    else:
+        # shift < src.size
+        result = m2_expr.ExprCompose(
+            src[shift:],
+            dst[:shift],
+        )
+
+    return [m2_expr.ExprAff(dst, result)], []
+
 
 mnemo_func = {'mov': mov,
               'xchg': xchg,
@@ -4306,6 +4344,7 @@ mnemo_func = {'mov': mov,
               'prefetch1': prefetch1,
               'prefetch2': prefetch2,
               'prefetchw': prefetchw,
+              'prefetchnta': prefetchnta,
               'lfence': lfence,
               'mfence': mfence,
               'sfence': sfence,
@@ -4483,9 +4522,7 @@ mnemo_func = {'mov': mov,
               "cvttss2si": cvttss2si,
 
 
-
-
-
+              "bndmov": bndmov,
 
 
 
@@ -4565,6 +4602,9 @@ mnemo_func = {'mov': mov,
               "pslld": pslld,
               "psllq": psllq,
               "pslldq": pslldq,
+              "psrldq": psrldq,
+
+              "palignr": palignr,
 
               "pmaxub": pmaxub,
               "pmaxuw": pmaxuw,
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 972a2e12..d3b2964c 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -2802,6 +2802,12 @@ reg_tests = [
     (m32, "00000000    PCMPGTQ    XMM0, XMM5",
     "660f3837C5"),
 
+    (m64, "00000000    PCMPGTB    XMM8, XMM5",
+     "66440f64c5"),
+
+    (m64, "00000000    PALIGNR    XMM1, XMM2, 0xC",
+     "660f3a0fca0c"),
+
 
     (m32, "00000000    PUNPCKHBW  MM2, QWORD PTR [EDX]",
     "0F6812"),
@@ -2959,6 +2965,11 @@ reg_tests = [
     (m32, "00000000    AESDECLAST XMM1, XMM2",
      "660f38dfca"),
 
+    (m64, "00000000    BNDMOV     XMMWORD PTR [RSP + 0x80], BND0",
+     "660f1b842480000000"),
+    (m64, "00000000    BNDMOV     BND3, XMMWORD PTR [RSP + 0xB0]",
+     "660f1a9c24b0000000"),
+
 ]