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;
}