changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: 7c: fix long to vlong/pointer conversion, avoid negative immediate offsets

changeset 7169: 94fca26a23d8
parent 7168: 1a2f7f23c5bd
child 7170: 55bc217eb3f5
author: cinap_lenrek@felloff.net
date: Wed, 17 Apr 2019 23:38:00 +0200
files: sys/src/cmd/7c/cgen.c sys/src/cmd/7c/peep.c sys/src/cmd/7c/reg.c sys/src/cmd/7c/txt.c
description: 7c: fix long to vlong/pointer conversion, avoid negative immediate offsets

we have to explicitely convert to vlong by sign or
zero extending as not every operation leaves a proper
zero/sign extended result in the register. for example
NEGW will zero extend, breaking negative int offsets
on pointers.

we explicitely insert SXTW or MOVWU instructions which
the peephole optimizer takes out again when it is safe
todo so.

when promoting constant offsets to immediate offsets,
make sure the offset will be in range. otherwise the
linker will produce not so optimal pointer arithmetic
instructions to calculate the offset.
     1.1--- a/sys/src/cmd/7c/cgen.c
     1.2+++ b/sys/src/cmd/7c/cgen.c
     1.3@@ -390,7 +390,7 @@ cgenrel(Node *n, Node *nn, int inrel)
     1.4 		r = l;
     1.5 		while(r->op == OADD)
     1.6 			r = r->right;
     1.7-		if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) {
     1.8+		if(usableoffset(n, nod.xoffset, r)){
     1.9 			v = r->vconst;
    1.10 			r->vconst = 0;
    1.11 			cgen(l, &nod);
    1.12@@ -613,7 +613,7 @@ reglcgen(Node *t, Node *n, Node *nn)
    1.13 		r = n->left;
    1.14 		while(r->op == OADD)
    1.15 			r = r->right;
    1.16-		if(sconst(r) && (v = r->vconst+t->xoffset) >= -4096 && v < 4096) {
    1.17+		if(usableoffset(n, t->xoffset, r)) {
    1.18 			v = r->vconst;
    1.19 			r->vconst = 0;
    1.20 			lcgen(n, t);
    1.21@@ -623,11 +623,17 @@ reglcgen(Node *t, Node *n, Node *nn)
    1.22 			return;
    1.23 		}
    1.24 	} else if(n->op == OINDREG) {
    1.25-		if((v = n->xoffset) >= -4096 && v < 4096) {
    1.26+		if(usableoffset(n, t->xoffset+n->xoffset, nil)) {
    1.27+			Type *tt = n->type;
    1.28+			n->type = types[TIND];
    1.29 			n->op = OREGISTER;
    1.30+			v = n->xoffset;
    1.31+			n->xoffset = 0;
    1.32 			cgen(n, t);
    1.33 			t->xoffset += v;
    1.34+			n->xoffset = v;
    1.35 			n->op = OINDREG;
    1.36+			n->type = tt;
    1.37 			regind(t, n);
    1.38 			return;
    1.39 		}
     2.1--- a/sys/src/cmd/7c/peep.c
     2.2+++ b/sys/src/cmd/7c/peep.c
     2.3@@ -2,6 +2,9 @@
     2.4 
     2.5 int xtramodes(Reg*, Adr*);
     2.6 
     2.7+Reg* findpre(Reg *r, Adr *v);
     2.8+Reg* findinc(Reg *r, Reg *r2, Adr *v);
     2.9+
    2.10 void
    2.11 peep(void)
    2.12 {
    2.13@@ -55,6 +58,21 @@ loop1:
    2.14 				t++;
    2.15 			}
    2.16 		}
    2.17+		if(p->as == ASXTW){
    2.18+			r1 = findpre(r, &p->from);
    2.19+			if(r1 != R){
    2.20+				p1 = r1->prog;
    2.21+				switch(p1->as){
    2.22+				case AMOVB:
    2.23+				case AMOVBU:
    2.24+				case AMOVH:
    2.25+				case AMOVHU:
    2.26+				case AMOVW:
    2.27+					p->as = AMOVW;
    2.28+					break;
    2.29+				}
    2.30+			}
    2.31+		}
    2.32 		if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
    2.33 		if(regtyp(&p->to)) {
    2.34 			if(p->from.type == D_CONST)
    2.35@@ -425,6 +443,7 @@ subprop(Reg *r0)
    2.36 		case AFMOVD:
    2.37 		case AMOVW:
    2.38 		case AMOV:
    2.39+		case ASXTW:
    2.40 			if(p->to.type == v1->type)
    2.41 			if(p->to.reg == v1->reg)
    2.42 				goto gotit;
    2.43@@ -954,8 +973,8 @@ copyu(Prog *p, Adr *v, Adr *s)
    2.44 	case AMOVBU:
    2.45 	case AMOVW:
    2.46 	case AMOVWU:
    2.47+	case ASXTW:
    2.48 	case AMOV:
    2.49-
    2.50 	case AMVN:
    2.51 	case AMVNW:
    2.52 	case ANEG:
     3.1--- a/sys/src/cmd/7c/reg.c
     3.2+++ b/sys/src/cmd/7c/reg.c
     3.3@@ -150,6 +150,7 @@ regopt(Prog *p)
     3.4 		case AMOVHU:
     3.5 		case AMOVW:
     3.6 		case AMOVWU:
     3.7+		case ASXTW:
     3.8 		case AFMOVS:
     3.9 		case AFCVTSD:
    3.10 		case AFMOVD:
     4.1--- a/sys/src/cmd/7c/txt.c
     4.2+++ b/sys/src/cmd/7c/txt.c
     4.3@@ -761,7 +761,10 @@ gmove(Node *f, Node *t)
     4.4 		case TVLONG:
     4.5 		case TUVLONG:
     4.6 		case TIND:
     4.7-			a = AMOV;
     4.8+			if(typeu[ft])
     4.9+				a = AMOVWU;
    4.10+			else
    4.11+				a = ASXTW;
    4.12 			break;
    4.13 		}
    4.14 		break;
    4.15@@ -785,14 +788,16 @@ gmove(Node *f, Node *t)
    4.16 		case TUINT:
    4.17 		case TLONG:
    4.18 		case TULONG:
    4.19-		case TVLONG:
    4.20-		case TUVLONG:
    4.21-		case TIND:
    4.22 		case TSHORT:
    4.23 		case TUSHORT:
    4.24 		case TCHAR:
    4.25 		case TUCHAR:
    4.26-			a = AMOV;	/* TO DO: conversion done? */
    4.27+			a = AMOVWU;
    4.28+			break;
    4.29+		case TVLONG:
    4.30+		case TUVLONG:
    4.31+		case TIND:
    4.32+			a = AMOV;
    4.33 			break;
    4.34 		}
    4.35 		break;
    4.36@@ -1323,16 +1328,19 @@ sval(vlong v)
    4.37 int
    4.38 usableoffset(Node *n, vlong o, Node *v)
    4.39 {
    4.40-	int s, et;
    4.41+	int s;
    4.42 
    4.43-	et = v->type->etype;
    4.44-	if(v->op != OCONST || typefd[et])
    4.45-		return 0;
    4.46+	if(v != nil){
    4.47+		if(v->op != OCONST || typefd[v->type->etype])
    4.48+			return 0;
    4.49+		o += v->vconst;
    4.50+	}
    4.51 	s = n->type->width;
    4.52 	if(s > 16)
    4.53 		s = 16;
    4.54-	o += v->vconst;
    4.55-	return o >= -256 || o < 4095*s;
    4.56+	if((o % s) != 0)
    4.57+		return 0;
    4.58+	return o >= -256 && o < 4096*s;
    4.59 }
    4.60 
    4.61 long