summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--all.h1
-rw-r--r--amd64/isel.c30
-rw-r--r--arm64/emit.c9
-rw-r--r--arm64/isel.c10
-rw-r--r--rv64/isel.c48
-rw-r--r--util.c30
6 files changed, 63 insertions, 65 deletions
diff --git a/all.h b/all.h
index 7e1a8d3..b775748 100644
--- a/all.h
+++ b/all.h
@@ -444,6 +444,7 @@ Ref getcon(int64_t, Fn *);
 int addcon(Con *, Con *);
 void blit(Ref, uint, Ref, uint, uint, Fn *);
 void blit0(Ref, Ref, uint, Fn *);
+void salloc(Ref, Ref, Fn *);
 void dumpts(BSet *, Tmp *, FILE *);
 
 void bsinit(BSet *, uint);
diff --git a/amd64/isel.c b/amd64/isel.c
index 4181e26..9dffd06 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -203,7 +203,6 @@ sel(Ins i, ANum *an, Fn *fn)
 {
 	Ref r0, r1, tmp[7];
 	int x, j, k, kc, sh, swap;
-	int64_t sz;
 	Ins *i0, *i1;
 
 	if (rtype(i.to) == RTmp)
@@ -375,31 +374,10 @@ Emit:
 		fixarg(&i1->arg[0], argcls(&i, 0), i1, fn);
 		fixarg(&i1->arg[1], argcls(&i, 1), i1, fn);
 		break;
-	case Oalloc:
-	case Oalloc+1:
-	case Oalloc+2: /* == Oalloc1 */
-		/* we need to make sure
-		 * the stack remains aligned
-		 * (rsp = 0) mod 16
-		 */
-		fn->dynalloc = 1;
-		if (rtype(i.arg[0]) == RCon) {
-			sz = fn->con[i.arg[0].val].bits.i;
-			if (sz < 0 || sz >= INT_MAX-15)
-				err("invalid alloc size %"PRId64, sz);
-			sz = (sz + 15)  & -16;
-			emit(Osalloc, Kl, i.to, getcon(sz, fn), R);
-		} else {
-			/* r0 = (i.arg[0] + 15) & -16 */
-			r0 = newtmp("isel", Kl, fn);
-			r1 = newtmp("isel", Kl, fn);
-			emit(Osalloc, Kl, i.to, r0, R);
-			emit(Oand, Kl, r0, r1, getcon(-16, fn));
-			emit(Oadd, Kl, r1, i.arg[0], getcon(15, fn));
-			if (fn->tmp[i.arg[0].val].slot != -1)
-				err("unlikely argument %%%s in %s",
-					fn->tmp[i.arg[0].val].name, optab[i.op].name);
-		}
+	case Oalloc4:
+	case Oalloc8:
+	case Oalloc16:
+		salloc(i.to, i.arg[0], fn);
 		break;
 	default:
 		if (isext(i.op))
diff --git a/arm64/emit.c b/arm64/emit.c
index b25f4f5..47097b7 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -385,6 +385,11 @@ emitins(Ins *i, E *e)
 				rn, s & 0xFFFF, rn, s >> 16, rn, rn
 			);
 		break;
+	case Osalloc:
+		emitf("sub sp, sp, %0", i, e);
+		if (!req(i->to, R))
+			emitf("mov %=, sp", i, e);
+		break;
 	}
 }
 
@@ -483,7 +488,7 @@ arm64_emitfn(Fn *fn, FILE *out)
 			"\tstp\tx29, x30, [sp, -16]!\n",
 			e->frame & 0xFFFF, e->frame >> 16
 		);
-	fputs("\tadd\tx29, sp, 0\n", e->f);
+	fputs("\tmov\tx29, sp\n", e->f);
 	s = (e->frame - e->padding) / 4;
 	for (r=arm64_rclob; *r>=0; r++)
 		if (e->fn->reg & BIT(*r)) {
@@ -509,6 +514,8 @@ arm64_emitfn(Fn *fn, FILE *out)
 					i->cls = *r >= V0 ? Kd : Kl;
 					emitins(i, e);
 				}
+			if (e->fn->dynalloc)
+				fputs("\tmov sp, x29\n", e->f);
 			o = e->frame + 16;
 			if (e->fn->vararg)
 				o += 192;
diff --git a/arm64/isel.c b/arm64/isel.c
index 031ba11..bb5c12b 100644
--- a/arm64/isel.c
+++ b/arm64/isel.c
@@ -163,6 +163,12 @@ sel(Ins i, Fn *fn)
 	Ins *i0;
 	int ck, cc;
 
+	if (INRANGE(i.op, Oalloc, Oalloc1)) {
+		i0 = curi - 1;
+		salloc(i.to, i.arg[0], fn);
+		fixarg(&i0->arg[0], Kl, 0, fn);
+		return;
+	}
 	if (iscmp(i.op, &ck, &cc)) {
 		emit(Oflag, i.cls, i.to, R, R);
 		i0 = curi;
@@ -170,7 +176,9 @@ sel(Ins i, Fn *fn)
 			i0->op += cmpop(cc);
 		else
 			i0->op += cc;
-	} else if (i.op != Onop) {
+		return;
+	}
+	if (i.op != Onop) {
 		emiti(i);
 		iarg = curi->arg; /* fixarg() can change curi */
 		fixarg(&iarg[0], argcls(&i, 0), 0, fn);
diff --git a/rv64/isel.c b/rv64/isel.c
index e441597..e41578b 100644
--- a/rv64/isel.c
+++ b/rv64/isel.c
@@ -174,46 +174,20 @@ selcmp(Ins i, int k, int op, Fn *fn)
 static void
 sel(Ins i, Fn *fn)
 {
-	Ref r0, r1;
 	Ins *i0;
 	int ck, cc;
-	int64_t sz;
 
-	switch (i.op) {
-	case Onop:
-		break;
-	case Oalloc4:
-	case Oalloc8:
-	case Oalloc16:
-		/* we need to make sure
-		 * the stack remains aligned
-		 * (rsp = 0) mod 16
-		 */
-		fn->dynalloc = 1;
-		if (rtype(i.arg[0]) == RCon) {
-			sz = fn->con[i.arg[0].val].bits.i;
-			if (sz < 0)
-				err("invalid alloc size %"PRId64, sz);
-			sz = (sz + 15) & -16;
-			emit(Osalloc, Kl, i.to, getcon(sz, fn), R);
-			fixarg(&curi->arg[0], Kl, curi, fn);
-		} else {
-			/* r0 = (i.arg[0] + 15) & -16 */
-			r0 = newtmp("isel", Kl, fn);
-			r1 = newtmp("isel", Kl, fn);
-			emit(Osalloc, Kl, i.to, r0, R);
-			emit(Oand, Kl, r0, r1, getcon(-16, fn));
-			emit(Oadd, Kl, r1, i.arg[0], getcon(15, fn));
-			if (fn->tmp[i.arg[0].val].slot != -1)
-				err("unlikely argument %%%s in %s",
-					fn->tmp[i.arg[0].val].name, optab[i.op].name);
-		}
-		break;
-	default:
-		if (iscmp(i.op, &ck, &cc)) {
-			selcmp(i, ck, cc, fn);
-			break;
-		}
+	if (INRANGE(i.op, Oalloc, Oalloc1)) {
+		i0 = curi - 1;
+		salloc(i.to, i.arg[0], fn);
+		fixarg(&i0->arg[0], Kl, i0, fn);
+		return;
+	}
+	if (iscmp(i.op, &ck, &cc)) {
+		selcmp(i, ck, cc, fn);
+		return;
+	}
+	if (i.op != Onop) {
 		emiti(i);
 		i0 = curi; /* fixarg() can change curi */
 		fixarg(&i0->arg[0], argcls(&i, 0), i0, fn);
diff --git a/util.c b/util.c
index 5296b86..6a33d1a 100644
--- a/util.c
+++ b/util.c
@@ -429,6 +429,36 @@ blit0(Ref rdst, Ref rsrc, uint sz, Fn *fn)
 }
 
 void
+salloc(Ref rt, Ref rs, Fn *fn)
+{
+	Ref r0, r1;
+	int64_t sz;
+
+	/* we need to make sure
+	 * the stack remains aligned
+	 * (rsp = 0) mod 16
+	 */
+	fn->dynalloc = 1;
+	if (rtype(rs) == RCon) {
+		sz = fn->con[rs.val].bits.i;
+		if (sz < 0 || sz >= INT_MAX-15)
+			err("invalid alloc size %"PRId64, sz);
+		sz = (sz + 15)  & -16;
+		emit(Osalloc, Kl, rt, getcon(sz, fn), R);
+	} else {
+		/* r0 = (r + 15) & -16 */
+		r0 = newtmp("isel", Kl, fn);
+		r1 = newtmp("isel", Kl, fn);
+		emit(Osalloc, Kl, rt, r0, R);
+		emit(Oand, Kl, r0, r1, getcon(-16, fn));
+		emit(Oadd, Kl, r1, rs, getcon(15, fn));
+		if (fn->tmp[rs.val].slot != -1)
+			err("unlikely alloc argument %%%s for %%%s",
+				fn->tmp[rs.val].name, fn->tmp[rt.val].name);
+	}
+}
+
+void
 bsinit(BSet *bs, uint n)
 {
 	n = (n + NBit-1) / NBit;