about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2018-07-10 14:12:28 +0200
committerAjax <commial@gmail.com>2018-07-10 14:14:35 +0200
commitdd6fad30a3f78f3903e63c67a886d7db090aa25a (patch)
treeddb6e61cdda0b188bc30ffdb5244798f6ee15801
parent582a30bc9145ad3a88938fddce99908cf306f53c (diff)
downloadmiasm-dd6fad30a3f78f3903e63c67a886d7db090aa25a.tar.gz
miasm-dd6fad30a3f78f3903e63c67a886d7db090aa25a.zip
Expression: introduce operation on float (comparision, equality to NaN/sNan/qNaN)
-rw-r--r--miasm2/expression/expression.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py
index 7d5d9d45..3cf37070 100644
--- a/miasm2/expression/expression.py
+++ b/miasm2/expression/expression.py
@@ -1870,3 +1870,80 @@ def expr_is_signed_lower_or_equal(op1, op2):
     of = _expr_compute_of(op1, op2)
     zf = _expr_compute_zf(op1, op2)
     return zf | (nf ^ of)
+
+# sign bit | exponent | significand
+size_to_IEEE754_info = {
+    16: {
+        "exponent": 5,
+        "significand": 10,
+    },
+    32: {
+        "exponent": 8,
+        "significand": 23,
+    },
+    64: {
+        "exponent": 11,
+        "significand": 52,
+    },
+}
+
+def expr_is_NaN(expr):
+    """Return 1 or 0 on 1 bit if expr represent a NaN value according to IEEE754
+    """
+    info = size_to_IEEE754_info[expr.size]
+    exponent = expr[info["significand"]: info["significand"] + info["exponent"]]
+
+    # exponent is full of 1s and significand is not NULL
+    return ExprCond(exponent - ExprInt(-1, exponent.size),
+                    ExprInt(0, 1),
+                    ExprCond(expr[:info["significand"]], ExprInt(1, 1),
+                             ExprInt(0, 1)))
+
+
+def expr_is_qNaN(expr):
+    """Return 1 or 0 on 1 bit if expr represent a qNaN (quiet) value according to
+    IEEE754
+    """
+    info = size_to_IEEE754_info[expr.size]
+    significand_top = expr[info["significand"]: info["significand"] + 1]
+    return expr_is_NaN(expr) & significand_top
+
+
+def expr_is_sNaN(expr):
+    """Return 1 or 0 on 1 bit if expr represent a sNaN (signalling) value according
+    to IEEE754
+    """
+    info = size_to_IEEE754_info[expr.size]
+    significand_top = expr[info["significand"]: info["significand"] + 1]
+    return expr_is_NaN(expr) & ~significand_top
+
+
+def expr_is_float_lower(op1, op2):
+    """Return 1 on 1 bit if @op1 < @op2, 0 otherwise.
+    /!\ Assume @op1 and @op2 are not NaN
+    Comparision is the floating point one, defined in IEEE754
+    """
+    sign1, sign2 = op1.msb(), op2.msb()
+    magn1, magn2 = op1[:-1], op2[:-1]
+    return ExprCond(sign1 ^ sign2,
+                    # Sign different, only the sign matters
+                    sign1, # sign1 ? op1 < op2 : op1 >= op2
+                    # Sign equals, the result is inversed for negatives
+                    sign1 ^ (expr_is_unsigned_lower(magn1, magn2)))
+
+
+def expr_is_float_equal(op1, op2):
+    """Return 1 on 1 bit if @op1 == @op2, 0 otherwise.
+    /!\ Assume @op1 and @op2 are not NaN
+    Comparision is the floating point one, defined in IEEE754
+    """
+    sign1, sign2 = op1.msb(), op2.msb()
+    magn1, magn2 = op1[:-1], op2[:-1]
+    return ExprCond(magn1 ^ magn2,
+                    ExprInt(0, 1),
+                    ExprCond(magn1,
+                             # magn1 == magn2, are the signal equals?
+                             ~(sign1 ^ sign2),
+                             # Special case: -0.0 == +0.0
+                             ExprInt(1, 1))
+                    )