summaryrefslogtreecommitdiff
path: root/src/cmd/8l
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8l')
-rw-r--r--src/cmd/8l/8.out.h50
-rw-r--r--src/cmd/8l/asm.c393
-rw-r--r--src/cmd/8l/l.h330
-rw-r--r--src/cmd/8l/list.c313
-rw-r--r--src/cmd/8l/obj.c698
-rw-r--r--src/cmd/8l/optab.c1030
-rw-r--r--src/cmd/8l/pass.c858
-rw-r--r--src/cmd/8l/prof.c173
-rw-r--r--src/cmd/8l/span.c1507
9 files changed, 183 insertions, 5169 deletions
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 988e50f3e..8e642d390 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -547,6 +547,7 @@ enum as
APSUBW,
APUNPCKHQDQ,
APUNPCKLQDQ,
+ APXOR,
ARCPPS,
ARCPSS,
ARSQRTPS,
@@ -578,6 +579,10 @@ enum as
AFUNCDATA,
APCDATA,
ACHECKNIL,
+ AVARDEF,
+ AVARKILL,
+ ADUFFCOPY,
+ ADUFFZERO,
ALAST
};
@@ -631,30 +636,23 @@ enum
D_X5,
D_X6,
D_X7,
-
- D_NONE = 67,
-
- D_BRANCH = 68,
- D_EXTERN = 69,
- D_STATIC = 70,
- D_AUTO = 71,
- D_PARAM = 72,
- D_CONST = 73,
- D_FCONST = 74,
- D_SCONST = 75,
- D_ADDR = 76,
-
- D_FILE,
- D_FILE1,
+
+ D_TLS = 67,
+ D_NONE = 68,
+
+ D_BRANCH = 69,
+ D_EXTERN = 70,
+ D_STATIC = 71,
+ D_AUTO = 72,
+ D_PARAM = 73,
+ D_CONST = 74,
+ D_FCONST = 75,
+ D_SCONST = 76,
+ D_ADDR = 77,
D_INDIR, /* additive */
D_CONST2 = D_INDIR+D_INDIR,
- D_SIZE, /* 8l internal */
- D_PCREL,
- D_GOTOFF,
- D_GOTREL,
- D_TLS,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
@@ -676,15 +674,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/8l/asm.c b/src/cmd/8l/asm.c
index 3be37ea22..114a3eb5d 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -42,47 +42,20 @@ char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
char openbsddynld[] = "/usr/libexec/ld.so";
char netbsddynld[] = "/usr/libexec/ld.elf_so";
char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
-
-int32
-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;
-}
+char solarisdynld[] = "/lib/ld.so.1";
static int
needlib(char *name)
{
char *p;
- Sym *s;
+ LSym *s;
if(*name == '\0')
return 0;
/* reuse hash code in symbol table */
p = smprint(".dynlib.%s", name);
- s = lookup(p, 0);
+ s = linklookup(ctxt, p, 0);
free(p);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
@@ -93,11 +66,11 @@ needlib(char *name)
int nelfsym = 1;
-static void addpltsym(Sym*);
-static void addgotsym(Sym*);
+static void addpltsym(Link*, LSym*);
+static void addgotsym(Link*, LSym*);
void
-adddynrela(Sym *rela, Sym *s, Reloc *r)
+adddynrela(LSym *rela, LSym *s, Reloc *r)
{
USED(rela);
USED(s);
@@ -106,12 +79,12 @@ adddynrela(Sym *rela, Sym *s, Reloc *r)
}
void
-adddynrel(Sym *s, Reloc *r)
+adddynrel(LSym *s, Reloc *r)
{
- Sym *targ, *rel, *got;
+ LSym *targ, *rel, *got;
targ = r->sym;
- cursym = s;
+ ctxt->cursym = s;
switch(r->type) {
default:
@@ -127,16 +100,16 @@ adddynrel(Sym *s, Reloc *r)
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
if(targ->type == 0 || targ->type == SXREF)
diag("unknown symbol %s in pcrel", targ->name);
- r->type = D_PCREL;
+ r->type = R_PCREL;
r->add += 4;
return;
case 256 + R_386_PLT32:
- r->type = D_PCREL;
+ r->type = R_PCREL;
r->add += 4;
if(targ->type == SDYNIMPORT) {
- addpltsym(targ);
- r->sym = lookup(".plt", 0);
+ addpltsym(ctxt, targ);
+ r->sym = linklookup(ctxt, ".plt", 0);
r->add += targ->plt;
}
return;
@@ -150,46 +123,46 @@ adddynrel(Sym *s, Reloc *r)
return;
}
s->p[r->off-2] = 0x8d;
- r->type = D_GOTOFF;
+ r->type = R_GOTOFF;
return;
}
- addgotsym(targ);
- r->type = D_CONST; // write r->add during relocsym
+ addgotsym(ctxt, targ);
+ r->type = R_CONST; // write r->add during relocsym
r->sym = S;
r->add += targ->got;
return;
case 256 + R_386_GOTOFF:
- r->type = D_GOTOFF;
+ r->type = R_GOTOFF;
return;
case 256 + R_386_GOTPC:
- r->type = D_PCREL;
- r->sym = lookup(".got", 0);
+ r->type = R_PCREL;
+ r->sym = linklookup(ctxt, ".got", 0);
r->add += 4;
return;
case 256 + R_386_32:
if(targ->type == SDYNIMPORT)
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
- r->type = D_ADDR;
+ r->type = R_ADDR;
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
- r->type = D_ADDR;
+ r->type = R_ADDR;
if(targ->type == SDYNIMPORT)
diag("unexpected reloc for dynamic symbol %s", targ->name);
return;
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
if(targ->type == SDYNIMPORT) {
- addpltsym(targ);
- r->sym = lookup(".plt", 0);
+ addpltsym(ctxt, targ);
+ r->sym = linklookup(ctxt, ".plt", 0);
r->add = targ->plt;
- r->type = D_PCREL;
+ r->type = R_PCREL;
return;
}
- r->type = D_PCREL;
+ r->type = R_PCREL;
return;
case 512 + MACHO_FAKE_GOTPCREL:
@@ -201,13 +174,13 @@ adddynrel(Sym *s, Reloc *r)
return;
}
s->p[r->off-2] = 0x8d;
- r->type = D_PCREL;
+ r->type = R_PCREL;
return;
}
- addgotsym(targ);
- r->sym = lookup(".got", 0);
+ addgotsym(ctxt, targ);
+ r->sym = linklookup(ctxt, ".got", 0);
r->add += targ->got;
- r->type = D_PCREL;
+ r->type = R_PCREL;
return;
}
@@ -216,21 +189,22 @@ adddynrel(Sym *s, Reloc *r)
return;
switch(r->type) {
- case D_PCREL:
- addpltsym(targ);
- r->sym = lookup(".plt", 0);
+ case R_CALL:
+ case R_PCREL:
+ addpltsym(ctxt, targ);
+ r->sym = linklookup(ctxt, ".plt", 0);
r->add = targ->plt;
return;
- case D_ADDR:
+ case R_ADDR:
if(s->type != SDATA)
break;
if(iself) {
- adddynsym(targ);
- rel = lookup(".rel", 0);
- addaddrplus(rel, s, r->off);
- adduint32(rel, ELF32_R_INFO(targ->dynid, R_386_32));
- r->type = D_CONST; // write r->add during relocsym
+ adddynsym(ctxt, targ);
+ rel = linklookup(ctxt, ".rel", 0);
+ addaddrplus(ctxt, rel, s, r->off);
+ adduint32(ctxt, rel, ELF32_R_INFO(targ->dynid, R_386_32));
+ r->type = R_CONST; // write r->add during relocsym
r->sym = S;
return;
}
@@ -245,22 +219,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;
- adduint32(got, 0);
- adduint32(lookup(".linkedit.got", 0), targ->dynid);
+ adduint32(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);
}
@@ -276,21 +250,23 @@ elfreloc1(Reloc *r, vlong sectoff)
default:
return -1;
- case D_ADDR:
+ case R_ADDR:
if(r->siz == 4)
LPUT(R_386_32 | elfsym<<8);
else
return -1;
break;
- case D_PCREL:
+ case R_CALL:
+ case R_PCREL:
if(r->siz == 4)
LPUT(R_386_PC32 | elfsym<<8);
else
return -1;
break;
- case D_TLS:
+ case R_TLS_LE:
+ case R_TLS_IE:
if(r->siz == 4)
LPUT(R_386_TLS_LE | elfsym<<8);
else
@@ -304,7 +280,7 @@ int
machoreloc1(Reloc *r, vlong sectoff)
{
uint32 v;
- Sym *rs;
+ LSym *rs;
rs = r->xsym;
@@ -326,10 +302,11 @@ machoreloc1(Reloc *r, vlong sectoff)
switch(r->type) {
default:
return -1;
- case D_ADDR:
+ case R_ADDR:
v |= MACHO_GENERIC_RELOC_VANILLA<<28;
break;
- case D_PCREL:
+ case R_CALL:
+ case R_PCREL:
v |= 1<<24; // pc-relative bit
v |= MACHO_GENERIC_RELOC_VANILLA<<28;
break;
@@ -358,17 +335,17 @@ machoreloc1(Reloc *r, vlong sectoff)
}
int
-archreloc(Reloc *r, Sym *s, vlong *val)
+archreloc(Reloc *r, LSym *s, vlong *val)
{
USED(s);
if(linkmode == LinkExternal)
return -1;
switch(r->type) {
- case D_CONST:
+ case R_CONST:
*val = r->add;
return 0;
- case D_GOTOFF:
- *val = symaddr(r->sym) + r->add - symaddr(lookup(".got", 0));
+ case R_GOTOFF:
+ *val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
return 0;
}
return -1;
@@ -377,119 +354,119 @@ 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) {
// pushl got+4
- adduint8(plt, 0xff);
- adduint8(plt, 0x35);
- addaddrplus(plt, got, 4);
+ adduint8(ctxt, plt, 0xff);
+ adduint8(ctxt, plt, 0x35);
+ addaddrplus(ctxt, plt, got, 4);
// jmp *got+8
- adduint8(plt, 0xff);
- adduint8(plt, 0x25);
- addaddrplus(plt, got, 8);
+ adduint8(ctxt, plt, 0xff);
+ adduint8(ctxt, plt, 0x25);
+ addaddrplus(ctxt, plt, got, 8);
// zero pad
- adduint32(plt, 0);
+ adduint32(ctxt, plt, 0);
// assume got->size == 0 too
- addaddrplus(got, lookup(".dynamic", 0), 0);
- adduint32(got, 0);
- adduint32(got, 0);
+ addaddrplus(ctxt, got, linklookup(ctxt, ".dynamic", 0), 0);
+ adduint32(ctxt, got, 0);
+ adduint32(ctxt, got, 0);
}
}
static void
-addpltsym(Sym *s)
+addpltsym(Link *ctxt, LSym *s)
{
- Sym *plt, *got, *rel;
+ LSym *plt, *got, *rel;
if(s->plt >= 0)
return;
- adddynsym(s);
+ adddynsym(ctxt, s);
if(iself) {
- plt = lookup(".plt", 0);
- got = lookup(".got.plt", 0);
- rel = lookup(".rel.plt", 0);
+ plt = linklookup(ctxt, ".plt", 0);
+ got = linklookup(ctxt, ".got.plt", 0);
+ rel = linklookup(ctxt, ".rel.plt", 0);
if(plt->size == 0)
elfsetupplt();
// jmpq *got+size
- adduint8(plt, 0xff);
- adduint8(plt, 0x25);
- addaddrplus(plt, got, got->size);
+ adduint8(ctxt, plt, 0xff);
+ adduint8(ctxt, plt, 0x25);
+ addaddrplus(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);
// pushl $x
- adduint8(plt, 0x68);
- adduint32(plt, rel->size);
+ adduint8(ctxt, plt, 0x68);
+ adduint32(ctxt, plt, rel->size);
// jmp .plt
- adduint8(plt, 0xe9);
- adduint32(plt, -(plt->size+4));
+ adduint8(ctxt, plt, 0xe9);
+ adduint32(ctxt, plt, -(plt->size+4));
// rel
- addaddrplus(rel, got, got->size-4);
- adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT));
+ addaddrplus(ctxt, rel, got, got->size-4);
+ adduint32(ctxt, rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT));
s->plt = plt->size - 16;
} else if(HEADTYPE == Hdarwin) {
// Same laziness as in 6l.
- Sym *plt;
+ LSym *plt;
- plt = lookup(".plt", 0);
+ plt = linklookup(ctxt, ".plt", 0);
- addgotsym(s);
+ addgotsym(ctxt, s);
- 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);
- addaddrplus(plt, lookup(".got", 0), s->got);
+ adduint8(ctxt, plt, 0xff);
+ adduint8(ctxt, plt, 0x25);
+ addaddrplus(ctxt, plt, linklookup(ctxt, ".got", 0), s->got);
} else {
diag("addpltsym: unsupported binary format");
}
}
static void
-addgotsym(Sym *s)
+addgotsym(Link *ctxt, LSym *s)
{
- Sym *got, *rel;
+ LSym *got, *rel;
if(s->got >= 0)
return;
- adddynsym(s);
- got = lookup(".got", 0);
+ adddynsym(ctxt, s);
+ got = linklookup(ctxt, ".got", 0);
s->got = got->size;
- adduint32(got, 0);
+ adduint32(ctxt, got, 0);
if(iself) {
- rel = lookup(".rel", 0);
- addaddrplus(rel, got, s->got);
- adduint32(rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT));
+ rel = linklookup(ctxt, ".rel", 0);
+ addaddrplus(ctxt, rel, got, s->got);
+ adduint32(ctxt, rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT));
} 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;
@@ -499,20 +476,20 @@ adddynsym(Sym *s)
if(iself) {
s->dynid = nelfsym++;
- d = lookup(".dynsym", 0);
+ d = linklookup(ctxt, ".dynsym", 0);
/* name */
name = s->extname;
- adduint32(d, addstring(lookup(".dynstr", 0), name));
+ adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name));
/* value */
if(s->type == SDYNIMPORT)
- adduint32(d, 0);
+ adduint32(ctxt, d, 0);
else
- addaddr(d, s);
+ addaddr(ctxt, d, s);
/* size */
- adduint32(d, 0);
+ adduint32(ctxt, d, 0);
/* type */
t = STB_GLOBAL << 4;
@@ -520,12 +497,12 @@ adddynsym(Sym *s)
t |= STT_FUNC;
else
t |= STT_OBJECT;
- adduint8(d, t);
- adduint8(d, 0);
+ adduint8(ctxt, d, t);
+ adduint8(ctxt, d, 0);
/* shndx */
if(s->type == SDYNIMPORT)
- adduint16(d, SHN_UNDEF);
+ adduint16(ctxt, d, SHN_UNDEF);
else {
switch(s->type) {
default:
@@ -542,7 +519,7 @@ adddynsym(Sym *s)
t = 14;
break;
}
- adduint16(d, t);
+ adduint16(ctxt, d, t);
}
} else if(HEADTYPE == Hdarwin) {
diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
@@ -556,16 +533,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 if(HEADTYPE != Hwindows) {
@@ -576,10 +553,10 @@ adddynlib(char *lib)
void
asmb(void)
{
- int32 v, magic;
+ int32 magic;
uint32 symo, dwarfoff, machlink;
Section *sect;
- Sym *sym;
+ LSym *sym;
int i;
if(debug['v'])
@@ -641,18 +618,7 @@ asmb(void)
default:
if(iself)
goto Elfsym;
- case Hgarbunix:
- symo = rnd(HEADR+segtext.filelen, 8192)+segdata.filelen;
- break;
- case Hunixcoff:
- symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
- break;
- case Hplan9x32:
- symo = HEADR+segtext.filelen+segdata.filelen;
- break;
- case Hmsdoscom:
- case Hmsdosexe:
- debug['s'] = 1;
+ case Hplan9:
symo = HEADR+segtext.filelen+segdata.filelen;
break;
case Hdarwin:
@@ -685,11 +651,11 @@ asmb(void)
elfemitreloc();
}
break;
- case Hplan9x32:
+ 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++)
@@ -715,96 +681,7 @@ asmb(void)
cseek(0L);
switch(HEADTYPE) {
default:
- case Hgarbunix: /* garbage */
- lputb(0x160L<<16); /* magic and sections */
- lputb(0L); /* time and date */
- lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen);
- lputb(symsize); /* nsyms */
- lputb((0x38L<<16)|7L); /* size of optional hdr and flags */
- lputb((0413<<16)|0437L); /* magic and version */
- lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */
- lputb(segdata.filelen);
- lputb(segdata.len - segdata.filelen);
- lputb(entryvalue()); /* va of entry */
- lputb(INITTEXT-HEADR); /* va of base of text */
- lputb(segdata.vaddr); /* va of base of data */
- lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */
- lputb(~0L); /* gp reg mask */
- lputb(0L);
- lputb(0L);
- lputb(0L);
- lputb(0L);
- lputb(~0L); /* gp value ?? */
- break;
- case Hunixcoff: /* unix coff */
- /*
- * file header
- */
- lputl(0x0004014c); /* 4 sections, magic */
- lputl(0); /* unix time stamp */
- lputl(0); /* symbol table */
- lputl(0); /* nsyms */
- lputl(0x0003001c); /* flags, sizeof a.out header */
- /*
- * a.out header
- */
- lputl(0x10b); /* magic, version stamp */
- lputl(rnd(segtext.filelen, INITRND)); /* text sizes */
- lputl(segdata.filelen); /* data sizes */
- lputl(segdata.len - segdata.filelen); /* bss sizes */
- lputb(entryvalue()); /* va of entry */
- lputl(INITTEXT); /* text start */
- lputl(segdata.vaddr); /* data start */
- /*
- * text section header
- */
- s8put(".text");
- lputl(HEADR); /* pa */
- lputl(HEADR); /* va */
- lputl(segtext.filelen); /* text size */
- lputl(HEADR); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x20); /* flags text only */
- /*
- * data section header
- */
- s8put(".data");
- lputl(segdata.vaddr); /* pa */
- lputl(segdata.vaddr); /* va */
- lputl(segdata.filelen); /* data size */
- lputl(HEADR+segtext.filelen); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x40); /* flags data only */
- /*
- * bss section header
- */
- s8put(".bss");
- lputl(segdata.vaddr+segdata.filelen); /* pa */
- lputl(segdata.vaddr+segdata.filelen); /* va */
- lputl(segdata.len - segdata.filelen); /* bss size */
- lputl(0); /* file offset */
- lputl(0); /* relocation */
- lputl(0); /* line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x80); /* flags bss only */
- /*
- * comment section header
- */
- s8put(".comment");
- lputl(0); /* pa */
- lputl(0); /* va */
- lputl(symsize+lcsize); /* comment size */
- lputl(HEADR+segtext.filelen+segdata.filelen); /* file offset */
- lputl(HEADR+segtext.filelen+segdata.filelen); /* offset of syms */
- lputl(HEADR+segtext.filelen+segdata.filelen+symsize);/* offset of line numbers */
- lputl(0); /* relocation, line numbers */
- lputl(0x200); /* flags comment only */
- break;
- case Hplan9x32: /* plan9 */
+ case Hplan9: /* plan9 */
magic = 4*11*11+7;
lputb(magic); /* magic */
lputb(segtext.filelen); /* sizes */
@@ -815,31 +692,6 @@ asmb(void)
lputb(spsize); /* sp offsets */
lputb(lcsize); /* line offsets */
break;
- case Hmsdoscom:
- /* MS-DOS .COM */
- break;
- case Hmsdosexe:
- /* fake MS-DOS .EXE */
- v = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen;
- wputl(0x5A4D); /* 'MZ' */
- wputl(v % 512); /* bytes in last page */
- wputl(rnd(v, 512)/512); /* total number of pages */
- wputl(0x0000); /* number of reloc items */
- v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
- wputl(v/16); /* size of header */
- wputl(0x0000); /* minimum allocation */
- wputl(0xFFFF); /* maximum allocation */
- wputl(0x0000); /* initial ss value */
- wputl(0x0100); /* initial sp value */
- wputl(0x0000); /* complemented checksum */
- v = entryvalue();
- wputl(v); /* initial ip value (!) */
- wputl(0x0000); /* initial cs value */
- wputl(0x0000);
- wputl(0x0000);
- wputl(0x003E); /* reloc table offset */
- wputl(0x0000); /* overlay number */
- break;
case Hdarwin:
asmbmacho();
break;
@@ -848,6 +700,7 @@ asmb(void)
case Hnetbsd:
case Hopenbsd:
case Hdragonfly:
+ case Hnacl:
asmbelf(symo);
break;
case Hwindows:
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 814aa1458..c9695ade0 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -31,6 +31,7 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
+#include <link.h>
#include "8.out.h"
#ifndef EXTERN
@@ -42,141 +43,14 @@ enum
thechar = '8',
PtrSize = 4,
IntSize = 4,
+ RegSize = 4,
MaxAlign = 32, // max data alignment
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 Reloc Reloc;
-
-struct Adr
-{
- union
- {
- int32 u0offset;
- char u0scon[8];
- Prog *u0cond; /* not used, but should be D_BRANCH */
- Ieee u0ieee;
- char *u0sbig;
- } u0;
- Sym* sym;
- short type;
- uchar index;
- char scale;
- int32 offset2;
-};
-
-#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;
- int32 add;
- int32 xadd;
- Sym* sym;
- Sym* xsym;
-};
-
-struct Prog
-{
- Adr from;
- Adr to;
- Prog* forwd;
- Prog* comefrom;
- Prog* link;
- Prog* pcond; /* work on this */
- int32 pc;
- int32 spadj;
- int32 line;
- short as;
- char width; /* fake for DATA */
- char ft; /* oclass cache */
- char tt;
- uchar mark; /* work on these */
- uchar back;
- uchar bigjmp;
-};
-#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 value;
- int32 size;
- int32 sig;
- int32 dynid;
- 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 sub list
- Sym* outer; // container of sub
- Sym* gotype;
- Sym* reachparent;
- Sym* queue;
- 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[13];
-};
+#define S ((LSym*)0)
+#define TNAME (ctxt->cursym?ctxt->cursym->name:noname)
enum
{
@@ -185,202 +59,36 @@ enum
MINLC = 1,
MAXIO = 8192,
MAXHIST = 40, /* limit of path elements for history symbols */
-
- Yxxx = 0,
- Ynone,
- Yi0,
- Yi1,
- Yi8,
- Yi32,
- 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,
- Ydr0, Ydr1, Ydr2, Ydr3, Ydr4, Ydr5, Ydr6, Ydr7,
- Ytr0, Ytr1, Ytr2, Ytr3, Ytr4, Ytr5, Ytr6, Ytr7,
- Ymr, Ymm,
- Yxr, Yxm,
- Ymax,
-
- Zxxx = 0,
-
- Zlit,
- Zlitm_r,
- Z_rp,
- Zbr,
- Zcall,
- Zcallcon,
- Zcallind,
- Zib_,
- Zib_rp,
- Zibo_m,
- Zil_,
- Zil_rp,
- Zilo_m,
- Zjmp,
- Zjmpcon,
- Zloop,
- Zm_o,
- Zm_r,
- Zm2_r,
- Zm_r_xm,
- Zm_r_i_xm,
- Zaut_r,
- Zo_m,
- Zpseudo,
- Zr_m,
- Zr_m_xm,
- Zr_m_i_xm,
- Zrp_,
- Z_ib,
- Z_il,
- Zm_ibo,
- Zm_ilo,
- Zib_rr,
- Zil_rr,
- Zclr,
- Zibm_r, /* mmx1,mmx2/mem64,imm8 */
- Zbyte,
- Zmov,
- Zmax,
-
- Px = 0,
- Pe = 0x66, /* operand escape */
- Pm = 0x0f, /* 2byte opcode escape */
- Pq = 0xff, /* both escape */
- Pb = 0xfe, /* byte operands */
- Pf2 = 0xf2, /* xmm escape 1 */
- Pf3 = 0xf3, /* xmm escape 2 */
};
-#pragma varargck type "A" int
-#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 "Y" Sym*
-#pragma varargck type "Z" char*
-#pragma varargck type "i" char*
-EXTERN int32 HEADR;
-EXTERN int32 HEADTYPE;
-EXTERN int32 INITRND;
-EXTERN int32 INITTEXT;
-EXTERN int32 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* etextp;
EXTERN Prog* firstp;
-EXTERN uchar ycover[Ymax*Ymax];
-EXTERN uchar* andptr;
-EXTERN uchar and[100];
-EXTERN char reg[D_NONE];
EXTERN int32 lcsize;
-EXTERN int maxop;
-EXTERN int nerrors;
-EXTERN char* noname;
-EXTERN int32 pc;
EXTERN char* rpath;
EXTERN int32 spsize;
-EXTERN Sym* symlist;
+EXTERN LSym* symlist;
EXTERN int32 symsize;
-EXTERN Sym* textp;
EXTERN int32 textsize;
-EXTERN Prog zprg;
-EXTERN int dtype;
-EXTERN int tlsoffset;
-EXTERN Sym* adrgotype; // type symbol on last Adr read
-EXTERN Sym* fromgotype; // type symbol on last p->from read
-extern Optab optab[];
-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);
-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);
-int32 atolwhex(char*);
-Prog* brchain(Prog*);
-Prog* brloop(Prog*);
-void cflush(void);
-Prog* copyp(Prog*);
-vlong cpos(void);
-double cputime(void);
-void diag(char*, ...);
-void dodata(void);
-void doelf(void);
-void doprof1(void);
-void doprof2(void);
-void dostkoff(void);
-int32 entryvalue(void);
-void follow(void);
-void instinit(void);
+int elfreloc1(Reloc *r, vlong sectoff);
+void elfsetupplt(void);
void listinit(void);
-Sym* lookup(char*, int);
-void lputb(int32);
-void lputl(int32);
-void vputl(uint64);
-void strnput(char*, int);
-void main(int, char*[]);
-void* mal(uint32);
-int opsize(Prog*);
-void patch(void);
-Prog* prg(void);
-int relinv(int);
-int32 rnd(int32, int32);
-void s8put(char*);
-void span(void);
-void undef(void);
-int32 symaddr(Sym*);
-void wput(ushort);
-void wputl(ushort);
-void xdefine(char*, int, int32);
-
-uint32 machheadr(void);
-vlong addaddr(Sym *s, Sym *t);
-vlong addsize(Sym *s, Sym *t);
-vlong addstring(Sym *s, char *str);
-vlong adduint16(Sym *s, uint16 v);
-vlong adduint32(Sym *s, uint32 v);
-vlong adduint64(Sym *s, uint64 v);
-vlong adduint8(Sym *s, uint8 v);
-vlong adduintxx(Sym *s, uint64 v, int wid);
-
-/*
- * go.c
- */
-void deadcode(void);
+int machoreloc1(Reloc *r, vlong sectoff);
+void main(int argc, char *argv[]);
+int32 rnd(int32 v, int32 r);
+void s8put(char *n);
+char* xsymname(LSym *s);
/* Native is little-endian */
#define LPUT(a) lputl(a)
diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c
index e2a2ec5ed..0a7534060 100644
--- a/src/cmd/8l/list.c
+++ b/src/cmd/8l/list.c
@@ -36,297 +36,10 @@
void
listinit(void)
{
-
- fmtinstall('R', Rconv);
- fmtinstall('A', Aconv);
- fmtinstall('D', Dconv);
- fmtinstall('S', Sconv);
- fmtinstall('P', Pconv);
+ listinit8();
fmtinstall('I', Iconv);
}
-static Prog *bigP;
-
-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,%D",
- p->line, p->as, &p->from, p->from.scale, &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]);
-}
-
-char*
-xsymname(Sym *s)
-{
- if(s == nil)
- return "!!noname!!";
- return s->name;
-}
-
-int
-Dconv(Fmt *fp)
-{
- char str[STRINGSZ], s[STRINGSZ];
- Adr *a;
- int i;
-
- a = va_arg(fp->args, Adr*);
- i = a->type;
- if(i >= D_INDIR && i < 2*D_INDIR) {
- if(a->offset)
- snprint(str, sizeof str, "%d(%R)", a->offset, i-D_INDIR);
- else
- snprint(str, sizeof str, "(%R)", i-D_INDIR);
- goto brk;
- }
- switch(i) {
-
- default:
- 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, "%ux+%s", bigP->pcond->pc,
- a->sym->name);
- else
- snprint(str, sizeof str, "%ux", bigP->pcond->pc);
- else
- snprint(str, sizeof str, "%d(PC)", a->offset);
- break;
-
- case D_EXTERN:
- snprint(str, sizeof str, "%s+%d(SB)", xsymname(a->sym), a->offset);
- break;
-
- case D_STATIC:
- snprint(str, sizeof str, "%s<%d>+%d(SB)", xsymname(a->sym),
- a->sym->version, a->offset);
- break;
-
- case D_AUTO:
- snprint(str, sizeof str, "%s+%d(SP)", xsymname(a->sym), a->offset);
- break;
-
- case D_PARAM:
- if(a->sym)
- snprint(str, sizeof str, "%s+%d(FP)", a->sym->name, a->offset);
- else
- snprint(str, sizeof str, "%d(FP)", a->offset);
- break;
-
- case D_CONST:
- snprint(str, sizeof str, "$%d", a->offset);
- break;
-
- case D_CONST2:
- snprint(str, sizeof str, "$%d-%d", a->offset, a->offset2);
- 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) {
- sprint(s, "(%R*%d)", (int)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",
- "AH",
- "CH",
- "DH",
- "BH",
-
- "AX", /* [D_AX] */
- "CX",
- "DX",
- "BX",
- "SP",
- "BP",
- "SI",
- "DI",
-
- "F0", /* [D_F0] */
- "F1",
- "F2",
- "F3",
- "F4",
- "F5",
- "F6",
- "F7",
-
- "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",
-
- "DR0", /* [D_DR] */
- "DR1",
- "DR2",
- "DR3",
- "DR4",
- "DR5",
- "DR6",
- "DR7",
-
- "TR0", /* [D_TR] */
- "TR1",
- "TR2",
- "TR3",
- "TR4",
- "TR5",
- "TR6",
- "TR7",
-
- "X0",
- "X1",
- "X2",
- "X3",
- "X4",
- "X5",
- "X6",
- "X7",
-
- "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)
- sprint(str, "%s", regstr[r-D_AL]);
- else
- sprint(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)
{
@@ -352,27 +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();
- }
-}
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 3fdc41381..1b65c5eb9 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -30,7 +30,6 @@
// Reading object files.
-#define EXTERN
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
@@ -39,110 +38,17 @@
#include "../ld/pe.h"
#include <ar.h>
-#ifndef DEFAULT
-#define DEFAULT '9'
-#endif
-
-char *noname = "<none>";
-char *thestring = "386";
-
-Header headers[] = {
- "garbunix", Hgarbunix,
- "unixcoff", Hunixcoff,
- "plan9", Hplan9x32,
- "msdoscom", Hmsdoscom,
- "msdosexe", Hmsdosexe,
- "darwin", Hdarwin,
- "dragonfly", Hdragonfly,
- "linux", Hlinux,
- "freebsd", Hfreebsd,
- "netbsd", Hnetbsd,
- "openbsd", Hopenbsd,
- "windows", Hwindows,
- "windowsgui", Hwindows,
- 0, 0
-};
-
-/*
- * -Hgarbunix -T0x40004C -D0x10000000 is garbage unix
- * -Hunixcoff -T0xd0 -R4 is unix coff
- * -Hplan9 -T4128 -R4096 is plan9 format
- * -Hmsdoscom -Tx -Rx is MS-DOS .COM
- * -Hmsdosexe -Tx -Rx is fake MS-DOS .EXE
- * -Hdarwin -Tx -Rx is Apple Mach-O
- * -Hdragonfly -Tx -Rx is DragonFly ELF32
- * -Hlinux -Tx -Rx is Linux ELF32
- * -Hfreebsd -Tx -Rx is FreeBSD ELF32
- * -Hnetbsd -Tx -Rx is NetBSD ELF32
- * -Hopenbsd -Tx -Rx is OpenBSD ELF32
- * -Hwindows -Tx -Rx is MS Windows PE32
- */
+char* thestring = "386";
+LinkArch* thelinkarch = &link386;
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']);
- flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo);
- flagstr("E", "sym: entry symbol", &INITENTRY);
- flagint32("D", "addr: data address", &INITDAT);
- flagfn1("I", "interp: set ELF interp", setinterp);
- flagfn1("L", "dir: add dir to library path", Lflag);
- flagfn1("H", "head: header type", setheadtype);
- flagcount("K", "add stack underflow checks", &debug['K']);
- flagcount("O", "print pc-line tables", &debug['O']);
- flagcount("Q", "debug byte-register code gen", &debug['Q']);
- flagint32("R", "rnd: address rounding", &INITRND);
- flagcount("S", "check type signatures", &debug['S']);
- flagint32("T", "addr: text address", &INITTEXT);
- flagfn0("V", "print version and exit", doversion);
- flagcount("W", "disassemble input", &debug['W']);
- flagfn2("X", "name value: define string data", addstrdata);
- flagcount("Z", "clear stack frame on entry", &debug['Z']);
- flagcount("a", "disassemble output", &debug['a']);
- flagcount("c", "dump call graph", &debug['c']);
- flagcount("d", "disable dynamic executable", &debug['d']);
- 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);
- flagstr("o", "outfile: set output file", &outfile);
- flagcount("p", "insert profiling code", &debug['p']);
- flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath);
- flagcount("race", "enable race detector", &flag_race);
- flagcount("s", "disable symbol table", &debug['s']);
- flagcount("n", "dump symbol table", &debug['n']);
- flagstr("tmpdir", "leave temporary files in this directory", &tmpdir);
- flagcount("u", "reject unsafe packages", &debug['u']);
- flagcount("v", "print link trace", &debug['v']);
- flagcount("w", "disable DWARF generation", &debug['w']);
- // TODO: link mode flag
-
- flagparse(&argc, &argv, usage);
-
- if(argc != 1)
- usage();
-
- mywhatsys(); // get goos
-
- if(HEADTYPE == -1)
- HEADTYPE = headtype(goos);
+}
+void
+archinit(void)
+{
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
// Go was built; see ../../make.bash.
if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
@@ -164,40 +70,12 @@ main(int argc, char *argv[])
break;
}
- if(outfile == nil) {
- if(HEADTYPE == Hwindows)
- outfile = "8.out.exe";
- else
- outfile = "8.out";
- }
-
- libinit();
-
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
- case Hgarbunix: /* this is garbage */
- HEADR = 20L+56L;
- if(INITTEXT == -1)
- INITTEXT = 0x40004CL;
- if(INITDAT == -1)
- INITDAT = 0x10000000L;
- if(INITRND == -1)
- INITRND = 0;
- break;
- case Hunixcoff: /* is unix coff */
- HEADR = 0xd0L;
- if(INITTEXT == -1)
- INITTEXT = 0xd0;
- if(INITDAT == -1)
- INITDAT = 0x400000;
- if(INITRND == -1)
- INITRND = 0;
- break;
- case Hplan9x32: /* plan 9 */
- tlsoffset = -8;
+ case Hplan9: /* plan 9 */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 4096+32;
@@ -206,33 +84,7 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
- case Hmsdoscom: /* MS-DOS .COM */
- HEADR = 0;
- if(INITTEXT == -1)
- INITTEXT = 0x0100;
- if(INITDAT == -1)
- INITDAT = 0;
- if(INITRND == -1)
- INITRND = 4;
- break;
- case Hmsdosexe: /* fake MS-DOS .EXE */
- HEADR = 0x200;
- if(INITTEXT == -1)
- INITTEXT = 0x0100;
- if(INITDAT == -1)
- INITDAT = 0;
- if(INITRND == -1)
- INITRND = 4;
- HEADR += (INITTEXT & 0xFFFF);
- if(debug['v'])
- Bprint(&bso, "HEADR = 0x%d\n", HEADR);
- break;
case Hdarwin: /* apple MACH */
- /*
- * OS X system constant - offset from %gs to our TLS.
- * Explained in ../../pkg/runtime/cgo/gcc_darwin_386.c.
- */
- tlsoffset = 0x468;
machoinit();
HEADR = INITIAL_MACHO_HEADR;
if(INITTEXT == -1)
@@ -247,13 +99,6 @@ main(int argc, char *argv[])
case Hnetbsd:
case Hopenbsd:
case Hdragonfly:
- /*
- * ELF uses TLS offsets negative from %gs.
- * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
- * Also known to ../../pkg/runtime/sys_linux_386.s
- * and ../../pkg/runtime/cgo/gcc_linux_386.c.
- */
- tlsoffset = -8;
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
@@ -263,6 +108,19 @@ main(int argc, char *argv[])
if(INITRND == -1)
INITRND = 4096;
break;
+
+ case Hnacl:
+ elfinit();
+ 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;
@@ -275,518 +133,6 @@ main(int argc, char *argv[])
break;
}
if(INITDAT != 0 && INITRND != 0)
- print("warning: -D0x%ux is ignored because of -R0x%ux\n",
+ print("warning: -D0x%llux is ignored because of -R0x%ux\n",
INITDAT, INITRND);
- if(debug['v'])
- Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -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;
-
- pcstr = "%.6ux ";
- 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();
- if(HEADTYPE == Hwindows)
- dope();
- dostkoff();
- dostkcheck();
- if(debug['p'])
- if(debug['1'])
- doprof1();
- else
- doprof2();
- span();
- 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->type = D_NONE;
- a->offset = 0;
- if(t & T_OFFSET)
- a->offset = BGETLE4(f);
- a->offset2 = 0;
- if(t & T_OFFSET2) {
- a->offset2 = BGETLE4(f);
- a->type = D_CONST2;
- }
- a->sym = S;
- if(t & T_SYM)
- a->sym = zsym(pn, f, h);
- 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);
- adrgotype = S;
- if(t & T_GOTYPE)
- adrgotype = zsym(pn, f, h);
-
- t = a->type;
- if(t == D_INDIR+D_GS)
- a->offset += tlsoffset;
-
- s = a->sym;
- if(s == S)
- return;
- if(t != D_AUTO && t != D_PARAM) {
- if(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;
- }
- }
-
- 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)
-{
- int32 ipc;
- Prog *p;
- int v, o, r, skip;
- Sym *h[NSYM], *s;
- uint32 sig;
- int ntext;
- int32 eof;
- char *name, *x;
- 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;
-
-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 .%c file\n", thechar);
- 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;
- zaddr(pn, f, &p->from, h);
- fromgotype = adrgotype;
- zaddr(pn, f, &p->to, h);
-
- 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'])
- diag("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);
- }
- s->type = STEXT;
- s->hist = gethist();
- s->value = pc;
- s->args = p->to.offset2;
- lastp = p;
- p->pc = pc++;
- 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(Prog));
- *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;
- return p;
}
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
deleted file mode 100644
index a4c40e8e3..000000000
--- a/src/cmd/8l/optab.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-// Inferno utils/8l/optab.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/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, Yi32, Zpseudo,1,
- 0
-};
-uchar ynop[] =
-{
- Ynone, Ynone, Zpseudo,1,
- Ynone, Yml, Zpseudo,1,
- Ynone, Yrf, Zpseudo,1,
- Yml, Ynone, Zpseudo,1,
- Yrf, 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 yincl[] =
-{
- Ynone, Yrl, Z_rp, 1,
- 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 ymovw[] =
-{
- Yrl, Yml, Zr_m, 1,
- Yml, Yrl, Zm_r, 1,
- Yi0, Yrl, Zclr, 1+2,
-// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
- Yi32, Yrl, Zil_rp, 1,
- Yi32, Yml, Zilo_m, 2,
- Yiauto, Yrl, Zaut_r, 1,
- 0
-};
-uchar ymovl[] =
-{
- Yrl, Yml, Zr_m, 1,
- Yml, Yrl, Zm_r, 1,
- Yi0, Yrl, Zclr, 1+2,
-// Yi0, Yml, Zibo_m, 2, // shorter but slower AND $0,dst
- Yi32, Yrl, Zil_rp, 1,
- Yi32, Yml, Zilo_m, 2,
- Yml, Yxr, Zm_r_xm, 2, // XMM MOVD (32 bit)
- Yxr, Yml, Zr_m_xm, 2, // XMM MOVD (32 bit)
- Yiauto, Yrl, Zaut_r, 1,
- 0
-};
-uchar ymovq[] =
-{
- Yml, Yxr, Zm_r_xm, 2,
- 0
-};
-uchar ym_rl[] =
-{
- Ym, Yrl, Zm_r, 1,
- 0
-};
-uchar yrl_m[] =
-{
- Yrl, Ym, Zr_m, 1,
- 0
-};
-uchar ymb_rl[] =
-{
- Ymb, Yrl, Zm_r, 1,
- 0
-};
-uchar yml_rl[] =
-{
- Yml, Yrl, Zm_r, 1,
- 0
-};
-uchar yrb_mb[] =
-{
- Yrb, Ymb, Zr_m, 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 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,
- 0
-};
-uchar ybyte[] =
-{
- Yi32, 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, 1,
- 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_m, 0,
- Yrx, Yrx, Zo_m, 2,
- Ynone, Ycol, Zcallind, 2,
- Ynone, Ybr, Zcall, 0,
- Ynone, Yi32, Zcallcon, 1,
- 0
-};
-uchar yjmp[] =
-{
- Ynone, Yml, Zo_m, 2,
- Ynone, Ybr, Zjmp, 0,
- Ynone, Yi32, Zjmpcon, 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 yfcmv[] =
-{
- Yrf, Yf0, Zm_o, 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 ymskb[] =
-{
- Yxr, Yrl, Zm_r_xm, 2,
- Ymr, Yrl, Zm_r_xm, 1,
- 0
-};
-uchar yxm[] =
-{
- Yxm, Yxr, Zm_r_xm, 1,
- 0
-};
-uchar yxcvm1[] =
-{
- Yxm, Yxr, Zm_r_xm, 2,
- Yxm, Ymr, Zm_r_xm, 2,
- 0
-};
-uchar yxcvm2[] =
-{
- Yxm, Yxr, Zm_r_xm, 2,
- Ymm, Yxr, Zm_r_xm, 2,
- 0
-};
-uchar yxmq[] =
-{
- Yxm, Yxr, Zm_r_xm, 2,
- 0
-};
-uchar yxr[] =
-{
- Yxr, Yxr, Zm_r_xm, 1,
- 0
-};
-uchar yxr_ml[] =
-{
- Yxr, Yml, Zr_m_xm, 1,
- 0
-};
-uchar yxcmp[] =
-{
- Yxm, Yxr, Zm_r_xm, 1,
- 0
-};
-uchar yxcmpi[] =
-{
- Yxm, Yxr, Zm_r_i_xm, 2,
- 0
-};
-uchar yxmov[] =
-{
- Yxm, Yxr, Zm_r_xm, 1,
- Yxr, Yxm, Zr_m_xm, 1,
- 0
-};
-uchar yxcvfl[] =
-{
- Yxm, Yrl, Zm_r_xm, 1,
- 0
-};
-uchar yxcvlf[] =
-{
- Yml, Yxr, Zm_r_xm, 1,
- 0
-};
-uchar yxcvfq[] =
-{
- Yxm, Yrl, Zm_r_xm, 2,
- 0
-};
-uchar yxcvqf[] =
-{
- Yml, Yxr, Zm_r_xm, 2,
- 0
-};
-uchar yxrrl[] =
-{
- Yxr, Yrl, Zm_r, 1,
- 0
-};
-uchar yprefetch[] =
-{
- Ym, Ynone, Zm_o, 2,
- 0,
-};
-uchar yaes[] =
-{
- Yxm, Yxr, Zlitm_r, 2,
- 0
-};
-uchar yinsrd[] =
-{
- Yml, Yxr, Zibm_r, 2,
- 0
-};
-uchar ymshufb[] =
-{
- Yxm, Yxr, Zm2_r, 2,
- 0
-};
-
-Optab optab[] =
-/* as, ytab, andproto, opcode */
-{
- { AXXX },
- { AAAA, ynone, Px, 0x37 },
- { AAAD, ynone, Px, 0xd5,0x0a },
- { AAAM, ynone, Px, 0xd4,0x0a },
- { AAAS, ynone, Px, 0x3f },
- { AADCB, yxorb, Pb, 0x14,0x80,(02),0x10,0x10 },
- { AADCL, yxorl, Px, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADCW, yxorl, Pe, 0x83,(02),0x15,0x81,(02),0x11,0x13 },
- { AADDB, yxorb, Px, 0x04,0x80,(00),0x00,0x02 },
- { AADDL, yaddl, Px, 0x83,(00),0x05,0x81,(00),0x01,0x03 },
- { 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 },
- { AANDW, yxorl, Pe, 0x83,(04),0x25,0x81,(04),0x21,0x23 },
- { AARPL, yrl_ml, Px, 0x63 },
- { ABOUNDL, yrl_m, Px, 0x62 },
- { ABOUNDW, yrl_m, Pe, 0x62 },
- { ABSFL, yml_rl, Pm, 0xbc },
- { ABSFW, yml_rl, Pq, 0xbc },
- { ABSRL, yml_rl, Pm, 0xbd },
- { ABSRW, yml_rl, Pq, 0xbd },
- { ABTL, yml_rl, Pm, 0xa3 },
- { ABTW, yml_rl, Pq, 0xa3 },
- { ABTCL, yml_rl, Pm, 0xbb },
- { ABTCW, yml_rl, Pq, 0xbb },
- { ABTRL, yml_rl, Pm, 0xb3 },
- { ABTRW, yml_rl, Pq, 0xb3 },
- { ABTSL, yml_rl, Pm, 0xab },
- { ABTSW, yml_rl, Pq, 0xab },
- { ABYTE, ybyte, Px, 1 },
- { ACALL, ycall, Px, 0xff,(02),0xff,(0x15),0xe8 },
- { ACLC, ynone, Px, 0xf8 },
- { ACLD, ynone, Px, 0xfc },
- { ACLI, ynone, Px, 0xfa },
- { ACLTS, ynone, Pm, 0x06 },
- { ACMC, ynone, Px, 0xf5 },
- { ACMPB, ycmpb, Pb, 0x3c,0x80,(07),0x38,0x3a },
- { ACMPL, ycmpl, Px, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPW, ycmpl, Pe, 0x83,(07),0x3d,0x81,(07),0x39,0x3b },
- { ACMPSB, ynone, Pb, 0xa6 },
- { ACMPSL, ynone, Px, 0xa7 },
- { ACMPSW, ynone, Pe, 0xa7 },
- { ADAA, ynone, Px, 0x27 },
- { ADAS, ynone, Px, 0x2f },
- { ADATA },
- { ADECB, yincb, Pb, 0xfe,(01) },
- { ADECL, yincl, Px, 0x48,0xff,(01) },
- { ADECW, yincl, Pe, 0x48,0xff,(01) },
- { ADIVB, ydivb, Pb, 0xf6,(06) },
- { ADIVL, ydivl, Px, 0xf7,(06) },
- { ADIVW, ydivl, Pe, 0xf7,(06) },
- { AENTER }, /* botch */
- { AGLOBL },
- { AGOK },
- { AHISTORY },
- { AHLT, ynone, Px, 0xf4 },
- { AIDIVB, ydivb, Pb, 0xf6,(07) },
- { AIDIVL, ydivl, Px, 0xf7,(07) },
- { AIDIVW, ydivl, Pe, 0xf7,(07) },
- { AIMULB, ydivb, Pb, 0xf6,(05) },
- { AIMULL, yimul, Px, 0xf7,(05),0x6b,0x69 },
- { AIMULW, yimul, Pe, 0xf7,(05),0x6b,0x69 },
- { AINB, yin, Pb, 0xe4,0xec },
- { AINL, yin, Px, 0xe5,0xed },
- { AINW, yin, Pe, 0xe5,0xed },
- { AINCB, yincb, Pb, 0xfe,(00) },
- { AINCL, yincl, Px, 0x40,0xff,(00) },
- { AINCW, yincl, Pe, 0x40,0xff,(00) },
- { AINSB, ynone, Pb, 0x6c },
- { AINSL, ynone, Px, 0x6d },
- { AINSW, ynone, Pe, 0x6d },
- { AINT, yint, Px, 0xcd },
- { AINTO, ynone, Px, 0xce },
- { AIRETL, ynone, Px, 0xcf },
- { AIRETW, ynone, Pe, 0xcf },
- { AJCC, yjcond, Px, 0x73,0x83,(00) },
- { AJCS, yjcond, Px, 0x72,0x82 },
- { AJCXZL, yloop, Px, 0xe3 },
- { AJCXZW, 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 },
- { ALEAL, ym_rl, Px, 0x8d },
- { ALEAW, ym_rl, Pe, 0x8d },
- { ALEAVEL, ynone, Px, 0xc9 },
- { ALEAVEW, ynone, Pe, 0xc9 },
- { ALOCK, ynone, Px, 0xf0 },
- { ALODSB, ynone, Pb, 0xac },
- { ALODSL, ynone, Px, 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 },
- { AMOVB, ymovb, Pb, 0x88,0x8a,0xb0,0xc6,(00) },
- { AMOVL, ymovl, Px, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),Pe,0x6e,Pe,0x7e,0 },
- { AMOVW, ymovw, Pe, 0x89,0x8b,0x31,0x83,(04),0xb8,0xc7,(00),0 },
- { AMOVQ, ymovq, Pf3, 0x7e },
- { AMOVBLSX, ymb_rl, Pm, 0xbe },
- { AMOVBLZX, ymb_rl, Pm, 0xb6 },
- { AMOVBWSX, ymb_rl, Pq, 0xbe },
- { AMOVBWZX, ymb_rl, Pq, 0xb6 },
- { AMOVWLSX, yml_rl, Pm, 0xbf },
- { AMOVWLZX, yml_rl, Pm, 0xb7 },
- { AMOVSB, ynone, Pb, 0xa4 },
- { AMOVSL, ynone, Px, 0xa5 },
- { AMOVSW, ynone, Pe, 0xa5 },
- { AMULB, ydivb, Pb, 0xf6,(04) },
- { AMULL, ydivl, Px, 0xf7,(04) },
- { AMULW, ydivl, Pe, 0xf7,(04) },
- { ANAME },
- { ANEGB, yscond, Px, 0xf6,(03) },
- { ANEGL, yscond, Px, 0xf7,(03) },
- { ANEGW, yscond, Pe, 0xf7,(03) },
- { ANOP, ynop, Px,0,0 },
- { ANOTB, yscond, Px, 0xf6,(02) },
- { ANOTL, yscond, Px, 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 },
- { AORW, yxorl, Pe, 0x83,(01),0x0d,0x81,(01),0x09,0x0b },
- { AOUTB, yin, Pb, 0xe6,0xee },
- { AOUTL, yin, Px, 0xe7,0xef },
- { AOUTW, yin, Pe, 0xe7,0xef },
- { AOUTSB, ynone, Pb, 0x6e },
- { AOUTSL, ynone, Px, 0x6f },
- { AOUTSW, ynone, Pe, 0x6f },
- { APAUSE, ynone, Px, 0xf3,0x90 },
- { APOPAL, ynone, Px, 0x61 },
- { APOPAW, ynone, Pe, 0x61 },
- { APOPFL, ynone, Px, 0x9d },
- { APOPFW, ynone, Pe, 0x9d },
- { APOPL, ypopl, Px, 0x58,0x8f,(00) },
- { APOPW, ypopl, Pe, 0x58,0x8f,(00) },
- { APUSHAL, ynone, Px, 0x60 },
- { APUSHAW, ynone, Pe, 0x60 },
- { APUSHFL, ynone, Px, 0x9c },
- { APUSHFW, ynone, Pe, 0x9c },
- { APUSHL, ypushl, Px, 0x50,0xff,(06),0x6a,0x68 },
- { APUSHW, ypushl, Pe, 0x50,0xff,(06),0x6a,0x68 },
- { ARCLB, yshb, Pb, 0xd0,(02),0xc0,(02),0xd2,(02) },
- { ARCLL, yshl, Px, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCLW, yshl, Pe, 0xd1,(02),0xc1,(02),0xd3,(02),0xd3,(02) },
- { ARCRB, yshb, Pb, 0xd0,(03),0xc0,(03),0xd2,(03) },
- { ARCRL, yshl, Px, 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 },
- { AROLB, yshb, Pb, 0xd0,(00),0xc0,(00),0xd2,(00) },
- { AROLL, yshl, Px, 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) },
- { ARORW, yshl, Pe, 0xd1,(01),0xc1,(01),0xd3,(01),0xd3,(01) },
- { ASAHF, ynone, Px, 0x9e },
- { ASALB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASALL, yshl, Px, 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) },
- { 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 },
- { ASBBW, yxorl, Pe, 0x83,(03),0x1d,0x81,(03),0x19,0x1b },
- { ASCASB, ynone, Pb, 0xae },
- { ASCASL, ynone, Px, 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) },
- { ACDQ, ynone, Px, 0x99 },
- { ACWD, ynone, Pe, 0x99 },
- { ASHLB, yshb, Pb, 0xd0,(04),0xc0,(04),0xd2,(04) },
- { ASHLL, yshl, Px, 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) },
- { ASHRW, yshl, Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
- { ASTC, ynone, Px, 0xf9 },
- { ASTD, ynone, Px, 0xfd },
- { ASTI, ynone, Px, 0xfb },
- { ASTOSB, ynone, Pb, 0xaa },
- { ASTOSL, ynone, Px, 0xab },
- { ASTOSW, ynone, Pe, 0xab },
- { ASUBB, yxorb, Pb, 0x2c,0x80,(05),0x28,0x2a },
- { ASUBL, yaddl, Px, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASUBW, yaddl, Pe, 0x83,(05),0x2d,0x81,(05),0x29,0x2b },
- { ASYSCALL, ynone, Px, 0xcd,100 },
- { ATESTB, ytestb, Pb, 0xa8,0xf6,(00),0x84,0x84 },
- { ATESTL, ytestl, Px, 0xa9,0xf7,(00),0x85,0x85 },
- { ATESTW, ytestl, Pe, 0xa9,0xf7,(00),0x85,0x85 },
- { ATEXT, ytext, Px },
- { 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 },
- { 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 },
- { 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) },
- { AFCOMI, yfmvx, Px, 0xdb,(06) },
- { AFCOMIP, yfmvx, Px, 0xdf,(06) },
- { 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) },
- { AFUCOMI, ycompp, Px, 0xdb,(05) },
- { AFUCOMIP, ycompp, Px, 0xdf,(05) },
- { 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 },
- { AEND },
- { ADYNT_ },
- { AINIT_ },
- { ASIGNAME },
- { ACMPXCHGB, yrb_mb, Pm, 0xb0 },
- { ACMPXCHGL, yrl_ml, Pm, 0xb1 },
- { ACMPXCHGW, yrl_ml, Pm, 0xb1 },
- { ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
-
- { ACPUID, ynone, Pm, 0xa2 },
- { ARDTSC, ynone, Pm, 0x31 },
-
- { AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
- { AXADDL, yrl_ml, Pm, 0xc1 },
- { AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
-
- { 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 },
- { 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 },
-
- { AFCMOVCC, yfcmv, Px, 0xdb,(00) },
- { AFCMOVCS, yfcmv, Px, 0xda,(00) },
- { AFCMOVEQ, yfcmv, Px, 0xda,(01) },
- { AFCMOVHI, yfcmv, Px, 0xdb,(02) },
- { AFCMOVLS, yfcmv, Px, 0xda,(02) },
- { AFCMOVNE, yfcmv, Px, 0xdb,(01) },
- { AFCMOVNU, yfcmv, Px, 0xdb,(03) },
- { AFCMOVUN, yfcmv, Px, 0xda,(03) },
-
- { ALFENCE, ynone, Pm, 0xae,0xe8 },
- { AMFENCE, ynone, Pm, 0xae,0xf0 },
- { ASFENCE, ynone, Pm, 0xae,0xf8 },
-
- { AEMMS, ynone, Pm, 0x77 },
-
- { APREFETCHT0, yprefetch, Pm, 0x18,(01) },
- { APREFETCHT1, yprefetch, Pm, 0x18,(02) },
- { APREFETCHT2, yprefetch, Pm, 0x18,(03) },
- { APREFETCHNTA, yprefetch, Pm, 0x18,(00) },
-
- { ABSWAPL, ybswap, Pm, 0xc8 },
-
- { AUNDEF, ynone, Px, 0x0f, 0x0b },
-
- { AADDPD, yxm, Pq, 0x58 },
- { AADDPS, yxm, Pm, 0x58 },
- { AADDSD, yxm, Pf2, 0x58 },
- { AADDSS, yxm, Pf3, 0x58 },
- { AANDNPD, yxm, Pq, 0x55 },
- { AANDNPS, yxm, Pm, 0x55 },
- { AANDPD, yxm, Pq, 0x54 },
- { AANDPS, yxm, Pq, 0x54 },
- { ACMPPD, yxcmpi, Px, Pe,0xc2 },
- { ACMPPS, yxcmpi, Pm, 0xc2,0 },
- { ACMPSD, yxcmpi, Px, Pf2,0xc2 },
- { ACMPSS, yxcmpi, Px, Pf3,0xc2 },
- { ACOMISD, yxcmp, Pe, 0x2f },
- { ACOMISS, yxcmp, Pm, 0x2f },
- { ACVTPL2PD, yxcvm2, Px, Pf3,0xe6,Pe,0x2a },
- { ACVTPL2PS, yxcvm2, Pm, 0x5b,0,0x2a,0, },
- { ACVTPD2PL, yxcvm1, Px, Pf2,0xe6,Pe,0x2d },
- { ACVTPD2PS, yxm, Pe, 0x5a },
- { ACVTPS2PL, yxcvm1, Px, Pe,0x5b,Pm,0x2d },
- { ACVTPS2PD, yxm, Pm, 0x5a },
- { ACVTSD2SL, yxcvfl, Pf2, 0x2d },
- { ACVTSD2SS, yxm, Pf2, 0x5a },
- { ACVTSL2SD, yxcvlf, Pf2, 0x2a },
- { ACVTSL2SS, yxcvlf, Pf3, 0x2a },
- { ACVTSS2SD, yxm, Pf3, 0x5a },
- { ACVTSS2SL, yxcvfl, Pf3, 0x2d },
- { ACVTTPD2PL, yxcvm1, Px, Pe,0xe6,Pe,0x2c },
- { ACVTTPS2PL, yxcvm1, Px, Pf3,0x5b,Pm,0x2c },
- { ACVTTSD2SL, yxcvfl, Pf2, 0x2c },
- { ACVTTSS2SL, yxcvfl, Pf3, 0x2c },
- { ADIVPD, yxm, Pe, 0x5e },
- { ADIVPS, yxm, Pm, 0x5e },
- { ADIVSD, yxm, Pf2, 0x5e },
- { ADIVSS, yxm, Pf3, 0x5e },
- { AMASKMOVOU, yxr, Pe, 0xf7 },
- { AMAXPD, yxm, Pe, 0x5f },
- { AMAXPS, yxm, Pm, 0x5f },
- { AMAXSD, yxm, Pf2, 0x5f },
- { AMAXSS, yxm, Pf3, 0x5f },
- { AMINPD, yxm, Pe, 0x5d },
- { AMINPS, yxm, Pm, 0x5d },
- { AMINSD, yxm, Pf2, 0x5d },
- { AMINSS, yxm, Pf3, 0x5d },
- { AMOVAPD, yxmov, Pe, 0x28,0x29 },
- { AMOVAPS, yxmov, Pm, 0x28,0x29 },
- { AMOVO, yxmov, Pe, 0x6f,0x7f },
- { AMOVOU, yxmov, Pf3, 0x6f,0x7f },
- { AMOVHLPS, yxr, Pm, 0x12 },
- { AMOVHPD, yxmov, Pe, 0x16,0x17 },
- { AMOVHPS, yxmov, Pm, 0x16,0x17 },
- { AMOVLHPS, yxr, Pm, 0x16 },
- { AMOVLPD, yxmov, Pe, 0x12,0x13 },
- { AMOVLPS, yxmov, Pm, 0x12,0x13 },
- { AMOVMSKPD, yxrrl, Pq, 0x50 },
- { AMOVMSKPS, yxrrl, Pm, 0x50 },
- { AMOVNTO, yxr_ml, Pe, 0xe7 },
- { AMOVNTPD, yxr_ml, Pe, 0x2b },
- { AMOVNTPS, yxr_ml, Pm, 0x2b },
- { AMOVSD, yxmov, Pf2, 0x10,0x11 },
- { AMOVSS, yxmov, Pf3, 0x10,0x11 },
- { AMOVUPD, yxmov, Pe, 0x10,0x11 },
- { AMOVUPS, yxmov, Pm, 0x10,0x11 },
- { AMULPD, yxm, Pe, 0x59 },
- { AMULPS, yxm, Ym, 0x59 },
- { AMULSD, yxm, Pf2, 0x59 },
- { AMULSS, yxm, Pf3, 0x59 },
- { AORPD, yxm, Pq, 0x56 },
- { AORPS, yxm, Pm, 0x56 },
- { APADDQ, yxm, Pe, 0xd4 },
- { APAND, yxm, Pe, 0xdb },
- { APCMPEQB, yxmq, Pe ,0x74 },
- { APMAXSW, yxm, Pe, 0xee },
- { APMAXUB, yxm, Pe, 0xde },
- { APMINSW, yxm, Pe, 0xea },
- { APMINUB, yxm, Pe, 0xda },
- { APMOVMSKB, ymskb, Px, Pe,0xd7,0xd7 },
- { APSADBW, yxm, Pq, 0xf6 },
- { APSUBB, yxm, Pe, 0xf8 },
- { APSUBL, yxm, Pe, 0xfa },
- { APSUBQ, yxm, Pe, 0xfb },
- { APSUBSB, yxm, Pe, 0xe8 },
- { APSUBSW, yxm, Pe, 0xe9 },
- { APSUBUSB, yxm, Pe, 0xd8 },
- { APSUBUSW, yxm, Pe, 0xd9 },
- { APSUBW, yxm, Pe, 0xf9 },
- { APUNPCKHQDQ, yxm, Pe, 0x6d },
- { APUNPCKLQDQ, yxm, Pe, 0x6c },
- { ARCPPS, yxm, Pm, 0x53 },
- { ARCPSS, yxm, Pf3, 0x53 },
- { ARSQRTPS, yxm, Pm, 0x52 },
- { ARSQRTSS, yxm, Pf3, 0x52 },
- { ASQRTPD, yxm, Pe, 0x51 },
- { ASQRTPS, yxm, Pm, 0x51 },
- { ASQRTSD, yxm, Pf2, 0x51 },
- { ASQRTSS, yxm, Pf3, 0x51 },
- { ASUBPD, yxm, Pe, 0x5c },
- { ASUBPS, yxm, Pm, 0x5c },
- { ASUBSD, yxm, Pf2, 0x5c },
- { ASUBSS, yxm, Pf3, 0x5c },
- { AUCOMISD, yxcmp, Pe, 0x2e },
- { AUCOMISS, yxcmp, Pm, 0x2e },
- { AUNPCKHPD, yxm, Pe, 0x15 },
- { AUNPCKHPS, yxm, Pm, 0x15 },
- { AUNPCKLPD, yxm, Pe, 0x14 },
- { AUNPCKLPS, yxm, Pm, 0x14 },
- { AXORPD, yxm, Pe, 0x57 },
- { AXORPS, yxm, Pm, 0x57 },
-
- { AAESENC, yaes, Pq, 0x38,0xdc,(0) },
- { APINSRD, yinsrd, Pq, 0x3a, 0x22, (00) },
- { APSHUFB, ymshufb,Pq, 0x38, 0x00 },
-
- { AUSEFIELD, ynop, Px, 0,0 },
- { ATYPE },
- { AFUNCDATA, yfuncdata, Px, 0,0 },
- { APCDATA, ypcdata, Px, 0,0 },
-
- 0
-};
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
deleted file mode 100644
index 1eaf78fe0..000000000
--- a/src/cmd/8l/pass.c
+++ /dev/null
@@ -1,858 +0,0 @@
-// Inferno utils/8l/pass.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/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 AIRETW:
- case AUNDEF:
- return 1;
- }
- return 0;
-}
-
-static int
-pushpop(int a)
-{
- switch(a) {
- case APUSHL:
- case APUSHFL:
- case APUSHW:
- case APUSHFW:
- case APOPL:
- case APOPFL:
- 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;
-}
-
-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);
- return a;
-}
-
-void
-patch(void)
-{
- int32 c;
- Prog *p, *q;
- Sym *s;
- int32 vexit;
- Sym *plan9_tos;
-
- 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);
- s = lookup("exit", 0);
- vexit = s->value;
-
- plan9_tos = S;
- if(HEADTYPE == Hplan9x32)
- plan9_tos = lookup("_tos", 0);
-
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- for(p = cursym->text; p != P; p = p->link) {
- if(HEADTYPE == Hwindows) {
- // Convert
- // op n(GS), reg
- // to
- // MOVL 0x14(FS), 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) {
- 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 = AMOVL;
- p->from.type = D_INDIR+D_FS;
- p->from.offset = 0x14;
- }
- }
- if(HEADTYPE == Hlinux) {
- // Running binaries under Xen requires using
- // MOVL 0(GS), reg
- // and then off(reg) instead of saying off(GS) directly
- // when the offset is negative.
- // In external mode we just produce a reloc.
- if(p->from.type == D_INDIR+D_GS && p->from.offset < 0
- && p->to.type >= D_AX && p->to.type <= D_DI) {
- if(linkmode != LinkExternal) {
- 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 = AMOVL;
- p->from.type = D_INDIR+D_GS;
- p->from.offset = 0;
- } else {
- // Add signals to relocate.
- p->from.index = D_GS;
- p->from.scale = 1;
- }
- }
- }
- if(HEADTYPE == Hplan9x32) {
- if(p->from.type == D_INDIR+D_GS
- && p->to.type >= D_AX && p->to.type <= D_DI) {
- 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 = AMOVL;
- p->from.type = D_EXTERN;
- p->from.sym = plan9_tos;
- p->from.offset = 0;
- }
- }
- if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) {
- s = p->to.sym;
- if(p->to.type == D_INDIR+D_ADDR) {
- /* skip check if this is an indirect call (CALL *symbol(SB)) */
- continue;
- } else 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) {
- if(cursym->text == nil || cursym->p != nil)
- continue;
-
- 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 Prog* load_g_cx(Prog*);
-static Prog* stacksplit(Prog*, int32, Prog**);
-
-static Sym *plan9_tos;
-static Prog *pmorestack;
-static Sym *symmorestack;
-
-void
-dostkoff(void)
-{
- Prog *p, *q;
- int32 autoffset, deltasp;
- int a;
-
- pmorestack = P;
- symmorestack = lookup("runtime.morestack", 0);
-
- if(symmorestack->type != STEXT)
- diag("runtime.morestack not defined");
- else {
- pmorestack = symmorestack->text;
- symmorestack->text->from.scale |= NOSPLIT;
- }
-
- plan9_tos = S;
- if(HEADTYPE == Hplan9x32)
- plan9_tos = lookup("_tos", 0);
-
- for(cursym = textp; cursym != nil; cursym = cursym->next) {
- if(cursym->text == nil || cursym->text->link == nil)
- continue;
-
- p = cursym->text;
- autoffset = p->to.offset;
- if(autoffset < 0)
- autoffset = 0;
-
- 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['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
- // 8l -Z means zero the stack frame on entry.
- // This slows down function calls but can help avoid
- // false positives in garbage collection.
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_SP;
- p->to.type = D_DI;
-
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = autoffset/4;
- p->to.type = D_CX;
-
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_CONST;
- p->from.offset = 0;
- p->to.type = D_AX;
-
- p = appendp(p);
- p->as = AREP;
-
- p = appendp(p);
- p->as = ASTOSL;
- }
-
- for(; p != P; p = p->link) {
- a = p->from.type;
- if(a == D_AUTO)
- p->from.offset += deltasp;
- if(a == D_PARAM)
- p->from.offset += deltasp + 4;
- a = p->to.type;
- if(a == D_AUTO)
- p->to.offset += deltasp;
- if(a == D_PARAM)
- p->to.offset += deltasp + 4;
-
- switch(p->as) {
- default:
- continue;
- case APUSHL:
- case APUSHFL:
- deltasp += 4;
- p->spadj = 4;
- continue;
- case APUSHW:
- case APUSHFW:
- deltasp += 2;
- p->spadj = 2;
- continue;
- case APOPL:
- case APOPFL:
- deltasp -= 4;
- p->spadj = -4;
- 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)
-{
- switch(HEADTYPE) {
- case Hwindows:
- p->as = AMOVL;
- p->from.type = D_INDIR+D_FS;
- p->from.offset = 0x14;
- p->to.type = D_CX;
-
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
- p->from.offset = 0;
- p->to.type = D_CX;
- break;
-
- case Hlinux:
- if(linkmode != LinkExternal) {
- p->as = AMOVL;
- p->from.type = D_INDIR+D_GS;
- p->from.offset = 0;
- p->to.type = D_CX;
-
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
- p->from.offset = tlsoffset + 0;
- p->to.type = D_CX;
- } else {
- p->as = AMOVL;
- p->from.type = D_INDIR+D_GS;
- p->from.offset = tlsoffset + 0;
- p->to.type = D_CX;
- p->from.index = D_GS;
- p->from.scale = 1;
- }
- break;
-
- case Hplan9x32:
- p->as = AMOVL;
- p->from.type = D_EXTERN;
- p->from.sym = plan9_tos;
- p->to.type = D_CX;
-
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
- p->from.offset = tlsoffset + 0;
- p->to.type = D_CX;
- break;
-
- default:
- p->as = AMOVL;
- p->from.type = D_INDIR+D_GS;
- p->from.offset = tlsoffset + 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;
- int arg;
-
- if(debug['K']) {
- // 8l -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 = ACMPL;
- p->from.type = D_INDIR+D_CX;
- p->from.offset = 4;
- p->to.type = D_SP;
-
- p = appendp(p);
- p->as = AJCC;
- 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;
- }
- q1 = P;
-
- if(framesize <= StackSmall) {
- // small stack: SP <= stackguard
- // CMPL SP, stackguard
- p = appendp(p);
- p->as = ACMPL;
- p->from.type = D_SP;
- p->to.type = D_INDIR+D_CX;
- } else if(framesize <= StackBig) {
- // large stack: SP-framesize <= stackguard-StackSmall
- // LEAL -(framesize-StackSmall)(SP), AX
- // CMPL AX, stackguard
- p = appendp(p);
- p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
- p->from.offset = -(framesize-StackSmall);
- p->to.type = D_AX;
-
- p = appendp(p);
- p->as = ACMPL;
- 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.
- // MOVL stackguard, CX
- // CMPL CX, $StackPreempt
- // JEQ label-of-call-to-morestack
- // LEAL StackGuard(SP), AX
- // SUBL stackguard, AX
- // CMPL AX, $(framesize+(StackGuard-StackSmall))
- p = appendp(p);
- p->as = AMOVL;
- p->from.type = D_INDIR+D_CX;
- p->from.offset = 0;
- p->to.type = D_SI;
-
- p = appendp(p);
- p->as = ACMPL;
- p->from.type = D_SI;
- p->to.type = D_CONST;
- p->to.offset = (uint32)StackPreempt;
-
- p = appendp(p);
- p->as = AJEQ;
- p->to.type = D_BRANCH;
- q1 = p;
-
- p = appendp(p);
- p->as = ALEAL;
- p->from.type = D_INDIR+D_SP;
- p->from.offset = StackGuard;
- p->to.type = D_AX;
-
- p = appendp(p);
- p->as = ASUBL;
- p->from.type = D_SI;
- p->from.offset = 0;
- p->to.type = D_AX;
-
- p = appendp(p);
- p->as = ACMPL;
- 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;
- p->to.offset = 4;
- q = p;
-
- p = appendp(p); // save frame size in DI
- p->as = AMOVL;
- p->to.type = D_DI;
- p->from.type = D_CONST;
-
- // 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.
- if(StackTop + cursym->text->to.offset2 + PtrSize + framesize + PtrSize + StackLimit >= StackMin)
- p->from.offset = (framesize+7) & ~7LL;
-
- arg = cursym->text->to.offset2;
- if(arg == 1) // special marker for known 0
- arg = 0;
- if(arg&3)
- diag("misaligned argument size in stack split");
- p = appendp(p); // save arg size in AX
- p->as = AMOVL;
- p->to.type = D_AX;
- p->from.type = D_CONST;
- p->from.offset = arg;
-
- p = appendp(p);
- p->as = ACALL;
- p->to.type = D_BRANCH;
- p->pcond = pmorestack;
- p->to.sym = symmorestack;
-
- 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;
-}
-
-int32
-atolwhex(char *s)
-{
- int32 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/8l/prof.c b/src/cmd/8l/prof.c
deleted file mode 100644
index d99c5e408..000000000
--- a/src/cmd/8l/prof.c
+++ /dev/null
@@ -1,173 +0,0 @@
-// Inferno utils/8l/obj.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/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 // TODO(rsc)
- 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(p = firstp->link; p != P; p = p->link) {
- if(p->as == ATEXT) {
- 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;
- continue;
- }
- }
- 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/8l/span.c b/src/cmd/8l/span.c
deleted file mode 100644
index acf973cab..000000000
--- a/src/cmd/8l/span.c
+++ /dev/null
@@ -1,1507 +0,0 @@
-// Inferno utils/8l/span.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8l/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 int32 vaddr(Adr*, Reloc*);
-
-void
-span1(Sym *s)
-{
- Prog *p, *q;
- int32 c, v, loop;
- uchar *bp;
- int n, m, i;
-
- cursym = s;
-
- 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
-
- if(p->as == AADJSP) {
- p->to.type = D_SP;
- v = -p->from.offset;
- p->from.offset = v;
- p->as = AADDL;
- if(v < 0) {
- p->as = ASUBL;
- 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) {
- 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 == AJCXZW)
- 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 %d (%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%+d\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->text == nil || cursym->text->link == 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 = AADDL;
- if(v < 0) {
- p->as = ASUBL;
- v = -v;
- p->from.offset = v;
- }
- if(v == 0)
- p->as = ANOP;
- }
- }
- span1(cursym);
- }
-}
-
-void
-xdefine(char *p, int t, int32 v)
-{
- Sym *s;
-
- s = lookup(p, 0);
- s->type = t;
- s->value = v;
- s->reachable = 1;
- s->special = 1;
-}
-
-void
-instinit(void)
-{
- int i;
-
- for(i=1; optab[i].as; i++)
- if(i != optab[i].as) {
- diag("phase error in optab: at %A found %A", i, optab[i].as);
- errorexit();
- }
- maxop = 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 + Yi32] = 1;
- ycover[Yi1*Ymax + Yi32] = 1;
- ycover[Yi8*Ymax + Yi32] = 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[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[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_BH)
- reg[i] = (i-D_AL) & 7;
- if(i >= D_AX && i <= D_DI)
- reg[i] = (i-D_AX) & 7;
- if(i >= D_F0 && i <= D_F0+7)
- reg[i] = (i-D_F0) & 7;
- if(i >= D_X0 && i <= D_X0+7)
- reg[i] = (i-D_X0) & 7;
- }
-}
-
-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;
- }
- return 0;
-}
-
-int
-oclass(Adr *a)
-{
- int32 v;
-
- if((a->type >= D_INDIR && a->type < 2*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:
- return Yi32;
- case D_AUTO:
- case D_PARAM:
- return Yiauto;
- }
- return Yxxx;
- }
- //if(a->type == D_INDIR+D_ADDR)
- // print("*Ycol\n");
- return Ycol;
- }
- return Ym;
- }
- switch(a->type)
- {
- case D_AL:
- return Yal;
-
- case D_AX:
- return Yax;
-
- case D_CL:
- case D_DL:
- case D_BL:
- case D_AH:
- case D_CH:
- case D_DH:
- case D_BH:
- return Yrb;
-
- case D_CX:
- return Ycx;
-
- case D_DX:
- case D_BX:
- return Yrx;
-
- 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_X0+0:
- case D_X0+1:
- case D_X0+2:
- case D_X0+3:
- case D_X0+4:
- case D_X0+5:
- case D_X0+6:
- case D_X0+7:
- return Yxr;
-
- case D_NONE:
- return Ynone;
-
- 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_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_CONST2:
- 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;
- }
- return Yi32;
-
- 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_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_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);
-}
-
-int32
-symaddr(Sym *s)
-{
- if(!s->reachable)
- diag("unreachable symbol in symaddr - %s", s->name);
- return s->value;
-}
-
-static int32
-vaddr(Adr *a, Reloc *r)
-{
- int t;
- int32 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 != nil) {
- if(!s->reachable)
- sysfatal("unreachable symbol in vaddr - %s", s->name);
- if(r == nil) {
- diag("need reloc for %D", a);
- errorexit();
- }
- r->type = D_ADDR;
- r->siz = 4;
- r->off = -1;
- r->sym = s;
- r->add = v;
- v = 0;
- }
- }
- return v;
-}
-
-static int
-istls(Adr *a)
-{
- if(HEADTYPE == Hlinux)
- return a->index == D_GS;
- return a->type == D_INDIR+D_GS;
-}
-
-void
-asmand(Adr *a, int r)
-{
- int32 v;
- int t, scale;
- Reloc rel;
-
- 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 || t >= 2*D_INDIR) {
- switch(t) {
- 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;
- }
- } else
- t -= D_INDIR;
-
- 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) {
- *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_F7 || t >= D_X0 && t <= D_X7) {
- if(v)
- goto bad;
- *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
- return;
- }
-
- scale = a->scale;
- if(t < D_INDIR || t >= 2*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;
-
- if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
- *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
- goto putrelv;
- }
- if(t == D_SP) {
- if(v == 0 && rel.siz == 0) {
- *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
- asmidx(scale, D_NONE, t);
- return;
- }
- if(v >= -128 && v < 128 && rel.siz == 0) {
- *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
- asmidx(scale, D_NONE, t);
- *andptr++ = v;
- return;
- }
- *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
- asmidx(scale, D_NONE, t);
- goto putrelv;
- }
- if(t >= D_AX && t <= D_DI) {
- if(v == 0 && rel.siz == 0 && t != D_BP) {
- *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
- return;
- }
- if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) {
- andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
- andptr[1] = v;
- andptr += 2;
- 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 && istls(a) && 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;
-}
-
-#define E 0xff
-uchar 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,
-
- 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,
-
- 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, 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,
-
-/* 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,
-
- AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0,
- AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0,
- AMOVL, 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,
-
-/* 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,
-
-/* extra imul */
- AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0,
- AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
- 0
-};
-
-// byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
-// which is not referenced in a->type.
-// If a is empty, it returns BX to account for MULB-like instructions
-// that might use DX and AX.
-int
-byteswapreg(Adr *a)
-{
- int cana, canb, canc, cand;
-
- cana = canb = canc = cand = 1;
-
- switch(a->type) {
- case D_NONE:
- cana = cand = 0;
- break;
- case D_AX:
- case D_AL:
- case D_AH:
- case D_INDIR+D_AX:
- cana = 0;
- break;
- case D_BX:
- case D_BL:
- case D_BH:
- case D_INDIR+D_BX:
- canb = 0;
- break;
- case D_CX:
- case D_CL:
- case D_CH:
- case D_INDIR+D_CX:
- canc = 0;
- break;
- case D_DX:
- case D_DL:
- case D_DH:
- case D_INDIR+D_DX:
- cand = 0;
- break;
- }
- switch(a->index) {
- case D_AX:
- cana = 0;
- break;
- case D_BX:
- canb = 0;
- break;
- case D_CX:
- canc = 0;
- break;
- case D_DX:
- cand = 0;
- break;
- }
- if(cana)
- return D_AX;
- if(canb)
- return D_BX;
- if(canc)
- return D_CX;
- if(cand)
- return D_DX;
-
- diag("impossible byte register");
- errorexit();
- return 0;
-}
-
-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;
- p->ft = 0;
- }
- if(p->to.type == from) {
- p->to.type = to;
- p->tt = 0;
- }
-
- if(p->from.index == from) {
- p->from.index = to;
- p->ft = 0;
- }
- if(p->to.index == from) {
- p->to.index = to;
- p->tt = 0;
- }
-
- from += D_INDIR;
- if(p->from.type == from) {
- p->from.type = to+D_INDIR;
- p->ft = 0;
- }
- if(p->to.type == from) {
- p->to.type = to+D_INDIR;
- p->tt = 0;
- }
-
- 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;
- int z, op, ft, tt, breg;
- int32 v, pre;
- Reloc rel, *r;
- Adr *a;
-
- curp = p; // TODO
-
- 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;
- o = &optab[p->as];
- t = o->ytab;
- if(t == 0) {
- diag("asmins: noproto %P", p);
- return;
- }
- for(z=0; *t; z+=t[3],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 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 Pb: /* botch */
- break;
- }
-
- 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, reg[p->to.type]);
- break;
-
- case Zm_r:
- *andptr++ = op;
- asmand(&p->from, reg[p->to.type]);
- break;
-
- case Zm2_r:
- *andptr++ = op;
- *andptr++ = o->op[z+1];
- asmand(&p->from, reg[p->to.type]);
- break;
-
- case Zm_r_xm:
- mediaop(o, op, t[3], z);
- asmand(&p->from, reg[p->to.type]);
- break;
-
- case Zm_r_i_xm:
- mediaop(o, op, t[3], z);
- asmand(&p->from, reg[p->to.type]);
- *andptr++ = p->to.offset;
- break;
-
- case Zibm_r:
- while ((op = o->op[z++]) != 0)
- *andptr++ = op;
- asmand(&p->from, reg[p->to.type]);
- *andptr++ = p->to.offset;
- break;
-
- case Zaut_r:
- *andptr++ = 0x8d; /* leal */
- if(p->from.type != D_ADDR)
- diag("asmins: Zaut sb type ADDR");
- p->from.type = p->from.index;
- p->from.index = D_NONE;
- p->ft = 0;
- asmand(&p->from, reg[p->to.type]);
- p->from.index = p->from.type;
- p->from.type = D_ADDR;
- p->ft = 0;
- break;
-
- case Zm_o:
- *andptr++ = op;
- asmand(&p->from, o->op[z+1]);
- break;
-
- case Zr_m:
- *andptr++ = op;
- asmand(&p->to, reg[p->from.type]);
- break;
-
- case Zr_m_xm:
- mediaop(o, op, t[3], z);
- asmand(&p->to, reg[p->from.type]);
- break;
-
- case Zr_m_i_xm:
- mediaop(o, op, t[3], z);
- asmand(&p->to, reg[p->from.type]);
- *andptr++ = p->from.offset;
- break;
-
- case Zo_m:
- *andptr++ = op;
- asmand(&p->to, o->op[z+1]);
- break;
-
- case Zm_ibo:
- *andptr++ = op;
- asmand(&p->from, o->op[z+1]);
- *andptr++ = vaddr(&p->to, nil);
- break;
-
- case Zibo_m:
- *andptr++ = op;
- asmand(&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;
- v = vaddr(a, nil);
- *andptr++ = op;
- *andptr++ = v;
- break;
-
- case Zib_rp:
- *andptr++ = op + reg[p->to.type];
- *andptr++ = vaddr(&p->from, nil);
- break;
-
- case Zil_rp:
- *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 Zib_rr:
- *andptr++ = op;
- asmand(&p->to, reg[p->to.type]);
- *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;
- asmand(&p->to, o->op[z+1]);
- } else {
- a = &p->to;
- asmand(&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, 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 Z_rp:
- *andptr++ = op + reg[p->to.type];
- break;
-
- case Zrp_:
- *andptr++ = op + reg[p->from.type];
- break;
-
- case Zclr:
- *andptr++ = op;
- asmand(&p->to, reg[p->to.type]);
- 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->type = D_PCREL;
- r->siz = 4;
- r->sym = q->from.sym;
- put4(0);
- break;
-
- case Zbr:
- case Zjmp:
- case Zloop:
- q = p->pcond;
- if(q == nil) {
- diag("jmp/branch/loop without target");
- errorexit();
- }
- if(q->as == ATEXT) {
- // jump out of function
- 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 == AJCXZW)
- *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 == AJCXZW)
- *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;
-
- case Zcallcon:
- case Zjmpcon:
- if(t[2] == Zcallcon)
- *andptr++ = op;
- else
- *andptr++ = o->op[z+1];
- r = addrel(cursym);
- r->off = p->pc + andptr - and;
- r->type = D_PCREL;
- r->siz = 4;
- r->add = p->to.offset;
- put4(0);
- break;
-
- case Zcallind:
- *andptr++ = op;
- *andptr++ = o->op[z+1];
- r = addrel(cursym);
- r->off = p->pc + andptr - and;
- r->type = D_ADDR;
- r->siz = 4;
- r->add = p->to.offset;
- r->sym = p->to.sym;
- put4(0);
- 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;
- }
- }
- break;
-
- case Zmov:
- goto domov;
- }
- return;
-
-domov:
- for(t=ymovtab; *t; t+=8)
- if(p->as == t[0])
- if(ycover[ft+t[1]])
- if(ycover[tt+t[2]])
- goto mfound;
-bad:
- /*
- * 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((breg = byteswapreg(&p->to)) != D_AX) {
- *andptr++ = 0x87; /* xchg lhs,bx */
- asmand(&p->from, reg[breg]);
- subreg(&pp, z, breg);
- doasm(&pp);
- *andptr++ = 0x87; /* xchg lhs,bx */
- asmand(&p->from, reg[breg]);
- } 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((breg = byteswapreg(&p->from)) != D_AX) {
- *andptr++ = 0x87; /* xchg rhs,bx */
- asmand(&p->to, reg[breg]);
- subreg(&pp, z, breg);
- doasm(&pp);
- *andptr++ = 0x87; /* xchg rhs,bx */
- asmand(&p->to, reg[breg]);
- } 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 t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
- return;
-
-mfound:
- switch(t[3]) {
- default:
- diag("asmins: unknown mov %d %P", t[3], p);
- break;
-
- case 0: /* lit */
- for(z=4; t[z]!=E; z++)
- *andptr++ = t[z];
- break;
-
- case 1: /* r,m */
- *andptr++ = t[4];
- asmand(&p->to, t[5]);
- break;
-
- case 2: /* m,r */
- *andptr++ = t[4];
- asmand(&p->from, t[5]);
- break;
-
- case 3: /* r,m - 2op */
- *andptr++ = t[4];
- *andptr++ = t[5];
- asmand(&p->to, t[6]);
- break;
-
- case 4: /* m,r - 2op */
- *andptr++ = t[4];
- *andptr++ = t[5];
- asmand(&p->from, t[6]);
- break;
-
- case 5: /* load full pointer, trash heap */
- if(t[4])
- *andptr++ = t[4];
- 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, reg[p->to.type]);
- break;
-
- case 6: /* double shift */
- z = p->from.type;
- switch(z) {
- default:
- goto bad;
- case D_CONST:
- *andptr++ = 0x0f;
- *andptr++ = t[4];
- asmand(&p->to, reg[p->from.index]);
- *andptr++ = p->from.offset;
- break;
- case D_CL:
- case D_CX:
- *andptr++ = 0x0f;
- *andptr++ = t[5];
- asmand(&p->to, reg[p->from.index]);
- break;
- }
- break;
-
- case 7: /* imul rm,r */
- if(t[4] == Pq) {
- *andptr++ = Pe;
- *andptr++ = Pm;
- } else
- *andptr++ = t[4];
- *andptr++ = t[5];
- asmand(&p->from, reg[p->to.type]);
- break;
- }
-}
-
-void
-asmins(Prog *p)
-{
- andptr = and;
- doasm(p);
- if(andptr > and+sizeof and) {
- print("and[] is too short - %ld byte instruction\n", andptr - and);
- errorexit();
- }
-}