summaryrefslogtreecommitdiff
path: root/sys/src/cmd/7c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-04-17 23:38:00 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-04-17 23:38:00 +0200
commit15c3f45e5f7bccd121726de9b3adac001ffac887 (patch)
treea296d9da1ae8c7009939929f053e8a3e099ef830 /sys/src/cmd/7c
parentb44440bd165bdaa8c5764eead3fc54cadab7334f (diff)
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.
Diffstat (limited to 'sys/src/cmd/7c')
-rw-r--r--sys/src/cmd/7c/cgen.c12
-rw-r--r--sys/src/cmd/7c/peep.c21
-rw-r--r--sys/src/cmd/7c/reg.c1
-rw-r--r--sys/src/cmd/7c/txt.c30
4 files changed, 49 insertions, 15 deletions
diff --git a/sys/src/cmd/7c/cgen.c b/sys/src/cmd/7c/cgen.c
index ecdab98ba..bfef2fd4e 100644
--- a/sys/src/cmd/7c/cgen.c
+++ b/sys/src/cmd/7c/cgen.c
@@ -390,7 +390,7 @@ cgenrel(Node *n, Node *nn, int inrel)
r = l;
while(r->op == OADD)
r = r->right;
- if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) {
+ if(usableoffset(n, nod.xoffset, r)){
v = r->vconst;
r->vconst = 0;
cgen(l, &nod);
@@ -613,7 +613,7 @@ reglcgen(Node *t, Node *n, Node *nn)
r = n->left;
while(r->op == OADD)
r = r->right;
- if(sconst(r) && (v = r->vconst+t->xoffset) >= -4096 && v < 4096) {
+ if(usableoffset(n, t->xoffset, r)) {
v = r->vconst;
r->vconst = 0;
lcgen(n, t);
@@ -623,11 +623,17 @@ reglcgen(Node *t, Node *n, Node *nn)
return;
}
} else if(n->op == OINDREG) {
- if((v = n->xoffset) >= -4096 && v < 4096) {
+ if(usableoffset(n, t->xoffset+n->xoffset, nil)) {
+ Type *tt = n->type;
+ n->type = types[TIND];
n->op = OREGISTER;
+ v = n->xoffset;
+ n->xoffset = 0;
cgen(n, t);
t->xoffset += v;
+ n->xoffset = v;
n->op = OINDREG;
+ n->type = tt;
regind(t, n);
return;
}
diff --git a/sys/src/cmd/7c/peep.c b/sys/src/cmd/7c/peep.c
index 557af7b18..8d07cfcc9 100644
--- a/sys/src/cmd/7c/peep.c
+++ b/sys/src/cmd/7c/peep.c
@@ -2,6 +2,9 @@
int xtramodes(Reg*, Adr*);
+Reg* findpre(Reg *r, Adr *v);
+Reg* findinc(Reg *r, Reg *r2, Adr *v);
+
void
peep(void)
{
@@ -55,6 +58,21 @@ loop1:
t++;
}
}
+ if(p->as == ASXTW){
+ r1 = findpre(r, &p->from);
+ if(r1 != R){
+ p1 = r1->prog;
+ switch(p1->as){
+ case AMOVB:
+ case AMOVBU:
+ case AMOVH:
+ case AMOVHU:
+ case AMOVW:
+ p->as = AMOVW;
+ break;
+ }
+ }
+ }
if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
if(regtyp(&p->to)) {
if(p->from.type == D_CONST)
@@ -425,6 +443,7 @@ subprop(Reg *r0)
case AFMOVD:
case AMOVW:
case AMOV:
+ case ASXTW:
if(p->to.type == v1->type)
if(p->to.reg == v1->reg)
goto gotit;
@@ -954,8 +973,8 @@ copyu(Prog *p, Adr *v, Adr *s)
case AMOVBU:
case AMOVW:
case AMOVWU:
+ case ASXTW:
case AMOV:
-
case AMVN:
case AMVNW:
case ANEG:
diff --git a/sys/src/cmd/7c/reg.c b/sys/src/cmd/7c/reg.c
index 174ffd7e0..d992ba8f9 100644
--- a/sys/src/cmd/7c/reg.c
+++ b/sys/src/cmd/7c/reg.c
@@ -150,6 +150,7 @@ regopt(Prog *p)
case AMOVHU:
case AMOVW:
case AMOVWU:
+ case ASXTW:
case AFMOVS:
case AFCVTSD:
case AFMOVD:
diff --git a/sys/src/cmd/7c/txt.c b/sys/src/cmd/7c/txt.c
index 4a345cf46..96a9eaf86 100644
--- a/sys/src/cmd/7c/txt.c
+++ b/sys/src/cmd/7c/txt.c
@@ -761,7 +761,10 @@ gmove(Node *f, Node *t)
case TVLONG:
case TUVLONG:
case TIND:
- a = AMOV;
+ if(typeu[ft])
+ a = AMOVWU;
+ else
+ a = ASXTW;
break;
}
break;
@@ -785,14 +788,16 @@ gmove(Node *f, Node *t)
case TUINT:
case TLONG:
case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
case TSHORT:
case TUSHORT:
case TCHAR:
case TUCHAR:
- a = AMOV; /* TO DO: conversion done? */
+ a = AMOVWU;
+ break;
+ case TVLONG:
+ case TUVLONG:
+ case TIND:
+ a = AMOV;
break;
}
break;
@@ -1323,16 +1328,19 @@ sval(vlong v)
int
usableoffset(Node *n, vlong o, Node *v)
{
- int s, et;
+ int s;
- et = v->type->etype;
- if(v->op != OCONST || typefd[et])
- return 0;
+ if(v != nil){
+ if(v->op != OCONST || typefd[v->type->etype])
+ return 0;
+ o += v->vconst;
+ }
s = n->type->width;
if(s > 16)
s = 16;
- o += v->vconst;
- return o >= -256 || o < 4095*s;
+ if((o % s) != 0)
+ return 0;
+ return o >= -256 && o < 4096*s;
}
long