summary refs log tree commit diff
path: root/lisc/isel.c
diff options
context:
space:
mode:
Diffstat (limited to 'lisc/isel.c')
-rw-r--r--lisc/isel.c117
1 files changed, 45 insertions, 72 deletions
diff --git a/lisc/isel.c b/lisc/isel.c
index dd70a57..cceb128 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -20,15 +20,15 @@
 extern Ins insb[NIns], *curi; /* shared work buffer */
 
 static void
-emit(short op, Ref to, Ref arg0, Ref arg1)
+emit(int op, int w, Ref to, Ref arg0, Ref arg1)
 {
 	if (curi == insb)
 		diag("isel: too many instructions");
-	*--curi = (Ins){op, to, {arg0, arg1}};
+	*--curi = (Ins){op, w, to, {arg0, arg1}};
 }
 
 static Ref
-newtmp(int type, Fn *fn)
+newtmp(Fn *fn)
 {
 	static int n;
 	int t;
@@ -37,7 +37,7 @@ newtmp(int type, Fn *fn)
 	fn->tmp = realloc(fn->tmp, fn->ntmp * sizeof fn->tmp[0]);
 	if (!fn->tmp)
 		diag("isel: out of memory");
-	fn->tmp[t] = (Tmp){.type = type};
+	memset(&fn->tmp[t], 0, sizeof fn->tmp[t]);
 	sprintf(fn->tmp[t].name, "isel%d", ++n);
 	return TMP(t);
 }
@@ -80,17 +80,10 @@ noimm(Ref r, Fn *fn)
 	}
 }
 
-static int
-islong(Ref r, Fn *fn)
-{
-	return rtype(r) == RTmp && fn->tmp[r.val].type == TLong;
-}
-
 static void
-selcmp(Ref arg[2], Fn *fn)
+selcmp(Ref arg[2], int w, Fn *fn)
 {
 	Ref r;
-	int lng;
 
 	if (rtype(arg[0]) == RCon) {
 		r = arg[1];
@@ -98,12 +91,11 @@ selcmp(Ref arg[2], Fn *fn)
 		arg[0] = r;
 	}
 	assert(rtype(arg[0]) != RCon);
-	lng = islong(arg[0], fn) || islong(arg[1], fn);
-	emit(lng ? OXCmpl : OXCmpw, R, arg[1], arg[0]);
+	emit(OXCmp, w, R, arg[1], arg[0]);
 	r = arg[1];
-	if (lng && rtype(r) == RCon && noimm(r, fn)) {
-		curi->arg[0] = newtmp(TLong, fn);
-		emit(OCopy, curi->arg[0], r, R);
+	if (w && rtype(r) == RCon && noimm(r, fn)) {
+		curi->arg[0] = newtmp(fn);
+		emit(OCopy, w, curi->arg[0], r, R);
 	}
 }
 
@@ -118,8 +110,8 @@ rslot(Ref r, Fn *fn)
 static void
 sel(Ins i, Fn *fn)
 {
-	Ref r0, r1, ra, rd;
-	int n, ty, c, s;
+	Ref r0, r1;
+	int n, c, s, w;
 	int64_t val;
 	struct {
 		Ref r;
@@ -131,52 +123,38 @@ sel(Ins i, Fn *fn)
 		cpy[n].s = 0;
 		s = rslot(r0, fn);
 		if (s) {
-			r0 = newtmp(TLong, fn);
+			r0 = newtmp(fn);
 			i.arg[n] = r0;
 			cpy[n].r = r0;
 			cpy[n].s = s;
 		}
 	}
 
+	w = i.wide;
 	switch (i.op) {
 	case ODiv:
 	case ORem:
-		ty = fn->tmp[i.to.val].type;
-		switch (ty) {
-		default:
-			diag("isel: invalid division");
-		case TWord:
-			ra = TMP(EAX);
-			rd = TMP(EDX);
-			break;
-		case TLong:
-			ra = TMP(RAX);
-			rd = TMP(RDX);
-			break;
-		}
-		r0 = i.op == ODiv ? ra : rd;
-		r1 = i.op == ODiv ? rd : ra;
-		emit(OCopy, i.to, r0, R);
-		emit(OCopy, R, r1, R);
+		if (i.op == ODiv)
+			r0 = TMP(RAX), r1 = TMP(RDX);
+		else
+			r0 = TMP(RDX), r1 = TMP(RAX);
+		emit(OCopy, w, i.to, r0, R);
+		emit(OCopy, w, R, r1, R);
 		if (rtype(i.arg[1]) == RCon) {
 			/* immediates not allowed for
 			 * divisions in x86
 			 */
-			r0 = newtmp(ty, fn);
+			r0 = newtmp(fn);
 		} else
 			r0 = i.arg[1];
-		emit(OXDiv, R, r0, R);
-		emit(OSign, rd, ra, R);
-		emit(OCopy, ra, i.arg[0], R);
+		emit(OXDiv, w, R, r0, R);
+		emit(OSign, w, TMP(RDX), TMP(RAX), R);
+		emit(OCopy, w, TMP(RAX), i.arg[0], R);
 		if (rtype(i.arg[1]) == RCon)
-			emit(OCopy, r0, i.arg[1], R);
+			emit(OCopy, w, r0, i.arg[1], R);
 		break;
 	case ONop:
 		break;
-	case OXTestw:
-	case OXTestl:
-		n = i.op == OXTestl ? 2 : 0;
-		goto Emit;
 	case OSext:
 	case OZext:
 		n = 0;
@@ -189,10 +167,8 @@ sel(Ins i, Fn *fn)
 	case OMul:
 	case OAnd:
 	case OCopy:
-		if (fn->tmp[i.to.val].type == TLong)
-			n = 2;
-		else
-			n = 0;
+	case OXTest:
+		n = w ? 2 : 0;
 		goto Emit;
 	case OStorel:
 	case OStorew:
@@ -215,7 +191,7 @@ sel(Ins i, Fn *fn)
 		}
 		n = 0;
 Emit:
-		emit(i.op, i.to, i.arg[0], i.arg[1]);
+		emit(i.op, w, i.to, i.arg[0], i.arg[1]);
 		while (n--) {
 			/* load constants that do not fit in
 			 * a 32bit signed integer into a
@@ -223,8 +199,8 @@ Emit:
 			 */
 			r0 = i.arg[n];
 			if (rtype(r0) == RCon && noimm(r0, fn)) {
-				curi->arg[n] = newtmp(TLong, fn);
-				emit(OCopy, curi->arg[n], r0, R);
+				curi->arg[n] = newtmp(fn);
+				emit(OCopy, 1, curi->arg[n], r0, R);
 			}
 		}
 		break;
@@ -243,14 +219,14 @@ Emit:
 			val = (val + 15)  & ~INT64_C(15);
 			if (val < 0 || val > INT32_MAX)
 				diag("isel: alloc too large");
-			emit(OAlloc, i.to, newcon(val, fn), R);
+			emit(OAlloc, 0, i.to, newcon(val, fn), R);
 		} else {
 			/* r0 = (i.arg[0] + 15) & -16 */
-			r0 = newtmp(TLong, fn);
-			r1 = newtmp(TLong, fn);
-			emit(OAlloc, i.to, r0, R);
-			emit(OAnd, r0, r1, newcon(-16, fn));
-			emit(OAdd, r1, i.arg[0], newcon(15, fn));
+			r0 = newtmp(fn);
+			r1 = newtmp(fn);
+			emit(OAlloc, 0, i.to, r0, R);
+			emit(OAnd, 1, r0, r1, newcon(-16, fn));
+			emit(OAdd, 1, r1, i.arg[0], newcon(15, fn));
 		}
 		break;
 	default:
@@ -258,8 +234,8 @@ Emit:
 			c = i.op - OCmp;
 			if (rtype(i.arg[0]) == RCon)
 				c = COP(c);
-			emit(OXSet+c, i.to, R, R);
-			selcmp(i.arg, fn);
+			emit(OXSet+c, 0, i.to, R, R);
+			selcmp(i.arg, w, fn);
 			break;
 		}
 		diag("isel: non-exhaustive implementation");
@@ -267,7 +243,7 @@ Emit:
 
 	for (n=0; n<2; n++)
 		if (cpy[n].s)
-			emit(OAddr, cpy[n].r, SLOT(cpy[n].s), R);
+			emit(OAddr, 0, cpy[n].r, SLOT(cpy[n].s), R);
 }
 
 static Ins *
@@ -327,19 +303,16 @@ seljmp(Blk *b, Fn *fn)
 				c = COP(c);
 			b->jmp.type = JXJc + c;
 			if (fn->tmp[r.val].nuse == 1) {
-				assert(fn->tmp[r.val].ndef==1);
-				selcmp(fi->arg, fn);
-				*fi = (Ins){ONop, R, {R, R}};
+				assert(fn->tmp[r.val].ndef == 1);
+				selcmp(fi->arg, fi->wide, fn);
+				*fi = (Ins){.op = ONop};
 			}
 			return;
 		}
 		if (fi->op == OAnd && fn->tmp[r.val].nuse == 1
 		&& (rtype(fi->arg[0]) == RTmp ||
 		    rtype(fi->arg[1]) == RTmp)) {
-			if (fn->tmp[r.val].type == TLong)
-				fi->op = OXTestl;
-			else
-				fi->op = OXTestw;
+			fi->op = OXTest;
 			fi->to = R;
 			b->jmp.type = JXJc + Cne;
 			if (rtype(fi->arg[1]) == RCon) {
@@ -354,7 +327,7 @@ seljmp(Blk *b, Fn *fn)
 			return;
 		}
 	}
-	selcmp((Ref[2]){r, CON_Z}, fn);
+	selcmp((Ref[2]){r, CON_Z}, 0, fn); /* fixme, add long branch if non-zero */
 	b->jmp.type = JXJc + Cne;
 }
 
@@ -452,8 +425,8 @@ isel(Fn *fn)
 					assert(a+1 < p->narg);
 				s = rslot(p->arg[a], fn);
 				if (s) {
-					p->arg[a] = newtmp(TLong, fn);
-					emit(OAddr, p->arg[a], SLOT(s), R);
+					p->arg[a] = newtmp(fn);
+					emit(OAddr, 0, p->arg[a], SLOT(s), R);
 				}
 			}
 		curi = &insb[NIns];