summaryrefslogtreecommitdiff
path: root/src/cmd/8l
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
committerOndřej Surý <ondrej@sury.org>2012-04-06 15:14:11 +0200
commit505c19580e0f43fe5224431459cacb7c21edd93d (patch)
tree79e2634c253d60afc0cc0b2f510dc7dcbb48497b /src/cmd/8l
parent1336a7c91e596c423a49d1194ea42d98bca0d958 (diff)
downloadgolang-505c19580e0f43fe5224431459cacb7c21edd93d.tar.gz
Imported Upstream version 1upstream/1
Diffstat (limited to 'src/cmd/8l')
-rw-r--r--src/cmd/8l/8.out.h14
-rw-r--r--src/cmd/8l/Makefile48
-rw-r--r--src/cmd/8l/asm.c85
-rw-r--r--src/cmd/8l/doc.go43
-rw-r--r--src/cmd/8l/l.h2
-rw-r--r--src/cmd/8l/obj.c52
-rw-r--r--src/cmd/8l/optab.c14
-rw-r--r--src/cmd/8l/pass.c27
-rw-r--r--src/cmd/8l/span.c39
9 files changed, 182 insertions, 142 deletions
diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h
index 9a8483aaf..9d2751cf0 100644
--- a/src/cmd/8l/8.out.h
+++ b/src/cmd/8l/8.out.h
@@ -34,6 +34,7 @@
#define DUPOK (1<<1)
#define NOSPLIT (1<<2)
#define RODATA (1<<3)
+#define NOPTR (1<<4)
enum as
{
@@ -115,7 +116,8 @@ enum as
AIRETW,
AJCC,
AJCS,
- AJCXZ,
+ AJCXZL,
+ AJCXZW,
AJEQ,
AJGE,
AJGT,
@@ -394,7 +396,9 @@ enum as
ACMPXCHGL,
ACMPXCHGW,
ACMPXCHG8B,
-
+
+ ARDTSC,
+
AXADDB,
AXADDL,
AXADDW,
@@ -442,6 +446,12 @@ enum as
AFCMOVNU,
AFCMOVUN,
+ ALFENCE,
+ AMFENCE,
+ ASFENCE,
+
+ AEMMS,
+
ALAST
};
diff --git a/src/cmd/8l/Makefile b/src/cmd/8l/Makefile
index 7d34e1704..3f528d751 100644
--- a/src/cmd/8l/Makefile
+++ b/src/cmd/8l/Makefile
@@ -1,49 +1,5 @@
-# Copyright 2009 The Go Authors. All rights reserved.
+# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
-include ../../Make.inc
-O:=$(HOST_O)
-
-TARG=8l
-
-OFILES=\
- asm.$O\
- data.$O\
- dwarf.$O\
- elf.$O\
- enam.$O\
- go.$O\
- ldelf.$O\
- ldmacho.$O\
- ldpe.$O\
- lib.$O\
- list.$O\
- macho.$O\
- obj.$O\
- optab.$O\
- pass.$O\
- pe.$O\
- prof.$O\
- span.$O\
- symtab.$O\
-
-
-HFILES=\
- l.h\
- 8.out.h\
- ../ld/dwarf.h\
- ../ld/elf.h\
- ../ld/macho.h\
- ../ld/pe.h\
-
-include ../../Make.ccmd
-
-enam.c: 8.out.h
- sh mkenam
-
-CLEANFILES+=enam.c
-
-
-%.$O: ../ld/%.c
- $(HOST_CC) $(HOST_CFLAGS) -c -I. ../ld/$*.c
+include ../../Make.dist
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 22abd8049..25ffc786f 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -37,10 +37,10 @@
#include "../ld/macho.h"
#include "../ld/pe.h"
-#define Dbufslop 100
-
char linuxdynld[] = "/lib/ld-linux.so.2";
char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
+char openbsddynld[] = "/usr/libexec/ld.so";
+char netbsddynld[] = "/usr/libexec/ld.elf_so";
int32
entryvalue(void)
@@ -90,6 +90,9 @@ enum {
ElfStrPlt,
ElfStrGnuVersion,
ElfStrGnuVersionR,
+ ElfStrNoteNetbsdIdent,
+ ElfStrNoPtrData,
+ ElfStrNoPtrBss,
NElfStr
};
@@ -107,6 +110,7 @@ needlib(char *name)
/* reuse hash code in symbol table */
p = smprint(".dynlib.%s", name);
s = lookup(p, 0);
+ free(p);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
return 1;
@@ -416,7 +420,7 @@ adddynsym(Sym *s)
return;
if(s->dynimpname == nil)
- diag("adddynsym: no dynamic name for %s", s->name, *(int32*)0);
+ diag("adddynsym: no dynamic name for %s", s->name);
if(iself) {
s->dynid = nelfsym++;
@@ -524,8 +528,12 @@ doelf(void)
elfstr[ElfStrEmpty] = addstring(shstrtab, "");
elfstr[ElfStrText] = addstring(shstrtab, ".text");
+ elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
elfstr[ElfStrData] = addstring(shstrtab, ".data");
elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
+ elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
+ if(HEADTYPE == Hnetbsd)
+ elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
addstring(shstrtab, ".elfdata");
addstring(shstrtab, ".rodata");
addstring(shstrtab, ".gosymtab");
@@ -606,7 +614,7 @@ doelf(void)
/* define dynamic elf table */
s = lookup(".dynamic", 0);
s->reachable = 1;
- s->type = SELFROSECT;
+ s->type = SELFSECT; // writable
/*
* .dynamic table
@@ -626,6 +634,8 @@ doelf(void)
elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
+ elfwritedynent(s, DT_DEBUG, 0);
+
// Do not write DT_NULL. elfdynhash will finish it.
}
}
@@ -657,7 +667,7 @@ asmb(void)
{
int32 v, magic;
int a, dynsym;
- uint32 symo, startva, machlink;
+ uint32 symo, startva, dwarfoff, machlink, resoff;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
@@ -688,8 +698,19 @@ asmb(void)
datblk(segdata.vaddr, segdata.filelen);
machlink = 0;
- if(HEADTYPE == Hdarwin)
+ if(HEADTYPE == Hdarwin) {
+ if(debug['v'])
+ Bprint(&bso, "%5.2f dwarf\n", cputime());
+
+ dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
+ cseek(dwarfoff);
+
+ segdwarf.fileoff = cpos();
+ dwarfemitdebugsections();
+ segdwarf.filelen = cpos() - segdwarf.fileoff;
+
machlink = domacholink();
+ }
if(iself) {
/* index of elf text section; needed by asmelfsym, double-checked below */
@@ -700,6 +721,8 @@ asmb(void)
if(elfverneed)
elftextsh += 2;
}
+ if(HEADTYPE == Hnetbsd)
+ elftextsh += 1;
}
symsize = 0;
@@ -746,7 +769,7 @@ asmb(void)
default:
if(iself) {
if(debug['v'])
- Bprint(&bso, "%5.2f elfsym\n", cputime());
+ Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym();
cflush();
cwrite(elfstrdat, elfstrsize);
@@ -769,7 +792,6 @@ asmb(void)
cflush();
}
break;
- case Hdarwin:
case Hwindows:
if(debug['v'])
Bprint(&bso, "%5.2f dwarf\n", cputime());
@@ -918,6 +940,7 @@ asmb(void)
Elfput:
eh = getElfEhdr();
startva = INITTEXT - HEADR;
+ resoff = ELFRESERVE;
/* This null SHdr must appear before all others */
newElfShdr(elfstr[ElfStrEmpty]);
@@ -956,9 +979,15 @@ asmb(void)
case Hfreebsd:
interpreter = freebsddynld;
break;
+ case Hnetbsd:
+ interpreter = netbsddynld;
+ break;
+ case Hopenbsd:
+ interpreter = openbsddynld;
+ break;
}
}
- elfinterp(sh, startva, interpreter);
+ resoff -= elfinterp(sh, startva, resoff, interpreter);
ph = newElfPhdr();
ph->type = PT_INTERP;
@@ -966,11 +995,27 @@ asmb(void)
phsh(ph, sh);
}
+ if(HEADTYPE == Hnetbsd) {
+ sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
+ sh->type = SHT_NOTE;
+ sh->flags = SHF_ALLOC;
+ sh->addralign = 4;
+ resoff -= elfnetbsdsig(sh, startva, resoff);
+
+ ph = newElfPhdr();
+ ph->type = PT_NOTE;
+ ph->flags = PF_R;
+ phsh(ph, sh);
+ }
+
+ // Additions to the reserved area must be above this line.
+ USED(resoff);
+
elfphload(&segtext);
elfphload(&segdata);
/* Dynamic linking sections */
- if (!debug['d']) { /* -d suppresses dynamic loader format */
+ if(!debug['d']) { /* -d suppresses dynamic loader format */
/* S headers for dynamic linking */
sh = newElfShdr(elfstr[ElfStrGot]);
sh->type = SHT_PROGBITS;
@@ -1094,7 +1139,7 @@ asmb(void)
for(sect=segdata.sect; sect!=nil; sect=sect->next)
elfshbits(sect);
- if (!debug['s']) {
+ if(!debug['s']) {
sh = newElfShdr(elfstr[ElfStrSymtab]);
sh->type = SHT_SYMTAB;
sh->off = symo;
@@ -1122,7 +1167,13 @@ asmb(void)
eh->ident[EI_VERSION] = EV_CURRENT;
switch(HEADTYPE) {
case Hfreebsd:
- eh->ident[EI_OSABI] = 9;
+ eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
+ break;
+ case Hnetbsd:
+ eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
+ break;
+ case Hopenbsd:
+ eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
break;
}
@@ -1141,8 +1192,10 @@ asmb(void)
a += elfwritehdr();
a += elfwritephdrs();
a += elfwriteshdrs();
- cflush();
- if(a+elfwriteinterp() > ELFRESERVE)
+ a += elfwriteinterp(elfstr[ElfStrInterp]);
+ if(HEADTYPE == Hnetbsd)
+ a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
+ if(a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
break;
@@ -1205,12 +1258,16 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
case SSTRING:
case SGOSTRING:
case SWINDOWS:
+ case SNOPTRDATA:
+ case SSYMTAB:
+ case SPCLNTAB:
if(!s->reachable)
continue;
put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
continue;
case SBSS:
+ case SNOPTRBSS:
if(!s->reachable)
continue;
put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
diff --git a/src/cmd/8l/doc.go b/src/cmd/8l/doc.go
index b70888907..12301d4f2 100644
--- a/src/cmd/8l/doc.go
+++ b/src/cmd/8l/doc.go
@@ -4,47 +4,10 @@
/*
-8l is a modified version of the Plan 9 linker. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/2l
-
-Its target architecture is the x86, referred to by these tools for historical reasons as 386.
-It reads files in .8 format generated by 8g, 8c, and 8a and emits
-a binary called 8.out by default.
-
-Major changes include:
- - support for ELF and Mach-O binary files
- - support for segmented stacks (this feature is implemented here, not in the compilers).
-
-
-Original options are listed in the link above.
-
-Options new in this version:
-
--d
- Elide the dynamic linking header. With this option, the binary
- is statically linked and does not refer to dynld. Without this option
- (the default), the binary's contents are identical but it is loaded with dynld.
--Hplan9
- Write Plan 9 32-bit format binaries (default when $GOOS is plan9)
--Hdarwin
- Write Apple Mach-O binaries (default when $GOOS is darwin)
--Hlinux
- Write Linux ELF binaries (default when $GOOS is linux)
--Hfreebsd
- Write FreeBSD ELF binaries (default when $GOOS is freebsd)
--Hwindows
- Write Windows PE32 binaries (default when $GOOS is windows)
--I interpreter
- Set the ELF dynamic linker to use.
--L dir1 -L dir2
- Search for libraries (package files) in dir1, dir2, etc.
- The default is the single location $GOROOT/pkg/$GOOS_386.
--r dir1:dir2:...
- Set the dynamic linker search path when using ELF.
--V
- Print the linker version.
+8l is the linker for the 32-bit x86.
+The $GOARCH for these tools is 386.
+The flags are documented in ../ld/doc.go.
*/
package documentation
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 4ee0db967..b974f464b 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -134,6 +134,7 @@ struct Sym
int32 dynid;
int32 plt;
int32 got;
+ int32 align; // if non-zero, required alignment in bytes
Sym* hash; // in hash table
Sym* allsym; // in all symbol list
Sym* next; // in text or data list
@@ -209,6 +210,7 @@ enum
Zbr,
Zcall,
Zcallcon,
+ Zcallind,
Zib_,
Zib_rp,
Zibo_m,
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index a8e1c34a5..af4bc844f 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -47,17 +47,19 @@ char *noname = "<none>";
char *thestring = "386";
Header headers[] = {
- "garbunix", Hgarbunix,
- "unixcoff", Hunixcoff,
- "plan9", Hplan9x32,
- "msdoscom", Hmsdoscom,
- "msdosexe", Hmsdosexe,
- "darwin", Hdarwin,
- "linux", Hlinux,
- "freebsd", Hfreebsd,
- "windows", Hwindows,
- "windowsgui", Hwindows,
- 0, 0
+ "garbunix", Hgarbunix,
+ "unixcoff", Hunixcoff,
+ "plan9", Hplan9x32,
+ "msdoscom", Hmsdoscom,
+ "msdosexe", Hmsdosexe,
+ "darwin", Hdarwin,
+ "linux", Hlinux,
+ "freebsd", Hfreebsd,
+ "netbsd", Hnetbsd,
+ "openbsd", Hopenbsd,
+ "windows", Hwindows,
+ "windowsgui", Hwindows,
+ 0, 0
};
/*
@@ -69,6 +71,8 @@ Header headers[] = {
* -Hdarwin -Tx -Rx is Apple Mach-O
* -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
*/
@@ -83,6 +87,7 @@ void
main(int argc, char *argv[])
{
int c;
+ char *name, *val;
Binit(&bso, 1, OWRITE);
listinit();
@@ -94,6 +99,7 @@ main(int argc, char *argv[])
INITDAT = -1;
INITRND = -1;
INITENTRY = 0;
+ nuxiinit();
ARGBEGIN {
default:
@@ -133,6 +139,11 @@ main(int argc, char *argv[])
case 'V':
print("%cl version %s\n", thechar, getgoversion());
errorexit();
+ case 'X':
+ name = EARGF(usage());
+ val = EARGF(usage());
+ addstrdata(name, val);
+ break;
} ARGEND
if(argc != 1)
@@ -209,7 +220,7 @@ main(int argc, char *argv[])
case Hdarwin: /* apple MACH */
/*
* OS X system constant - offset from %gs to our TLS.
- * Explained in ../../libcgo/darwin_386.c.
+ * Explained in ../../pkg/runtime/cgo/gcc_darwin_386.c.
*/
tlsoffset = 0x468;
machoinit();
@@ -223,11 +234,13 @@ main(int argc, char *argv[])
break;
case Hlinux: /* elf32 executable */
case Hfreebsd:
+ case Hnetbsd:
+ case Hopenbsd:
/*
* ELF uses TLS offsets negative from %gs.
* Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
- * Also known to ../../pkg/runtime/linux/386/sys.s
- * and ../../libcgo/linux_386.c.
+ * Also known to ../../pkg/runtime/sys_linux_386.s
+ * and ../../pkg/runtime/cgo/gcc_linux_386.c.
*/
tlsoffset = -8;
elfinit();
@@ -269,7 +282,6 @@ main(int argc, char *argv[])
zprg.to = zprg.from;
pcstr = "%.6ux ";
- nuxiinit();
histgen = 0;
pc = 0;
dtype = 4;
@@ -477,7 +489,7 @@ loop:
sig = 1729;
if(sig != 0){
if(s->sig != 0 && s->sig != sig)
- diag("incompatible type signatures"
+ diag("incompatible type signatures "
"%ux(%s) and %ux(%s) for %s",
s->sig, s->file, sig, pn, s->name);
s->sig = sig;
@@ -551,7 +563,7 @@ loop:
s->type = SBSS;
s->size = 0;
}
- if(s->type != SBSS && !s->dupok) {
+ if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) {
diag("%s: redefinition: %s in %s",
pn, s->name, TNAME);
s->type = SBSS;
@@ -563,6 +575,8 @@ loop:
s->dupok = 1;
if(p->from.scale & RODATA)
s->type = SRODATA;
+ else if(p->from.scale & NOPTR)
+ s->type = SNOPTRBSS;
goto loop;
case ADATA:
@@ -594,6 +608,10 @@ 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;
}
diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c
index f5c195d75..856482290 100644
--- a/src/cmd/8l/optab.c
+++ b/src/cmd/8l/optab.c
@@ -260,6 +260,7 @@ uchar yloop[] =
uchar ycall[] =
{
Ynone, Yml, Zo_m, 2,
+ Ynone, Ycol, Zcallind, 2,
Ynone, Ybr, Zcall, 0,
Ynone, Yi32, Zcallcon, 1,
0
@@ -383,7 +384,7 @@ Optab optab[] =
{ ABTSL, yml_rl, Pm, 0xab },
{ ABTSW, yml_rl, Pq, 0xab },
{ ABYTE, ybyte, Px, 1 },
- { ACALL, ycall, Px, 0xff,(02),0xe8 },
+ { ACALL, ycall, Px, 0xff,(02),0xff,(0x15),0xe8 },
{ ACLC, ynone, Px, 0xf8 },
{ ACLD, ynone, Px, 0xfc },
{ ACLI, ynone, Px, 0xfa },
@@ -430,7 +431,8 @@ Optab optab[] =
{ AIRETW, ynone, Pe, 0xcf },
{ AJCC, yjcond, Px, 0x73,0x83,(00) },
{ AJCS, yjcond, Px, 0x72,0x82 },
- { AJCXZ, yloop, Px, 0xe3 },
+ { AJCXZL, yloop, Px, 0xe3 },
+ { AJCXZW, yloop, Px, 0xe3 },
{ AJEQ, yjcond, Px, 0x74,0x84 },
{ AJGE, yjcond, Px, 0x7d,0x8d },
{ AJGT, yjcond, Px, 0x7f,0x8f },
@@ -705,6 +707,8 @@ Optab optab[] =
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
{ ACMPXCHG8B, yscond, Pm, 0xc7,(01) },
+ { ARDTSC, ynone, Pm, 0x31 },
+
{ AXADDB, yrb_mb, Pb, 0x0f,0xc0 },
{ AXADDL, yrl_ml, Pm, 0xc1 },
{ AXADDW, yrl_ml, Pe, 0x0f,0xc1 },
@@ -751,5 +755,11 @@ Optab optab[] =
{ 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 },
+
0
};
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 2e0990c5a..9034fdf3a 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -259,7 +259,7 @@ patch(void)
// Convert
// op n(GS), reg
// to
- // MOVL 0x2C(FS), reg
+ // 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
@@ -273,7 +273,7 @@ patch(void)
q->as = p->as;
p->as = AMOVL;
p->from.type = D_INDIR+D_FS;
- p->from.offset = 0x2C;
+ p->from.offset = 0x14;
}
}
if(HEADTYPE == Hlinux) {
@@ -307,9 +307,12 @@ patch(void)
p->from.offset = 0;
}
}
- if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) {
+ if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH)) {
s = p->to.sym;
- if(s) {
+ 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&~SSUB) != STEXT) {
@@ -421,7 +424,7 @@ dostkoff(void)
case Hwindows:
p->as = AMOVL;
p->from.type = D_INDIR+D_FS;
- p->from.offset = 0x2c;
+ p->from.offset = 0x14;
p->to.type = D_CX;
p = appendp(p);
@@ -524,10 +527,18 @@ dostkoff(void)
p = appendp(p); // save frame size in DX
p->as = AMOVL;
p->to.type = D_DX;
- /* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 guard */
p->from.type = D_CONST;
- if(autoffset+160+cursym->text->to.offset2 > 4096)
- p->from.offset = (autoffset+160) & ~7LL;
+
+ // 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 + autoffset + PtrSize + StackLimit >= StackMin)
+ p->from.offset = (autoffset+7) & ~7LL;
p = appendp(p); // save arg size in AX
p->as = AMOVL;
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index a4cba1257..81c1d37eb 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -83,7 +83,10 @@ span1(Sym *s)
loop++;
q->back ^= 2;
}
- s->p[q->pc+1] = v;
+ 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;
@@ -282,6 +285,8 @@ oclass(Adr *a)
}
return Yxxx;
}
+ //if(a->type == D_INDIR+D_ADDR)
+ // print("*Ycol\n");
return Ycol;
}
return Ym;
@@ -1056,9 +1061,10 @@ found:
case Zbr:
case Zjmp:
+ case Zloop:
q = p->pcond;
if(q == nil) {
- diag("jmp/branch without target");
+ diag("jmp/branch/loop without target");
errorexit();
}
if(q->as == ATEXT) {
@@ -1084,8 +1090,12 @@ found:
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) {
@@ -1105,8 +1115,12 @@ found:
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;
@@ -1131,18 +1145,17 @@ found:
r->add = p->to.offset;
put4(0);
break;
-
- case Zloop:
- q = p->pcond;
- if(q == nil) {
- diag("loop without target");
- errorexit();
- }
- v = q->pc - p->pc - 2;
- if(v < -128 && v > 127)
- diag("loop too far: %P", p);
+
+ case Zcallind:
*andptr++ = op;
- *andptr++ = v;
+ *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: