summaryrefslogtreecommitdiff
path: root/src/liblink/obj6.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-02-27 20:37:00 -0500
committerRuss Cox <rsc@golang.org>2014-02-27 20:37:00 -0500
commit7d945de10bfc48118799dbfc8dabf50954074b38 (patch)
tree40abe92a9fb62456630a51d27c32ea726af4be35 /src/liblink/obj6.c
parente88dfc14e2bcc8c151af8d6c3264e2704698281e (diff)
downloadgo-7d945de10bfc48118799dbfc8dabf50954074b38.tar.gz
all: final merge of NaCl tree
This CL replays the following one CL from the rsc-go13nacl repo. This is the last replay CL: after this CL the main repo will have everything the rsc-go13nacl repo did. Changes made to the main repo after the rsc-go13nacl repo branched off probably mean that NaCl doesn't actually work after this CL, but all the code is now moved over and just needs to be redebugged. --- cmd/6l, cmd/8l, cmd/ld: support for Native Client See golang.org/s/go13nacl for design overview. This CL is publicly visible but not CC'ed to golang-dev, to avoid distracting from the preparation of the Go 1.2 release. This CL and the others will be checked into my rsc-go13nacl clone repo for now, and I will send CLs against the main repo early in the Go 1.3 development. R?khr https://codereview.appspot.com/15750044 --- LGTM=bradfitz, dave, iant R=dave, bradfitz, iant CC=golang-codereviews https://codereview.appspot.com/69040044
Diffstat (limited to 'src/liblink/obj6.c')
-rw-r--r--src/liblink/obj6.c168
1 files changed, 143 insertions, 25 deletions
diff --git a/src/liblink/obj6.c b/src/liblink/obj6.c
index e8967f3ec..9b99a5995 100644
--- a/src/liblink/obj6.c
+++ b/src/liblink/obj6.c
@@ -97,6 +97,8 @@ settextflag(Prog *p, int f)
p->from.scale = f;
}
+static void nacladdr(Link*, Prog*, Addr*);
+
static void
progedit(Link *ctxt, Prog *p)
{
@@ -104,6 +106,11 @@ progedit(Link *ctxt, Prog *p)
LSym *s;
Prog *q;
+ if(ctxt->headtype == Hnacl) {
+ nacladdr(ctxt, p, &p->from);
+ nacladdr(ctxt, p, &p->to);
+ }
+
if(p->from.type == D_INDIR+D_GS || p->from.index == D_GS)
p->from.offset += ctxt->tlsoffset;
if(p->to.type == D_INDIR+D_GS || p->to.index == D_GS)
@@ -298,6 +305,39 @@ progedit(Link *ctxt, Prog *p)
}
}
+static void
+nacladdr(Link *ctxt, Prog *p, Addr *a)
+{
+ if(p->as == ALEAL || p->as == ALEAQ)
+ return;
+
+ if(a->type == D_BP || a->type == D_INDIR+D_BP) {
+ ctxt->diag("invalid address: %P", p);
+ return;
+ }
+ if(a->type == D_INDIR+D_GS)
+ a->type = D_INDIR+D_BP;
+ else if(a->type == D_GS)
+ a->type = D_BP;
+ if(D_INDIR <= a->type && a->type <= D_INDIR+D_INDIR) {
+ switch(a->type) {
+ case D_INDIR+D_BP:
+ case D_INDIR+D_SP:
+ case D_INDIR+D_R15:
+ // all ok
+ break;
+ default:
+ if(a->index != D_NONE)
+ ctxt->diag("invalid address %P", p);
+ a->index = a->type - D_INDIR;
+ if(a->index != D_NONE)
+ a->scale = 1;
+ a->type = D_INDIR+D_R15;
+ break;
+ }
+ }
+}
+
static char*
morename[] =
{
@@ -316,6 +356,7 @@ morename[] =
static Prog* load_g_cx(Link*, Prog*);
static Prog* stacksplit(Link*, Prog*, int32, int32, Prog**);
+static void indir_cx(Link*, Addr*);
static void
parsetextconst(vlong arg, vlong *textstksiz, vlong *textarg)
@@ -369,7 +410,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
noleaf:;
}
- if((p->from.scale & NOSPLIT) && autoffset >= StackSmall)
+ if((p->from.scale & NOSPLIT) && autoffset >= StackLimit)
ctxt->diag("nosplit func likely to overflow stack");
q = nil;
@@ -381,6 +422,8 @@ addstacksplit(Link *ctxt, LSym *cursym)
p = stacksplit(ctxt, p, autoffset, textarg, &q); // emit split check
if(autoffset) {
+ if(autoffset%ctxt->arch->regsize != 0)
+ ctxt->diag("unaligned stack size %d", autoffset);
p = appendp(ctxt, p);
p->as = AADJSP;
p->from.type = D_CONST;
@@ -402,12 +445,12 @@ addstacksplit(Link *ctxt, LSym *cursym)
deltasp = autoffset;
if(cursym->text->from.scale & WRAPPER) {
- // g->panicwrap += autoffset + ctxt->arch->ptrsize;
+ // g->panicwrap += autoffset + ctxt->arch->regsize;
p = appendp(ctxt, p);
p->as = AADDL;
p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->ptrsize;
- p->to.type = D_INDIR+D_CX;
+ p->from.offset = autoffset + ctxt->arch->regsize;
+ indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize;
}
@@ -417,7 +460,7 @@ addstacksplit(Link *ctxt, LSym *cursym)
// function is marked as nosplit.
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_INDIR+D_CX;
+ indir_cx(ctxt, &p->from);
p->from.offset = 0;
p->to.type = D_BX;
@@ -531,11 +574,11 @@ addstacksplit(Link *ctxt, LSym *cursym)
if(cursym->text->from.scale & WRAPPER) {
p = load_g_cx(ctxt, p);
p = appendp(ctxt, p);
- // g->panicwrap -= autoffset + ctxt->arch->ptrsize;
+ // g->panicwrap -= autoffset + ctxt->arch->regsize;
p->as = ASUBL;
p->from.type = D_CONST;
- p->from.offset = autoffset + ctxt->arch->ptrsize;
- p->to.type = D_INDIR+D_CX;
+ p->from.offset = autoffset + ctxt->arch->regsize;
+ indir_cx(ctxt, &p->to);
p->to.offset = 2*ctxt->arch->ptrsize;
p = appendp(ctxt, p);
p->as = ARET;
@@ -559,6 +602,19 @@ addstacksplit(Link *ctxt, LSym *cursym)
}
}
+static void
+indir_cx(Link *ctxt, Addr *a)
+{
+ if(ctxt->headtype == Hnacl) {
+ a->type = D_INDIR + D_R15;
+ a->index = D_CX;
+ a->scale = 1;
+ return;
+ }
+
+ a->type = D_INDIR+D_CX;
+}
+
// Append code to p to load g into cx.
// Overwrites p with the first instruction (no first appendp).
// Overwriting p is unusual but it lets use this in both the
@@ -582,12 +638,15 @@ load_g_cx(Link *ctxt, Prog *p)
|| ctxt->headtype == Hsolaris)
// ELF uses FS
p->from.type = D_INDIR+D_FS;
- else
+ else if(ctxt->headtype == Hnacl) {
+ p->as = AMOVL;
+ p->from.type = D_INDIR+D_BP;
+ } else
p->from.type = D_INDIR+D_GS;
if(ctxt->flag_shared) {
// Add TLS offset stored in CX
p->from.index = p->from.type - D_INDIR;
- p->from.type = D_INDIR + D_CX;
+ indir_cx(ctxt, &p->from);
}
p->from.offset = ctxt->tlsoffset+0;
p->to.type = D_CX;
@@ -601,7 +660,7 @@ load_g_cx(Link *ctxt, Prog *p)
p = appendp(ctxt, p);
p->as = AMOVQ;
- p->from.type = D_INDIR+D_CX;
+ indir_cx(ctxt, &p->from);
p->from.offset = 0;
p->to.type = D_CX;
}
@@ -619,6 +678,19 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
{
Prog *q, *q1;
uint32 moreconst1, moreconst2, i;
+ int cmp, lea, mov, sub;
+
+ cmp = ACMPQ;
+ lea = ALEAQ;
+ mov = AMOVQ;
+ sub = ASUBQ;
+
+ if(ctxt->headtype == Hnacl) {
+ cmp = ACMPL;
+ lea = ALEAL;
+ mov = AMOVL;
+ sub = ASUBL;
+ }
if(ctxt->debugstack) {
// 6l -K means check not only for stack
@@ -628,8 +700,8 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// catches out-of-sync stack guard info
p = appendp(ctxt, p);
- p->as = ACMPQ;
- p->from.type = D_INDIR+D_CX;
+ p->as = cmp;
+ indir_cx(ctxt, &p->from);
p->from.offset = 8;
p->to.type = D_SP;
@@ -654,23 +726,23 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// small stack: SP <= stackguard
// CMPQ SP, stackguard
p = appendp(ctxt, p);
- p->as = ACMPQ;
+ p->as = cmp;
p->from.type = D_SP;
- p->to.type = D_INDIR+D_CX;
+ indir_cx(ctxt, &p->to);
} else if(framesize <= StackBig) {
// large stack: SP-framesize <= stackguard-StackSmall
// LEAQ -xxx(SP), AX
// CMPQ AX, stackguard
p = appendp(ctxt, p);
- p->as = ALEAQ;
+ p->as = lea;
p->from.type = D_INDIR+D_SP;
p->from.offset = -(framesize-StackSmall);
p->to.type = D_AX;
p = appendp(ctxt, p);
- p->as = ACMPQ;
+ p->as = cmp;
p->from.type = D_AX;
- p->to.type = D_INDIR+D_CX;
+ indir_cx(ctxt, &p->to);
} else {
// Such a large stack we need to protect against wraparound.
// If SP is close to zero:
@@ -688,13 +760,13 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
// CMPQ AX, $(framesize+(StackGuard-StackSmall))
p = appendp(ctxt, p);
- p->as = AMOVQ;
- p->from.type = D_INDIR+D_CX;
+ p->as = mov;
+ indir_cx(ctxt, &p->from);
p->from.offset = 0;
p->to.type = D_SI;
p = appendp(ctxt, p);
- p->as = ACMPQ;
+ p->as = cmp;
p->from.type = D_SI;
p->to.type = D_CONST;
p->to.offset = StackPreempt;
@@ -705,18 +777,18 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
q1 = p;
p = appendp(ctxt, p);
- p->as = ALEAQ;
+ p->as = lea;
p->from.type = D_INDIR+D_SP;
p->from.offset = StackGuard;
p->to.type = D_AX;
p = appendp(ctxt, p);
- p->as = ASUBQ;
+ p->as = sub;
p->from.type = D_SI;
p->to.type = D_AX;
p = appendp(ctxt, p);
- p->as = ACMPQ;
+ p->as = cmp;
p->from.type = D_AX;
p->to.type = D_CONST;
p->to.offset = framesize+(StackGuard-StackSmall);
@@ -780,7 +852,7 @@ stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
p->to.type = D_BRANCH;
p->to.sym = ctxt->symmorestack[2];
} else {
- p->as = AMOVQ;
+ p->as = mov;
p->from.type = D_CONST;
p->from.offset = (uint64)moreconst2 << 32;
p->from.offset |= moreconst1;
@@ -1035,6 +1107,52 @@ LinkArch linkamd64 = {
.minlc = 1,
.ptrsize = 8,
+ .regsize = 8,
+
+ .D_ADDR = D_ADDR,
+ .D_BRANCH = D_BRANCH,
+ .D_CONST = D_CONST,
+ .D_EXTERN = D_EXTERN,
+ .D_FCONST = D_FCONST,
+ .D_NONE = D_NONE,
+ .D_PCREL = D_PCREL,
+ .D_SCONST = D_SCONST,
+ .D_SIZE = D_SIZE,
+ .D_STATIC = D_STATIC,
+
+ .ACALL = ACALL,
+ .ADATA = ADATA,
+ .AEND = AEND,
+ .AFUNCDATA = AFUNCDATA,
+ .AGLOBL = AGLOBL,
+ .AJMP = AJMP,
+ .ANOP = ANOP,
+ .APCDATA = APCDATA,
+ .ARET = ARET,
+ .ATEXT = ATEXT,
+ .ATYPE = ATYPE,
+ .AUSEFIELD = AUSEFIELD,
+};
+
+LinkArch linkamd64p32 = {
+ .name = "amd64p32",
+ .thechar = '6',
+
+ .addstacksplit = addstacksplit,
+ .assemble = span6,
+ .datasize = datasize,
+ .follow = follow,
+ .iscall = iscall,
+ .isdata = isdata,
+ .prg = prg,
+ .progedit = progedit,
+ .settextflag = settextflag,
+ .symtype = symtype,
+ .textflag = textflag,
+
+ .minlc = 1,
+ .ptrsize = 4,
+ .regsize = 8,
.D_ADDR = D_ADDR,
.D_BRANCH = D_BRANCH,