diff options
| author | Ajax <commial@gmail.com> | 2018-08-30 14:42:08 +0200 |
|---|---|---|
| committer | Ajax <commial@gmail.com> | 2018-09-03 19:07:21 +0200 |
| commit | ecf6cac84d3330c923a6c65bb424e2911f9065a6 (patch) | |
| tree | d1f859ada761e3abe2391b161661d84d6eacff16 | |
| parent | 579d439700d1944f067a2c28d4aa9ea6736d631a (diff) | |
| download | miasm-ecf6cac84d3330c923a6c65bb424e2911f9065a6.tar.gz miasm-ecf6cac84d3330c923a6c65bb424e2911f9065a6.zip | |
Add support for more FP operations, expand fxam
| -rw-r--r-- | miasm2/arch/x86/sem.py | 105 | ||||
| -rw-r--r-- | miasm2/ir/translators/C.py | 13 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 24 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.c | 102 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.h | 9 |
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); |