summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-03-20 16:40:00 -0700
committerRuss Cox <rsc@golang.org>2009-03-20 16:40:00 -0700
commitb3e6c9aab3f96ddf2c0be0832b70ab1e504bbb3c (patch)
tree2f91f407749726e7de5074f35c4927adb6a04910
parentaa63fd67d59b14fef1795ee074a45c8e8935a0ee (diff)
downloadgolang-b3e6c9aab3f96ddf2c0be0832b70ab1e504bbb3c.tar.gz
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
-rw-r--r--src/cmd/8a/a.h2
-rw-r--r--src/cmd/8a/a.y66
-rw-r--r--src/cmd/8a/lex.c22
-rw-r--r--src/cmd/8c/gc.h1
-rw-r--r--src/cmd/8c/list.c4
-rw-r--r--src/cmd/8c/sgen.c32
-rw-r--r--src/cmd/8c/swt.c15
-rw-r--r--src/cmd/8c/txt.c13
-rw-r--r--src/cmd/8l/8.out.h6
-rw-r--r--src/cmd/8l/l.h5
-rw-r--r--src/cmd/8l/list.c18
-rw-r--r--src/cmd/8l/obj.c306
-rw-r--r--src/cmd/8l/optab.c8
-rw-r--r--src/cmd/8l/pass.c138
-rw-r--r--src/cmd/8l/span.c44
-rw-r--r--src/cmd/cc/cc.h1
-rw-r--r--src/cmd/cc/com.c5
-rw-r--r--src/cmd/cc/sub.c1
18 files changed, 543 insertions, 144 deletions
diff --git a/src/cmd/8a/a.h b/src/cmd/8a/a.h
index 8b5f7d9ef..dbe439929 100644
--- a/src/cmd/8a/a.h
+++ b/src/cmd/8a/a.h
@@ -32,7 +32,6 @@
#include <libc.h>
#include <bio.h>
#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 505defd28..fced3efa4 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 <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
-%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI
+%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG
%token <lval> LCONST LFP LPC LSB
%token <lval> LBREG LLREG LSREG LFREG
%token <dval> LFCONST
%token <sval> LSCONST LSP
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset
-%type <gen> mem imm reg nam rel rem rim rom omem nmem
+%type <con2> con2
+%type <gen> mem imm imm2 reg nam rel rem rim rom omem nmem
%type <gen2> nonnon nonrel nonrem rimnon rimrem remrim
-%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7
+%type <gen2> 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 8576f01b7..fcc4cf964 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<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
@@ -172,6 +175,8 @@ assemble(char *file)
cclean();
return nerrors;
}
+
+ Bprint(&obuf, "\n!\n");
pass = 2;
outhist();
@@ -304,6 +309,9 @@ struct
"CMPSB", LTYPE0, ACMPSB,
"CMPSL", LTYPE0, ACMPSL,
"CMPSW", LTYPE0, ACMPSW,
+ "CMPXCHGB", LTYPE3, ACMPXCHGB,
+ "CMPXCHGL", LTYPE3, ACMPXCHGL,
+ "CMPXCHGW", LTYPE3, ACMPXCHGW,
"DAA", LTYPE0, ADAA,
"DAS", LTYPE0, ADAS,
"DATA", LTYPED, ADATA,
@@ -315,7 +323,7 @@ struct
"DIVW", LTYPE2, ADIVW,
"END", LTYPE0, AEND,
"ENTER", LTYPE2, AENTER,
- "GLOBL", LTYPET, AGLOBL,
+ "GLOBL", LTYPEG, AGLOBL,
"HLT", LTYPE0, AHLT,
"IDIVB", LTYPE2, AIDIVB,
"IDIVL", LTYPE2, AIDIVL,
@@ -714,7 +722,7 @@ zname(char *n, int t, int s)
void
zaddr(Gen *a, int s)
{
- long l;
+ int32 l;
int i, t;
char *n;
Ieee e;
@@ -734,6 +742,9 @@ zaddr(Gen *a, int s)
case D_FCONST:
t |= T_FCONST;
break;
+ case D_CONST2:
+ t |= T_OFFSET|T_OFFSET2;
+ break;
case D_SCONST:
t |= T_SCONST;
break;
@@ -753,6 +764,13 @@ zaddr(Gen *a, int s)
Bputc(&obuf, l>>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 c30eb55bc..55a37c42c 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 d700b63af..ec5ac9d60 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 14bd32adb..c4d5665d8 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 13e9a51e3..6d693337a 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<NSYM; sym++) {
h[sym].sym = S;
@@ -530,6 +533,9 @@ zaddr(Biobuf *b, Adr *a, int s)
case D_SCONST:
t |= T_SCONST;
break;
+ case D_CONST2:
+ t |= T_OFFSET|T_OFFSET2;
+ break;
}
Bputc(b, t);
@@ -544,6 +550,13 @@ zaddr(Biobuf *b, Adr *a, int s)
Bputc(b, l>>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 4e95f3c7a..5cc43e0e9 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 647c1dd59..f7750129d 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 fabf89034..114c66369 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 ebd8b864b..873f7c1f8 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 a1d14318d..022f315d2 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)
+{
+ 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 c, t, i;
+ 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; i<NSNAME; i++)
- a->scon[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; i<libraryp; i++)
if(strcmp(name, library[i]) == 0)
return;
@@ -663,6 +687,22 @@ addlib(char *obj)
}
void
+copyhistfrog(char *buf, int nbuf)
+{
+ char *p, *ep;
+ int i;
+
+ p = buf;
+ ep = buf + nbuf;
+ i = 0;
+ for(i=0; i<histfrogp; i++) {
+ p = seprint(p, ep, "%s", histfrog[i]->name+1);
+ if(i+1<histfrogp && (p == buf || p[-1] != '/'))
+ p = seprint(p, ep, "/");
+ }
+}
+
+void
addhist(int32 line, int type)
{
Auto *u;
@@ -679,6 +719,7 @@ addhist(int32 line, int type)
u->link = curhist;
curhist = u;
+ s->name[0] = 0;
j = 1;
for(i=0; i<histfrogp; i++) {
k = histfrog[i]->value;
@@ -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){
+ if(o == ASIGNAME)
+ sig = Bget4(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;
}
- v = bloc[2]; /* type */
- o = bloc[3]; /* sym */
- bloc += 4;
- c -= 4;
-
- r = 0;
- if(v == D_STATIC)
- r = version;
- s = lookup((char*)bloc, r);
- c -= &stop[1] - bloc;
- bloc = stop + 1;
+ 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 d88e861c5..934f14e9b 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 aa69c5849..0726d1ea8 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 b524c735f..81703d304 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') {
@@ -334,6 +344,24 @@ asmlc(void)
}
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;
@@ -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 3b13126df..42341a70c 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 5ee38e882..af2509c5f 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 cad5eda72..335d30bfb 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",