diff options
Diffstat (limited to 'src/cmd/8l')
-rw-r--r-- | src/cmd/8l/8.out.h | 10 | ||||
-rw-r--r-- | src/cmd/8l/asm.c | 185 | ||||
-rw-r--r-- | src/cmd/8l/l.h | 13 | ||||
-rw-r--r-- | src/cmd/8l/obj.c | 29 | ||||
-rw-r--r-- | src/cmd/8l/optab.c | 31 | ||||
-rw-r--r-- | src/cmd/8l/span.c | 19 |
6 files changed, 185 insertions, 102 deletions
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h index 386889956..93d44eb51 100644 --- a/src/cmd/8l/8.out.h +++ b/src/cmd/8l/8.out.h @@ -153,6 +153,7 @@ enum as AMOVB, AMOVL, AMOVW, + AMOVQ, AMOVBLSX, AMOVBLZX, AMOVBWSX, @@ -397,6 +398,7 @@ enum as ACMPXCHGW, ACMPXCHG8B, + ACPUID, ARDTSC, AXADDB, @@ -531,6 +533,7 @@ enum as AORPD, AORPS, APADDQ, + APAND, APMAXSW, APMAXUB, APMINSW, @@ -566,7 +569,12 @@ enum as AUNPCKLPS, AXORPD, AXORPS, - + + /* SSE 3+ */ + AAESENC, + APINSRD, + APSHUFB, + AUSEFIELD, ALOCALS, ATYPE, diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index a00174c36..bfeb13839 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -128,7 +128,7 @@ adddynrel(Sym *s, Reloc *r) // Handle relocations found in ELF object files. case 256 + R_386_PC32: - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name); if(targ->type == 0 || targ->type == SXREF) diag("unknown symbol %s in pcrel", targ->name); @@ -139,7 +139,7 @@ adddynrel(Sym *s, Reloc *r) case 256 + R_386_PLT32: r->type = D_PCREL; r->add += 4; - if(targ->dynimpname != nil && !targ->dynexport) { + if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add += targ->plt; @@ -147,7 +147,7 @@ adddynrel(Sym *s, Reloc *r) return; case 256 + R_386_GOT32: - if(targ->dynimpname == nil || targ->dynexport) { + if(targ->type != SDYNIMPORT) { // have symbol // turn MOVL of GOT entry into LEAL of symbol itself if(r->off < 2 || s->p[r->off-2] != 0x8b) { @@ -175,19 +175,19 @@ adddynrel(Sym *s, Reloc *r) return; case 256 + R_386_32: - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name); r->type = D_ADDR; return; case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0: r->type = D_ADDR; - if(targ->dynimpname != nil && !targ->dynexport) + if(targ->type == SDYNIMPORT) diag("unexpected reloc for dynamic symbol %s", targ->name); return; case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1: - if(targ->dynimpname != nil && !targ->dynexport) { + if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add = targ->plt; @@ -198,7 +198,7 @@ adddynrel(Sym *s, Reloc *r) return; case 512 + MACHO_FAKE_GOTPCREL: - if(targ->dynimpname == nil || targ->dynexport) { + if(targ->type != SDYNIMPORT) { // have symbol // turn MOVL of GOT entry into LEAL of symbol itself if(r->off < 2 || s->p[r->off-2] != 0x8b) { @@ -217,7 +217,7 @@ adddynrel(Sym *s, Reloc *r) } // Handle references to ELF symbols from our own object files. - if(targ->dynimpname == nil || targ->dynexport) + if(targ->type != SDYNIMPORT) return; switch(r->type) { @@ -270,12 +270,13 @@ adddynrel(Sym *s, Reloc *r) } int -elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) +elfreloc1(Reloc *r, vlong sectoff) { - USED(add); // written to obj file by ../ld/data.c's reloc + int32 elfsym; - LPUT(off); + LPUT(sectoff); + elfsym = r->xsym->elfsym; switch(r->type) { default: return -1; @@ -298,6 +299,78 @@ elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add) return 0; } +int +machoreloc1(Reloc *r, vlong sectoff) +{ + uint32 v; + Sym *rs; + + rs = r->xsym; + + if(rs->type == SHOSTOBJ) { + if(rs->dynid < 0) { + diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type); + return -1; + } + v = rs->dynid; + v |= 1<<27; // external relocation + } else { + v = rs->sect->extnum; + if(v == 0) { + diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type); + return -1; + } + } + + switch(r->type) { + default: + return -1; + case D_ADDR: + v |= MACHO_GENERIC_RELOC_VANILLA<<28; + break; + case D_PCREL: + v |= 1<<24; // pc-relative bit + v |= MACHO_GENERIC_RELOC_VANILLA<<28; + break; + } + + switch(r->siz) { + default: + return -1; + case 1: + v |= 0<<25; + break; + case 2: + v |= 1<<25; + break; + case 4: + v |= 2<<25; + break; + case 8: + v |= 3<<25; + break; + } + + LPUT(sectoff); + LPUT(v); + return 0; +} + +int +archreloc(Reloc *r, Sym *s, vlong *val) +{ + USED(s); + switch(r->type) { + case D_CONST: + *val = r->add; + return 0; + case D_GOTOFF: + *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0)); + return 0; + } + return -1; +} + void elfsetupplt(void) { @@ -326,21 +399,6 @@ elfsetupplt(void) } } -int -archreloc(Reloc *r, Sym *s, vlong *val) -{ - USED(s); - switch(r->type) { - case D_CONST: - *val = r->add; - return 0; - case D_GOTOFF: - *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0)); - return 0; - } - return -1; -} - static void addpltsym(Sym *s) { @@ -428,26 +486,20 @@ addgotsym(Sym *s) void adddynsym(Sym *s) { - Sym *d, *str; + Sym *d; int t; char *name; - vlong off; if(s->dynid >= 0) return; - if(s->dynimpname == nil) - diag("adddynsym: no dynamic name for %s", s->name); - if(iself) { s->dynid = nelfsym++; d = lookup(".dynsym", 0); /* name */ - name = s->dynimpname; - if(name == nil) - name = s->name; + name = s->extname; adduint32(d, addstring(lookup(".dynstr", 0), name)); /* value */ @@ -461,7 +513,7 @@ adddynsym(Sym *s) /* type */ t = STB_GLOBAL << 4; - if(s->dynexport && (s->type&SMASK) == STEXT) + if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; @@ -469,7 +521,7 @@ adddynsym(Sym *s) adduint8(d, 0); /* shndx */ - if(!s->dynexport && s->dynimpname != nil) + if(s->type == SDYNIMPORT) adduint16(d, SHN_UNDEF); else { switch(s->type) { @@ -490,57 +542,10 @@ adddynsym(Sym *s) adduint16(d, t); } } else if(HEADTYPE == Hdarwin) { - // Mach-O symbol nlist32 - d = lookup(".dynsym", 0); - name = s->dynimpname; - if(name == nil) - name = s->name; - if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps - symgrow(d, ndynexp*12); - } - if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp() - s->dynid = -s->dynid-100; - off = s->dynid*12; - } else { - off = d->size; - s->dynid = off/12; - } - // darwin still puts _ prefixes on all C symbols - str = lookup(".dynstr", 0); - setuint32(d, off, str->size); - off += 4; - adduint8(str, '_'); - addstring(str, name); - if(s->type == SDYNIMPORT) { - setuint8(d, off, 0x01); // type - N_EXT - external symbol - off++; - setuint8(d, off, 0); // section - off++; - } else { - setuint8(d, off, 0x0f); - off++; - switch(s->type) { - default: - case STEXT: - setuint8(d, off, 1); - break; - case SDATA: - setuint8(d, off, 2); - break; - case SBSS: - setuint8(d, off, 4); - break; - } - off++; - } - setuint16(d, off, 0); // desc - off += 2; - if(s->type == SDYNIMPORT) - setuint32(d, off, 0); // value - else - setaddr(d, off, s); - off += 4; - } else if(HEADTYPE != Hwindows) { + diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); + } else if(HEADTYPE == Hwindows) { + // already taken care of + } else { diag("adddynsym: unsupported binary format"); } } @@ -666,7 +671,7 @@ asmb(void) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); - if(isobj) + if(linkmode == LinkExternal) elfemitreloc(); } break; @@ -688,6 +693,10 @@ asmb(void) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); break; + case Hdarwin: + if(linkmode == LinkExternal) + machoemitreloc(); + break; } } if(debug['v']) diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index f88f058e3..980a7f830 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -42,6 +42,7 @@ enum thechar = '8', PtrSize = 4, IntSize = 4, + MaxAlign = 32, // max data alignment FuncAlign = 16 }; @@ -83,9 +84,12 @@ struct Reloc { int32 off; uchar siz; + uchar done; int32 type; int32 add; + int32 xadd; Sym* sym; + Sym* xsym; }; struct Prog @@ -122,11 +126,12 @@ struct Auto struct Sym { char* name; + char* extname; // name used in external object files short type; short version; uchar dupok; uchar reachable; - uchar dynexport; + uchar cgoexport; uchar special; uchar stkcheck; uchar hide; @@ -149,7 +154,6 @@ struct Sym Sym* reachparent; Sym* queue; char* file; - char* dynimpname; char* dynimplib; char* dynimpvers; struct Section* sect; @@ -172,7 +176,7 @@ struct Optab short as; uchar* ytab; uchar prefix; - uchar op[10]; + uchar op[12]; }; enum @@ -217,6 +221,7 @@ enum Zxxx = 0, Zlit, + Zlitm_r, Z_rp, Zbr, Zcall, @@ -233,6 +238,7 @@ enum Zloop, Zm_o, Zm_r, + Zm2_r, Zm_r_xm, Zm_r_i_xm, Zaut_r, @@ -249,6 +255,7 @@ enum Zib_rr, Zil_rr, Zclr, + Zibm_r, /* mmx1,mmx2/mem64,imm8 */ Zbyte, Zmov, Zmax, diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index dcb8390b9..306e288a3 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -90,6 +90,7 @@ main(int argc, char *argv[]) INITRND = -1; INITENTRY = 0; LIBINITENTRY = 0; + linkmode = LinkInternal; // TODO: LinkAuto once everything works. nuxiinit(); flagcount("1", "use alternate profiling code", &debug['1']); @@ -114,7 +115,7 @@ main(int argc, char *argv[]) flagcount("d", "disable dynamic executable", &debug['d']); flagcount("f", "ignore version mismatch", &debug['f']); flagcount("g", "disable go package data checks", &debug['g']); - flagcount("hostobj", "generate host object file", &isobj); + flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); flagstr("k", "sym: set field tracking symbol", &tracksym); flagstr("o", "outfile: set output file", &outfile); flagcount("p", "insert profiling code", &debug['p']); @@ -122,9 +123,11 @@ main(int argc, char *argv[]) flagcount("race", "enable race detector", &flag_race); flagcount("s", "disable symbol table", &debug['s']); flagcount("n", "dump symbol table", &debug['n']); + flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); flagcount("u", "reject unsafe packages", &debug['u']); flagcount("v", "print link trace", &debug['v']); flagcount("w", "disable DWARF generation", &debug['w']); + // TODO: link mode flag flagparse(&argc, &argv, usage); @@ -136,13 +139,19 @@ main(int argc, char *argv[]) if(HEADTYPE == -1) HEADTYPE = headtype(goos); - if(isobj) { - switch(HEADTYPE) { - default: - sysfatal("cannot use -hostobj with -H %s", headstr(HEADTYPE)); - case Hlinux: - break; - } + switch(HEADTYPE) { + default: + if(linkmode == LinkAuto) + linkmode = LinkInternal; + if(linkmode == LinkExternal) + sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); + break; + case Hdarwin: + case Hfreebsd: + case Hlinux: + case Hnetbsd: + case Hopenbsd: + break; } if(outfile == nil) { @@ -308,6 +317,8 @@ main(int argc, char *argv[]) reloc(); asmb(); undef(); + hostlink(); + if(debug['v']) { Bprint(&bso, "%5.2f cpu time\n", cputime()); Bprint(&bso, "%d symbols\n", nsymbol); @@ -431,7 +442,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) ntext = 0; eof = Boffset(f) + len; src[0] = 0; - + pn = estrdup(pn); // we keep it in Sym* references newloop: memset(h, 0, sizeof(h)); diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c index 79d7b39f0..a6ebf063e 100644 --- a/src/cmd/8l/optab.c +++ b/src/cmd/8l/optab.c @@ -150,9 +150,16 @@ uchar ymovl[] = // Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst Yi32, Yrl, Zil_rp, 1, Yi32, Yml, Zilo_m, 2, + Yml, Yxr, Zm_r_xm, 2, // XMM MOVD (32 bit) + Yxr, Yml, Zr_m_xm, 2, // XMM MOVD (32 bit) Yiauto, Yrl, Zaut_r, 2, 0 }; +uchar ymovq[] = +{ + Yml, Yxr, Zm_r_xm, 2, + 0 +}; uchar ym_rl[] = { Ym, Yrl, Zm_r, 1, @@ -435,6 +442,21 @@ uchar yprefetch[] = Ym, Ynone, Zm_o, 2, 0, }; +uchar yaes[] = +{ + Yxm, Yxr, Zlitm_r, 2, + 0 +}; +uchar yinsrd[] = +{ + Yml, Yxr, Zibm_r, 2, + 0 +}; +uchar ymshufb[] = +{ + Yxm, Yxr, Zm2_r, 2, + 0 +}; Optab optab[] = /* as, ytab, andproto, opcode */ @@ -552,8 +574,9 @@ Optab optab[] = { ALSLL, yml_rl, Pm, 0x03 }, { ALSLW, yml_rl, Pq, 0x03 }, { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) }, - { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) }, + { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e }, { AMOVW, ymovl, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00) }, + { AMOVQ, ymovq, Pf3, 0x7e }, { AMOVBLSX, ymb_rl, Pm, 0xbe }, { AMOVBLZX, ymb_rl, Pm, 0xb6 }, { AMOVBWSX, ymb_rl, Pq, 0xbe }, @@ -793,6 +816,7 @@ Optab optab[] = { ACMPXCHGW, yrl_ml, Pm, 0xb1 }, { ACMPXCHG8B, yscond, Pm, 0xc7,(01) }, + { ACPUID, ynone, Pm, 0xa2 }, { ARDTSC, ynone, Pm, 0x31 }, { AXADDB, yrb_mb, Pb, 0x0f,0xc0 }, @@ -925,6 +949,7 @@ Optab optab[] = { AORPD, yxm, Pq, 0x56 }, { AORPS, yxm, Pm, 0x56 }, { APADDQ, yxm, Pe, 0xd4 }, + { APAND, yxm, Pe, 0xdb }, { APMAXSW, yxm, Pe, 0xee }, { APMAXUB, yxm, Pe, 0xde }, { APMINSW, yxm, Pe, 0xea }, @@ -961,6 +986,10 @@ Optab optab[] = { AXORPD, yxm, Pe, 0x57 }, { AXORPS, yxm, Pm, 0x57 }, + { AAESENC, yaes, Pq, 0x38,0xdc,(0) }, + { APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) }, + { APSHUFB, ymshufb,Pq, 0x38, 0x00 }, + { AUSEFIELD, ynop, Px, 0,0 }, { ALOCALS }, { ATYPE }, diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index b828d8645..0678fa8f2 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -1003,11 +1003,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 +1031,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) |