summary refs log tree commit diff
path: root/lisc
diff options
context:
space:
mode:
Diffstat (limited to 'lisc')
-rw-r--r--lisc/emit.c48
-rw-r--r--lisc/isel.c71
-rw-r--r--lisc/lisc.h76
-rw-r--r--lisc/parse.c20
4 files changed, 160 insertions, 55 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
index ecc6b36..3b916c4 100644
--- a/lisc/emit.c
+++ b/lisc/emit.c
@@ -74,12 +74,14 @@ static struct {
 	{ OXCmp,   Kd, "comisd %D0, %D1" },
 	{ OXCmp,   Ki, "cmp%k %0, %1" },
 	{ OXTest,  Ki, "test%k %0, %1" },
-	{ OXSet+Ceq,  Ki, "setz %B=\n\tmovzb%k %B=, %=" },
-	{ OXSet+Csle, Ki, "setle %B=\n\tmovzb%k %B=, %=" },
-	{ OXSet+Cslt, Ki, "setl %B=\n\tmovzb%k %B=, %=" },
-	{ OXSet+Csgt, Ki, "setg %B=\n\tmovzb%k %B=, %=" },
-	{ OXSet+Csge, Ki, "setge %B=\n\tmovzb%k %B=, %=" },
-	{ OXSet+Cne,  Ki, "setnz %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICeq,  Ki, "setz %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICsle, Ki, "setle %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICslt, Ki, "setl %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICsgt, Ki, "setg %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICsge, Ki, "setge %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICne,  Ki, "setnz %B=\n\tmovzb%k %B=, %=" },
+	{ OXSet+ICXnp, Ki, "setnp %B=\n\tmovsb%k %B=, %=" },
+	{ OXSet+ICXp,  Ki, "setp %B=\n\tmovsb%k %B=, %=" },
 	{ NOp, 0, 0 }
 };
 
@@ -411,12 +413,18 @@ cneg(int cmp)
 {
 	switch (cmp) {
 	default:   diag("emit: cneg() unhandled comparison");
-	case Ceq:  return Cne;
-	case Csle: return Csgt;
-	case Cslt: return Csge;
-	case Csgt: return Csle;
-	case Csge: return Cslt;
-	case Cne:  return Ceq;
+	case ICule: return ICugt;
+	case ICult: return ICuge;
+	case ICsle: return ICsgt;
+	case ICslt: return ICsge;
+	case ICsgt: return ICsle;
+	case ICsge: return ICslt;
+	case ICugt: return ICule;
+	case ICuge: return ICult;
+	case ICeq:  return ICne;
+	case ICne:  return ICeq;
+	case ICXnp: return ICXp;
+	case ICXp:  return ICXnp;
 	}
 }
 
@@ -437,8 +445,18 @@ void
 emitfn(Fn *fn, FILE *f)
 {
 	static char *ctoa[] = {
-		[Ceq] = "z", [Csle] = "le", [Cslt] = "l",
-		[Csgt] = "g", [Csge] = "ge", [Cne] = "nz"
+		[ICeq]  = "z",
+		[ICule] = "be",
+		[ICult] = "b",
+		[ICsle] = "le",
+		[ICslt] = "l",
+		[ICsgt] = "g",
+		[ICsge] = "ge",
+		[ICugt] = "a",
+		[ICuge] = "ae",
+		[ICne]  = "nz",
+		[ICXnp] = "np",
+		[ICXp]  = "p"
 	};
 	Blk *b, *s;
 	Ins *i, itmp;
@@ -484,7 +502,7 @@ emitfn(Fn *fn, FILE *f)
 			break;
 		default:
 			c = b->jmp.type - JXJc;
-			if (0 <= c && c <= NCmp) {
+			if (0 <= c && c <= NXICmp) {
 				if (b->link == b->s2) {
 					s = b->s1;
 				} else if (b->link == b->s1) {
diff --git a/lisc/isel.c b/lisc/isel.c
index 45f793c..41ca011 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -31,6 +31,48 @@ struct ANum {
 static void amatch(Addr *, Ref, ANum *, Fn *, int);
 
 static int
+fcmptoi(int fc)
+{
+	switch (fc) {
+	default:   diag("isel: fcmptoi defaulted");
+	case FCle: return ICule;
+	case FClt: return ICult;
+	case FCgt: return ICugt;
+	case FCge: return ICuge;
+	case FCne: return ICne;
+	case FCeq: return ICeq;
+	case FCo:  return ICXnp;
+	case FCuo: return ICXp;
+	}
+}
+
+static int
+iscmp(int op, int *k, int *c)
+{
+	if (OCmpw <= op && op <= OCmpw1) {
+		*c = op - OCmpw;
+		*k = Kw;
+		return 1;
+	}
+	if (OCmpl <= op && op <= OCmpl1) {
+		*c = op - OCmpl;
+		*k = Kl;
+		return 1l;
+	}
+	if (OCmps <= op && op <= OCmps1) {
+		*c = fcmptoi(op - OCmps);
+		*k = Ks;
+		return 1;
+	}
+	if (OCmpd <= op && op <= OCmpd1) {
+		*c = fcmptoi(op - OCmpd);
+		*k = Kd;
+		return 1;
+	}
+	return 0;
+}
+
+static int
 noimm(Ref r, Fn *fn)
 {
 	int64_t val;
@@ -159,7 +201,7 @@ static void
 sel(Ins i, ANum *an, Fn *fn)
 {
 	Ref r0, r1;
-	int x, k;
+	int x, k, kc;
 	int64_t val;
 	Ins *i0;
 
@@ -248,12 +290,11 @@ Emit:
 			goto case_OExt;
 		if (OLoad <= i.op && i.op <= OLoad1)
 			goto case_OLoad;
-		if (OCmp <= i.op && i.op <= OCmp1) {
-			x = i.op - OCmp;
+		if (iscmp(i.op, &kc, &x)) {
 			if (rtype(i.arg[0]) == RCon)
-				x = COP(x);
-			emit(OXSet+x, Kw, i.to, R, R);
-			selcmp(i.arg, k, fn);
+				x = icmpop(x);
+			emit(OXSet+x, k, i.to, R, R);
+			selcmp(i.arg, kc, fn);
 			break;
 		}
 		diag("isel: non-exhaustive implementation");
@@ -271,7 +312,10 @@ flagi(Ins *i0, Ins *i)
 	while (i>i0)
 		switch ((--i)->op) {
 		default:
-			if (OCmp <= i->op && i->op <= OCmp1)
+			if ((OCmpw <= i->op && i->op <= OCmpw1)
+			||  (OCmpl <= i->op && i->op <= OCmpl1)
+			||  (OCmps <= i->op && i->op <= OCmps1)
+			||  (OCmpd <= i->op && i->op <= OCmpd1))
 				return i;
 			if (OExt <= i->op && i->op <= OExt1)
 				continue;
@@ -295,7 +339,7 @@ static void
 seljmp(Blk *b, Fn *fn)
 {
 	Ref r;
-	int c, w;
+	int c, w, k;
 	Ins *fi;
 
 	switch (b->jmp.type) {
@@ -325,10 +369,9 @@ seljmp(Blk *b, Fn *fn)
 	}
 	fi = flagi(b->ins, &b->ins[b->nins]);
 	if (fi && req(fi->to, r)) {
-		if (OCmp <= fi->op && fi->op <= OCmp1) {
-			c = fi->op - OCmp;
+		if (iscmp(fi->op, &k, &c)) {
 			if (rtype(fi->arg[0]) == RCon)
-				c = COP(c);
+				c = icmpop(c);
 			b->jmp.type = JXJc + c;
 			if (fn->tmp[r.val].nuse == 1) {
 				assert(fn->tmp[r.val].ndef == 1);
@@ -342,7 +385,7 @@ seljmp(Blk *b, Fn *fn)
 		    rtype(fi->arg[1]) == RTmp)) {
 			fi->op = OXTest;
 			fi->to = R;
-			b->jmp.type = JXJc + Cne;
+			b->jmp.type = JXJc + ICne;
 			if (rtype(fi->arg[1]) == RCon) {
 				r = fi->arg[1];
 				fi->arg[1] = fi->arg[0];
@@ -351,12 +394,12 @@ seljmp(Blk *b, Fn *fn)
 			return;
 		}
 		if (fn->tmp[r.val].nuse > 1) {
-			b->jmp.type = JXJc + Cne;
+			b->jmp.type = JXJc + ICne;
 			return;
 		}
 	}
 	selcmp((Ref[2]){r, CON_Z}, 0, fn); /* todo, add long branch if non-zero */
-	b->jmp.type = JXJc + Cne;
+	b->jmp.type = JXJc + ICne;
 }
 
 struct AClass {
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 2e99374..90f3ee2 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -150,22 +150,49 @@ static inline int isreg(Ref r)
 	return rtype(r) == RTmp && r.val < Tmp0;
 }
 
-#define CMPS(X) \
-	X(eq)   \
-	X(sle)  \
-	X(slt)  \
-	X(sgt)  \
-	X(sge)  \
-	X(ne)   /* mirror opposite cmps! */
-
-#define COP(c) (c==Ceq||c==Cne ? c : NCmp-1 - c)
-
-enum Cmp {
-#define X(c) C##c,
-	CMPS(X)
+enum ICmp {
+#define ICMPS(X) \
+	X(ule)   \
+	X(ult)   \
+	X(sle)   \
+	X(slt)   \
+	X(sgt)   \
+	X(sge)   \
+	X(ugt)   \
+	X(uge)   \
+	X(eq)    \
+	X(ne) /* make sure icmpop() below works! */
+
+#define X(c) IC##c,
+	ICMPS(X)
 #undef X
+	NICmp,
 
-	NCmp
+	ICXnp = NICmp, /* x64 specific */
+	ICXp,
+	NXICmp
+};
+
+static inline int icmpop(int c)
+{
+	return c >= ICeq ? c : ICuge - c;
+}
+
+enum FCmp {
+#define FCMPS(X) \
+	X(le)    \
+	X(lt)    \
+	X(gt)    \
+	X(ge)    \
+	X(ne)    \
+	X(eq)    \
+	X(o)     \
+	X(uo)
+
+#define X(c) FC##c,
+	FCMPS(X)
+#undef X
+	NFCmp
 };
 
 enum Class {
@@ -188,8 +215,14 @@ enum Op {
 	ORem,
 	OMul,
 	OAnd,
-	OCmp,
-	OCmp1 = OCmp + NCmp-1,
+	OCmpw,
+	OCmpw1 = OCmpw + NICmp-1,
+	OCmpl,
+	OCmpl1 = OCmpl + NICmp-1,
+	OCmps,
+	OCmps1 = OCmps + NFCmp-1,
+	OCmpd,
+	OCmpd1 = OCmpd + NFCmp-1,
 
 	OStored,
 	OStores,
@@ -243,7 +276,8 @@ enum Op {
 	OXDiv,
 	OXCmp,
 	OXSet,
-	OXSet1 = OXSet + NCmp-1,
+	OXSetnp = OXSet + NICmp,
+	OXSetp,
 	OXTest,
 	NOp
 };
@@ -257,7 +291,8 @@ enum Jmp {
 	JJmp,
 	JJnz,
 	JXJc,
-	JXJc1 = JXJc + NCmp-1,
+	JXJnp = JXJc + NICmp,
+	JXJp,
 	NJmp
 };
 
@@ -456,10 +491,9 @@ void copy(Fn *);
 Bits liveon(Blk *, Blk *);
 void filllive(Fn *);
 
-
 /* isel.c */
-extern int rsave[NRSave];
-extern int rclob[NRClob];
+extern int rsave[/* NRSave */];
+extern int rclob[/* NRClob */];
 ulong calldef(Ins, int[2]);
 ulong calluse(Ins, int[2]);
 void isel(Fn *);
diff --git a/lisc/parse.c b/lisc/parse.c
index b0d011c..a77904c 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -49,10 +49,18 @@ OpDesc opdesc[NOp] = {
 	[OAlloc]   = { "alloc4",  1 },
 	[OAlloc+1] = { "alloc8",  1 },
 	[OAlloc+2] = { "alloc16", 1 },
+	[OXSetnp] = { "xsetnp", 0},
+	[OXSetp]  = { "xsetp",  0},
 #define X(c) \
-	[OCmp+C##c]  = { "c"    #c, 0 }, \
-	[OXSet+C##c] = { "xset" #c, 0 },
-	CMPS(X)
+	[OCmpw+IC##c] = { "c"    #c "w", 0 }, \
+	[OCmpl+IC##c] = { "c"    #c "l", 0 }, \
+	[OXSet+IC##c] = { "xset" #c,     0 },
+	ICMPS(X)
+#undef X
+#define X(c) \
+	[OCmps+FC##c] = { "c"    #c "s", 0 }, \
+	[OCmpd+FC##c] = { "c"    #c "d", 0 },
+	FCMPS(X)
 #undef X
 };
 
@@ -917,8 +925,10 @@ printfn(Fn *fn, FILE *f)
 		[JRetl]     = "retl",
 		[JRetc]     = "retc",
 		[JJnz]      = "jnz",
-	#define X(c) [JXJc+C##c] = "xj" #c,
-		CMPS(X)
+		[JXJnp]     = "xjnp",
+		[JXJp]      = "xjp",
+	#define X(c) [JXJc+IC##c] = "xj" #c,
+		ICMPS(X)
 	#undef X
 	};
 	static char prcls[NOp] = {