changelog shortlog tags branches files raw gz bz2 help

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

changeset 7170: 55bc217eb3f5
parent 7169: 94fca26a23d8
child 7171: f7b606b2be21
author: cinap_lenrek@felloff.net
date: Wed, 17 Apr 2019 23:43:59 +0200
files: sys/src/cmd/7l/asmout.c sys/src/cmd/7l/optab.c sys/src/cmd/7l/span.c
description: 7l: deal with huge (negative or > 24bit) register offsets, fix LACON, avoid DWORD in constant pool when we can sign extend
     1.1--- a/sys/src/cmd/7l/asmout.c
     1.2+++ b/sys/src/cmd/7l/asmout.c
     1.3@@ -74,7 +74,6 @@ void
     1.4 asmout(Prog *p, Optab *o)
     1.5 {
     1.6 	long o1, o2, o3, o4, o5, v, hi;
     1.7-	ulong u;
     1.8 	vlong d;
     1.9 	int r, s, rf, rt, ra, nzcv, cond, i, as;
    1.10 	Mask *mask;
    1.11@@ -223,8 +222,6 @@ asmout(Prog *p, Optab *o)
    1.12 
    1.13 	case 13:	/* addop $lcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
    1.14 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
    1.15-		if(!o1)
    1.16-			break;
    1.17 		rt = p->to.reg;
    1.18 		if(p->to.type == D_NONE)
    1.19 			rt = REGZERO;
    1.20@@ -427,8 +424,6 @@ asmout(Prog *p, Optab *o)
    1.21 
    1.22 	case 28:	/* logop $lcon, [R], R (64 bit literal) */
    1.23 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
    1.24-		if(!o1)
    1.25-			break;
    1.26 		r = p->reg;
    1.27 		if(r == NREG)
    1.28 			r = p->to.reg;
    1.29@@ -448,10 +443,10 @@ asmout(Prog *p, Optab *o)
    1.30 		if(s < 0)
    1.31 			diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
    1.32 		v = regoff(&p->to);
    1.33-		if(v < 0)
    1.34-			diag("negative large offset\n%P", p);
    1.35 		if((v & ((1<<s)-1)) != 0)
    1.36 			diag("misaligned offset\n%P", p);
    1.37+		if(v < 0 || (v>>s) >= (1<<24))
    1.38+			goto Hugestxr;
    1.39 		hi = v - (v & (0xFFF<<s));
    1.40 		if((hi & 0xFFF) != 0)
    1.41 			diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
    1.42@@ -468,10 +463,10 @@ asmout(Prog *p, Optab *o)
    1.43 		if(s < 0)
    1.44 			diag("unexpected long move, op %A tab %A\n%P", p->as, o->as, p);
    1.45 		v = regoff(&p->from);
    1.46-		if(v < 0)
    1.47-			diag("negative large offset\n%P", p);
    1.48 		if((v & ((1<<s)-1)) != 0)
    1.49 			diag("misaligned offset\n%P", p);
    1.50+		if(v < 0 || (v>>s) >= (1<<24))
    1.51+			goto Hugeldxr;
    1.52 		hi = v - (v & (0xFFF<<s));
    1.53 		if((hi & 0xFFF) != 0)
    1.54 			diag("internal: miscalculated offset %ld [%d]\n%P", v, s, p);
    1.55@@ -670,23 +665,23 @@ asmout(Prog *p, Optab *o)
    1.56 		break;
    1.57 
    1.58 	case 47:	/* movT R,V(R) -> strT (huge offset) */
    1.59-		o1 = omovlit(AMOVW, p, &p->to, REGTMP);
    1.60-		if(!o1)
    1.61-			break;
    1.62+	Hugestxr:
    1.63+		o1 = omovlit(AMOV, p, &p->to, REGTMP);
    1.64 		r = p->to.reg;
    1.65 		if(r == NREG)
    1.66 			r = o->param;
    1.67-		o2 = olsxrr(p->as, REGTMP,r, p->from.reg);
    1.68+		o2 = LD2STR(olsxrr(p->as, REGTMP, r, p->from.reg));
    1.69+		o2 |= 7<<13;	// REGTMP.SX
    1.70 		break;
    1.71 
    1.72 	case 48:	/* movT V(R), R -> ldrT (huge offset) */
    1.73-		o1 = omovlit(AMOVW, p, &p->from, REGTMP);
    1.74-		if(!o1)
    1.75-			break;
    1.76+	Hugeldxr:
    1.77+		o1 = omovlit(AMOV, p, &p->from, REGTMP);
    1.78 		r = p->from.reg;
    1.79 		if(r == NREG)
    1.80 			r = o->param;
    1.81-		o2 = olsxrr(p->as, REGTMP,r, p->to.reg);
    1.82+		o2 = olsxrr(p->as, REGTMP, r, p->to.reg);
    1.83+		o2 |= 7<<13;	// REGTMP.SX
    1.84 		break;
    1.85 
    1.86 	case 50:	/* sys/sysl */
    1.87@@ -845,15 +840,11 @@ asmout(Prog *p, Optab *o)
    1.88 	/* reloc ops */
    1.89 	case 64:	/* movT R,addr */
    1.90 		o1 = omovlit(AMOV, p, &p->to, REGTMP);
    1.91-		if(!o1)
    1.92-			break;
    1.93 		o2 = olsr12u(opstr12(p->as), 0, REGTMP, p->from.reg);
    1.94 		break;
    1.95 
    1.96 	case 65:	/* movT addr,R */
    1.97 		o1 = omovlit(AMOV, p, &p->from, REGTMP);
    1.98-		if(!o1)
    1.99-			break;
   1.100 		o2 = olsr12u(opldr12(p->as), 0, REGTMP, p->to.reg);
   1.101 		break;
   1.102 	}
   1.103@@ -1572,8 +1563,7 @@ opldrpp(int a)
   1.104 static long
   1.105 olsxrr(int a, int b, int c, int d)
   1.106 {
   1.107-	diag("need load/store extended register\n%P", curp);
   1.108-	return -1;
   1.109+	return opldrpp(a) | 1<<21 | b<<16 | 2<<10 | c<<5 | d;
   1.110 }
   1.111 
   1.112 static long
   1.113@@ -1598,7 +1588,6 @@ omovlit(int as, Prog *p, Adr *a, int dr)
   1.114 
   1.115 	if(p->cond == nil){	/* not in literal pool */
   1.116 		aclass(a);
   1.117-fprint(2, "omovlit add %lld (%#llux)\n", instoffset, instoffset);
   1.118 		/* TO DO: could be clever, and use general constant builder */
   1.119 		o1 = opirr(AADD);
   1.120 		v = instoffset;
   1.121@@ -1606,6 +1595,8 @@ fprint(2, "omovlit add %lld (%#llux)\n",
   1.122 			v >>= 12;
   1.123 			o1 |= 1<<22;	/* shift, by 12 */
   1.124 		}
   1.125+		if(v < 0 || v > 0xFFF)
   1.126+			diag("literal out of range\n%P", p);
   1.127 		o1 |= ((v& 0xFFF) << 10) | (REGZERO<<5) | dr;
   1.128 	}else{
   1.129 		fp = 0;
     2.1--- a/sys/src/cmd/7l/optab.c
     2.2+++ b/sys/src/cmd/7l/optab.c
     2.3@@ -141,7 +141,7 @@ Optab	optab[] =
     2.4 	{ AWORD,	C_NONE,	C_NONE,	C_ADDR,		14, 4, 0 },
     2.5 
     2.6 	{ AMOVW,	C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
     2.7-	{ AMOV,	C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
     2.8+	{ AMOV,		C_LCON,	C_NONE,	C_REG,		12, 4, 0,	LFROM },
     2.9 
    2.10 	{ AMOVW,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
    2.11 	{ AMOVB,	C_REG,	C_NONE,	C_ADDR,		64, 8, 0,	LTO },
    2.12@@ -236,54 +236,62 @@ Optab	optab[] =
    2.13 	{ AMOV,	C_UOREG32K,C_NONE,	C_REG,		21, 4, REGSP },
    2.14 	{ AMOV,	C_NSOREG,C_NONE,	C_REG,	21, 4, REGSP },
    2.15 
    2.16-	/* long displacement store */
    2.17-	{ AMOVB,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
    2.18-	{ AMOVB,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
    2.19-	{ AMOVB,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
    2.20-	{ AMOVH,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
    2.21-	{ AMOVH,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
    2.22-	{ AMOVH,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
    2.23-	{ AMOVW,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
    2.24-	{ AMOVW,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
    2.25-	{ AMOVW,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
    2.26-	{ AMOV,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB },  // 
    2.27-	{ AMOV,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP },  // 
    2.28-	{ AMOV,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0 },  // 
    2.29+	/* large displacement store */
    2.30+	{ AMOVB,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
    2.31+	{ AMOVB,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
    2.32+	{ AMOVB,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
    2.33+	{ AMOVBU,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
    2.34+	{ AMOVBU,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
    2.35+	{ AMOVBU,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
    2.36+
    2.37+	{ AMOVH,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
    2.38+	{ AMOVH,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
    2.39+	{ AMOVH,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
    2.40+
    2.41+	{ AMOVW,	C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
    2.42+	{ AMOVW,	C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
    2.43+	{ AMOVW,	C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
    2.44+
    2.45+	{ AMOV,		C_REG,	C_NONE,	C_LEXT,		30, 8, REGSB,	LTO },
    2.46+	{ AMOV,		C_REG,	C_NONE,	C_LAUTO,	30, 8, REGSP,	LTO },
    2.47+	{ AMOV,		C_REG,	C_NONE,	C_LOREG,	30, 8, 0,	LTO },
    2.48 
    2.49-	/* long displacement load */
    2.50-	{ AMOVB,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
    2.51-	{ AMOVB,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
    2.52-	{ AMOVB,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
    2.53-	{ AMOVB,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
    2.54-	{ AMOVH,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
    2.55-	{ AMOVH,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
    2.56-	{ AMOVH,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
    2.57-	{ AMOVH,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
    2.58-	{ AMOVW,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
    2.59-	{ AMOVW,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
    2.60-	{ AMOVW,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
    2.61-	{ AMOVW,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
    2.62-	{ AMOV,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB },  // 
    2.63-	{ AMOV,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP },  // 
    2.64-	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },  // 
    2.65-	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0 },	//
    2.66+	/* large displacement load */
    2.67+	{ AMOVB,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
    2.68+	{ AMOVB,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
    2.69+	{ AMOVB,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
    2.70+	{ AMOVBU,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
    2.71+	{ AMOVBU,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
    2.72+	{ AMOVBU,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
    2.73 
    2.74-	/* load long effective stack address (load long offset and add) */
    2.75-	{ AMOV,		C_LACON,C_NONE,	C_REG,		34, 8, REGSP,	LFROM },  //
    2.76+	{ AMOVH,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
    2.77+	{ AMOVH,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
    2.78+	{ AMOVH,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
    2.79+
    2.80+	{ AMOVW,	C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
    2.81+	{ AMOVW,	C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
    2.82+	{ AMOVW,	C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
    2.83+
    2.84+	{ AMOV,		C_LEXT,	C_NONE,	C_REG,		31, 8, REGSB,	LFROM  },
    2.85+	{ AMOV,		C_LAUTO,C_NONE,	C_REG,		31, 8, REGSP,	LFROM  },
    2.86+	{ AMOV,		C_LOREG,C_NONE,	C_REG,		31, 8, 0,	LFROM  },
    2.87+
    2.88+	/* load large effective stack address (load large offset and add) */
    2.89+	{ AMOV,		C_LACON,C_NONE,	C_REG,		34, 8, REGSP,	LFROM },
    2.90 
    2.91 	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
    2.92 	{ AMOV,		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.93 	{ AMOVW, 	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.94-	{ AMOVH,		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.95-	{ AMOVB, 		C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.96+	{ AMOVH,	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.97+	{ AMOVB, 	C_XPOST,	C_NONE,	C_REG,		22, 4, 0 },
    2.98 	{ AMOVBU, 	C_XPOST,	C_NONE, C_REG,		22, 4, 0 },
    2.99 	{ AFMOVS, 	C_XPOST,	C_NONE,	C_FREG,	22, 4, 0 },
   2.100 	{ AFMOVD, 	C_XPOST,	C_NONE,	C_FREG,	22, 4, 0 },
   2.101 
   2.102 	{ AMOV,		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.103 	{ AMOVW, 	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.104-	{ AMOVH,		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.105-	{ AMOVB, 		C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.106+	{ AMOVH,	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.107+	{ AMOVB, 	C_XPRE,	C_NONE,	C_REG,		22, 4, 0 },
   2.108 	{ AMOVBU, 	C_XPRE,	C_NONE, C_REG,		22, 4, 0 },
   2.109 	{ AFMOVS, 	C_XPRE,	C_NONE,	C_FREG,	22, 4, 0 },
   2.110 	{ AFMOVD, 	C_XPRE,	C_NONE,	C_FREG,	22, 4, 0 },
     3.1--- a/sys/src/cmd/7l/span.c
     3.2+++ b/sys/src/cmd/7l/span.c
     3.3@@ -200,23 +200,21 @@ void
     3.4 addpool(Prog *p, Adr *a)
     3.5 {
     3.6 	Prog *q, t;
     3.7-	int c, sz;
     3.8+	int sz;
     3.9 
    3.10-	c = aclass(a);
    3.11 
    3.12 	t = zprg;
    3.13 	t.as = AWORD;
    3.14 	sz = 4;
    3.15-	if(p->as == AMOV || (cmp(C_VCON, c) && (ulong)(a->offset & 0xFFFFFFFF) != a->offset)) {
    3.16-		t.as = ADWORD;
    3.17-		sz = 8;
    3.18-	}
    3.19-
    3.20-	switch(c) {
    3.21+	switch(aclass(a)) {
    3.22 	default:
    3.23+		if(p->as == AMOV && (a->name == D_EXTERN || a->name == D_STATIC)
    3.24+		|| (a->offset >> 32) != 0 && (a->offset >> 31) != -1){
    3.25+			t.as = ADWORD;
    3.26+			sz = 8;
    3.27+		}
    3.28 		t.to = *a;
    3.29 		break;
    3.30-
    3.31 	case C_PSAUTO:
    3.32 	case C_PPAUTO:
    3.33 	case C_UAUTO4K:
    3.34@@ -237,9 +235,11 @@ addpool(Prog *p, Adr *a)
    3.35 	case C_NSOREG:
    3.36 	case C_NPOREG:
    3.37 	case C_LOREG:
    3.38+	case C_LACON:
    3.39+		if((instoffset >> 32) != 0 && (instoffset >> 31) != -1)
    3.40+			diag("offset too large\n%P", p);
    3.41 		t.to.type = D_CONST;
    3.42 		t.to.offset = instoffset;
    3.43-		sz = 4;
    3.44 		break;
    3.45 	}
    3.46 
    3.47@@ -741,7 +741,8 @@ oplook(Prog *p)
    3.48 		if(c1[o->a1])
    3.49 		if(c3[o->a3]) {
    3.50 			if(0)
    3.51-				print("%P\t-> %d (%d %d %d)\n", p, o->type, o->a1, o->a2, o->a3);
    3.52+				print("%P\t-> %d (%d %d %d)\n", p, o->type,
    3.53+					o->a1, o->a2, o->a3);
    3.54 			p->optab = (o-optab)+1;
    3.55 			return o;
    3.56 		}