shithub: riscv

Download patch

ref: 7c7acbef314c6998354219f24cfee3283cb45ec1
parent: 4a916ba86e700d5e99311b45a81dc7be8a50b843
author: cinap_lenrek <[email protected]>
date: Wed Oct 7 05:40:48 EDT 2015

qc: import changes from charles forsyth

--- a/sys/src/cmd/qc/cgen.c
+++ b/sys/src/cmd/qc/cgen.c
@@ -4,6 +4,7 @@
 static void testv(Node*, int);
 static void cgen64(Node*, Node*);
 static int isvconstable(int, vlong);
+static void genasop(int, Node*, Node*, Node*);
 
 void
 cgen(Node *n, Node *nn)
@@ -255,6 +256,8 @@
 				regfree(&nod2);
 			break;
 		}
+		genasop(o, l, r, nn);
+		break;
 
 	case OASLMUL:
 	case OASLDIV:
@@ -264,31 +267,7 @@
 	case OASMOD:
 		if(l->op == OBIT)
 			goto asbitop;
-		if(l->complex >= r->complex) {
-			if(l->addable < INDEXED)
-				reglcgen(&nod2, l, Z);
-			else
-				nod2 = *l;
-			regalloc(&nod, r, Z);
-			cgen(r, &nod);
-		} else {
-			regalloc(&nod, r, Z);
-			cgen(r, &nod);
-			if(l->addable < INDEXED)
-				reglcgen(&nod2, l, Z);
-			else
-				nod2 = *l;
-		}
-		regalloc(&nod1, n, nn);
-		gopcode(OAS, &nod2, Z, &nod1);
-		gopcode(o, &nod, Z, &nod1);
-		gopcode(OAS, &nod1, Z, &nod2);
-		if(nn != Z)
-			gopcode(OAS, &nod1, Z, nn);
-		regfree(&nod);
-		regfree(&nod1);
-		if(l->addable < INDEXED)
-			regfree(&nod2);
+		genasop(o, l, r, nn);
 		break;
 
 	asbitop:
@@ -559,6 +538,43 @@
 		break;
 	}
 	cursafe = curs;
+}
+
+static void
+genasop(int o, Node *l, Node *r, Node *nn)
+{
+	Node nod, nod1, nod2;
+	int hardleft;
+
+	hardleft = l->addable < INDEXED || l->complex >= FNX;
+	if(l->complex >= r->complex) {
+		if(hardleft)
+			reglcgen(&nod2, l, Z);
+		else
+			nod2 = *l;
+		regalloc(&nod1, r, Z);
+		cgen(r, &nod1);
+	} else {
+		regalloc(&nod1, r, Z);
+		cgen(r, &nod1);
+		if(hardleft)
+			reglcgen(&nod2, l, Z);
+		else
+			nod2 = *l;
+	}
+	if(nod1.type == nod2.type || !typefd[nod1.type->etype])
+		regalloc(&nod, &nod2, nn);
+	else
+		regalloc(&nod, &nod1, Z);
+	gmove(&nod2, &nod);
+	gopcode(o, &nod1, Z, &nod);
+	gmove(&nod, &nod2);
+	if(nn != Z)
+		gmove(&nod2, nn);
+	regfree(&nod);
+	regfree(&nod1);
+	if(hardleft)
+		regfree(&nod2);
 }
 
 void
--- a/sys/src/cmd/qc/machcap.c
+++ b/sys/src/cmd/qc/machcap.c
@@ -18,10 +18,12 @@
 
 	case OMUL:
 	case OLMUL:
-	case OASMUL:
 	case OASLMUL:
 		return 1;
 
+	case OASMUL:
+		return !mixedasop(n->type, n->right->type);
+
 	case OLSHR:
 	case OASHR:
 	case OASHL:
@@ -58,6 +60,8 @@
 
 	case OASADD:
 	case OASSUB:
+		return !mixedasop(n->type, n->right->type);
+
 	case OASAND:
 	case OASOR:
 	case OASXOR:
--- a/sys/src/cmd/qc/swt.c
+++ b/sys/src/cmd/qc/swt.c
@@ -657,8 +657,8 @@
 	w = SZ_LONG;
 	if((debug['8'] || hasdoubled) && !debug['4'])
 		w = SZ_DOUBLE;
-	v += w-1;
+	v = round(v, w);
 	if(v > max)
-		max = round(v, w);
+		return v;
 	return max;
 }
--- a/sys/src/cmd/qc/txt.c
+++ b/sys/src/cmd/qc/txt.c
@@ -622,12 +622,86 @@
 	regfree(&nod3);
 }
 
+static void
+floattofix(Node *f, Node *t)
+{
+	Node nod, fxrat;
+
+	regalloc(&nod, f, Z);
+	regsalloc(&fxrat, &fconstnode);
+	gins(AFCTIWZ, f, &nod);
+	gins(AFMOVD, &nod, &fxrat);
+	regfree(&nod);
+	fxrat.type = nodrat->type;
+	fxrat.etype = nodrat->etype;
+	fxrat.xoffset += 4;
+	gins(AMOVW, &fxrat, t);
+	gmove(t, t);
+}
+
+static void
+fixtofloat(Node *f, Node *t)
+{
+	int a, ft, tt;
+	Prog *p1;
+	Node nod, fxc0, fxc1, fxc2, fxrat;
+
+	ft = f->type->etype;
+	tt = t->type->etype;
+
+	/*
+	 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
+	 * t = *(double*)rat - FREGCVI;
+	 * is-unsigned(t) => if(t<0) t += 2^32;
+	 * could be streamlined for int-to-float
+	 */
+	regalloc(&fxc0, f, Z);
+	regalloc(&fxc2, f, Z);
+	regsalloc(&fxrat, &fconstnode);	/* should be type float */
+	gins(AMOVW, nodconst(0x43300000L), &fxc0);
+	gins(AMOVW, f, &fxc2);
+	gins(AMOVW, &fxc0, &fxrat);
+	gins(AXOR, nodconst(0x80000000L), &fxc2);
+	fxc1 = fxrat;
+	fxc1.type = nodrat->type;
+	fxc1.etype = nodrat->etype;
+	fxc1.xoffset += SZ_LONG;
+	gins(AMOVW, &fxc2, &fxc1);
+	regfree(&fxc2);
+	regfree(&fxc0);
+	regalloc(&nod, t, t);	/* should be type float */
+	gins(AFMOVD, &fxrat, &nod);
+	nodreg(&fxc1, t, NREG+FREGCVI);
+	gins(AFSUB, &fxc1, &nod);
+	a = AFMOVD;
+	if(tt == TFLOAT)
+		a = AFRSP;
+	gins(a, &nod, t);
+	regfree(&nod);
+	if(ft == TULONG) {
+		regalloc(&nod, t, Z);
+		gins(AFCMPU, t, Z);
+		p->to.type = D_FREG;
+		p->to.reg = FREGZERO;
+		gins(ABGE, Z, Z);
+		p1 = p;
+		if(tt == TFLOAT) {
+			gins(AFMOVS, nodfconst(4294967296.), &nod);
+			gins(AFADDS, &nod, t);
+		} else {
+			gins(AFMOVD, nodfconst(4294967296.), &nod);
+			gins(AFADD, &nod, t);
+		}
+		patch(p1, pc);
+		regfree(&nod);
+	}
+}
+
 void
 gmove(Node *f, Node *t)
 {
 	int ft, tt, a;
-	Node nod, fxc0, fxc1, fxc2, fxrat;
-	Prog *p1;
+	Node nod;
 	double d;
 
 	ft = f->type->etype;
@@ -727,7 +801,7 @@
 			break;
 		}
 		if(typev[ft]) {
-			if(typev[tt]) {
+			if(typev[tt] || typefd[tt]) {
 				regalloc(&nod, f, t);
 				/* low order first, because its value will be used first */
 				f->xoffset += SZ_LONG;
@@ -832,17 +906,12 @@
 		case TCHAR:
 		case TUCHAR:
 			/* BUG: not right for unsigned long */
-			regalloc(&nod, f, Z);	/* should be type float */
-			regsalloc(&fxrat, &fconstnode);
-			gins(AFCTIWZ, f, &nod);
-			gins(AFMOVD, &nod, &fxrat);
-			regfree(&nod);
-			fxrat.type = nodrat->type;
-			fxrat.etype = nodrat->etype;
-			fxrat.xoffset += 4;
-			gins(AMOVW, &fxrat, t);
-			gmove(t, t);
+			floattofix(f, t);
 			return;
+		case TVLONG:
+		case TUVLONG:
+			diag(f, "unimplemented double->vlong");
+			return;
 		}
 		break;
 	case TINT:
@@ -853,7 +922,8 @@
 		switch(tt) {
 		case TDOUBLE:
 		case TFLOAT:
-			goto fxtofl;
+			fixtofloat(f, t);
+			return;
 		case TINT:
 		case TUINT:
 		case TLONG:
@@ -871,7 +941,8 @@
 		switch(tt) {
 		case TDOUBLE:
 		case TFLOAT:
-			goto fxtofl;
+			fixtofloat(f, t);
+			return;
 		case TINT:
 		case TUINT:
 		case TLONG:
@@ -891,7 +962,8 @@
 		switch(tt) {
 		case TDOUBLE:
 		case TFLOAT:
-			goto fxtofl;
+			fixtofloat(f, t);
+			return;
 		case TINT:
 		case TUINT:
 		case TLONG:
@@ -911,7 +983,8 @@
 		switch(tt) {
 		case TDOUBLE:
 		case TFLOAT:
-			goto fxtofl;
+			fixtofloat(f, t);
+			return;
 		case TINT:
 		case TUINT:
 		case TLONG:
@@ -931,58 +1004,7 @@
 		switch(tt) {
 		case TDOUBLE:
 		case TFLOAT:
-		fxtofl:
-			/*
-			 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
-			 * t = *(double*)rat - FREGCVI;
-			 * is-unsigned(t) => if(t<0) t += 2^32;
-			 * could be streamlined for int-to-float
-			 */
-			regalloc(&fxc0, f, Z);
-			regalloc(&fxc2, f, Z);
-			regsalloc(&fxrat, &fconstnode);	/* should be type float */
-			gins(AMOVW, nodconst(0x43300000L), &fxc0);
-			gins(AMOVW, f, &fxc2);
-			gins(AMOVW, &fxc0, &fxrat);
-			gins(AXOR, nodconst(0x80000000L), &fxc2);
-			fxc1 = fxrat;
-			fxc1.type = nodrat->type;
-			fxc1.etype = nodrat->etype;
-			fxc1.xoffset += SZ_LONG;
-			gins(AMOVW, &fxc2, &fxc1);
-			regfree(&fxc2);
-			regfree(&fxc0);
-			regalloc(&nod, t, t);	/* should be type float */
-			gins(AFMOVD, &fxrat, &nod);
-			nodreg(&fxc1, t, NREG+FREGCVI);
-			gins(AFSUB, &fxc1, &nod);
-			a = AFMOVD;
-			if(tt == TFLOAT)
-				a = AFRSP;
-			gins(a, &nod, t);
-			regfree(&nod);
-			if(ft == TULONG) {
-				regalloc(&nod, t, Z);
-				if(tt == TFLOAT) {
-					gins(AFCMPU, t, Z);
-					p->to.type = D_FREG;
-					p->to.reg = FREGZERO;
-					gins(ABGE, Z, Z);
-					p1 = p;
-					gins(AFMOVS, nodfconst(4294967296.), &nod);
-					gins(AFADDS, &nod, t);
-				} else {
-					gins(AFCMPU, t, Z);
-					p->to.type = D_FREG;
-					p->to.reg = FREGZERO;
-					gins(ABGE, Z, Z);
-					p1 = p;
-					gins(AFMOVD, nodfconst(4294967296.), &nod);
-					gins(AFADD, &nod, t);
-				}
-				patch(p1, pc);
-				regfree(&nod);
-			}
+			fixtofloat(f, t);
 			return;
 		case TINT:
 		case TUINT:
@@ -1522,7 +1544,7 @@
 	if(a1 == AGOK || a2 == AGOK)
 		diag(Z, "bad in gopcode64 %O", o);
 	if(f1->op == OCONST) {
-		if(f2 != Z && f2 != t)
+		if(f2 != Z & f2 != t)
 			diag(Z, "bad const in gopcode64 %O", o);
 		gins(a1, nod32const(f1->vconst), t->right);
 		gins(a2, nod32const(f1->vconst>>32), t->left);