git: 9front

Download patch

ref: 0d7e3fd4a27a8494d8e513b43cac12b7d9b9dea6
parent: e51689b3d21710c77f7f48fdc30cf16e70fc5bed
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Sep 20 10:58:43 EDT 2013

5c: apply richard millers 5c-nan-cmp patch (from sources)

On ARM, it turns out that comparisons with NaN can be made to do the
right thing with no code penalty, by a more careful selection of
condition code values in the subsequent conditional branch.  The
meaning of the CC bits in the PSR is subtly different when they've
been copied from the floating point status register.

Suggested patch is 5c-nan-cmp (works on both vfp and emulated arm7500).

--- a/sys/src/cmd/5c/cgen.c
+++ b/sys/src/cmd/5c/cgen.c
@@ -701,7 +701,7 @@
 		if(true)
 			o = comrel[relindex(o)];
 		if(typefd[n->type->etype]) {
-			gopcode(o, nodfconst(0), &nod, Z);
+			gopcode(true ? o | BTRUE : o, nodfconst(0), &nod, Z);
 		} else
 			gopcode(o, nodconst(0), &nod, Z);
 		regfree(&nod);
@@ -800,7 +800,7 @@
 			regalloc(&nod, r, nn);
 			cgenrel(r, &nod, 1);
 			o = invrel[relindex(o)];
-			gopcode(o, l, &nod, Z);
+			gopcode(true ? o | BTRUE : o, l, &nod, Z);
 			regfree(&nod);
 			goto com;
 		}
@@ -807,7 +807,7 @@
 		if(sconst(r)) {
 			regalloc(&nod, l, nn);
 			cgenrel(l, &nod, 1);
-			gopcode(o, r, &nod, Z);
+			gopcode(true ? o | BTRUE : o, r, &nod, Z);
 			regfree(&nod);
 			goto com;
 		}
@@ -822,7 +822,7 @@
 			regalloc(&nod1, l, Z);
 			cgenrel(l, &nod1, 1);
 		}
-		gopcode(o, &nod, &nod1, Z);
+		gopcode(true ? o | BTRUE : o, &nod, &nod1, Z);
 		regfree(&nod);
 		regfree(&nod1);
 
--- a/sys/src/cmd/5c/gc.h
+++ b/sys/src/cmd/5c/gc.h
@@ -14,6 +14,7 @@
 #define	SZ_VLONG	8
 #define	SZ_DOUBLE	8
 #define	FNX		100
+#define BTRUE		0x1000
 
 typedef	struct	Adr	Adr;
 typedef	struct	Prog	Prog;
--- a/sys/src/cmd/5c/txt.c
+++ b/sys/src/cmd/5c/txt.c
@@ -929,12 +929,14 @@
 void
 gopcode(int o, Node *f1, Node *f2, Node *t)
 {
-	int a, et;
+	int a, et, true;
 	Adr ta;
 
 	et = TLONG;
 	if(f1 != Z && f1->type != T)
 		et = f1->type->etype;
+	true = o & BTRUE;
+	o &= ~BTRUE;
 	a = AGOK;
 	switch(o) {
 	case OAS:
@@ -1076,15 +1078,24 @@
 			break;
 		case OLT:
 			a = ABLT;
+			/* ensure NaN comparison is always false */
+			if(typefd[et] && !true)
+				a = ABMI;
 			break;
 		case OLE:
 			a = ABLE;
+			if(typefd[et] && !true)
+				a = ABLS;
 			break;
 		case OGE:
 			a = ABGE;
+			if(typefd[et] && true)
+				a = ABPL;
 			break;
 		case OGT:
 			a = ABGT;
+			if(typefd[et] && true)
+				a = ABHI;
 			break;
 		case OLO:
 			a = ABLO;
--