aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorgrischka <grischka>2016-10-16 19:04:40 +0200
committergrischka <grischka>2016-10-16 19:04:40 +0200
commitd9b7f018ce08bdd6b0e35608dbe75ba933622d92 (patch)
treec2e5f22444a9cf1785ab6a551ce729c0254dd4ee /tccgen.c
parent6245db9fca4046e568da41c6a1f8c51ee9e2f56c (diff)
downloadtinycc-d9b7f018ce08bdd6b0e35608dbe75ba933622d92.tar.gz
tinycc-d9b7f018ce08bdd6b0e35608dbe75ba933622d92.tar.bz2
i386: do not 'lexpand' into registers necessarily
Previously, long longs were 'lexpand'ed into two registers always. Now, it expands - constants into two constants (lo-part, hi-part) - variables into two lvalues with offset+4 for the hi-part. This makes long long operations look a bit nicer. Also: don't apply i386 'inc/dec' optimization if carry generation is wanted.
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/tccgen.c b/tccgen.c
index f7f4d17..147f01e 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -1209,19 +1209,25 @@ static int reg_fret(int t)
return REG_FRET;
}
-/* expand long long on stack in two int registers */
+/* expand long long on stack in two ints */
static void lexpand(void)
{
- int u;
-
+ int u, v;
u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
- gv(RC_INT);
- vdup();
- vtop[0].r = vtop[-1].r2;
- vtop[0].r2 = VT_CONST;
- vtop[-1].r2 = VT_CONST;
- vtop[0].type.t = VT_INT | u;
- vtop[-1].type.t = VT_INT | u;
+ v = vtop->r & (VT_VALMASK | VT_LVAL);
+ if (v == VT_CONST) {
+ vdup();
+ vtop[0].c.i >>= 32;
+ } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
+ vdup();
+ vtop[0].c.i += 4;
+ } else {
+ gv(RC_INT);
+ vdup();
+ vtop[0].r = vtop[-1].r2;
+ vtop[0].r2 = vtop[-1].r2 = VT_CONST;
+ }
+ vtop[0].type.t = vtop[-1].type.t = VT_INT | u;
}
#ifdef TCC_TARGET_ARM