about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/sem.py105
-rw-r--r--miasm2/ir/translators/C.py13
-rw-r--r--miasm2/jitter/llvmconvert.py24
-rw-r--r--miasm2/jitter/op_semantics.c102
-rw-r--r--miasm2/jitter/op_semantics.h9
5 files changed, 126 insertions, 127 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index ec85ae32..0cb9f3e2 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -2136,17 +2136,98 @@ def ftst(_, instr):
     return e, []
 
 
-def fxam(_, instr):
+def fxam(ir, instr):
+    """
+    NaN:
+        C3, C2, C0 = 001;
+    Normal:
+        C3, C2, C0 = 010;
+    Infinity:
+        C3, C2, C0 = 011;
+    Zero:
+        C3, C2, C0 = 100;
+    Empty:
+        C3, C2, C0 = 101;
+    Denormal:
+        C3, C2, C0 = 110;
+
+    C1 = sign bit of ST; (* 0 for positive, 1 for negative *)
+    """
     dst = float_st0
 
-    e = []
-    e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fxam_c0', dst)))
-    e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fxam_c1', dst)))
-    e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fxam_c2', dst)))
-    e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fxam_c3', dst)))
+    # Empty not handled
+    locs = {}
+    for name in ["NaN", "Normal", "Infinity", "Zero", "Denormal"]:
+        locs[name] = ir.gen_loc_key_and_expr(ir.IRDst.size)
+    loc_next = ir.get_next_loc_key(instr)
+    loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size)
 
-    e += set_float_cs_eip(instr)
-    return e, []
+    # if Denormal:
+    #     if zero:
+    #         do_zero
+    #     else:
+    #         do_denormal
+    # else:
+    #     if Nan:
+    #         do_nan
+    #     else:
+    #         if infinity:
+    #             do_infinity
+    #         else:
+    #             do_normal
+
+    irdst = m2_expr.ExprCond(
+        m2_expr.expr_is_IEEE754_denormal(dst),
+        m2_expr.ExprCond(m2_expr.expr_is_IEEE754_zero(dst),
+                 locs["Zero"][1],
+                 locs["Denormal"][1],
+        ),
+        m2_expr.ExprCond(m2_expr.expr_is_NaN(dst),
+                 locs["NaN"][1],
+                 m2_expr.ExprCond(m2_expr.expr_is_infinite(dst),
+                          locs["Infinity"][1],
+                          locs["Normal"][1],
+                 )
+        )
+    )
+    base = [m2_expr.ExprAff(ir.IRDst, irdst),
+         m2_expr.ExprAff(float_c1, dst.msb())
+    ]
+    base += set_float_cs_eip(instr)
+
+    out = [
+        IRBlock(locs["Zero"][0], [AssignBlock({
+            float_c0: m2_expr.ExprInt(0, float_c0.size),
+            float_c2: m2_expr.ExprInt(0, float_c2.size),
+            float_c3: m2_expr.ExprInt(1, float_c3.size),
+            ir.IRDst: loc_next_expr,
+        }, instr)]),
+        IRBlock(locs["Denormal"][0], [AssignBlock({
+            float_c0: m2_expr.ExprInt(0, float_c0.size),
+            float_c2: m2_expr.ExprInt(1, float_c2.size),
+            float_c3: m2_expr.ExprInt(1, float_c3.size),
+            ir.IRDst: loc_next_expr,
+        }, instr)]),
+        IRBlock(locs["NaN"][0], [AssignBlock({
+            float_c0: m2_expr.ExprInt(1, float_c0.size),
+            float_c2: m2_expr.ExprInt(0, float_c2.size),
+            float_c3: m2_expr.ExprInt(0, float_c3.size),
+            ir.IRDst: loc_next_expr,
+        }, instr)]),
+        IRBlock(locs["Infinity"][0], [AssignBlock({
+            float_c0: m2_expr.ExprInt(1, float_c0.size),
+            float_c2: m2_expr.ExprInt(1, float_c2.size),
+            float_c3: m2_expr.ExprInt(0, float_c3.size),
+            ir.IRDst: loc_next_expr,
+        }, instr)]),
+        IRBlock(locs["Normal"][0], [AssignBlock({
+            float_c0: m2_expr.ExprInt(0, float_c0.size),
+            float_c2: m2_expr.ExprInt(1, float_c2.size),
+            float_c3: m2_expr.ExprInt(0, float_c3.size),
+            ir.IRDst: loc_next_expr,
+        }, instr)]),
+    ]
+    return base, out
 
 
 def ficom(_, instr, dst, src=None):
@@ -2485,10 +2566,10 @@ def fprem(_, instr):
     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]),
+    quotient = m2_expr.ExprOp('fp_to_sint32', m2_expr.ExprOp('fpround_towardszero', m2_expr.ExprOp('fdiv', float_st0, float_st1)))
+    e += [m2_expr.ExprAff(float_c0, quotient[2:3]),
+          m2_expr.ExprAff(float_c3, quotient[1:2]),
+          m2_expr.ExprAff(float_c1, quotient[0:1]),
           # Consider the reduction is always completed
           m2_expr.ExprAff(float_c2, m2_expr.ExprInt(0, 1)),
           ]
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index 6700e826..71f42636 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -327,9 +327,16 @@ class TranslatorC(Translator):
                 return "%s(%s, %s)" % (expr.op,
                                        self.from_expr(expr.args[0]),
                                        self.from_expr(expr.args[1]))
-            elif (expr.op.startswith("fcom")  or
-                  expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale",
-                              "fprem", "fprem_lsb", "fyl2x", "fpatan"]):
+            elif expr.op.startswith("fcom"):
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+                if not expr.args[0].size <= self.NATIVE_INT_MAX_SIZE:
+                    raise ValueError("Bad semantic: fpu do operations do not support such size")
+                out = "fpu_%s(%s, %s)" % (expr.op, arg0, arg1)
+                return out
+
+            elif expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale",
+                             "fprem", "fyl2x", "fpatan"]:
                 arg0 = self.from_expr(expr.args[0])
                 arg1 = self.from_expr(expr.args[1])
                 if not expr.args[0].size <= self.NATIVE_INT_MAX_SIZE:
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index e7bd004c..1c2b453b 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -280,22 +280,26 @@ class LLVMContext_JIT(LLVMContext):
               "x86_cpuid": {"ret": itype,
                         "args": [itype,
                                  itype]},
-              "fcom_c0": {"ret": itype,
+              "fpu_fcom_c0": {"ret": itype,
                           "args": [dtype,
                                    dtype]},
-              "fcom_c1": {"ret": itype,
+              "fpu_fcom_c1": {"ret": itype,
                           "args": [dtype,
                                    dtype]},
-              "fcom_c2": {"ret": itype,
+              "fpu_fcom_c2": {"ret": itype,
                           "args": [dtype,
                                    dtype]},
-              "fcom_c3": {"ret": itype,
+              "fpu_fcom_c3": {"ret": itype,
                           "args": [dtype,
                                    dtype]},
               "llvm.sqrt.f32": {"ret": ftype,
                                 "args": [ftype]},
               "llvm.sqrt.f64": {"ret": dtype,
                                 "args": [dtype]},
+              "llvm.fabs.f32": {"ret": ftype,
+                                "args": [ftype]},
+              "llvm.fabs.f64": {"ret": dtype,
+                                "args": [dtype]},
         }
 
         for k in [8, 16]:
@@ -999,7 +1003,7 @@ class LLVMFunction():
             if op in ["fcom_c0", "fcom_c1", "fcom_c2", "fcom_c3"]:
                 arg1 = self.add_ir(expr.args[0])
                 arg2 = self.add_ir(expr.args[0])
-                fc_name = op
+                fc_name = "fpu_%s" % op
                 fc_ptr = self.mod.get_global(fc_name)
                 casted_args = [
                     builder.bitcast(arg1, llvm_ir.DoubleType()),
@@ -1014,17 +1018,19 @@ class LLVMFunction():
                 self.update_cache(expr, ret)
                 return ret
 
-            if op in ["fsqrt"]:
+            if op in ["fsqrt", "fabs"]:
                 arg = self.add_ir(expr.args[0])
+                if op == "fsqrt":
+                    op = "sqrt"
 
-                # Apply the correct sqrt func
+                # Apply the correct func
                 if expr.size == 32:
                     arg = builder.bitcast(arg, llvm_ir.FloatType())
-                    ret = builder.call(self.mod.get_global("llvm.sqrt.f32"),
+                    ret = builder.call(self.mod.get_global("llvm.%s.f32" % op),
                                        [arg])
                 elif expr.size == 64:
                     arg = builder.bitcast(arg, llvm_ir.DoubleType())
-                    ret = builder.call(self.mod.get_global("llvm.sqrt.f64"),
+                    ret = builder.call(self.mod.get_global("llvm.%s.f64" % op),
                                        [arg])
                 else:
                     raise RuntimeError("Unsupported precision: %x", expr.size)
diff --git a/miasm2/jitter/op_semantics.c b/miasm2/jitter/op_semantics.c
index c3e11189..a0c2316e 100644
--- a/miasm2/jitter/op_semantics.c
+++ b/miasm2/jitter/op_semantics.c
@@ -582,49 +582,26 @@ uint64_t fpu_fsqrt64(uint64_t a)
 	return *((uint64_t*)&b);
 }
 
-double fpu_fabs(double a)
+uint64_t fpu_fabs64(uint64_t a)
 {
 	double b;
-	b = abs(a);
+	b = abs(*((double*)&a));
 #ifdef DEBUG_MIASM_DOUBLE
 	dump_float();
 	printf("%e abs %e\n", a, b);
 #endif
-	return b;
+	return *((uint64_t*)&b);
 }
 
-double fpu_fprem(double a, double b)
+uint64_t fpu_fprem64(uint64_t a, uint64_t b)
 {
 	double c;
-	c = fmod(a, b);
+	c = fmod(*((double*)&a), *((double*)&b));
 #ifdef DEBUG_MIASM_DOUBLE
 	dump_float();
 	printf("%e %% %e -> %e\n", a, b, c);
 #endif
-	return c;
-}
-
-unsigned int fpu_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;
+	return *((uint64_t*)&c);
 }
 
 double fpu_fchs(double a)
@@ -688,73 +665,6 @@ unsigned int fpu_fcom_c3(double a, double b)
 	return 0;
 }
 
-unsigned int fpu_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 fpu_fxam_c1(double a)
-{
-	if ((a < 0) || isnan(a))
-		return 1;
-	return 0;
-}
-
-unsigned int fpu_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 fpu_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;
-	}
-}
-
 uint64_t sint_to_fp_64(int64_t a)
 {
 	double result = (double) a;
diff --git a/miasm2/jitter/op_semantics.h b/miasm2/jitter/op_semantics.h
index 3d7ca31a..c56c41cf 100644
--- a/miasm2/jitter/op_semantics.h
+++ b/miasm2/jitter/op_semantics.h
@@ -115,20 +115,15 @@ double fpu_fscale(double a, double b);
 double fpu_f2xm1(double a);
 uint32_t fpu_fsqrt32(uint32_t a);
 uint64_t fpu_fsqrt64(uint64_t a);
-double fpu_fabs(double a);
-double fpu_fprem(double a, double b);
+uint64_t fpu_fabs64(uint64_t a);
+uint64_t fpu_fprem64(uint64_t a, uint64_t b);
 double fpu_fchs(double a);
 double fpu_fyl2x(double a, double b);
 double fpu_fpatan(double a, double b);
-unsigned int fpu_fprem_lsb(double a, double b);
 unsigned int fpu_fcom_c0(double a, double b);
 unsigned int fpu_fcom_c1(double a, double b);
 unsigned int fpu_fcom_c2(double a, double b);
 unsigned int fpu_fcom_c3(double a, double b);
-unsigned int fpu_fxam_c0(double a);
-unsigned int fpu_fxam_c1(double a);
-unsigned int fpu_fxam_c2(double a);
-unsigned int fpu_fxam_c3(double a);
 
 uint64_t sint_to_fp_64(int64_t a);
 uint32_t sint_to_fp_32(int32_t a);