diff options
| author | Ajax <commial@gmail.com> | 2018-07-10 14:12:28 +0200 |
|---|---|---|
| committer | Ajax <commial@gmail.com> | 2018-07-10 14:14:35 +0200 |
| commit | dd6fad30a3f78f3903e63c67a886d7db090aa25a (patch) | |
| tree | ddb6e61cdda0b188bc30ffdb5244798f6ee15801 | |
| parent | 582a30bc9145ad3a88938fddce99908cf306f53c (diff) | |
| download | miasm-dd6fad30a3f78f3903e63c67a886d7db090aa25a.tar.gz miasm-dd6fad30a3f78f3903e63c67a886d7db090aa25a.zip | |
Expression: introduce operation on float (comparision, equality to NaN/sNan/qNaN)
| -rw-r--r-- | miasm2/expression/expression.py | 77 |
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)) + ) |