changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: 7l: fix bitcon instruction selection and encoding

changeset 7145: 84d616f1d180
parent 7144: d0b9ab522e8b
child 7146: ffe417e0ec24
author: cinap_lenrek@felloff.net
date: Mon, 08 Apr 2019 14:12:01 +0200
files: sys/src/cmd/7l/asmout.c sys/src/cmd/7l/l.h sys/src/cmd/7l/optab.c sys/src/cmd/7l/span.c
description: 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.
     1.1--- a/sys/src/cmd/7l/asmout.c
     1.2+++ b/sys/src/cmd/7l/asmout.c
     1.3@@ -722,27 +722,24 @@ asmout(Prog *p, Optab *o)
     1.4 		if(as == AMOV){
     1.5 			as = AORR;
     1.6 			r = REGZERO;
     1.7-		}else if(as == AMOVW){
     1.8+		}else if(as == AMOVW || as == AMOVWU){
     1.9 			as = AORRW;
    1.10 			r = REGZERO;
    1.11 		}
    1.12 		o1 = opirr(as);
    1.13-		s = o1 & S64? 64: 32;
    1.14 		mask = findmask(p->from.offset);
    1.15 		if(mask == nil)
    1.16-			mask = findmask(p->from.offset | (p->from.offset<<32));
    1.17-		if(mask != nil){
    1.18-			o1 |= ((mask->r&(s-1))<<16) | (((mask->s-1)&(s-1))<<10);
    1.19-			if(s == 64){
    1.20-				if(mask->e == 64 && ((uvlong)p->from.offset>>32) != 0)
    1.21-					o1 |= 1<<22;
    1.22-			}else{
    1.23-				u = (uvlong)p->from.offset >> 32;
    1.24-				if(u != 0 && u != 0xFFFFFFFF)
    1.25-					diag("mask needs 64 bits %#llux\n%P", p->from.offset, p);
    1.26-			}
    1.27-		}else
    1.28-			diag("invalid mask %#llux\n%P", p->from.offset, p);	/* probably shouldn't happen */
    1.29+			mask = findmask(p->from.offset | p->from.offset<<32);
    1.30+		if(mask == nil)
    1.31+			diag("invalid mask %#llux\n%P", p->from.offset, p);
    1.32+		switch(mask->e){
    1.33+		case  2: o1 |= 0xF000; break;
    1.34+		case  4: o1 |= 0xE000; break;
    1.35+		case  8: o1 |= 0xC000; break;
    1.36+		case 16: o1 |= 0x8000; break;
    1.37+		case 64: o1 |= ((o1&S64)!=0)<<22; break;
    1.38+		}
    1.39+		o1 |= (mask->r<<16) | ((mask->s-1)<<10);
    1.40 		o1 |= (r<<5) | rt;
    1.41 		break;
    1.42 
    1.43@@ -1591,7 +1588,7 @@ oaddi(long o1, long v, int r, int rt)
    1.44 }
    1.45 
    1.46 /*
    1.47- * load a a literal value into dr
    1.48+ * load a literal value into dr
    1.49  */
    1.50 static long
    1.51 omovlit(int as, Prog *p, Adr *a, int dr)
     2.1--- a/sys/src/cmd/7l/l.h
     2.2+++ b/sys/src/cmd/7l/l.h
     2.3@@ -158,7 +158,9 @@ enum
     2.4 	C_ADDCON0,	/* 12-bit unsigned, unshifted */
     2.5 	C_ADDCON,	/* 12-bit unsigned, shifted left by 0 or 12 */
     2.6 	C_MOVCON,	/* generated by a 16-bit constant, optionally inverted and/or shifted by multiple of 16 */
     2.7-	C_BITCON,	/* bimm32 */
     2.8+	C_BITCON,	/* bimm32/bimm64 */
     2.9+	C_BITCON32,	/* bimm32 */
    2.10+	C_BITCON64,	/* bimm64 */
    2.11 	C_ABCON,	/* could be C_ADDCON or C_BITCON */
    2.12 	C_MBCON,	/* could be C_MOVCON or C_BITCON */
    2.13 	C_LCON,		/* 32-bit constant */
     3.1--- a/sys/src/cmd/7l/optab.c
     3.2+++ b/sys/src/cmd/7l/optab.c
     3.3@@ -42,25 +42,42 @@ Optab	optab[] =
     3.4 
     3.5 	/* logical operations */
     3.6 	{ AAND,		C_REG,	C_REG,	C_REG,		 1, 4, 0 },
     3.7+	{ AANDW,	C_REG,	C_REG,	C_REG,		 1, 4, 0 },
     3.8 	{ AAND,		C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
     3.9+	{ AANDW,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
    3.10 	{ ABIC,		C_REG,	C_REG,	C_REG,		 1, 4, 0 },
    3.11+	{ ABICW,	C_REG,	C_REG,	C_REG,		 1, 4, 0 },
    3.12 	{ ABIC,		C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
    3.13+	{ ABICW,	C_REG,	C_NONE,	C_REG,		 1, 4, 0 },
    3.14 
    3.15-	{ AAND,		C_BITCON,	C_REG,	C_REG,		53, 4, 0 },
    3.16-	{ AAND,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
    3.17-	{ ABIC,		C_BITCON,	C_REG,	C_REG,		53, 4, 0 },
    3.18-	{ ABIC,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
    3.19+	{ AAND,		C_BITCON64,C_REG,C_REG,		53, 4, 0 },
    3.20+	{ AANDW,	C_BITCON32,C_REG,C_REG,		53, 4, 0 },
    3.21+	{ AAND,		C_BITCON64,C_NONE,C_REG,	53, 4, 0 },
    3.22+	{ AANDW,	C_BITCON32,C_NONE,C_REG,	53, 4, 0 },
    3.23+	{ ABIC,		C_BITCON64,C_REG,C_REG,		53, 4, 0 },
    3.24+	{ ABICW,	C_BITCON32,C_REG,C_REG,		53, 4, 0 },
    3.25+	{ ABIC,		C_BITCON64,C_NONE,C_REG,	53, 4, 0 },
    3.26+	{ ABICW,	C_BITCON32,C_NONE,C_REG,	53, 4, 0 },
    3.27 
    3.28 	{ AAND,		C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
    3.29+	{ AANDW,	C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
    3.30 	{ AAND,		C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
    3.31+	{ AANDW,	C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
    3.32 	{ ABIC,		C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
    3.33+	{ ABICW,	C_LCON,	C_REG,	C_REG,		28, 8, 0,	LFROM },
    3.34 	{ ABIC,		C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
    3.35+	{ ABICW,	C_LCON,	C_NONE,	C_REG,		28, 8, 0,	LFROM },
    3.36 
    3.37 	{ AAND,		C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
    3.38+	{ AANDW,	C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
    3.39 	{ AAND,		C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
    3.40+	{ AANDW,	C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
    3.41 	{ ABIC,		C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
    3.42+	{ ABICW,	C_SHIFT,C_REG,	C_REG,		 3, 4, 0 },
    3.43 	{ ABIC,		C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
    3.44+	{ ABICW,	C_SHIFT,C_NONE,	C_REG,		 3, 4, 0 },
    3.45 
    3.46+	/* moves */
    3.47 	{ AMOV,		C_RSP,	C_NONE,	C_RSP,		24, 4, 0 },
    3.48 	{ AMVN,		C_REG,	C_NONE,	C_REG,		24, 4, 0 },
    3.49 	{ AMOVB,		C_REG,	C_NONE,	C_REG,		45, 4, 0 },
    3.50@@ -70,12 +87,13 @@ Optab	optab[] =
    3.51 	/* TO DO: MVN C_SHIFT */
    3.52 
    3.53 	/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
    3.54-	{ AMOVW,		C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
    3.55+	{ AMOVW,	C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
    3.56 	{ AMOV,		C_MOVCON,	C_NONE,	C_REG,		32, 4, 0 },
    3.57-//	{ AMOVW,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
    3.58+//	{ AMOVW,	C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
    3.59 //	{ AMOV,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 },
    3.60-//	{ AMOVW,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
    3.61-//	{ AMOV,		C_BITCON,	C_NONE,	C_REG,		53, 4, 0 },
    3.62+
    3.63+	{ AMOV,		C_BITCON64,	C_NONE,	C_REG,		53, 4, 0 },
    3.64+	{ AMOVW,	C_BITCON32,	C_NONE,	C_REG,		53, 4, 0 },
    3.65 
    3.66 	{ AMOVK,		C_LCON,	C_NONE,	C_REG,			33, 4, 0 },
    3.67 
     4.1--- a/sys/src/cmd/7l/span.c
     4.2+++ b/sys/src/cmd/7l/span.c
     4.3@@ -7,7 +7,7 @@ static struct {
     4.4 	ulong	size;
     4.5 } pool;
     4.6 
     4.7-static void		checkpool(Prog*, int);
     4.8+static void	checkpool(Prog*, int);
     4.9 static void 	flushpool(Prog*, int);
    4.10 static int	ispcdisp(long);
    4.11 
    4.12@@ -330,10 +330,30 @@ isaddcon(vlong v)
    4.13 }
    4.14 
    4.15 static int
    4.16+isbitcon64(uvlong v)
    4.17+{
    4.18+	return findmask(v) != nil;
    4.19+}
    4.20+
    4.21+static int
    4.22+isbitcon32(uvlong v)
    4.23+{
    4.24+	return (v >> 32) == 0 && findmask(v | v<<32) != nil;
    4.25+}
    4.26+
    4.27+static int
    4.28 isbitcon(uvlong v)
    4.29 {
    4.30-	/*  fancy bimm32 or bimm64? */
    4.31-	return findmask(v) != nil || (v>>32) == 0 && findmask(v | (v<<32)) != nil;
    4.32+	Mask *m;
    4.33+
    4.34+	if((v >> 32) != 0)
    4.35+		return 0;
    4.36+	m = findmask(v);
    4.37+	if(m == nil)
    4.38+		return 0;
    4.39+	if(m->s >= 32)
    4.40+		return 0;
    4.41+	return 1;
    4.42 }
    4.43 
    4.44 static int
    4.45@@ -618,6 +638,10 @@ aclass(Adr *a)
    4.46 			}
    4.47 			if(isbitcon(v))
    4.48 				return C_BITCON;
    4.49+			if(isbitcon64(v))
    4.50+				return C_BITCON64;
    4.51+			if(isbitcon32(v))
    4.52+				return C_BITCON32;
    4.53 			return C_LCON;
    4.54 
    4.55 		case D_EXTERN:
    4.56@@ -716,6 +740,8 @@ oplook(Prog *p)
    4.57 		if(o->a2 == a2 || c2[o->a2])
    4.58 		if(c1[o->a1])
    4.59 		if(c3[o->a3]) {
    4.60+			if(0)
    4.61+				print("%P\t-> %d (%d %d %d)\n", p, o->type, o->a1, o->a2, o->a3);
    4.62 			p->optab = (o-optab)+1;
    4.63 			return o;
    4.64 		}
    4.65@@ -755,6 +781,11 @@ cmp(int a, int b)
    4.66 			return 1;
    4.67 		break;
    4.68 
    4.69+	case C_BITCON32:
    4.70+	case C_BITCON64:
    4.71+		if(b == C_BITCON)
    4.72+			return 1;
    4.73+		/* wet floor */
    4.74 	case C_BITCON:
    4.75 		if(b == C_ABCON || b == C_MBCON)
    4.76 			return 1;
    4.77@@ -766,7 +797,7 @@ cmp(int a, int b)
    4.78 		break;
    4.79 
    4.80 	case C_LCON:
    4.81-		if(b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON)
    4.82+		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)
    4.83 			return 1;
    4.84 		break;
    4.85 
    4.86@@ -934,20 +965,24 @@ buildop(void)
    4.87 			break;
    4.88 		case AAND:	/* logical immediate, logical shifted register */
    4.89 			oprange[AANDS] = t;
    4.90+			oprange[AEOR] = t;
    4.91+			oprange[AORR] = t;
    4.92+			break;
    4.93+		case AANDW:
    4.94 			oprange[AANDSW] = t;
    4.95 			oprange[AANDW] = t;
    4.96-			oprange[AEOR] = t;
    4.97 			oprange[AEORW] = t;
    4.98-			oprange[AORR] = t;
    4.99 			oprange[AORRW] = t;
   4.100 			break;
   4.101 		case ABIC:	/* only logical shifted register */
   4.102 			oprange[ABICS] = t;
   4.103+			oprange[AEON] = t;
   4.104+			oprange[AORN] = t;
   4.105+			break;
   4.106+		case ABICW:
   4.107 			oprange[ABICSW] = t;
   4.108 			oprange[ABICW] = t;
   4.109-			oprange[AEON] = t;
   4.110 			oprange[AEONW] = t;
   4.111-			oprange[AORN] = t;
   4.112 			oprange[AORNW] = t;
   4.113 			break;
   4.114 		case ANEG: