summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-20 17:46:17 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-20 17:47:23 -0400
commit9fcad221d074f09bde0ff7da9a49558d2ab067c7 (patch)
treea186bf9bfd28c0083ca92f017996333b71305f35
parentdab9590ce754e6fd4b3a311a195fcf797c3b3eb3 (diff)
downloadroux-9fcad221d074f09bde0ff7da9a49558d2ab067c7.tar.gz
save callee-save registers
-rw-r--r--lisc/emit.c20
-rw-r--r--lisc/isel.c24
-rw-r--r--lisc/lisc.h17
-rw-r--r--lisc/rega.c12
4 files changed, 50 insertions, 23 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index 7b15229..116d0d2 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -286,14 +286,17 @@ eins(Ins i, Fn *fn, FILE *f)
 static int
 framesz(Fn *fn)
 {
-	int i, a, f;
+	int i, o, a, f;
 
+	for (i=0, o=0; i<NRClob; i++)
+		o ^= 1 & (fn->reg >> rclob[i]);
 	f = 0;
 	for (i=NAlign-1, a=1<<i; i>=0; i--, a/=2)
 		if (f == 0 || f - a == fn->svec[i])
 			f = fn->svec[i];
 	a = 1 << (NAlign-2);
-	while ((f + a) % (2 * a) != a)
+	o *= a;
+	while ((f + o) % (2 * a))
 		f += a - f % a;
 	return f * 16 / (1 << (NAlign-1));
 }
@@ -303,7 +306,7 @@ emitfn(Fn *fn, FILE *f)
 {
 	Blk *b, *s;
 	Ins *i;
-	int c, fs;
+	int r, j, c, fs;
 
 	fprintf(f,
 		".text\n"
@@ -317,12 +320,23 @@ emitfn(Fn *fn, FILE *f)
 	fs = framesz(fn);
 	if (fs)
 		fprintf(f, "\tsub $%d, %%rsp\n", fs);
+	for (j=0; j<NRClob; j++) {
+		r = rclob[j];
+		if (fn->reg & BIT(r))
+			emitf(fn, f, "\tpush%w %R\n", 1, TMP(r));
+	}
+
 	for (b=fn->start; b; b=b->link) {
 		fprintf(f, ".L%s:\n", b->name);
 		for (i=b->ins; i-b->ins < b->nins; i++)
 			eins(*i, fn, f);
 		switch (b->jmp.type) {
 		case JRet:
+			for (j=NRClob; j>=0; j--) {
+				r = rclob[j];
+				if (fn->reg & BIT(r))
+					emitf(fn, f, "\tpop%w %R\n", 1, TMP(r));
+			}
 			fprintf(f,
 				"\tleave\n"
 				"\tret\n"
diff --git a/lisc/isel.c b/lisc/isel.c
index c4d7dca..8c428e7 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -486,42 +486,46 @@ classify(Ins *i0, Ins *i1, AClass *ac, int op)
 }
 
 int rsave[NRSave] = {RDI, RSI, RDX, RCX, R8, R9, R10, R11, RAX};
+int rclob[NRClob] = {RBX, R12, R13, R14, R15};
 
-uint64_t calldef(Ins i, int *p)
+ulong
+calldef(Ins i, int *p)
 {
-	uint64_t b;
+	ulong b;
 	int n;
 
 	n = i.arg[1].val & 15;
-	b = 1ll << RAX;
+	b = BIT(RAX);
 	if (n == 2)
-		b |= 1ll << RDX;
+		b |= BIT(RDX);
 	if (p)
 		*p = n;
 	return b;
 }
 
-uint64_t calluse(Ins i, int *p)
+ulong
+calluse(Ins i, int *p)
 {
-	uint64_t b;
+	ulong b;
 	int j, n;
 
 	n = (i.arg[1].val >> 4) & 15;
 	for (j = 0, b = 0; j < n; j++)
-		b |= 1ll << rsave[j];
+		b |= BIT(rsave[j]);
 	if (p)
 		*p = n;
 	return b;
 }
 
-uint64_t callclb(Ins i, int *p)
+ulong
+callclb(Ins i, int *p)
 {
-	uint64_t b;
+	ulong b;
 	int j, n;
 
 	n = (i.arg[1].val >> 4) & 15;
 	for (j = n, b = 0; j < NRSave; j++)
-		b |= 1ll << rsave[j];
+		b |= BIT(rsave[j]);
 	if (p)
 		*p = n;
 	return b;
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 930651d..43713a5 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -5,6 +5,7 @@
 #include <string.h>
 
 typedef unsigned int uint;
+typedef unsigned long long ulong;
 
 typedef struct Bits Bits;
 typedef struct Ref Ref;
@@ -45,6 +46,7 @@ enum Reg {
 
 	NReg = R12 - RAX + 1,
 	NRSave = 9,
+	NRClob = 5,
 };
 
 enum {
@@ -61,12 +63,13 @@ enum {
 };
 
 struct Bits {
-	uint64_t t[BITS];
+	ulong t[BITS];
 };
 
+#define BIT(n)     (1ull << (n))
 #define BGET(b, n) (1&((b).t[n/NBit]>>(n%NBit)))
-#define BSET(b, n) ((b).t[n/NBit] |= 1ll<<(n%NBit))
-#define BCLR(b, n) ((b).t[n/NBit] &= ~(1ll<<(n%NBit)))
+#define BSET(b, n) ((b).t[n/NBit] |= BIT(n%NBit))
+#define BCLR(b, n) ((b).t[n/NBit] &= ~BIT(n%NBit))
 
 struct Ref {
 	uint16_t type:2;
@@ -240,6 +243,7 @@ struct Fn {
 	int ncon;
 	int nblk;
 	Blk **rpo;
+	ulong reg;
 	int svec[NAlign];
 	char name[NString];
 };
@@ -280,9 +284,10 @@ void filllive(Fn *);
 
 /* isel.c */
 extern int rsave[NRSave];
-uint64_t calldef(Ins, int *);
-uint64_t calluse(Ins, int *);
-uint64_t callclb(Ins, int *);
+extern int rclob[NRClob];
+ulong calldef(Ins, int *);
+ulong calluse(Ins, int *);
+ulong callclb(Ins, int *);
 int slota(int, int, int *);
 void isel(Fn *);
 
diff --git a/lisc/rega.c b/lisc/rega.c
index e792d55..66836be 100644
--- a/lisc/rega.c
+++ b/lisc/rega.c
@@ -13,6 +13,7 @@ struct RMap {
 };
 
 extern Ins insb[NIns], *curi;
+static ulong regu;     /* registers used */
 static Tmp *tmp;       /* function temporaries */
 static struct {
 	Ref src, dst;
@@ -58,6 +59,7 @@ radd(RMap *m, int t, int r)
 	m->t[m->n] = t;
 	m->r[m->n] = r;
 	m->n++;
+	regu |= BIT(r);
 }
 
 static Ref
@@ -218,7 +220,7 @@ dopm(Blk *b, Ins *i, RMap *m)
 	RMap m0;
 	int n, r, r1, t, nins;
 	Ins *i1, *ib, *ip, *ir;
-	uint64_t def;
+	ulong def;
 
 	m0 = *m;
 	i1 = i+1;
@@ -233,7 +235,7 @@ dopm(Blk *b, Ins *i, RMap *m)
 	if (i > b->ins && (i-1)->op == OCall) {
 		def = calldef(*i, 0);
 		for (r=0; r<NRSave; r++)
-			if (!((1ll << rsave[r]) & def))
+			if (!(BIT(rsave[r]) & def))
 				move(rsave[r], R, m);
 	}
 	for (npm=0, n=0; n<m->n; n++)
@@ -280,8 +282,9 @@ rega(Fn *fn)
 	Phi *p;
 	uint a;
 	Ref src, dst;
-	uint64_t rs;
+	ulong rs;
 
+	regu = 0;
 	tmp = fn->tmp;
 	end = alloc(fn->nblk * sizeof end[0]);
 	beg = alloc(fn->nblk * sizeof beg[0]);
@@ -322,7 +325,7 @@ rega(Fn *fn)
 			case OCall:
 				rs = calluse(*i, 0);
 				for (r=0; r<NRSave; r++)
-					if (!((1ll << rsave[r]) & rs))
+					if (!(BIT(rsave[r]) & rs))
 						rfree(&cur, rsave[r]);
 				continue;
 			case OCopy:
@@ -430,6 +433,7 @@ rega(Fn *fn)
 			b->phi = p->link;
 			free(p);
 		}
+	fn->reg = regu;
 
 	free(end);
 	free(beg);