shithub: riscv

Download patch

ref: 107ca1b42d099d74cd033be7f363b92d4ff29e3c
parent: bfd0cb0db474a2ace38443537aff86382ec10baf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 4 16:06:30 EDT 2015

cc: handle 64 bit mixedmode asop and type vlong <-> float/double type conversions

--- a/sys/src/cmd/cc/com64.c
+++ b/sys/src/cmd/cc/com64.c
@@ -49,6 +49,8 @@
 
 Node*	nodv2f;
 Node*	nodv2d;
+Node*	noduv2f;
+Node*	noduv2d;
 Node*	nodv2ui;
 Node*	nodv2si;
 Node*	nodv2ul;
@@ -63,6 +65,11 @@
 Node*	nodvmm;
 Node*	nodmmv;
 
+Node*	nodaddd;
+Node*	nodsubd;
+Node*	nodmuld;
+Node*	noddivd;
+
 Node*	nodvasop;
 
 char	etconv[NTYPE];	/* for _vasop */
@@ -146,6 +153,8 @@
 
 	nodv2f = fvn("_v2f", TFLOAT);
 	nodv2d = fvn("_v2d", TDOUBLE);
+	noduv2f = fvn("_uv2f", TFLOAT);
+	noduv2d = fvn("_uv2d", TDOUBLE);
 	nodv2sl = fvn("_v2sl", TLONG);
 	nodv2ul = fvn("_v2ul", TULONG);
 	nodv2si = fvn("_v2si", TINT);
@@ -160,6 +169,11 @@
 	nodvmm = fvn("_vmm", TVLONG);
 	nodmmv = fvn("_mmv", TVLONG);
 
+	nodaddd = fvn("_vasaddd", TVLONG);
+	nodsubd = fvn("_vassubd", TVLONG);
+	nodmuld = fvn("_vasmuld", TVLONG);
+	noddivd = fvn("_vasdivd", TVLONG);
+
 	nodvasop = fvn("_vasop", TVLONG);
 
 	for(p = initetconv; p->code >= 0; p++)
@@ -416,28 +430,6 @@
 		}
 	}
 
-	if(typefd[n->type->etype] && l && l->op == OFUNC) {
-		switch(n->op) {
-		case OASADD:
-		case OASSUB:
-		case OASMUL:
-		case OASLMUL:
-		case OASDIV:
-		case OASLDIV:
-		case OASMOD:
-		case OASLMOD:
-		case OASASHL:
-		case OASASHR:
-		case OASLSHR:
-		case OASAND:
-		case OASOR:
-		case OASXOR:
-			if(l->right && typev[l->right->etype]) {
-				diag(n, "sorry float <asop> vlong not implemented\n");
-			}
-		}
-	}
-
 	if(n->op == OCAST) {
 		if(l->type && typev[l->type->etype]) {
 			if(machcap(n))
@@ -444,10 +436,16 @@
 				return 1;
 			switch(n->type->etype) {
 			case TDOUBLE:
-				a = nodv2d;
+				if(l->type->etype == TUVLONG)
+					a = noduv2d;
+				else
+					a = nodv2d;
 				goto setfnx;
 			case TFLOAT:
-				a = nodv2f;
+				if(l->type->etype == TUVLONG)
+					a = noduv2f;
+				else
+					a = nodv2f;
 				goto setfnx;
 			case TLONG:
 				a = nodv2sl;
@@ -524,9 +522,43 @@
 	return 1;
 
 setasop:
-	if(l->op == OFUNC) {
+	while(l->op == OFUNC)
 		l = l->right;
-		goto setasop;
+
+	if(mixedasop(n->left->type, n->right->type)) {
+		if(n->right->type->etype != TDOUBLE) {
+			r = new(OCAST, r, 0);
+			r->type = types[TDOUBLE];
+		}
+
+		if(l->type->etype == TUVLONG)
+			a = noduv2d;
+		else
+			a = nodv2d;
+
+		t = new(OADDR, a, 0);
+		t->type = typ(TIND, a->type);
+		r = new(OLIST, t, r);
+
+		t = new(OADDR, l, 0);
+		t->type = typ(TIND, l->type);
+		t->complex = l->complex;
+		r = new(OLIST, t, r);
+
+		switch(n->op){
+		default:	diag(n, "mixed vlong/double %O not implemented", n->op);
+		case OASADD:	a = nodaddd; break;
+		case OASSUB:	a = nodsubd; break;
+		case OASMUL:	a = nodmuld; break;
+		case OASDIV:	a = noddivd; break;
+		}
+
+		n->left = a;
+		n->right = r;
+		n->complex = FNX;
+		n->op = OFUNC;
+
+		return 1;
 	}
 
 	t = new(OCONST, 0, 0);