about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZheng Luo <vicluo96@gmail.com>2019-10-06 16:53:04 -0700
committerZheng Luo <vicluo96@gmail.com>2019-10-06 21:10:25 -0700
commitfbdf26b0b4f2e88005d5d133c19d0ebf6864315d (patch)
tree325e62de29130421101db08a16e7534368fd0528
parent6fdd9a51103949c9b21c74a82916e6e82d436330 (diff)
downloadmiasm-fbdf26b0b4f2e88005d5d133c19d0ebf6864315d.tar.gz
miasm-fbdf26b0b4f2e88005d5d133c19d0ebf6864315d.zip
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 <entry>:
    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]
Diffstat (limited to '')
-rw-r--r--miasm/arch/x86/sem.py31
1 files changed, 31 insertions, 0 deletions
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,