diff options
| -rw-r--r-- | miasm2/arch/x86/sem.py | 115 | ||||
| -rw-r--r-- | miasm2/ir/translators/C.py | 6 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.c | 149 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.h | 11 |
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); |