summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/emit.c9
-rw-r--r--lisc/isel.c27
-rw-r--r--lisc/lisc.h7
-rw-r--r--lisc/parse.c2
4 files changed, 35 insertions, 10 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index 00bce4b..3e03a81 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -145,6 +145,10 @@ eins(Ins i, Fn *fn, FILE *f)
 		[OLoadus] = "movzw",
 		[OLoadsb] = "movsb",
 		[OLoadub] = "movzb",
+		[OXCmpw]  = "cmpl",
+		[OXCmpl]  = "cmpq",
+		[OXTestw] = "testl",
+		[OXTestl] = "testq",
 	};
 	static char *stoa[] = {
 		[OStorel - OStorel] = "q",
@@ -240,8 +244,9 @@ eins(Ins i, Fn *fn, FILE *f)
 		break;
 	case OXCmpw:
 	case OXCmpl:
-		eop(i.op == OXCmpw ? "cmpl" : "cmpq",
-			i.arg[0], i.arg[1], fn, f);
+	case OXTestw:
+	case OXTestl:
+		eop(otoa[i.op], i.arg[0], i.arg[1], fn, f);
 		break;
 	case ONop:
 		break;
diff --git a/lisc/isel.c b/lisc/isel.c
index 97a0124..41ff9f2 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -173,6 +173,10 @@ sel(Ins i, Fn *fn)
 		break;
 	case ONop:
 		break;
+	case OXTestw:
+	case OXTestl:
+		n = 2;
+		goto Emit;
 	case OAdd:
 	case OSub:
 	case OAnd:
@@ -318,15 +322,26 @@ seljmp(Blk *b, Fn *fn)
 				selcmp(fi->arg, fn);
 				*fi = (Ins){ONop, R, {R, R}};
 			}
-		} else {
-			if (fn->tmp[r.val].nuse == 1)
-				emit(OCopy, R, r, R);
+			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->to = R;
 			b->jmp.type = JXJc + Cne;
+			return;
+		}
+		if (fn->tmp[r.val].nuse > 1) {
+			b->jmp.type = JXJc + Cne;
+			return;
 		}
-	} else {
-		selcmp((Ref[2]){r, CON_Z}, fn);
-		b->jmp.type = JXJc + Cne;
 	}
+	selcmp((Ref[2]){r, CON_Z}, fn);
+	b->jmp.type = JXJc + Cne;
 }
 
 int
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 50c6504..76290dc 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -58,7 +58,7 @@ enum Reg {
 
 	Tmp0, /* first non-reg temporary */
 
-	NReg = RDX - RAX + 1
+	NReg = R11 - RAX + 1
 };
 
 #define RWORD(r) (r + (EAX-RAX))
@@ -139,13 +139,14 @@ enum Op {
 	OLoadus,
 	OLoadsb,
 	OLoadub,
-	OCopy,
 	OAlloc,
 	OAlloc1 = OAlloc + 2,
+	OCopy,
 	NPubOp,
 
 	/* reserved instructions */
 	ONop = NPubOp,
+	OAddr,
 	OSwap,
 	OSign,
 	OXDiv,
@@ -153,6 +154,8 @@ enum Op {
 	OXCmpl,
 	OXSet,
 	OXSet1 = OXSet + NCmp-1,
+	OXTestw,
+	OXTestl,
 	NOp
 };
 
diff --git a/lisc/parse.c b/lisc/parse.c
index f51d5a5..4856d5c 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -33,6 +33,8 @@ OpDesc opdesc[NOp] = {
 	[OXDiv]   = { "xdiv",   1, 1 },
 	[OXCmpw]  = { "xcmpw",  2, 1 },
 	[OXCmpl]  = { "xcmpl",  2, 1 },
+	[OXTestw] = { "xtestw", 2, 1 },
+	[OXTestl] = { "xtestl", 2, 1 },
 	[OAlloc]   = { "alloc4",  1, 1 },
 	[OAlloc+1] = { "alloc8",  1, 1 },
 	[OAlloc+2] = { "alloc16", 1, 1 },