From fbdf26b0b4f2e88005d5d133c19d0ebf6864315d Mon Sep 17 00:00:00 2001 From: Zheng Luo Date: Sun, 6 Oct 2019 16:53:04 -0700 Subject: arch: x86: add translation from roundsd to IR This change adds three new ops for rounding: - 'fpround_towardsnearest': rounds to nearest int, even for ties - 'fpround_down': rounds to nearest int <= float - 'fpround_up': rounds to nearest int >= float - 'fpround_towardszero'(existing): rounds to nearest int s.t. |int| <= |float| For a variant of roundsd that uses mxcsr register as the rounding mode, currently we assume it's fpround_towardsnearest. This may cause trouble if the program modifies MXCSR register. Tested: $ objdump -dSC rounds.so 0000000000001000 : 1000: 66 0f 3a 0b c0 01 roundsd $0x1,%xmm0,%xmm0 1006: 66 0f 3a 0a c0 0c roundss $0xc,%xmm0,%xmm0 100c: c3 retq $ cat test.py from miasm.analysis.binary import * from miasm.analysis.machine import Machine from miasm.expression.simplifications import expr_simp with open('rounds.so', 'rb') as f: cont = ContainerELF.from_stream(f) machine = Machine(cont.arch) mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) asmcfg = mdis.dis_multiblock(cont.loc_db.get_name_offset('entry')) ir = machine.ir(asmcfg.loc_db) ircfg = ir.new_ircfg_from_asmcfg(asmcfg) ircfg.simplify(expr_simp) print(ircfg.blocks[ircfg.heads()[0]].to_string()) $ python test.py loc_key_0: XMM0 = {fpround_down(XMM0[0:64]) 0 64, XMM0[64:128] 64 128} XMM0 = {fpround_towardsnearest(XMM0[0:32]) 0 32, XMM0[32:128] 32 128} RSP = RSP + 0x8 RIP = @64[RSP] IRDst = @64[RSP] --- miasm/arch/x86/sem.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py index 962667b4..370370e4 100644 --- a/miasm/arch/x86/sem.py +++ b/miasm/arch/x86/sem.py @@ -5080,6 +5080,33 @@ def movmskpd(ir, instr, dst, src): out.append(src[(64 * i) + 63:(64 * i) + 64]) return [m2_expr.ExprAssign(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], [] +def _roundscalar(ir, inst, dst, src, imm8, double): + res = None + ctl = int(imm8) + dst_expr = dst[:64] if double else dst[:32] + src_expr = src[:64] if double else src[:32] + if ctl & 0x4 != 0: + # Use MXCSR rounding config + # TODO: here we assume it's round to nearest, ties to even + res = m2_expr.ExprOp('fpround_towardsnearest', src_expr) + else: + # Use encoded rounding mechanism + rounding_mechanism = ctl & 0x3 + ROUNDING_MODE = { + 0x0: 'fpround_towardsnearest', + 0x1: 'fpround_down', + 0x2: 'fpround_up', + 0x3: 'fpround_towardszero' + } + res = m2_expr.ExprOp(ROUNDING_MODE[rounding_mechanism], src_expr) + return [m2_expr.ExprAssign(dst_expr, res)], [] + +def roundss(ir, inst, dst, src, imm8): + return _roundscalar(ir, inst, dst, src, imm8, False) + +def roundsd(ir, inst, dst, src, imm8): + return _roundscalar(ir, inst, dst, src, imm8, True) + def fxsave(_ir, _instr, _src): # Implemented as a NOP for now return [], [] @@ -5523,6 +5550,10 @@ mnemo_func = {'mov': mov, "divps": divps, "divpd": divpd, + # Rounding + "roundss": roundss, + "roundsd": roundsd, + # Comparisons (floating-point) # "minps": minps, -- cgit 1.4.1