ref: 8c95a221b041848a479cb2f79d5bb7be74022446
parent: 15c3f45e5f7bccd121726de9b3adac001ffac887
author: cinap_lenrek <cinap_lenrek@felloff.net>
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;
}
--
⑨