summaryrefslogtreecommitdiff
path: root/src/cmd/8l
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-03-04 21:27:36 +0100
committerMichael Stapelberg <michael@stapelberg.de>2013-03-04 21:27:36 +0100
commit04b08da9af0c450d645ab7389d1467308cfc2db8 (patch)
treedb247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/cmd/8l
parent917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff)
downloadgolang-upstream/1.1_hg20130304.tar.gz
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/cmd/8l')
-rw-r--r--src/cmd/8l/8.out.h152
-rw-r--r--src/cmd/8l/asm.c648
-rw-r--r--src/cmd/8l/doc.go4
-rw-r--r--src/cmd/8l/l.h23
-rw-r--r--src/cmd/8l/list.c9
-rw-r--r--src/cmd/8l/obj.c148
-rw-r--r--src/cmd/8l/optab.c208
-rw-r--r--src/cmd/8l/pass.c79
-rw-r--r--src/cmd/8l/span.c156
9 files changed, 767 insertions, 660 deletions
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 9d2751cf0..386889956 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -451,6 +451,125 @@ enum as
ASFENCE,
AEMMS,
+
+ APREFETCHT0,
+ APREFETCHT1,
+ APREFETCHT2,
+ APREFETCHNTA,
+
+ ABSWAPL,
+
+ AUNDEF,
+
+ // SSE2
+ AADDPD,
+ AADDPS,
+ AADDSD,
+ AADDSS,
+ AANDNPD,
+ AANDNPS,
+ AANDPD,
+ AANDPS,
+ ACMPPD,
+ ACMPPS,
+ ACMPSD,
+ ACMPSS,
+ ACOMISD,
+ ACOMISS,
+ ACVTPL2PD,
+ ACVTPL2PS,
+ ACVTPD2PL,
+ ACVTPD2PS,
+ ACVTPS2PL,
+ ACVTPS2PD,
+ ACVTSD2SL,
+ ACVTSD2SS,
+ ACVTSL2SD,
+ ACVTSL2SS,
+ ACVTSS2SD,
+ ACVTSS2SL,
+ ACVTTPD2PL,
+ ACVTTPS2PL,
+ ACVTTSD2SL,
+ ACVTTSS2SL,
+ ADIVPD,
+ ADIVPS,
+ ADIVSD,
+ ADIVSS,
+ AMASKMOVOU,
+ AMAXPD,
+ AMAXPS,
+ AMAXSD,
+ AMAXSS,
+ AMINPD,
+ AMINPS,
+ AMINSD,
+ AMINSS,
+ AMOVAPD,
+ AMOVAPS,
+ AMOVO,
+ AMOVOU,
+ AMOVHLPS,
+ AMOVHPD,
+ AMOVHPS,
+ AMOVLHPS,
+ AMOVLPD,
+ AMOVLPS,
+ AMOVMSKPD,
+ AMOVMSKPS,
+ AMOVNTO,
+ AMOVNTPD,
+ AMOVNTPS,
+ AMOVSD,
+ AMOVSS,
+ AMOVUPD,
+ AMOVUPS,
+ AMULPD,
+ AMULPS,
+ AMULSD,
+ AMULSS,
+ AORPD,
+ AORPS,
+ APADDQ,
+ APMAXSW,
+ APMAXUB,
+ APMINSW,
+ APMINUB,
+ APSADBW,
+ APSUBB,
+ APSUBL,
+ APSUBQ,
+ APSUBSB,
+ APSUBSW,
+ APSUBUSB,
+ APSUBUSW,
+ APSUBW,
+ APUNPCKHQDQ,
+ APUNPCKLQDQ,
+ ARCPPS,
+ ARCPSS,
+ ARSQRTPS,
+ ARSQRTSS,
+ ASQRTPD,
+ ASQRTPS,
+ ASQRTSD,
+ ASQRTSS,
+ ASUBPD,
+ ASUBPS,
+ ASUBSD,
+ ASUBSS,
+ AUCOMISD,
+ AUCOMISS,
+ AUNPCKHPD,
+ AUNPCKHPS,
+ AUNPCKLPD,
+ AUNPCKLPS,
+ AXORPD,
+ AXORPS,
+
+ AUSEFIELD,
+ ALOCALS,
+ ATYPE,
ALAST
};
@@ -496,17 +615,26 @@ enum
D_DR = 43,
D_TR = 51,
- D_NONE = 59,
-
- D_BRANCH = 60,
- D_EXTERN = 61,
- D_STATIC = 62,
- D_AUTO = 63,
- D_PARAM = 64,
- D_CONST = 65,
- D_FCONST = 66,
- D_SCONST = 67,
- D_ADDR = 68,
+ D_X0 = 59,
+ D_X1,
+ D_X2,
+ D_X3,
+ D_X4,
+ D_X5,
+ D_X6,
+ D_X7,
+
+ D_NONE = 67,
+
+ D_BRANCH = 68,
+ D_EXTERN = 69,
+ D_STATIC = 70,
+ D_AUTO = 71,
+ D_PARAM = 72,
+ D_CONST = 73,
+ D_FCONST = 74,
+ D_SCONST = 75,
+ D_ADDR = 76,
D_FILE,
D_FILE1,
@@ -538,7 +666,7 @@ enum
/*
* this is the ranlib header
*/
-#define SYMDEF "__.SYMDEF"
+#define SYMDEF "__.GOSYMDEF"
/*
* this is the simulated IEEE floating point
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 25ffc786f..a00174c36 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -70,34 +70,6 @@ datoff(vlong addr)
return 0;
}
-enum {
- ElfStrEmpty,
- ElfStrInterp,
- ElfStrHash,
- ElfStrGot,
- ElfStrGotPlt,
- ElfStrDynamic,
- ElfStrDynsym,
- ElfStrDynstr,
- ElfStrRel,
- ElfStrText,
- ElfStrData,
- ElfStrBss,
- ElfStrShstrtab,
- ElfStrSymtab,
- ElfStrStrtab,
- ElfStrRelPlt,
- ElfStrPlt,
- ElfStrGnuVersion,
- ElfStrGnuVersionR,
- ElfStrNoteNetbsdIdent,
- ElfStrNoPtrData,
- ElfStrNoPtrBss,
- NElfStr
-};
-
-vlong elfstr[NElfStr];
-
static int
needlib(char *name)
{
@@ -123,6 +95,21 @@ int nelfsym = 1;
static void addpltsym(Sym*);
static void addgotsym(Sym*);
+Sym *
+lookuprel(void)
+{
+ return lookup(".rel", 0);
+}
+
+void
+adddynrela(Sym *rela, Sym *s, Reloc *r)
+{
+ USED(rela);
+ USED(s);
+ USED(r);
+ sysfatal("adddynrela not implemented");
+}
+
void
adddynrel(Sym *s, Reloc *r)
{
@@ -282,7 +269,36 @@ adddynrel(Sym *s, Reloc *r)
diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
}
-static void
+int
+elfreloc1(Reloc *r, vlong off, int32 elfsym, vlong add)
+{
+ USED(add); // written to obj file by ../ld/data.c's reloc
+
+ LPUT(off);
+
+ switch(r->type) {
+ default:
+ return -1;
+
+ case D_ADDR:
+ if(r->siz == 4)
+ LPUT(R_386_32 | elfsym<<8);
+ else
+ return -1;
+ break;
+
+ case D_PCREL:
+ if(r->siz == 4)
+ LPUT(R_386_PC32 | elfsym<<8);
+ else
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+void
elfsetupplt(void)
{
Sym *plt, *got;
@@ -415,6 +431,7 @@ adddynsym(Sym *s)
Sym *d, *str;
int t;
char *name;
+ vlong off;
if(s->dynid >= 0)
return;
@@ -444,7 +461,7 @@ adddynsym(Sym *s)
/* type */
t = STB_GLOBAL << 4;
- if(s->dynexport && s->type == STEXT)
+ if(s->dynexport && (s->type&SMASK) == STEXT)
t |= STT_FUNC;
else
t |= STT_OBJECT;
@@ -478,16 +495,51 @@ adddynsym(Sym *s)
name = s->dynimpname;
if(name == nil)
name = s->name;
- s->dynid = d->size/12;
+ 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);
- adduint32(d, str->size);
+ setuint32(d, off, str->size);
+ off += 4;
adduint8(str, '_');
addstring(str, name);
- adduint8(d, 0x01); // type - N_EXT - external symbol
- adduint8(d, 0); // section
- adduint16(d, 0); // desc
- adduint32(d, 0); // value
+ 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: unsupported binary format");
}
@@ -514,177 +566,26 @@ adddynlib(char *lib)
}
void
-doelf(void)
-{
- Sym *s, *shstrtab, *dynstr;
-
- if(!iself)
- return;
-
- /* predefine strings we need for section headers */
- shstrtab = lookup(".shstrtab", 0);
- shstrtab->type = SELFROSECT;
- shstrtab->reachable = 1;
-
- elfstr[ElfStrEmpty] = addstring(shstrtab, "");
- elfstr[ElfStrText] = addstring(shstrtab, ".text");
- elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
- elfstr[ElfStrData] = addstring(shstrtab, ".data");
- elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
- elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
- if(HEADTYPE == Hnetbsd)
- elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
- addstring(shstrtab, ".elfdata");
- addstring(shstrtab, ".rodata");
- addstring(shstrtab, ".gosymtab");
- addstring(shstrtab, ".gopclntab");
- if(!debug['s']) {
- elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
- elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
- dwarfaddshstrings(shstrtab);
- }
- elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
-
- if(!debug['d']) { /* -d suppresses dynamic loader format */
- elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
- elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
- elfstr[ElfStrGot] = addstring(shstrtab, ".got");
- elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
- elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
- elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
- elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
- elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
- elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
- elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
- elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
- elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
-
- /* dynamic symbol table - first entry all zeros */
- s = lookup(".dynsym", 0);
- s->type = SELFROSECT;
- s->reachable = 1;
- s->size += ELF32SYMSIZE;
-
- /* dynamic string table */
- s = lookup(".dynstr", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
- if(s->size == 0)
- addstring(s, "");
- dynstr = s;
-
- /* relocation table */
- s = lookup(".rel", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- /* global offset table */
- s = lookup(".got", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- /* hash */
- s = lookup(".hash", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- /* got.plt */
- s = lookup(".got.plt", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- s = lookup(".plt", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".rel.plt", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".gnu.version", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- s = lookup(".gnu.version_r", 0);
- s->reachable = 1;
- s->type = SELFROSECT;
-
- elfsetupplt();
-
- /* define dynamic elf table */
- s = lookup(".dynamic", 0);
- s->reachable = 1;
- s->type = SELFSECT; // writable
-
- /*
- * .dynamic table
- */
- elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
- elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
- elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
- elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
- elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
- elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
- elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
- elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
- if(rpath)
- elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
- elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
- elfwritedynent(s, DT_PLTREL, DT_REL);
- elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
- elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
-
- elfwritedynent(s, DT_DEBUG, 0);
-
- // Do not write DT_NULL. elfdynhash will finish it.
- }
-}
-
-void
-shsym(Elf64_Shdr *sh, Sym *s)
-{
- vlong addr;
- addr = symaddr(s);
- if(sh->flags&SHF_ALLOC)
- sh->addr = addr;
- sh->off = datoff(addr);
- sh->size = s->size;
-}
-
-void
-phsh(Elf64_Phdr *ph, Elf64_Shdr *sh)
-{
- ph->vaddr = sh->addr;
- ph->paddr = ph->vaddr;
- ph->off = sh->off;
- ph->filesz = sh->size;
- ph->memsz = sh->size;
- ph->align = sh->addralign;
-}
-
-void
asmb(void)
{
int32 v, magic;
- int a, dynsym;
- uint32 symo, startva, dwarfoff, machlink, resoff;
- ElfEhdr *eh;
- ElfPhdr *ph, *pph;
- ElfShdr *sh;
+ uint32 symo, dwarfoff, machlink;
Section *sect;
Sym *sym;
- int o;
int i;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
+ if(iself)
+ asmbelfsetup();
+
sect = segtext.sect;
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len);
- /* output read-only data in text segment (rodata, gosymtab and pclntab) */
+ /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len);
@@ -712,19 +613,6 @@ asmb(void)
machlink = domacholink();
}
- if(iself) {
- /* index of elf text section; needed by asmelfsym, double-checked below */
- /* !debug['d'] causes extra sections before the .text section */
- elftextsh = 2;
- if(!debug['d']) {
- elftextsh += 10;
- if(elfverneed)
- elftextsh += 2;
- }
- if(HEADTYPE == Hnetbsd)
- elftextsh += 1;
- }
-
symsize = 0;
spsize = 0;
lcsize = 0;
@@ -777,6 +665,9 @@ asmb(void)
if(debug['v'])
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
+
+ if(isobj)
+ elfemitreloc();
}
break;
case Hplan9x32:
@@ -805,8 +696,6 @@ asmb(void)
cseek(0L);
switch(HEADTYPE) {
default:
- if(iself)
- goto Elfput;
case Hgarbunix: /* garbage */
lputb(0x160L<<16); /* magic and sections */
lputb(0L); /* time and date */
@@ -932,273 +821,15 @@ asmb(void)
wputl(0x003E); /* reloc table offset */
wputl(0x0000); /* overlay number */
break;
-
case Hdarwin:
asmbmacho();
break;
-
- Elfput:
- eh = getElfEhdr();
- startva = INITTEXT - HEADR;
- resoff = ELFRESERVE;
-
- /* This null SHdr must appear before all others */
- newElfShdr(elfstr[ElfStrEmpty]);
-
- /* program header info */
- pph = newElfPhdr();
- pph->type = PT_PHDR;
- pph->flags = PF_R + PF_X;
- pph->off = eh->ehsize;
- pph->vaddr = INITTEXT - HEADR + pph->off;
- pph->paddr = INITTEXT - HEADR + pph->off;
- pph->align = INITRND;
-
- /*
- * PHDR must be in a loaded segment. Adjust the text
- * segment boundaries downwards to include it.
- */
- o = segtext.vaddr - pph->vaddr;
- segtext.vaddr -= o;
- segtext.len += o;
- o = segtext.fileoff - pph->off;
- segtext.fileoff -= o;
- segtext.filelen += o;
-
- if(!debug['d']) {
- /* interpreter */
- sh = newElfShdr(elfstr[ElfStrInterp]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- if(interpreter == nil) {
- switch(HEADTYPE) {
- case Hlinux:
- interpreter = linuxdynld;
- break;
- case Hfreebsd:
- interpreter = freebsddynld;
- break;
- case Hnetbsd:
- interpreter = netbsddynld;
- break;
- case Hopenbsd:
- interpreter = openbsddynld;
- break;
- }
- }
- resoff -= elfinterp(sh, startva, resoff, interpreter);
-
- ph = newElfPhdr();
- ph->type = PT_INTERP;
- ph->flags = PF_R;
- phsh(ph, sh);
- }
-
- if(HEADTYPE == Hnetbsd) {
- sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
- sh->type = SHT_NOTE;
- sh->flags = SHF_ALLOC;
- sh->addralign = 4;
- resoff -= elfnetbsdsig(sh, startva, resoff);
-
- ph = newElfPhdr();
- ph->type = PT_NOTE;
- ph->flags = PF_R;
- phsh(ph, sh);
- }
-
- // Additions to the reserved area must be above this line.
- USED(resoff);
-
- elfphload(&segtext);
- elfphload(&segdata);
-
- /* Dynamic linking sections */
- if(!debug['d']) { /* -d suppresses dynamic loader format */
- /* S headers for dynamic linking */
- sh = newElfShdr(elfstr[ElfStrGot]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 4;
- sh->addralign = 4;
- shsym(sh, lookup(".got", 0));
-
- sh = newElfShdr(elfstr[ElfStrGotPlt]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 4;
- sh->addralign = 4;
- shsym(sh, lookup(".got.plt", 0));
-
- dynsym = eh->shnum;
- sh = newElfShdr(elfstr[ElfStrDynsym]);
- sh->type = SHT_DYNSYM;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF32SYMSIZE;
- sh->addralign = 4;
- sh->link = dynsym+1; // dynstr
- // sh->info = index of first non-local symbol (number of local symbols)
- shsym(sh, lookup(".dynsym", 0));
-
- sh = newElfShdr(elfstr[ElfStrDynstr]);
- sh->type = SHT_STRTAB;
- sh->flags = SHF_ALLOC;
- sh->addralign = 1;
- shsym(sh, lookup(".dynstr", 0));
-
- if(elfverneed) {
- sh = newElfShdr(elfstr[ElfStrGnuVersion]);
- sh->type = SHT_GNU_VERSYM;
- sh->flags = SHF_ALLOC;
- sh->addralign = 2;
- sh->link = dynsym;
- sh->entsize = 2;
- shsym(sh, lookup(".gnu.version", 0));
-
- sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
- sh->type = SHT_GNU_VERNEED;
- sh->flags = SHF_ALLOC;
- sh->addralign = 4;
- sh->info = elfverneed;
- sh->link = dynsym+1; // dynstr
- shsym(sh, lookup(".gnu.version_r", 0));
- }
-
- sh = newElfShdr(elfstr[ElfStrRelPlt]);
- sh->type = SHT_REL;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF32RELSIZE;
- sh->addralign = 4;
- sh->link = dynsym;
- sh->info = eh->shnum; // .plt
- shsym(sh, lookup(".rel.plt", 0));
-
- sh = newElfShdr(elfstr[ElfStrPlt]);
- sh->type = SHT_PROGBITS;
- sh->flags = SHF_ALLOC+SHF_EXECINSTR;
- sh->entsize = 4;
- sh->addralign = 4;
- shsym(sh, lookup(".plt", 0));
-
- sh = newElfShdr(elfstr[ElfStrHash]);
- sh->type = SHT_HASH;
- sh->flags = SHF_ALLOC;
- sh->entsize = 4;
- sh->addralign = 4;
- sh->link = dynsym;
- shsym(sh, lookup(".hash", 0));
-
- sh = newElfShdr(elfstr[ElfStrRel]);
- sh->type = SHT_REL;
- sh->flags = SHF_ALLOC;
- sh->entsize = ELF32RELSIZE;
- sh->addralign = 4;
- sh->link = dynsym;
- shsym(sh, lookup(".rel", 0));
-
- /* sh and PT_DYNAMIC for .dynamic section */
- sh = newElfShdr(elfstr[ElfStrDynamic]);
- sh->type = SHT_DYNAMIC;
- sh->flags = SHF_ALLOC+SHF_WRITE;
- sh->entsize = 8;
- sh->addralign = 4;
- sh->link = dynsym+1; // dynstr
- shsym(sh, lookup(".dynamic", 0));
- ph = newElfPhdr();
- ph->type = PT_DYNAMIC;
- ph->flags = PF_R + PF_W;
- phsh(ph, sh);
-
- /*
- * Thread-local storage segment (really just size).
- */
- if(tlsoffset != 0) {
- ph = newElfPhdr();
- ph->type = PT_TLS;
- ph->flags = PF_R;
- ph->memsz = -tlsoffset;
- ph->align = 4;
- }
- }
-
- ph = newElfPhdr();
- ph->type = PT_GNU_STACK;
- ph->flags = PF_W+PF_R;
- ph->align = 4;
-
- sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
- sh->type = SHT_STRTAB;
- sh->addralign = 1;
- shsym(sh, lookup(".shstrtab", 0));
-
- if(elftextsh != eh->shnum)
- diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
- for(sect=segtext.sect; sect!=nil; sect=sect->next)
- elfshbits(sect);
- for(sect=segdata.sect; sect!=nil; sect=sect->next)
- elfshbits(sect);
-
- if(!debug['s']) {
- sh = newElfShdr(elfstr[ElfStrSymtab]);
- sh->type = SHT_SYMTAB;
- sh->off = symo;
- sh->size = symsize;
- sh->addralign = 4;
- sh->entsize = 16;
- sh->link = eh->shnum; // link to strtab
-
- sh = newElfShdr(elfstr[ElfStrStrtab]);
- sh->type = SHT_STRTAB;
- sh->off = symo+symsize;
- sh->size = elfstrsize;
- sh->addralign = 1;
-
- dwarfaddelfheaders();
- }
-
- /* Main header */
- eh->ident[EI_MAG0] = '\177';
- eh->ident[EI_MAG1] = 'E';
- eh->ident[EI_MAG2] = 'L';
- eh->ident[EI_MAG3] = 'F';
- eh->ident[EI_CLASS] = ELFCLASS32;
- eh->ident[EI_DATA] = ELFDATA2LSB;
- eh->ident[EI_VERSION] = EV_CURRENT;
- switch(HEADTYPE) {
- case Hfreebsd:
- eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
- break;
- case Hnetbsd:
- eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
- break;
- case Hopenbsd:
- eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
- break;
- }
-
- eh->type = ET_EXEC;
- eh->machine = EM_386;
- eh->version = EV_CURRENT;
- eh->entry = entryvalue();
-
- if(pph != nil) {
- pph->filesz = eh->phnum * eh->phentsize;
- pph->memsz = pph->filesz;
- }
-
- cseek(0);
- a = 0;
- a += elfwritehdr();
- a += elfwritephdrs();
- a += elfwriteshdrs();
- a += elfwriteinterp(elfstr[ElfStrInterp]);
- if(HEADTYPE == Hnetbsd)
- a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
- if(a > ELFRESERVE)
- diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
+ case Hlinux:
+ case Hfreebsd:
+ case Hnetbsd:
+ case Hopenbsd:
+ asmbelf(symo);
break;
-
case Hwindows:
asmbpe();
break;
@@ -1231,80 +862,3 @@ rnd(int32 v, int32 r)
v -= c;
return v;
}
-
-void
-genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
-{
- Auto *a;
- Sym *s;
- int h;
-
- s = lookup("etext", 0);
- if(s->type == STEXT)
- put(s, s->name, 'T', s->value, s->size, s->version, 0);
-
- for(h=0; h<NHASH; h++) {
- for(s=hash[h]; s!=S; s=s->hash) {
- if(s->hide)
- continue;
- switch(s->type&~SSUB) {
- case SCONST:
- case SRODATA:
- case SDATA:
- case SELFROSECT:
- case SMACHO:
- case SMACHOGOT:
- case STYPE:
- case SSTRING:
- case SGOSTRING:
- case SWINDOWS:
- case SNOPTRDATA:
- case SSYMTAB:
- case SPCLNTAB:
- if(!s->reachable)
- continue;
- put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
- continue;
-
- case SBSS:
- case SNOPTRBSS:
- if(!s->reachable)
- continue;
- put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
- continue;
-
- case SFILE:
- put(nil, s->name, 'f', s->value, 0, s->version, 0);
- continue;
- }
- }
- }
-
- for(s = textp; s != nil; s = s->next) {
- if(s->text == nil)
- continue;
-
- /* filenames first */
- for(a=s->autom; a; a=a->link)
- if(a->type == D_FILE)
- put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
- else
- if(a->type == D_FILE1)
- put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
-
- put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
-
- /* frame, auto and param after */
- put(nil, ".frame", 'm', s->text->to.offset+4, 0, 0, 0);
-
- for(a=s->autom; a; a=a->link)
- if(a->type == D_AUTO)
- put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
- else
- if(a->type == D_PARAM)
- put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
- }
- if(debug['v'] || debug['n'])
- Bprint(&bso, "symsize = %d\n", symsize);
- Bflush(&bso);
-}
diff --git a/src/cmd/8l/doc.go b/src/cmd/8l/doc.go
index 12301d4f2..ff06bc376 100644
--- a/src/cmd/8l/doc.go
+++ b/src/cmd/8l/doc.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build ignore
+
/*
8l is the linker for the 32-bit x86.
@@ -10,4 +12,4 @@ The $GOARCH for these tools is 386.
The flags are documented in ../ld/doc.go.
*/
-package documentation
+package main
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index b974f464b..f88f058e3 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -40,7 +40,9 @@
enum
{
thechar = '8',
- PtrSize = 4
+ PtrSize = 4,
+ IntSize = 4,
+ FuncAlign = 16
};
#define P ((Prog*)0)
@@ -135,16 +137,22 @@ struct Sym
int32 plt;
int32 got;
int32 align; // if non-zero, required alignment in bytes
+ int32 elfsym;
+ int32 locals; // size of stack frame locals area
+ int32 args; // size of stack frame incoming arguments area
Sym* hash; // in hash table
Sym* allsym; // in all symbol list
Sym* next; // in text or data list
Sym* sub; // in sub list
Sym* outer; // container of sub
Sym* gotype;
+ Sym* reachparent;
+ Sym* queue;
char* file;
char* dynimpname;
char* dynimplib;
char* dynimpvers;
+ struct Section* sect;
// STEXT
Auto* autom;
@@ -157,6 +165,7 @@ struct Sym
Reloc* r;
int32 nr;
int32 maxr;
+ int rel_ro;
};
struct Optab
{
@@ -201,6 +210,8 @@ enum
Ycr0, Ycr1, Ycr2, Ycr3, Ycr4, Ycr5, Ycr6, Ycr7,
Ydr0, Ydr1, Ydr2, Ydr3, Ydr4, Ydr5, Ydr6, Ydr7,
Ytr0, Ytr1, Ytr2, Ytr3, Ytr4, Ytr5, Ytr6, Ytr7,
+ Ymr, Ymm,
+ Yxr, Yxm,
Ymax,
Zxxx = 0,
@@ -222,10 +233,14 @@ enum
Zloop,
Zm_o,
Zm_r,
+ Zm_r_xm,
+ Zm_r_i_xm,
Zaut_r,
Zo_m,
Zpseudo,
Zr_m,
+ Zr_m_xm,
+ Zr_m_i_xm,
Zrp_,
Z_ib,
Z_il,
@@ -243,6 +258,8 @@ enum
Pm = 0x0f, /* 2byte opcode escape */
Pq = 0xff, /* both escape */
Pb = 0xfe, /* byte operands */
+ Pf2 = 0xf2, /* xmm escape 1 */
+ Pf3 = 0xf3, /* xmm escape 2 */
};
#pragma varargck type "A" int
@@ -261,6 +278,7 @@ EXTERN int32 INITRND;
EXTERN int32 INITTEXT;
EXTERN int32 INITDAT;
EXTERN char* INITENTRY; /* entry point */
+EXTERN char* LIBINITENTRY; /* shared library entry point */
EXTERN int32 casepc;
EXTERN char* pcstr;
EXTERN Auto* curauto;
@@ -269,7 +287,7 @@ EXTERN Prog* curp;
EXTERN Sym* cursym;
EXTERN Sym* datap;
EXTERN int32 elfdatsize;
-EXTERN char debug[128];
+EXTERN int debug[128];
EXTERN char literal[32];
EXTERN Sym* etextp;
EXTERN Prog* firstp;
@@ -282,7 +300,6 @@ EXTERN int maxop;
EXTERN int nerrors;
EXTERN char* noname;
EXTERN int32 pc;
-EXTERN char* interpreter;
EXTERN char* rpath;
EXTERN int32 spsize;
EXTERN Sym* symlist;
diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c
index 31ae02346..0b544fbce 100644
--- a/src/cmd/8l/list.c
+++ b/src/cmd/8l/list.c
@@ -254,6 +254,15 @@ char* regstr[] =
"TR5",
"TR6",
"TR7",
+
+ "X0",
+ "X1",
+ "X2",
+ "X3",
+ "X4",
+ "X5",
+ "X6",
+ "X7",
"NONE", /* [D_NONE] */
};
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index af4bc844f..dcb8390b9 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -77,18 +77,8 @@ Header headers[] = {
*/
void
-usage(void)
-{
- fprint(2, "usage: 8l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.8\n");
- exits("usage");
-}
-
-void
main(int argc, char *argv[])
{
- int c;
- char *name, *val;
-
Binit(&bso, 1, OWRITE);
listinit();
memset(debug, 0, sizeof(debug));
@@ -99,52 +89,44 @@ main(int argc, char *argv[])
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ LIBINITENTRY = 0;
nuxiinit();
- ARGBEGIN {
- default:
- c = ARGC();
- if(c == 'l')
- usage();
- if(c >= 0 && c < sizeof(debug))
- debug[c]++;
- break;
- case 'o': /* output to (next arg) */
- outfile = EARGF(usage());
- break;
- case 'E':
- INITENTRY = EARGF(usage());
- break;
- case 'H':
- HEADTYPE = headtype(EARGF(usage()));
- break;
- case 'I':
- interpreter = EARGF(usage());
- break;
- case 'L':
- Lflag(EARGF(usage()));
- break;
- case 'T':
- INITTEXT = atolwhex(EARGF(usage()));
- break;
- case 'D':
- INITDAT = atolwhex(EARGF(usage()));
- break;
- case 'R':
- INITRND = atolwhex(EARGF(usage()));
- break;
- case 'r':
- rpath = EARGF(usage());
- break;
- case 'V':
- print("%cl version %s\n", thechar, getgoversion());
- errorexit();
- case 'X':
- name = EARGF(usage());
- val = EARGF(usage());
- addstrdata(name, val);
- break;
- } ARGEND
+ flagcount("1", "use alternate profiling code", &debug['1']);
+ flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
+ flagstr("E", "sym: entry symbol", &INITENTRY);
+ flagint32("D", "addr: data address", &INITDAT);
+ flagfn1("I", "interp: set ELF interp", setinterp);
+ flagfn1("L", "dir: add dir to library path", Lflag);
+ flagfn1("H", "head: header type", setheadtype);
+ flagcount("K", "add stack underflow checks", &debug['K']);
+ flagcount("O", "print pc-line tables", &debug['O']);
+ flagcount("Q", "debug byte-register code gen", &debug['Q']);
+ flagint32("R", "rnd: address rounding", &INITRND);
+ flagcount("S", "check type signatures", &debug['S']);
+ flagint32("T", "addr: text address", &INITTEXT);
+ flagfn0("V", "print version and exit", doversion);
+ flagcount("W", "disassemble input", &debug['W']);
+ flagfn2("X", "name value: define string data", addstrdata);
+ flagcount("Z", "clear stack frame on entry", &debug['Z']);
+ flagcount("a", "disassemble output", &debug['a']);
+ flagcount("c", "dump call graph", &debug['c']);
+ 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);
+ flagstr("k", "sym: set field tracking symbol", &tracksym);
+ flagstr("o", "outfile: set output file", &outfile);
+ flagcount("p", "insert profiling code", &debug['p']);
+ flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
+ flagcount("race", "enable race detector", &flag_race);
+ flagcount("s", "disable symbol table", &debug['s']);
+ flagcount("n", "dump symbol table", &debug['n']);
+ flagcount("u", "reject unsafe packages", &debug['u']);
+ flagcount("v", "print link trace", &debug['v']);
+ flagcount("w", "disable DWARF generation", &debug['w']);
+
+ flagparse(&argc, &argv, usage);
if(argc != 1)
usage();
@@ -154,6 +136,15 @@ 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;
+ }
+ }
+
if(outfile == nil) {
if(HEADTYPE == Hwindows)
outfile = "8.out.exe";
@@ -300,6 +291,7 @@ main(int argc, char *argv[])
if(HEADTYPE == Hwindows)
dope();
dostkoff();
+ dostkcheck();
if(debug['p'])
if(debug['1'])
doprof1();
@@ -332,7 +324,7 @@ zsym(char *pn, Biobuf *f, Sym *h[])
{
int o;
- o = Bgetc(f);
+ o = BGETC(f);
if(o < 0 || o >= NSYM || h[o] == nil)
mangle(pn);
return h[o];
@@ -346,12 +338,12 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
Sym *s;
Auto *u;
- t = Bgetc(f);
+ t = BGETC(f);
a->index = D_NONE;
a->scale = 0;
if(t & T_INDEX) {
- a->index = Bgetc(f);
- a->scale = Bgetc(f);
+ a->index = BGETC(f);
+ a->scale = BGETC(f);
}
a->type = D_NONE;
a->offset = 0;
@@ -375,7 +367,7 @@ zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
a->type = D_SCONST;
}
if(t & T_TYPE)
- a->type = Bgetc(f);
+ a->type = BGETC(f);
adrgotype = S;
if(t & T_GOTYPE)
adrgotype = zsym(pn, f, h);
@@ -451,10 +443,10 @@ newloop:
loop:
if(f->state == Bracteof || Boffset(f) >= eof)
goto eof;
- o = Bgetc(f);
+ o = BGETC(f);
if(o == Beof)
goto eof;
- o |= Bgetc(f) << 8;
+ o |= BGETC(f) << 8;
if(o <= AXXX || o >= ALAST) {
if(o < 0)
goto eof;
@@ -467,8 +459,8 @@ loop:
sig = 0;
if(o == ASIGNAME)
sig = Bget4(f);
- v = Bgetc(f); /* type */
- o = Bgetc(f); /* sym */
+ v = BGETC(f); /* type */
+ o = BGETC(f); /* sym */
r = 0;
if(v == D_STATIC)
r = version;
@@ -523,8 +515,6 @@ loop:
p->as = o;
p->line = Bget4(f);
p->back = 2;
- p->ft = 0;
- p->tt = 0;
zaddr(pn, f, &p->from, h);
fromgotype = adrgotype;
zaddr(pn, f, &p->to, h);
@@ -605,6 +595,15 @@ loop:
pc++;
goto loop;
+ case ALOCALS:
+ cursym->locals = p->to.offset;
+ pc++;
+ goto loop;
+
+ case ATYPE:
+ pc++;
+ goto loop;
+
case ATEXT:
s = p->from.sym;
if(s->text != nil) {
@@ -643,6 +642,7 @@ loop:
}
s->type = STEXT;
s->value = pc;
+ s->args = p->to.offset2;
lastp = p;
p->pc = pc++;
goto loop;
@@ -656,6 +656,13 @@ loop:
case AFDIVRF:
case AFCOMF:
case AFCOMFP:
+ case AMOVSS:
+ case AADDSS:
+ case ASUBSS:
+ case AMULSS:
+ case ADIVSS:
+ case ACOMISS:
+ case AUCOMISS:
if(skip)
goto casdef;
if(p->from.type == D_FCONST) {
@@ -663,7 +670,7 @@ loop:
sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
s = lookup(literal, 0);
if(s->type == 0) {
- s->type = SDATA;
+ s->type = SRODATA;
adduint32(s, ieeedtof(&p->from.ieee));
s->reachable = 0;
}
@@ -682,6 +689,13 @@ loop:
case AFDIVRD:
case AFCOMD:
case AFCOMDP:
+ case AMOVSD:
+ case AADDSD:
+ case ASUBSD:
+ case AMULSD:
+ case ADIVSD:
+ case ACOMISD:
+ case AUCOMISD:
if(skip)
goto casdef;
if(p->from.type == D_FCONST) {
@@ -690,7 +704,7 @@ loop:
p->from.ieee.l, p->from.ieee.h);
s = lookup(literal, 0);
if(s->type == 0) {
- s->type = SDATA;
+ s->type = SRODATA;
adduint32(s, p->from.ieee.l);
adduint32(s, p->from.ieee.h);
s->reachable = 0;
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index 856482290..79d7b39f0 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -242,6 +242,11 @@ uchar ypopl[] =
Ynone, Ym, Zo_m, 2,
0
};
+uchar ybswap[] =
+{
+ Ynone, Yrl, Z_rp, 1,
+ 0,
+};
uchar yscond[] =
{
Ynone, Ymb, Zo_m, 2,
@@ -249,7 +254,9 @@ uchar yscond[] =
};
uchar yjcond[] =
{
- Ynone, Ybr, Zbr, 1,
+ Ynone, Ybr, Zbr, 0,
+ Yi0, Ybr, Zbr, 0,
+ Yi1, Ybr, Zbr, 1,
0
};
uchar yloop[] =
@@ -259,7 +266,8 @@ uchar yloop[] =
};
uchar ycall[] =
{
- Ynone, Yml, Zo_m, 2,
+ Ynone, Yml, Zo_m, 0,
+ Yrx, Yrx, Zo_m, 2,
Ynone, Ycol, Zcallind, 2,
Ynone, Ybr, Zcall, 0,
Ynone, Yi32, Zcallcon, 1,
@@ -349,6 +357,84 @@ uchar ysvrs[] =
Ym, Ynone, Zm_o, 2,
0
};
+uchar yxm[] =
+{
+ Yxm, Yxr, Zm_r_xm, 1,
+ 0
+};
+uchar yxcvm1[] =
+{
+ Yxm, Yxr, Zm_r_xm, 2,
+ Yxm, Ymr, Zm_r_xm, 2,
+ 0
+};
+uchar yxcvm2[] =
+{
+ Yxm, Yxr, Zm_r_xm, 2,
+ Ymm, Yxr, Zm_r_xm, 2,
+ 0
+};
+uchar yxmq[] =
+{
+ Yxm, Yxr, Zm_r_xm, 2,
+ 0
+};
+uchar yxr[] =
+{
+ Yxr, Yxr, Zm_r_xm, 1,
+ 0
+};
+uchar yxr_ml[] =
+{
+ Yxr, Yml, Zr_m_xm, 1,
+ 0
+};
+uchar yxcmp[] =
+{
+ Yxm, Yxr, Zm_r_xm, 1,
+ 0
+};
+uchar yxcmpi[] =
+{
+ Yxm, Yxr, Zm_r_i_xm, 2,
+ 0
+};
+uchar yxmov[] =
+{
+ Yxm, Yxr, Zm_r_xm, 1,
+ Yxr, Yxm, Zr_m_xm, 1,
+ 0
+};
+uchar yxcvfl[] =
+{
+ Yxm, Yrl, Zm_r_xm, 1,
+ 0
+};
+uchar yxcvlf[] =
+{
+ Yml, Yxr, Zm_r_xm, 1,
+ 0
+};
+uchar yxcvfq[] =
+{
+ Yxm, Yrl, Zm_r_xm, 2,
+ 0
+};
+uchar yxcvqf[] =
+{
+ Yml, Yxr, Zm_r_xm, 2,
+ 0
+};
+uchar yxrrl[] =
+{
+ Yxr, Yrl, Zm_r, 1,
+ 0
+};
+uchar yprefetch[] =
+{
+ Ym, Ynone, Zm_o, 2,
+ 0,
+};
Optab optab[] =
/* as, ytab, andproto, opcode */
@@ -761,5 +847,123 @@ Optab optab[] =
{ AEMMS, ynone, Pm, 0x77 },
+ { APREFETCHT0, yprefetch, Pm, 0x18,(01) },
+ { APREFETCHT1, yprefetch, Pm, 0x18,(02) },
+ { APREFETCHT2, yprefetch, Pm, 0x18,(03) },
+ { APREFETCHNTA, yprefetch, Pm, 0x18,(00) },
+
+ { ABSWAPL, ybswap, Pm, 0xc8 },
+
+ { AUNDEF, ynone, Px, 0x0f, 0x0b },
+
+ { AADDPD, yxm, Pq, 0x58 },
+ { AADDPS, yxm, Pm, 0x58 },
+ { AADDSD, yxm, Pf2, 0x58 },
+ { AADDSS, yxm, Pf3, 0x58 },
+ { AANDNPD, yxm, Pq, 0x55 },
+ { AANDNPS, yxm, Pm, 0x55 },
+ { AANDPD, yxm, Pq, 0x54 },
+ { AANDPS, yxm, Pq, 0x54 },
+ { ACMPPD, yxcmpi, Px, Pe,0xc2 },
+ { ACMPPS, yxcmpi, Pm, 0xc2,0 },
+ { ACMPSD, yxcmpi, Px, Pf2,0xc2 },
+ { ACMPSS, yxcmpi, Px, Pf3,0xc2 },
+ { ACOMISD, yxcmp, Pe, 0x2f },
+ { ACOMISS, yxcmp, Pm, 0x2f },
+ { ACVTPL2PD, yxcvm2, Px, Pf3,0xe6,Pe,0x2a },
+ { ACVTPL2PS, yxcvm2, Pm, 0x5b,0,0x2a,0, },
+ { ACVTPD2PL, yxcvm1, Px, Pf2,0xe6,Pe,0x2d },
+ { ACVTPD2PS, yxm, Pe, 0x5a },
+ { ACVTPS2PL, yxcvm1, Px, Pe,0x5b,Pm,0x2d },
+ { ACVTPS2PD, yxm, Pm, 0x5a },
+ { ACVTSD2SL, yxcvfl, Pf2, 0x2d },
+ { ACVTSD2SS, yxm, Pf2, 0x5a },
+ { ACVTSL2SD, yxcvlf, Pf2, 0x2a },
+ { ACVTSL2SS, yxcvlf, Pf3, 0x2a },
+ { ACVTSS2SD, yxm, Pf3, 0x5a },
+ { ACVTSS2SL, yxcvfl, Pf3, 0x2d },
+ { ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c },
+ { ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c },
+ { ACVTTSD2SL, yxcvfl, Pf2, 0x2c },
+ { ACVTTSS2SL, yxcvfl, Pf3, 0x2c },
+ { ADIVPD, yxm, Pe, 0x5e },
+ { ADIVPS, yxm, Pm, 0x5e },
+ { ADIVSD, yxm, Pf2, 0x5e },
+ { ADIVSS, yxm, Pf3, 0x5e },
+ { AMASKMOVOU, yxr, Pe, 0xf7 },
+ { AMAXPD, yxm, Pe, 0x5f },
+ { AMAXPS, yxm, Pm, 0x5f },
+ { AMAXSD, yxm, Pf2, 0x5f },
+ { AMAXSS, yxm, Pf3, 0x5f },
+ { AMINPD, yxm, Pe, 0x5d },
+ { AMINPS, yxm, Pm, 0x5d },
+ { AMINSD, yxm, Pf2, 0x5d },
+ { AMINSS, yxm, Pf3, 0x5d },
+ { AMOVAPD, yxmov, Pe, 0x28,0x29 },
+ { AMOVAPS, yxmov, Pm, 0x28,0x29 },
+ { AMOVO, yxmov, Pe, 0x6f,0x7f },
+ { AMOVOU, yxmov, Pf3, 0x6f,0x7f },
+ { AMOVHLPS, yxr, Pm, 0x12 },
+ { AMOVHPD, yxmov, Pe, 0x16,0x17 },
+ { AMOVHPS, yxmov, Pm, 0x16,0x17 },
+ { AMOVLHPS, yxr, Pm, 0x16 },
+ { AMOVLPD, yxmov, Pe, 0x12,0x13 },
+ { AMOVLPS, yxmov, Pm, 0x12,0x13 },
+ { AMOVMSKPD, yxrrl, Pq, 0x50 },
+ { AMOVMSKPS, yxrrl, Pm, 0x50 },
+ { AMOVNTO, yxr_ml, Pe, 0xe7 },
+ { AMOVNTPD, yxr_ml, Pe, 0x2b },
+ { AMOVNTPS, yxr_ml, Pm, 0x2b },
+ { AMOVSD, yxmov, Pf2, 0x10,0x11 },
+ { AMOVSS, yxmov, Pf3, 0x10,0x11 },
+ { AMOVUPD, yxmov, Pe, 0x10,0x11 },
+ { AMOVUPS, yxmov, Pm, 0x10,0x11 },
+ { AMULPD, yxm, Pe, 0x59 },
+ { AMULPS, yxm, Ym, 0x59 },
+ { AMULSD, yxm, Pf2, 0x59 },
+ { AMULSS, yxm, Pf3, 0x59 },
+ { AORPD, yxm, Pq, 0x56 },
+ { AORPS, yxm, Pm, 0x56 },
+ { APADDQ, yxm, Pe, 0xd4 },
+ { APMAXSW, yxm, Pe, 0xee },
+ { APMAXUB, yxm, Pe, 0xde },
+ { APMINSW, yxm, Pe, 0xea },
+ { APMINUB, yxm, Pe, 0xda },
+ { APSADBW, yxm, Pq, 0xf6 },
+ { APSUBB, yxm, Pe, 0xf8 },
+ { APSUBL, yxm, Pe, 0xfa },
+ { APSUBQ, yxm, Pe, 0xfb },
+ { APSUBSB, yxm, Pe, 0xe8 },
+ { APSUBSW, yxm, Pe, 0xe9 },
+ { APSUBUSB, yxm, Pe, 0xd8 },
+ { APSUBUSW, yxm, Pe, 0xd9 },
+ { APSUBW, yxm, Pe, 0xf9 },
+ { APUNPCKHQDQ, yxm, Pe, 0x6d },
+ { APUNPCKLQDQ, yxm, Pe, 0x6c },
+ { ARCPPS, yxm, Pm, 0x53 },
+ { ARCPSS, yxm, Pf3, 0x53 },
+ { ARSQRTPS, yxm, Pm, 0x52 },
+ { ARSQRTSS, yxm, Pf3, 0x52 },
+ { ASQRTPD, yxm, Pe, 0x51 },
+ { ASQRTPS, yxm, Pm, 0x51 },
+ { ASQRTSD, yxm, Pf2, 0x51 },
+ { ASQRTSS, yxm, Pf3, 0x51 },
+ { ASUBPD, yxm, Pe, 0x5c },
+ { ASUBPS, yxm, Pm, 0x5c },
+ { ASUBSD, yxm, Pf2, 0x5c },
+ { ASUBSS, yxm, Pf3, 0x5c },
+ { AUCOMISD, yxcmp, Pe, 0x2e },
+ { AUCOMISS, yxcmp, Pm, 0x2e },
+ { AUNPCKHPD, yxm, Pe, 0x15 },
+ { AUNPCKHPS, yxm, Pm, 0x15 },
+ { AUNPCKLPD, yxm, Pe, 0x14 },
+ { AUNPCKLPS, yxm, Pm, 0x14 },
+ { AXORPD, yxm, Pe, 0x57 },
+ { AXORPS, yxm, Pm, 0x57 },
+
+ { AUSEFIELD, ynop, Px, 0,0 },
+ { ALOCALS },
+ { ATYPE },
+
0
};
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 9034fdf3a..14dd3e0dc 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -75,6 +75,7 @@ nofollow(int a)
case ARET:
case AIRETL:
case AIRETW:
+ case AUNDEF:
return 1;
}
return 0;
@@ -184,20 +185,34 @@ loop:
* recurse to follow one path.
* continue loop on the other.
*/
- q = brchain(p->link);
- if(q != P && q->mark)
- if(a != ALOOP) {
- p->as = relinv(a);
- p->link = p->pcond;
+ if((q = brchain(p->pcond)) != P)
p->pcond = q;
+ if((q = brchain(p->link)) != P)
+ p->link = q;
+ if(p->from.type == D_CONST) {
+ if(p->from.offset == 1) {
+ /*
+ * expect conditional jump to be taken.
+ * rewrite so that's the fall-through case.
+ */
+ p->as = relinv(a);
+ q = p->link;
+ p->link = p->pcond;
+ p->pcond = q;
+ }
+ } else {
+ q = p->link;
+ if(q->mark)
+ if(a != ALOOP) {
+ p->as = relinv(a);
+ p->link = p->pcond;
+ p->pcond = q;
+ }
}
xfol(p->link, last);
- q = brchain(p->pcond);
- if(q->mark) {
- p->pcond = q;
+ if(p->pcond->mark)
return;
- }
- p = q;
+ p = p->pcond;
goto loop;
}
p = p->link;
@@ -315,7 +330,7 @@ patch(void)
} else if(s) {
if(debug['c'])
Bprint(&bso, "%s calls %s\n", TNAME, s->name);
- if((s->type&~SSUB) != STEXT) {
+ if((s->type&SMASK) != STEXT) {
/* diag prints TNAME first */
diag("undefined: %s", s->name);
s->type = STEXT;
@@ -524,9 +539,9 @@ dostkoff(void)
q = p;
}
- p = appendp(p); // save frame size in DX
+ p = appendp(p); // save frame size in DI
p->as = AMOVL;
- p->to.type = D_DX;
+ p->to.type = D_DI;
p->from.type = D_CONST;
// If we ask for more stack, we'll get a minimum of StackMin bytes.
@@ -565,9 +580,47 @@ dostkoff(void)
p->spadj = autoffset;
if(q != P)
q->pcond = p;
+ } else {
+ // zero-byte stack adjustment.
+ // Insert a fake non-zero adjustment so that stkcheck can
+ // recognize the end of the stack-splitting prolog.
+ p = appendp(p);
+ p->as = ANOP;
+ p->spadj = -PtrSize;
+ p = appendp(p);
+ p->as = ANOP;
+ p->spadj = PtrSize;
}
deltasp = autoffset;
+ if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
+ // 8l -Z means zero the stack frame on entry.
+ // This slows down function calls but can help avoid
+ // false positives in garbage collection.
+ p = appendp(p);
+ p->as = AMOVL;
+ p->from.type = D_SP;
+ p->to.type = D_DI;
+
+ p = appendp(p);
+ p->as = AMOVL;
+ p->from.type = D_CONST;
+ p->from.offset = autoffset/4;
+ p->to.type = D_CX;
+
+ p = appendp(p);
+ p->as = AMOVL;
+ p->from.type = D_CONST;
+ p->from.offset = 0;
+ p->to.type = D_AX;
+
+ p = appendp(p);
+ p->as = AREP;
+
+ p = appendp(p);
+ p->as = ASTOSL;
+ }
+
for(; p != P; p = p->link) {
a = p->from.type;
if(a == D_AUTO)
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 81c1d37eb..b828d8645 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -194,7 +194,7 @@ instinit(void)
for(i=1; optab[i].as; i++)
if(i != optab[i].as) {
- diag("phase error in optab: %d", i);
+ diag("phase error in optab: at %A found %A", i, optab[i].as);
errorexit();
}
maxop = i;
@@ -238,6 +238,16 @@ instinit(void)
ycover[Yrl*Ymax + Yml] = 1;
ycover[Ym*Ymax + Yml] = 1;
+ ycover[Yax*Ymax + Ymm] = 1;
+ ycover[Ycx*Ymax + Ymm] = 1;
+ ycover[Yrx*Ymax + Ymm] = 1;
+ ycover[Yrl*Ymax + Ymm] = 1;
+ ycover[Ym*Ymax + Ymm] = 1;
+ ycover[Ymr*Ymax + Ymm] = 1;
+
+ ycover[Ym*Ymax + Yxm] = 1;
+ ycover[Yxr*Ymax + Yxm] = 1;
+
for(i=0; i<D_NONE; i++) {
reg[i] = -1;
if(i >= D_AL && i <= D_BH)
@@ -246,6 +256,8 @@ instinit(void)
reg[i] = (i-D_AX) & 7;
if(i >= D_F0 && i <= D_F0+7)
reg[i] = (i-D_F0) & 7;
+ if(i >= D_X0 && i <= D_X0+7)
+ reg[i] = (i-D_X0) & 7;
}
}
@@ -333,6 +345,16 @@ oclass(Adr *a)
case D_F0+7:
return Yrf;
+ case D_X0+0:
+ case D_X0+1:
+ case D_X0+2:
+ case D_X0+3:
+ case D_X0+4:
+ case D_X0+5:
+ case D_X0+6:
+ case D_X0+7:
+ return Yxr;
+
case D_NONE:
return Ynone;
@@ -585,7 +607,7 @@ asmand(Adr *a, int r)
asmidx(a->scale, a->index, t);
goto putrelv;
}
- if(t >= D_AL && t <= D_F0+7) {
+ if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
if(v)
goto bad;
*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
@@ -772,19 +794,71 @@ uchar ymovtab[] =
0
};
+// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
+// which is not referenced in a->type.
+// If a is empty, it returns BX to account for MULB-like instructions
+// that might use DX and AX.
int
-isax(Adr *a)
+byteswapreg(Adr *a)
{
+ int cana, canb, canc, cand;
+
+ cana = canb = canc = cand = 1;
switch(a->type) {
+ case D_NONE:
+ cana = cand = 0;
+ break;
case D_AX:
case D_AL:
case D_AH:
case D_INDIR+D_AX:
- return 1;
+ cana = 0;
+ break;
+ case D_BX:
+ case D_BL:
+ case D_BH:
+ case D_INDIR+D_BX:
+ canb = 0;
+ break;
+ case D_CX:
+ case D_CL:
+ case D_CH:
+ case D_INDIR+D_CX:
+ canc = 0;
+ break;
+ case D_DX:
+ case D_DL:
+ case D_DH:
+ case D_INDIR+D_DX:
+ cand = 0;
+ break;
+ }
+ switch(a->index) {
+ case D_AX:
+ cana = 0;
+ break;
+ case D_BX:
+ canb = 0;
+ break;
+ case D_CX:
+ canc = 0;
+ break;
+ case D_DX:
+ cand = 0;
+ break;
}
- if(a->index == D_AX)
- return 1;
+ if(cana)
+ return D_AX;
+ if(canb)
+ return D_BX;
+ if(canc)
+ return D_CX;
+ if(cand)
+ return D_DX;
+
+ diag("impossible byte register");
+ errorexit();
return 0;
}
@@ -827,13 +901,37 @@ subreg(Prog *p, int from, int to)
print("%P\n", p);
}
+static int
+mediaop(Optab *o, int op, int osize, int z)
+{
+ switch(op){
+ case Pm:
+ case Pe:
+ case Pf2:
+ case Pf3:
+ if(osize != 1){
+ if(op != Pm)
+ *andptr++ = op;
+ *andptr++ = Pm;
+ op = o->op[++z];
+ break;
+ }
+ default:
+ if(andptr == and || andptr[-1] != Pm)
+ *andptr++ = Pm;
+ break;
+ }
+ *andptr++ = op;
+ return z;
+}
+
void
doasm(Prog *p)
{
Optab *o;
Prog *q, pp;
uchar *t;
- int z, op, ft, tt;
+ int z, op, ft, tt, breg;
int32 v, pre;
Reloc rel, *r;
Adr *a;
@@ -873,6 +971,12 @@ found:
*andptr++ = Pm;
break;
+ case Pf2: /* xmm opcode escape */
+ case Pf3:
+ *andptr++ = o->prefix;
+ *andptr++ = Pm;
+ break;
+
case Pm: /* opcode escape */
*andptr++ = Pm;
break;
@@ -904,6 +1008,17 @@ found:
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]);
+ break;
+
+ case Zm_r_i_xm:
+ mediaop(o, op, t[3], z);
+ asmand(&p->from, reg[p->to.type]);
+ *andptr++ = p->to.offset;
+ break;
+
case Zaut_r:
*andptr++ = 0x8d; /* leal */
if(p->from.type != D_ADDR)
@@ -927,6 +1042,17 @@ found:
asmand(&p->to, reg[p->from.type]);
break;
+ case Zr_m_xm:
+ mediaop(o, op, t[3], z);
+ asmand(&p->to, reg[p->from.type]);
+ break;
+
+ case Zr_m_i_xm:
+ mediaop(o, op, t[3], z);
+ asmand(&p->to, reg[p->from.type]);
+ *andptr++ = p->from.offset;
+ break;
+
case Zo_m:
*andptr++ = op;
asmand(&p->to, o->op[z+1]);
@@ -1198,13 +1324,13 @@ bad:
pp = *p;
z = p->from.type;
if(z >= D_BP && z <= D_DI) {
- if(isax(&p->to)) {
+ if((breg = byteswapreg(&p->to)) != D_AX) {
*andptr++ = 0x87; /* xchg lhs,bx */
- asmand(&p->from, reg[D_BX]);
- subreg(&pp, z, D_BX);
+ asmand(&p->from, reg[breg]);
+ subreg(&pp, z, breg);
doasm(&pp);
*andptr++ = 0x87; /* xchg lhs,bx */
- asmand(&p->from, reg[D_BX]);
+ asmand(&p->from, reg[breg]);
} else {
*andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
subreg(&pp, z, D_AX);
@@ -1215,13 +1341,13 @@ bad:
}
z = p->to.type;
if(z >= D_BP && z <= D_DI) {
- if(isax(&p->from)) {
+ if((breg = byteswapreg(&p->from)) != D_AX) {
*andptr++ = 0x87; /* xchg rhs,bx */
- asmand(&p->to, reg[D_BX]);
- subreg(&pp, z, D_BX);
+ asmand(&p->to, reg[breg]);
+ subreg(&pp, z, breg);
doasm(&pp);
*andptr++ = 0x87; /* xchg rhs,bx */
- asmand(&p->to, reg[D_BX]);
+ asmand(&p->to, reg[breg]);
} else {
*andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
subreg(&pp, z, D_AX);