about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorserpilliere <serpilliere@users.noreply.github.com>2018-05-17 12:31:35 +0200
committerGitHub <noreply@github.com>2018-05-17 12:31:35 +0200
commitf6a9db54b4f385d680abfe91b33c7c5f577118cb (patch)
tree37ec6ee8f5c153aa34f7476d76053578eb50a69d
parentcb1e73d65b99b5e6f73bd7823b6142e99ef9994a (diff)
parent23cee4aeb4d667b6ff93b279a8619acf56a70bc3 (diff)
downloadmiasm-f6a9db54b4f385d680abfe91b33c7c5f577118cb.tar.gz
miasm-f6a9db54b4f385d680abfe91b33c7c5f577118cb.zip
Merge pull request #746 from commial/feature/XMM-regs
Feature/xmm regs
-rw-r--r--miasm2/ir/translators/C.py91
-rw-r--r--miasm2/jitter/JitCore.c11
-rw-r--r--miasm2/jitter/JitCore.h20
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c68
-rw-r--r--miasm2/jitter/arch/JitCore_x86.h19
-rw-r--r--miasm2/jitter/codegen.py11
-rw-r--r--miasm2/jitter/llvmconvert.py2
-rw-r--r--miasm2/jitter/vm_mngr.c40
-rw-r--r--miasm2/jitter/vm_mngr.h27
-rw-r--r--test/arch/x86/unit/access_xmm.py16
-rwxr-xr-xtest/test_all.py2
11 files changed, 263 insertions, 44 deletions
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index 26443b09..226f26f1 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -18,6 +18,17 @@ class TranslatorC(Translator):
                '>>>': 'rot_right',
                }
 
+    def _size2mask(self, size):
+        """Return a C string corresponding to the size2mask operation, with support for
+        @size <= 128"""
+        mask = size2mask(size)
+        if size > 64:
+            # Avoid "integer constant is too large for its type" error
+            return "(0x%x | ((uint128_t) 0x%x << 64))" % (
+                mask & 0xFFFFFFFFFFFFFFFF,
+                (mask >> 64) & 0xFFFFFFFFFFFFFFFF,
+            )
+        return "0x%x" % mask
 
     def from_ExprId(self, expr):
         if isinstance(expr.name, asmblock.AsmLabel):
@@ -25,6 +36,12 @@ class TranslatorC(Translator):
         return str(expr)
 
     def from_ExprInt(self, expr):
+        if expr.size == 128:
+            # Avoid "integer constant is too large for its type" error
+            return "(0x%x | ((uint128_t) 0x%x << 64))" % (
+                int(expr) & 0xFFFFFFFFFFFFFFFF,
+                (int(expr) >> 64) & 0xFFFFFFFFFFFFFFFF,
+            )
         return "0x%x" % expr.arg.arg
 
     def from_ExprAff(self, expr):
@@ -41,15 +58,19 @@ class TranslatorC(Translator):
     def from_ExprOp(self, expr):
         if len(expr.args) == 1:
             if expr.op == 'parity':
-                return "parity(%s&0x%x)" % (self.from_expr(expr.args[0]),
-                                            size2mask(expr.args[0].size))
+                return "parity(%s&%s)" % (
+                    self.from_expr(expr.args[0]),
+                    self._size2mask(expr.args[0].size),
+                )
             elif expr.op in ['cntleadzeros', 'cnttrailzeros']:
                 return "%s(0x%x, %s)" % (expr.op,
                                              expr.args[0].size,
                                              self.from_expr(expr.args[0]))
             elif expr.op == '!':
-                return "(~ %s)&0x%x" % (self.from_expr(expr.args[0]),
-                                        size2mask(expr.args[0].size))
+                return "(~ %s)&%s" % (
+                    self.from_expr(expr.args[0]),
+                    self._size2mask(expr.args[0].size),
+                )
             elif (expr.op.startswith("double_to_") or
                   expr.op.endswith("_to_double")   or
                   expr.op.startswith("access_")    or
@@ -63,31 +84,40 @@ class TranslatorC(Translator):
 
         elif len(expr.args) == 2:
             if expr.op == "==":
-                return '(((%s&0x%x) == (%s&0x%x))?1:0)' % (
-                    self.from_expr(expr.args[0]), size2mask(expr.args[0].size),
-                    self.from_expr(expr.args[1]), size2mask(expr.args[1].size))
+                return '(((%s&%s) == (%s&%s))?1:0)' % (
+                    self.from_expr(expr.args[0]),
+                    self._size2mask(expr.args[0].size),
+                    self.from_expr(expr.args[1]),
+                    self._size2mask(expr.args[1].size),
+                )
             elif expr.op in self.dct_shift:
                 return 'SHIFT_%s(%d, %s, %s)' % (self.dct_shift[expr.op].upper(),
                                                  expr.args[0].size,
                                                  self.from_expr(expr.args[0]),
                                                  self.from_expr(expr.args[1]))
             elif expr.is_associative() or expr.op in ["%", "/"]:
-                oper = ['(%s&0x%x)' % (self.from_expr(arg), size2mask(arg.size))
+                oper = ['(%s&%s)' % (
+                    self.from_expr(arg),
+                    self._size2mask(arg.size)
+                )
                         for arg in expr.args]
                 oper = str(expr.op).join(oper)
-                return "((%s)&0x%x)" % (oper, size2mask(expr.args[0].size))
+                return "((%s)&%s)" % (oper, self._size2mask(expr.args[0].size))
             elif expr.op in ['-']:
-                return '(((%s&0x%x) %s (%s&0x%x))&0x%x)' % (
-                    self.from_expr(expr.args[0]), size2mask(expr.args[0].size),
+                return '(((%s&%s) %s (%s&%s))&%s)' % (
+                    self.from_expr(expr.args[0]), self._size2mask(expr.args[0].size),
                     str(expr.op),
-                    self.from_expr(expr.args[1]), size2mask(expr.args[1].size),
-                    size2mask(expr.args[0].size))
+                    self.from_expr(expr.args[1]), self._size2mask(expr.args[1].size),
+                    self._size2mask(expr.args[0].size)
+                )
             elif expr.op in self.dct_rot:
-                return '(%s(%s, %s, %s) &0x%x)' % (self.dct_rot[expr.op],
-                                                   expr.args[0].size,
-                                                   self.from_expr(expr.args[0]),
-                                                   self.from_expr(expr.args[1]),
-                                                   size2mask(expr.args[0].size))
+                return '(%s(%s, %s, %s) &%s)' % (
+                    self.dct_rot[expr.op],
+                    expr.args[0].size,
+                    self.from_expr(expr.args[0]),
+                    self.from_expr(expr.args[1]),
+                    self._size2mask(expr.args[0].size),
+                )
             elif expr.op == 'x86_cpuid':
                 return "%s(%s, %s)" % (expr.op,
                                        self.from_expr(expr.args[0]),
@@ -114,19 +144,24 @@ class TranslatorC(Translator):
                 raise NotImplementedError('Unknown op: %r' % expr.op)
 
         elif len(expr.args) >= 3 and expr.is_associative():  # ?????
-            oper = ['(%s&0x%x)' % (self.from_expr(arg), size2mask(arg.size))
+            oper = ['(%s&%s)' % (
+                self.from_expr(arg),
+                self._size2mask(arg.size),
+            )
                     for arg in expr.args]
             oper = str(expr.op).join(oper)
-            return "((%s)&0x%x)" % (oper, size2mask(expr.args[0].size))
-
+            return "((%s)&%s)" % (
+                oper,
+                self._size2mask(expr.args[0].size)
+            )
         else:
             raise NotImplementedError('Unknown op: %s' % expr.op)
 
     def from_ExprSlice(self, expr):
         # XXX check mask for 64 bit & 32 bit compat
-        return "((%s>>%d) & 0x%X)" % (self.from_expr(expr.arg),
-                                      expr.start,
-                                      (1 << (expr.stop - expr.start)) - 1)
+        return "((%s>>%d) &%s)" % (self.from_expr(expr.arg),
+                                   expr.start,
+                                   self._size2mask(expr.stop - expr.start))
 
     def from_ExprCompose(self, expr):
         out = []
@@ -143,10 +178,10 @@ class TranslatorC(Translator):
 
         dst_cast = "uint%d_t" % size
         for index, arg in expr.iter_args():
-            out.append("(((%s)(%s & 0x%X)) << %d)" % (dst_cast,
-                                                      self.from_expr(arg),
-                                                      (1 << arg.size) - 1,
-                                                      index))
+            out.append("(((%s)(%s & %s)) << %d)" % (dst_cast,
+                                                    self.from_expr(arg),
+                                                    self._size2mask(arg.size),
+                                                    index))
         out = ' | '.join(out)
         return '(' + out + ')'
 
diff --git a/miasm2/jitter/JitCore.c b/miasm2/jitter/JitCore.c
index 84f835f1..496ec8e1 100644
--- a/miasm2/jitter/JitCore.c
+++ b/miasm2/jitter/JitCore.c
@@ -74,6 +74,11 @@ uint64_t __attribute__((weak)) MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr)
 	return vm_MEM_LOOKUP_64(&(jitcpu->pyvm->vm_mngr), addr);
 }
 
+uint128_t __attribute__((weak)) MEM_LOOKUP_128(JitCpu* jitcpu, uint64_t addr)
+{
+	return vm_MEM_LOOKUP_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr);
+}
+
 void __attribute__((weak)) MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src)
 {
 	vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
@@ -94,8 +99,10 @@ void __attribute__((weak)) MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t
 	vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
 }
 
-
-
+void __attribute__((weak)) MEM_WRITE_128(JitCpu* jitcpu, uint64_t addr, uint128_t src)
+{
+	vm_MEM_WRITE_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src);
+}
 
 PyObject* __attribute__((weak)) vm_get_mem(JitCpu *self, PyObject* args)
 {
diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h
index f599d6ea..c703178d 100644
--- a/miasm2/jitter/JitCore.h
+++ b/miasm2/jitter/JitCore.h
@@ -4,6 +4,7 @@
 #define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
 #define RAISE_ret0(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return 0;}
 
+#define uint128_t __uint128_t
 
 #define PyGetInt(item, value)						\
 	if (PyInt_Check(item)){						\
@@ -30,6 +31,23 @@
 	}								\
 
 
+#define getset_reg_u128(regname)						\
+	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
+	{ \
+		return _PyLong_FromByteArray((const unsigned char*) &(((vm_cpu_t*)(self->cpu))->  regname  ), sizeof(uint128_t), /*little_endian*/ 1, /*is_signed*/ 0); \
+	}								\
+	static int JitCpu_set_ ## regname  (JitCpu *self, PyObject *value, void *closure) \
+	{								\
+		uint128_t val = 0;					\
+		int i;                                                  \
+		unsigned char bytes[sizeof(uint128_t)];			\
+		_PyLong_AsByteArray((PyLongObject*)value, bytes, sizeof(uint128_t), /*little_endian*/ 1, /*is_signed*/ 0); \
+		for (i = 0; i < sizeof(uint128_t); i++) {               \
+			val |= (uint128_t) bytes[i] << (8 * i);         \
+		}                                                       \
+		((vm_cpu_t*)(self->cpu))->  regname   = val;		\
+		return 0;						\
+	}
 
 #define getset_reg_u64(regname)						\
 	static PyObject *JitCpu_get_ ## regname  (JitCpu *self, void *closure) \
@@ -122,10 +140,12 @@ uint8_t MEM_LOOKUP_08(JitCpu* jitcpu, uint64_t addr);
 uint16_t MEM_LOOKUP_16(JitCpu* jitcpu, uint64_t addr);
 uint32_t MEM_LOOKUP_32(JitCpu* jitcpu, uint64_t addr);
 uint64_t MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr);
+uint128_t MEM_LOOKUP_128(JitCpu* jitcpu, uint64_t addr);
 void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src);
 void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src);
 void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src);
 void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src);
+void MEM_WRITE_128(JitCpu* jitcpu, uint64_t addr, uint128_t src);
 PyObject* vm_get_mem(JitCpu *self, PyObject* args);
 
 
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
index 648716a0..f54cb1d3 100644
--- a/miasm2/jitter/arch/JitCore_x86.c
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -120,6 +120,23 @@ PyObject* cpu_get_gpreg(JitCpu* self)
     get_reg(MM6);
     get_reg(MM7);
 
+    get_reg(XMM0);
+    get_reg(XMM1);
+    get_reg(XMM2);
+    get_reg(XMM3);
+    get_reg(XMM4);
+    get_reg(XMM5);
+    get_reg(XMM6);
+    get_reg(XMM7);
+    get_reg(XMM8);
+    get_reg(XMM9);
+    get_reg(XMM10);
+    get_reg(XMM11);
+    get_reg(XMM12);
+    get_reg(XMM13);
+    get_reg(XMM14);
+    get_reg(XMM15);
+
     get_reg(tsc1);
     get_reg(tsc2);
 
@@ -526,6 +543,23 @@ getset_reg_u64(MM5);
 getset_reg_u64(MM6);
 getset_reg_u64(MM7);
 
+getset_reg_u128(XMM0);
+getset_reg_u128(XMM1);
+getset_reg_u128(XMM2);
+getset_reg_u128(XMM3);
+getset_reg_u128(XMM4);
+getset_reg_u128(XMM5);
+getset_reg_u128(XMM6);
+getset_reg_u128(XMM7);
+getset_reg_u128(XMM8);
+getset_reg_u128(XMM9);
+getset_reg_u128(XMM10);
+getset_reg_u128(XMM11);
+getset_reg_u128(XMM12);
+getset_reg_u128(XMM13);
+getset_reg_u128(XMM14);
+getset_reg_u128(XMM15);
+
 getset_reg_u32(tsc1);
 getset_reg_u32(tsc2);
 
@@ -602,6 +636,23 @@ PyObject* get_gpreg_offset_all(void)
     get_reg_off(MM6);
     get_reg_off(MM7);
 
+    get_reg_off(XMM0);
+    get_reg_off(XMM1);
+    get_reg_off(XMM2);
+    get_reg_off(XMM3);
+    get_reg_off(XMM4);
+    get_reg_off(XMM5);
+    get_reg_off(XMM6);
+    get_reg_off(XMM7);
+    get_reg_off(XMM8);
+    get_reg_off(XMM9);
+    get_reg_off(XMM10);
+    get_reg_off(XMM11);
+    get_reg_off(XMM12);
+    get_reg_off(XMM13);
+    get_reg_off(XMM14);
+    get_reg_off(XMM15);
+
     get_reg_off(tsc1);
     get_reg_off(tsc2);
 
@@ -690,6 +741,23 @@ static PyGetSetDef JitCpu_getseters[] = {
     {"MM6", (getter)JitCpu_get_MM6, (setter)JitCpu_set_MM6, "MM6", NULL},
     {"MM7", (getter)JitCpu_get_MM7, (setter)JitCpu_set_MM7, "MM7", NULL},
 
+    {"XMM0", (getter)JitCpu_get_XMM0, (setter)JitCpu_set_XMM0, "XMM0", NULL},
+    {"XMM1", (getter)JitCpu_get_XMM1, (setter)JitCpu_set_XMM1, "XMM1", NULL},
+    {"XMM2", (getter)JitCpu_get_XMM2, (setter)JitCpu_set_XMM2, "XMM2", NULL},
+    {"XMM3", (getter)JitCpu_get_XMM3, (setter)JitCpu_set_XMM3, "XMM3", NULL},
+    {"XMM4", (getter)JitCpu_get_XMM4, (setter)JitCpu_set_XMM4, "XMM4", NULL},
+    {"XMM5", (getter)JitCpu_get_XMM5, (setter)JitCpu_set_XMM5, "XMM5", NULL},
+    {"XMM6", (getter)JitCpu_get_XMM6, (setter)JitCpu_set_XMM6, "XMM6", NULL},
+    {"XMM7", (getter)JitCpu_get_XMM7, (setter)JitCpu_set_XMM7, "XMM7", NULL},
+    {"XMM8", (getter)JitCpu_get_XMM8, (setter)JitCpu_set_XMM8, "XMM8", NULL},
+    {"XMM9", (getter)JitCpu_get_XMM9, (setter)JitCpu_set_XMM9, "XMM9", NULL},
+    {"XMM10", (getter)JitCpu_get_XMM10, (setter)JitCpu_set_XMM10, "XMM10", NULL},
+    {"XMM11", (getter)JitCpu_get_XMM11, (setter)JitCpu_set_XMM11, "XMM11", NULL},
+    {"XMM12", (getter)JitCpu_get_XMM12, (setter)JitCpu_set_XMM12, "XMM12", NULL},
+    {"XMM13", (getter)JitCpu_get_XMM13, (setter)JitCpu_set_XMM13, "XMM13", NULL},
+    {"XMM14", (getter)JitCpu_get_XMM14, (setter)JitCpu_set_XMM14, "XMM14", NULL},
+    {"XMM15", (getter)JitCpu_get_XMM15, (setter)JitCpu_set_XMM15, "XMM15", NULL},
+
     {"tsc1", (getter)JitCpu_get_tsc1, (setter)JitCpu_set_tsc1, "tsc1", NULL},
     {"tsc2", (getter)JitCpu_get_tsc2, (setter)JitCpu_set_tsc2, "tsc2", NULL},
 
diff --git a/miasm2/jitter/arch/JitCore_x86.h b/miasm2/jitter/arch/JitCore_x86.h
index bb1e005a..221ba5db 100644
--- a/miasm2/jitter/arch/JitCore_x86.h
+++ b/miasm2/jitter/arch/JitCore_x86.h
@@ -1,3 +1,4 @@
+#define uint128_t __uint128_t
 
 typedef struct {
 	uint32_t exception_flags;
@@ -96,6 +97,24 @@ typedef struct {
 	uint64_t MM6;
 	uint64_t MM7;
 
+	/* SSE */
+	uint128_t XMM0;
+	uint128_t XMM1;
+	uint128_t XMM2;
+	uint128_t XMM3;
+	uint128_t XMM4;
+	uint128_t XMM5;
+	uint128_t XMM6;
+	uint128_t XMM7;
+	uint128_t XMM8;
+	uint128_t XMM9;
+	uint128_t XMM10;
+	uint128_t XMM11;
+	uint128_t XMM12;
+	uint128_t XMM13;
+	uint128_t XMM14;
+	uint128_t XMM15;
+
 	uint32_t segm_base[0x10000];
 
 }vm_cpu_t;
diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py
index 2c546be8..b10a9257 100644
--- a/miasm2/jitter/codegen.py
+++ b/miasm2/jitter/codegen.py
@@ -10,9 +10,8 @@ from miasm2.core.asmblock import expr_is_label, AsmBlockBad, AsmLabel
 # Miasm to C translator
 TRANSLATOR = Translator.to_language("C")
 
-SIZE_TO_MASK = {x: 2**x - 1 for x in (1, 2, 3, 7, 8, 16, 32, 64)}
-
-MASK_INT = 0xffffffffffffffff
+SIZE_TO_MASK = {size: TRANSLATOR.from_expr(m2_expr.ExprInt(0, size).mask)
+                for size in (1, 2, 3, 7, 8, 16, 32, 64, 128)}
 
 
 class Attributes(object):
@@ -246,9 +245,9 @@ class CGen(object):
                         '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src)))
                 else:
                     c_main.append(
-                        '%s = (%s)&0x%X;' % (self.id_to_c(new_dst),
-                                             self.id_to_c(src),
-                                             SIZE_TO_MASK[src.size]))
+                        '%s = (%s)&%s;' % (self.id_to_c(new_dst),
+                                           self.id_to_c(src),
+                                           SIZE_TO_MASK[src.size]))
             elif isinstance(dst, m2_expr.ExprMem):
                 ptr = dst.arg.replace_expr(prefetchers)
                 new_dst = m2_expr.ExprMem(ptr, dst.size)
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index 97cd9f17..2b0f2702 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -193,7 +193,7 @@ class LLVMContext_JIT(LLVMContext):
 
         fc = {}
         p8 = llvm_ir.PointerType(LLVMType.IntType(8))
-        for i in [8, 16, 32, 64]:
+        for i in [8, 16, 32, 64, 128]:
             fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.IntType(i),
                                          "args": [p8,
                                                   LLVMType.IntType(64)]}
diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c
index 6da7bfed..8601ec20 100644
--- a/miasm2/jitter/vm_mngr.c
+++ b/miasm2/jitter/vm_mngr.c
@@ -101,6 +101,13 @@ uint64_t set_endian64(vm_mngr_t* vm_mngr, uint64_t val)
 		return Endian64_Swap(val);
 }
 
+uint128_t set_endian128(vm_mngr_t* vm_mngr, uint128_t val)
+{
+	if (vm_mngr->sex == __BYTE_ORDER)
+		return val;
+	else
+		return Endian128_Swap(val);
+}
 
 void print_val(uint64_t base, uint64_t addr)
 {
@@ -159,11 +166,11 @@ struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint6
 
 
 
-static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad)
+static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad)
 {
 	struct memory_page_node * mpn;
 	unsigned char * addr;
-	uint64_t ret = 0;
+	uint128_t ret = 0;
 	struct memory_breakpoint_info * b;
 
 
@@ -206,6 +213,10 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6
 			ret = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL;
 			ret = set_endian64(vm_mngr, ret);
 			break;
+		case 128:
+			ret = *((uint128_t*)addr)&MASK_128;
+			ret = set_endian128(vm_mngr, ret);
+			break;
 		default:
 			exit(EXIT_FAILURE);
 			break;
@@ -238,6 +249,9 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6
 		case 64:
 			ret = set_endian64(vm_mngr, ret);
 			break;
+		case 128:
+			ret = set_endian128(vm_mngr, ret);
+			break;
 		default:
 			exit(EXIT_FAILURE);
 			break;
@@ -247,7 +261,7 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6
 }
 
 static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size,
-			      uint64_t ad, uint64_t src)
+			      uint64_t ad, uint128_t src)
 {
 	struct memory_page_node * mpn;
 	unsigned char * addr;
@@ -291,6 +305,10 @@ static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size,
 			src = set_endian64(vm_mngr, src);
 			*((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL;
 			break;
+		case 128:
+			src = set_endian128(vm_mngr, src);
+			*((uint128_t*)addr) = src&MASK_128;
+			break;
 		default:
 			exit(EXIT_FAILURE);
 			break;
@@ -312,6 +330,9 @@ static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size,
 		case 64:
 			src = set_endian64(vm_mngr, src);
 			break;
+		case 128:
+			src = set_endian128(vm_mngr, src);
+			break;
 		default:
 			exit(EXIT_FAILURE);
 			break;
@@ -480,6 +501,12 @@ void vm_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src)
 	memory_page_write(vm_mngr, 64, addr, src);
 }
 
+void vm_MEM_WRITE_128(vm_mngr_t* vm_mngr, uint64_t addr, uint128_t src)
+{
+	add_mem_write(vm_mngr, addr, 16);
+	memory_page_write(vm_mngr, 128, addr, src);
+}
+
 unsigned char vm_MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr)
 {
 	unsigned char ret;
@@ -508,6 +535,13 @@ uint64_t vm_MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr)
 	ret = memory_page_read(vm_mngr, 64, addr);
 	return ret;
 }
+uint128_t vm_MEM_LOOKUP_128(vm_mngr_t* vm_mngr, uint128_t addr)
+{
+	uint128_t ret;
+	add_mem_read(vm_mngr, addr, 16);
+	ret = memory_page_read(vm_mngr, 128, addr);
+	return ret;
+}
 
 
 int vm_read_mem(vm_mngr_t* vm_mngr, uint64_t addr, char** buffer_ptr, uint64_t size)
diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h
index eff5e0da..a50b52d0 100644
--- a/miasm2/jitter/vm_mngr.h
+++ b/miasm2/jitter/vm_mngr.h
@@ -26,6 +26,8 @@
 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
 #endif
 
+#define uint128_t __uint128_t
+
 #define Endian16_Swap(value) \
       ((((uint16_t)((value) & 0x00FF)) << 8) | \
        (((uint16_t)((value) & 0xFF00)) >> 8))
@@ -46,8 +48,25 @@
 	 ((((uint64_t)value)>>40) & 0x000000000000FF00ULL)  |	      \
 	 ((((uint64_t)value)>>56) & 0x00000000000000FFULL))
 
-
-
+#define Endian128_Swap(value)                                   \
+	(((((uint128_t)value)>>120) & 0xFF)             |	\
+	 ((((uint128_t)value)>>112) & 0xFF) << 8	|	\
+	 ((((uint128_t)value)>>104) & 0xFF) << 16       |	\
+	 ((((uint128_t)value)>>96) & 0xFF) << 24	|	\
+	 ((((uint128_t)value)>>88) & 0xFF) << 32	|	\
+	 ((((uint128_t)value)>>80) & 0xFF) << 40	|	\
+	 ((((uint128_t)value)>>72) & 0xFF) << 48	|	\
+	 ((((uint128_t)value)>>64) & 0xFF) << 56	|	\
+	 ((((uint128_t)value)>>56) & 0xFF) << 64	|	\
+	 ((((uint128_t)value)>>48) & 0xFF) << 72	|	\
+	 ((((uint128_t)value)>>40) & 0xFF) << 80	|	\
+	 ((((uint128_t)value)>>32) & 0xFF) << 88	|	\
+	 ((((uint128_t)value)>>24) & 0xFF) << 96	|	\
+	 ((((uint128_t)value)>>16) & 0xFF) << 104       |	\
+	 ((((uint128_t)value)>>8) & 0xFF) << 112	|	\
+	 ((((uint128_t)value)) & 0xFF) << 120)
+
+#define MASK_128 ((uint128_t) 0xFFFFFFFFFFFFFFFFULL | (uint128_t) 0xFFFFFFFFFFFFFFFFULL << 64)
 
 LIST_HEAD(code_bloc_list_head, code_bloc_node);
 LIST_HEAD(memory_breakpoint_info_head, memory_breakpoint_info);
@@ -174,13 +193,13 @@ void vm_MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src);
 void vm_MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src);
 void vm_MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src);
 void vm_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src);
-
+void vm_MEM_WRITE_128(vm_mngr_t* vm_mngr, uint64_t addr, uint128_t src);
 
 unsigned char vm_MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr);
 unsigned short vm_MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr);
 unsigned int vm_MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr);
 uint64_t vm_MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr);
-
+uint128_t vm_MEM_LOOKUP_128(vm_mngr_t* vm_mngr, uint128_t addr);
 
 void MEM_WRITE_08_PASSTHROUGH(uint64_t addr, unsigned char src);
 void MEM_WRITE_16_PASSTHROUGH(uint64_t addr, unsigned short src);
diff --git a/test/arch/x86/unit/access_xmm.py b/test/arch/x86/unit/access_xmm.py
new file mode 100644
index 00000000..950c8b56
--- /dev/null
+++ b/test/arch/x86/unit/access_xmm.py
@@ -0,0 +1,16 @@
+#! /usr/bin/env python2
+"""Test getter and setter for XMM registers (128 bits)"""
+
+from miasm2.analysis.machine import Machine
+
+# Jitter engine doesn't matter, use the always available 'python' one
+myjit = Machine("x86_32").jitter("python")
+
+# Test basic access (get)
+assert myjit.cpu.XMM0 == 0
+
+# Test set
+myjit.cpu.XMM1 = 0x00112233445566778899aabbccddeeffL
+
+# Ensure set has been correctly handled
+assert myjit.cpu.XMM1 == 0x00112233445566778899aabbccddeeffL
diff --git a/test/test_all.py b/test/test_all.py
index 3572bda7..f9c90759 100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -97,6 +97,8 @@ for script in ["x86/sem.py",
         tags = [TAGS[jitter]] if jitter in TAGS else []
         testset += ArchUnitTest(script, jitter, base_dir="arch", tags=tags)
 
+testset += ArchUnitTest("x86/unit/access_xmm.py", "python", base_dir="arch")
+
 ### QEMU regression tests
 class QEMUTest(RegressionTest):
     """Test against QEMU regression tests