diff --git a/arm-gen.c b/arm-gen.c index cca9da5d..9b6bca26 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1177,7 +1177,8 @@ again: } } - /* second pass to restore registers that were saved on stack by accident */ + /* second pass to restore registers that were saved on stack by accident. + Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */ if (++pass < 2) goto again; diff --git a/i386-gen.c b/i386-gen.c index 79087d08..b96e4fb6 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -848,6 +848,8 @@ ST_FUNC void gen_opi(int op) fr = vtop[0].r; vtop--; save_reg(TREG_EDX); + /* save EAX too if used otherwise */ + save_reg_upstack(TREG_EAX, 1); if (op == TOK_UMULL) { o(0xf7); /* mul fr */ o(0xe0 + fr); diff --git a/tcc.h b/tcc.h index c25ab019..49fde3bd 100644 --- a/tcc.h +++ b/tcc.h @@ -1295,6 +1295,7 @@ ST_FUNC void lexpand_nr(void); #endif ST_FUNC void vpushv(SValue *v); ST_FUNC void save_reg(int r); +ST_FUNC void save_reg_upstack(int r, int n); ST_FUNC int get_reg(int rc); ST_FUNC void save_regs(int n); ST_FUNC void gaddrof(void); diff --git a/tccgen.c b/tccgen.c index 56be31bf..8144dc04 100644 --- a/tccgen.c +++ b/tccgen.c @@ -533,17 +533,35 @@ static void vdup(void) vpushv(vtop); } +/* save registers up to (vtop - n) stack entry */ +ST_FUNC void save_regs(int n) +{ + SValue *p, *p1; + for(p = vstack, p1 = vtop - n; p <= p1; p++) + save_reg(p->r); +} + /* save r to the memory stack, and mark it as being free */ ST_FUNC void save_reg(int r) +{ + save_reg_upstack(r, 0); +} + +/* save r to the memory stack, and mark it as being free, + if seen up to (vtop - n) stack entry */ +ST_FUNC void save_reg_upstack(int r, int n) { int l, saved, size, align; - SValue *p, sv; + SValue *p, *p1, sv; CType *type; + if ((r &= VT_VALMASK) >= VT_CONST) + return; + /* modify all stack values */ saved = 0; l = 0; - for(p=vstack;p<=vtop;p++) { + for(p = vstack, p1 = vtop - n; p <= p1; p++) { if ((p->r & VT_VALMASK) == r || ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) { /* must save value on stack if not already done */ @@ -659,20 +677,6 @@ ST_FUNC int get_reg(int rc) return -1; } -/* save registers up to (vtop - n) stack entry */ -ST_FUNC void save_regs(int n) -{ - int r; - SValue *p, *p1; - p1 = vtop - n; - for(p = vstack;p <= p1; p++) { - r = p->r & VT_VALMASK; - if (r < VT_CONST) { - save_reg(r); - } - } -} - /* move register 's' (of type 't') to 'r', and flush previous value of r to memory if needed */ static void move_reg(int r, int s, int t) @@ -859,13 +863,17 @@ ST_FUNC int gv(int rc) vpushi(ll >> 32); /* second word */ } else #endif - if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */ - (vtop->r & VT_LVAL)) { + if (vtop->r & VT_LVAL) { /* We do not want to modifier the long long pointer here, so the safest (and less efficient) is to save all the other registers in the stack. XXX: totally inefficient. */ + #if 0 save_regs(1); + #else + /* lvalue_save: save only if used further down the stack */ + save_reg_upstack(vtop->r, 1); + #endif /* load from memory */ vtop->type.t = load_type; load(r, vtop); diff --git a/tests/tcctest.c b/tests/tcctest.c index 5e9b07f3..e55dc054 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1953,6 +1953,11 @@ long long int value(struct S *v) return ((long long int)v->item); } +long long llfunc2(long long x, long long y, int z) +{ + return x * y * z; +} + void longlong_test(void) { long long a, b, c; @@ -1999,15 +2004,17 @@ void longlong_test(void) } lloptest(0x80000000, 0); - /* another long long spill test */ { - long long *p, v; + long long *p, v, **pp; v = 1; p = &v; p[0]++; - printf("%lld\n", *p); - } + printf("another long long spill test : %lld\n", *p); + pp = &p; + v = llfunc2(**pp, **pp, ia); + printf("a long long function (arm-)reg-args test : %lld\n", v); + } a = 68719476720LL; b = 4294967295LL; printf("%d %d %d %d\n", a > b, a < b, a >= b, a <= b);