about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/sem.py115
-rw-r--r--miasm2/ir/translators/C.py6
-rw-r--r--miasm2/jitter/vm_mngr.c149
-rw-r--r--miasm2/jitter/vm_mngr.h11
4 files changed, 250 insertions, 31 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index ddce70fe..b622e930 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -168,7 +168,8 @@ def mem2double(arg):
     """
     if isinstance(arg, m2_expr.ExprMem):
         if arg.size > 64:
-            raise NotImplementedError('float to long')
+            # TODO: move to 80 bits
+            arg = m2_expr.ExprMem(arg.arg, size=64)
         return m2_expr.ExprOp('mem_%.2d_to_double' % arg.size, arg)
     else:
         return arg
@@ -1733,7 +1734,8 @@ def float_prev(flt, popcount=1):
         return None
     i = float_list.index(flt)
     if i < popcount:
-        raise ValueError('broken index')
+        # Drop value (ex: FSTP ST(0))
+        return None
     flt = float_list[i - popcount]
     return flt
 
@@ -1766,11 +1768,10 @@ def fcom(ir, instr, a=None, b=None):
     if a is None and b is None:
         a, b = float_st0, float_st1
     elif b is None:
-        b = a
+        b = mem2double(a)
         a = float_st0
 
     e = []
-    b = mem2double(b)
 
     e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', a, b)))
     e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', a, b)))
@@ -1800,6 +1801,7 @@ def fxam(ir, instr):
 
     e = []
     e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fxam_c0', a)))
+    e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fxam_c1', a)))
     e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fxam_c2', a)))
     e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fxam_c3', a)))
 
@@ -1971,9 +1973,9 @@ def fst(ir, instr, a):
     if isinstance(a, m2_expr.ExprMem):
         if a.size > 64:
             raise NotImplementedError('float to long')
-        src = m2_expr.ExprOp('double_to_mem_%.2d' % a.size, a)
+        src = m2_expr.ExprOp('double_to_mem_%.2d' % a.size, float_st0)
     else:
-        src = a
+        src = float_st0
 
     e.append(m2_expr.ExprAff(a, src))
     e += set_float_cs_eip(instr)
@@ -1981,9 +1983,25 @@ def fst(ir, instr, a):
 
 
 def fstp(ir, instr, a):
-    e, extra = fst(ir, instr, a)
+    e = []
+
+    if isinstance(a, m2_expr.ExprMem):
+        if a.size > 64:
+            # TODO: move to 80 bits
+            a = m2_expr.ExprMem(a.arg, size=64)
+
+        src = m2_expr.ExprOp('double_to_mem_%.2d' % a.size, float_st0)
+        e.append(m2_expr.ExprAff(a, src))
+    else:
+        src = float_st0
+        if float_list.index(a) > 1:
+            # a = st0 -> st0 is dropped
+            # a = st1 -> st0 = st0, useless
+            e.append(m2_expr.ExprAff(float_prev(a), src))
+
+    e += set_float_cs_eip(instr)
     e += float_pop(a)
-    return e, extra
+    return e, []
 
 
 def fist(ir, instr, a):
@@ -1999,14 +2017,6 @@ def fistp(ir, instr, a):
     e += float_pop(a)
     return e, extra
 
-def fist(ir, instr, a):
-    e = []
-    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('double_to_int_%d' % a.size,
-                                               float_st0)))
-
-    e += set_float_cs_eip(instr)
-    return e, []
-
 def fisttp(ir, instr, a):
     e = []
     e.append(m2_expr.ExprAff(a,
@@ -2054,9 +2064,9 @@ def fldpi(ir, instr):
 
 def fldln2(ir, instr):
     value_f = math.log(2)
-    value = struct.unpack('I', struct.pack('f', value_f))[0]
-    return fld(ir, instr, m2_expr.ExprOp('int_32_to_double',
-                                         m2_expr.ExprInt32(value)))
+    value = struct.unpack('Q', struct.pack('d', value_f))[0]
+    return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double',
+                                         m2_expr.ExprInt64(value)))
 
 
 def fldl2e(ir, instr):
@@ -2112,7 +2122,8 @@ def fisubr(ir, instr, a, b=None):
 def fpatan(ir, instr):
     e = []
     a = float_st1
-    e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fpatan', float_st0, float_st1)))
+    e.append(m2_expr.ExprAff(float_prev(a),
+                             m2_expr.ExprOp('fpatan', float_st0, float_st1)))
     e += set_float_cs_eip(instr)
     e += float_pop(a)
     return e, []
@@ -2121,6 +2132,14 @@ def fpatan(ir, instr):
 def fprem(ir, instr):
     e = []
     e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem', float_st0, float_st1)))
+    # Remaining bits (ex: used in argument reduction in tan)
+    remain = m2_expr.ExprOp('fprem_lsb', float_st0, float_st1)
+    e += [m2_expr.ExprAff(float_c0, remain[2:3]),
+          m2_expr.ExprAff(float_c3, remain[1:2]),
+          m2_expr.ExprAff(float_c1, remain[0:1]),
+          # Consider the reduction is always completed
+          m2_expr.ExprAff(float_c2, m2_expr.ExprInt1(0)),
+    ]
     e += set_float_cs_eip(instr)
     return e, []
 
@@ -2170,7 +2189,7 @@ def fnstenv(ir, instr, a):
                                ])
 
     s = instr.mode
-    # The behaviour in 64bit is identical to 64 bit
+    # The behaviour in 64bit is identical to 32 bit
     # This will truncate addresses
     s = min(32, s)
     ad = m2_expr.ExprMem(a.arg, size=16)
@@ -2192,6 +2211,42 @@ def fnstenv(ir, instr, a):
     e.append(m2_expr.ExprAff(ad, float_ds))
     return e, []
 
+def fldenv(ir, instr, a):
+    e = []
+    # Inspired from fnstenv (same TODOs / issues)
+
+    s = instr.mode
+    # The behaviour in 64bit is identical to 32 bit
+    # This will truncate addresses
+    s = min(32, s)
+
+    ## Float control
+    ad = m2_expr.ExprMem(a.arg, size=16)
+    e.append(m2_expr.ExprAff(float_control, ad))
+
+    ## Status word
+    ad = m2_expr.ExprMem(a.arg + m2_expr.ExprInt(s / 8 * 1, size=a.arg.size),
+                         size=16)
+    e += [m2_expr.ExprAff(x, y) for x, y in ((float_c0, ad[8:9]),
+                                             (float_c1, ad[9:10]),
+                                             (float_c2, ad[10:11]),
+                                             (float_stack_ptr, ad[11:14]),
+                                             (float_c3, ad[14:15]))
+          ]
+
+    ## EIP, CS, Address, DS
+    for offset, target in ((3, float_eip[:s]),
+                           (4, float_cs),
+                           (5, float_address[:s]),
+                           (6, float_ds)):
+        size = target.size
+        ad = m2_expr.ExprMem(a.arg + m2_expr.ExprInt(s / 8 * offset,
+                                                     size=a.arg.size),
+                             size=target.size)
+        e.append(m2_expr.ExprAff(target, ad))
+
+    return e, []
+
 
 def fsub(ir, instr, a, b=None):
     a, b = float_implicit_st0(a, b)
@@ -2422,13 +2477,16 @@ def fabs(ir, instr):
 
 
 def fnstsw(ir, instr, dst):
-    args = [(m2_expr.ExprInt8(0),        0, 8),
-            (float_c0,           8, 9),
-            (float_c1,           9, 10),
-            (float_c2,           10, 11),
-            (float_stack_ptr,    11, 14),
-            (float_c3,           14, 15),
-            (m2_expr.ExprInt1(0), 15, 16)]
+    args = [
+        # Exceptions -> 0
+        (m2_expr.ExprInt8(0),0, 8),
+        (float_c0,           8, 9),
+        (float_c1,           9, 10),
+        (float_c2,           10, 11),
+        (float_stack_ptr,    11, 14),
+        (float_c3,           14, 15),
+        # B: FPU is not busy -> 0
+        (m2_expr.ExprInt1(0), 15, 16)]
     e = [m2_expr.ExprAff(dst, m2_expr.ExprCompose(args))]
     return e, []
 
@@ -3625,6 +3683,7 @@ mnemo_func = {'mov': mov,
               'fcmovnbe': fcmovnbe,
               'fcmovnu':  fcmovnu,
               'fnstenv': fnstenv,
+              'fldenv': fldenv,
               'sidt': sidt,
               'sldt': sldt,
               'arpl': arpl,
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index b87c2656..e9d799ca 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -67,8 +67,9 @@ class TranslatorC(Translator):
                   expr.op.endswith("_to_double")   or
                   expr.op.startswith("access_")    or
                   expr.op.startswith("load_")      or
+                  expr.op.startswith("fxam_c")     or
                   expr.op in ["-", "ftan", "frndint", "f2xm1",
-                              "fsin", "fsqrt", "fabs", "fcos"]):
+                              "fsin", "fsqrt", "fabs", "fcos", "fchs"]):
                 return "%s(%s)" % (expr.op, self.from_expr(expr.args[0]))
             else:
                 raise NotImplementedError('Unknown op: %r' % expr.op)
@@ -102,7 +103,8 @@ class TranslatorC(Translator):
                                                    size2mask(expr.args[0].size))
             elif (expr.op.startswith('cpuid') or
                   expr.op.startswith("fcom")  or
-                  expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale"]):
+                  expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale",
+                              "fprem", "fprem_lsb", "fyl2x", "fpatan"]):
                 return "%s(%s, %s)" % (expr.op, self.from_expr(expr.args[0]),
                                        self.from_expr(expr.args[1]))
             elif expr.op == "segm":
diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c
index bf1eb7df..3e5c262d 100644
--- a/miasm2/jitter/vm_mngr.c
+++ b/miasm2/jitter/vm_mngr.c
@@ -1083,6 +1083,18 @@ double int_64_to_double(uint64_t m)
 	return d;
 }
 
+int16_t double_to_int_16(double d)
+{
+	int16_t i;
+
+	i = (int16_t)d;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e int %d\n", d, i);
+#endif
+	return i;
+}
+
 int32_t double_to_int_32(double d)
 {
 	int32_t i;
@@ -1243,10 +1255,77 @@ double fabs(double a)
 	return b;
 }
 
+double fprem(double a, double b)
+{
+	double c;
+	c = fmod(a, b);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e %% %e -> %e\n", a, b, c);
+#endif
+	return c;
+}
+
+unsigned int fprem_lsb(double a, double b)
+{
+	// Inspired from qemu/fpu_helper.c
+	double c;
+	signed long long int q;
+	c = a / b; /* ST0 / ST1 */
+	/* round dblq towards zero */
+	c = (c < 0.0) ? ceil(c) : floor(c);
+
+	/* convert dblq to q by truncating towards zero */
+	if (c < 0.0) {
+	    q = (signed long long int)(-c);
+	} else {
+	    q = (signed long long int)c;
+	}
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e %% %e -> %d %d %d\n", a, b, q & 0x4,
+	       q & 0x2, q & 0x1);
+#endif
+	return q;
+}
+
+double fchs(double a)
+{
+	double b;
+	b = -a;
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf(" - %e -> %e\n", a, b);
+#endif
+	return b;
+}
+
+double fyl2x(double a, double b)
+{
+	double c;
+	c = b * (log(a) / log(2));
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("%e * log(%e) -> %e\n", b, a, c);
+#endif
+	return c;
+}
 
+double fpatan(double a, double b)
+{
+	double c;
+	c = atan2(b, a);
+#ifdef DEBUG_MIASM_DOUBLE
+	dump_float();
+	printf("arctan(%e / %e) -> %e\n", b, a, c);
+#endif
+	return c;
+}
 
 unsigned int fcom_c0(double a, double b)
 {
+	if (isnan(a) || isnan(b))
+		return 1;
 	if (a>=b)
 		return 0;
 	return 1;
@@ -1258,15 +1337,85 @@ unsigned int fcom_c1(double a, double b)
 }
 unsigned int fcom_c2(double a, double b)
 {
+	if (isnan(a) || isnan(b))
+		return 1;
 	return 0;
 }
 unsigned int fcom_c3(double a, double b)
 {
+	if (isnan(a) || isnan(b))
+		return 1;
 	if (a==b)
 		return 1;
 	return 0;
 }
 
+unsigned int fxam_c0(double a)
+{
+	switch(fpclassify(a)) {
+		case FP_NAN:
+			return 1;
+		case FP_NORMAL:
+			return 0;
+		case FP_INFINITE:
+			return 1;
+		case FP_ZERO:
+			return 0;
+		case FP_SUBNORMAL:
+			return 0;
+		default:
+			// ClassEmpty
+			// ClassUnsupported
+			return 0;
+	}
+}
+
+unsigned int fxam_c1(double a)
+{
+	if ((a < 0) || isnan(a))
+		return 1;
+	return 0;
+}
+
+unsigned int fxam_c2(double a)
+{
+	switch(fpclassify(a)) {
+		case FP_NAN:
+			return 0;
+		case FP_NORMAL:
+			return 1;
+		case FP_INFINITE:
+			return 1;
+		case FP_ZERO:
+			return 0;
+		case FP_SUBNORMAL:
+			return 1;
+		default:
+			// ClassEmpty
+			// ClassUnsupported
+			return 0;
+	}
+}
+
+unsigned int fxam_c3(double a)
+{
+	switch(fpclassify(a)) {
+		case FP_NAN:
+			return 0;
+		case FP_NORMAL:
+			return 0;
+		case FP_INFINITE:
+			return 0;
+		case FP_ZERO:
+			return 1;
+		case FP_SUBNORMAL:
+			return 1;
+		default:
+			// ClassEmpty
+			// ClassUnsupported
+			return 0;
+	}
+}
 
 unsigned int double_to_mem_32(double d)
 {
diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h
index c93ed583..8653dd55 100644
--- a/miasm2/jitter/vm_mngr.h
+++ b/miasm2/jitter/vm_mngr.h
@@ -370,11 +370,19 @@ double fscale(double a, double b);
 double f2xm1(double a);
 double fsqrt(double a);
 double fabs(double a);
+double fprem(double a, double b);
+double fchs(double a);
+double fyl2x(double a, double b);
+double fpatan(double a, double b);
+unsigned int fprem_lsb(double a, double b);
 unsigned int fcom_c0(double a, double b);
 unsigned int fcom_c1(double a, double b);
 unsigned int fcom_c2(double a, double b);
 unsigned int fcom_c3(double a, double b);
-
+unsigned int fxam_c0(double a);
+unsigned int fxam_c1(double a);
+unsigned int fxam_c2(double a);
+unsigned int fxam_c3(double a);
 
 
 double mem_32_to_double(unsigned int m);
@@ -382,6 +390,7 @@ double mem_64_to_double(uint64_t m);
 double int_16_to_double(unsigned int m);
 double int_32_to_double(unsigned int m);
 double int_64_to_double(uint64_t m);
+int16_t double_to_int_16(double d);
 int32_t double_to_int_32(double d);
 int64_t double_to_int_64(double d);
 double fadd(double a, double b);