diff options
Diffstat (limited to 'src/cmd/6l')
-rw-r--r-- | src/cmd/6l/6.out.h | 44 | ||||
-rw-r--r-- | src/cmd/6l/asm.c | 299 | ||||
-rw-r--r-- | src/cmd/6l/l.h | 374 | ||||
-rw-r--r-- | src/cmd/6l/list.c | 396 | ||||
-rw-r--r-- | src/cmd/6l/obj.c | 701 | ||||
-rw-r--r-- | src/cmd/6l/optab.c | 1369 | ||||
-rw-r--r-- | src/cmd/6l/pass.c | 991 | ||||
-rw-r--r-- | src/cmd/6l/prof.c | 171 | ||||
-rw-r--r-- | src/cmd/6l/span.c | 1846 |
9 files changed, 209 insertions, 5982 deletions
diff --git a/src/cmd/6l/6.out.h b/src/cmd/6l/6.out.h index 5fa73a65b..1e2a1488f 100644 --- a/src/cmd/6l/6.out.h +++ b/src/cmd/6l/6.out.h @@ -762,6 +762,10 @@ enum as AFUNCDATA, APCDATA, ACHECKNIL, + AVARDEF, + AVARKILL, + ADUFFCOPY, + ADUFFZERO, ALAST }; @@ -846,27 +850,21 @@ enum D_DR = 95, D_TR = 103, - D_NONE = 111, + D_TLS = 111, + D_NONE = 112, - D_BRANCH = 112, - D_EXTERN = 113, - D_STATIC = 114, - D_AUTO = 115, - D_PARAM = 116, - D_CONST = 117, - D_FCONST = 118, - D_SCONST = 119, - D_ADDR = 120, - - D_FILE, - D_FILE1, + D_BRANCH = 113, + D_EXTERN = 114, + D_STATIC = 115, + D_AUTO = 116, + D_PARAM = 117, + D_CONST = 118, + D_FCONST = 119, + D_SCONST = 120, + D_ADDR = 121, D_INDIR, /* additive */ - D_SIZE = D_INDIR + D_INDIR, /* 6l internal */ - D_PCREL, - D_TLS, - T_TYPE = 1<<0, T_INDEX = 1<<1, T_OFFSET = 1<<2, @@ -890,15 +888,3 @@ enum * this is the ranlib header */ #define SYMDEF "__.GOSYMDEF" - -/* - * this is the simulated IEEE floating point - */ -typedef struct ieee Ieee; -struct ieee -{ - int32 l; /* contains ls-man 0xffffffff */ - int32 h; /* contains sign 0x80000000 - exp 0x7ff00000 - ms-man 0x000fffff */ -}; diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index a09cc9727..e251e32ca 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -44,49 +44,22 @@ char freebsddynld[] = "/libexec/ld-elf.so.1"; char openbsddynld[] = "/usr/libexec/ld.so"; char netbsddynld[] = "/libexec/ld.elf_so"; char dragonflydynld[] = "/usr/libexec/ld-elf.so.2"; +char solarisdynld[] = "/lib/amd64/ld.so.1"; char zeroes[32]; -vlong -entryvalue(void) -{ - char *a; - Sym *s; - - a = INITENTRY; - if(*a >= '0' && *a <= '9') - return atolwhex(a); - s = lookup(a, 0); - if(s->type == 0) - return INITTEXT; - if(s->type != STEXT) - diag("entry not text: %s", s->name); - return s->value; -} - -vlong -datoff(vlong addr) -{ - if(addr >= segdata.vaddr) - return addr - segdata.vaddr + segdata.fileoff; - if(addr >= segtext.vaddr) - return addr - segtext.vaddr + segtext.fileoff; - diag("datoff %#llx", addr); - return 0; -} - static int needlib(char *name) { char *p; - Sym *s; + LSym *s; if(*name == '\0') return 0; /* reuse hash code in symbol table */ p = smprint(".elfload.%s", name); - s = lookup(p, 0); + s = linklookup(ctxt, p, 0); free(p); if(s->type == 0) { s->type = 100; // avoid SDATA, etc. @@ -97,24 +70,24 @@ needlib(char *name) int nelfsym = 1; -static void addpltsym(Sym*); -static void addgotsym(Sym*); +static void addpltsym(LSym*); +static void addgotsym(LSym*); void -adddynrela(Sym *rela, Sym *s, Reloc *r) +adddynrela(LSym *rela, LSym *s, Reloc *r) { - addaddrplus(rela, s, r->off); - adduint64(rela, R_X86_64_RELATIVE); - addaddrplus(rela, r->sym, r->add); // Addend + addaddrplus(ctxt, rela, s, r->off); + adduint64(ctxt, rela, R_X86_64_RELATIVE); + addaddrplus(ctxt, rela, r->sym, r->add); // Addend } void -adddynrel(Sym *s, Reloc *r) +adddynrel(LSym *s, Reloc *r) { - Sym *targ, *rela, *got; + LSym *targ, *rela, *got; targ = r->sym; - cursym = s; + ctxt->cursym = s; switch(r->type) { default: @@ -130,16 +103,16 @@ adddynrel(Sym *s, Reloc *r) diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name); if(targ->type == 0 || targ->type == SXREF) diag("unknown symbol %s in pcrel", targ->name); - r->type = D_PCREL; + r->type = R_PCREL; r->add += 4; return; case 256 + R_X86_64_PLT32: - r->type = D_PCREL; + r->type = R_PCREL; r->add += 4; if(targ->type == SDYNIMPORT) { addpltsym(targ); - r->sym = lookup(".plt", 0); + r->sym = linklookup(ctxt, ".plt", 0); r->add += targ->plt; } return; @@ -150,7 +123,7 @@ adddynrel(Sym *s, Reloc *r) if(r->off >= 2 && s->p[r->off-2] == 0x8b) { // turn MOVQ of GOT entry into LEAQ of symbol itself s->p[r->off-2] = 0x8d; - r->type = D_PCREL; + r->type = R_PCREL; r->add += 4; return; } @@ -158,8 +131,8 @@ adddynrel(Sym *s, Reloc *r) // TODO: just needs relocation, no need to put in .dynsym } addgotsym(targ); - r->type = D_PCREL; - r->sym = lookup(".got", 0); + r->type = R_PCREL; + r->sym = linklookup(ctxt, ".got", 0); r->add += 4; r->add += targ->got; return; @@ -167,7 +140,7 @@ adddynrel(Sym *s, Reloc *r) case 256 + R_X86_64_64: if(targ->type == SDYNIMPORT) diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name); - r->type = D_ADDR; + r->type = R_ADDR; return; // Handle relocations found in Mach-O object files. @@ -175,7 +148,7 @@ adddynrel(Sym *s, Reloc *r) case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 0: case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0: // TODO: What is the difference between all these? - r->type = D_ADDR; + r->type = R_ADDR; if(targ->type == SDYNIMPORT) diag("unexpected reloc for dynamic symbol %s", targ->name); return; @@ -183,9 +156,9 @@ adddynrel(Sym *s, Reloc *r) case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1: if(targ->type == SDYNIMPORT) { addpltsym(targ); - r->sym = lookup(".plt", 0); + r->sym = linklookup(ctxt, ".plt", 0); r->add = targ->plt; - r->type = D_PCREL; + r->type = R_PCREL; return; } // fall through @@ -194,7 +167,7 @@ adddynrel(Sym *s, Reloc *r) case 512 + MACHO_X86_64_RELOC_SIGNED_1*2 + 1: case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1: case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1: - r->type = D_PCREL; + r->type = R_PCREL; if(targ->type == SDYNIMPORT) diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name); return; @@ -208,7 +181,7 @@ adddynrel(Sym *s, Reloc *r) return; } s->p[r->off-2] = 0x8d; - r->type = D_PCREL; + r->type = R_PCREL; return; } // fall through @@ -216,8 +189,8 @@ adddynrel(Sym *s, Reloc *r) if(targ->type != SDYNIMPORT) diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); addgotsym(targ); - r->type = D_PCREL; - r->sym = lookup(".got", 0); + r->type = R_PCREL; + r->sym = linklookup(ctxt, ".got", 0); r->add += targ->got; return; } @@ -227,24 +200,34 @@ adddynrel(Sym *s, Reloc *r) return; switch(r->type) { - case D_PCREL: + case R_CALL: + case R_PCREL: addpltsym(targ); - r->sym = lookup(".plt", 0); + r->sym = linklookup(ctxt, ".plt", 0); r->add = targ->plt; return; - case D_ADDR: + case R_ADDR: + if(s->type == STEXT && iself) { + // The code is asking for the address of an external + // function. We provide it with the address of the + // correspondent GOT symbol. + addgotsym(targ); + r->sym = linklookup(ctxt, ".got", 0); + r->add += targ->got; + return; + } if(s->type != SDATA) break; if(iself) { - adddynsym(targ); - rela = lookup(".rela", 0); - addaddrplus(rela, s, r->off); + adddynsym(ctxt, targ); + rela = linklookup(ctxt, ".rela", 0); + addaddrplus(ctxt, rela, s, r->off); if(r->siz == 8) - adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_64_64)); + adduint64(ctxt, rela, ELF64_R_INFO(targ->dynid, R_X86_64_64)); else - adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_64_32)); - adduint64(rela, r->add); + adduint64(ctxt, rela, ELF64_R_INFO(targ->dynid, R_X86_64_32)); + adduint64(ctxt, rela, r->add); r->type = 256; // ignore during relocsym return; } @@ -259,22 +242,22 @@ adddynrel(Sym *s, Reloc *r) // just in case the C code assigns to the variable, // and of course it only works for single pointers, // but we only need to support cgo and that's all it needs. - adddynsym(targ); - got = lookup(".got", 0); + adddynsym(ctxt, targ); + got = linklookup(ctxt, ".got", 0); s->type = got->type | SSUB; s->outer = got; s->sub = got->sub; got->sub = s; s->value = got->size; - adduint64(got, 0); - adduint32(lookup(".linkedit.got", 0), targ->dynid); + adduint64(ctxt, got, 0); + adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), targ->dynid); r->type = 256; // ignore during relocsym return; } break; } - cursym = s; + ctxt->cursym = s; diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type); } @@ -290,7 +273,7 @@ elfreloc1(Reloc *r, vlong sectoff) default: return -1; - case D_ADDR: + case R_ADDR: if(r->siz == 4) VPUT(R_X86_64_32 | (uint64)elfsym<<32); else if(r->siz == 8) @@ -299,14 +282,25 @@ elfreloc1(Reloc *r, vlong sectoff) return -1; break; - case D_PCREL: + case R_TLS_LE: if(r->siz == 4) - VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); + VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32); else return -1; break; + + case R_CALL: + case R_PCREL: + if(r->siz == 4) { + if(r->xsym->type == SDYNIMPORT) + VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32); + else + VPUT(R_X86_64_PC32 | (uint64)elfsym<<32); + } else + return -1; + break; - case D_TLS: + case R_TLS: if(r->siz == 4) { if(flag_shared) VPUT(R_X86_64_GOTTPOFF | (uint64)elfsym<<32); @@ -325,7 +319,7 @@ int machoreloc1(Reloc *r, vlong sectoff) { uint32 v; - Sym *rs; + LSym *rs; rs = r->xsym; @@ -347,10 +341,11 @@ machoreloc1(Reloc *r, vlong sectoff) switch(r->type) { default: return -1; - case D_ADDR: + case R_ADDR: v |= MACHO_X86_64_RELOC_UNSIGNED<<28; break; - case D_PCREL: + case R_CALL: + case R_PCREL: v |= 1<<24; // pc-relative bit v |= MACHO_X86_64_RELOC_BRANCH<<28; break; @@ -379,7 +374,7 @@ machoreloc1(Reloc *r, vlong sectoff) } int -archreloc(Reloc *r, Sym *s, vlong *val) +archreloc(Reloc *r, LSym *s, vlong *val) { USED(r); USED(s); @@ -390,68 +385,68 @@ archreloc(Reloc *r, Sym *s, vlong *val) void elfsetupplt(void) { - Sym *plt, *got; + LSym *plt, *got; - plt = lookup(".plt", 0); - got = lookup(".got.plt", 0); + plt = linklookup(ctxt, ".plt", 0); + got = linklookup(ctxt, ".got.plt", 0); if(plt->size == 0) { // pushq got+8(IP) - adduint8(plt, 0xff); - adduint8(plt, 0x35); - addpcrelplus(plt, got, 8); + adduint8(ctxt, plt, 0xff); + adduint8(ctxt, plt, 0x35); + addpcrelplus(ctxt, plt, got, 8); // jmpq got+16(IP) - adduint8(plt, 0xff); - adduint8(plt, 0x25); - addpcrelplus(plt, got, 16); + adduint8(ctxt, plt, 0xff); + adduint8(ctxt, plt, 0x25); + addpcrelplus(ctxt, plt, got, 16); // nopl 0(AX) - adduint32(plt, 0x00401f0f); + adduint32(ctxt, plt, 0x00401f0f); // assume got->size == 0 too - addaddrplus(got, lookup(".dynamic", 0), 0); - adduint64(got, 0); - adduint64(got, 0); + addaddrplus(ctxt, got, linklookup(ctxt, ".dynamic", 0), 0); + adduint64(ctxt, got, 0); + adduint64(ctxt, got, 0); } } static void -addpltsym(Sym *s) +addpltsym(LSym *s) { if(s->plt >= 0) return; - adddynsym(s); + adddynsym(ctxt, s); if(iself) { - Sym *plt, *got, *rela; + LSym *plt, *got, *rela; - plt = lookup(".plt", 0); - got = lookup(".got.plt", 0); - rela = lookup(".rela.plt", 0); + plt = linklookup(ctxt, ".plt", 0); + got = linklookup(ctxt, ".got.plt", 0); + rela = linklookup(ctxt, ".rela.plt", 0); if(plt->size == 0) elfsetupplt(); // jmpq *got+size(IP) - adduint8(plt, 0xff); - adduint8(plt, 0x25); - addpcrelplus(plt, got, got->size); + adduint8(ctxt, plt, 0xff); + adduint8(ctxt, plt, 0x25); + addpcrelplus(ctxt, plt, got, got->size); // add to got: pointer to current pos in plt - addaddrplus(got, plt, plt->size); + addaddrplus(ctxt, got, plt, plt->size); // pushq $x - adduint8(plt, 0x68); - adduint32(plt, (got->size-24-8)/8); + adduint8(ctxt, plt, 0x68); + adduint32(ctxt, plt, (got->size-24-8)/8); // jmpq .plt - adduint8(plt, 0xe9); - adduint32(plt, -(plt->size+4)); + adduint8(ctxt, plt, 0xe9); + adduint32(ctxt, plt, -(plt->size+4)); // rela - addaddrplus(rela, got, got->size-8); - adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT)); - adduint64(rela, 0); + addaddrplus(ctxt, rela, got, got->size-8); + adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_JMP_SLOT)); + adduint64(ctxt, rela, 0); s->plt = plt->size - 16; } else if(HEADTYPE == Hdarwin) { @@ -465,53 +460,53 @@ addpltsym(Sym *s) // http://networkpx.blogspot.com/2009/09/about-lcdyldinfoonly-command.html // has details about what we're avoiding. - Sym *plt; + LSym *plt; addgotsym(s); - plt = lookup(".plt", 0); + plt = linklookup(ctxt, ".plt", 0); - adduint32(lookup(".linkedit.plt", 0), s->dynid); + adduint32(ctxt, linklookup(ctxt, ".linkedit.plt", 0), s->dynid); // jmpq *got+size(IP) s->plt = plt->size; - adduint8(plt, 0xff); - adduint8(plt, 0x25); - addpcrelplus(plt, lookup(".got", 0), s->got); + adduint8(ctxt, plt, 0xff); + adduint8(ctxt, plt, 0x25); + addpcrelplus(ctxt, plt, linklookup(ctxt, ".got", 0), s->got); } else { diag("addpltsym: unsupported binary format"); } } static void -addgotsym(Sym *s) +addgotsym(LSym *s) { - Sym *got, *rela; + LSym *got, *rela; if(s->got >= 0) return; - adddynsym(s); - got = lookup(".got", 0); + adddynsym(ctxt, s); + got = linklookup(ctxt, ".got", 0); s->got = got->size; - adduint64(got, 0); + adduint64(ctxt, got, 0); if(iself) { - rela = lookup(".rela", 0); - addaddrplus(rela, got, s->got); - adduint64(rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT)); - adduint64(rela, 0); + rela = linklookup(ctxt, ".rela", 0); + addaddrplus(ctxt, rela, got, s->got); + adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_X86_64_GLOB_DAT)); + adduint64(ctxt, rela, 0); } else if(HEADTYPE == Hdarwin) { - adduint32(lookup(".linkedit.got", 0), s->dynid); + adduint32(ctxt, linklookup(ctxt, ".linkedit.got", 0), s->dynid); } else { diag("addgotsym: unsupported binary format"); } } void -adddynsym(Sym *s) +adddynsym(Link *ctxt, LSym *s) { - Sym *d; + LSym *d; int t; char *name; @@ -521,24 +516,24 @@ adddynsym(Sym *s) if(iself) { s->dynid = nelfsym++; - d = lookup(".dynsym", 0); + d = linklookup(ctxt, ".dynsym", 0); name = s->extname; - adduint32(d, addstring(lookup(".dynstr", 0), name)); + adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name)); /* type */ t = STB_GLOBAL << 4; if(s->cgoexport && (s->type&SMASK) == STEXT) t |= STT_FUNC; else t |= STT_OBJECT; - adduint8(d, t); + adduint8(ctxt, d, t); /* reserved */ - adduint8(d, 0); + adduint8(ctxt, d, 0); /* section where symbol is defined */ if(s->type == SDYNIMPORT) - adduint16(d, SHN_UNDEF); + adduint16(ctxt, d, SHN_UNDEF); else { switch(s->type) { default: @@ -555,21 +550,21 @@ adddynsym(Sym *s) t = 14; break; } - adduint16(d, t); + adduint16(ctxt, d, t); } /* value */ if(s->type == SDYNIMPORT) - adduint64(d, 0); + adduint64(ctxt, d, 0); else - addaddr(d, s); + addaddr(ctxt, d, s); /* size of object */ - adduint64(d, s->size); + adduint64(ctxt, d, s->size); if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) { - elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, - addstring(lookup(".dynstr", 0), s->dynimplib)); + elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, + addstring(linklookup(ctxt, ".dynstr", 0), s->dynimplib)); } } else if(HEADTYPE == Hdarwin) { diag("adddynsym: missed symbol %s (%s)", s->name, s->extname); @@ -583,16 +578,16 @@ adddynsym(Sym *s) void adddynlib(char *lib) { - Sym *s; + LSym *s; if(!needlib(lib)) return; if(iself) { - s = lookup(".dynstr", 0); + s = linklookup(ctxt, ".dynstr", 0); if(s->size == 0) addstring(s, ""); - elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, lib)); + elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib)); } else if(HEADTYPE == Hdarwin) { machoadddynlib(lib); } else { @@ -607,7 +602,7 @@ asmb(void) int i; vlong vl, symo, dwarfoff, machlink; Section *sect; - Sym *sym; + LSym *sym; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); @@ -662,8 +657,7 @@ asmb(void) switch(HEADTYPE) { default: diag("unknown header type %d", HEADTYPE); - case Hplan9x32: - case Hplan9x64: + case Hplan9: case Helf: break; case Hdarwin: @@ -674,8 +668,10 @@ asmb(void) case Hnetbsd: case Hopenbsd: case Hdragonfly: + case Hsolaris: debug['8'] = 1; /* 64-bit addresses */ break; + case Hnacl: case Hwindows: break; } @@ -690,7 +686,7 @@ asmb(void) Bflush(&bso); switch(HEADTYPE) { default: - case Hplan9x64: + case Hplan9: case Helf: debug['s'] = 1; symo = HEADR+segtext.len+segdata.filelen; @@ -703,6 +699,8 @@ asmb(void) case Hnetbsd: case Hopenbsd: case Hdragonfly: + case Hsolaris: + case Hnacl: symo = rnd(HEADR+segtext.len, INITRND)+rnd(segrodata.len, INITRND)+segdata.filelen; symo = rnd(symo, INITRND); break; @@ -729,11 +727,11 @@ asmb(void) elfemitreloc(); } break; - case Hplan9x64: + case Hplan9: asmplan9sym(); cflush(); - sym = lookup("pclntab", 0); + sym = linklookup(ctxt, "pclntab", 0); if(sym != nil) { lcsize = sym->np; for(i=0; i < lcsize; i++) @@ -761,7 +759,7 @@ asmb(void) cseek(0L); switch(HEADTYPE) { default: - case Hplan9x64: /* plan9 */ + case Hplan9: /* plan9 */ magic = 4*26*26+7; magic |= 0x00008000; /* fat header */ lputb(magic); /* magic */ @@ -775,17 +773,6 @@ asmb(void) lputb(lcsize); /* line offsets */ vputb(vl); /* va of entry */ break; - case Hplan9x32: /* plan9 */ - magic = 4*26*26+7; - lputb(magic); /* magic */ - lputb(segtext.filelen); /* sizes */ - lputb(segdata.filelen); - lputb(segdata.len - segdata.filelen); - lputb(symsize); /* nsyms */ - lputb(entryvalue()); /* va of entry */ - lputb(spsize); /* sp offsets */ - lputb(lcsize); /* line offsets */ - break; case Hdarwin: asmbmacho(); break; @@ -794,6 +781,8 @@ asmb(void) case Hnetbsd: case Hopenbsd: case Hdragonfly: + case Hsolaris: + case Hnacl: asmbelf(symo); break; case Hwindows: diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index ecab867e4..7303910a6 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -31,6 +31,7 @@ #include <u.h> #include <libc.h> #include <bio.h> +#include <link.h> #include "6.out.h" #ifndef EXTERN @@ -40,8 +41,6 @@ enum { thechar = '6', - PtrSize = 8, - IntSize = 8, MaxAlign = 32, // max data alignment // Loop alignment constants: @@ -63,147 +62,13 @@ enum FuncAlign = 16 }; -#define P ((Prog*)0) -#define S ((Sym*)0) -#define TNAME (cursym?cursym->name:noname) - -typedef struct Adr Adr; -typedef struct Prog Prog; -typedef struct Sym Sym; -typedef struct Auto Auto; -typedef struct Optab Optab; -typedef struct Movtab Movtab; -typedef struct Reloc Reloc; - -struct Adr -{ - union - { - vlong u0offset; - char u0scon[8]; - Prog *u0cond; /* not used, but should be D_BRANCH */ - Ieee u0ieee; - char *u0sbig; - } u0; - Sym* sym; - short type; - char index; - char scale; -}; - -#define offset u0.u0offset -#define scon u0.u0scon -#define cond u0.u0cond -#define ieee u0.u0ieee -#define sbig u0.u0sbig - -struct Reloc -{ - int32 off; - uchar siz; - uchar done; - int32 type; - int64 add; - int64 xadd; - Sym* sym; - Sym* xsym; -}; - -struct Prog -{ - Adr from; - Adr to; - Prog* forwd; - Prog* comefrom; - Prog* link; - Prog* pcond; /* work on this */ - vlong pc; - int32 spadj; - int32 line; - short as; - char ft; /* oclass cache */ - char tt; - uchar mark; /* work on these */ - uchar back; - - char width; /* fake for DATA */ - char mode; /* 16, 32, or 64 */ -}; -#define datasize from.scale -#define textflag from.scale -#define iscall(p) ((p)->as == ACALL) - -struct Auto -{ - Sym* asym; - Auto* link; - int32 aoffset; - short type; - Sym* gotype; -}; -struct Sym -{ - char* name; - char* extname; // name used in external object files - short type; - short version; - uchar dupok; - uchar reachable; - uchar cgoexport; - uchar special; - uchar stkcheck; - uchar hide; - int32 dynid; - int32 sig; - int32 plt; - int32 got; - int32 align; // if non-zero, required alignment in bytes - int32 elfsym; - 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 SSUB list - Sym* outer; // container of sub - Sym* reachparent; - Sym* queue; - vlong value; - vlong size; - Sym* gotype; - char* file; - char* dynimplib; - char* dynimpvers; - struct Section* sect; - struct Hist* hist; // for ATEXT - - // STEXT - Auto* autom; - Prog* text; - - // SDATA, SBSS - uchar* p; - int32 np; - int32 maxp; - Reloc* r; - int32 nr; - int32 maxr; -}; -struct Optab -{ - short as; - uchar* ytab; - uchar prefix; - uchar op[23]; -}; -struct Movtab -{ - short as; - uchar ft; - uchar tt; - uchar code; - uchar op[4]; -}; +EXTERN int PtrSize; +EXTERN int IntSize; +EXTERN int RegSize; +#define P ((Prog*)0) +#define S ((LSym*)0) +#define TNAME (ctxt->cursym?ctxt->cursym->name:noname) enum { MINSIZ = 8, @@ -211,239 +76,42 @@ enum MINLC = 1, MAXIO = 8192, MAXHIST = 40, /* limit of path elements for history symbols */ - - Yxxx = 0, - Ynone, - Yi0, - Yi1, - Yi8, - Ys32, - Yi32, - Yi64, - Yiauto, - Yal, - Ycl, - Yax, - Ycx, - Yrb, - Yrl, - Yrf, - Yf0, - Yrx, - Ymb, - Yml, - Ym, - Ybr, - Ycol, - - Ycs, Yss, Yds, Yes, Yfs, Ygs, - Ygdtr, Yidtr, Yldtr, Ymsw, Ytask, - Ycr0, Ycr1, Ycr2, Ycr3, Ycr4, Ycr5, Ycr6, Ycr7, Ycr8, - Ydr0, Ydr1, Ydr2, Ydr3, Ydr4, Ydr5, Ydr6, Ydr7, - Ytr0, Ytr1, Ytr2, Ytr3, Ytr4, Ytr5, Ytr6, Ytr7, Yrl32, Yrl64, - Ymr, Ymm, - Yxr, Yxm, - Ymax, - - Zxxx = 0, - - Zlit, - Zlitm_r, - Z_rp, - Zbr, - Zcall, - Zib_, - Zib_rp, - Zibo_m, - Zibo_m_xm, - Zil_, - Zil_rp, - Ziq_rp, - Zilo_m, - Ziqo_m, - Zjmp, - Zloop, - Zo_iw, - Zm_o, - Zm_r, - Zm2_r, - Zm_r_xm, - Zm_r_i_xm, - Zm_r_3d, - Zm_r_xm_nr, - Zr_m_xm_nr, - Zibm_r, /* mmx1,mmx2/mem64,imm8 */ - Zmb_r, - Zaut_r, - Zo_m, - Zo_m64, - Zpseudo, - Zr_m, - Zr_m_xm, - Zr_m_i_xm, - Zrp_, - Z_ib, - Z_il, - Zm_ibo, - Zm_ilo, - Zib_rr, - Zil_rr, - Zclr, - Zbyte, - Zmax, - - Px = 0, - P32 = 0x32, /* 32-bit only */ - Pe = 0x66, /* operand escape */ - Pm = 0x0f, /* 2byte opcode escape */ - Pq = 0xff, /* both escapes: 66 0f */ - Pb = 0xfe, /* byte operands */ - Pf2 = 0xf2, /* xmm escape 1: f2 0f */ - Pf3 = 0xf3, /* xmm escape 2: f3 0f */ - Pq3 = 0x67, /* xmm escape 3: 66 48 0f */ - Pw = 0x48, /* Rex.w */ - Py = 0x80, /* defaults to 64-bit mode */ - - Rxf = 1<<9, /* internal flag for Rxr on from */ - Rxt = 1<<8, /* internal flag for Rxr on to */ - Rxw = 1<<3, /* =1, 64-bit operand size */ - Rxr = 1<<2, /* extend modrm reg */ - Rxx = 1<<1, /* extend sib index */ - Rxb = 1<<0, /* extend modrm r/m, sib base, or opcode reg */ - - Maxand = 10, /* in -a output width of the byte codes */ }; -#pragma varargck type "A" uint -#pragma varargck type "D" Adr* #pragma varargck type "I" uchar* -#pragma varargck type "P" Prog* -#pragma varargck type "R" int -#pragma varargck type "S" char* -#pragma varargck type "i" char* -EXTERN int32 HEADR; -EXTERN int32 HEADTYPE; -EXTERN int32 INITRND; -EXTERN int64 INITTEXT; -EXTERN int64 INITDAT; -EXTERN char* INITENTRY; /* entry point */ -EXTERN char* pcstr; -EXTERN Auto* curauto; -EXTERN Auto* curhist; -EXTERN Prog* curp; -EXTERN Sym* cursym; -EXTERN Sym* datap; +EXTERN LSym* datap; EXTERN int debug[128]; EXTERN char literal[32]; -EXTERN Sym* textp; -EXTERN Sym* etextp; -EXTERN char ycover[Ymax*Ymax]; -EXTERN uchar* andptr; -EXTERN uchar* rexptr; -EXTERN uchar and[30]; -EXTERN int reg[D_NONE]; -EXTERN int regrex[D_NONE+1]; EXTERN int32 lcsize; -EXTERN int nerrors; -EXTERN char* noname; -EXTERN char* outfile; -EXTERN vlong pc; -EXTERN char* interpreter; EXTERN char* rpath; EXTERN int32 spsize; -EXTERN Sym* symlist; +EXTERN LSym* symlist; EXTERN int32 symsize; -EXTERN int tlsoffset; -EXTERN Prog zprg; -EXTERN int dtype; -EXTERN char* paramspace; -EXTERN Sym* adrgotype; // type symbol on last Adr read -EXTERN Sym* fromgotype; // type symbol on last p->from read EXTERN vlong textstksiz; EXTERN vlong textarg; -extern Optab optab[]; -extern Optab* opindex[]; -extern char* anames[]; - -int Aconv(Fmt*); -int Dconv(Fmt*); -int Iconv(Fmt*); -int Pconv(Fmt*); -int Rconv(Fmt*); -int Sconv(Fmt*); -void addhist(int32, int); -void addstackmark(void); -Prog* appendp(Prog*); +int Iconv(Fmt *fp); +void adddynlib(char *lib); +void adddynrel(LSym *s, Reloc *r); +void adddynrela(LSym *rela, LSym *s, Reloc *r); +void adddynsym(Link *ctxt, LSym *s); +int archreloc(Reloc *r, LSym *s, vlong *val); void asmb(void); -void asmdyn(void); -void asmins(Prog*); -void asmsym(void); -void asmelfsym(void); -vlong atolwhex(char*); -Prog* brchain(Prog*); -Prog* brloop(Prog*); -void buildop(void); -Prog* copyp(Prog*); -double cputime(void); -void datblk(int32, int32); -void deadcode(void); -void diag(char*, ...); -void dodata(void); -void doelf(void); -void domacho(void); -void doprof1(void); -void doprof2(void); -void dostkoff(void); -vlong entryvalue(void); -void follow(void); -void gethunk(void); -void gotypestrings(void); +int elfreloc1(Reloc *r, vlong sectoff); +void elfsetupplt(void); void listinit(void); -Sym* lookup(char*, int); -void lputb(int32); -void lputl(int32); -void instinit(void); -void main(int, char*[]); -void* mysbrk(uint32); -Prog* newtext(Prog*, Sym*); -void nopout(Prog*); -int opsize(Prog*); -void patch(void); -Prog* prg(void); -void parsetextconst(vlong); -int relinv(int); -vlong rnd(vlong, vlong); -void span(void); -void undef(void); -vlong symaddr(Sym*); -void vputb(uint64); -void vputl(uint64); -void wputb(uint16); -void wputl(uint16); -void xdefine(char*, int, vlong); - -void machseg(char*, vlong, vlong, vlong, vlong, uint32, uint32, uint32, uint32); -void machsymseg(uint32, uint32); -void machsect(char*, char*, vlong, vlong, uint32, uint32, uint32, uint32, uint32); -void machstack(vlong); -void machdylink(void); -uint32 machheadr(void); +int machoreloc1(Reloc *r, vlong sectoff); +void main(int argc, char *argv[]); +void parsetextconst(vlong arg); +vlong rnd(vlong v, vlong r); /* Native is little-endian */ #define LPUT(a) lputl(a) #define WPUT(a) wputl(a) #define VPUT(a) vputl(a) -#pragma varargck type "D" Adr* -#pragma varargck type "P" Prog* -#pragma varargck type "R" int -#pragma varargck type "Z" char* -#pragma varargck type "A" int -#pragma varargck argpos diag 1 - /* Used by ../ld/dwarf.c */ enum { diff --git a/src/cmd/6l/list.c b/src/cmd/6l/list.c index 5040e4327..d960fcc91 100644 --- a/src/cmd/6l/list.c +++ b/src/cmd/6l/list.c @@ -33,371 +33,14 @@ #include "l.h" #include "../ld/lib.h" -static Prog* bigP; - void listinit(void) { - - fmtinstall('R', Rconv); - fmtinstall('A', Aconv); - fmtinstall('D', Dconv); - fmtinstall('S', Sconv); - fmtinstall('P', Pconv); + listinit6(); fmtinstall('I', Iconv); } int -Pconv(Fmt *fp) -{ - Prog *p; - - p = va_arg(fp->args, Prog*); - bigP = p; - switch(p->as) { - case ATEXT: - if(p->from.scale) { - fmtprint(fp, "(%d) %A %D,%d,%lD", - p->line, p->as, &p->from, p->from.scale, &p->to); - break; - } - fmtprint(fp, "(%d) %A %D,%lD", - p->line, p->as, &p->from, &p->to); - break; - default: - fmtprint(fp, "(%d) %A %D,%D", - p->line, p->as, &p->from, &p->to); - break; - case ADATA: - case AINIT_: - case ADYNT_: - fmtprint(fp, "(%d) %A %D/%d,%D", - p->line, p->as, &p->from, p->from.scale, &p->to); - break; - } - bigP = P; - return 0; -} - -int -Aconv(Fmt *fp) -{ - int i; - - i = va_arg(fp->args, int); - return fmtstrcpy(fp, anames[i]); -} - -int -Dconv(Fmt *fp) -{ - char str[STRINGSZ], s[STRINGSZ]; - Adr *a; - int i; - - a = va_arg(fp->args, Adr*); - i = a->type; - - if(fp->flags & FmtLong) { - if(i != D_CONST) { - // ATEXT dst is not constant - snprint(str, sizeof(str), "!!%D", a); - goto brk; - } - parsetextconst(a->offset); - if(textarg == 0) { - snprint(str, sizeof(str), "$%lld", textstksiz); - goto brk; - } - snprint(str, sizeof(str), "$%lld-%lld", textstksiz, textarg); - goto brk; - } - - if(i >= D_INDIR) { - if(a->offset) - snprint(str, sizeof(str), "%lld(%R)", a->offset, i-D_INDIR); - else - snprint(str, sizeof(str), "(%R)", i-D_INDIR); - goto brk; - } - switch(i) { - - default: - if(a->offset) - snprint(str, sizeof(str), "$%lld,%R", a->offset, i); - else - snprint(str, sizeof(str), "%R", i); - break; - - case D_NONE: - str[0] = 0; - break; - - case D_BRANCH: - if(bigP != P && bigP->pcond != P) - if(a->sym != S) - snprint(str, sizeof(str), "%llux+%s", bigP->pcond->pc, - a->sym->name); - else - snprint(str, sizeof(str), "%llux", bigP->pcond->pc); - else - snprint(str, sizeof(str), "%lld(PC)", a->offset); - break; - - case D_EXTERN: - if(a->sym) { - snprint(str, sizeof(str), "%s+%lld(SB)", a->sym->name, a->offset); - break; - } - snprint(str, sizeof(str), "!!noname!!+%lld(SB)", a->offset); - break; - - case D_STATIC: - if(a->sym) { - snprint(str, sizeof(str), "%s<%d>+%lld(SB)", a->sym->name, - a->sym->version, a->offset); - break; - } - snprint(str, sizeof(str), "!!noname!!<999>+%lld(SB)", a->offset); - break; - - case D_AUTO: - if(a->sym) { - snprint(str, sizeof(str), "%s+%lld(SP)", a->sym->name, a->offset); - break; - } - snprint(str, sizeof(str), "!!noname!!+%lld(SP)", a->offset); - break; - - case D_PARAM: - if(a->sym) { - snprint(str, sizeof(str), "%s+%lld(%s)", a->sym->name, a->offset, paramspace); - break; - } - snprint(str, sizeof(str), "!!noname!!+%lld(%s)", a->offset, paramspace); - break; - - case D_CONST: - snprint(str, sizeof(str), "$%lld", a->offset); - break; - - case D_FCONST: - snprint(str, sizeof(str), "$(%.8ux,%.8ux)", a->ieee.h, a->ieee.l); - break; - - case D_SCONST: - snprint(str, sizeof(str), "$\"%S\"", a->scon); - break; - - case D_ADDR: - a->type = a->index; - a->index = D_NONE; - snprint(str, sizeof(str), "$%D", a); - a->index = a->type; - a->type = D_ADDR; - goto conv; - } -brk: - if(a->index != D_NONE) { - snprint(s, sizeof(s), "(%R*%d)", a->index, a->scale); - strcat(str, s); - } -conv: - fmtstrcpy(fp, str); -// if(a->gotype) -// fmtprint(fp, "«%s»", a->gotype->name); - return 0; - -} - -char* regstr[] = -{ - "AL", /* [D_AL] */ - "CL", - "DL", - "BL", - "SPB", - "BPB", - "SIB", - "DIB", - "R8B", - "R9B", - "R10B", - "R11B", - "R12B", - "R13B", - "R14B", - "R15B", - - "AX", /* [D_AX] */ - "CX", - "DX", - "BX", - "SP", - "BP", - "SI", - "DI", - "R8", - "R9", - "R10", - "R11", - "R12", - "R13", - "R14", - "R15", - - "AH", - "CH", - "DH", - "BH", - - "F0", /* [D_F0] */ - "F1", - "F2", - "F3", - "F4", - "F5", - "F6", - "F7", - - "M0", - "M1", - "M2", - "M3", - "M4", - "M5", - "M6", - "M7", - - "X0", - "X1", - "X2", - "X3", - "X4", - "X5", - "X6", - "X7", - "X8", - "X9", - "X10", - "X11", - "X12", - "X13", - "X14", - "X15", - - "CS", /* [D_CS] */ - "SS", - "DS", - "ES", - "FS", - "GS", - - "GDTR", /* [D_GDTR] */ - "IDTR", /* [D_IDTR] */ - "LDTR", /* [D_LDTR] */ - "MSW", /* [D_MSW] */ - "TASK", /* [D_TASK] */ - - "CR0", /* [D_CR] */ - "CR1", - "CR2", - "CR3", - "CR4", - "CR5", - "CR6", - "CR7", - "CR8", - "CR9", - "CR10", - "CR11", - "CR12", - "CR13", - "CR14", - "CR15", - - "DR0", /* [D_DR] */ - "DR1", - "DR2", - "DR3", - "DR4", - "DR5", - "DR6", - "DR7", - - "TR0", /* [D_TR] */ - "TR1", - "TR2", - "TR3", - "TR4", - "TR5", - "TR6", - "TR7", - - "NONE", /* [D_NONE] */ -}; - -int -Rconv(Fmt *fp) -{ - char str[STRINGSZ]; - int r; - - r = va_arg(fp->args, int); - if(r >= D_AL && r <= D_NONE) - snprint(str, sizeof(str), "%s", regstr[r-D_AL]); - else - snprint(str, sizeof(str), "gok(%d)", r); - - return fmtstrcpy(fp, str); -} - -int -Sconv(Fmt *fp) -{ - int i, c; - char str[STRINGSZ], *p, *a; - - a = va_arg(fp->args, char*); - p = str; - for(i=0; i<sizeof(double); i++) { - c = a[i] & 0xff; - if(c >= 'a' && c <= 'z' || - c >= 'A' && c <= 'Z' || - c >= '0' && c <= '9') { - *p++ = c; - continue; - } - *p++ = '\\'; - switch(c) { - default: - if(c < 040 || c >= 0177) - break; /* not portable */ - p[-1] = c; - continue; - case 0: - *p++ = 'z'; - continue; - case '\\': - case '"': - *p++ = c; - continue; - case '\n': - *p++ = 'n'; - continue; - case '\t': - *p++ = 't'; - continue; - } - *p++ = (c>>6) + '0'; - *p++ = ((c>>3) & 7) + '0'; - *p++ = (c & 7) + '0'; - } - *p = 0; - return fmtstrcpy(fp, str); -} - -int Iconv(Fmt *fp) { int i, n; @@ -422,40 +65,3 @@ Iconv(Fmt *fp) free(s); return 0; } - -void -diag(char *fmt, ...) -{ - char buf[1024], *tn, *sep; - va_list arg; - - tn = ""; - sep = ""; - if(cursym != S) { - tn = cursym->name; - sep = ": "; - } - va_start(arg, fmt); - vseprint(buf, buf+sizeof(buf), fmt, arg); - va_end(arg); - print("%s%s%s\n", tn, sep, buf); - - nerrors++; - if(nerrors > 20) { - print("too many errors\n"); - errorexit(); - } -} - -void -parsetextconst(vlong arg) -{ - textstksiz = arg & 0xffffffffLL; - if(textstksiz & 0x80000000LL) - textstksiz = -(-textstksiz & 0xffffffffLL); - - textarg = (arg >> 32) & 0xffffffffLL; - if(textarg & 0x80000000LL) - textarg = 0; - textarg = (textarg+7) & ~7LL; -} diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index ae649a74b..3b8e8f4d7 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -30,7 +30,6 @@ // Reading object files. -#define EXTERN #include "l.h" #include "../ld/lib.h" #include "../ld/elf.h" @@ -39,104 +38,22 @@ #include "../ld/pe.h" #include <ar.h> -char *noname = "<none>"; char* thestring = "amd64"; -char* paramspace = "FP"; - -Header headers[] = { - "plan9x32", Hplan9x32, - "plan9", Hplan9x64, - "elf", Helf, - "darwin", Hdarwin, - "dragonfly", Hdragonfly, - "linux", Hlinux, - "freebsd", Hfreebsd, - "netbsd", Hnetbsd, - "openbsd", Hopenbsd, - "windows", Hwindows, - "windowsgui", Hwindows, - 0, 0 -}; - -/* - * -Hplan9x32 -T4128 -R4096 is plan9 32-bit format - * -Hplan9 -T0x200028 -R0x200000 is plan9 64-bit format - * -Helf -T0x80110000 -R4096 is ELF32 - * -Hdarwin -Tx -Rx is apple MH-exec - * -Hdragonfly -Tx -Rx is DragonFly elf-exec - * -Hlinux -Tx -Rx is linux elf-exec - * -Hfreebsd -Tx -Rx is FreeBSD elf-exec - * -Hnetbsd -Tx -Rx is NetBSD elf-exec - * -Hopenbsd -Tx -Rx is OpenBSD elf-exec - * -Hwindows -Tx -Rx is MS Windows PE32+ - */ +LinkArch* thelinkarch = &linkamd64; void -main(int argc, char *argv[]) +linkarchinit(void) { - Binit(&bso, 1, OWRITE); - listinit(); - memset(debug, 0, sizeof(debug)); - nerrors = 0; - outfile = nil; - HEADTYPE = -1; - INITTEXT = -1; - INITDAT = -1; - INITRND = -1; - INITENTRY = 0; - linkmode = LinkAuto; - nuxiinit(); - - flagcount("1", "use alternate profiling code", &debug['1']); - flagcount("8", "assume 64-bit addresses", &debug['8']); - flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); - flagint64("D", "addr: data address", &INITDAT); - flagstr("E", "sym: entry symbol", &INITENTRY); - 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']); - flagint64("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']); - flagstr("extld", "linker to run in external mode", &extld); - flagstr("extldflags", "flags for external linker", &extldflags); - flagcount("f", "ignore version mismatch", &debug['f']); - flagcount("g", "disable go package data checks", &debug['g']); - flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix); - flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); - flagstr("k", "sym: set field tracking symbol", &tracksym); - flagcount("n", "dump symbol table", &debug['n']); - 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("shared", "generate shared object (implies -linkmode external)", &flag_shared); - 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']); - - flagparse(&argc, &argv, usage); - - if(argc != 1) - usage(); - - mywhatsys(); // get goos - - if(HEADTYPE == -1) - HEADTYPE = headtype(goos); + if(strcmp(getgoarch(), "amd64p32") == 0) + thelinkarch = &linkamd64p32; + PtrSize = thelinkarch->ptrsize; + IntSize = PtrSize; + RegSize = thelinkarch->regsize; +} +void +archinit(void) +{ // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when // Go was built; see ../../make.bash. if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) @@ -156,34 +73,18 @@ main(int argc, char *argv[]) case Hdragonfly: case Hfreebsd: case Hlinux: + case Hnacl: case Hnetbsd: case Hopenbsd: + case Hsolaris: break; } - if(outfile == nil) { - if(HEADTYPE == Hwindows) - outfile = "6.out.exe"; - else - outfile = "6.out"; - } - - libinit(); - switch(HEADTYPE) { default: diag("unknown -H option"); errorexit(); - case Hplan9x32: /* plan 9 */ - HEADR = 32L; - if(INITTEXT == -1) - INITTEXT = 4096+HEADR; - if(INITDAT == -1) - INITDAT = 0; - if(INITRND == -1) - INITRND = 4096; - break; - case Hplan9x64: /* plan 9 */ + case Hplan9: /* plan 9 */ HEADR = 32L + 8L; if(INITTEXT == -1) INITTEXT = 0x200000+HEADR; @@ -202,11 +103,6 @@ main(int argc, char *argv[]) INITRND = 4096; break; case Hdarwin: /* apple MACH */ - /* - * OS X system constant - offset from 0(GS) to our TLS. - * Explained in ../../pkg/runtime/cgo/gcc_darwin_amd64.c. - */ - tlsoffset = 0x8a0; machoinit(); HEADR = INITIAL_MACHO_HEADR; if(INITRND == -1) @@ -221,13 +117,7 @@ main(int argc, char *argv[]) case Hnetbsd: /* netbsd */ case Hopenbsd: /* openbsd */ case Hdragonfly: /* dragonfly */ - /* - * ELF uses TLS offset negative from FS. - * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). - * Also known to ../../pkg/runtime/sys_linux_amd64.s - * and ../../pkg/runtime/cgo/gcc_linux_amd64.c. - */ - tlsoffset = -16; + case Hsolaris: /* solaris */ elfinit(); HEADR = ELFRESERVE; if(INITTEXT == -1) @@ -237,6 +127,18 @@ main(int argc, char *argv[]) if(INITRND == -1) INITRND = 4096; break; + case Hnacl: + elfinit(); + debug['w']++; // disable dwarf, which gets confused and is useless anyway + HEADR = 0x10000; + funcalign = 32; + if(INITTEXT == -1) + INITTEXT = 0x20000; + if(INITDAT == -1) + INITDAT = 0; + if(INITRND == -1) + INITRND = 0x10000; + break; case Hwindows: /* PE executable */ peinit(); HEADR = PEFILEHEADR; @@ -248,555 +150,8 @@ main(int argc, char *argv[]) INITRND = PESECTALIGN; break; } + if(INITDAT != 0 && INITRND != 0) print("warning: -D0x%llux is ignored because of -R0x%ux\n", INITDAT, INITRND); - if(debug['v']) - Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n", - HEADTYPE, INITTEXT, INITDAT, INITRND); - Bflush(&bso); - instinit(); - - zprg.link = P; - zprg.pcond = P; - zprg.back = 2; - zprg.as = AGOK; - zprg.from.type = D_NONE; - zprg.from.index = D_NONE; - zprg.from.scale = 1; - zprg.to = zprg.from; - zprg.mode = 64; - - pcstr = "%.6llux "; - histgen = 0; - pc = 0; - dtype = 4; - version = 0; - cbp = buf.cbuf; - cbc = sizeof(buf.cbuf); - - addlibpath("command line", "command line", argv[0], "main"); - loadlib(); - deadcode(); - patch(); - follow(); - doelf(); - if(HEADTYPE == Hdarwin) - domacho(); - dostkoff(); - dostkcheck(); - paramspace = "SP"; /* (FP) now (SP) on output */ - if(debug['p']) - if(debug['1']) - doprof1(); - else - doprof2(); - span(); - if(HEADTYPE == Hwindows) - dope(); - addexport(); - textaddress(); - pclntab(); - symtab(); - dodata(); - address(); - doweak(); - reloc(); - asmb(); - undef(); - hostlink(); - if(debug['v']) { - Bprint(&bso, "%5.2f cpu time\n", cputime()); - Bprint(&bso, "%d symbols\n", nsymbol); - Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); - Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); - } - Bflush(&bso); - - errorexit(); -} - -static Sym* -zsym(char *pn, Biobuf *f, Sym *h[]) -{ - int o; - - o = BGETC(f); - if(o < 0 || o >= NSYM || h[o] == nil) - mangle(pn); - return h[o]; -} - -static void -zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) -{ - int t; - int32 l; - Sym *s; - Auto *u; - - t = BGETC(f); - a->index = D_NONE; - a->scale = 0; - if(t & T_INDEX) { - a->index = BGETC(f); - a->scale = BGETC(f); - } - a->offset = 0; - if(t & T_OFFSET) { - a->offset = BGETLE4(f); - if(t & T_64) { - a->offset &= 0xFFFFFFFFULL; - a->offset |= (uvlong)BGETLE4(f) << 32; - } - } - a->sym = S; - if(t & T_SYM) - a->sym = zsym(pn, f, h); - a->type = D_NONE; - if(t & T_FCONST) { - a->ieee.l = BGETLE4(f); - a->ieee.h = BGETLE4(f); - a->type = D_FCONST; - } else - if(t & T_SCONST) { - Bread(f, a->scon, NSNAME); - a->type = D_SCONST; - } - if(t & T_TYPE) - a->type = BGETC(f); - if(a->type < 0 || a->type >= D_SIZE) - mangle(pn); - adrgotype = S; - if(t & T_GOTYPE) - adrgotype = zsym(pn, f, h); - s = a->sym; - t = a->type; - if(t == D_INDIR+D_GS || a->index == D_GS) - a->offset += tlsoffset; - if(t != D_AUTO && t != D_PARAM) { - if(s && adrgotype) - s->gotype = adrgotype; - return; - } - l = a->offset; - for(u=curauto; u; u=u->link) { - if(u->asym == s) - if(u->type == t) { - if(u->aoffset > l) - u->aoffset = l; - if(adrgotype) - u->gotype = adrgotype; - return; - } - } - - switch(t) { - case D_FILE: - case D_FILE1: - case D_AUTO: - case D_PARAM: - if(s == S) - mangle(pn); - } - - u = mal(sizeof(*u)); - u->link = curauto; - curauto = u; - u->asym = s; - u->aoffset = l; - u->type = t; - u->gotype = adrgotype; -} - -void -nopout(Prog *p) -{ - p->as = ANOP; - p->from.type = D_NONE; - p->to.type = D_NONE; -} - -void -ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) -{ - vlong ipc; - Prog *p; - int v, o, r, skip, mode; - Sym *h[NSYM], *s; - uint32 sig; - char *name, *x; - int ntext; - vlong eof; - char src[1024]; - Prog *lastp; - - lastp = nil; - ntext = 0; - eof = Boffset(f) + len; - src[0] = 0; - pn = estrdup(pn); // we keep it in Sym* references - -newloop: - memset(h, 0, sizeof(h)); - version++; - histfrogp = 0; - ipc = pc; - skip = 0; - mode = 64; - -loop: - if(f->state == Bracteof || Boffset(f) >= eof) - goto eof; - o = BGETC(f); - if(o == Beof) - goto eof; - o |= BGETC(f) << 8; - if(o <= AXXX || o >= ALAST) { - if(o < 0) - goto eof; - diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); - print(" probably not a .6 file\n"); - errorexit(); - } - - if(o == ANAME || o == ASIGNAME) { - sig = 0; - if(o == ASIGNAME) - sig = BGETLE4(f); - v = BGETC(f); /* type */ - o = BGETC(f); /* sym */ - r = 0; - if(v == D_STATIC) - r = version; - name = Brdline(f, '\0'); - if(name == nil) { - if(Blinelen(f) > 0) { - fprint(2, "%s: name too long\n", pn); - errorexit(); - } - goto eof; - } - x = expandpkg(name, pkg); - s = lookup(x, r); - if(x != name) - free(x); - - if(debug['S'] && r == 0) - sig = 1729; - if(sig != 0){ - if(s->sig != 0 && s->sig != sig) - diag("incompatible type signatures " - "%ux(%s) and %ux(%s) for %s", - s->sig, s->file, sig, pn, s->name); - s->sig = sig; - s->file = pn; - } - - if(debug['W']) - print(" ANAME %s\n", s->name); - if(o < 0 || o >= nelem(h)) - mangle(pn); - h[o] = s; - if((v == D_EXTERN || v == D_STATIC) && s->type == 0) - s->type = SXREF; - if(v == D_FILE) { - if(s->type != SFILE) { - histgen++; - s->type = SFILE; - s->value = histgen; - } - if(histfrogp < MAXHIST) { - histfrog[histfrogp] = s; - histfrogp++; - } else - collapsefrog(s); - dwarfaddfrag(s->value, s->name); - } - goto loop; - } - - p = mal(sizeof(*p)); - p->as = o; - p->line = BGETLE4(f); - p->back = 2; - p->mode = mode; - zaddr(pn, f, &p->from, h); - fromgotype = adrgotype; - zaddr(pn, f, &p->to, h); - - switch(p->as) { - case ATEXT: - case ADATA: - case AGLOBL: - if(p->from.sym == S) - mangle(pn); - break; - } - - if(debug['W']) - print("%P\n", p); - - switch(p->as) { - case AHISTORY: - if(p->to.offset == -1) { - addlib(src, pn); - histfrogp = 0; - goto loop; - } - if(src[0] == '\0') - copyhistfrog(src, sizeof src); - addhist(p->line, D_FILE); /* 'z' */ - if(p->to.offset) - addhist(p->to.offset, D_FILE1); /* 'Z' */ - savehist(p->line, p->to.offset); - histfrogp = 0; - goto loop; - - case AEND: - histtoauto(); - if(cursym != nil && cursym->text) - cursym->autom = curauto; - curauto = 0; - cursym = nil; - if(Boffset(f) == eof) - return; - goto newloop; - - case AGLOBL: - s = p->from.sym; - if(s->type == 0 || s->type == SXREF) { - s->type = SBSS; - s->size = 0; - } - if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) { - diag("%s: redefinition: %s in %s", - pn, s->name, TNAME); - s->type = SBSS; - s->size = 0; - } - if(p->to.offset > s->size) - s->size = p->to.offset; - if(p->from.scale & DUPOK) - s->dupok = 1; - if(p->from.scale & RODATA) - s->type = SRODATA; - else if(p->from.scale & NOPTR) - s->type = SNOPTRBSS; - goto loop; - - case ADATA: - // Assume that AGLOBL comes after ADATA. - // If we've seen an AGLOBL that said this sym was DUPOK, - // ignore any more ADATA we see, which must be - // redefinitions. - s = p->from.sym; - if(s->dupok) { -// if(debug['v']) -// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); - goto loop; - } - if(s->file == nil) - s->file = pn; - else if(s->file != pn) { - diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); - errorexit(); - } - savedata(s, p, pn); - unmal(p, sizeof *p); - goto loop; - - case AGOK: - diag("%s: GOK opcode in %s", pn, TNAME); - pc++; - goto loop; - - case ATYPE: - if(skip) - goto casdef; - pc++; - goto loop; - - case ATEXT: - s = p->from.sym; - if(s->text != nil) { - if(p->from.scale & DUPOK) { - skip = 1; - goto casdef; - } - diag("%s: %s: redefinition", pn, s->name); - return; - } - if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { - /* redefinition, so file has probably been seen before */ - if(debug['v']) - Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); - return; - } - if(cursym != nil && cursym->text) { - histtoauto(); - cursym->autom = curauto; - curauto = 0; - } - skip = 0; - if(etextp) - etextp->next = s; - else - textp = s; - etextp = s; - s->text = p; - cursym = s; - if(s->type != 0 && s->type != SXREF) { - if(p->from.scale & DUPOK) { - skip = 1; - goto casdef; - } - diag("%s: redefinition: %s\n%P", pn, s->name, p); - } - if(fromgotype) { - if(s->gotype && s->gotype != fromgotype) - diag("%s: type mismatch for %s", pn, s->name); - s->gotype = fromgotype; - } - s->type = STEXT; - s->hist = gethist(); - s->value = pc; - s->args = p->to.offset >> 32; - lastp = p; - p->pc = pc++; - goto loop; - - case AMODE: - if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){ - switch((int)p->from.offset){ - case 16: case 32: case 64: - mode = p->from.offset; - break; - } - } - goto loop; - - case AFMOVF: - case AFADDF: - case AFSUBF: - case AFSUBRF: - case AFMULF: - case AFDIVF: - 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) { - /* size sb 9 max */ - sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); - s = lookup(literal, 0); - if(s->type == 0) { - s->type = SRODATA; - adduint32(s, ieeedtof(&p->from.ieee)); - s->reachable = 0; - } - p->from.type = D_EXTERN; - p->from.sym = s; - p->from.offset = 0; - } - goto casdef; - - case AFMOVD: - case AFADDD: - case AFSUBD: - case AFSUBRD: - case AFMULD: - case AFDIVD: - 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) { - /* size sb 18 max */ - sprint(literal, "$%ux.%ux", - p->from.ieee.l, p->from.ieee.h); - s = lookup(literal, 0); - if(s->type == 0) { - s->type = SRODATA; - adduint32(s, p->from.ieee.l); - adduint32(s, p->from.ieee.h); - s->reachable = 0; - } - p->from.type = D_EXTERN; - p->from.sym = s; - p->from.offset = 0; - } - goto casdef; - - casdef: - default: - if(skip) - nopout(p); - p->pc = pc; - pc++; - - if(p->to.type == D_BRANCH) - p->to.offset += ipc; - if(lastp == nil) { - if(p->as != ANOP) - diag("unexpected instruction: %P", p); - goto loop; - } - lastp->link = p; - lastp = p; - goto loop; - } - -eof: - diag("truncated object file: %s", pn); -} - -Prog* -prg(void) -{ - Prog *p; - - p = mal(sizeof(*p)); - - *p = zprg; - return p; -} - -Prog* -copyp(Prog *q) -{ - Prog *p; - - p = prg(); - *p = *q; - return p; -} - -Prog* -appendp(Prog *q) -{ - Prog *p; - - p = prg(); - p->link = q->link; - q->link = p; - p->line = q->line; - p->mode = q->mode; - return p; } diff --git a/src/cmd/6l/optab.c b/src/cmd/6l/optab.c deleted file mode 100644 index 46603ad45..000000000 --- a/src/cmd/6l/optab.c +++ /dev/null @@ -1,1369 +0,0 @@ -// Inferno utils/6l/optab.c -// http://code.google.com/p/inferno-os/source/browse/utils/6l/optab.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include "l.h" - -uchar ynone[] = -{ - Ynone, Ynone, Zlit, 1, - 0 -}; -uchar ytext[] = -{ - Ymb, Yi64, Zpseudo,1, - 0 -}; -uchar ynop[] = -{ - Ynone, Ynone, Zpseudo,0, - Ynone, Yiauto, Zpseudo,0, - Ynone, Yml, Zpseudo,0, - Ynone, Yrf, Zpseudo,0, - Ynone, Yxr, Zpseudo,0, - Yiauto, Ynone, Zpseudo,0, - Yml, Ynone, Zpseudo,0, - Yrf, Ynone, Zpseudo,0, - Yxr, Ynone, Zpseudo,1, - 0 -}; -uchar yfuncdata[] = -{ - Yi32, Ym, Zpseudo, 0, - 0 -}; -uchar ypcdata[] = -{ - Yi32, Yi32, Zpseudo, 0, - 0 -}; -uchar yxorb[] = -{ - Yi32, Yal, Zib_, 1, - Yi32, Ymb, Zibo_m, 2, - Yrb, Ymb, Zr_m, 1, - Ymb, Yrb, Zm_r, 1, - 0 -}; -uchar yxorl[] = -{ - Yi8, Yml, Zibo_m, 2, - Yi32, Yax, Zil_, 1, - Yi32, Yml, Zilo_m, 2, - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - 0 -}; -uchar yaddl[] = -{ - Yi8, Yml, Zibo_m, 2, - Yi32, Yax, Zil_, 1, - Yi32, Yml, Zilo_m, 2, - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - 0 -}; -uchar yincb[] = -{ - Ynone, Ymb, Zo_m, 2, - 0 -}; -uchar yincw[] = -{ - Ynone, Yml, Zo_m, 2, - 0 -}; -uchar yincl[] = -{ - Ynone, Yml, Zo_m, 2, - 0 -}; -uchar ycmpb[] = -{ - Yal, Yi32, Z_ib, 1, - Ymb, Yi32, Zm_ibo, 2, - Ymb, Yrb, Zm_r, 1, - Yrb, Ymb, Zr_m, 1, - 0 -}; -uchar ycmpl[] = -{ - Yml, Yi8, Zm_ibo, 2, - Yax, Yi32, Z_il, 1, - Yml, Yi32, Zm_ilo, 2, - Yml, Yrl, Zm_r, 1, - Yrl, Yml, Zr_m, 1, - 0 -}; -uchar yshb[] = -{ - Yi1, Ymb, Zo_m, 2, - Yi32, Ymb, Zibo_m, 2, - Ycx, Ymb, Zo_m, 2, - 0 -}; -uchar yshl[] = -{ - Yi1, Yml, Zo_m, 2, - Yi32, Yml, Zibo_m, 2, - Ycl, Yml, Zo_m, 2, - Ycx, Yml, Zo_m, 2, - 0 -}; -uchar ytestb[] = -{ - Yi32, Yal, Zib_, 1, - Yi32, Ymb, Zibo_m, 2, - Yrb, Ymb, Zr_m, 1, - Ymb, Yrb, Zm_r, 1, - 0 -}; -uchar ytestl[] = -{ - Yi32, Yax, Zil_, 1, - Yi32, Yml, Zilo_m, 2, - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - 0 -}; -uchar ymovb[] = -{ - Yrb, Ymb, Zr_m, 1, - Ymb, Yrb, Zm_r, 1, - Yi32, Yrb, Zib_rp, 1, - Yi32, Ymb, Zibo_m, 2, - 0 -}; -uchar ymbs[] = -{ - Ymb, Ynone, Zm_o, 2, - 0 -}; -uchar ybtl[] = -{ - Yi8, Yml, Zibo_m, 2, - Yrl, Yml, Zr_m, 1, - 0 -}; -uchar ymovw[] = -{ - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - Yi0, Yrl, Zclr, 1, - Yi32, Yrl, Zil_rp, 1, - Yi32, Yml, Zilo_m, 2, - Yiauto, Yrl, Zaut_r, 2, - 0 -}; -uchar ymovl[] = -{ - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - Yi0, Yrl, Zclr, 1, - Yi32, Yrl, Zil_rp, 1, - Yi32, Yml, Zilo_m, 2, - Yml, Ymr, Zm_r_xm, 1, // MMX MOVD - Ymr, Yml, Zr_m_xm, 1, // MMX MOVD - 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 yret[] = -{ - Ynone, Ynone, Zo_iw, 1, - Yi32, Ynone, Zo_iw, 1, - 0 -}; -uchar ymovq[] = -{ - Yrl, Yml, Zr_m, 1, // 0x89 - Yml, Yrl, Zm_r, 1, // 0x8b - Yi0, Yrl, Zclr, 1, // 0x31 - Ys32, Yrl, Zilo_m, 2, // 32 bit signed 0xc7,(0) - Yi64, Yrl, Ziq_rp, 1, // 0xb8 -- 32/64 bit immediate - Yi32, Yml, Zilo_m, 2, // 0xc7,(0) - Ym, Ymr, Zm_r_xm_nr, 1, // MMX MOVQ (shorter encoding) - Ymr, Ym, Zr_m_xm_nr, 1, // MMX MOVQ - Ymm, Ymr, Zm_r_xm, 1, // MMX MOVD - Ymr, Ymm, Zr_m_xm, 1, // MMX MOVD - Yxr, Ymr, Zm_r_xm_nr, 2, // MOVDQ2Q - Yxm, Yxr, Zm_r_xm_nr, 2, // MOVQ xmm1/m64 -> xmm2 - Yxr, Yxm, Zr_m_xm_nr, 2, // MOVQ xmm1 -> xmm2/m64 - Yml, Yxr, Zm_r_xm, 2, // MOVD xmm load - Yxr, Yml, Zr_m_xm, 2, // MOVD xmm store - Yiauto, Yrl, Zaut_r, 2, // built-in LEAQ - 0 -}; -uchar ym_rl[] = -{ - Ym, Yrl, Zm_r, 1, - 0 -}; -uchar yrl_m[] = -{ - Yrl, Ym, Zr_m, 1, - 0 -}; -uchar ymb_rl[] = -{ - Ymb, Yrl, Zmb_r, 1, - 0 -}; -uchar yml_rl[] = -{ - Yml, Yrl, Zm_r, 1, - 0 -}; -uchar yrl_ml[] = -{ - Yrl, Yml, Zr_m, 1, - 0 -}; -uchar yml_mb[] = -{ - Yrb, Ymb, Zr_m, 1, - Ymb, Yrb, Zm_r, 1, - 0 -}; -uchar yrb_mb[] = -{ - Yrb, Ymb, Zr_m, 1, - 0 -}; -uchar yxchg[] = -{ - Yax, Yrl, Z_rp, 1, - Yrl, Yax, Zrp_, 1, - Yrl, Yml, Zr_m, 1, - Yml, Yrl, Zm_r, 1, - 0 -}; -uchar ydivl[] = -{ - Yml, Ynone, Zm_o, 2, - 0 -}; -uchar ydivb[] = -{ - Ymb, Ynone, Zm_o, 2, - 0 -}; -uchar yimul[] = -{ - Yml, Ynone, Zm_o, 2, - Yi8, Yrl, Zib_rr, 1, - Yi32, Yrl, Zil_rr, 1, - Yml, Yrl, Zm_r, 2, - 0 -}; -uchar yimul3[] = -{ - Yml, Yrl, Zibm_r, 2, - 0 -}; -uchar ybyte[] = -{ - Yi64, Ynone, Zbyte, 1, - 0 -}; -uchar yin[] = -{ - Yi32, Ynone, Zib_, 1, - Ynone, Ynone, Zlit, 1, - 0 -}; -uchar yint[] = -{ - Yi32, Ynone, Zib_, 1, - 0 -}; -uchar ypushl[] = -{ - Yrl, Ynone, Zrp_, 1, - Ym, Ynone, Zm_o, 2, - Yi8, Ynone, Zib_, 1, - Yi32, Ynone, Zil_, 1, - 0 -}; -uchar ypopl[] = -{ - Ynone, Yrl, Z_rp, 1, - Ynone, Ym, Zo_m, 2, - 0 -}; -uchar ybswap[] = -{ - Ynone, Yrl, Z_rp, 2, - 0, -}; -uchar yscond[] = -{ - Ynone, Ymb, Zo_m, 2, - 0 -}; -uchar yjcond[] = -{ - Ynone, Ybr, Zbr, 0, - Yi0, Ybr, Zbr, 0, - Yi1, Ybr, Zbr, 1, - 0 -}; -uchar yloop[] = -{ - Ynone, Ybr, Zloop, 1, - 0 -}; -uchar ycall[] = -{ - Ynone, Yml, Zo_m64, 0, - Yrx, Yrx, Zo_m64, 2, - Ynone, Ybr, Zcall, 1, - 0 -}; -uchar yjmp[] = -{ - Ynone, Yml, Zo_m64, 2, - Ynone, Ybr, Zjmp, 1, - 0 -}; - -uchar yfmvd[] = -{ - Ym, Yf0, Zm_o, 2, - Yf0, Ym, Zo_m, 2, - Yrf, Yf0, Zm_o, 2, - Yf0, Yrf, Zo_m, 2, - 0 -}; -uchar yfmvdp[] = -{ - Yf0, Ym, Zo_m, 2, - Yf0, Yrf, Zo_m, 2, - 0 -}; -uchar yfmvf[] = -{ - Ym, Yf0, Zm_o, 2, - Yf0, Ym, Zo_m, 2, - 0 -}; -uchar yfmvx[] = -{ - Ym, Yf0, Zm_o, 2, - 0 -}; -uchar yfmvp[] = -{ - Yf0, Ym, Zo_m, 2, - 0 -}; -uchar yfadd[] = -{ - Ym, Yf0, Zm_o, 2, - Yrf, Yf0, Zm_o, 2, - Yf0, Yrf, Zo_m, 2, - 0 -}; -uchar yfaddp[] = -{ - Yf0, Yrf, Zo_m, 2, - 0 -}; -uchar yfxch[] = -{ - Yf0, Yrf, Zo_m, 2, - Yrf, Yf0, Zm_o, 2, - 0 -}; -uchar ycompp[] = -{ - Yf0, Yrf, Zo_m, 2, /* botch is really f0,f1 */ - 0 -}; -uchar ystsw[] = -{ - Ynone, Ym, Zo_m, 2, - Ynone, Yax, Zlit, 1, - 0 -}; -uchar ystcw[] = -{ - Ynone, Ym, Zo_m, 2, - Ym, Ynone, Zm_o, 2, - 0 -}; -uchar ysvrs[] = -{ - Ynone, Ym, Zo_m, 2, - Ym, Ynone, Zm_o, 2, - 0 -}; -uchar ymm[] = -{ - Ymm, Ymr, Zm_r_xm, 1, - Yxm, Yxr, Zm_r_xm, 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 ymr[] = -{ - Ymr, Ymr, Zm_r, 1, - 0 -}; -uchar ymr_ml[] = -{ - Ymr, 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 yps[] = -{ - Ymm, Ymr, Zm_r_xm, 1, - Yi8, Ymr, Zibo_m_xm, 2, - Yxm, Yxr, Zm_r_xm, 2, - Yi8, Yxr, Zibo_m_xm, 3, - 0 -}; -uchar yxrrl[] = -{ - Yxr, Yrl, Zm_r, 1, - 0 -}; -uchar ymfp[] = -{ - Ymm, Ymr, Zm_r_3d, 1, - 0, -}; -uchar ymrxr[] = -{ - Ymr, Yxr, Zm_r, 1, - Yxm, Yxr, Zm_r_xm, 1, - 0 -}; -uchar ymshuf[] = -{ - Ymm, Ymr, Zibm_r, 2, - 0 -}; -uchar ymshufb[] = -{ - Yxm, Yxr, Zm2_r, 2, - 0 -}; -uchar yxshuf[] = -{ - Yxm, Yxr, Zibm_r, 2, - 0 -}; -uchar yextrw[] = -{ - Yxr, Yrl, Zibm_r, 2, - 0 -}; -uchar yinsrw[] = -{ - Yml, Yxr, Zibm_r, 2, - 0 -}; -uchar yinsr[] = -{ - Ymm, Yxr, Zibm_r, 3, - 0 -}; -uchar ypsdq[] = -{ - Yi8, Yxr, Zibo_m, 2, - 0 -}; -uchar ymskb[] = -{ - Yxr, Yrl, Zm_r_xm, 2, - Ymr, Yrl, Zm_r_xm, 1, - 0 -}; -uchar ycrc32l[] = -{ - Yml, Yrl, Zlitm_r, 0, -}; -uchar yprefetch[] = -{ - Ym, Ynone, Zm_o, 2, - 0, -}; -uchar yaes[] = -{ - Yxm, Yxr, Zlitm_r, 2, - 0 -}; -uchar yaes2[] = -{ - Yxm, Yxr, Zibm_r, 2, - 0 -}; - -/* - * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32, - * and p->from and p->to as operands (Adr*). The linker scans optab to find - * the entry with the given p->as and then looks through the ytable for that - * instruction (the second field in the optab struct) for a line whose first - * two values match the Ytypes of the p->from and p->to operands. The function - * oclass in span.c computes the specific Ytype of an operand and then the set - * of more general Ytypes that it satisfies is implied by the ycover table, set - * up in instinit. For example, oclass distinguishes the constants 0 and 1 - * from the more general 8-bit constants, but instinit says - * - * ycover[Yi0*Ymax + Ys32] = 1; - * ycover[Yi1*Ymax + Ys32] = 1; - * ycover[Yi8*Ymax + Ys32] = 1; - * - * which means that Yi0, Yi1, and Yi8 all count as Ys32 (signed 32) - * if that's what an instruction can handle. - * - * In parallel with the scan through the ytable for the appropriate line, there - * is a z pointer that starts out pointing at the strange magic byte list in - * the Optab struct. With each step past a non-matching ytable line, z - * advances by the 4th entry in the line. When a matching line is found, that - * z pointer has the extra data to use in laying down the instruction bytes. - * The actual bytes laid down are a function of the 3rd entry in the line (that - * is, the Ztype) and the z bytes. - * - * For example, let's look at AADDL. The optab line says: - * { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 }, - * - * and yaddl says - * uchar yaddl[] = - * { - * Yi8, Yml, Zibo_m, 2, - * Yi32, Yax, Zil_, 1, - * Yi32, Yml, Zilo_m, 2, - * Yrl, Yml, Zr_m, 1, - * Yml, Yrl, Zm_r, 1, - * 0 - * }; - * - * so there are 5 possible types of ADDL instruction that can be laid down, and - * possible states used to lay them down (Ztype and z pointer, assuming z - * points at {0x83,(00),0x05,0x81,(00),0x01,0x03}) are: - * - * Yi8, Yml -> Zibo_m, z (0x83, 00) - * Yi32, Yax -> Zil_, z+2 (0x05) - * Yi32, Yml -> Zilo_m, z+2+1 (0x81, 0x00) - * Yrl, Yml -> Zr_m, z+2+1+2 (0x01) - * Yml, Yrl -> Zm_r, z+2+1+2+1 (0x03) - * - * The Pconstant in the optab line controls the prefix bytes to emit. That's - * relatively straightforward as this program goes. - * - * The switch on t[2] in doasm implements the various Z cases. Zibo_m, for - * example, is an opcode byte (z[0]) then an asmando (which is some kind of - * encoded addressing mode for the Yml arg), and then a single immediate byte. - * Zilo_m is the same but a long (32-bit) immediate. - */ -Optab optab[] = -/* as, ytab, andproto, opcode */ -{ - { AXXX }, - { AAAA, ynone, P32, 0x37 }, - { AAAD, ynone, P32, 0xd5,0x0a }, - { AAAM, ynone, P32, 0xd4,0x0a }, - { AAAS, ynone, P32, 0x3f }, - { AADCB, yxorb, Pb, 0x14,0x80,(02),0x10,0x10 }, - { AADCL, yxorl, Px, 0x83,(02),0x15,0x81,(02),0x11,0x13 }, - { AADCQ, yxorl, Pw, 0x83,(02),0x15,0x81,(02),0x11,0x13 }, - { AADCW, yxorl, Pe, 0x83,(02),0x15,0x81,(02),0x11,0x13 }, - { AADDB, yxorb, Pb, 0x04,0x80,(00),0x00,0x02 }, - { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 }, - { AADDPD, yxm, Pq, 0x58 }, - { AADDPS, yxm, Pm, 0x58 }, - { AADDQ, yaddl, Pw, 0x83,(00),0x05,0x81,(00),0x01,0x03 }, - { AADDSD, yxm, Pf2, 0x58 }, - { AADDSS, yxm, Pf3, 0x58 }, - { AADDW, yaddl, Pe, 0x83,(00),0x05,0x81,(00),0x01,0x03 }, - { AADJSP }, - { AANDB, yxorb, Pb, 0x24,0x80,(04),0x20,0x22 }, - { AANDL, yxorl, Px, 0x83,(04),0x25,0x81,(04),0x21,0x23 }, - { AANDNPD, yxm, Pq, 0x55 }, - { AANDNPS, yxm, Pm, 0x55 }, - { AANDPD, yxm, Pq, 0x54 }, - { AANDPS, yxm, Pq, 0x54 }, - { AANDQ, yxorl, Pw, 0x83,(04),0x25,0x81,(04),0x21,0x23 }, - { AANDW, yxorl, Pe, 0x83,(04),0x25,0x81,(04),0x21,0x23 }, - { AARPL, yrl_ml, P32, 0x63 }, - { ABOUNDL, yrl_m, P32, 0x62 }, - { ABOUNDW, yrl_m, Pe, 0x62 }, - { ABSFL, yml_rl, Pm, 0xbc }, - { ABSFQ, yml_rl, Pw, 0x0f,0xbc }, - { ABSFW, yml_rl, Pq, 0xbc }, - { ABSRL, yml_rl, Pm, 0xbd }, - { ABSRQ, yml_rl, Pw, 0x0f,0xbd }, - { ABSRW, yml_rl, Pq, 0xbd }, - { ABSWAPL, ybswap, Px, 0x0f,0xc8 }, - { ABSWAPQ, ybswap, Pw, 0x0f,0xc8 }, - { ABTCL, ybtl, Pm, 0xba,(07),0xbb }, - { ABTCQ, ybtl, Pw, 0x0f,0xba,(07),0x0f,0xbb }, - { ABTCW, ybtl, Pq, 0xba,(07),0xbb }, - { ABTL, ybtl, Pm, 0xba,(04),0xa3 }, - { ABTQ, ybtl, Pw, 0x0f,0xba,(04),0x0f,0xa3}, - { ABTRL, ybtl, Pm, 0xba,(06),0xb3 }, - { ABTRQ, ybtl, Pw, 0x0f,0xba,(06),0x0f,0xb3 }, - { ABTRW, ybtl, Pq, 0xba,(06),0xb3 }, - { ABTSL, ybtl, Pm, 0xba,(05),0xab }, - { ABTSQ, ybtl, Pw, 0x0f,0xba,(05),0x0f,0xab }, - { ABTSW, ybtl, Pq, 0xba,(05),0xab }, - { ABTW, ybtl, Pq, 0xba,(04),0xa3 }, - { ABYTE, ybyte, Px, 1 }, - { ACALL, ycall, Px, 0xff,(02),0xe8 }, - { ACDQ, ynone, Px, 0x99 }, - { ACLC, ynone, Px, 0xf8 }, - { ACLD, ynone, Px, 0xfc }, - { ACLI, ynone, Px, 0xfa }, - { ACLTS, ynone, Pm, 0x06 }, - { ACMC, ynone, Px, 0xf5 }, - { ACMOVLCC, yml_rl, Pm, 0x43 }, - { ACMOVLCS, yml_rl, Pm, 0x42 }, - { ACMOVLEQ, yml_rl, Pm, 0x44 }, - { ACMOVLGE, yml_rl, Pm, 0x4d }, - { ACMOVLGT, yml_rl, Pm, 0x4f }, - { ACMOVLHI, yml_rl, Pm, 0x47 }, - { ACMOVLLE, yml_rl, Pm, 0x4e }, - { ACMOVLLS, yml_rl, Pm, 0x46 }, - { ACMOVLLT, yml_rl, Pm, 0x4c }, - { ACMOVLMI, yml_rl, Pm, 0x48 }, - { ACMOVLNE, yml_rl, Pm, 0x45 }, - { ACMOVLOC, yml_rl, Pm, 0x41 }, - { ACMOVLOS, yml_rl, Pm, 0x40 }, - { ACMOVLPC, yml_rl, Pm, 0x4b }, - { ACMOVLPL, yml_rl, Pm, 0x49 }, - { ACMOVLPS, yml_rl, Pm, 0x4a }, - { ACMOVQCC, yml_rl, Pw, 0x0f,0x43 }, - { ACMOVQCS, yml_rl, Pw, 0x0f,0x42 }, - { ACMOVQEQ, yml_rl, Pw, 0x0f,0x44 }, - { ACMOVQGE, yml_rl, Pw, 0x0f,0x4d }, - { ACMOVQGT, yml_rl, Pw, 0x0f,0x4f }, - { ACMOVQHI, yml_rl, Pw, 0x0f,0x47 }, - { ACMOVQLE, yml_rl, Pw, 0x0f,0x4e }, - { ACMOVQLS, yml_rl, Pw, 0x0f,0x46 }, - { ACMOVQLT, yml_rl, Pw, 0x0f,0x4c }, - { ACMOVQMI, yml_rl, Pw, 0x0f,0x48 }, - { ACMOVQNE, yml_rl, Pw, 0x0f,0x45 }, - { ACMOVQOC, yml_rl, Pw, 0x0f,0x41 }, - { ACMOVQOS, yml_rl, Pw, 0x0f,0x40 }, - { ACMOVQPC, yml_rl, Pw, 0x0f,0x4b }, - { ACMOVQPL, yml_rl, Pw, 0x0f,0x49 }, - { ACMOVQPS, yml_rl, Pw, 0x0f,0x4a }, - { ACMOVWCC, yml_rl, Pq, 0x43 }, - { ACMOVWCS, yml_rl, Pq, 0x42 }, - { ACMOVWEQ, yml_rl, Pq, 0x44 }, - { ACMOVWGE, yml_rl, Pq, 0x4d }, - { ACMOVWGT, yml_rl, Pq, 0x4f }, - { ACMOVWHI, yml_rl, Pq, 0x47 }, - { ACMOVWLE, yml_rl, Pq, 0x4e }, - { ACMOVWLS, yml_rl, Pq, 0x46 }, - { ACMOVWLT, yml_rl, Pq, 0x4c }, - { ACMOVWMI, yml_rl, Pq, 0x48 }, - { ACMOVWNE, yml_rl, Pq, 0x45 }, - { ACMOVWOC, yml_rl, Pq, 0x41 }, - { ACMOVWOS, yml_rl, Pq, 0x40 }, - { ACMOVWPC, yml_rl, Pq, 0x4b }, - { ACMOVWPL, yml_rl, Pq, 0x49 }, - { ACMOVWPS, yml_rl, Pq, 0x4a }, - { ACMPB, ycmpb, Pb, 0x3c,0x80,(07),0x38,0x3a }, - { ACMPL, ycmpl, Px, 0x83,(07),0x3d,0x81,(07),0x39,0x3b }, - { ACMPPD, yxcmpi, Px, Pe,0xc2 }, - { ACMPPS, yxcmpi, Pm, 0xc2,0 }, - { ACMPQ, ycmpl, Pw, 0x83,(07),0x3d,0x81,(07),0x39,0x3b }, - { ACMPSB, ynone, Pb, 0xa6 }, - { ACMPSD, yxcmpi, Px, Pf2,0xc2 }, - { ACMPSL, ynone, Px, 0xa7 }, - { ACMPSQ, ynone, Pw, 0xa7 }, - { ACMPSS, yxcmpi, Px, Pf3,0xc2 }, - { ACMPSW, ynone, Pe, 0xa7 }, - { ACMPW, ycmpl, Pe, 0x83,(07),0x3d,0x81,(07),0x39,0x3b }, - { ACOMISD, yxcmp, Pe, 0x2f }, - { ACOMISS, yxcmp, Pm, 0x2f }, - { ACPUID, ynone, Pm, 0xa2 }, - { 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 }, - { API2FW, ymfp, Px, 0x0c }, - { ACVTSD2SL, yxcvfl, Pf2, 0x2d }, - { ACVTSD2SQ, yxcvfq, Pw, Pf2,0x2d }, - { ACVTSD2SS, yxm, Pf2, 0x5a }, - { ACVTSL2SD, yxcvlf, Pf2, 0x2a }, - { ACVTSQ2SD, yxcvqf, Pw, Pf2,0x2a }, - { ACVTSL2SS, yxcvlf, Pf3, 0x2a }, - { ACVTSQ2SS, yxcvqf, Pw, Pf3,0x2a }, - { ACVTSS2SD, yxm, Pf3, 0x5a }, - { ACVTSS2SL, yxcvfl, Pf3, 0x2d }, - { ACVTSS2SQ, yxcvfq, Pw, Pf3,0x2d }, - { ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c }, - { ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c }, - { ACVTTSD2SL, yxcvfl, Pf2, 0x2c }, - { ACVTTSD2SQ, yxcvfq, Pw, Pf2,0x2c }, - { ACVTTSS2SL, yxcvfl, Pf3, 0x2c }, - { ACVTTSS2SQ, yxcvfq, Pw, Pf3,0x2c }, - { ACWD, ynone, Pe, 0x99 }, - { ACQO, ynone, Pw, 0x99 }, - { ADAA, ynone, P32, 0x27 }, - { ADAS, ynone, P32, 0x2f }, - { ADATA }, - { ADECB, yincb, Pb, 0xfe,(01) }, - { ADECL, yincl, Px, 0xff,(01) }, - { ADECQ, yincl, Pw, 0xff,(01) }, - { ADECW, yincw, Pe, 0xff,(01) }, - { ADIVB, ydivb, Pb, 0xf6,(06) }, - { ADIVL, ydivl, Px, 0xf7,(06) }, - { ADIVPD, yxm, Pe, 0x5e }, - { ADIVPS, yxm, Pm, 0x5e }, - { ADIVQ, ydivl, Pw, 0xf7,(06) }, - { ADIVSD, yxm, Pf2, 0x5e }, - { ADIVSS, yxm, Pf3, 0x5e }, - { ADIVW, ydivl, Pe, 0xf7,(06) }, - { AEMMS, ynone, Pm, 0x77 }, - { AENTER }, /* botch */ - { AFXRSTOR, ysvrs, Pm, 0xae,(01),0xae,(01) }, - { AFXSAVE, ysvrs, Pm, 0xae,(00),0xae,(00) }, - { AFXRSTOR64, ysvrs, Pw, 0x0f,0xae,(01),0x0f,0xae,(01) }, - { AFXSAVE64, ysvrs, Pw, 0x0f,0xae,(00),0x0f,0xae,(00) }, - { AGLOBL }, - { AGOK }, - { AHISTORY }, - { AHLT, ynone, Px, 0xf4 }, - { AIDIVB, ydivb, Pb, 0xf6,(07) }, - { AIDIVL, ydivl, Px, 0xf7,(07) }, - { AIDIVQ, ydivl, Pw, 0xf7,(07) }, - { AIDIVW, ydivl, Pe, 0xf7,(07) }, - { AIMULB, ydivb, Pb, 0xf6,(05) }, - { AIMULL, yimul, Px, 0xf7,(05),0x6b,0x69,Pm,0xaf }, - { AIMULQ, yimul, Pw, 0xf7,(05),0x6b,0x69,Pm,0xaf }, - { AIMULW, yimul, Pe, 0xf7,(05),0x6b,0x69,Pm,0xaf }, - { AIMUL3Q, yimul3, Pw, 0x6b,(00) }, - { AINB, yin, Pb, 0xe4,0xec }, - { AINCB, yincb, Pb, 0xfe,(00) }, - { AINCL, yincl, Px, 0xff,(00) }, - { AINCQ, yincl, Pw, 0xff,(00) }, - { AINCW, yincw, Pe, 0xff,(00) }, - { AINL, yin, Px, 0xe5,0xed }, - { AINSB, ynone, Pb, 0x6c }, - { AINSL, ynone, Px, 0x6d }, - { AINSW, ynone, Pe, 0x6d }, - { AINT, yint, Px, 0xcd }, - { AINTO, ynone, P32, 0xce }, - { AINW, yin, Pe, 0xe5,0xed }, - { AIRETL, ynone, Px, 0xcf }, - { AIRETQ, ynone, Pw, 0xcf }, - { AIRETW, ynone, Pe, 0xcf }, - { AJCC, yjcond, Px, 0x73,0x83,(00) }, - { AJCS, yjcond, Px, 0x72,0x82 }, - { AJCXZL, yloop, Px, 0xe3 }, - { AJCXZQ, yloop, Px, 0xe3 }, - { AJEQ, yjcond, Px, 0x74,0x84 }, - { AJGE, yjcond, Px, 0x7d,0x8d }, - { AJGT, yjcond, Px, 0x7f,0x8f }, - { AJHI, yjcond, Px, 0x77,0x87 }, - { AJLE, yjcond, Px, 0x7e,0x8e }, - { AJLS, yjcond, Px, 0x76,0x86 }, - { AJLT, yjcond, Px, 0x7c,0x8c }, - { AJMI, yjcond, Px, 0x78,0x88 }, - { AJMP, yjmp, Px, 0xff,(04),0xeb,0xe9 }, - { AJNE, yjcond, Px, 0x75,0x85 }, - { AJOC, yjcond, Px, 0x71,0x81,(00) }, - { AJOS, yjcond, Px, 0x70,0x80,(00) }, - { AJPC, yjcond, Px, 0x7b,0x8b }, - { AJPL, yjcond, Px, 0x79,0x89 }, - { AJPS, yjcond, Px, 0x7a,0x8a }, - { ALAHF, ynone, Px, 0x9f }, - { ALARL, yml_rl, Pm, 0x02 }, - { ALARW, yml_rl, Pq, 0x02 }, - { ALDMXCSR, ysvrs, Pm, 0xae,(02),0xae,(02) }, - { ALEAL, ym_rl, Px, 0x8d }, - { ALEAQ, ym_rl, Pw, 0x8d }, - { ALEAVEL, ynone, P32, 0xc9 }, - { ALEAVEQ, ynone, Py, 0xc9 }, - { ALEAVEW, ynone, Pe, 0xc9 }, - { ALEAW, ym_rl, Pe, 0x8d }, - { ALOCK, ynone, Px, 0xf0 }, - { ALODSB, ynone, Pb, 0xac }, - { ALODSL, ynone, Px, 0xad }, - { ALODSQ, ynone, Pw, 0xad }, - { ALODSW, ynone, Pe, 0xad }, - { ALONG, ybyte, Px, 4 }, - { ALOOP, yloop, Px, 0xe2 }, - { ALOOPEQ, yloop, Px, 0xe1 }, - { ALOOPNE, yloop, Px, 0xe0 }, - { ALSLL, yml_rl, Pm, 0x03 }, - { ALSLW, yml_rl, Pq, 0x03 }, - { AMASKMOVOU, yxr, Pe, 0xf7 }, - { AMASKMOVQ, ymr, Pm, 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 }, - { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) }, - { AMOVBLSX, ymb_rl, Pm, 0xbe }, - { AMOVBLZX, ymb_rl, Pm, 0xb6 }, - { AMOVBQSX, ymb_rl, Pw, 0x0f,0xbe }, - { AMOVBQZX, ymb_rl, Pw, 0x0f,0xb6 }, - { AMOVBWSX, ymb_rl, Pq, 0xbe }, - { AMOVBWZX, ymb_rl, Pq, 0xb6 }, - { AMOVO, yxmov, Pe, 0x6f,0x7f }, - { AMOVOU, yxmov, Pf3, 0x6f,0x7f }, - { AMOVHLPS, yxr, Pm, 0x12 }, - { AMOVHPD, yxmov, Pe, 0x16,0x17 }, - { AMOVHPS, yxmov, Pm, 0x16,0x17 }, - { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0xb8,0xc7,(00),0x6e,0x7e,Pe,0x6e,Pe,0x7e,0 }, - { AMOVLHPS, yxr, Pm, 0x16 }, - { AMOVLPD, yxmov, Pe, 0x12,0x13 }, - { AMOVLPS, yxmov, Pm, 0x12,0x13 }, - { AMOVLQSX, yml_rl, Pw, 0x63 }, - { AMOVLQZX, yml_rl, Px, 0x8b }, - { AMOVMSKPD, yxrrl, Pq, 0x50 }, - { AMOVMSKPS, yxrrl, Pm, 0x50 }, - { AMOVNTO, yxr_ml, Pe, 0xe7 }, - { AMOVNTPD, yxr_ml, Pe, 0x2b }, - { AMOVNTPS, yxr_ml, Pm, 0x2b }, - { AMOVNTQ, ymr_ml, Pm, 0xe7 }, - { AMOVQ, ymovq, Pw, 0x89, 0x8b, 0x31, 0xc7,(00), 0xb8, 0xc7,(00), 0x6f, 0x7f, 0x6e, 0x7e, Pf2,0xd6, Pf3,0x7e, Pe,0xd6, Pe,0x6e, Pe,0x7e,0 }, - { AMOVQOZX, ymrxr, Pf3, 0xd6,0x7e }, - { AMOVSB, ynone, Pb, 0xa4 }, - { AMOVSD, yxmov, Pf2, 0x10,0x11 }, - { AMOVSL, ynone, Px, 0xa5 }, - { AMOVSQ, ynone, Pw, 0xa5 }, - { AMOVSS, yxmov, Pf3, 0x10,0x11 }, - { AMOVSW, ynone, Pe, 0xa5 }, - { AMOVUPD, yxmov, Pe, 0x10,0x11 }, - { AMOVUPS, yxmov, Pm, 0x10,0x11 }, - { AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0xb8,0xc7,(00),0 }, - { AMOVWLSX, yml_rl, Pm, 0xbf }, - { AMOVWLZX, yml_rl, Pm, 0xb7 }, - { AMOVWQSX, yml_rl, Pw, 0x0f,0xbf }, - { AMOVWQZX, yml_rl, Pw, 0x0f,0xb7 }, - { AMULB, ydivb, Pb, 0xf6,(04) }, - { AMULL, ydivl, Px, 0xf7,(04) }, - { AMULPD, yxm, Pe, 0x59 }, - { AMULPS, yxm, Ym, 0x59 }, - { AMULQ, ydivl, Pw, 0xf7,(04) }, - { AMULSD, yxm, Pf2, 0x59 }, - { AMULSS, yxm, Pf3, 0x59 }, - { AMULW, ydivl, Pe, 0xf7,(04) }, - { ANAME }, - { ANEGB, yscond, Pb, 0xf6,(03) }, - { ANEGL, yscond, Px, 0xf7,(03) }, - { ANEGQ, yscond, Pw, 0xf7,(03) }, - { ANEGW, yscond, Pe, 0xf7,(03) }, - { ANOP, ynop, Px, 0,0 }, - { ANOTB, yscond, Pb, 0xf6,(02) }, - { ANOTL, yscond, Px, 0xf7,(02) }, - { ANOTQ, yscond, Pw, 0xf7,(02) }, - { ANOTW, yscond, Pe, 0xf7,(02) }, - { AORB, yxorb, Pb, 0x0c,0x80,(01),0x08,0x0a }, - { AORL, yxorl, Px, 0x83,(01),0x0d,0x81,(01),0x09,0x0b }, - { AORPD, yxm, Pq, 0x56 }, - { AORPS, yxm, Pm, 0x56 }, - { AORQ, yxorl, Pw, 0x83,(01),0x0d,0x81,(01),0x09,0x0b }, - { AORW, yxorl, Pe, 0x83,(01),0x0d,0x81,(01),0x09,0x0b }, - { AOUTB, yin, Pb, 0xe6,0xee }, - { AOUTL, yin, Px, 0xe7,0xef }, - { AOUTSB, ynone, Pb, 0x6e }, - { AOUTSL, ynone, Px, 0x6f }, - { AOUTSW, ynone, Pe, 0x6f }, - { AOUTW, yin, Pe, 0xe7,0xef }, - { APACKSSLW, ymm, Py, 0x6b,Pe,0x6b }, - { APACKSSWB, ymm, Py, 0x63,Pe,0x63 }, - { APACKUSWB, ymm, Py, 0x67,Pe,0x67 }, - { APADDB, ymm, Py, 0xfc,Pe,0xfc }, - { APADDL, ymm, Py, 0xfe,Pe,0xfe }, - { APADDQ, yxm, Pe, 0xd4 }, - { APADDSB, ymm, Py, 0xec,Pe,0xec }, - { APADDSW, ymm, Py, 0xed,Pe,0xed }, - { APADDUSB, ymm, Py, 0xdc,Pe,0xdc }, - { APADDUSW, ymm, Py, 0xdd,Pe,0xdd }, - { APADDW, ymm, Py, 0xfd,Pe,0xfd }, - { APAND, ymm, Py, 0xdb,Pe,0xdb }, - { APANDN, ymm, Py, 0xdf,Pe,0xdf }, - { APAUSE, ynone, Px, 0xf3,0x90 }, - { APAVGB, ymm, Py, 0xe0,Pe,0xe0 }, - { APAVGW, ymm, Py, 0xe3,Pe,0xe3 }, - { APCMPEQB, ymm, Py, 0x74,Pe,0x74 }, - { APCMPEQL, ymm, Py, 0x76,Pe,0x76 }, - { APCMPEQW, ymm, Py, 0x75,Pe,0x75 }, - { APCMPGTB, ymm, Py, 0x64,Pe,0x64 }, - { APCMPGTL, ymm, Py, 0x66,Pe,0x66 }, - { APCMPGTW, ymm, Py, 0x65,Pe,0x65 }, - { APEXTRW, yextrw, Pq, 0xc5,(00) }, - { APF2IL, ymfp, Px, 0x1d }, - { APF2IW, ymfp, Px, 0x1c }, - { API2FL, ymfp, Px, 0x0d }, - { APFACC, ymfp, Px, 0xae }, - { APFADD, ymfp, Px, 0x9e }, - { APFCMPEQ, ymfp, Px, 0xb0 }, - { APFCMPGE, ymfp, Px, 0x90 }, - { APFCMPGT, ymfp, Px, 0xa0 }, - { APFMAX, ymfp, Px, 0xa4 }, - { APFMIN, ymfp, Px, 0x94 }, - { APFMUL, ymfp, Px, 0xb4 }, - { APFNACC, ymfp, Px, 0x8a }, - { APFPNACC, ymfp, Px, 0x8e }, - { APFRCP, ymfp, Px, 0x96 }, - { APFRCPIT1, ymfp, Px, 0xa6 }, - { APFRCPI2T, ymfp, Px, 0xb6 }, - { APFRSQIT1, ymfp, Px, 0xa7 }, - { APFRSQRT, ymfp, Px, 0x97 }, - { APFSUB, ymfp, Px, 0x9a }, - { APFSUBR, ymfp, Px, 0xaa }, - { APINSRW, yinsrw, Pq, 0xc4,(00) }, - { APINSRD, yinsr, Pq, 0x3a, 0x22, (00) }, - { APINSRQ, yinsr, Pq3, 0x3a, 0x22, (00) }, - { APMADDWL, ymm, Py, 0xf5,Pe,0xf5 }, - { APMAXSW, yxm, Pe, 0xee }, - { APMAXUB, yxm, Pe, 0xde }, - { APMINSW, yxm, Pe, 0xea }, - { APMINUB, yxm, Pe, 0xda }, - { APMOVMSKB, ymskb, Px, Pe,0xd7,0xd7 }, - { APMULHRW, ymfp, Px, 0xb7 }, - { APMULHUW, ymm, Py, 0xe4,Pe,0xe4 }, - { APMULHW, ymm, Py, 0xe5,Pe,0xe5 }, - { APMULLW, ymm, Py, 0xd5,Pe,0xd5 }, - { APMULULQ, ymm, Py, 0xf4,Pe,0xf4 }, - { APOPAL, ynone, P32, 0x61 }, - { APOPAW, ynone, Pe, 0x61 }, - { APOPFL, ynone, P32, 0x9d }, - { APOPFQ, ynone, Py, 0x9d }, - { APOPFW, ynone, Pe, 0x9d }, - { APOPL, ypopl, P32, 0x58,0x8f,(00) }, - { APOPQ, ypopl, Py, 0x58,0x8f,(00) }, - { APOPW, ypopl, Pe, 0x58,0x8f,(00) }, - { APOR, ymm, Py, 0xeb,Pe,0xeb }, - { APSADBW, yxm, Pq, 0xf6 }, - { APSHUFHW, yxshuf, Pf3, 0x70,(00) }, - { APSHUFL, yxshuf, Pq, 0x70,(00) }, - { APSHUFLW, yxshuf, Pf2, 0x70,(00) }, - { APSHUFW, ymshuf, Pm, 0x70,(00) }, - { APSHUFB, ymshufb,Pq, 0x38, 0x00 }, - { APSLLO, ypsdq, Pq, 0x73,(07) }, - { APSLLL, yps, Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) }, - { APSLLQ, yps, Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) }, - { APSLLW, yps, Py, 0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06) }, - { APSRAL, yps, Py, 0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04) }, - { APSRAW, yps, Py, 0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04) }, - { APSRLO, ypsdq, Pq, 0x73,(03) }, - { APSRLL, yps, Py, 0xd2, 0x72,(02), Pe,0xd2, Pe,0x72,(02) }, - { APSRLQ, yps, Py, 0xd3, 0x73,(02), Pe,0xd3, Pe,0x73,(02) }, - { APSRLW, yps, Py, 0xd1, 0x71,(02), Pe,0xe1, Pe,0x71,(02) }, - { 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 }, - { APSWAPL, ymfp, Px, 0xbb }, - { APUNPCKHBW, ymm, Py, 0x68,Pe,0x68 }, - { APUNPCKHLQ, ymm, Py, 0x6a,Pe,0x6a }, - { APUNPCKHQDQ, yxm, Pe, 0x6d }, - { APUNPCKHWL, ymm, Py, 0x69,Pe,0x69 }, - { APUNPCKLBW, ymm, Py, 0x60,Pe,0x60 }, - { APUNPCKLLQ, ymm, Py, 0x62,Pe,0x62 }, - { APUNPCKLQDQ, yxm, Pe, 0x6c }, - { APUNPCKLWL, ymm, Py, 0x61,Pe,0x61 }, - { APUSHAL, ynone, P32, 0x60 }, - { APUSHAW, ynone, Pe, 0x60 }, - { APUSHFL, ynone, P32, 0x9c }, - { APUSHFQ, ynone, Py, 0x9c }, - { APUSHFW, ynone, Pe, 0x9c }, - { APUSHL, ypushl, P32, 0x50,0xff,(06),0x6a,0x68 }, - { APUSHQ, ypushl, Py, 0x50,0xff,(06),0x6a,0x68 }, - { APUSHW, ypushl, Pe, 0x50,0xff,(06),0x6a,0x68 }, - { APXOR, ymm, Py, 0xef,Pe,0xef }, - { AQUAD, ybyte, Px, 8 }, - { ARCLB, yshb, Pb, 0xd0,(02),0xc0,(02),0xd2,(02) }, - { ARCLL, yshl, Px, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) }, - { ARCLQ, yshl, Pw, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) }, - { ARCLW, yshl, Pe, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) }, - { ARCPPS, yxm, Pm, 0x53 }, - { ARCPSS, yxm, Pf3, 0x53 }, - { ARCRB, yshb, Pb, 0xd0,(03),0xc0,(03),0xd2,(03) }, - { ARCRL, yshl, Px, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) }, - { ARCRQ, yshl, Pw, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) }, - { ARCRW, yshl, Pe, 0xd1,(03),0xc1,(03),0xd3,(03),0xd3,(03) }, - { AREP, ynone, Px, 0xf3 }, - { AREPN, ynone, Px, 0xf2 }, - { ARET, ynone, Px, 0xc3 }, - { ARETFW, yret, Pe, 0xcb,0xca }, - { ARETFL, yret, Px, 0xcb,0xca }, - { ARETFQ, yret, Pw, 0xcb,0xca }, - { AROLB, yshb, Pb, 0xd0,(00),0xc0,(00),0xd2,(00) }, - { AROLL, yshl, Px, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) }, - { AROLQ, yshl, Pw, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) }, - { AROLW, yshl, Pe, 0xd1,(00),0xc1,(00),0xd3,(00),0xd3,(00) }, - { ARORB, yshb, Pb, 0xd0,(01),0xc0,(01),0xd2,(01) }, - { ARORL, yshl, Px, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) }, - { ARORQ, yshl, Pw, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) }, - { ARORW, yshl, Pe, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) }, - { ARSQRTPS, yxm, Pm, 0x52 }, - { ARSQRTSS, yxm, Pf3, 0x52 }, - { ASAHF, ynone, Px, 0x86,0xe0,0x50,0x9d }, /* XCHGB AH,AL; PUSH AX; POPFL */ - { ASALB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) }, - { ASALL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASALQ, yshl, Pw, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASALW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASARB, yshb, Pb, 0xd0,(07),0xc0,(07),0xd2,(07) }, - { ASARL, yshl, Px, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) }, - { ASARQ, yshl, Pw, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) }, - { ASARW, yshl, Pe, 0xd1,(07),0xc1,(07),0xd3,(07),0xd3,(07) }, - { ASBBB, yxorb, Pb, 0x1c,0x80,(03),0x18,0x1a }, - { ASBBL, yxorl, Px, 0x83,(03),0x1d,0x81,(03),0x19,0x1b }, - { ASBBQ, yxorl, Pw, 0x83,(03),0x1d,0x81,(03),0x19,0x1b }, - { ASBBW, yxorl, Pe, 0x83,(03),0x1d,0x81,(03),0x19,0x1b }, - { ASCASB, ynone, Pb, 0xae }, - { ASCASL, ynone, Px, 0xaf }, - { ASCASQ, ynone, Pw, 0xaf }, - { ASCASW, ynone, Pe, 0xaf }, - { ASETCC, yscond, Pm, 0x93,(00) }, - { ASETCS, yscond, Pm, 0x92,(00) }, - { ASETEQ, yscond, Pm, 0x94,(00) }, - { ASETGE, yscond, Pm, 0x9d,(00) }, - { ASETGT, yscond, Pm, 0x9f,(00) }, - { ASETHI, yscond, Pm, 0x97,(00) }, - { ASETLE, yscond, Pm, 0x9e,(00) }, - { ASETLS, yscond, Pm, 0x96,(00) }, - { ASETLT, yscond, Pm, 0x9c,(00) }, - { ASETMI, yscond, Pm, 0x98,(00) }, - { ASETNE, yscond, Pm, 0x95,(00) }, - { ASETOC, yscond, Pm, 0x91,(00) }, - { ASETOS, yscond, Pm, 0x90,(00) }, - { ASETPC, yscond, Pm, 0x96,(00) }, - { ASETPL, yscond, Pm, 0x99,(00) }, - { ASETPS, yscond, Pm, 0x9a,(00) }, - { ASHLB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) }, - { ASHLL, yshl, Px, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASHLQ, yshl, Pw, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASHLW, yshl, Pe, 0xd1,(04),0xc1,(04),0xd3,(04),0xd3,(04) }, - { ASHRB, yshb, Pb, 0xd0,(05),0xc0,(05),0xd2,(05) }, - { ASHRL, yshl, Px, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) }, - { ASHRQ, yshl, Pw, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) }, - { ASHRW, yshl, Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) }, - { ASHUFPD, yxshuf, Pq, 0xc6,(00) }, - { ASHUFPS, yxshuf, Pm, 0xc6,(00) }, - { ASQRTPD, yxm, Pe, 0x51 }, - { ASQRTPS, yxm, Pm, 0x51 }, - { ASQRTSD, yxm, Pf2, 0x51 }, - { ASQRTSS, yxm, Pf3, 0x51 }, - { ASTC, ynone, Px, 0xf9 }, - { ASTD, ynone, Px, 0xfd }, - { ASTI, ynone, Px, 0xfb }, - { ASTMXCSR, ysvrs, Pm, 0xae,(03),0xae,(03) }, - { ASTOSB, ynone, Pb, 0xaa }, - { ASTOSL, ynone, Px, 0xab }, - { ASTOSQ, ynone, Pw, 0xab }, - { ASTOSW, ynone, Pe, 0xab }, - { ASUBB, yxorb, Pb, 0x2c,0x80,(05),0x28,0x2a }, - { ASUBL, yaddl, Px, 0x83,(05),0x2d,0x81,(05),0x29,0x2b }, - { ASUBPD, yxm, Pe, 0x5c }, - { ASUBPS, yxm, Pm, 0x5c }, - { ASUBQ, yaddl, Pw, 0x83,(05),0x2d,0x81,(05),0x29,0x2b }, - { ASUBSD, yxm, Pf2, 0x5c }, - { ASUBSS, yxm, Pf3, 0x5c }, - { ASUBW, yaddl, Pe, 0x83,(05),0x2d,0x81,(05),0x29,0x2b }, - { ASWAPGS, ynone, Pm, 0x01,0xf8 }, - { ASYSCALL, ynone, Px, 0x0f,0x05 }, /* fast syscall */ - { ATESTB, ytestb, Pb, 0xa8,0xf6,(00),0x84,0x84 }, - { ATESTL, ytestl, Px, 0xa9,0xf7,(00),0x85,0x85 }, - { ATESTQ, ytestl, Pw, 0xa9,0xf7,(00),0x85,0x85 }, - { ATESTW, ytestl, Pe, 0xa9,0xf7,(00),0x85,0x85 }, - { ATEXT, ytext, Px }, - { AUCOMISD, yxcmp, Pe, 0x2e }, - { AUCOMISS, yxcmp, Pm, 0x2e }, - { AUNPCKHPD, yxm, Pe, 0x15 }, - { AUNPCKHPS, yxm, Pm, 0x15 }, - { AUNPCKLPD, yxm, Pe, 0x14 }, - { AUNPCKLPS, yxm, Pm, 0x14 }, - { AVERR, ydivl, Pm, 0x00,(04) }, - { AVERW, ydivl, Pm, 0x00,(05) }, - { AWAIT, ynone, Px, 0x9b }, - { AWORD, ybyte, Px, 2 }, - { AXCHGB, yml_mb, Pb, 0x86,0x86 }, - { AXCHGL, yxchg, Px, 0x90,0x90,0x87,0x87 }, - { AXCHGQ, yxchg, Pw, 0x90,0x90,0x87,0x87 }, - { AXCHGW, yxchg, Pe, 0x90,0x90,0x87,0x87 }, - { AXLAT, ynone, Px, 0xd7 }, - { AXORB, yxorb, Pb, 0x34,0x80,(06),0x30,0x32 }, - { AXORL, yxorl, Px, 0x83,(06),0x35,0x81,(06),0x31,0x33 }, - { AXORPD, yxm, Pe, 0x57 }, - { AXORPS, yxm, Pm, 0x57 }, - { AXORQ, yxorl, Pw, 0x83,(06),0x35,0x81,(06),0x31,0x33 }, - { AXORW, yxorl, Pe, 0x83,(06),0x35,0x81,(06),0x31,0x33 }, - - { AFMOVB, yfmvx, Px, 0xdf,(04) }, - { AFMOVBP, yfmvp, Px, 0xdf,(06) }, - { AFMOVD, yfmvd, Px, 0xdd,(00),0xdd,(02),0xd9,(00),0xdd,(02) }, - { AFMOVDP, yfmvdp, Px, 0xdd,(03),0xdd,(03) }, - { AFMOVF, yfmvf, Px, 0xd9,(00),0xd9,(02) }, - { AFMOVFP, yfmvp, Px, 0xd9,(03) }, - { AFMOVL, yfmvf, Px, 0xdb,(00),0xdb,(02) }, - { AFMOVLP, yfmvp, Px, 0xdb,(03) }, - { AFMOVV, yfmvx, Px, 0xdf,(05) }, - { AFMOVVP, yfmvp, Px, 0xdf,(07) }, - { AFMOVW, yfmvf, Px, 0xdf,(00),0xdf,(02) }, - { AFMOVWP, yfmvp, Px, 0xdf,(03) }, - { AFMOVX, yfmvx, Px, 0xdb,(05) }, - { AFMOVXP, yfmvp, Px, 0xdb,(07) }, - - { AFCOMB }, - { AFCOMBP }, - { AFCOMD, yfadd, Px, 0xdc,(02),0xd8,(02),0xdc,(02) }, /* botch */ - { AFCOMDP, yfadd, Px, 0xdc,(03),0xd8,(03),0xdc,(03) }, /* botch */ - { AFCOMDPP, ycompp, Px, 0xde,(03) }, - { AFCOMF, yfmvx, Px, 0xd8,(02) }, - { AFCOMFP, yfmvx, Px, 0xd8,(03) }, - { AFCOML, yfmvx, Px, 0xda,(02) }, - { AFCOMLP, yfmvx, Px, 0xda,(03) }, - { AFCOMW, yfmvx, Px, 0xde,(02) }, - { AFCOMWP, yfmvx, Px, 0xde,(03) }, - - { AFUCOM, ycompp, Px, 0xdd,(04) }, - { AFUCOMP, ycompp, Px, 0xdd,(05) }, - { AFUCOMPP, ycompp, Px, 0xda,(13) }, - - { AFADDDP, yfaddp, Px, 0xde,(00) }, - { AFADDW, yfmvx, Px, 0xde,(00) }, - { AFADDL, yfmvx, Px, 0xda,(00) }, - { AFADDF, yfmvx, Px, 0xd8,(00) }, - { AFADDD, yfadd, Px, 0xdc,(00),0xd8,(00),0xdc,(00) }, - - { AFMULDP, yfaddp, Px, 0xde,(01) }, - { AFMULW, yfmvx, Px, 0xde,(01) }, - { AFMULL, yfmvx, Px, 0xda,(01) }, - { AFMULF, yfmvx, Px, 0xd8,(01) }, - { AFMULD, yfadd, Px, 0xdc,(01),0xd8,(01),0xdc,(01) }, - - { AFSUBDP, yfaddp, Px, 0xde,(05) }, - { AFSUBW, yfmvx, Px, 0xde,(04) }, - { AFSUBL, yfmvx, Px, 0xda,(04) }, - { AFSUBF, yfmvx, Px, 0xd8,(04) }, - { AFSUBD, yfadd, Px, 0xdc,(04),0xd8,(04),0xdc,(05) }, - - { AFSUBRDP, yfaddp, Px, 0xde,(04) }, - { AFSUBRW, yfmvx, Px, 0xde,(05) }, - { AFSUBRL, yfmvx, Px, 0xda,(05) }, - { AFSUBRF, yfmvx, Px, 0xd8,(05) }, - { AFSUBRD, yfadd, Px, 0xdc,(05),0xd8,(05),0xdc,(04) }, - - { AFDIVDP, yfaddp, Px, 0xde,(07) }, - { AFDIVW, yfmvx, Px, 0xde,(06) }, - { AFDIVL, yfmvx, Px, 0xda,(06) }, - { AFDIVF, yfmvx, Px, 0xd8,(06) }, - { AFDIVD, yfadd, Px, 0xdc,(06),0xd8,(06),0xdc,(07) }, - - { AFDIVRDP, yfaddp, Px, 0xde,(06) }, - { AFDIVRW, yfmvx, Px, 0xde,(07) }, - { AFDIVRL, yfmvx, Px, 0xda,(07) }, - { AFDIVRF, yfmvx, Px, 0xd8,(07) }, - { AFDIVRD, yfadd, Px, 0xdc,(07),0xd8,(07),0xdc,(06) }, - - { AFXCHD, yfxch, Px, 0xd9,(01),0xd9,(01) }, - { AFFREE }, - { AFLDCW, ystcw, Px, 0xd9,(05),0xd9,(05) }, - { AFLDENV, ystcw, Px, 0xd9,(04),0xd9,(04) }, - { AFRSTOR, ysvrs, Px, 0xdd,(04),0xdd,(04) }, - { AFSAVE, ysvrs, Px, 0xdd,(06),0xdd,(06) }, - { AFSTCW, ystcw, Px, 0xd9,(07),0xd9,(07) }, - { AFSTENV, ystcw, Px, 0xd9,(06),0xd9,(06) }, - { AFSTSW, ystsw, Px, 0xdd,(07),0xdf,0xe0 }, - { AF2XM1, ynone, Px, 0xd9, 0xf0 }, - { AFABS, ynone, Px, 0xd9, 0xe1 }, - { AFCHS, ynone, Px, 0xd9, 0xe0 }, - { AFCLEX, ynone, Px, 0xdb, 0xe2 }, - { AFCOS, ynone, Px, 0xd9, 0xff }, - { AFDECSTP, ynone, Px, 0xd9, 0xf6 }, - { AFINCSTP, ynone, Px, 0xd9, 0xf7 }, - { AFINIT, ynone, Px, 0xdb, 0xe3 }, - { AFLD1, ynone, Px, 0xd9, 0xe8 }, - { AFLDL2E, ynone, Px, 0xd9, 0xea }, - { AFLDL2T, ynone, Px, 0xd9, 0xe9 }, - { AFLDLG2, ynone, Px, 0xd9, 0xec }, - { AFLDLN2, ynone, Px, 0xd9, 0xed }, - { AFLDPI, ynone, Px, 0xd9, 0xeb }, - { AFLDZ, ynone, Px, 0xd9, 0xee }, - { AFNOP, ynone, Px, 0xd9, 0xd0 }, - { AFPATAN, ynone, Px, 0xd9, 0xf3 }, - { AFPREM, ynone, Px, 0xd9, 0xf8 }, - { AFPREM1, ynone, Px, 0xd9, 0xf5 }, - { AFPTAN, ynone, Px, 0xd9, 0xf2 }, - { AFRNDINT, ynone, Px, 0xd9, 0xfc }, - { AFSCALE, ynone, Px, 0xd9, 0xfd }, - { AFSIN, ynone, Px, 0xd9, 0xfe }, - { AFSINCOS, ynone, Px, 0xd9, 0xfb }, - { AFSQRT, ynone, Px, 0xd9, 0xfa }, - { AFTST, ynone, Px, 0xd9, 0xe4 }, - { AFXAM, ynone, Px, 0xd9, 0xe5 }, - { AFXTRACT, ynone, Px, 0xd9, 0xf4 }, - { AFYL2X, ynone, Px, 0xd9, 0xf1 }, - { AFYL2XP1, ynone, Px, 0xd9, 0xf9 }, - - { ACMPXCHGB, yrb_mb, Pb, 0x0f,0xb0 }, - { ACMPXCHGL, yrl_ml, Px, 0x0f,0xb1 }, - { ACMPXCHGW, yrl_ml, Pe, 0x0f,0xb1 }, - { ACMPXCHGQ, yrl_ml, Pw, 0x0f,0xb1 }, - { ACMPXCHG8B, yscond, Pm, 0xc7,(01) }, - { AINVD, ynone, Pm, 0x08 }, - { AINVLPG, ymbs, Pm, 0x01,(07) }, - { ALFENCE, ynone, Pm, 0xae,0xe8 }, - { AMFENCE, ynone, Pm, 0xae,0xf0 }, - { AMOVNTIL, yrl_ml, Pm, 0xc3 }, - { AMOVNTIQ, yrl_ml, Pw, 0x0f,0xc3 }, - { ARDMSR, ynone, Pm, 0x32 }, - { ARDPMC, ynone, Pm, 0x33 }, - { ARDTSC, ynone, Pm, 0x31 }, - { ARSM, ynone, Pm, 0xaa }, - { ASFENCE, ynone, Pm, 0xae,0xf8 }, - { ASYSRET, ynone, Pm, 0x07 }, - { AWBINVD, ynone, Pm, 0x09 }, - { AWRMSR, ynone, Pm, 0x30 }, - - { AXADDB, yrb_mb, Pb, 0x0f,0xc0 }, - { AXADDL, yrl_ml, Px, 0x0f,0xc1 }, - { AXADDQ, yrl_ml, Pw, 0x0f,0xc1 }, - { AXADDW, yrl_ml, Pe, 0x0f,0xc1 }, - - { ACRC32B, ycrc32l,Px, 0xf2,0x0f,0x38,0xf0,0 }, - { ACRC32Q, ycrc32l,Pw, 0xf2,0x0f,0x38,0xf1,0 }, - - { APREFETCHT0, yprefetch, Pm, 0x18,(01) }, - { APREFETCHT1, yprefetch, Pm, 0x18,(02) }, - { APREFETCHT2, yprefetch, Pm, 0x18,(03) }, - { APREFETCHNTA, yprefetch, Pm, 0x18,(00) }, - - { AMOVQL, yrl_ml, Px, 0x89 }, - - { AUNDEF, ynone, Px, 0x0f, 0x0b }, - - { AAESENC, yaes, Pq, 0x38,0xdc,(0) }, - { AAESENCLAST, yaes, Pq, 0x38,0xdd,(0) }, - { AAESDEC, yaes, Pq, 0x38,0xde,(0) }, - { AAESDECLAST, yaes, Pq, 0x38,0xdf,(0) }, - { AAESIMC, yaes, Pq, 0x38,0xdb,(0) }, - { AAESKEYGENASSIST, yaes2, Pq, 0x3a,0xdf,(0) }, - - { APSHUFD, yaes2, Pq, 0x70,(0) }, - { APCLMULQDQ, yxshuf, Pq, 0x3a,0x44,0 }, - - { AUSEFIELD, ynop, Px, 0,0 }, - { AFUNCDATA, yfuncdata, Px, 0,0 }, - { APCDATA, ypcdata, Px, 0,0 }, - - { AEND }, - 0 -}; - -Optab* opindex[ALAST+1]; - -/* -AMOVD 0f 6e/r mmx,reg/mem32[mem64-rex?] -AMOVD 0f 7e/r reg/mem32[64],mmx STORE -AMOVQ 0f 6f/r mmx1,mmx2/mem64 -AMOVQ 0f 7f/r mmx1/mem64,mmx2 -*/ diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c deleted file mode 100644 index 1be3c18fe..000000000 --- a/src/cmd/6l/pass.c +++ /dev/null @@ -1,991 +0,0 @@ -// Inferno utils/6l/pass.c -// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Code and data passes. - -#include "l.h" -#include "../ld/lib.h" -#include "../../pkg/runtime/stack.h" - -static void xfol(Prog*, Prog**); - -Prog* -brchain(Prog *p) -{ - int i; - - for(i=0; i<20; i++) { - if(p == P || p->as != AJMP) - return p; - p = p->pcond; - } - return P; -} - -void -follow(void) -{ - Prog *firstp, *lastp; - - if(debug['v']) - Bprint(&bso, "%5.2f follow\n", cputime()); - Bflush(&bso); - - for(cursym = textp; cursym != nil; cursym = cursym->next) { - firstp = prg(); - lastp = firstp; - xfol(cursym->text, &lastp); - lastp->link = nil; - cursym->text = firstp->link; - } -} - -static int -nofollow(int a) -{ - switch(a) { - case AJMP: - case ARET: - case AIRETL: - case AIRETQ: - case AIRETW: - case ARETFL: - case ARETFQ: - case ARETFW: - case AUNDEF: - return 1; - } - return 0; -} - -static int -pushpop(int a) -{ - switch(a) { - case APUSHL: - case APUSHFL: - case APUSHQ: - case APUSHFQ: - case APUSHW: - case APUSHFW: - case APOPL: - case APOPFL: - case APOPQ: - case APOPFQ: - case APOPW: - case APOPFW: - return 1; - } - return 0; -} - -static void -xfol(Prog *p, Prog **last) -{ - Prog *q; - int i; - enum as a; - -loop: - if(p == P) - return; - if(p->as == AJMP) - if((q = p->pcond) != P && q->as != ATEXT) { - /* mark instruction as done and continue layout at target of jump */ - p->mark = 1; - p = q; - if(p->mark == 0) - goto loop; - } - if(p->mark) { - /* - * p goes here, but already used it elsewhere. - * copy up to 4 instructions or else branch to other copy. - */ - for(i=0,q=p; i<4; i++,q=q->link) { - if(q == P) - break; - if(q == *last) - break; - a = q->as; - if(a == ANOP) { - i--; - continue; - } - if(nofollow(a) || pushpop(a)) - break; // NOTE(rsc): arm does goto copy - if(q->pcond == P || q->pcond->mark) - continue; - if(a == ACALL || a == ALOOP) - continue; - for(;;) { - if(p->as == ANOP) { - p = p->link; - continue; - } - q = copyp(p); - p = p->link; - q->mark = 1; - (*last)->link = q; - *last = q; - if(q->as != a || q->pcond == P || q->pcond->mark) - continue; - - q->as = relinv(q->as); - p = q->pcond; - q->pcond = q->link; - q->link = p; - xfol(q->link, last); - p = q->link; - if(p->mark) - return; - goto loop; - } - } /* */ - q = prg(); - q->as = AJMP; - q->line = p->line; - q->to.type = D_BRANCH; - q->to.offset = p->pc; - q->pcond = p; - p = q; - } - - /* emit p */ - p->mark = 1; - (*last)->link = p; - *last = p; - a = p->as; - - /* continue loop with what comes after p */ - if(nofollow(a)) - return; - if(p->pcond != P && a != ACALL) { - /* - * some kind of conditional branch. - * recurse to follow one path. - * continue loop on the other. - */ - 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); - if(p->pcond->mark) - return; - p = p->pcond; - goto loop; - } - p = p->link; - goto loop; -} - -Prog* -byteq(int v) -{ - Prog *p; - - p = prg(); - p->as = ABYTE; - p->from.type = D_CONST; - p->from.offset = v&0xff; - return p; -} - -int -relinv(int a) -{ - - switch(a) { - case AJEQ: return AJNE; - case AJNE: return AJEQ; - case AJLE: return AJGT; - case AJLS: return AJHI; - case AJLT: return AJGE; - case AJMI: return AJPL; - case AJGE: return AJLT; - case AJPL: return AJMI; - case AJGT: return AJLE; - case AJHI: return AJLS; - case AJCS: return AJCC; - case AJCC: return AJCS; - case AJPS: return AJPC; - case AJPC: return AJPS; - case AJOS: return AJOC; - case AJOC: return AJOS; - } - diag("unknown relation: %s in %s", anames[a], TNAME); - errorexit(); - return a; -} - -void -patch(void) -{ - int32 c; - Prog *p, *q; - Sym *s; - int32 vexit; - Sym *gmsym; - - if(debug['v']) - Bprint(&bso, "%5.2f mkfwd\n", cputime()); - Bflush(&bso); - mkfwd(); - if(debug['v']) - Bprint(&bso, "%5.2f patch\n", cputime()); - Bflush(&bso); - - if(flag_shared) { - s = lookup("init_array", 0); - s->type = SINITARR; - s->reachable = 1; - s->hide = 1; - addaddr(s, lookup(INITENTRY, 0)); - } - - gmsym = lookup("runtime.tlsgm", 0); - if(linkmode != LinkExternal) - gmsym->reachable = 0; - s = lookup("exit", 0); - vexit = s->value; - for(cursym = textp; cursym != nil; cursym = cursym->next) - for(p = cursym->text; p != P; p = p->link) { - if(HEADTYPE == Hwindows) { - // Windows - // Convert - // op n(GS), reg - // to - // MOVL 0x28(GS), reg - // op n(reg), reg - // The purpose of this patch is to fix some accesses - // to extern register variables (TLS) on Windows, as - // a different method is used to access them. - if(p->from.type == D_INDIR+D_GS - && p->to.type >= D_AX && p->to.type <= D_DI - && p->from.offset <= 8) { - q = appendp(p); - q->from = p->from; - q->from.type = D_INDIR + p->to.type; - q->to = p->to; - q->as = p->as; - p->as = AMOVQ; - p->from.type = D_INDIR+D_GS; - p->from.offset = 0x28; - } - } - if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd - || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd - || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) { - // ELF uses FS instead of GS. - if(p->from.type == D_INDIR+D_GS) - p->from.type = D_INDIR+D_FS; - if(p->to.type == D_INDIR+D_GS) - p->to.type = D_INDIR+D_FS; - if(p->from.index == D_GS) - p->from.index = D_FS; - if(p->to.index == D_GS) - p->to.index = D_FS; - } - if(!flag_shared) { - // Convert g() or m() accesses of the form - // op n(reg)(GS*1), reg - // to - // op n(GS*1), reg - if(p->from.index == D_FS || p->from.index == D_GS) { - p->from.type = D_INDIR + p->from.index; - p->from.index = D_NONE; - } - // Convert g() or m() accesses of the form - // op reg, n(reg)(GS*1) - // to - // op reg, n(GS*1) - if(p->to.index == D_FS || p->to.index == D_GS) { - p->to.type = D_INDIR + p->to.index; - p->to.index = D_NONE; - } - // Convert get_tls access of the form - // op runtime.tlsgm(SB), reg - // to - // NOP - if(gmsym != S && p->from.sym == gmsym) { - p->as = ANOP; - p->from.type = D_NONE; - p->to.type = D_NONE; - p->from.sym = nil; - p->to.sym = nil; - continue; - } - } else { - // Convert TLS reads of the form - // op n(GS), reg - // to - // MOVQ $runtime.tlsgm(SB), reg - // op n(reg)(GS*1), reg - if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) { - q = appendp(p); - q->to = p->to; - q->as = p->as; - q->from.type = D_INDIR+p->to.type; - q->from.index = p->from.type - D_INDIR; - q->from.scale = 1; - q->from.offset = p->from.offset; - p->as = AMOVQ; - p->from.type = D_EXTERN; - p->from.sym = gmsym; - p->from.offset = 0; - } - } - if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) { - s = p->to.sym; - if(s) { - if(debug['c']) - Bprint(&bso, "%s calls %s\n", TNAME, s->name); - if((s->type&SMASK) != STEXT) { - /* diag prints TNAME first */ - diag("undefined: %s", s->name); - s->type = STEXT; - s->value = vexit; - continue; // avoid more error messages - } - if(s->text == nil) - continue; - p->to.type = D_BRANCH; - p->to.offset = s->text->pc; - p->pcond = s->text; - continue; - } - } - if(p->to.type != D_BRANCH) - continue; - c = p->to.offset; - for(q = cursym->text; q != P;) { - if(c == q->pc) - break; - if(q->forwd != P && c >= q->forwd->pc) - q = q->forwd; - else - q = q->link; - } - if(q == P) { - diag("branch out of range in %s (%#ux)\n%P [%s]", - TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>"); - p->to.type = D_NONE; - } - p->pcond = q; - } - - for(cursym = textp; cursym != nil; cursym = cursym->next) - for(p = cursym->text; p != P; p = p->link) { - p->mark = 0; /* initialization for follow */ - if(p->pcond != P) { - p->pcond = brloop(p->pcond); - if(p->pcond != P) - if(p->to.type == D_BRANCH) - p->to.offset = p->pcond->pc; - } - } -} - -Prog* -brloop(Prog *p) -{ - int c; - Prog *q; - - c = 0; - for(q = p; q != P; q = q->pcond) { - if(q->as != AJMP) - break; - c++; - if(c >= 5000) - return P; - } - return q; -} - -static char* -morename[] = -{ - "runtime.morestack00", - "runtime.morestack10", - "runtime.morestack01", - "runtime.morestack11", - - "runtime.morestack8", - "runtime.morestack16", - "runtime.morestack24", - "runtime.morestack32", - "runtime.morestack40", - "runtime.morestack48", -}; -Prog* pmorestack[nelem(morename)]; -Sym* symmorestack[nelem(morename)]; -Sym* gmsym; - -static Prog* load_g_cx(Prog*); -static Prog* stacksplit(Prog*, int32, Prog**); - -void -dostkoff(void) -{ - Prog *p, *q, *q1; - int32 autoffset, deltasp; - int a, pcsize; - uint32 i; - - gmsym = lookup("runtime.tlsgm", 0); - for(i=0; i<nelem(morename); i++) { - symmorestack[i] = lookup(morename[i], 0); - if(symmorestack[i]->type != STEXT) - diag("morestack trampoline not defined - %s", morename[i]); - pmorestack[i] = symmorestack[i]->text; - } - - for(cursym = textp; cursym != nil; cursym = cursym->next) { - if(cursym->text == nil || cursym->text->link == nil) - continue; - - p = cursym->text; - parsetextconst(p->to.offset); - autoffset = textstksiz; - if(autoffset < 0) - autoffset = 0; - - if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) { - for(q = p; q != P; q = q->link) - if(q->as == ACALL) - goto noleaf; - p->from.scale |= NOSPLIT; - noleaf:; - } - - if((p->from.scale & NOSPLIT) && autoffset >= StackSmall) - diag("nosplit func likely to overflow stack"); - - q = P; - if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) { - p = appendp(p); - p = load_g_cx(p); // load g into CX - } - if(!(cursym->text->from.scale & NOSPLIT)) - p = stacksplit(p, autoffset, &q); // emit split check - - if(autoffset) { - p = appendp(p); - p->as = AADJSP; - p->from.type = D_CONST; - p->from.offset = autoffset; - p->spadj = autoffset; - } 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; - } - if(q != P) - q->pcond = p; - deltasp = autoffset; - - if(cursym->text->from.scale & WRAPPER) { - // g->panicwrap += autoffset + PtrSize; - p = appendp(p); - p->as = AADDL; - p->from.type = D_CONST; - p->from.offset = autoffset + PtrSize; - p->to.type = D_INDIR+D_CX; - p->to.offset = 2*PtrSize; - } - - if(debug['K'] > 1 && autoffset) { - // 6l -KK means double-check for stack overflow - // even after calling morestack and even if the - // function is marked as nosplit. - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_BX; - - p = appendp(p); - p->as = ASUBQ; - p->from.type = D_CONST; - p->from.offset = StackSmall+32; - p->to.type = D_BX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SP; - p->to.type = D_BX; - - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - q1 = p; - - p = appendp(p); - p->as = AINT; - p->from.type = D_CONST; - p->from.offset = 3; - - p = appendp(p); - p->as = ANOP; - q1->pcond = p; - } - - if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) { - // 6l -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 = AMOVQ; - p->from.type = D_SP; - p->to.type = D_DI; - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_CONST; - p->from.offset = autoffset/8; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVQ; - 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 = ASTOSQ; - } - - for(; p != P; p = p->link) { - pcsize = p->mode/8; - a = p->from.type; - if(a == D_AUTO) - p->from.offset += deltasp; - if(a == D_PARAM) - p->from.offset += deltasp + pcsize; - a = p->to.type; - if(a == D_AUTO) - p->to.offset += deltasp; - if(a == D_PARAM) - p->to.offset += deltasp + pcsize; - - switch(p->as) { - default: - continue; - case APUSHL: - case APUSHFL: - deltasp += 4; - p->spadj = 4; - continue; - case APUSHQ: - case APUSHFQ: - deltasp += 8; - p->spadj = 8; - continue; - case APUSHW: - case APUSHFW: - deltasp += 2; - p->spadj = 2; - continue; - case APOPL: - case APOPFL: - deltasp -= 4; - p->spadj = -4; - continue; - case APOPQ: - case APOPFQ: - deltasp -= 8; - p->spadj = -8; - continue; - case APOPW: - case APOPFW: - deltasp -= 2; - p->spadj = -2; - continue; - case ARET: - break; - } - - if(autoffset != deltasp) - diag("unbalanced PUSH/POP"); - - if(cursym->text->from.scale & WRAPPER) { - p = load_g_cx(p); - p = appendp(p); - // g->panicwrap -= autoffset + PtrSize; - p->as = ASUBL; - p->from.type = D_CONST; - p->from.offset = autoffset + PtrSize; - p->to.type = D_INDIR+D_CX; - p->to.offset = 2*PtrSize; - p = appendp(p); - p->as = ARET; - } - - if(autoffset) { - p->as = AADJSP; - p->from.type = D_CONST; - p->from.offset = -autoffset; - p->spadj = -autoffset; - p = appendp(p); - p->as = ARET; - // If there are instructions following - // this ARET, they come from a branch - // with the same stackframe, so undo - // the cleanup. - p->spadj = +autoffset; - } - if(p->to.sym) // retjmp - p->as = AJMP; - } - } -} - -// 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 -// prologue (caller must call appendp first) and in the epilogue. -// Returns last new instruction. -static Prog* -load_g_cx(Prog *p) -{ - if(flag_shared) { - // Load TLS offset with MOVQ $runtime.tlsgm(SB), CX - p->as = AMOVQ; - p->from.type = D_EXTERN; - p->from.sym = gmsym; - p->to.type = D_CX; - p = appendp(p); - } - p->as = AMOVQ; - if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd - || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd - || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) - // ELF uses FS - p->from.type = D_INDIR+D_FS; - else - p->from.type = D_INDIR+D_GS; - if(flag_shared) { - // Add TLS offset stored in CX - p->from.index = p->from.type - D_INDIR; - p->from.type = D_INDIR + D_CX; - } - p->from.offset = tlsoffset+0; - p->to.type = D_CX; - if(HEADTYPE == Hwindows) { - // movq %gs:0x28, %rcx - // movq (%rcx), %rcx - p->as = AMOVQ; - p->from.type = D_INDIR+D_GS; - p->from.offset = 0x28; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_CX; - } - return p; -} - -// Append code to p to check for stack split. -// Appends to (does not overwrite) p. -// Assumes g is in CX. -// Returns last new instruction. -// On return, *jmpok is the instruction that should jump -// to the stack frame allocation if no split is needed. -static Prog* -stacksplit(Prog *p, int32 framesize, Prog **jmpok) -{ - Prog *q, *q1; - uint32 moreconst1, moreconst2, i; - - if(debug['K']) { - // 6l -K means check not only for stack - // overflow but stack underflow. - // On underflow, INT 3 (breakpoint). - // Underflow itself is rare but this also - // catches out-of-sync stack guard info - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 8; - p->to.type = D_SP; - - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - p->to.offset = 4; - q1 = p; - - p = appendp(p); - p->as = AINT; - p->from.type = D_CONST; - p->from.offset = 3; - - p = appendp(p); - p->as = ANOP; - q1->pcond = p; - } - - q = P; - q1 = P; - if(framesize <= StackSmall) { - // small stack: SP <= stackguard - // CMPQ SP, stackguard - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SP; - p->to.type = D_INDIR+D_CX; - } else if(framesize <= StackBig) { - // large stack: SP-framesize <= stackguard-StackSmall - // LEAQ -xxx(SP), AX - // CMPQ AX, stackguard - p = appendp(p); - p->as = ALEAQ; - p->from.type = D_INDIR+D_SP; - p->from.offset = -(framesize-StackSmall); - p->to.type = D_AX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_AX; - p->to.type = D_INDIR+D_CX; - } else { - // Such a large stack we need to protect against wraparound. - // If SP is close to zero: - // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall) - // The +StackGuard on both sides is required to keep the left side positive: - // SP is allowed to be slightly below stackguard. See stack.h. - // - // Preemption sets stackguard to StackPreempt, a very large value. - // That breaks the math above, so we have to check for that explicitly. - // MOVQ stackguard, CX - // CMPQ CX, $StackPreempt - // JEQ label-of-call-to-morestack - // LEAQ StackGuard(SP), AX - // SUBQ CX, AX - // CMPQ AX, $(framesize+(StackGuard-StackSmall)) - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_SI; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SI; - p->to.type = D_CONST; - p->to.offset = StackPreempt; - - p = appendp(p); - p->as = AJEQ; - p->to.type = D_BRANCH; - q1 = p; - - p = appendp(p); - p->as = ALEAQ; - p->from.type = D_INDIR+D_SP; - p->from.offset = StackGuard; - p->to.type = D_AX; - - p = appendp(p); - p->as = ASUBQ; - p->from.type = D_SI; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_AX; - p->to.type = D_CONST; - p->to.offset = framesize+(StackGuard-StackSmall); - } - - // common - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - q = p; - - // If we ask for more stack, we'll get a minimum of StackMin bytes. - // We need a stack frame large enough to hold the top-of-stack data, - // the function arguments+results, our caller's PC, our frame, - // a word for the return PC of the next call, and then the StackLimit bytes - // that must be available on entry to any function called from a function - // that did a stack check. If StackMin is enough, don't ask for a specific - // amount: then we can use the custom functions and save a few - // instructions. - moreconst1 = 0; - if(StackTop + textarg + PtrSize + framesize + PtrSize + StackLimit >= StackMin) - moreconst1 = framesize; - moreconst2 = textarg; - if(moreconst2 == 1) // special marker - moreconst2 = 0; - if((moreconst2&7) != 0) - diag("misaligned argument size in stack split"); - // 4 varieties varieties (const1==0 cross const2==0) - // and 6 subvarieties of (const1==0 and const2!=0) - p = appendp(p); - if(moreconst1 == 0 && moreconst2 == 0) { - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[0]; - p->to.sym = symmorestack[0]; - } else - if(moreconst1 != 0 && moreconst2 == 0) { - p->as = AMOVL; - p->from.type = D_CONST; - p->from.offset = moreconst1; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[1]; - p->to.sym = symmorestack[1]; - } else - if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) { - i = moreconst2/8 + 3; - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[i]; - p->to.sym = symmorestack[i]; - } else - if(moreconst1 == 0 && moreconst2 != 0) { - p->as = AMOVL; - p->from.type = D_CONST; - p->from.offset = moreconst2; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[2]; - p->to.sym = symmorestack[2]; - } else { - p->as = AMOVQ; - p->from.type = D_CONST; - p->from.offset = (uint64)moreconst2 << 32; - p->from.offset |= moreconst1; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[3]; - p->to.sym = symmorestack[3]; - } - - p = appendp(p); - p->as = AJMP; - p->to.type = D_BRANCH; - p->pcond = cursym->text->link; - - if(q != P) - q->pcond = p->link; - if(q1 != P) - q1->pcond = q->link; - - *jmpok = q; - return p; -} - -vlong -atolwhex(char *s) -{ - vlong n; - int f; - - n = 0; - f = 0; - while(*s == ' ' || *s == '\t') - s++; - if(*s == '-' || *s == '+') { - if(*s++ == '-') - f = 1; - while(*s == ' ' || *s == '\t') - s++; - } - if(s[0]=='0' && s[1]){ - if(s[1]=='x' || s[1]=='X'){ - s += 2; - for(;;){ - if(*s >= '0' && *s <= '9') - n = n*16 + *s++ - '0'; - else if(*s >= 'a' && *s <= 'f') - n = n*16 + *s++ - 'a' + 10; - else if(*s >= 'A' && *s <= 'F') - n = n*16 + *s++ - 'A' + 10; - else - break; - } - } else - while(*s >= '0' && *s <= '7') - n = n*8 + *s++ - '0'; - } else - while(*s >= '0' && *s <= '9') - n = n*10 + *s++ - '0'; - if(f) - n = -n; - return n; -} diff --git a/src/cmd/6l/prof.c b/src/cmd/6l/prof.c deleted file mode 100644 index 862ce080c..000000000 --- a/src/cmd/6l/prof.c +++ /dev/null @@ -1,171 +0,0 @@ -// Inferno utils/6l/obj.c -// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Profiling. - -#include "l.h" -#include "../ld/lib.h" - -void -doprof1(void) -{ -#ifdef NOTDEF - Sym *s; - int32 n; - Prog *p, *q; - - if(debug['v']) - Bprint(&bso, "%5.2f profile 1\n", cputime()); - Bflush(&bso); - s = lookup("__mcount", 0); - n = 1; - for(cursym = textp; cursym != nil; cursym = cursym->next) { - p = cursym->text; - q = prg(); - q->line = p->line; - q->link = datap; - datap = q; - q->as = ADATA; - q->from.type = D_EXTERN; - q->from.offset = n*4; - q->from.sym = s; - q->from.scale = 4; - q->to = p->from; - q->to.type = D_CONST; - - q = prg(); - q->line = p->line; - q->pc = p->pc; - q->link = p->link; - p->link = q; - p = q; - p->as = AADDL; - p->from.type = D_CONST; - p->from.offset = 1; - p->to.type = D_EXTERN; - p->to.sym = s; - p->to.offset = n*4 + 4; - - n += 2; - } - q = prg(); - q->line = 0; - q->link = datap; - datap = q; - - q->as = ADATA; - q->from.type = D_EXTERN; - q->from.sym = s; - q->from.scale = 4; - q->to.type = D_CONST; - q->to.offset = n; - - s->type = SBSS; - s->size = n*4; -#endif -} - -void -doprof2(void) -{ - Sym *s2, *s4; - Prog *p, *q, *ps2, *ps4; - - if(debug['v']) - Bprint(&bso, "%5.2f profile 2\n", cputime()); - Bflush(&bso); - - s2 = lookup("_profin", 0); - s4 = lookup("_profout", 0); - if(s2->type != STEXT || s4->type != STEXT) { - diag("_profin/_profout not defined"); - return; - } - - ps2 = P; - ps4 = P; - for(cursym = textp; cursym != nil; cursym = cursym->next) { - p = cursym->text; - if(p->from.sym == s2) { - p->from.scale = 1; - ps2 = p; - } - if(p->from.sym == s4) { - p->from.scale = 1; - ps4 = p; - } - } - for(cursym = textp; cursym != nil; cursym = cursym->next) { - p = cursym->text; - - if(p->from.scale & NOPROF) /* dont profile */ - continue; - - /* - * JMPL profin - */ - q = prg(); - q->line = p->line; - q->pc = p->pc; - q->link = p->link; - p->link = q; - p = q; - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = ps2; - p->to.sym = s2; - - for(; p; p=p->link) { - if(p->as == ARET) { - /* - * RET - */ - q = prg(); - q->as = ARET; - q->from = p->from; - q->to = p->to; - q->link = p->link; - p->link = q; - - /* - * JAL profout - */ - p->as = ACALL; - p->from = zprg.from; - p->to = zprg.to; - p->to.type = D_BRANCH; - p->pcond = ps4; - p->to.sym = s4; - - p = q; - } - } - } -} diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c deleted file mode 100644 index 74f11d635..000000000 --- a/src/cmd/6l/span.c +++ /dev/null @@ -1,1846 +0,0 @@ -// Inferno utils/6l/span.c -// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Instruction layout. - -#include "l.h" -#include "../ld/lib.h" -#include "../ld/elf.h" - -static int rexflag; -static int asmode; -static vlong vaddr(Adr*, Reloc*); - -// single-instruction no-ops of various lengths. -// constructed by hand and disassembled with gdb to verify. -// see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion. -static uchar nop[][16] = { - {0x90}, - {0x66, 0x90}, - {0x0F, 0x1F, 0x00}, - {0x0F, 0x1F, 0x40, 0x00}, - {0x0F, 0x1F, 0x44, 0x00, 0x00}, - {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00}, - {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00}, - {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, -}; - -static void -fillnop(uchar *p, int n) -{ - int m; - - while(n > 0) { - m = n; - if(m > nelem(nop)) - m = nelem(nop); - memmove(p, nop[m-1], m); - p += m; - n -= m; - } -} - -void -span1(Sym *s) -{ - Prog *p, *q; - int32 c, v, loop; - uchar *bp; - int n, m, i; - - cursym = s; - - if(s->p != nil) - return; - - for(p = s->text; p != P; p = p->link) { - p->back = 2; // use short branches first time through - if((q = p->pcond) != P && (q->back & 2)) { - p->back |= 1; // backward jump - q->back |= 4; // loop head - } - - if(p->as == AADJSP) { - p->to.type = D_SP; - v = -p->from.offset; - p->from.offset = v; - p->as = p->mode != 64? AADDL: AADDQ; - if(v < 0) { - p->as = p->mode != 64? ASUBL: ASUBQ; - v = -v; - p->from.offset = v; - } - if(v == 0) - p->as = ANOP; - } - } - - n = 0; - do { - loop = 0; - memset(s->r, 0, s->nr*sizeof s->r[0]); - s->nr = 0; - s->np = 0; - c = 0; - for(p = s->text; p != P; p = p->link) { - if((p->back & 4) && (c&(LoopAlign-1)) != 0) { - // pad with NOPs - v = -c&(LoopAlign-1); - if(v <= MaxLoopPad) { - symgrow(s, c+v); - fillnop(s->p+c, v); - c += v; - } - } - - p->pc = c; - - // process forward jumps to p - for(q = p->comefrom; q != P; q = q->forwd) { - v = p->pc - (q->pc + q->mark); - if(q->back & 2) { // short - if(v > 127) { - loop++; - q->back ^= 2; - } - if(q->as == AJCXZL) - s->p[q->pc+2] = v; - else - s->p[q->pc+1] = v; - } else { - bp = s->p + q->pc + q->mark - 4; - *bp++ = v; - *bp++ = v>>8; - *bp++ = v>>16; - *bp = v>>24; - } - } - p->comefrom = P; - - asmins(p); - p->pc = c; - m = andptr-and; - symgrow(s, p->pc+m); - memmove(s->p+p->pc, and, m); - p->mark = m; - c += m; - } - if(++n > 20) { - diag("span must be looping"); - errorexit(); - } - } while(loop); - s->size = c; - - if(debug['a'] > 1) { - print("span1 %s %lld (%d tries)\n %.6ux", s->name, s->size, n, 0); - for(i=0; i<s->np; i++) { - print(" %.2ux", s->p[i]); - if(i%16 == 15) - print("\n %.6ux", i+1); - } - if(i%16) - print("\n"); - - for(i=0; i<s->nr; i++) { - Reloc *r; - - r = &s->r[i]; - print(" rel %#.4ux/%d %s%+lld\n", r->off, r->siz, r->sym->name, r->add); - } - } -} - -void -span(void) -{ - Prog *p, *q; - int32 v; - int n; - - if(debug['v']) - Bprint(&bso, "%5.2f span\n", cputime()); - - // NOTE(rsc): If we get rid of the globals we should - // be able to parallelize these iterations. - for(cursym = textp; cursym != nil; cursym = cursym->next) { - if(cursym->p != nil) - continue; - // TODO: move into span1 - for(p = cursym->text; p != P; p = p->link) { - n = 0; - if(p->to.type == D_BRANCH) - if(p->pcond == P) - p->pcond = p; - if((q = p->pcond) != P) - if(q->back != 2) - n = 1; - p->back = n; - if(p->as == AADJSP) { - p->to.type = D_SP; - v = -p->from.offset; - p->from.offset = v; - p->as = p->mode != 64? AADDL: AADDQ; - if(v < 0) { - p->as = p->mode != 64? ASUBL: ASUBQ; - v = -v; - p->from.offset = v; - } - if(v == 0) - p->as = ANOP; - } - } - span1(cursym); - } -} - -void -xdefine(char *p, int t, vlong v) -{ - Sym *s; - - s = lookup(p, 0); - s->type = t; - s->value = v; - s->reachable = 1; - s->special = 1; -} - -void -instinit(void) -{ - int c, i; - - for(i=1; optab[i].as; i++) { - c = optab[i].as; - if(opindex[c] != nil) { - diag("phase error in optab: %d (%A)", i, c); - errorexit(); - } - opindex[c] = &optab[i]; - } - - for(i=0; i<Ymax; i++) - ycover[i*Ymax + i] = 1; - - ycover[Yi0*Ymax + Yi8] = 1; - ycover[Yi1*Ymax + Yi8] = 1; - - ycover[Yi0*Ymax + Ys32] = 1; - ycover[Yi1*Ymax + Ys32] = 1; - ycover[Yi8*Ymax + Ys32] = 1; - - ycover[Yi0*Ymax + Yi32] = 1; - ycover[Yi1*Ymax + Yi32] = 1; - ycover[Yi8*Ymax + Yi32] = 1; - ycover[Ys32*Ymax + Yi32] = 1; - - ycover[Yi0*Ymax + Yi64] = 1; - ycover[Yi1*Ymax + Yi64] = 1; - ycover[Yi8*Ymax + Yi64] = 1; - ycover[Ys32*Ymax + Yi64] = 1; - ycover[Yi32*Ymax + Yi64] = 1; - - ycover[Yal*Ymax + Yrb] = 1; - ycover[Ycl*Ymax + Yrb] = 1; - ycover[Yax*Ymax + Yrb] = 1; - ycover[Ycx*Ymax + Yrb] = 1; - ycover[Yrx*Ymax + Yrb] = 1; - ycover[Yrl*Ymax + Yrb] = 1; - - ycover[Ycl*Ymax + Ycx] = 1; - - ycover[Yax*Ymax + Yrx] = 1; - ycover[Ycx*Ymax + Yrx] = 1; - - ycover[Yax*Ymax + Yrl] = 1; - ycover[Ycx*Ymax + Yrl] = 1; - ycover[Yrx*Ymax + Yrl] = 1; - - ycover[Yf0*Ymax + Yrf] = 1; - - ycover[Yal*Ymax + Ymb] = 1; - ycover[Ycl*Ymax + Ymb] = 1; - ycover[Yax*Ymax + Ymb] = 1; - ycover[Ycx*Ymax + Ymb] = 1; - ycover[Yrx*Ymax + Ymb] = 1; - ycover[Yrb*Ymax + Ymb] = 1; - ycover[Yrl*Ymax + Ymb] = 1; - ycover[Ym*Ymax + Ymb] = 1; - - ycover[Yax*Ymax + Yml] = 1; - ycover[Ycx*Ymax + Yml] = 1; - ycover[Yrx*Ymax + Yml] = 1; - 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_R15B) { - reg[i] = (i-D_AL) & 7; - if(i >= D_SPB && i <= D_DIB) - regrex[i] = 0x40; - if(i >= D_R8B && i <= D_R15B) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_AH && i<= D_BH) - reg[i] = 4 + ((i-D_AH) & 7); - if(i >= D_AX && i <= D_R15) { - reg[i] = (i-D_AX) & 7; - if(i >= D_R8) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_F0 && i <= D_F0+7) - reg[i] = (i-D_F0) & 7; - if(i >= D_M0 && i <= D_M0+7) - reg[i] = (i-D_M0) & 7; - if(i >= D_X0 && i <= D_X0+15) { - reg[i] = (i-D_X0) & 7; - if(i >= D_X0+8) - regrex[i] = Rxr | Rxx | Rxb; - } - if(i >= D_CR+8 && i <= D_CR+15) - regrex[i] = Rxr; - } -} - -int -prefixof(Adr *a) -{ - switch(a->type) { - case D_INDIR+D_CS: - return 0x2e; - case D_INDIR+D_DS: - return 0x3e; - case D_INDIR+D_ES: - return 0x26; - case D_INDIR+D_FS: - return 0x64; - case D_INDIR+D_GS: - return 0x65; - } - switch(a->index) { - case D_CS: - return 0x2e; - case D_DS: - return 0x3e; - case D_ES: - return 0x26; - case D_FS: - return 0x64; - case D_GS: - return 0x65; - } - return 0; -} - -int -oclass(Adr *a) -{ - vlong v; - int32 l; - - if(a->type >= D_INDIR || a->index != D_NONE) { - if(a->index != D_NONE && a->scale == 0) { - if(a->type == D_ADDR) { - switch(a->index) { - case D_EXTERN: - case D_STATIC: - if(flag_shared) - return Yiauto; - else - return Yi32; /* TO DO: Yi64 */ - case D_AUTO: - case D_PARAM: - return Yiauto; - } - return Yxxx; - } - return Ycol; - } - return Ym; - } - switch(a->type) - { - case D_AL: - return Yal; - - case D_AX: - return Yax; - -/* - case D_SPB: -*/ - case D_BPB: - case D_SIB: - case D_DIB: - case D_R8B: - case D_R9B: - case D_R10B: - case D_R11B: - case D_R12B: - case D_R13B: - case D_R14B: - case D_R15B: - if(asmode != 64) - return Yxxx; - case D_DL: - case D_BL: - case D_AH: - case D_CH: - case D_DH: - case D_BH: - return Yrb; - - case D_CL: - return Ycl; - - case D_CX: - return Ycx; - - case D_DX: - case D_BX: - return Yrx; - - case D_R8: /* not really Yrl */ - case D_R9: - case D_R10: - case D_R11: - case D_R12: - case D_R13: - case D_R14: - case D_R15: - if(asmode != 64) - return Yxxx; - case D_SP: - case D_BP: - case D_SI: - case D_DI: - return Yrl; - - case D_F0+0: - return Yf0; - - case D_F0+1: - case D_F0+2: - case D_F0+3: - case D_F0+4: - case D_F0+5: - case D_F0+6: - case D_F0+7: - return Yrf; - - case D_M0+0: - case D_M0+1: - case D_M0+2: - case D_M0+3: - case D_M0+4: - case D_M0+5: - case D_M0+6: - case D_M0+7: - return Ymr; - - 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: - case D_X0+8: - case D_X0+9: - case D_X0+10: - case D_X0+11: - case D_X0+12: - case D_X0+13: - case D_X0+14: - case D_X0+15: - return Yxr; - - case D_NONE: - return Ynone; - - case D_CS: return Ycs; - case D_SS: return Yss; - case D_DS: return Yds; - case D_ES: return Yes; - case D_FS: return Yfs; - case D_GS: return Ygs; - - case D_GDTR: return Ygdtr; - case D_IDTR: return Yidtr; - case D_LDTR: return Yldtr; - case D_MSW: return Ymsw; - case D_TASK: return Ytask; - - case D_CR+0: return Ycr0; - case D_CR+1: return Ycr1; - case D_CR+2: return Ycr2; - case D_CR+3: return Ycr3; - case D_CR+4: return Ycr4; - case D_CR+5: return Ycr5; - case D_CR+6: return Ycr6; - case D_CR+7: return Ycr7; - case D_CR+8: return Ycr8; - - case D_DR+0: return Ydr0; - case D_DR+1: return Ydr1; - case D_DR+2: return Ydr2; - case D_DR+3: return Ydr3; - case D_DR+4: return Ydr4; - case D_DR+5: return Ydr5; - case D_DR+6: return Ydr6; - case D_DR+7: return Ydr7; - - case D_TR+0: return Ytr0; - case D_TR+1: return Ytr1; - case D_TR+2: return Ytr2; - case D_TR+3: return Ytr3; - case D_TR+4: return Ytr4; - case D_TR+5: return Ytr5; - case D_TR+6: return Ytr6; - case D_TR+7: return Ytr7; - - case D_EXTERN: - case D_STATIC: - case D_AUTO: - case D_PARAM: - return Ym; - - case D_CONST: - case D_ADDR: - if(a->sym == S) { - v = a->offset; - if(v == 0) - return Yi0; - if(v == 1) - return Yi1; - if(v >= -128 && v <= 127) - return Yi8; - l = v; - if((vlong)l == v) - return Ys32; /* can sign extend */ - if((v>>32) == 0) - return Yi32; /* unsigned */ - return Yi64; - } - return Yi32; /* TO DO: D_ADDR as Yi64 */ - - case D_BRANCH: - return Ybr; - } - return Yxxx; -} - -void -asmidx(int scale, int index, int base) -{ - int i; - - switch(index) { - default: - goto bad; - - case D_NONE: - i = 4 << 3; - goto bas; - - case D_R8: - case D_R9: - case D_R10: - case D_R11: - case D_R12: - case D_R13: - case D_R14: - case D_R15: - if(asmode != 64) - goto bad; - case D_AX: - case D_CX: - case D_DX: - case D_BX: - case D_BP: - case D_SI: - case D_DI: - i = reg[index] << 3; - break; - } - switch(scale) { - default: - goto bad; - case 1: - break; - case 2: - i |= (1<<6); - break; - case 4: - i |= (2<<6); - break; - case 8: - i |= (3<<6); - break; - } -bas: - switch(base) { - default: - goto bad; - case D_NONE: /* must be mod=00 */ - i |= 5; - break; - case D_R8: - case D_R9: - case D_R10: - case D_R11: - case D_R12: - case D_R13: - case D_R14: - case D_R15: - if(asmode != 64) - goto bad; - case D_AX: - case D_CX: - case D_DX: - case D_BX: - case D_SP: - case D_BP: - case D_SI: - case D_DI: - i |= reg[base]; - break; - } - *andptr++ = i; - return; -bad: - diag("asmidx: bad address %d/%d/%d", scale, index, base); - *andptr++ = 0; - return; -} - -static void -put4(int32 v) -{ - andptr[0] = v; - andptr[1] = v>>8; - andptr[2] = v>>16; - andptr[3] = v>>24; - andptr += 4; -} - -static void -relput4(Prog *p, Adr *a) -{ - vlong v; - Reloc rel, *r; - - v = vaddr(a, &rel); - if(rel.siz != 0) { - if(rel.siz != 4) - diag("bad reloc"); - r = addrel(cursym); - *r = rel; - r->off = p->pc + andptr - and; - } - put4(v); -} - -static void -put8(vlong v) -{ - andptr[0] = v; - andptr[1] = v>>8; - andptr[2] = v>>16; - andptr[3] = v>>24; - andptr[4] = v>>32; - andptr[5] = v>>40; - andptr[6] = v>>48; - andptr[7] = v>>56; - andptr += 8; -} - -/* -static void -relput8(Prog *p, Adr *a) -{ - vlong v; - Reloc rel, *r; - - v = vaddr(a, &rel); - if(rel.siz != 0) { - r = addrel(cursym); - *r = rel; - r->siz = 8; - r->off = p->pc + andptr - and; - } - put8(v); -} -*/ - -vlong -symaddr(Sym *s) -{ - if(!s->reachable) - diag("unreachable symbol in symaddr - %s", s->name); - return s->value; -} - -static vlong -vaddr(Adr *a, Reloc *r) -{ - int t; - vlong v; - Sym *s; - - if(r != nil) - memset(r, 0, sizeof *r); - - t = a->type; - v = a->offset; - if(t == D_ADDR) - t = a->index; - switch(t) { - case D_STATIC: - case D_EXTERN: - s = a->sym; - if(!s->reachable) - diag("unreachable symbol in vaddr - %s", s->name); - if(r == nil) { - diag("need reloc for %D", a); - errorexit(); - } - r->siz = 4; // TODO: 8 for external symbols - r->off = -1; // caller must fill in - r->sym = s; - r->add = v; - v = 0; - if(flag_shared) { - if(s->type == STLSBSS) { - r->xadd = r->add - r->siz; - r->type = D_TLS; - r->xsym = s; - } else - r->type = D_PCREL; - } else - r->type = D_ADDR; - } - return v; -} - -static void -asmandsz(Adr *a, int r, int rex, int m64) -{ - int32 v; - int t, scale; - Reloc rel; - - USED(m64); - rex &= (0x40 | Rxr); - v = a->offset; - t = a->type; - rel.siz = 0; - if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) { - if(t < D_INDIR) { - switch(t) { - default: - goto bad; - case D_STATIC: - case D_EXTERN: - if(flag_shared) - goto bad; - t = D_NONE; - v = vaddr(a, &rel); - break; - case D_AUTO: - case D_PARAM: - t = D_SP; - break; - } - } else - t -= D_INDIR; - rexflag |= (regrex[(int)a->index] & Rxx) | (regrex[t] & Rxb) | rex; - if(t == D_NONE) { - *andptr++ = (0 << 6) | (4 << 0) | (r << 3); - asmidx(a->scale, a->index, t); - goto putrelv; - } - if(v == 0 && rel.siz == 0 && t != D_BP && t != D_R13) { - *andptr++ = (0 << 6) | (4 << 0) | (r << 3); - asmidx(a->scale, a->index, t); - return; - } - if(v >= -128 && v < 128 && rel.siz == 0) { - *andptr++ = (1 << 6) | (4 << 0) | (r << 3); - asmidx(a->scale, a->index, t); - *andptr++ = v; - return; - } - *andptr++ = (2 << 6) | (4 << 0) | (r << 3); - asmidx(a->scale, a->index, t); - goto putrelv; - } - if(t >= D_AL && t <= D_X0+15) { - if(v) - goto bad; - *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); - rexflag |= (regrex[t] & (0x40 | Rxb)) | rex; - return; - } - - scale = a->scale; - if(t < D_INDIR) { - switch(a->type) { - default: - goto bad; - case D_STATIC: - case D_EXTERN: - t = D_NONE; - v = vaddr(a, &rel); - break; - case D_AUTO: - case D_PARAM: - t = D_SP; - break; - } - scale = 1; - } else - t -= D_INDIR; - - rexflag |= (regrex[t] & Rxb) | rex; - if(t == D_NONE || (D_CS <= t && t <= D_GS)) { - if(flag_shared && t == D_NONE && (a->type == D_STATIC || a->type == D_EXTERN) || asmode != 64) { - *andptr++ = (0 << 6) | (5 << 0) | (r << 3); - goto putrelv; - } - /* temporary */ - *andptr++ = (0 << 6) | (4 << 0) | (r << 3); /* sib present */ - *andptr++ = (0 << 6) | (4 << 3) | (5 << 0); /* DS:d32 */ - goto putrelv; - } - if(t == D_SP || t == D_R12) { - if(v == 0) { - *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); - asmidx(scale, D_NONE, t); - return; - } - if(v >= -128 && v < 128) { - *andptr++ = (1 << 6) | (reg[t] << 0) | (r << 3); - asmidx(scale, D_NONE, t); - *andptr++ = v; - return; - } - *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); - asmidx(scale, D_NONE, t); - goto putrelv; - } - if(t >= D_AX && t <= D_R15) { - if(v == 0 && t != D_BP && t != D_R13) { - *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); - return; - } - if(v >= -128 && v < 128) { - andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); - andptr[1] = v; - andptr += 2; - return; - } - *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); - goto putrelv; - } - goto bad; - -putrelv: - if(rel.siz != 0) { - Reloc *r; - - if(rel.siz != 4) { - diag("bad rel"); - goto bad; - } - r = addrel(cursym); - *r = rel; - r->off = curp->pc + andptr - and; - } else if(iself && linkmode == LinkExternal && a->type == D_INDIR+D_FS - && HEADTYPE != Hopenbsd) { - Reloc *r; - Sym *s; - - r = addrel(cursym); - r->off = curp->pc + andptr - and; - r->add = a->offset-tlsoffset; - r->xadd = r->add; - r->siz = 4; - r->type = D_TLS; - s = lookup("runtime.tlsgm", 0); - r->sym = s; - r->xsym = s; - v = 0; - } - - put4(v); - return; - -bad: - diag("asmand: bad address %D", a); - return; -} - -void -asmand(Adr *a, Adr *ra) -{ - asmandsz(a, reg[ra->type], regrex[ra->type], 0); -} - -void -asmando(Adr *a, int o) -{ - asmandsz(a, o, 0, 0); -} - -static void -bytereg(Adr *a, char *t) -{ - if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15)) { - a->type = D_AL + (a->type-D_AX); - *t = 0; - } -} - -#define E 0xff -Movtab ymovtab[] = -{ -/* push */ - {APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0}, - {APUSHL, Yss, Ynone, 0, 0x16,E,0,0}, - {APUSHL, Yds, Ynone, 0, 0x1e,E,0,0}, - {APUSHL, Yes, Ynone, 0, 0x06,E,0,0}, - {APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0}, - {APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0}, - {APUSHQ, Yfs, Ynone, 0, 0x0f,0xa0,E,0}, - {APUSHQ, Ygs, Ynone, 0, 0x0f,0xa8,E,0}, - - {APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0}, - {APUSHW, Yss, Ynone, 0, Pe,0x16,E,0}, - {APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0}, - {APUSHW, Yes, Ynone, 0, Pe,0x06,E,0}, - {APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E}, - {APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E}, - -/* pop */ - {APOPL, Ynone, Yds, 0, 0x1f,E,0,0}, - {APOPL, Ynone, Yes, 0, 0x07,E,0,0}, - {APOPL, Ynone, Yss, 0, 0x17,E,0,0}, - {APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0}, - {APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0}, - {APOPQ, Ynone, Yfs, 0, 0x0f,0xa1,E,0}, - {APOPQ, Ynone, Ygs, 0, 0x0f,0xa9,E,0}, - - {APOPW, Ynone, Yds, 0, Pe,0x1f,E,0}, - {APOPW, Ynone, Yes, 0, Pe,0x07,E,0}, - {APOPW, Ynone, Yss, 0, Pe,0x17,E,0}, - {APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E}, - {APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E}, - -/* mov seg */ - {AMOVW, Yes, Yml, 1, 0x8c,0,0,0}, - {AMOVW, Ycs, Yml, 1, 0x8c,1,0,0}, - {AMOVW, Yss, Yml, 1, 0x8c,2,0,0}, - {AMOVW, Yds, Yml, 1, 0x8c,3,0,0}, - {AMOVW, Yfs, Yml, 1, 0x8c,4,0,0}, - {AMOVW, Ygs, Yml, 1, 0x8c,5,0,0}, - - {AMOVW, Yml, Yes, 2, 0x8e,0,0,0}, - {AMOVW, Yml, Ycs, 2, 0x8e,1,0,0}, - {AMOVW, Yml, Yss, 2, 0x8e,2,0,0}, - {AMOVW, Yml, Yds, 2, 0x8e,3,0,0}, - {AMOVW, Yml, Yfs, 2, 0x8e,4,0,0}, - {AMOVW, Yml, Ygs, 2, 0x8e,5,0,0}, - -/* mov cr */ - {AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0}, - {AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0}, - {AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0}, - {AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0}, - {AMOVL, Ycr8, Yml, 3, 0x0f,0x20,8,0}, - {AMOVQ, Ycr0, Yml, 3, 0x0f,0x20,0,0}, - {AMOVQ, Ycr2, Yml, 3, 0x0f,0x20,2,0}, - {AMOVQ, Ycr3, Yml, 3, 0x0f,0x20,3,0}, - {AMOVQ, Ycr4, Yml, 3, 0x0f,0x20,4,0}, - {AMOVQ, Ycr8, Yml, 3, 0x0f,0x20,8,0}, - - {AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0}, - {AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0}, - {AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0}, - {AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0}, - {AMOVL, Yml, Ycr8, 4, 0x0f,0x22,8,0}, - {AMOVQ, Yml, Ycr0, 4, 0x0f,0x22,0,0}, - {AMOVQ, Yml, Ycr2, 4, 0x0f,0x22,2,0}, - {AMOVQ, Yml, Ycr3, 4, 0x0f,0x22,3,0}, - {AMOVQ, Yml, Ycr4, 4, 0x0f,0x22,4,0}, - {AMOVQ, Yml, Ycr8, 4, 0x0f,0x22,8,0}, - -/* mov dr */ - {AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0}, - {AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0}, - {AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0}, - {AMOVQ, Ydr0, Yml, 3, 0x0f,0x21,0,0}, - {AMOVQ, Ydr6, Yml, 3, 0x0f,0x21,6,0}, - {AMOVQ, Ydr7, Yml, 3, 0x0f,0x21,7,0}, - - {AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0}, - {AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0}, - {AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0}, - {AMOVQ, Yml, Ydr0, 4, 0x0f,0x23,0,0}, - {AMOVQ, Yml, Ydr6, 4, 0x0f,0x23,6,0}, - {AMOVQ, Yml, Ydr7, 4, 0x0f,0x23,7,0}, - -/* mov tr */ - {AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0}, - {AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0}, - - {AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E}, - {AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E}, - -/* lgdt, sgdt, lidt, sidt */ - {AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0}, - {AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0}, - {AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0}, - {AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0}, - {AMOVQ, Ym, Ygdtr, 4, 0x0f,0x01,2,0}, - {AMOVQ, Ygdtr, Ym, 3, 0x0f,0x01,0,0}, - {AMOVQ, Ym, Yidtr, 4, 0x0f,0x01,3,0}, - {AMOVQ, Yidtr, Ym, 3, 0x0f,0x01,1,0}, - -/* lldt, sldt */ - {AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0}, - {AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0}, - -/* lmsw, smsw */ - {AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0}, - {AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0}, - -/* ltr, str */ - {AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0}, - {AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0}, - -/* load full pointer */ - {AMOVL, Yml, Ycol, 5, 0,0,0,0}, - {AMOVW, Yml, Ycol, 5, Pe,0,0,0}, - -/* double shift */ - {ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0}, - {ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0}, - {ASHLQ, Ycol, Yml, 6, Pw,0xa4,0xa5,0}, - {ASHRQ, Ycol, Yml, 6, Pw,0xac,0xad,0}, - {ASHLW, Ycol, Yml, 6, Pe,0xa4,0xa5,0}, - {ASHRW, Ycol, Yml, 6, Pe,0xac,0xad,0}, - 0 -}; - -int -isax(Adr *a) -{ - - switch(a->type) { - case D_AX: - case D_AL: - case D_AH: - case D_INDIR+D_AX: - return 1; - } - if(a->index == D_AX) - return 1; - return 0; -} - -void -subreg(Prog *p, int from, int to) -{ - - if(debug['Q']) - print("\n%P s/%R/%R/\n", p, from, to); - - if(p->from.type == from) - p->from.type = to; - if(p->to.type == from) - p->to.type = to; - - if(p->from.index == from) - p->from.index = to; - if(p->to.index == from) - p->to.index = to; - - from += D_INDIR; - if(p->from.type == from) - p->from.type = to+D_INDIR; - if(p->to.type == from) - p->to.type = to+D_INDIR; - - if(debug['Q']) - 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; - Movtab *mo; - int z, op, ft, tt, xo, l, pre; - vlong v; - Reloc rel, *r; - Adr *a; - - curp = p; // TODO - - o = opindex[p->as]; - if(o == nil) { - diag("asmins: missing op %P", p); - return; - } - - pre = prefixof(&p->from); - if(pre) - *andptr++ = pre; - pre = prefixof(&p->to); - if(pre) - *andptr++ = pre; - - if(p->ft == 0) - p->ft = oclass(&p->from); - if(p->tt == 0) - p->tt = oclass(&p->to); - - ft = p->ft * Ymax; - tt = p->tt * Ymax; - - t = o->ytab; - if(t == 0) { - diag("asmins: noproto %P", p); - return; - } - xo = o->op[0] == 0x0f; - for(z=0; *t; z+=t[3]+xo,t+=4) - if(ycover[ft+t[0]]) - if(ycover[tt+t[1]]) - goto found; - goto domov; - -found: - switch(o->prefix) { - case Pq: /* 16 bit escape and opcode escape */ - *andptr++ = Pe; - *andptr++ = Pm; - break; - case Pq3: /* 16 bit escape, Rex.w, and opcode escape */ - *andptr++ = Pe; - *andptr++ = Pw; - *andptr++ = Pm; - break; - - case Pf2: /* xmm opcode escape */ - case Pf3: - *andptr++ = o->prefix; - *andptr++ = Pm; - break; - - case Pm: /* opcode escape */ - *andptr++ = Pm; - break; - - case Pe: /* 16 bit escape */ - *andptr++ = Pe; - break; - - case Pw: /* 64-bit escape */ - if(p->mode != 64) - diag("asmins: illegal 64: %P", p); - rexflag |= Pw; - break; - - case Pb: /* botch */ - bytereg(&p->from, &p->ft); - bytereg(&p->to, &p->tt); - break; - - case P32: /* 32 bit but illegal if 64-bit mode */ - if(p->mode == 64) - diag("asmins: illegal in 64-bit mode: %P", p); - break; - - case Py: /* 64-bit only, no prefix */ - if(p->mode != 64) - diag("asmins: illegal in %d-bit mode: %P", p->mode, p); - break; - } - - if(z >= nelem(o->op)) - sysfatal("asmins bad table %P", p); - op = o->op[z]; - if(op == 0x0f) { - *andptr++ = op; - op = o->op[++z]; - } - switch(t[2]) { - default: - diag("asmins: unknown z %d %P", t[2], p); - return; - - case Zpseudo: - break; - - case Zlit: - for(; op = o->op[z]; z++) - *andptr++ = op; - break; - - case Zlitm_r: - for(; op = o->op[z]; z++) - *andptr++ = op; - asmand(&p->from, &p->to); - break; - - case Zmb_r: - bytereg(&p->from, &p->ft); - /* fall through */ - case Zm_r: - *andptr++ = op; - asmand(&p->from, &p->to); - break; - case Zm2_r: - *andptr++ = op; - *andptr++ = o->op[z+1]; - asmand(&p->from, &p->to); - break; - - case Zm_r_xm: - mediaop(o, op, t[3], z); - asmand(&p->from, &p->to); - break; - - case Zm_r_xm_nr: - rexflag = 0; - mediaop(o, op, t[3], z); - asmand(&p->from, &p->to); - break; - - case Zm_r_i_xm: - mediaop(o, op, t[3], z); - asmand(&p->from, &p->to); - *andptr++ = p->to.offset; - break; - - case Zm_r_3d: - *andptr++ = 0x0f; - *andptr++ = 0x0f; - asmand(&p->from, &p->to); - *andptr++ = op; - break; - - case Zibm_r: - while ((op = o->op[z++]) != 0) - *andptr++ = op; - asmand(&p->from, &p->to); - *andptr++ = p->to.offset; - break; - - case Zaut_r: - *andptr++ = 0x8d; /* leal */ - if(p->from.type != D_ADDR) - diag("asmins: Zaut sb type ADDR"); - p->from.type = p->from.index; - p->from.index = D_NONE; - asmand(&p->from, &p->to); - p->from.index = p->from.type; - p->from.type = D_ADDR; - break; - - case Zm_o: - *andptr++ = op; - asmando(&p->from, o->op[z+1]); - break; - - case Zr_m: - *andptr++ = op; - asmand(&p->to, &p->from); - break; - - case Zr_m_xm: - mediaop(o, op, t[3], z); - asmand(&p->to, &p->from); - break; - - case Zr_m_xm_nr: - rexflag = 0; - mediaop(o, op, t[3], z); - asmand(&p->to, &p->from); - break; - - case Zr_m_i_xm: - mediaop(o, op, t[3], z); - asmand(&p->to, &p->from); - *andptr++ = p->from.offset; - break; - - case Zo_m: - *andptr++ = op; - asmando(&p->to, o->op[z+1]); - break; - - case Zo_m64: - *andptr++ = op; - asmandsz(&p->to, o->op[z+1], 0, 1); - break; - - case Zm_ibo: - *andptr++ = op; - asmando(&p->from, o->op[z+1]); - *andptr++ = vaddr(&p->to, nil); - break; - - case Zibo_m: - *andptr++ = op; - asmando(&p->to, o->op[z+1]); - *andptr++ = vaddr(&p->from, nil); - break; - - case Zibo_m_xm: - z = mediaop(o, op, t[3], z); - asmando(&p->to, o->op[z+1]); - *andptr++ = vaddr(&p->from, nil); - break; - - case Z_ib: - case Zib_: - if(t[2] == Zib_) - a = &p->from; - else - a = &p->to; - *andptr++ = op; - *andptr++ = vaddr(a, nil); - break; - - case Zib_rp: - rexflag |= regrex[p->to.type] & (Rxb|0x40); - *andptr++ = op + reg[p->to.type]; - *andptr++ = vaddr(&p->from, nil); - break; - - case Zil_rp: - rexflag |= regrex[p->to.type] & Rxb; - *andptr++ = op + reg[p->to.type]; - if(o->prefix == Pe) { - v = vaddr(&p->from, nil); - *andptr++ = v; - *andptr++ = v>>8; - } - else - relput4(p, &p->from); - break; - - case Zo_iw: - *andptr++ = op; - if(p->from.type != D_NONE){ - v = vaddr(&p->from, nil); - *andptr++ = v; - *andptr++ = v>>8; - } - break; - - case Ziq_rp: - v = vaddr(&p->from, &rel); - l = v>>32; - if(l == 0 && rel.siz != 8){ - //p->mark |= 0100; - //print("zero: %llux %P\n", v, p); - rexflag &= ~(0x40|Rxw); - rexflag |= regrex[p->to.type] & Rxb; - *andptr++ = 0xb8 + reg[p->to.type]; - if(rel.type != 0) { - r = addrel(cursym); - *r = rel; - r->off = p->pc + andptr - and; - } - put4(v); - }else if(l == -1 && (v&((uvlong)1<<31))!=0){ /* sign extend */ - //p->mark |= 0100; - //print("sign: %llux %P\n", v, p); - *andptr ++ = 0xc7; - asmando(&p->to, 0); - put4(v); - }else{ /* need all 8 */ - //print("all: %llux %P\n", v, p); - rexflag |= regrex[p->to.type] & Rxb; - *andptr++ = op + reg[p->to.type]; - if(rel.type != 0) { - r = addrel(cursym); - *r = rel; - r->off = p->pc + andptr - and; - } - put8(v); - } - break; - - case Zib_rr: - *andptr++ = op; - asmand(&p->to, &p->to); - *andptr++ = vaddr(&p->from, nil); - break; - - case Z_il: - case Zil_: - if(t[2] == Zil_) - a = &p->from; - else - a = &p->to; - *andptr++ = op; - if(o->prefix == Pe) { - v = vaddr(a, nil); - *andptr++ = v; - *andptr++ = v>>8; - } - else - relput4(p, a); - break; - - case Zm_ilo: - case Zilo_m: - *andptr++ = op; - if(t[2] == Zilo_m) { - a = &p->from; - asmando(&p->to, o->op[z+1]); - } else { - a = &p->to; - asmando(&p->from, o->op[z+1]); - } - if(o->prefix == Pe) { - v = vaddr(a, nil); - *andptr++ = v; - *andptr++ = v>>8; - } - else - relput4(p, a); - break; - - case Zil_rr: - *andptr++ = op; - asmand(&p->to, &p->to); - if(o->prefix == Pe) { - v = vaddr(&p->from, nil); - *andptr++ = v; - *andptr++ = v>>8; - } - else - relput4(p, &p->from); - break; - - case Z_rp: - rexflag |= regrex[p->to.type] & (Rxb|0x40); - *andptr++ = op + reg[p->to.type]; - break; - - case Zrp_: - rexflag |= regrex[p->from.type] & (Rxb|0x40); - *andptr++ = op + reg[p->from.type]; - break; - - case Zclr: - *andptr++ = op; - asmand(&p->to, &p->to); - break; - - case Zcall: - q = p->pcond; - if(q == nil) { - diag("call without target"); - errorexit(); - } - if(q->as != ATEXT) { - // Could handle this case by making D_PCREL - // record the Prog* instead of the Sym*, but let's - // wait until the need arises. - diag("call of non-TEXT %P", q); - errorexit(); - } - *andptr++ = op; - r = addrel(cursym); - r->off = p->pc + andptr - and; - r->sym = q->from.sym; - r->type = D_PCREL; - r->siz = 4; - put4(0); - break; - - case Zbr: - case Zjmp: - case Zloop: - // TODO: jump across functions needs reloc - q = p->pcond; - if(q == nil) { - diag("jmp/branch/loop without target"); - errorexit(); - } - if(q->as == ATEXT) { - if(t[2] == Zbr) { - diag("branch to ATEXT"); - errorexit(); - } - *andptr++ = o->op[z+1]; - r = addrel(cursym); - r->off = p->pc + andptr - and; - r->sym = q->from.sym; - r->type = D_PCREL; - r->siz = 4; - put4(0); - break; - } - // Assumes q is in this function. - // TODO: Check in input, preserve in brchain. - - // Fill in backward jump now. - if(p->back & 1) { - v = q->pc - (p->pc + 2); - if(v >= -128) { - if(p->as == AJCXZL) - *andptr++ = 0x67; - *andptr++ = op; - *andptr++ = v; - } else if(t[2] == Zloop) { - diag("loop too far: %P", p); - } else { - v -= 5-2; - if(t[2] == Zbr) { - *andptr++ = 0x0f; - v--; - } - *andptr++ = o->op[z+1]; - *andptr++ = v; - *andptr++ = v>>8; - *andptr++ = v>>16; - *andptr++ = v>>24; - } - break; - } - - // Annotate target; will fill in later. - p->forwd = q->comefrom; - q->comefrom = p; - if(p->back & 2) { // short - if(p->as == AJCXZL) - *andptr++ = 0x67; - *andptr++ = op; - *andptr++ = 0; - } else if(t[2] == Zloop) { - diag("loop too far: %P", p); - } else { - if(t[2] == Zbr) - *andptr++ = 0x0f; - *andptr++ = o->op[z+1]; - *andptr++ = 0; - *andptr++ = 0; - *andptr++ = 0; - *andptr++ = 0; - } - break; - -/* - v = q->pc - p->pc - 2; - if((v >= -128 && v <= 127) || p->pc == -1 || q->pc == -1) { - *andptr++ = op; - *andptr++ = v; - } else { - v -= 5-2; - if(t[2] == Zbr) { - *andptr++ = 0x0f; - v--; - } - *andptr++ = o->op[z+1]; - *andptr++ = v; - *andptr++ = v>>8; - *andptr++ = v>>16; - *andptr++ = v>>24; - } -*/ - break; - - case Zbyte: - v = vaddr(&p->from, &rel); - if(rel.siz != 0) { - rel.siz = op; - r = addrel(cursym); - *r = rel; - r->off = p->pc + andptr - and; - } - *andptr++ = v; - if(op > 1) { - *andptr++ = v>>8; - if(op > 2) { - *andptr++ = v>>16; - *andptr++ = v>>24; - if(op > 4) { - *andptr++ = v>>32; - *andptr++ = v>>40; - *andptr++ = v>>48; - *andptr++ = v>>56; - } - } - } - break; - } - return; - -domov: - for(mo=ymovtab; mo->as; mo++) - if(p->as == mo->as) - if(ycover[ft+mo->ft]) - if(ycover[tt+mo->tt]){ - t = mo->op; - goto mfound; - } -bad: - if(p->mode != 64){ - /* - * here, the assembly has failed. - * if its a byte instruction that has - * unaddressable registers, try to - * exchange registers and reissue the - * instruction with the operands renamed. - */ - pp = *p; - z = p->from.type; - if(z >= D_BP && z <= D_DI) { - if(isax(&p->to) || p->to.type == D_NONE) { - // We certainly don't want to exchange - // with AX if the op is MUL or DIV. - *andptr++ = 0x87; /* xchg lhs,bx */ - asmando(&p->from, reg[D_BX]); - subreg(&pp, z, D_BX); - doasm(&pp); - *andptr++ = 0x87; /* xchg lhs,bx */ - asmando(&p->from, reg[D_BX]); - } else { - *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ - subreg(&pp, z, D_AX); - doasm(&pp); - *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ - } - return; - } - z = p->to.type; - if(z >= D_BP && z <= D_DI) { - if(isax(&p->from)) { - *andptr++ = 0x87; /* xchg rhs,bx */ - asmando(&p->to, reg[D_BX]); - subreg(&pp, z, D_BX); - doasm(&pp); - *andptr++ = 0x87; /* xchg rhs,bx */ - asmando(&p->to, reg[D_BX]); - } else { - *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ - subreg(&pp, z, D_AX); - doasm(&pp); - *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ - } - return; - } - } - diag("doasm: notfound from=%ux to=%ux %P", p->from.type, p->to.type, p); - return; - -mfound: - switch(mo->code) { - default: - diag("asmins: unknown mov %d %P", mo->code, p); - break; - - case 0: /* lit */ - for(z=0; t[z]!=E; z++) - *andptr++ = t[z]; - break; - - case 1: /* r,m */ - *andptr++ = t[0]; - asmando(&p->to, t[1]); - break; - - case 2: /* m,r */ - *andptr++ = t[0]; - asmando(&p->from, t[1]); - break; - - case 3: /* r,m - 2op */ - *andptr++ = t[0]; - *andptr++ = t[1]; - asmando(&p->to, t[2]); - rexflag |= regrex[p->from.type] & (Rxr|0x40); - break; - - case 4: /* m,r - 2op */ - *andptr++ = t[0]; - *andptr++ = t[1]; - asmando(&p->from, t[2]); - rexflag |= regrex[p->to.type] & (Rxr|0x40); - break; - - case 5: /* load full pointer, trash heap */ - if(t[0]) - *andptr++ = t[0]; - switch(p->to.index) { - default: - goto bad; - case D_DS: - *andptr++ = 0xc5; - break; - case D_SS: - *andptr++ = 0x0f; - *andptr++ = 0xb2; - break; - case D_ES: - *andptr++ = 0xc4; - break; - case D_FS: - *andptr++ = 0x0f; - *andptr++ = 0xb4; - break; - case D_GS: - *andptr++ = 0x0f; - *andptr++ = 0xb5; - break; - } - asmand(&p->from, &p->to); - break; - - case 6: /* double shift */ - if(t[0] == Pw){ - if(p->mode != 64) - diag("asmins: illegal 64: %P", p); - rexflag |= Pw; - t++; - }else if(t[0] == Pe){ - *andptr++ = Pe; - t++; - } - z = p->from.type; - switch(z) { - default: - goto bad; - case D_CONST: - *andptr++ = 0x0f; - *andptr++ = t[0]; - asmandsz(&p->to, reg[(int)p->from.index], regrex[(int)p->from.index], 0); - *andptr++ = p->from.offset; - break; - case D_CL: - case D_CX: - *andptr++ = 0x0f; - *andptr++ = t[1]; - asmandsz(&p->to, reg[(int)p->from.index], regrex[(int)p->from.index], 0); - break; - } - break; - } -} - -void -asmins(Prog *p) -{ - int n, np, c; - Reloc *r; - - rexflag = 0; - andptr = and; - asmode = p->mode; - doasm(p); - if(rexflag){ - /* - * as befits the whole approach of the architecture, - * the rex prefix must appear before the first opcode byte - * (and thus after any 66/67/f2/f3/26/2e/3e prefix bytes, but - * before the 0f opcode escape!), or it might be ignored. - * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'. - */ - if(p->mode != 64) - diag("asmins: illegal in mode %d: %P", p->mode, p); - n = andptr - and; - for(np = 0; np < n; np++) { - c = and[np]; - if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26) - break; - } - memmove(and+np+1, and+np, n-np); - and[np] = 0x40 | rexflag; - andptr++; - } - n = andptr - and; - for(r=cursym->r+cursym->nr; r-- > cursym->r; ) { - if(r->off < p->pc) - break; - if(rexflag) - r->off++; - if(r->type == D_PCREL) - r->add -= p->pc + n - (r->off + r->siz); - } -} |