about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/arm/sem.py39
-rw-r--r--miasm2/arch/ppc/sem.py25
-rw-r--r--miasm2/ir/translators/C.py65
-rw-r--r--miasm2/jitter/bn.c86
-rw-r--r--miasm2/jitter/bn.h13
-rw-r--r--miasm2/jitter/llvmconvert.py37
6 files changed, 240 insertions, 25 deletions
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py
index 64403206..3e017d1f 100644
--- a/miasm2/arch/arm/sem.py
+++ b/miasm2/arch/arm/sem.py
@@ -1754,15 +1754,52 @@ class ir_arml(IntermediateRepresentation):
 
             irblocks.append(irblock)
 
+            it_instr_irblocks = []
             assignments = []
             loc = loc_do
+
             split = self.add_instr_to_current_state(
                 instr, block, assignments,
-                irblocks, gen_pc_updt
+                it_instr_irblocks, gen_pc_updt
             )
             if split:
                 raise NotImplementedError("Unsupported instr in IT block (%s)" % instr)
 
+            if it_instr_irblocks:
+                assert len(it_instr_irblocks) == 1
+                it_instr_irblocks = it_instr_irblocks.pop()
+            # Remove flags assignment if instr != [CMP, CMN, TST]
+            if instr.name not in ["CMP", "CMN", "TST"]:
+                # Fix assignments
+                out = []
+                for assignment in assignments:
+                    assignment = AssignBlock(
+                        {
+                            dst:src for (dst, src) in assignment.iteritems()
+                            if dst not in [zf, nf, of, cf]
+                        },
+                        assignment.instr
+                    )
+                    out.append(assignment)
+                assignments = out
+                # Fix extra irblocksx
+                new_irblocks = []
+                for irblock in it_instr_irblocks:
+                    out = []
+                    for tmp_assignment in irblock:
+                        assignment = AssignBlock(
+                            {
+                                dst:src for (dst, src) in assignment.iteritems()
+                                if dst not in [zf, nf, of, cf]
+                            },
+                            assignment.instr
+                        )
+                        out.append(assignment)
+                    new_irblock = IRBlock(irblock.loc_key, out)
+                    new_irblocks.append(new_irblock)
+                it_instr_irblocks = new_irblocks
+
+            irblocks += it_instr_irblocks
             dst = ExprAssign(self.IRDst, ExprLoc(loc_next, 32))
             dst_blk = AssignBlock([dst], instr)
             assignments.append(dst_blk)
diff --git a/miasm2/arch/ppc/sem.py b/miasm2/arch/ppc/sem.py
index 44895624..558450b2 100644
--- a/miasm2/arch/ppc/sem.py
+++ b/miasm2/arch/ppc/sem.py
@@ -17,7 +17,12 @@ crf_dict = dict((ExprId("CR%d" % i, 4),
                        for bit in ['LT', 'GT', 'EQ', 'SO' ] ))
                 for i in xrange(8) )
 
-ctx = { 'crf_dict': crf_dict, 'spr_dict': spr_dict }
+ctx = {
+    'crf_dict': crf_dict,
+    'spr_dict': spr_dict,
+    'expr': expr,
+}
+
 ctx.update(all_regs_ids_byname)
 sbuild = SemBuilder(ctx)
 
@@ -746,22 +751,16 @@ def mn_do_nop_warn(ir, instr, *args):
 
 @sbuild.parse
 def mn_cmp_signed(arg1, arg2, arg3):
-    crf_dict[arg1]['LT'] = ((arg2 - arg3) ^
-                            ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb()
-    crf_dict[arg1]['GT'] = ((arg3 - arg2) ^
-                            ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))).msb()
-    crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1)
+    crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg2, arg3)
+    crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg3, arg2)
+    crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3)
     crf_dict[arg1]['SO'] = XER_SO
 
 @sbuild.parse
 def mn_cmp_unsigned(arg1, arg2, arg3):
-    crf_dict[arg1]['LT'] = (((arg2 - arg3) ^
-                             ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^
-                            arg2 ^ arg3).msb()
-    crf_dict[arg1]['GT'] = (((arg3 - arg2) ^
-                             ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))) ^
-                            arg2 ^ arg3).msb()
-    crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1)
+    crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg2, arg3)
+    crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg3, arg2)
+    crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3)
     crf_dict[arg1]['SO'] = XER_SO
 
 def mn_nop(ir, instr, *args):
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index a239383b..5a55237f 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -1,7 +1,9 @@
 from miasm2.ir.translators.translator import Translator
 from miasm2.expression.modint import size2mask
 from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose, \
-    TOK_EQUAL
+    TOK_EQUAL, \
+    TOK_INF_SIGNED, TOK_INF_UNSIGNED, \
+    TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED
 
 def int_size_to_bn(value, size):
     if size < 32:
@@ -17,6 +19,22 @@ def int_size_to_bn(value, size):
     return int_str, size_nibble
 
 
+TOK_CMP_TO_NATIVE_C = {
+    TOK_EQUAL: "==",
+    TOK_INF_SIGNED: "<",
+    TOK_INF_UNSIGNED: "<",
+    TOK_INF_EQUAL_SIGNED: "<=",
+    TOK_INF_EQUAL_UNSIGNED: "<=",
+}
+
+TOK_CMP_TO_BIGNUM_C = {
+    TOK_EQUAL: "equal",
+    TOK_INF_SIGNED: "inf_signed",
+    TOK_INF_UNSIGNED: "inf_unsigned",
+    TOK_INF_EQUAL_SIGNED: "inf_equal_signed",
+    TOK_INF_EQUAL_UNSIGNED: "inf_equal_unsigned",
+}
+
 
 class TranslatorC(Translator):
     "Translate a Miasm expression to an equivalent C code"
@@ -238,14 +256,7 @@ class TranslatorC(Translator):
                 raise NotImplementedError('Unknown op: %r' % expr.op)
 
         elif len(expr.args) == 2:
-            if expr.op == TOK_EQUAL:
-                return '(((%s&%s) == (%s&%s))?1:0)' % (
-                    self.from_expr(expr.args[0]),
-                    self._size2mask(expr.args[0].size),
-                    self.from_expr(expr.args[1]),
-                    self._size2mask(expr.args[1].size),
-                )
-            elif expr.op in self.dct_shift:
+            if expr.op in self.dct_shift:
                 arg0 = self.from_expr(expr.args[0])
                 arg1 = self.from_expr(expr.args[1])
                 if expr.size <= self.NATIVE_INT_MAX_SIZE:
@@ -399,6 +410,42 @@ class TranslatorC(Translator):
                     self.from_expr(expr.args[0]),
                     self.from_expr(expr.args[1])
                 )
+
+
+            elif expr.op in [
+                    TOK_EQUAL,
+                    TOK_INF_SIGNED,
+                    TOK_INF_UNSIGNED,
+                    TOK_INF_EQUAL_SIGNED,
+                    TOK_INF_EQUAL_UNSIGNED,
+            ]:
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    op = TOK_CMP_TO_NATIVE_C[expr.op]
+                    if expr.op in [TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED]:
+                        cast = "(int%d_t)" % expr.args[0].size
+                    else:
+                        cast = "(uint%d_t)" % expr.args[0].size
+                    out = '((%s%s %s %s%s)?1:0)' % (
+                        cast,
+                        arg0,
+                        op,
+                        cast,
+                        arg1
+                    )
+                else:
+                    op = TOK_CMP_TO_BIGNUM_C[expr.op]
+                    out = "bignum_is_%s(%s, %s)" % (
+                        op,
+                        arg0,
+                        arg1
+                    )
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
+
             else:
                 raise NotImplementedError('Unknown op: %r' % expr.op)
 
diff --git a/miasm2/jitter/bn.c b/miasm2/jitter/bn.c
index c621d102..dd4f34ef 100644
--- a/miasm2/jitter/bn.c
+++ b/miasm2/jitter/bn.c
@@ -579,6 +579,92 @@ int bignum_cmp(bn_t a, bn_t b)
 }
 
 
+/* Signed compare bn */
+int bignum_cmp_signed(bn_t a, bn_t b)
+{
+	int i = BN_ARRAY_SIZE;
+	do {
+		i -= 1; /* Decrement first, to start with last array element */
+		if ((DTYPE_SIGNED)a.array[i] > (DTYPE_SIGNED)b.array[i]) {
+			return LARGER;
+		}
+		else if ((DTYPE_SIGNED)a.array[i] < (DTYPE_SIGNED)b.array[i]) {
+			return SMALLER;
+		}
+	}
+	while (i != 0);
+
+	return EQUAL;
+}
+
+
+/* Unsigned compare bn */
+int bignum_cmp_unsigned(bn_t a, bn_t b)
+{
+	return bignum_cmp(a, b);
+}
+
+
+/* Return 1 if a == b else 0 */
+int bignum_is_equal(bn_t a, bn_t b)
+{
+	int ret;
+	ret = bignum_cmp_unsigned(a, b);
+	if (ret == EQUAL)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* Return 1 if a <u b else 0 */
+int bignum_is_inf_unsigned(bn_t a, bn_t b)
+{
+	int ret;
+	ret = bignum_cmp_unsigned(a, b);
+	if (ret == SMALLER)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* Return 1 if a <=u b else 0 */
+int bignum_is_inf_equal_unsigned(bn_t a, bn_t b)
+{
+	int ret;
+	ret = bignum_cmp_unsigned(a, b);
+	if (ret == EQUAL || ret == SMALLER)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* Return 1 if a <s b else 0 */
+int bignum_is_inf_signed(bn_t a, bn_t b)
+{
+	int ret;
+	ret = bignum_cmp_signed(a, b);
+	if (ret == SMALLER)
+		return 1;
+	else
+		return 0;
+}
+
+
+/* Return 1 if a <=s b else 0 */
+int bignum_is_inf_equal_signed(bn_t a, bn_t b)
+{
+	int ret;
+	ret = bignum_cmp_signed(a, b);
+	if (ret == EQUAL || ret == SMALLER)
+		return 1;
+	else
+		return 0;
+}
+
+
 int bignum_is_zero(bn_t n)
 {
 	//require(n, "n is null");
diff --git a/miasm2/jitter/bn.h b/miasm2/jitter/bn.h
index f0a13b53..1aa6b432 100644
--- a/miasm2/jitter/bn.h
+++ b/miasm2/jitter/bn.h
@@ -56,6 +56,7 @@ Code slightly modified to support ast generation calculus style from Expr.
 #elif (WORD_SIZE == 1)
   /* Data type of array in structure */
   #define DTYPE                    uint8_t
+  #define DTYPE_SIGNED             int8_t
   /* bitmask for getting MSB */
   #define DTYPE_MSB                ((DTYPE_TMP)(0x80))
   /* Data-type larger than DTYPE, for holding intermediate results of calculations */
@@ -67,6 +68,7 @@ Code slightly modified to support ast generation calculus style from Expr.
   #define MAX_VAL                  ((DTYPE_TMP)0xFF)
 #elif (WORD_SIZE == 2)
   #define DTYPE                    uint16_t
+  #define DTYPE_SIGNED             int16_t
   #define DTYPE_TMP                uint32_t
   #define DTYPE_MSB                ((DTYPE_TMP)(0x8000))
   #define SPRINTF_FORMAT_STR       "%.04x"
@@ -74,6 +76,7 @@ Code slightly modified to support ast generation calculus style from Expr.
   #define MAX_VAL                  ((DTYPE_TMP)0xFFFF)
 #elif (WORD_SIZE == 4)
   #define DTYPE                    uint32_t
+  #define DTYPE_SIGNED             int32_t
   #define DTYPE_TMP                uint64_t
   #define DTYPE_MSB                ((DTYPE_TMP)(0x80000000))
   #define SPRINTF_FORMAT_STR       "%.08x"
@@ -132,7 +135,15 @@ _MIASM_EXPORT bn_t bignum_a_rshift(bn_t a, int size, int nbits); /* b = a a>> nb
 _MIASM_EXPORT bn_t bignum_not(bn_t a); /* c = ~a */
 
 /* Special operators and comparison */
-_MIASM_EXPORT int  bignum_cmp(bn_t a, bn_t b);               /* Compare: returns LARGER, EQUAL or SMALLER */
+_MIASM_EXPORT int bignum_cmp(bn_t a, bn_t b);                      /* Compare: returns LARGER, EQUAL or SMALLER */
+_MIASM_EXPORT int bignum_is_equal(bn_t a, bn_t b);                 /* Return 1 if a == b else 0 */
+_MIASM_EXPORT int bignum_is_inf_unsigned(bn_t a, bn_t b);          /* Return 1 if a <u b else 0 */
+_MIASM_EXPORT int bignum_is_inf_equal_unsigned(bn_t a, bn_t b);    /* Return 1 if a <=u b else 0 */
+_MIASM_EXPORT int bignum_is_inf_signed(bn_t a, bn_t b);            /* Return 1 if a <s b else 0 */
+_MIASM_EXPORT int bignum_is_inf_equal_signed(bn_t a, bn_t b);      /* Return 1 if a <=s b else 0 */
+
+
+
 _MIASM_EXPORT int  bignum_is_zero(bn_t n);                         /* For comparison with zero */
 _MIASM_EXPORT bn_t bignum_inc(bn_t n);                             /* Increment: add one to n */
 _MIASM_EXPORT bn_t bignum_dec(bn_t n);                             /* Decrement: subtract one from n */
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index a31348cf..fd32001c 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -15,7 +15,11 @@ import os
 from llvmlite import binding as llvm
 from llvmlite import ir as llvm_ir
 from miasm2.expression.expression import ExprId, ExprInt, ExprMem, ExprSlice, \
-    ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey, Expr
+    ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey, Expr, \
+    TOK_EQUAL, \
+    TOK_INF_SIGNED, TOK_INF_UNSIGNED, \
+    TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED
+
 import miasm2.jitter.csts as m2_csts
 import miasm2.core.asmblock as m2_asmblock
 from miasm2.jitter.codegen import CGen, Attributes
@@ -1074,6 +1078,37 @@ class LLVMFunction(object):
                 self.update_cache(expr, ret)
                 return ret
 
+            if op in [
+                    TOK_EQUAL,
+                    TOK_INF_SIGNED,
+                    TOK_INF_EQUAL_SIGNED,
+                    TOK_INF_UNSIGNED,
+                    TOK_INF_EQUAL_UNSIGNED,
+            ]:
+                if op == TOK_EQUAL:
+                    opname = "=="
+                    callback = builder.icmp_unsigned
+                elif op == TOK_INF_SIGNED:
+                    opname = "<"
+                    callback = builder.icmp_signed
+                elif op == TOK_INF_UNSIGNED:
+                    opname = "<"
+                    callback = builder.icmp_unsigned
+                elif op == TOK_INF_EQUAL_SIGNED:
+                    opname = "<="
+                    callback = builder.icmp_signed
+                elif op == TOK_INF_EQUAL_UNSIGNED:
+                    opname = "<"
+                    callback = builder.icmp_unsigned
+
+                left = self.add_ir(expr.args[0])
+                right = self.add_ir(expr.args[1])
+
+                ret = callback(opname, left, right)
+                self.update_cache(expr, ret)
+
+                return ret
+
             if len(expr.args) > 1:
 
                 if op == "*":