shithub: riscv

Download patch

ref: 12fc1c7d3e04649fb7d213d16f9da597726dd7b6
parent: d8d4802f80b40bc9a43031e3d6484aa237e7d444
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Apr 8 10:12:01 EDT 2019

7l: fix bitcon instruction selection and encoding

the possible bitmasks generated depend on the data width
of the instruction, so we introduce C_BITCON32 and C_BITCON64
operand types to keep them apart.

the encoding of the bitcon operation was wrong.

--- a/sys/src/cmd/7l/asmout.c
+++ b/sys/src/cmd/7l/asmout.c
@@ -722,27 +722,24 @@
 		if(as == AMOV){
 			as = AORR;
 			r = REGZERO;
-		}else if(as == AMOVW){
+		}else if(as == AMOVW || as == AMOVWU){
 			as = AORRW;
 			r = REGZERO;
 		}
 		o1 = opirr(as);
-		s = o1 & S64? 64: 32;
 		mask = findmask(p->from.offset);
 		if(mask == nil)
-			mask = findmask(p->from.offset | (p->from.offset<<32));
-		if(mask != nil){
-			o1 |= ((mask->r&(s-1))<<16) | (((mask->s-1)&(s-1))<<10);
-			if(s == 64){
-				if(mask->e == 64 && ((uvlong)p->from.offset>>32) != 0)
-					o1 |= 1<<22;
-			}else{
-				u = (uvlong)p->from.offset >> 32;
-				if(u != 0 && u != 0xFFFFFFFF)
-					diag("mask needs 64 bits %#llux\n%P", p->from.offset, p);
-			}
-		}else
-			diag("invalid mask %#llux\n%P", p->from.offset, p);	/* probably shouldn't happen */
+			mask = findmask(p->from.offset | p->from.offset<<32);
+		if(mask == nil)
+			diag("invalid mask %#llux\n%P", p->from.offset, p);
+		switch(mask->e){
+		case  2: o1 |= 0xF000; break;
+		case  4: o1 |= 0xE000; break;
+		case  8: o1 |= 0xC000; break;
+		case 16: o1 |= 0x8000; break;
+		case 64: o1 |= ((o1&S64)!=0)<<22; break;
+		}
+		o1 |= (mask->r<<16) | ((mask->s-1)<<10);
 		o1 |= (r<<5) | rt;
 		break;
 
@@ -1591,7 +1588,7 @@
 }
 
 /*
- * load a a literal value into dr
+ * load a literal value into dr
  */
 static long
 omovlit(int as, Prog *p, Adr *a, int dr)
--- a/sys/src/cmd/7l/l.h
+++ b/sys/src/cmd/7l/l.h
@@ -158,7 +158,9 @@
 	C_ADDCON0,	/* 12-bit unsigned, unshifted */
 	C_ADDCON,	/* 12-bit unsigned, shifted left by 0 or 12 */
 	C_MOVCON,	/* generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 */
-	C_BITCON,	/* bimm32 */
+	C_BITCON,	/* bimm32/bimm64 */
+	C_BITCON32,	/* bimm32 */
+	C_BITCON64,	/* bimm64 */
 	C_ABCON,	/* could be C_ADDCON or C_BITCON */
 	C_MBCON,	/* could be C_MOVCON or C_BITCON */
 	C_LCON,		/* 32-bit constant */
--- a/sys/src/cmd/7l/optab.c
+++ b/sys/src/cmd/7l/optab.c
@@ -42,25 +42,42 @@
 
 	/* logical operations */
 	{ AAND,		C_REG,	C_REG,	C_REG,		 1, 4, 0 },
+	{ AANDW,	C_REG,	C_REG,	C_REG,		 1, 4, 0 },
 	{ AAND,		C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
+	{ AANDW,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
 	{ ABIC,		C_REG,	C_REG,	C_REG,		 1, 4, 0 },
+	{ ABICW,	C_REG,	C_REG,	C_REG,		 1, 4, 0 },
 	{ ABIC,		C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
+	{ ABICW,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
 
-	{ AAND,		C_BITCON,	C_REG,	C_REG,		53, 4, 0 },
-	{ AAND,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
-	{ ABIC,		C_BITCON,	C_REG,	C_REG,		53, 4, 0 },
-	{ ABIC,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
+	{ AAND,		C_BITCON64,C_REG,C_REG,		53, 4, 0 },
+	{ AANDW,	C_BITCON32,C_REG,C_REG,		53, 4, 0 },
+	{ AAND,		C_BITCON64,C_NONE,C_REG,	53, 4, 0 },
+	{ AANDW,	C_BITCON32,C_NONE,C_REG,	53, 4, 0 },
+	{ ABIC,		C_BITCON64,C_REG,C_REG,		53, 4, 0 },
+	{ ABICW,	C_BITCON32,C_REG,C_REG,		53, 4, 0 },
+	{ ABIC,		C_BITCON64,C_NONE,C_REG,	53, 4, 0 },
+	{ ABICW,	C_BITCON32,C_NONE,C_REG,	53, 4, 0 },
 
 	{ AAND,		C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
+	{ AANDW,	C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
 	{ AAND,		C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
+	{ AANDW,	C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
 	{ ABIC,		C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
+	{ ABICW,	C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
 	{ ABIC,		C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
+	{ ABICW,	C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
 
 	{ AAND,		C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
+	{ AANDW,	C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
 	{ AAND,		C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
+	{ AANDW,	C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
 	{ ABIC,		C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
+	{ ABICW,	C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
 	{ ABIC,		C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
+	{ ABICW,	C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
 
+	/* moves */
 	{ AMOV,		C_RSP,	C_NONE,	C_RSP,		24, 4, 0 },
 	{ AMVN,		C_REG,	C_NONE,	C_REG,		24, 4, 0 },
 	{ AMOVB,		C_REG,	C_NONE,	C_REG,		45, 4, 0 },
@@ -70,12 +87,13 @@
 	/* TO DO: MVN C_SHIFT */
 
 	/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
-	{ AMOVW,		C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
+	{ AMOVW,	C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
 	{ AMOV,		C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
-//	{ AMOVW,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
+//	{ AMOVW,	C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
 //	{ AMOV,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
-//	{ AMOVW,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
-//	{ AMOV,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
+
+	{ AMOV,		C_BITCON64,	C_NONE,	C_REG,		53, 4, 0 },
+	{ AMOVW,	C_BITCON32,	C_NONE,	C_REG,		53, 4, 0 },
 
 	{ AMOVK,		C_LCON,	C_NONE,	C_REG,			33, 4, 0 },
 
--- a/sys/src/cmd/7l/span.c
+++ b/sys/src/cmd/7l/span.c
@@ -7,7 +7,7 @@
 	ulong	size;
 } pool;
 
-static void		checkpool(Prog*, int);
+static void	checkpool(Prog*, int);
 static void 	flushpool(Prog*, int);
 static int	ispcdisp(long);
 
@@ -330,10 +330,30 @@
 }
 
 static int
+isbitcon64(uvlong v)
+{
+	return findmask(v) != nil;
+}
+
+static int
+isbitcon32(uvlong v)
+{
+	return (v >> 32) == 0 && findmask(v | v<<32) != nil;
+}
+
+static int
 isbitcon(uvlong v)
 {
-	/*  fancy bimm32 or bimm64? */
-	return findmask(v) != nil || (v>>32) == 0 && findmask(v | (v<<32)) != nil;
+	Mask *m;
+
+	if((v >> 32) != 0)
+		return 0;
+	m = findmask(v);
+	if(m == nil)
+		return 0;
+	if(m->s >= 32)
+		return 0;
+	return 1;
 }
 
 static int
@@ -618,6 +638,10 @@
 			}
 			if(isbitcon(v))
 				return C_BITCON;
+			if(isbitcon64(v))
+				return C_BITCON64;
+			if(isbitcon32(v))
+				return C_BITCON32;
 			return C_LCON;
 
 		case D_EXTERN:
@@ -716,6 +740,8 @@
 		if(o->a2 == a2 || c2[o->a2])
 		if(c1[o->a1])
 		if(c3[o->a3]) {
+			if(0)
+				print("%P\t-> %d (%d %d %d)\n", p, o->type, o->a1, o->a2, o->a3);
 			p->optab = (o-optab)+1;
 			return o;
 		}
@@ -755,6 +781,11 @@
 			return 1;
 		break;
 
+	case C_BITCON32:
+	case C_BITCON64:
+		if(b == C_BITCON)
+			return 1;
+		/* wet floor */
 	case C_BITCON:
 		if(b == C_ABCON || b == C_MBCON)
 			return 1;
@@ -766,7 +797,7 @@
 		break;
 
 	case C_LCON:
-		if(b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON)
+		if(b == C_ZCON || b == C_BITCON || b == C_BITCON32 || b == C_BITCON64 || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON)
 			return 1;
 		break;
 
@@ -934,20 +965,24 @@
 			break;
 		case AAND:	/* logical immediate, logical shifted register */
 			oprange[AANDS] = t;
+			oprange[AEOR] = t;
+			oprange[AORR] = t;
+			break;
+		case AANDW:
 			oprange[AANDSW] = t;
 			oprange[AANDW] = t;
-			oprange[AEOR] = t;
 			oprange[AEORW] = t;
-			oprange[AORR] = t;
 			oprange[AORRW] = t;
 			break;
 		case ABIC:	/* only logical shifted register */
 			oprange[ABICS] = t;
+			oprange[AEON] = t;
+			oprange[AORN] = t;
+			break;
+		case ABICW:
 			oprange[ABICSW] = t;
 			oprange[ABICW] = t;
-			oprange[AEON] = t;
 			oprange[AEONW] = t;
-			oprange[AORN] = t;
 			oprange[AORNW] = t;
 			break;
 		case ANEG: