From 2bd101c4b14faa550ddc91821b154f793700773c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 20 Mar 2009 16:40:00 -0700 Subject: [PATCH] update 8a, 8c, 8l to use new object format. add "extern register" support to 8c. extern register means allocate in the FS-relative segment. make 8l generate segmented stack checks. R=ken OCL=26600 CL=26606 --- src/cmd/8a/a.h | 2 +- src/cmd/8a/a.y | 66 +++++++++- src/cmd/8a/lex.c | 22 +++- src/cmd/8c/gc.h | 1 + src/cmd/8c/list.c | 4 + src/cmd/8c/sgen.c | 32 +++++ src/cmd/8c/swt.c | 15 ++- src/cmd/8c/txt.c | 13 ++ src/cmd/8l/8.out.h | 6 + src/cmd/8l/l.h | 5 +- src/cmd/8l/list.c | 18 ++- src/cmd/8l/obj.c | 308 +++++++++++++++++++++++++++------------------ src/cmd/8l/optab.c | 8 ++ src/cmd/8l/pass.c | 138 +++++++++++++++++++- src/cmd/8l/span.c | 44 ++++++- src/cmd/cc/cc.h | 1 + src/cmd/cc/com.c | 5 + src/cmd/cc/sub.c | 1 + 18 files changed, 544 insertions(+), 145 deletions(-) diff --git a/src/cmd/8a/a.h b/src/cmd/8a/a.h index 8b5f7d9efa9..dbe43992953 100644 --- a/src/cmd/8a/a.h +++ b/src/cmd/8a/a.h @@ -32,7 +32,6 @@ #include #include #include "../8l/8.out.h" -#include "compat.h" #ifndef EXTERN @@ -104,6 +103,7 @@ struct Gen double dval; char sval[8]; int32 offset; + int32 offset2; Sym* sym; short type; short index; diff --git a/src/cmd/8a/a.y b/src/cmd/8a/a.y index 505defd2878..fced3efa47b 100644 --- a/src/cmd/8a/a.y +++ b/src/cmd/8a/a.y @@ -34,6 +34,10 @@ %union { Sym *sym; int32 lval; + struct { + int32 v1; + int32 v2; + } con2; double dval; char sval[8]; Gen gen; @@ -46,16 +50,17 @@ %left '+' '-' %left '*' '/' '%' %token LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 -%token LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI +%token LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG %token LCONST LFP LPC LSB %token LBREG LLREG LSREG LFREG %token LFCONST %token LSCONST LSP %token LNAME LLAB LVAR %type con expr pointer offset -%type mem imm reg nam rel rem rim rom omem nmem +%type con2 +%type mem imm imm2 reg nam rel rem rim rom omem nmem %type nonnon nonrel nonrem rimnon rimrem remrim -%type spec1 spec2 spec3 spec4 spec5 spec6 spec7 +%type spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 %% prog: | prog line @@ -103,6 +108,7 @@ inst: | LTYPES spec5 { outcode($1, &$2); } | LTYPEM spec6 { outcode($1, &$2); } | LTYPEI spec7 { outcode($1, &$2); } +| LTYPEG spec8 { outcode($1, &$2); } nonnon: { @@ -174,12 +180,12 @@ spec1: /* DATA */ } spec2: /* TEXT */ - mem ',' imm + mem ',' imm2 { $$.from = $1; $$.to = $3; } -| mem ',' con ',' imm +| mem ',' con ',' imm2 { $$.from = $1; $$.from.scale = $3; @@ -249,6 +255,19 @@ spec7: $$.to = $3; } +spec8: /* GLOBL */ + mem ',' imm + { + $$.from = $1; + $$.to = $3; + } +| mem ',' con ',' imm + { + $$.from = $1; + $$.from.scale = $3; + $$.to = $5; + } + rem: reg | mem @@ -365,6 +384,37 @@ imm: $$.dval = -$3; } +imm2: + '$' con2 + { + $$ = nullgen; + $$.type = D_CONST2; + $$.offset = $2.v1; + $$.offset2 = $2.v2; + } + +con2: + LCONST + { + $$.v1 = $1; + $$.v2 = 0; + } +| '-' LCONST + { + $$.v1 = -$2; + $$.v2 = 0; + } +| LCONST '-' LCONST + { + $$.v1 = $1; + $$.v2 = $3; + } +| '-' LCONST '-' LCONST + { + $$.v1 = -$2; + $$.v2 = $4; + } + mem: omem | nmem @@ -416,6 +466,12 @@ omem: $$ = nullgen; $$.type = D_INDIR+D_SP; } +| con '(' LSREG ')' + { + $$ = nullgen; + $$.type = D_INDIR+$3; + $$.offset = $1; + } | '(' LLREG '*' con ')' { $$ = nullgen; diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c index 8576f01b730..fcc4cf964a8 100644 --- a/src/cmd/8a/lex.c +++ b/src/cmd/8a/lex.c @@ -165,6 +165,9 @@ assemble(char *file) pass = 1; pinit(file); + + Bprint(&obuf, "%s\n", thestring); + for(i=0; i>16); Bputc(&obuf, l>>24); } + if(t & T_OFFSET2) { + l = a->offset2; + Bputc(&obuf, l); + Bputc(&obuf, l>>8); + Bputc(&obuf, l>>16); + Bputc(&obuf, l>>24); + } if(t & T_SYM) /* implies sym */ Bputc(&obuf, s); if(t & T_FCONST) { diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h index c30eb55bc16..55a37c42cdf 100644 --- a/src/cmd/8c/gc.h +++ b/src/cmd/8c/gc.h @@ -66,6 +66,7 @@ EXTERN struct struct Adr { int32 offset; + int32 offset2; double dval; char sval[NSNAME]; diff --git a/src/cmd/8c/list.c b/src/cmd/8c/list.c index d700b63af52..ec5ac9d60f8 100644 --- a/src/cmd/8c/list.c +++ b/src/cmd/8c/list.c @@ -154,6 +154,10 @@ Dconv(Fmt *fp) sprint(str, "$%ld", a->offset); break; + case D_CONST2: + sprint(str, "$%ld-%ld", a->offset, a->offset2); + break; + case D_FCONST: sprint(str, "$(%.17e)", a->dval); break; diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c index 14bd32adb32..c4d5665d835 100644 --- a/src/cmd/8c/sgen.c +++ b/src/cmd/8c/sgen.c @@ -30,6 +30,31 @@ #include "gc.h" +int32 +argsize(void) +{ + Type *t; + int32 s; + +//print("t=%T\n", thisfn); + s = 0; + for(t=thisfn->down; t!=T; t=t->down) { + switch(t->etype) { + case TVOID: + break; + case TDOT: + s += 64; + break; + default: + s = align(s, t, Aarg1); + s = align(s, t, Aarg2); + break; + } +//print(" %d %T\n", s, t); + } + return (s+7) & ~7; +} + void codgen(Node *n, Node *nn) { @@ -52,7 +77,10 @@ codgen(Node *n, Node *nn) break; } nearln = nn->lineno; + gpseudo(ATEXT, n1->sym, nodconst(stkoff)); + p->to.type = D_CONST2; + p->to.offset2 = argsize(); /* * isolate first argument @@ -494,6 +522,10 @@ xcom(Node *n) n->addable = 11; break; + case OEXREG: + n->addable = 10; + break; + case OREGISTER: n->addable = 12; break; diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index 13e9a51e316..6d693337ae8 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -328,7 +328,10 @@ outcode(void) return; } Binit(&b, f, OWRITE); - Bseek(&b, 0L, 2); + + Bprint(&b, "%s\n", thestring); + Bprint(&b, "!\n"); + outhist(&b); for(sym=0; sym>16); Bputc(b, l>>24); } + if(t & T_OFFSET2) { /* implies offset2 */ + l = a->offset2; + Bputc(b, l); + Bputc(b, l>>8); + Bputc(b, l>>16); + Bputc(b, l>>24); + } if(t & T_SYM) /* implies sym */ Bputc(b, s); if(t & T_FCONST) { diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c index 4e95f3c7a87..5cc43e0e94c 100644 --- a/src/cmd/8c/txt.c +++ b/src/cmd/8c/txt.c @@ -449,6 +449,10 @@ naddr(Node *n, Adr *a) a->sym = S; break; + case OEXREG: + a->type = D_INDIR + D_FS; + a->offset = n->reg - 1; + break; case OIND: naddr(n->left, a); @@ -1389,6 +1393,15 @@ sconst(Node *n) int32 exreg(Type *t) { + int32 o; + + if(typechlp[t->etype]){ + if(exregoffset >= 32) + return 0; + o = exregoffset; + exregoffset += 4; + return o+1; // +1 to avoid 0 == failure; naddr case OEXREG will -1. + } USED(t); return 0; diff --git a/src/cmd/8l/8.out.h b/src/cmd/8l/8.out.h index 647c1dd5965..f7750129d8e 100644 --- a/src/cmd/8l/8.out.h +++ b/src/cmd/8l/8.out.h @@ -32,6 +32,7 @@ #define NSNAME 8 #define NOPROF (1<<0) #define DUPOK (1<<1) +#define NOSPLIT (1<<2) enum as { @@ -78,6 +79,9 @@ enum as ACMPSB, ACMPSL, ACMPSW, + ACMPXCHGB, + ACMPXCHGL, + ACMPXCHGW, ADAA, ADAS, ADATA, @@ -437,6 +441,7 @@ enum D_FCONST = 66, D_SCONST = 67, D_ADDR = 68, + D_CONST2 = 69, D_FILE, D_FILE1, @@ -449,6 +454,7 @@ enum T_FCONST = 1<<3, T_SYM = 1<<4, T_SCONST = 1<<5, + T_OFFSET2 = 1<<6, REGARG = 0, REGRET = D_AX, diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index fabf8903417..114c6636904 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -67,6 +67,7 @@ struct Adr short type; uchar index; char scale; + int32 offset2; }; #define offset u0.u0offset @@ -342,7 +343,7 @@ void histtoauto(void); double ieeedtod(Ieee*); int32 ieeedtof(Ieee*); void import(void); -void ldobj(int, int32, char*); +void ldobj(Biobuf*, int32, char*); void loadlib(void); void listinit(void); Sym* lookup(char*, int); @@ -368,7 +369,7 @@ int32 vaddr(Adr*); void wput(ushort); void xdefine(char*, int, int32); void xfol(Prog*); -int zaddr(uchar*, Adr*, Sym*[]); +void zaddr(Biobuf*, Adr*, Sym*[]); void zerosig(char*); uint32 machheadr(void); uint32 elfheadr(void); diff --git a/src/cmd/8l/list.c b/src/cmd/8l/list.c index ebd8b864b90..873f7c1f857 100644 --- a/src/cmd/8l/list.c +++ b/src/cmd/8l/list.c @@ -82,6 +82,14 @@ Aconv(Fmt *fp) return fmtstrcpy(fp, anames[i]); } +char* +xsymname(Sym *s) +{ + if(s == nil) + return "!!noname!!"; + return s->name; +} + int Dconv(Fmt *fp) { @@ -120,16 +128,16 @@ Dconv(Fmt *fp) break; case D_EXTERN: - sprint(str, "%s+%ld(SB)", a->sym->name, a->offset); + sprint(str, "%s+%ld(SB)", xsymname(a->sym), a->offset); break; case D_STATIC: - sprint(str, "%s<%d>+%ld(SB)", a->sym->name, + sprint(str, "%s<%d>+%ld(SB)", xsymname(a->sym), a->sym->version, a->offset); break; case D_AUTO: - sprint(str, "%s+%ld(SP)", a->sym->name, a->offset); + sprint(str, "%s+%ld(SP)", xsymname(a->sym), a->offset); break; case D_PARAM: @@ -143,6 +151,10 @@ Dconv(Fmt *fp) sprint(str, "$%ld", a->offset); break; + case D_CONST2: + sprint(str, "$%ld-%ld", a->offset, a->offset2); + break; + case D_FCONST: sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l); break; diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index a1d14318dda..022f315d297 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -419,14 +419,15 @@ void objfile(char *file) { int32 off, esym, cnt, l; - int f, work; + int work; + Biobuf *f; Sym *s; char magbuf[SARMAG]; char name[100], pname[150]; struct ar_hdr arhdr; char *e, *start, *stop; - if(file[0] == '-' && file[1] == 'l') { + if(file[0] == '-' && file[1] == 'l') { // TODO: fix this if(debug['9']) sprint(name, "/%s/lib/lib", thestring); else @@ -438,22 +439,22 @@ objfile(char *file) if(debug['v']) Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); Bflush(&bso); - f = open(file, 0); - if(f < 0) { + f = Bopen(file, 0); + if(f == nil) { diag("cannot open file: %s", file); errorexit(); } - l = read(f, magbuf, SARMAG); + l = Bread(f, magbuf, SARMAG); if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ /* load it as a regular file */ - l = seek(f, 0L, 2); - seek(f, 0L, 0); + l = Bseek(f, 0L, 2); + Bseek(f, 0L, 0); ldobj(f, l, file); - close(f); + Bterm(f); return; } - l = read(f, &arhdr, SAR_HDR); + l = Bread(f, &arhdr, SAR_HDR); if(l != SAR_HDR) { diag("%s: short read on archive file symbol header", file); goto out; @@ -469,12 +470,12 @@ objfile(char *file) /* * just bang the whole symbol file into memory */ - seek(f, off, 0); + Bseek(f, off, 0); cnt = esym - off; start = malloc(cnt + 10); - cnt = read(f, start, cnt); + cnt = Bread(f, start, cnt); if(cnt <= 0){ - close(f); + Bterm(f); return; } stop = &start[cnt]; @@ -498,12 +499,16 @@ objfile(char *file) l |= (e[2] & 0xff) << 8; l |= (e[3] & 0xff) << 16; l |= (e[4] & 0xff) << 24; - seek(f, l, 0); - l = read(f, &arhdr, SAR_HDR); + Bseek(f, l, 0); + l = Bread(f, &arhdr, SAR_HDR); if(l != SAR_HDR) goto bad; if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) goto bad; + l = SARNAME; + while(l > 0 && arhdr.name[l-1] == ' ') + l--; + sprint(pname, "%s(%.*s)", file, l, arhdr.name); l = atolwhex(arhdr.size); ldobj(f, l, pname); if(s->type == SXREF) { @@ -519,85 +524,87 @@ objfile(char *file) bad: diag("%s: bad or out of date archive", file); out: - close(f); + Bterm(f); } -int -zaddr(uchar *p, Adr *a, Sym *h[]) +int32 +Bget4(Biobuf *f) { - int c, t, i; + uchar p[4]; + + if(Bread(f, p, 4) != 4) + return 0; + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +void +zaddr(Biobuf *f, Adr *a, Sym *h[]) +{ + int t; int32 l; Sym *s; Auto *u; - t = p[0]; - - c = 1; + t = Bgetc(f); if(t & T_INDEX) { - a->index = p[c]; - a->scale = p[c+1]; - c += 2; + a->index = Bgetc(f); + a->scale = Bgetc(f); } else { a->index = D_NONE; a->scale = 0; } + a->type = D_NONE; a->offset = 0; - if(t & T_OFFSET) { - a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); - c += 4; + if(t & T_OFFSET) + a->offset = Bget4(f); + a->offset2 = 0; + if(t & T_OFFSET2) { + a->offset2 = Bget4(f); + a->type = D_CONST2; } a->sym = S; - if(t & T_SYM) { - a->sym = h[p[c]]; - c++; - } - a->type = D_NONE; + if(t & T_SYM) + a->sym = h[Bgetc(f)]; if(t & T_FCONST) { - a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); - a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); - c += 8; + a->ieee.l = Bget4(f); + a->ieee.h = Bget4(f); a->type = D_FCONST; } else if(t & T_SCONST) { - for(i=0; iscon[i] = p[c+i]; - c += NSNAME; + Bread(f, a->scon, NSNAME); a->type = D_SCONST; } - if(t & T_TYPE) { - a->type = p[c]; - c++; - } + if(t & T_TYPE) + a->type = Bgetc(f); s = a->sym; if(s == S) - return c; + return; t = a->type; if(t != D_AUTO && t != D_PARAM) - return c; + 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; - return c; + return; } } - u = mal(sizeof(Auto)); + u = mal(sizeof(*u)); u->link = curauto; curauto = u; u->asym = s; u->aoffset = l; u->type = t; - return c; } void -addlib(char *obj) +addlib(char *src, char *obj) { - char name[1024], comp[256], *p; + char name[1024], comp[256], *p, *q; int i; if(histfrogp <= 0) @@ -645,6 +652,23 @@ addlib(char *obj) strcat(name, "/"); strcat(name, comp); } + if(debug['v']) + Bprint(&bso, "%5.2f addlib: %s %s pulls in %s\n", cputime(), obj, src, name); + + p = strrchr(src, '/'); + q = strrchr(name, '/'); + if(p != nil && q != nil && p - src == q - name && memcmp(src, name, p - src) == 0) { + // leading paths are the same. + // if the source file refers to an object in its own directory + // and we are inside an archive, ignore the reference, in the hope + // that the archive contains that object too. + if(strchr(obj, '(')) { + if(debug['v']) + Bprint(&bso, "%5.2f ignored srcdir object %s\n", cputime(), name); + return; + } + } + for(i=0; iname+1); + if(i+1link = curhist; curhist = u; + s->name[0] = 0; j = 1; for(i=0; ivalue; @@ -686,6 +727,8 @@ addhist(int32 line, int type) s->name[j+1] = k; j += 2; } + s->name[j] = 0; + s->name[j+1] = 0; } void @@ -746,35 +789,27 @@ nopout(Prog *p) p->to.type = D_NONE; } -uchar* -readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) -{ - int n; - - n = stop - good; - memmove(buf, good, stop - good); - stop = buf + n; - n = MAXIO - n; - if(n > max) - n = max; - n = read(f, stop, n); - if(n <= 0) - return 0; - return stop + n; -} - void -ldobj(int f, int32 c, char *pn) +ldobj(Biobuf *f, int32 len, char *pn) { int32 ipc; Prog *p, *t; - uchar *bloc, *bsize, *stop; int v, o, r, skip; Sym *h[NSYM], *s, *di; uint32 sig; static int files; static char **filen; char **nfilen; + int ntext, n, c1, c2, c3; + int32 eof; + int32 import0, import1; + char *line, *name; + char src[1024]; + + src[0] = '\0'; + eof = Boffset(f) + len; + + ntext = 0; if((files&15) == 0){ nfilen = malloc((files+16)*sizeof(char*)); @@ -782,12 +817,48 @@ ldobj(int f, int32 c, char *pn) free(filen); filen = nfilen; } - filen[files++] = strdup(pn); + pn = strdup(pn); + filen[files++] = pn; - bsize = buf.xbuf; - bloc = buf.xbuf; di = S; + /* check the header */ + line = Brdline(f, '\n'); + if(line == nil) { + if(Blinelen(f) > 0) { + diag("%s: malformed object file", pn); + return; + } + goto eof; + } + n = Blinelen(f) - 1; + if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) { + if(line) + line[n] = '\0'; + diag("file not %s [%s]\n", thestring, line); + return; + } + + /* skip over exports and other info -- ends with \n!\n */ + import0 = Boffset(f); + c1 = '\n'; // the last line ended in \n + c2 = Bgetc(f); + c3 = Bgetc(f); + while(c1 != '\n' || c2 != '!' || c3 != '\n') { + c1 = c2; + c2 = c3; + c3 = Bgetc(f); + if(c3 == Beof) + goto eof; + } + import1 = Boffset(f); + + Bseek(f, import0, 0); +// ldpkg(f, import1 - import0 - 2, pn); // -2 for !\n + Bseek(f, import1, 0); + +print("import %ld-%ld\n", import0, import1); + newloop: memset(h, 0, sizeof(h)); version++; @@ -796,61 +867,46 @@ newloop: skip = 0; loop: - if(c <= 0) + if(f->state == Bracteof || Boffset(f) >= eof) goto eof; - r = bsize - bloc; - if(r < 100 && r < c) { /* enough for largest prog */ - bsize = readsome(f, buf.xbuf, bloc, bsize, c); - if(bsize == 0) - goto eof; - bloc = buf.xbuf; - goto loop; - } - o = bloc[0] | (bloc[1] << 8); + o = Bgetc(f); + if(o == Beof) + goto eof; + o |= Bgetc(f) << 8; if(o <= AXXX || o >= ALAST) { if(o < 0) goto eof; - diag("%s: opcode out of range %d", pn, o); - print(" probably not a .8 file\n"); + 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 = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); - bloc += 4; - c -= 4; - } - stop = memchr(&bloc[4], 0, bsize-&bloc[4]); - if(stop == 0){ - bsize = readsome(f, buf.xbuf, bloc, bsize, c); - if(bsize == 0) - goto eof; - bloc = buf.xbuf; - stop = memchr(&bloc[4], 0, bsize-&bloc[4]); - if(stop == 0){ - fprint(2, "%s: name too long\n", pn); - errorexit(); - } - } - v = bloc[2]; /* type */ - o = bloc[3]; /* sym */ - bloc += 4; - c -= 4; - + if(o == ASIGNAME) + sig = Bget4(f); + v = Bgetc(f); /* type */ + o = Bgetc(f); /* sym */ r = 0; if(v == D_STATIC) r = version; - s = lookup((char*)bloc, r); - c -= &stop[1] - bloc; - bloc = stop + 1; + name = Brdline(f, '\0'); + if(name == nil) { + if(Blinelen(f) > 0) { + fprint(2, "%s: name too long\n", pn); + errorexit(); + } + goto eof; + } + s = lookup(name, r); if(debug['S'] && r == 0) sig = 1729; if(sig != 0){ if(s->sig != 0 && s->sig != sig) - diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name); + diag("incompatible type signatures" + "%lux(%s) and %lux(%s) for %s", + s->sig, filen[s->file], sig, pn, s->name); s->sig = sig; s->file = files-1; } @@ -877,12 +933,10 @@ loop: p = mal(sizeof(*p)); p->as = o; - p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24); + p->line = Bget4(f); p->back = 2; - r = zaddr(bloc+6, &p->from, h) + 6; - r += zaddr(bloc+r, &p->to, h); - bloc += r; - c -= r; + zaddr(f, &p->from, h); + zaddr(f, &p->to, h); if(debug['W']) print("%P\n", p); @@ -890,10 +944,12 @@ loop: switch(p->as) { case AHISTORY: if(p->to.offset == -1) { - addlib(pn); + 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' */ @@ -906,9 +962,9 @@ loop: curtext->to.autom = curauto; curauto = 0; curtext = P; - if(c) - goto newloop; - return; + if(Boffset(f) == eof) + return; + goto newloop; case AGLOBL: s = p->from.sym; @@ -983,6 +1039,17 @@ loop: goto loop; case ATEXT: + s = p->from.sym; + if(s == S) { + diag("%s: no TEXT symbol: %P", pn, p); + errorexit(); + } + 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(curtext != P) { histtoauto(); curtext->to.autom = curauto; @@ -990,11 +1057,6 @@ loop: } skip = 0; curtext = p; - s = p->from.sym; - if(s == S) { - diag("%s: no TEXT symbol: %P", pn, p); - errorexit(); - } if(s->type != 0 && s->type != SXREF) { if(p->from.scale & DUPOK) { skip = 1; diff --git a/src/cmd/8l/optab.c b/src/cmd/8l/optab.c index d88e861c569..934f14e9bca 100644 --- a/src/cmd/8l/optab.c +++ b/src/cmd/8l/optab.c @@ -173,6 +173,11 @@ 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, @@ -383,6 +388,9 @@ Optab optab[] = { ACMPSB, ynone, Pb, 0xa6 }, { ACMPSL, ynone, Px, 0xa7 }, { ACMPSW, ynone, Pe, 0xa7 }, + { ACMPXCHGB, yrb_mb, Pm, 0xb0 }, + { ACMPXCHGL, yrl_ml, Pm, 0xb1 }, + { ACMPXCHGW, yrl_ml, Pm, 0xb1 }, { ADAA, ynone, Px, 0x27 }, { ADAS, ynone, Px, 0x2f }, { ADATA }, diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index aa69c58498d..0726d1ea8fc 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -165,7 +165,7 @@ loop: if(p->as == ATEXT) curtext = p; if(p->as == AJMP) - if((q = p->pcond) != P) { + if((q = p->pcond) != P && q->as != ATEXT) { p->mark = 1; p = q; if(p->mark == 0) @@ -331,14 +331,15 @@ patch(void) for(p = firstp; p != P; p = p->link) { if(p->as == ATEXT) curtext = p; - if(p->as == ACALL || p->as == ARET) { + if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) { s = p->to.sym; if(s) { if(debug['c']) Bprint(&bso, "%s calls %s\n", TNAME, s->name); switch(s->type) { default: - diag("undefined: %s in %s", s->name, TNAME); + /* diag prints TNAME first */ + diag("%s is undefined", s->name); s->type = STEXT; s->value = vexit; break; /* or fall through to set offset? */ @@ -440,9 +441,27 @@ brloop(Prog *p) void dostkoff(void) { - Prog *p, *q; + Prog *p, *q, *q1; int32 autoffset, deltasp; int a, f, curframe, curbecome, maxbecome; + Prog *pmorestack; + Sym *symmorestack; + + pmorestack = P; + symmorestack = lookup("sys·morestack", 0); + + if(symmorestack->type == STEXT) + for(p = firstp; p != P; p = p->link) { + if(p->as == ATEXT) { + if(p->from.sym == symmorestack) { + pmorestack = p; + p->from.scale |= NOSPLIT; + break; + } + } + } + if(pmorestack == P) + diag("sys·morestack not defined"); curframe = 0; curbecome = 0; @@ -521,11 +540,122 @@ dostkoff(void) autoffset = p->to.offset; if(autoffset < 0) autoffset = 0; + + q = P; + q1 = P; + if(pmorestack != P) + if(!(p->from.scale & NOSPLIT)) { + p = appendp(p); // load g into CX + p->as = AMOVL; + p->from.type = D_INDIR+D_FS; + p->from.offset = 0; + p->to.type = D_CX; + + 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 = AJHI; + p->to.type = D_BRANCH; + p->to.offset = 4; + q1 = p; + + p = appendp(p); + p->as = AINT; + p->from.type = D_CONST; + p->from.offset = 3; + } + + if(autoffset < 4096) { // do we need to call morestack + if(autoffset <= 75) { + // small stack + p = appendp(p); + p->as = ACMPL; + p->from.type = D_SP; + p->to.type = D_INDIR+D_CX; + if(q1) { + q1->pcond = p; + q1 = P; + } + } else { + // large stack + p = appendp(p); + p->as = ALEAL; + p->from.type = D_INDIR+D_SP; + p->from.offset = -(autoffset-75); + p->to.type = D_AX; + if(q1) { + q1->pcond = p; + q1 = P; + } + + p = appendp(p); + p->as = ACMPL; + p->from.type = D_AX; + p->to.type = D_INDIR+D_CX; + } + + // common + p = appendp(p); + p->as = AJHI; + p->to.type = D_BRANCH; + p->to.offset = 4; + q = p; + } + + p = appendp(p); // load m into DX + p->as = AMOVL; + p->from.type = D_INDIR+D_FS; + p->from.offset = 4; + p->to.type = D_DX; + if(q1) { + q1->pcond = p; + q1 = P; + } + + p = appendp(p); // save autoffset in 4(DX) + p->as = AMOVL; + p->to.type = D_INDIR+D_DX; + p->to.offset = 4; + /* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 guard */ + p->from.type = D_CONST; + if(autoffset+160 > 4096) + p->from.offset = (autoffset+160) & ~7LL; + + p = appendp(p); // save textarg in 8(DX) + p->as = AMOVL; + p->to.type = D_INDIR+D_DX; + p->to.offset = 8; + p->from.type = D_CONST; + p->from.offset = curtext->to.offset2; + + p = appendp(p); + p->as = ACALL; + p->to.type = D_BRANCH; + p->pcond = pmorestack; + p->to.sym = symmorestack; + + } + + if(q != P) + q->pcond = p->link; + if(autoffset) { p = appendp(p); p->as = AADJSP; p->from.type = D_CONST; p->from.offset = autoffset; + if(q != P) + q->pcond = p; } deltasp = autoffset; } diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c index b524c735f7a..81703d3046a 100644 --- a/src/cmd/8l/span.c +++ b/src/cmd/8l/span.c @@ -148,7 +148,10 @@ xdefine(char *p, int t, int32 v) void putsymb(char *s, int t, int32 v, int ver) { - int i, f; + int i, j, f; + char *go; + + go = nil; // TODO if(t == 'f') s++; @@ -172,7 +175,14 @@ putsymb(char *s, int t, int32 v, int ver) cput(s[i]); cput(0); } - symsize += 4 + 1 + i + 1; + j = 0; + if(go) { + for(j=0; go[j]; j++) + cput(go[j]); + } + cput(0); + + symsize += 4 + 1 + i + 1 + j + 1; if(debug['n']) { if(t == 'z' || t == 'Z') { @@ -333,6 +343,24 @@ asmlc(void) Bflush(&bso); } +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) { @@ -447,6 +475,7 @@ oclass(Adr *a) return Ym; case D_CONST: + case D_CONST2: case D_ADDR: if(a->sym == S) { v = a->offset; @@ -636,7 +665,7 @@ asmand(Adr *a, int r) } if(t >= D_INDIR) { t -= D_INDIR; - if(t == D_NONE) { + if(t == D_NONE || (D_CS <= t && t <= D_GS)) { *andptr++ = (0 << 6) | (5 << 0) | (r << 3); put4(v); return; @@ -851,7 +880,14 @@ doasm(Prog *p) Prog *q, pp; uchar *t; int z, op, ft, tt; - int32 v; + int32 v, pre; + + pre = prefixof(&p->from); + if(pre) + *andptr++ = pre; + pre = prefixof(&p->to); + if(pre) + *andptr++ = pre; o = &optab[p->as]; ft = oclass(&p->from) * Ymax; diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h index 3b13126df4f..42341a70c9c 100644 --- a/src/cmd/cc/cc.h +++ b/src/cmd/cc/cc.h @@ -262,6 +262,7 @@ enum ODWHILE, OENUM, OEQ, + OEXREG, OFOR, OFUNC, OGE, diff --git a/src/cmd/cc/com.c b/src/cmd/cc/com.c index 5ee38e88237..af2509c5fd0 100644 --- a/src/cmd/cc/com.c +++ b/src/cmd/cc/com.c @@ -638,6 +638,11 @@ tcomo(Node *n, int f) n->addable = 1; if(n->class == CEXREG) { n->op = OREGISTER; + // on 386, "extern register" generates + // memory references relative to the + // fs segment. + if(thechar == '8') // [sic] + n->op = OEXREG; n->reg = n->sym->offset; n->xoffset = 0; break; diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c index cad5eda729f..335d30bfb0b 100644 --- a/src/cmd/cc/sub.c +++ b/src/cmd/cc/sub.c @@ -1460,6 +1460,7 @@ Init onamesinit[] = ODWHILE, 0, "DWHILE", OENUM, 0, "ENUM", OEQ, 0, "EQ", + OEXREG, 0, "EXREG", OFOR, 0, "FOR", OFUNC, 0, "FUNC", OGE, 0, "GE",