Commit 32c75a2d authored by Austin Clements's avatar Austin Clements

[dev.power64] liblink: power64 fixes and ports of changes

Ports of platform-specific changes that happened on default
after dev.power64 forked (fixes for c2go, wrapper math fixes,
moved stackguard field, stackguard1 support, precise stacks).
Bug fixes (missing AMOVW in instruction table, correct
unsigned 32-bit remainder).

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/164920044
parent 93341e86
...@@ -232,6 +232,7 @@ static Optab optab[] = { ...@@ -232,6 +232,7 @@ static Optab optab[] = {
{ AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, { AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP },
{ AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, { AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP },
{ AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, { AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
{ AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
{ AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, { AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
{ AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, { AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
{ AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, { AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
...@@ -349,8 +350,12 @@ static Optab optab[] = { ...@@ -349,8 +350,12 @@ static Optab optab[] = {
{ AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0 }, { AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0 },
{ AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0 }, { AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0 },
{ AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0 },
{ AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0 },
{ AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 }, { AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 },
{ AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0 }, { AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0 },
{ AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 },
{ AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0 },
{ AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0 }, { AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0 },
{ AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0 }, { AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0 },
...@@ -433,12 +438,11 @@ static Optab optab[] = { ...@@ -433,12 +438,11 @@ static Optab optab[] = {
{ AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0 }, { AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
{ APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0 }, { APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0 },
{ AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0 }, { AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0 },
{ ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
{ ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL { ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL
{ ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL { ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL
{ ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 },
{ AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 },
}; };
...@@ -472,7 +476,7 @@ static struct ...@@ -472,7 +476,7 @@ static struct
Optab* stop; Optab* stop;
} oprange[ALAST]; } oprange[ALAST];
static char xcmp[C_NCLASS][C_NCLASS]; static uchar xcmp[C_NCLASS][C_NCLASS];
void void
...@@ -747,7 +751,7 @@ static Optab* ...@@ -747,7 +751,7 @@ static Optab*
oplook(Link *ctxt, Prog *p) oplook(Link *ctxt, Prog *p)
{ {
int a1, a2, a3, a4, r; int a1, a2, a3, a4, r;
char *c1, *c3, *c4; uchar *c1, *c3, *c4;
Optab *o, *e; Optab *o, *e;
a1 = p->optab; a1 = p->optab;
...@@ -931,6 +935,8 @@ buildop(Link *ctxt) ...@@ -931,6 +935,8 @@ buildop(Link *ctxt)
oprange[AREMCC] = oprange[r]; oprange[AREMCC] = oprange[r];
oprange[AREMV] = oprange[r]; oprange[AREMV] = oprange[r];
oprange[AREMVCC] = oprange[r]; oprange[AREMVCC] = oprange[r];
break;
case AREMU:
oprange[AREMU] = oprange[r]; oprange[AREMU] = oprange[r];
oprange[AREMUCC] = oprange[r]; oprange[AREMUCC] = oprange[r];
oprange[AREMUV] = oprange[r]; oprange[AREMUV] = oprange[r];
...@@ -940,6 +946,8 @@ buildop(Link *ctxt) ...@@ -940,6 +946,8 @@ buildop(Link *ctxt)
oprange[AREMDCC] = oprange[r]; oprange[AREMDCC] = oprange[r];
oprange[AREMDV] = oprange[r]; oprange[AREMDV] = oprange[r];
oprange[AREMDVCC] = oprange[r]; oprange[AREMDVCC] = oprange[r];
break;
case AREMDU:
oprange[AREMDU] = oprange[r]; oprange[AREMDU] = oprange[r];
oprange[AREMDUCC] = oprange[r]; oprange[AREMDUCC] = oprange[r];
oprange[AREMDUV] = oprange[r]; oprange[AREMDUV] = oprange[r];
...@@ -2005,6 +2013,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) ...@@ -2005,6 +2013,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg); o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg); o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r); o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
if(p->as == AREMU) {
o4 = o3;
/* Clear top 32 bits */
o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5);
}
break; break;
case 51: /* remd[u] r1[,r2],r3 */ case 51: /* remd[u] r1[,r2],r3 */
...@@ -2264,54 +2277,6 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) ...@@ -2264,54 +2277,6 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
out[3] = o4; out[3] = o4;
out[4] = o5; out[4] = o5;
return; return;
#if NOTDEF
v = p->pc;
switch(o->size) {
default:
if(debug['a'])
Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
break;
case 4:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
lput(o1);
break;
case 8:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
lput(o1);
lput(o2);
break;
case 12:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
lput(o1);
lput(o2);
lput(o3);
break;
case 16:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
v, o1, o2, o3, o4, p);
lput(o1);
lput(o2);
lput(o3);
lput(o4);
break;
case 20:
if(debug['a'])
Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
v, o1, o2, o3, o4, o5, p);
lput(o1);
lput(o2);
lput(o3);
lput(o4);
lput(o5);
break;
}
return 0;
#endif
} }
static vlong static vlong
......
...@@ -199,7 +199,7 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg) ...@@ -199,7 +199,7 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
static void static void
addstacksplit(Link *ctxt, LSym *cursym) addstacksplit(Link *ctxt, LSym *cursym)
{ {
Prog *p, *q, *q1; Prog *p, *q, *p1, *p2, *q1;
int o, mov, aoffset; int o, mov, aoffset;
vlong textstksiz, textarg; vlong textstksiz, textarg;
int32 autoffset, autosize; int32 autoffset, autosize;
...@@ -472,32 +472,92 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -472,32 +472,92 @@ addstacksplit(Link *ctxt, LSym *cursym)
q->spadj = -aoffset; q->spadj = -aoffset;
if(cursym->text->reg & WRAPPER) { if(cursym->text->reg & WRAPPER) {
// g->panicwrap += autosize; // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
// MOVWZ panicwrap_offset(g), R3 //
// ADD $autosize, R3 // MOVD g_panic(g), R3
// MOVWZ R3, panicwrap_offset(g) // CMP R0, R3
p = appendp(ctxt, q); // BEQ end
p->as = AMOVWZ; // MOVD panic_argp(R3), R4
// ADD $(autosize+8), R1, R5
// CMP R4, R5
// BNE end
// ADD $8, R1, R6
// MOVD R6, panic_argp(R3)
// end:
// NOP
//
// The NOP is needed to give the jumps somewhere to land.
// It is a liblink NOP, not a Power64 NOP: it encodes to 0 instruction bytes.
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_OREG; p->from.type = D_OREG;
p->from.reg = REGG; p->from.reg = REGG;
p->from.offset = 2*ctxt->arch->ptrsize; p->from.offset = 4*ctxt->arch->ptrsize; // G.panic
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 3; p->to.reg = 3;
p = appendp(ctxt, p);
p->as = ACMP;
p->from.type = D_REG;
p->from.reg = 0;
p->to.type = D_REG;
p->to.reg = 3;
p = appendp(ctxt, p);
p->as = ABEQ;
p->to.type = D_BRANCH;
p1 = p;
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_OREG;
p->from.reg = 3;
p->from.offset = 0; // Panic.argp
p->to.type = D_REG;
p->to.reg = 4;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AADD; p->as = AADD;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = autosize; p->from.offset = autosize+8;
p->reg = REGSP;
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 3; p->to.reg = 5;
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVWZ; p->as = ACMP;
p->from.type = D_REG; p->from.type = D_REG;
p->from.reg = 3; p->from.reg = 4;
p->to.type = D_REG;
p->to.reg = 5;
p = appendp(ctxt, p);
p->as = ABNE;
p->to.type = D_BRANCH;
p2 = p;
p = appendp(ctxt, p);
p->as = AADD;
p->from.type = D_CONST;
p->from.offset = 8;
p->reg = REGSP;
p->to.type = D_REG;
p->to.reg = 6;
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_REG;
p->from.reg = 6;
p->to.type = D_OREG; p->to.type = D_OREG;
p->to.reg = REGG; p->to.reg = 3;
p->to.offset = 2*ctxt->arch->ptrsize; p->to.offset = 0; // Panic.argp
p = appendp(ctxt, p);
p->as = ANOP;
p1->pcond = p;
p2->pcond = p;
} }
break; break;
...@@ -512,36 +572,6 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -512,36 +572,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
break; break;
} }
if(cursym->text->reg & WRAPPER) {
// g->panicwrap -= autosize;
// MOVWZ panicwrap_offset(g), R3
// ADD $-autosize, R3
// MOVWZ R3, panicwrap_offset(g)
p->as = AMOVWZ;
p->from.type = D_OREG;
p->from.reg = REGG;
p->from.offset = 2*ctxt->arch->ptrsize;
p->to.type = D_REG;
p->to.reg = 3;
p = appendp(ctxt, p);
p->as = AADD;
p->from.type = D_CONST;
p->from.offset = -autosize;
p->to.type = D_REG;
p->to.reg = 3;
p = appendp(ctxt, p);
p->as = AMOVWZ;
p->from.type = D_REG;
p->from.reg = 3;
p->to.type = D_OREG;
p->to.reg = REGG;
p->to.offset = 2*ctxt->arch->ptrsize;
p = appendp(ctxt, p);
p->as = ARETURN;
}
if(cursym->text->mark & LEAF) { if(cursym->text->mark & LEAF) {
if(!autosize) { if(!autosize) {
p->as = ABR; p->as = ABR;
...@@ -673,18 +703,19 @@ addstacksplit(Link *ctxt, LSym *cursym) ...@@ -673,18 +703,19 @@ addstacksplit(Link *ctxt, LSym *cursym)
static Prog* static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
{ {
int32 arg; Prog *q1;
Prog *q, *q1;
// MOVD g_stackguard(g), R3 // MOVD g_stackguard(g), R3
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVD; p->as = AMOVD;
p->from.type = D_OREG; p->from.type = D_OREG;
p->from.reg = REGG; p->from.reg = REGG;
p->from.offset = 2*ctxt->arch->ptrsize; // G.stackguard0
if(ctxt->cursym->cfunc)
p->from.offset = 3*ctxt->arch->ptrsize; // G.stackguard1
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 3; p->to.reg = 3;
q = nil;
if(framesize <= StackSmall) { if(framesize <= StackSmall) {
// small stack: SP < stackguard // small stack: SP < stackguard
// CMP stackguard, SP // CMP stackguard, SP
...@@ -735,7 +766,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) ...@@ -735,7 +766,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->to.type = D_CONST; p->to.type = D_CONST;
p->to.offset = StackPreempt; p->to.offset = StackPreempt;
q = p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ABEQ; p->as = ABEQ;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
...@@ -774,31 +805,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) ...@@ -774,31 +805,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->as = ABLT; p->as = ABLT;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
// MOVD $framesize, R3
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_CONST;
p->from.offset = framesize;
p->to.type = D_REG;
p->to.reg = 3;
if(q)
q->pcond = p;
// MOVD $args, R4
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_CONST;
arg = (ctxt->cursym->text->to.offset >> 32) & 0xffffffffull;
if(arg == 1) // special marker for known 0
arg = 0;
else if(arg == ArgsSizeUnknown)
ctxt->diag("%s: arg size unknown, but split stack", ctxt->cursym->name);
if(arg&7)
ctxt->diag("misaligned argument size in stack split: %d", arg);
p->from.offset = arg;
p->to.type = D_REG;
p->to.reg = 4;
// MOVD LR, R5 // MOVD LR, R5
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = AMOVD; p->as = AMOVD;
...@@ -811,6 +817,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt) ...@@ -811,6 +817,9 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p = appendp(ctxt, p); p = appendp(ctxt, p);
p->as = ABL; p->as = ABL;
p->to.type = D_BRANCH; p->to.type = D_BRANCH;
if(ctxt->cursym->cfunc)
p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
else
p->to.sym = ctxt->symmorestack[noctxt]; p->to.sym = ctxt->symmorestack[noctxt];
// BR start // BR start
...@@ -1010,6 +1019,7 @@ LinkArch linkpower64 = { ...@@ -1010,6 +1019,7 @@ LinkArch linkpower64 = {
.D_PARAM = D_PARAM, .D_PARAM = D_PARAM,
.D_SCONST = D_SCONST, .D_SCONST = D_SCONST,
.D_STATIC = D_STATIC, .D_STATIC = D_STATIC,
.D_OREG = D_OREG,
.ACALL = ABL, .ACALL = ABL,
.ADATA = ADATA, .ADATA = ADATA,
...@@ -1056,6 +1066,7 @@ LinkArch linkpower64le = { ...@@ -1056,6 +1066,7 @@ LinkArch linkpower64le = {
.D_PARAM = D_PARAM, .D_PARAM = D_PARAM,
.D_SCONST = D_SCONST, .D_SCONST = D_SCONST,
.D_STATIC = D_STATIC, .D_STATIC = D_STATIC,
.D_OREG = D_OREG,
.ACALL = ABL, .ACALL = ABL,
.ADATA = ADATA, .ADATA = ADATA,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment