translate: fix an issue with ebp arg
authornotaz <notasas@gmail.com>
Sun, 28 Jun 2015 23:33:04 +0000 (02:33 +0300)
committernotaz <notasas@gmail.com>
Sun, 28 Jun 2015 23:33:04 +0000 (02:33 +0300)
tests/Makefile
tests/reg_call4.asm [new file with mode: 0644]
tests/reg_call4.expect.c [new file with mode: 0644]
tests/reg_call4.seed.h [new file with mode: 0644]
tests/reg_call5.asm [new file with mode: 0644]
tests/reg_call5.expect.c [new file with mode: 0644]
tests/reg_call5.seed.h [new file with mode: 0644]
tools/translate.c

index 83def3c..9f0639c 100644 (file)
@@ -1,5 +1,6 @@
 
-TESTS = reg_call1 reg_call2 reg_call3 reg_call_tail reg_save \
+TESTS = reg_call1 reg_call2 reg_call3 reg_call4 reg_call5 \
+       reg_call_tail reg_save \
        varargs ops x87 x87_f x87_s deref
 
 all: $(addsuffix .ok,$(TESTS))
diff --git a/tests/reg_call4.asm b/tests/reg_call4.asm
new file mode 100644 (file)
index 0000000..b409416
--- /dev/null
@@ -0,0 +1,12 @@
+; call a func with ebp reg-arg
+
+_text           segment para public 'CODE' use32
+
+call_test       proc near
+                mov     ebp, 1
+                jmp     ebpcall_func
+call_test       endp
+
+_text           ends
+
+; vim:expandtab
diff --git a/tests/reg_call4.expect.c b/tests/reg_call4.expect.c
new file mode 100644 (file)
index 0000000..ca8d14b
--- /dev/null
@@ -0,0 +1,8 @@
+void call_test()
+{
+  u32 ebp;
+
+  ebp = 1;
+  ebpcall_func(ebp);  // tailcall
+}
+
diff --git a/tests/reg_call4.seed.h b/tests/reg_call4.seed.h
new file mode 100644 (file)
index 0000000..b4a82f2
--- /dev/null
@@ -0,0 +1 @@
+void __usercall ebpcall_func(int a1/*<ebp>*/);
diff --git a/tests/reg_call5.asm b/tests/reg_call5.asm
new file mode 100644 (file)
index 0000000..d325b24
--- /dev/null
@@ -0,0 +1,21 @@
+; special case of callee sharing the stack frame
+
+_text           segment para public 'CODE' use32
+
+sub_test        proc near
+
+var_8           = dword ptr -8
+
+                push    ebp
+                mov     ebp, esp
+                sub     esp, 8
+                mov     [ebp+var_8], 1
+                call    ebpcall_func
+                and     eax, 0
+                leave
+                retn
+sub_test        endp
+
+_text           ends
+
+; vim:expandtab
diff --git a/tests/reg_call5.expect.c b/tests/reg_call5.expect.c
new file mode 100644 (file)
index 0000000..d3571e1
--- /dev/null
@@ -0,0 +1,11 @@
+int sub_test()
+{
+  union { u32 d[2]; u8 b[8]; } sf;
+  u32 eax;
+
+  sf.d[0] = 1;  // var_8
+  ebpcall_func((u32)&sf.b[sizeof(sf)]);  // bp_ref
+  eax = 0;
+  return eax;
+}
+
diff --git a/tests/reg_call5.seed.h b/tests/reg_call5.seed.h
new file mode 100644 (file)
index 0000000..b4a82f2
--- /dev/null
@@ -0,0 +1 @@
+void __usercall ebpcall_func(int a1/*<ebp>*/);
index 5e810a9..de2da47 100644 (file)
@@ -6955,7 +6955,7 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
               if (pp->arg[arg].type.is_retreg)
                 fprintf(fout, "&%s", pp->arg[arg].reg);
               else if (IS(pp->arg[arg].reg, "ebp")
-                    && !(po->flags & OPF_EBP_S))
+                    && g_bp_frame && !(po->flags & OPF_EBP_S))
               {
                 // rare special case
                 fprintf(fout, "%s(u32)&sf.b[sizeof(sf)]", cast);
@@ -7747,8 +7747,11 @@ static void gen_hdr_dep_pass(int i, int opcnt, unsigned char *cbits,
       po->regmask_dst |= 1 << xAX;
 
       dep = hg_fp_find_dep(fp, po->operand[0].name);
-      if (dep != NULL)
+      if (dep != NULL) {
         dep->regmask_live = regmask_save | regmask_dst;
+        if (g_bp_frame && !(po->flags & OPF_EBP_S))
+          dep->regmask_live |= 1 << xBP;
+      }
     }
     else if (po->op == OP_RET) {
       if (po->operand_cnt > 0) {