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

front
cinap_lenrek 2019-04-17 23:43:59 +02:00
parent 15c3f45e5f
commit 8c95a221b0
3 changed files with 72 additions and 72 deletions

View File

@ -74,7 +74,6 @@ void
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 @@ asmout(Prog *p, Optab *o)
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 @@ asmout(Prog *p, Optab *o)
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 @@ asmout(Prog *p, Optab *o)
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 @@ asmout(Prog *p, Optab *o)
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 @@ asmout(Prog *p, Optab *o)
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 @@ asmout(Prog *p, Optab *o)
/* 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 @@ opldrpp(int a)
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 @@ omovlit(int as, Prog *p, Adr *a, int dr)
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 @@ fprint(2, "omovlit add %lld (%#llux)\n", instoffset, instoffset);
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;

View File

@ -141,7 +141,7 @@ Optab optab[] =
{ 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,54 +236,62 @@ Optab optab[] =
{ 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 },
{ 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 },

View File

@ -200,23 +200,21 @@ void
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 @@ addpool(Prog *p, Adr *a)
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 @@ oplook(Prog *p)
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;
}