summaryrefslogtreecommitdiff
path: root/src/cmd/8l/span.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-05-14 18:39:35 +0200
committerMichael Stapelberg <michael@stapelberg.de>2013-05-14 18:39:35 +0200
commitefcc50dfdc94c82ee0292bf71992ecb7c0123061 (patch)
tree17dca99d1dc7fc4e9fe49c2cf6a99d337d4c039f /src/cmd/8l/span.c
parent04b08da9af0c450d645ab7389d1467308cfc2db8 (diff)
downloadgolang-efcc50dfdc94c82ee0292bf71992ecb7c0123061.tar.gz
Imported Upstream version 1.1upstream/1.1
Diffstat (limited to 'src/cmd/8l/span.c')
-rw-r--r--src/cmd/8l/span.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index b828d8645..980186b16 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -32,6 +32,7 @@
#include "l.h"
#include "../ld/lib.h"
+#include "../ld/elf.h"
static int32 vaddr(Adr*, Reloc*);
@@ -559,6 +560,14 @@ vaddr(Adr *a, Reloc *r)
return v;
}
+static int
+istls(Adr *a)
+{
+ if(HEADTYPE == Hlinux)
+ return a->index == D_GS;
+ return a->type == D_INDIR+D_GS;
+}
+
void
asmand(Adr *a, int r)
{
@@ -569,7 +578,7 @@ asmand(Adr *a, int r)
v = a->offset;
t = a->type;
rel.siz = 0;
- if(a->index != D_NONE) {
+ if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) {
if(t < D_INDIR || t >= 2*D_INDIR) {
switch(t) {
default:
@@ -658,7 +667,7 @@ asmand(Adr *a, int r)
*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
return;
}
- if(v >= -128 && v < 128 && rel.siz == 0) {
+ if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) {
andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
andptr[1] = v;
andptr += 2;
@@ -680,7 +689,29 @@ putrelv:
r = addrel(cursym);
*r = rel;
r->off = curp->pc + andptr - and;
+ } else if(iself && linkmode == LinkExternal && istls(a) && HEADTYPE != Hopenbsd) {
+ Reloc *r;
+ Sym *s;
+
+ r = addrel(cursym);
+ r->off = curp->pc + andptr - and;
+ r->add = 0;
+ r->xadd = 0;
+ r->siz = 4;
+ r->type = D_TLS;
+ if(a->offset == tlsoffset+0)
+ s = lookup("runtime.g", 0);
+ else
+ s = lookup("runtime.m", 0);
+ s->type = STLSBSS;
+ s->reachable = 1;
+ s->hide = 1;
+ s->size = PtrSize;
+ r->sym = s;
+ r->xsym = s;
+ v = 0;
}
+
put4(v);
return;
@@ -1003,11 +1034,23 @@ found:
*andptr++ = op;
break;
+ case Zlitm_r:
+ for(; op = o->op[z]; z++)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r:
*andptr++ = op;
asmand(&p->from, reg[p->to.type]);
break;
+ case Zm2_r:
+ *andptr++ = op;
+ *andptr++ = o->op[z+1];
+ asmand(&p->from, reg[p->to.type]);
+ break;
+
case Zm_r_xm:
mediaop(o, op, t[3], z);
asmand(&p->from, reg[p->to.type]);
@@ -1019,6 +1062,13 @@ found:
*andptr++ = p->to.offset;
break;
+ case Zibm_r:
+ while ((op = o->op[z++]) != 0)
+ *andptr++ = op;
+ asmand(&p->from, reg[p->to.type]);
+ *andptr++ = p->to.offset;
+ break;
+
case Zaut_r:
*andptr++ = 0x8d; /* leal */
if(p->from.type != D_ADDR)