aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-10-18 11:09:59 -0400
committerRuss Cox <rsc@golang.org>2010-10-18 11:09:59 -0400
commit3d0a85785a7680663fa40d55e8c92c008dffcbfc (patch)
tree75fac6f6d6250a3535ca15ee99699cdb4871bfc5
parenta647f59c1f80dd575c6e4107618681aea65edbd2 (diff)
downloadgo-3d0a85785a7680663fa40d55e8c92c008dffcbfc.tar.gz
go-3d0a85785a7680663fa40d55e8c92c008dffcbfc.zip
5l: data-relocatable code layout
R=ken2 CC=golang-dev https://golang.org/cl/2479043
-rw-r--r--src/cmd/5l/asm.c46
-rw-r--r--src/cmd/5l/l.h2
-rw-r--r--src/cmd/5l/obj.c2
-rw-r--r--src/cmd/5l/span.c52
4 files changed, 63 insertions, 39 deletions
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 4d9264c914..0b38e0b29b 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -291,13 +291,11 @@ phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
void
asmb(void)
{
- Prog *p;
int32 t;
int a, dynsym;
uint32 va, fo, w, symo, startva;
uint32 symdatva = SYMDATVA;
int strtabsize;
- Optab *o;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
@@ -312,28 +310,8 @@ asmb(void)
OFFSET = HEADR;
seek(cout, OFFSET, 0);
pc = INITTEXT;
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- for(p = cursym->text; p != P; p = p->link) {
- setarch(p);
- if(p->as == ATEXT)
- autosize = p->to.offset + 4;
- if(p->pc != pc) {
- diag("phase error %ux sb %ux",
- p->pc, pc);
- if(!debug['a'])
- prasm(curp);
- pc = p->pc;
- }
- curp = p;
- o = oplook(p); /* could probably avoid this call */
- if(thumb)
- thumbasmout(p, o);
- else
- asmout(p, o);
- pc += o->size;
- }
- }
- cflush();
+ codeblk(pc, segtext.sect->len);
+ pc += segtext.sect->len;
if(seek(cout, 0, 1) != pc - segtext.vaddr + segtext.fileoff)
diag("text phase error");
@@ -846,10 +824,11 @@ asmthumbmap(void)
}
void
-asmout(Prog *p, Optab *o)
+asmout(Prog *p, Optab *o, int32 *out)
{
int32 o1, o2, o3, o4, o5, o6, v;
int r, rf, rt, rt2;
+ Reloc *rel;
PP = p;
o1 = 0;
@@ -991,6 +970,15 @@ if(debug['G']) print("%ux: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym-
case 11: /* word */
aclass(&p->to);
o1 = instoffset;
+ if(p->to.sym != S) {
+ rel = addrel(cursym);
+ rel->off = pc - cursym->value;
+ rel->siz = 4;
+ rel->type = D_ADDR;
+ rel->sym = p->to.sym;
+ rel->add = p->to.offset;
+ o1 = 0;
+ }
break;
case 12: /* movw $lcon, reg */
@@ -1588,6 +1576,14 @@ if(debug['G']) print("%ux: %s: arm %d %d %d %d\n", (uint32)(p->pc), p->from.sym-
o1 |= (p->scond & C_SCOND) << 28;
break;
}
+
+ out[0] = o1;
+ out[1] = o2;
+ out[2] = o3;
+ out[3] = o4;
+ out[4] = o5;
+ out[5] = o6;
+ return;
v = p->pc;
switch(o->size) {
diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h
index 1e720f3bea..4f7ec52235 100644
--- a/src/cmd/5l/l.h
+++ b/src/cmd/5l/l.h
@@ -379,7 +379,7 @@ void addhist(int32, int);
Prog* appendp(Prog*);
void asmb(void);
void asmthumbmap(void);
-void asmout(Prog*, Optab*);
+void asmout(Prog*, Optab*, int32*);
void thumbasmout(Prog*, Optab*);
void asmsym(void);
int32 atolwhex(char*);
diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c
index 6392d93ca8..5a508b4f4a 100644
--- a/src/cmd/5l/obj.c
+++ b/src/cmd/5l/obj.c
@@ -70,7 +70,7 @@ main(int argc, char *argv[])
{
int c, i;
-debug['s'] = 1;
+//debug['s'] = 1; // qemu cannot handle symdat load
Binit(&bso, 1, OWRITE);
cout = -1;
listinit();
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c
index 3a1c35b62d..048a4768b6 100644
--- a/src/cmd/5l/span.c
+++ b/src/cmd/5l/span.c
@@ -166,11 +166,12 @@ span(void)
{
Prog *p, *op;
Optab *o;
- int m, bflag;
- int32 c, otxt;
+ int m, bflag, i, v;
+ int32 c, otxt, out[6];
int lastthumb = -1;
Section *rosect, *sect;
Sym *sym;
+ uchar *bp;
if(debug['v'])
Bprint(&bso, "%5.2f span\n", cputime());
@@ -187,11 +188,8 @@ span(void)
p = cursym->text;
setarch(p);
p->pc = c;
+ cursym->value = c;
- if(blitrl && lastthumb != -1 && lastthumb != thumb){ // flush literal pool
- if(flushpool(op, 0, 1))
- c = p->pc = scan(op, p, c);
- }
lastthumb = thumb;
autosize = p->to.offset + 4;
if(p->from.sym != S)
@@ -216,8 +214,6 @@ span(void)
c = p->pc = scan(op, p, c);
}
if(m == 0) {
- if(p->as == ATEXT) {
- }
diag("zero-width instruction\n%P", p);
continue;
}
@@ -237,12 +233,13 @@ span(void)
flushpool(p, 0, 0);
c += m;
}
- if(blitrl && cursym->next == nil){
+ if(blitrl){
if(thumb && isbranch(op))
pool.extra += brextra(op);
if(checkpool(op, 0))
c = scan(op, P, c);
}
+ cursym->size = c - cursym->value;
}
/*
@@ -257,6 +254,7 @@ span(void)
bflag = 0;
c = INITTEXT;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
+ cursym->value = c;
for(p = cursym->text; p != P; p = p->link) {
setarch(p);
p->pc = c;
@@ -299,6 +297,7 @@ span(void)
}
c += m;
}
+ cursym->size = c - cursym->value;
}
}
@@ -318,6 +317,7 @@ span(void)
oop = op = nil;
again = 0;
for(cursym = textp; cursym != nil; cursym = cursym->next) {
+ cursym->value = c;
for(p = cursym->text; p != P; oop = op, op = p, p = p->link) {
setarch(p);
if(p->pc != c)
@@ -361,6 +361,7 @@ span(void)
}
c += m;
}
+ cursym->size = c - cursym->value;
}
if(c != lastc || again){
lastc = c;
@@ -368,12 +369,39 @@ span(void)
}
}
c = rnd(c, 8);
-
xdefine("etext", STEXT, c);
- for(cursym = textp; cursym != nil; cursym = cursym->next)
- cursym->value = cursym->text->pc;
textsize = c - INITTEXT;
+ /*
+ * lay out the code. all the pc-relative code references,
+ * even cross-function, are resolved now;
+ * only data references need to be relocated.
+ * with more work we could leave cross-function
+ * code references to be relocated too, and then
+ * perhaps we'd be able to parallelize the span loop above.
+ */
+ for(cursym = textp; cursym != nil; cursym = cursym->next) {
+ p = cursym->text;
+ setarch(p);
+ autosize = p->to.offset + 4;
+ symgrow(cursym, cursym->size);
+
+ bp = cursym->p;
+ for(p = p->link; p != P; p = p->link) {
+ pc = p->pc;
+ curp = p;
+ o = oplook(p);
+ asmout(p, o, out);
+ for(i=0; i<o->size/4; i++) {
+ v = out[i];
+ *bp++ = v;
+ *bp++ = v>>8;
+ *bp++ = v>>16;
+ *bp++ = v>>24;
+ }
+ }
+ }
+
rosect = segtext.sect->next;
if(rosect) {
if(INITRND)