summaryrefslogtreecommitdiff
path: root/src/liblink
diff options
context:
space:
mode:
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 47d515e05..c5a78e53c 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 3906181a3..fa8af5f83 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,