shithub: riscv

Download patch

ref: 8c95a221b041848a479cb2f79d5bb7be74022446
parent: 15c3f45e5f7bccd121726de9b3adac001ffac887
author: cinap_lenrek <[email protected]>
date: Wed Apr 17 19:43:59 EDT 2019

7l: deal with huge (negative or > 24bit) register offsets, fix LACON, avoid DWORD in constant pool when we can sign extend

--- a/sys/src/cmd/7l/asmout.c
+++ b/sys/src/cmd/7l/asmout.c
@@ -74,7 +74,6 @@
 asmout(Prog *p, Optab *o)
 {
 	long o1, o2, o3, o4, o5, v, hi;
-	ulong u;
 	vlong d;
 	int r, s, rf, rt, ra, nzcv, cond, i, as;
 	Mask *mask;
@@ -223,8 +222,6 @@
 
 	case 13:	/* addop $lcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
-		if(!o1)
-			break;
 		rt = p->to.reg;
 		if(p->to.type == D_NONE)
 			rt = REGZERO;
@@ -427,8 +424,6 @@
 
 	case 28:	/* logop $lcon, [R], R (64 bit literal) */
 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
-		if(!o1)
-			break;
 		r = p->reg;
 		if(r == NREG)
 			r = p->to.reg;
@@ -448,10 +443,10 @@
 		if(s < 0)
 			diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
 		v = regoff(&p->to);
-		if(v < 0)
-			diag("negative large offset\n%P", p);
 		if((v & ((1<<s)-1)) != 0)
 			diag("misaligned offset\n%P", p);
+		if(v < 0 || (v>>s) >= (1<<24))
+			goto Hugestxr;
 		hi = v - (v & (0xFFF<<s));
 		if((hi & 0xFFF) != 0)
 			diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
@@ -468,10 +463,10 @@
 		if(s < 0)
 			diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
 		v = regoff(&p->from);
-		if(v < 0)
-			diag("negative large offset\n%P", p);
 		if((v & ((1<<s)-1)) != 0)
 			diag("misaligned offset\n%P", p);
+		if(v < 0 || (v>>s) >= (1<<24))
+			goto Hugeldxr;
 		hi = v - (v & (0xFFF<<s));
 		if((hi & 0xFFF) != 0)
 			diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
@@ -670,23 +665,23 @@
 		break;
 
 	case 47:	/* movT R,V(R) -> strT (huge offset) */
-		o1 = omovlit(AMOVW, p, &p->to, REGTMP);
-		if(!o1)
-			break;
+	Hugestxr:
+		o1 = omovlit(AMOV, p, &p->to, REGTMP);
 		r = p->to.reg;
 		if(r == NREG)
 			r = o->param;
-		o2 = olsxrr(p->as, REGTMP,r, p->from.reg);
+		o2 = LD2STR(olsxrr(p->as, REGTMP, r, p->from.reg));
+		o2 |= 7<<13;	// REGTMP.SX
 		break;
 
 	case 48:	/* movT V(R), R -> ldrT (huge offset) */
-		o1 = omovlit(AMOVW, p, &p->from, REGTMP);
-		if(!o1)
-			break;
+	Hugeldxr:
+		o1 = omovlit(AMOV, p, &p->from, REGTMP);
 		r = p->from.reg;
 		if(r == NREG)
 			r = o->param;
-		o2 = olsxrr(p->as, REGTMP,r, p->to.reg);
+		o2 = olsxrr(p->as, REGTMP, r, p->to.reg);
+		o2 |= 7<<13;	// REGTMP.SX
 		break;
 
 	case 50:	/* sys/sysl */
@@ -845,15 +840,11 @@
 	/* reloc ops */
 	case 64:	/* movT R,addr */
 		o1 = omovlit(AMOV, p, &p->to, REGTMP);
-		if(!o1)
-			break;
 		o2 = olsr12u(opstr12(p->as), 0, REGTMP, p->from.reg);
 		break;
 
 	case 65:	/* movT addr,R */
 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
-		if(!o1)
-			break;
 		o2 = olsr12u(opldr12(p->as), 0, REGTMP, p->to.reg);
 		break;
 	}
@@ -1572,8 +1563,7 @@
 static long
 olsxrr(int a, int b, int c, int d)
 {
-	diag("need load/store extended register\n%P", curp);
-	return -1;
+	return opldrpp(a) | 1<<21 | b<<16 | 2<<10 | c<<5 | d;
 }
 
 static long
@@ -1598,7 +1588,6 @@
 
 	if(p->cond == nil){	/* not in literal pool */
 		aclass(a);
-fprint(2, "omovlit add %lld (%#llux)\n", instoffset, instoffset);
 		/* TO DO: could be clever, and use general constant builder */
 		o1 = opirr(AADD);
 		v = instoffset;
@@ -1606,6 +1595,8 @@
 			v >>= 12;
 			o1 |= 1<<22;	/* shift, by 12 */
 		}
+		if(v < 0 || v > 0xFFF)
+			diag("literal out of range\n%P", p);
 		o1 |= ((v& 0xFFF) << 10) | (REGZERO<<5) | dr;
 	}else{
 		fp = 0;
--- a/sys/src/cmd/7l/optab.c
+++ b/sys/src/cmd/7l/optab.c
@@ -141,7 +141,7 @@
 	{ AWORD,	C_NONE,	C_NONE,	C_ADDR,		14, 4, 0 },
 
 	{ AMOVW,	C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
-	{ AMOV,	C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
+	{ AMOV,		C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
 
 	{ AMOVW,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
 	{ AMOVB,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
@@ -236,46 +236,54 @@
 	{ AMOV,	C_UOREG32K,C_NONE,	C_REG,		21, 4, REGSP },
 	{ AMOV,	C_NSOREG,C_NONE,	C_REG,	21, 4, REGSP },
 
-	/* long displacement store */
-	{ AMOVB,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
-	{ AMOVB,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
-	{ AMOVB,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
-	{ AMOVH,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
-	{ AMOVH,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
-	{ AMOVH,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
-	{ AMOVW,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
-	{ AMOVW,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
-	{ AMOVW,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
-	{ AMOV,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
-	{ AMOV,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
-	{ AMOV,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
+	/* large displacement store */
+	{ AMOVB,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
+	{ AMOVB,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
+	{ AMOVB,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
+	{ AMOVBU,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
+	{ AMOVBU,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
+	{ AMOVBU,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
 
-	/* long displacement load */
-	{ AMOVB,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
-	{ AMOVB,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
-	{ AMOVB,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
-	{ AMOVB,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
-	{ AMOVH,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
-	{ AMOVH,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
-	{ AMOVH,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
-	{ AMOVH,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
-	{ AMOVW,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
-	{ AMOVW,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
-	{ AMOVW,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
-	{ AMOVW,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
-	{ AMOV,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
-	{ AMOV,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
-	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
-	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
+	{ AMOVH,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
+	{ AMOVH,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
+	{ AMOVH,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
 
-	/* load long effective stack address (load long offset and add) */
-	{ AMOV,		C_LACON,C_NONE,	C_REG,		34, 8, REGSP,	LFROM },  //
+	{ AMOVW,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
+	{ AMOVW,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
+	{ AMOVW,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
 
+	{ AMOV,		C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
+	{ AMOV,		C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
+	{ AMOV,		C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
+
+	/* large displacement load */
+	{ AMOVB,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
+	{ AMOVB,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
+	{ AMOVB,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
+	{ AMOVBU,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
+	{ AMOVBU,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
+	{ AMOVBU,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
+
+	{ AMOVH,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
+	{ AMOVH,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
+	{ AMOVH,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
+
+	{ AMOVW,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
+	{ AMOVW,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
+	{ AMOVW,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
+
+	{ AMOV,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
+	{ AMOV,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
+	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
+
+	/* load large effective stack address (load large offset and add) */
+	{ AMOV,		C_LACON,C_NONE,	C_REG,		34, 8, REGSP,	LFROM },
+
 	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
 	{ AMOV,		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
 	{ AMOVW, 	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
-	{ AMOVH,		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
-	{ AMOVB, 		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
+	{ AMOVH,	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
+	{ AMOVB, 	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
 	{ AMOVBU, 	C_XPOST,	C_NONE, C_REG,		22, 4, 0 },
 	{ AFMOVS, 	C_XPOST,	C_NONE,	C_FREG,	22, 4, 0 },
 	{ AFMOVD, 	C_XPOST,	C_NONE,	C_FREG,	22, 4, 0 },
@@ -282,8 +290,8 @@
 
 	{ AMOV,		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
 	{ AMOVW, 	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
-	{ AMOVH,		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
-	{ AMOVB, 		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
+	{ AMOVH,	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
+	{ AMOVB, 	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
 	{ AMOVBU, 	C_XPRE,	C_NONE, C_REG,		22, 4, 0 },
 	{ AFMOVS, 	C_XPRE,	C_NONE,	C_FREG,	22, 4, 0 },
 	{ AFMOVD, 	C_XPRE,	C_NONE,	C_FREG,	22, 4, 0 },
--- a/sys/src/cmd/7l/span.c
+++ b/sys/src/cmd/7l/span.c
@@ -200,23 +200,21 @@
 addpool(Prog *p, Adr *a)
 {
 	Prog *q, t;
-	int c, sz;
+	int sz;
 
-	c = aclass(a);
 
 	t = zprg;
 	t.as = AWORD;
 	sz = 4;
-	if(p->as == AMOV || (cmp(C_VCON, c) && (ulong)(a->offset & 0xFFFFFFFF) != a->offset)) {
-		t.as = ADWORD;
-		sz = 8;
-	}
-
-	switch(c) {
+	switch(aclass(a)) {
 	default:
+		if(p->as == AMOV && (a->name == D_EXTERN || a->name == D_STATIC)
+		|| (a->offset >> 32) != 0 && (a->offset >> 31) != -1){
+			t.as = ADWORD;
+			sz = 8;
+		}
 		t.to = *a;
 		break;
-
 	case C_PSAUTO:
 	case C_PPAUTO:
 	case C_UAUTO4K:
@@ -237,9 +235,11 @@
 	case C_NSOREG:
 	case C_NPOREG:
 	case C_LOREG:
+	case C_LACON:
+		if((instoffset >> 32) != 0 && (instoffset >> 31) != -1)
+			diag("offset too large\n%P", p);
 		t.to.type = D_CONST;
 		t.to.offset = instoffset;
-		sz = 4;
 		break;
 	}
 
@@ -741,7 +741,8 @@
 		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);
+				print("%P\t-> %d (%d %d %d)\n", p, o->type,
+					o->a1, o->a2, o->a3);
 			p->optab = (o-optab)+1;
 			return o;
 		}