shithub: riscv

Download patch

ref: 19dc7c2097cbbdeeef02ba79161a2c67f3ba3987
parent: 8547defe701a6ea353b12e61008a28e0b6967134
author: cinap_lenrek <[email protected]>
date: Mon Jan 2 00:49:18 EST 2017

6c, 8c: fix "DI botch" evacuating DI/SI/CX registers to ".save" variables

--- a/sys/src/cmd/6c/cgen.c
+++ b/sys/src/cmd/6c/cgen.c
@@ -1396,7 +1396,7 @@
 	Prog *p1;
 	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
 	Type *t;
-	int c, mt, mo;
+	int v, c, mt, mo;
 	vlong o0, o1;
 
 	if(n == Z || n->type == T)
@@ -1615,8 +1615,8 @@
 		return;
 	}
 
+	c = cursafe;
 	if(w <= 32) {
-		c = cursafe;
 		if(n->left != Z && n->left->complex >= FNX
 		&& n->right != Z && n->right->complex >= FNX) {
 			regsalloc(&nod1, n->right);
@@ -1696,77 +1696,84 @@
 		return;
 	}
 
-	/* botch, need to save in .safe */
-	c = 0;
-	if(n->complex > nn->complex) {
-		t = n->type;
+	t = n->type;
+	if(t != types[TIND]){
 		n->type = types[TIND];
-		nodreg(&nod1, n, D_SI);
-		if(reg[D_SI]) {
-			gins(APUSHQ, &nod1, Z);
-			c |= 1;
-			reg[D_SI]++;
-		}
-		lcgen(n, &nod1);
+		sugen(n, nn, w);
 		n->type = t;
-
-		t = nn->type;
+		return;
+	}
+	t = nn->type;
+	if(t != types[TIND]){
 		nn->type = types[TIND];
-		nodreg(&nod2, nn, D_DI);
-		if(reg[D_DI]) {
-warn(Z, "DI botch");
-			gins(APUSHQ, &nod2, Z);
-			c |= 2;
-			reg[D_DI]++;
-		}
-		lcgen(nn, &nod2);
+		sugen(n, nn, w);
 		nn->type = t;
+		return;
+	}
+
+	if(nodreg(&nod1, n, D_SI)) {
+		regsalloc(&nod4, &nod1);
+		gmove(&nod1, &nod4);
+		v = reg[D_SI];
+		reg[D_SI] = 0;
+		sugen(n, nn, w);
+		reg[D_SI] = v;
+		gmove(&nod4, &nod1);
+		cursafe = c;
+		return;
+	}
+	if(nodreg(&nod2, nn, D_DI)) {
+		regsalloc(&nod4, &nod2);
+		gmove(&nod2, &nod4);
+		v = reg[D_DI];
+		reg[D_DI] = 0;
+		sugen(n, nn, w);
+		reg[D_DI] = v;
+		gmove(&nod4, &nod2);
+		cursafe = c;
+		return;
+	}
+	if(nodreg(&nod3, Z, D_CX)) {
+		regsalloc(&nod4, &nod3);
+		gmove(&nod3, &nod4);
+		v = reg[D_CX];
+		reg[D_CX] = 0;
+		sugen(n, nn, w);
+		reg[D_CX] = v;
+		gmove(&nod4, &nod3);
+		cursafe = c;
+		return;
+	}
+
+	if(n->complex > nn->complex){
+		reg[nod1.reg]++;
+		lcgen(n, &nod1);
+
+		reg[nod2.reg]++;
+		lcgen(nn, &nod2);
 	} else {
-		t = nn->type;
-		nn->type = types[TIND];
-		nodreg(&nod2, nn, D_DI);
-		if(reg[D_DI]) {
-warn(Z, "DI botch");
-			gins(APUSHQ, &nod2, Z);
-			c |= 2;
-			reg[D_DI]++;
-		}
+		reg[nod2.reg]++;
 		lcgen(nn, &nod2);
-		nn->type = t;
 
-		t = n->type;
-		n->type = types[TIND];
-		nodreg(&nod1, n, D_SI);
-		if(reg[D_SI]) {
-			gins(APUSHQ, &nod1, Z);
-			c |= 1;
-			reg[D_SI]++;
-		}
+		reg[nod1.reg]++;
 		lcgen(n, &nod1);
-		n->type = t;
 	}
-	nodreg(&nod3, n, D_CX);
-	if(reg[D_CX]) {
-		gins(APUSHQ, &nod3, Z);
-		c |= 4;
-		reg[D_CX]++;
-	}
-	gins(AMOVL, nodconst(w/SZ_INT), &nod3);
+	reg[nod3.reg]++;
+
+	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
 	gins(ACLD, Z, Z);
 	gins(AREP, Z, Z);
 	gins(AMOVSL, Z, Z);
-	if(c & 4) {
-		gins(APOPQ, Z, &nod3);
-		reg[D_CX]--;
+	if(w & (SZ_LONG-1)) {
+		/* odd length of packed structure */
+		gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
+		gins(AREP, Z, Z);
+		gins(AMOVSB, Z, Z);
 	}
-	if(c & 2) {
-		gins(APOPQ, Z, &nod2);
-		reg[nod2.reg]--;
-	}
-	if(c & 1) {
-		gins(APOPQ, Z, &nod1);
-		reg[nod1.reg]--;
-	}
+
+	reg[nod3.reg]--;
+	reg[nod2.reg]--;
+	reg[nod1.reg]--;
 }
 
 /*
--- a/sys/src/cmd/8c/cgen.c
+++ b/sys/src/cmd/8c/cgen.c
@@ -1687,11 +1687,10 @@
 
 	x = 0;
 	v = w == 8;
+	c = cursafe;
 	if(v) {
-		c = cursafe;
 		if(n->left != Z && n->left->complex >= FNX
 		&& n->right != Z && n->right->complex >= FNX) {
-//			warn(n, "toughie");
 			regsalloc(&nod1, n->right);
 			cgen(n->right, &nod1);
 			nod2 = *n;
@@ -1708,14 +1707,10 @@
 			n = n->left;
 			x = 1;
 		}
-	}
 
-	/* botch, need to save in .safe */
-	c = 0;
-	if(n->complex > nn->complex) {
-		t = n->type;
-		n->type = types[TLONG];
-		if(v) {
+		if(n->complex > nn->complex){
+			t = n->type;
+			n->type = types[TLONG];
 			regalloc(&nod0, n, Z);
 			if(!vaddr(n, 0)) {
 				reglcgen(&nod1, n, Z);
@@ -1724,21 +1719,9 @@
 			}
 			else
 				n->type = t;
-		}
-		else {
-			nodreg(&nod1, n, D_SI);
-			if(reg[D_SI]) {
-				gins(APUSHL, &nod1, Z);
-				c |= 1;
-				reg[D_SI]++;
-			}
-			lcgen(n, &nod1);
-			n->type = t;
-		}
 
-		t = nn->type;
-		nn->type = types[TLONG];
-		if(v) {
+			t = nn->type;
+			nn->type = types[TLONG];
 			if(!vaddr(nn, 0)) {
 				reglcgen(&nod2, nn, Z);
 				nn->type = t;
@@ -1746,21 +1729,9 @@
 			}
 			else
 				nn->type = t;
-		}
-		else {
-			nodreg(&nod2, nn, D_DI);
-			if(reg[D_DI]) {
-				gins(APUSHL, &nod2, Z);
-				c |= 2;
-				reg[D_DI]++;
-			}
-			lcgen(nn, &nod2);
-			nn->type = t;
-		}
-	} else {
-		t = nn->type;
-		nn->type = types[TLONG];
-		if(v) {
+		} else {
+			t = nn->type;
+			nn->type = types[TLONG];
 			regalloc(&nod0, nn, Z);
 			if(!vaddr(nn, 0)) {
 				reglcgen(&nod2, nn, Z);
@@ -1769,21 +1740,9 @@
 			}
 			else
 				nn->type = t;
-		}
-		else {
-			nodreg(&nod2, nn, D_DI);
-			if(reg[D_DI]) {
-				gins(APUSHL, &nod2, Z);
-				c |= 2;
-				reg[D_DI]++;
-			}
-			lcgen(nn, &nod2);
-			nn->type = t;
-		}
 
-		t = n->type;
-		n->type = types[TLONG];
-		if(v) {
+			t = n->type;
+			n->type = types[TLONG];
 			if(!vaddr(n, 0)) {
 				reglcgen(&nod1, n, Z);
 				n->type = t;
@@ -1792,18 +1751,6 @@
 			else
 				n->type = t;
 		}
-		else {
-			nodreg(&nod1, n, D_SI);
-			if(reg[D_SI]) {
-				gins(APUSHL, &nod1, Z);
-				c |= 1;
-				reg[D_SI]++;
-			}
-			lcgen(n, &nod1);
-			n->type = t;
-		}
-	}
-	if(v) {
 		gins(AMOVL, n, &nod0);
 		if(x)
 			gins(ANOTL, Z, &nod0);
@@ -1823,12 +1770,71 @@
 		regfree(&nod0);
 		return;
 	}
-	nodreg(&nod3, n, D_CX);
-	if(reg[D_CX]) {
-		gins(APUSHL, &nod3, Z);
-		c |= 4;
-		reg[D_CX]++;
+
+	t = n->type;
+	if(t != types[TIND]){
+		n->type = types[TIND];
+		sugen(n, nn, w);
+		n->type = t;
+		return;
 	}
+	t = nn->type;
+	if(t != types[TIND]){
+		nn->type = types[TIND];
+		sugen(n, nn, w);
+		nn->type = t;
+		return;
+	}
+
+	if(nodreg(&nod1, n, D_SI)) {
+		regsalloc(&nod4, &nod1);
+		gmove(&nod1, &nod4);
+		v = reg[D_SI];
+		reg[D_SI] = 0;
+		sugen(n, nn, w);
+		reg[D_SI] = v;
+		gmove(&nod4, &nod1);
+		cursafe = c;
+		return;
+	}
+	if(nodreg(&nod2, nn, D_DI)) {
+		regsalloc(&nod4, &nod2);
+		gmove(&nod2, &nod4);
+		v = reg[D_DI];
+		reg[D_DI] = 0;
+		sugen(n, nn, w);
+		reg[D_DI] = v;
+		gmove(&nod4, &nod2);
+		cursafe = c;
+		return;
+	}
+	if(nodreg(&nod3, Z, D_CX)) {
+		regsalloc(&nod4, &nod3);
+		gmove(&nod3, &nod4);
+		v = reg[D_CX];
+		reg[D_CX] = 0;
+		sugen(n, nn, w);
+		reg[D_CX] = v;
+		gmove(&nod4, &nod3);
+		cursafe = c;
+		return;
+	}
+
+	if(n->complex > nn->complex){
+		reg[nod1.reg]++;
+		lcgen(n, &nod1);
+
+		reg[nod2.reg]++;
+		lcgen(nn, &nod2);
+	} else {
+		reg[nod2.reg]++;
+		lcgen(nn, &nod2);
+
+		reg[nod1.reg]++;
+		lcgen(n, &nod1);
+	}
+	reg[nod3.reg]++;
+
 	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
 	gins(ACLD, Z, Z);
 	gins(AREP, Z, Z);
@@ -1839,16 +1845,8 @@
 		gins(AREP, Z, Z);
 		gins(AMOVSB, Z, Z);
 	}
-	if(c & 4) {
-		gins(APOPL, Z, &nod3);
-		reg[D_CX]--;
-	}
-	if(c & 2) {
-		gins(APOPL, Z, &nod2);
-		reg[nod2.reg]--;
-	}
-	if(c & 1) {
-		gins(APOPL, Z, &nod1);
-		reg[nod1.reg]--;
-	}
+
+	reg[nod3.reg]--;
+	reg[nod2.reg]--;
+	reg[nod1.reg]--;
 }