aboutsummaryrefslogtreecommitdiff
path: root/src/liblink
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-10-27 15:25:40 -0400
committerAustin Clements <austin@google.com>2014-10-27 15:25:40 -0400
commit32c75a2d3d121f31ace325d48d9fcbdde58cc042 (patch)
tree69e73a35319a603f45823b16c922bb2a4cc5848e /src/liblink
parent93341e8664e66b217a6911a08e1c1dac9dcf004e (diff)
downloadgo-32c75a2d3d121f31ace325d48d9fcbdde58cc042.tar.xz
[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
Diffstat (limited to 'src/liblink')
-rw-r--r--src/liblink/asm9.c69
-rw-r--r--src/liblink/obj9.c159
2 files changed, 102 insertions, 126 deletions
diff --git a/src/liblink/asm9.c b/src/liblink/asm9.c
index 47d515e054..c5a78e53ca 100644
--- a/src/liblink/asm9.c
+++ b/src/liblink/asm9.c
@@ -232,6 +232,7 @@ static Optab optab[] = {
{ AMOVBZ, 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 },
+ { AMOVW, 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 },
{ AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO },
@@ -349,8 +350,12 @@ static Optab optab[] = {
{ AREM, C_REG, C_NONE, 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_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 },
{ AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0 },
@@ -433,12 +438,11 @@ static Optab optab[] = {
{ AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 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 },
+ { 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
{ 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 },
};
@@ -472,7 +476,7 @@ static struct
Optab* stop;
} oprange[ALAST];
-static char xcmp[C_NCLASS][C_NCLASS];
+static uchar xcmp[C_NCLASS][C_NCLASS];
void
@@ -747,7 +751,7 @@ static Optab*
oplook(Link *ctxt, Prog *p)
{
int a1, a2, a3, a4, r;
- char *c1, *c3, *c4;
+ uchar *c1, *c3, *c4;
Optab *o, *e;
a1 = p->optab;
@@ -931,6 +935,8 @@ buildop(Link *ctxt)
oprange[AREMCC] = oprange[r];
oprange[AREMV] = oprange[r];
oprange[AREMVCC] = oprange[r];
+ break;
+ case AREMU:
oprange[AREMU] = oprange[r];
oprange[AREMUCC] = oprange[r];
oprange[AREMUV] = oprange[r];
@@ -940,6 +946,8 @@ buildop(Link *ctxt)
oprange[AREMDCC] = oprange[r];
oprange[AREMDV] = oprange[r];
oprange[AREMDVCC] = oprange[r];
+ break;
+ case AREMDU:
oprange[AREMDU] = oprange[r];
oprange[AREMDUCC] = oprange[r];
oprange[AREMDUV] = oprange[r];
@@ -2005,6 +2013,11 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
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;
case 51: /* remd[u] r1[,r2],r3 */
@@ -2264,54 +2277,6 @@ asmout(Link *ctxt, Prog *p, Optab *o, int32 *out)
out[3] = o4;
out[4] = o5;
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
diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c
index 3906181a31..fa8af5f839 100644
--- a/src/liblink/obj9.c
+++ b/src/liblink/obj9.c
@@ -199,7 +199,7 @@ parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
static void
addstacksplit(Link *ctxt, LSym *cursym)
{
- Prog *p, *q, *q1;
+ Prog *p, *q, *p1, *p2, *q1;
int o, mov, aoffset;
vlong textstksiz, textarg;
int32 autoffset, autosize;
@@ -472,32 +472,92 @@ addstacksplit(Link *ctxt, LSym *cursym)
q->spadj = -aoffset;
if(cursym->text->reg & WRAPPER) {
- // g->panicwrap += autosize;
- // MOVWZ panicwrap_offset(g), R3
- // ADD $autosize, R3
- // MOVWZ R3, panicwrap_offset(g)
- p = appendp(ctxt, q);
- p->as = AMOVWZ;
+ // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+ //
+ // MOVD g_panic(g), R3
+ // CMP R0, R3
+ // BEQ end
+ // 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.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.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->as = AADD;
p->from.type = D_CONST;
- p->from.offset = autosize;
+ p->from.offset = autosize+8;
+ p->reg = REGSP;
p->to.type = D_REG;
- p->to.reg = 3;
+ p->to.reg = 5;
p = appendp(ctxt, p);
- p->as = AMOVWZ;
+ p->as = ACMP;
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.reg = REGG;
- p->to.offset = 2*ctxt->arch->ptrsize;
+ p->to.reg = 3;
+ p->to.offset = 0; // Panic.argp
+
+ p = appendp(ctxt, p);
+ p->as = ANOP;
+ p1->pcond = p;
+ p2->pcond = p;
}
break;
@@ -512,36 +572,6 @@ addstacksplit(Link *ctxt, LSym *cursym)
p->to.type = D_BRANCH;
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(!autosize) {
p->as = ABR;
@@ -673,18 +703,19 @@ addstacksplit(Link *ctxt, LSym *cursym)
static Prog*
stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
{
- int32 arg;
- Prog *q, *q1;
+ Prog *q1;
// MOVD g_stackguard(g), R3
p = appendp(ctxt, p);
p->as = AMOVD;
p->from.type = D_OREG;
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.reg = 3;
- q = nil;
if(framesize <= StackSmall) {
// small stack: SP < stackguard
// CMP stackguard, SP
@@ -735,7 +766,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->to.type = D_CONST;
p->to.offset = StackPreempt;
- q = p = appendp(ctxt, p);
+ p = appendp(ctxt, p);
p->as = ABEQ;
p->to.type = D_BRANCH;
@@ -774,31 +805,6 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p->as = ABLT;
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
p = appendp(ctxt, p);
p->as = AMOVD;
@@ -811,7 +817,10 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
p = appendp(ctxt, p);
p->as = ABL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[noctxt];
+ if(ctxt->cursym->cfunc)
+ p->to.sym = linklookup(ctxt, "runtime.morestackc", 0);
+ else
+ p->to.sym = ctxt->symmorestack[noctxt];
// BR start
p = appendp(ctxt, p);
@@ -1010,6 +1019,7 @@ LinkArch linkpower64 = {
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
+ .D_OREG = D_OREG,
.ACALL = ABL,
.ADATA = ADATA,
@@ -1056,6 +1066,7 @@ LinkArch linkpower64le = {
.D_PARAM = D_PARAM,
.D_SCONST = D_SCONST,
.D_STATIC = D_STATIC,
+ .D_OREG = D_OREG,
.ACALL = ABL,
.ADATA = ADATA,