7l: deal with huge (negative or > 24bit) register offsets, fix LACON, avoid DWORD in constant pool when we can sign extend
This commit is contained in:
parent
15c3f45e5f
commit
8c95a221b0
3 changed files with 72 additions and 72 deletions
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue