about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/sem.py51
-rw-r--r--miasm2/ir/translators/C.py8
-rw-r--r--miasm2/jitter/vm_mngr.c19
-rw-r--r--test/ir/ir2C.py2
-rw-r--r--test/samples/x86_32/bsr_bsf.S42
-rw-r--r--test/test_all.py8
6 files changed, 95 insertions, 35 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index bc98baf3..928554cb 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -2496,32 +2496,41 @@ def aas(ir, instr, ):
     return e, []
 
 
-def bsf(ir, instr, a, b):
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
-
-    e = [m2_expr.ExprAff(zf, m2_expr.ExprCond(b, m2_expr.ExprInt_from(zf, 0),
-                                              m2_expr.ExprInt_from(zf, 1)))]
+def bsr_bsf(ir, instr, a, b, op_name):
+    """
+    IF SRC == 0
+        ZF = 1
+        DEST is left unchanged
+    ELSE
+        ZF = 0
+        DEST = @op_name(SRC)
+    """
+    lbl_src_null = m2_expr.ExprId(ir.gen_label(), instr.mode)
+    lbl_src_not_null = m2_expr.ExprId(ir.gen_label(), instr.mode)
+    lbl_next = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
 
-    e_do = []
-    e_do.append(m2_expr.ExprAff(a, m2_expr.ExprOp('bsf', b)))
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(b, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
+    aff_dst = m2_expr.ExprAff(ir.IRDst, lbl_next)
+    e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(b,
+                                                    lbl_src_not_null,
+                                                    lbl_src_null))]
+    e_src_null = []
+    e_src_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt_from(zf, 1)))
+    # XXX destination is undefined
+    e_src_null.append(aff_dst)
 
+    e_src_not_null = []
+    e_src_not_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt_from(zf, 0)))
+    e_src_not_null.append(m2_expr.ExprAff(a, m2_expr.ExprOp(op_name, b)))
+    e_src_not_null.append(aff_dst)
 
-def bsr(ir, instr, a, b):
-    lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode)
-    lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode)
+    return e, [irbloc(lbl_src_null.name, [e_src_null]),
+               irbloc(lbl_src_not_null.name, [e_src_not_null])]
 
-    e = [m2_expr.ExprAff(zf, m2_expr.ExprCond(b, m2_expr.ExprInt_from(zf, 0),
-                                              m2_expr.ExprInt_from(zf, 1)))]
+def bsf(ir, instr, a, b):
+    return bsr_bsf(ir, instr, a, b, "bsf")
 
-    e_do = []
-    e_do.append(m2_expr.ExprAff(a, m2_expr.ExprOp('bsr', b)))
-    e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
-    e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(b, lbl_do, lbl_skip)))
-    return e, [irbloc(lbl_do.name, [e_do])]
+def bsr(ir, instr, a, b):
+    return bsr_bsf(ir, instr, a, b, "bsr")
 
 
 def arpl(ir, instr, a, b):
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index a730b1d8..007f8378 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -59,6 +59,10 @@ class TranslatorC(Translator):
             if expr.op == 'parity':
                 return "parity(%s&0x%x)" % (cls.from_expr(expr.args[0]),
                                             size2mask(expr.args[0].size))
+            elif expr.op in ['bsr', 'bsf']:
+                return "x86_%s(%s, 0x%x)" % (expr.op,
+                                             cls.from_expr(expr.args[0]),
+                                             expr.args[0].size)
             elif expr.op == '!':
                 return "(~ %s)&0x%x" % (cls.from_expr(expr.args[0]),
                                         size2mask(expr.args[0].size))
@@ -102,10 +106,6 @@ class TranslatorC(Translator):
                                                    cls.from_expr(expr.args[0]),
                                                    cls.from_expr(expr.args[1]),
                                                    size2mask(expr.args[0].size))
-            elif expr.op in ['bsr', 'bsf']:
-                return 'my_%s(%s, %s)' % (expr.op,
-                                          cls.from_expr(expr.args[0]),
-                                          cls.from_expr(expr.args[1]))
             elif (expr.op.startswith('cpuid') or
                   expr.op.startswith("fcom")  or
                   expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale"]):
diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c
index 188f0372..057c10be 100644
--- a/miasm2/jitter/vm_mngr.c
+++ b/miasm2/jitter/vm_mngr.c
@@ -915,26 +915,29 @@ int rcr_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf
 {
 	return rcl_cf_op(size, a, size+1-b, cf);
 }
-unsigned int my_bsr(unsigned int a, unsigned int b)
+
+unsigned int x86_bsr(uint64_t src, unsigned int size)
 {
 	int i;
 
-	for (i=31; i>=0; i--){
-		if (b & (1<<i))
+	for (i=size-1; i>=0; i--){
+		if (src & (1<<i))
 			return i;
 	}
-	return a;
+	fprintf(stderr, "sanity check error bsr\n");
+	exit(0);
 }
 
-unsigned int my_bsf(unsigned int a, unsigned int b)
+unsigned int x86_bsf(uint64_t src, unsigned int size)
 {
 	int i;
 
-	for (i=0; i<32; i++){
-		if (b & (1<<i))
+	for (i=0; i<size; i++){
+		if (src & (1<<i))
 			return i;
 	}
-	return a;
+	fprintf(stderr, "sanity check error bsf\n");
+	exit(0);
 }
 
 
diff --git a/test/ir/ir2C.py b/test/ir/ir2C.py
index 1089bba4..11b9b10e 100644
--- a/test/ir/ir2C.py
+++ b/test/ir/ir2C.py
@@ -37,7 +37,7 @@ class TestIrIr2C(unittest.TestCase):
         self.translationTest(
             ExprOp('-',       *args[:2]), r'(((0x0&0xffffffff) - (0x1&0xffffffff))&0xffffffff)')
         self.translationTest(
-            ExprOp('bsr',     *args[:2]), r'my_bsr(0x0, 0x1)')
+            ExprOp('bsr',     *args[:1]), r'x86_bsr(0x0, 0x20)')
         self.translationTest(
             ExprOp('cpuid0',  *args[:2]), r'cpuid0(0x0, 0x1)')
         self.translationTest(
diff --git a/test/samples/x86_32/bsr_bsf.S b/test/samples/x86_32/bsr_bsf.S
new file mode 100644
index 00000000..0f915ed1
--- /dev/null
+++ b/test/samples/x86_32/bsr_bsf.S
@@ -0,0 +1,42 @@
+main:
+	;; BSF
+	;; standard case
+	MOV ECX, 0xF0000004
+	MOV EAX, 0x0
+	BSF EAX, ECX
+	JZ bad
+	CMP EAX, 2
+	JNZ bad
+
+
+	 ;; case undef
+	MOV ECX, 0x0
+	MOV EAX, 0x1337beef
+	BSF EAX, ECX
+	JNZ bad
+	CMP EAX, 0x1337beef
+	JNZ bad
+
+	;; BSR
+	;; standard case
+	MOV ECX, 0x4000000F
+	MOV EAX, 0x0
+	BSR EAX, ECX
+	JZ bad
+	CMP EAX, 30
+	JNZ bad
+
+
+	 ;; case undef
+	MOV ECX, 0x0
+	MOV EAX, 0x1337beef
+	BSR EAX, ECX
+	JNZ bad
+	CMP EAX, 0x1337beef
+	JNZ bad
+
+	RET
+
+bad:
+	INT 0x3
+	RET
diff --git a/test/test_all.py b/test/test_all.py
index a2fd6df3..1e5de442 100644
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -68,7 +68,9 @@ class SemanticTestAsm(RegressionTest):
 class SemanticTestExec(RegressionTest):
     """Execute a binary file"""
 
-    launcher_dct = {("PE", "x86_64"): "sandbox_pe_x86_64.py"}
+    launcher_dct = {("PE", "x86_64"): "sandbox_pe_x86_64.py",
+                    ("PE", "x86_32"): "sandbox_pe_x86_32.py",
+                }
     launcher_base = os.path.join("..", "example", "jitter")
 
     def __init__(self, arch, container, address, *args, **kwargs):
@@ -86,9 +88,13 @@ class SemanticTestExec(RegressionTest):
 
 
 test_x86_64_mul_div = SemanticTestAsm("x86_64", "PE", ["mul_div"])
+test_x86_32_bsr_bsf = SemanticTestAsm("x86_32", "PE", ["bsr_bsf"])
 testset += test_x86_64_mul_div
+testset += test_x86_32_bsr_bsf
 testset += SemanticTestExec("x86_64", "PE", 0x401000, ["mul_div"],
                             depends=[test_x86_64_mul_div])
+testset += SemanticTestExec("x86_32", "PE", 0x401000, ["bsr_bsf"],
+                            depends=[test_x86_32_bsr_bsf])
 
 ## Core
 for script in ["interval.py",