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
This commit is contained in:
Russ Cox 2009-03-20 16:40:00 -07:00
parent c1e748bd2e
commit 2bd101c4b1
18 changed files with 544 additions and 145 deletions

View file

@ -32,7 +32,6 @@
#include <libc.h> #include <libc.h>
#include <bio.h> #include <bio.h>
#include "../8l/8.out.h" #include "../8l/8.out.h"
#include "compat.h"
#ifndef EXTERN #ifndef EXTERN
@ -104,6 +103,7 @@ struct Gen
double dval; double dval;
char sval[8]; char sval[8];
int32 offset; int32 offset;
int32 offset2;
Sym* sym; Sym* sym;
short type; short type;
short index; short index;

View file

@ -34,6 +34,10 @@
%union { %union {
Sym *sym; Sym *sym;
int32 lval; int32 lval;
struct {
int32 v1;
int32 v2;
} con2;
double dval; double dval;
char sval[8]; char sval[8];
Gen gen; Gen gen;
@ -46,16 +50,17 @@
%left '+' '-' %left '+' '-'
%left '*' '/' '%' %left '*' '/' '%'
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 %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> LCONST LFP LPC LSB
%token <lval> LBREG LLREG LSREG LFREG %token <lval> LBREG LLREG LSREG LFREG
%token <dval> LFCONST %token <dval> LFCONST
%token <sval> LSCONST LSP %token <sval> LSCONST LSP
%token <sym> LNAME LLAB LVAR %token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset %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> 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:
| prog line | prog line
@ -103,6 +108,7 @@ inst:
| LTYPES spec5 { outcode($1, &$2); } | LTYPES spec5 { outcode($1, &$2); }
| LTYPEM spec6 { outcode($1, &$2); } | LTYPEM spec6 { outcode($1, &$2); }
| LTYPEI spec7 { outcode($1, &$2); } | LTYPEI spec7 { outcode($1, &$2); }
| LTYPEG spec8 { outcode($1, &$2); }
nonnon: nonnon:
{ {
@ -174,12 +180,12 @@ spec1: /* DATA */
} }
spec2: /* TEXT */ spec2: /* TEXT */
mem ',' imm mem ',' imm2
{ {
$$.from = $1; $$.from = $1;
$$.to = $3; $$.to = $3;
} }
| mem ',' con ',' imm | mem ',' con ',' imm2
{ {
$$.from = $1; $$.from = $1;
$$.from.scale = $3; $$.from.scale = $3;
@ -249,6 +255,19 @@ spec7:
$$.to = $3; $$.to = $3;
} }
spec8: /* GLOBL */
mem ',' imm
{
$$.from = $1;
$$.to = $3;
}
| mem ',' con ',' imm
{
$$.from = $1;
$$.from.scale = $3;
$$.to = $5;
}
rem: rem:
reg reg
| mem | mem
@ -365,6 +384,37 @@ imm:
$$.dval = -$3; $$.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: mem:
omem omem
| nmem | nmem
@ -416,6 +466,12 @@ omem:
$$ = nullgen; $$ = nullgen;
$$.type = D_INDIR+D_SP; $$.type = D_INDIR+D_SP;
} }
| con '(' LSREG ')'
{
$$ = nullgen;
$$.type = D_INDIR+$3;
$$.offset = $1;
}
| '(' LLREG '*' con ')' | '(' LLREG '*' con ')'
{ {
$$ = nullgen; $$ = nullgen;

View file

@ -165,6 +165,9 @@ assemble(char *file)
pass = 1; pass = 1;
pinit(file); pinit(file);
Bprint(&obuf, "%s\n", thestring);
for(i=0; i<nDlist; i++) for(i=0; i<nDlist; i++)
dodefine(Dlist[i]); dodefine(Dlist[i]);
yyparse(); yyparse();
@ -173,6 +176,8 @@ assemble(char *file)
return nerrors; return nerrors;
} }
Bprint(&obuf, "\n!\n");
pass = 2; pass = 2;
outhist(); outhist();
pinit(file); pinit(file);
@ -304,6 +309,9 @@ struct
"CMPSB", LTYPE0, ACMPSB, "CMPSB", LTYPE0, ACMPSB,
"CMPSL", LTYPE0, ACMPSL, "CMPSL", LTYPE0, ACMPSL,
"CMPSW", LTYPE0, ACMPSW, "CMPSW", LTYPE0, ACMPSW,
"CMPXCHGB", LTYPE3, ACMPXCHGB,
"CMPXCHGL", LTYPE3, ACMPXCHGL,
"CMPXCHGW", LTYPE3, ACMPXCHGW,
"DAA", LTYPE0, ADAA, "DAA", LTYPE0, ADAA,
"DAS", LTYPE0, ADAS, "DAS", LTYPE0, ADAS,
"DATA", LTYPED, ADATA, "DATA", LTYPED, ADATA,
@ -315,7 +323,7 @@ struct
"DIVW", LTYPE2, ADIVW, "DIVW", LTYPE2, ADIVW,
"END", LTYPE0, AEND, "END", LTYPE0, AEND,
"ENTER", LTYPE2, AENTER, "ENTER", LTYPE2, AENTER,
"GLOBL", LTYPET, AGLOBL, "GLOBL", LTYPEG, AGLOBL,
"HLT", LTYPE0, AHLT, "HLT", LTYPE0, AHLT,
"IDIVB", LTYPE2, AIDIVB, "IDIVB", LTYPE2, AIDIVB,
"IDIVL", LTYPE2, AIDIVL, "IDIVL", LTYPE2, AIDIVL,
@ -714,7 +722,7 @@ zname(char *n, int t, int s)
void void
zaddr(Gen *a, int s) zaddr(Gen *a, int s)
{ {
long l; int32 l;
int i, t; int i, t;
char *n; char *n;
Ieee e; Ieee e;
@ -734,6 +742,9 @@ zaddr(Gen *a, int s)
case D_FCONST: case D_FCONST:
t |= T_FCONST; t |= T_FCONST;
break; break;
case D_CONST2:
t |= T_OFFSET|T_OFFSET2;
break;
case D_SCONST: case D_SCONST:
t |= T_SCONST; t |= T_SCONST;
break; break;
@ -753,6 +764,13 @@ zaddr(Gen *a, int s)
Bputc(&obuf, l>>16); Bputc(&obuf, l>>16);
Bputc(&obuf, l>>24); 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 */ if(t & T_SYM) /* implies sym */
Bputc(&obuf, s); Bputc(&obuf, s);
if(t & T_FCONST) { if(t & T_FCONST) {

View file

@ -66,6 +66,7 @@ EXTERN struct
struct Adr struct Adr
{ {
int32 offset; int32 offset;
int32 offset2;
double dval; double dval;
char sval[NSNAME]; char sval[NSNAME];

View file

@ -154,6 +154,10 @@ Dconv(Fmt *fp)
sprint(str, "$%ld", a->offset); sprint(str, "$%ld", a->offset);
break; break;
case D_CONST2:
sprint(str, "$%ld-%ld", a->offset, a->offset2);
break;
case D_FCONST: case D_FCONST:
sprint(str, "$(%.17e)", a->dval); sprint(str, "$(%.17e)", a->dval);
break; break;

View file

@ -30,6 +30,31 @@
#include "gc.h" #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 void
codgen(Node *n, Node *nn) codgen(Node *n, Node *nn)
{ {
@ -52,7 +77,10 @@ codgen(Node *n, Node *nn)
break; break;
} }
nearln = nn->lineno; nearln = nn->lineno;
gpseudo(ATEXT, n1->sym, nodconst(stkoff)); gpseudo(ATEXT, n1->sym, nodconst(stkoff));
p->to.type = D_CONST2;
p->to.offset2 = argsize();
/* /*
* isolate first argument * isolate first argument
@ -494,6 +522,10 @@ xcom(Node *n)
n->addable = 11; n->addable = 11;
break; break;
case OEXREG:
n->addable = 10;
break;
case OREGISTER: case OREGISTER:
n->addable = 12; n->addable = 12;
break; break;

View file

@ -328,7 +328,10 @@ outcode(void)
return; return;
} }
Binit(&b, f, OWRITE); Binit(&b, f, OWRITE);
Bseek(&b, 0L, 2);
Bprint(&b, "%s\n", thestring);
Bprint(&b, "!\n");
outhist(&b); outhist(&b);
for(sym=0; sym<NSYM; sym++) { for(sym=0; sym<NSYM; sym++) {
h[sym].sym = S; h[sym].sym = S;
@ -530,6 +533,9 @@ zaddr(Biobuf *b, Adr *a, int s)
case D_SCONST: case D_SCONST:
t |= T_SCONST; t |= T_SCONST;
break; break;
case D_CONST2:
t |= T_OFFSET|T_OFFSET2;
break;
} }
Bputc(b, t); Bputc(b, t);
@ -544,6 +550,13 @@ zaddr(Biobuf *b, Adr *a, int s)
Bputc(b, l>>16); Bputc(b, l>>16);
Bputc(b, l>>24); 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 */ if(t & T_SYM) /* implies sym */
Bputc(b, s); Bputc(b, s);
if(t & T_FCONST) { if(t & T_FCONST) {

View file

@ -449,6 +449,10 @@ naddr(Node *n, Adr *a)
a->sym = S; a->sym = S;
break; break;
case OEXREG:
a->type = D_INDIR + D_FS;
a->offset = n->reg - 1;
break;
case OIND: case OIND:
naddr(n->left, a); naddr(n->left, a);
@ -1389,6 +1393,15 @@ sconst(Node *n)
int32 int32
exreg(Type *t) 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); USED(t);
return 0; return 0;

View file

@ -32,6 +32,7 @@
#define NSNAME 8 #define NSNAME 8
#define NOPROF (1<<0) #define NOPROF (1<<0)
#define DUPOK (1<<1) #define DUPOK (1<<1)
#define NOSPLIT (1<<2)
enum as enum as
{ {
@ -78,6 +79,9 @@ enum as
ACMPSB, ACMPSB,
ACMPSL, ACMPSL,
ACMPSW, ACMPSW,
ACMPXCHGB,
ACMPXCHGL,
ACMPXCHGW,
ADAA, ADAA,
ADAS, ADAS,
ADATA, ADATA,
@ -437,6 +441,7 @@ enum
D_FCONST = 66, D_FCONST = 66,
D_SCONST = 67, D_SCONST = 67,
D_ADDR = 68, D_ADDR = 68,
D_CONST2 = 69,
D_FILE, D_FILE,
D_FILE1, D_FILE1,
@ -449,6 +454,7 @@ enum
T_FCONST = 1<<3, T_FCONST = 1<<3,
T_SYM = 1<<4, T_SYM = 1<<4,
T_SCONST = 1<<5, T_SCONST = 1<<5,
T_OFFSET2 = 1<<6,
REGARG = 0, REGARG = 0,
REGRET = D_AX, REGRET = D_AX,

View file

@ -67,6 +67,7 @@ struct Adr
short type; short type;
uchar index; uchar index;
char scale; char scale;
int32 offset2;
}; };
#define offset u0.u0offset #define offset u0.u0offset
@ -342,7 +343,7 @@ void histtoauto(void);
double ieeedtod(Ieee*); double ieeedtod(Ieee*);
int32 ieeedtof(Ieee*); int32 ieeedtof(Ieee*);
void import(void); void import(void);
void ldobj(int, int32, char*); void ldobj(Biobuf*, int32, char*);
void loadlib(void); void loadlib(void);
void listinit(void); void listinit(void);
Sym* lookup(char*, int); Sym* lookup(char*, int);
@ -368,7 +369,7 @@ int32 vaddr(Adr*);
void wput(ushort); void wput(ushort);
void xdefine(char*, int, int32); void xdefine(char*, int, int32);
void xfol(Prog*); void xfol(Prog*);
int zaddr(uchar*, Adr*, Sym*[]); void zaddr(Biobuf*, Adr*, Sym*[]);
void zerosig(char*); void zerosig(char*);
uint32 machheadr(void); uint32 machheadr(void);
uint32 elfheadr(void); uint32 elfheadr(void);

View file

@ -82,6 +82,14 @@ Aconv(Fmt *fp)
return fmtstrcpy(fp, anames[i]); return fmtstrcpy(fp, anames[i]);
} }
char*
xsymname(Sym *s)
{
if(s == nil)
return "!!noname!!";
return s->name;
}
int int
Dconv(Fmt *fp) Dconv(Fmt *fp)
{ {
@ -120,16 +128,16 @@ Dconv(Fmt *fp)
break; break;
case D_EXTERN: case D_EXTERN:
sprint(str, "%s+%ld(SB)", a->sym->name, a->offset); sprint(str, "%s+%ld(SB)", xsymname(a->sym), a->offset);
break; break;
case D_STATIC: 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); a->sym->version, a->offset);
break; break;
case D_AUTO: case D_AUTO:
sprint(str, "%s+%ld(SP)", a->sym->name, a->offset); sprint(str, "%s+%ld(SP)", xsymname(a->sym), a->offset);
break; break;
case D_PARAM: case D_PARAM:
@ -143,6 +151,10 @@ Dconv(Fmt *fp)
sprint(str, "$%ld", a->offset); sprint(str, "$%ld", a->offset);
break; break;
case D_CONST2:
sprint(str, "$%ld-%ld", a->offset, a->offset2);
break;
case D_FCONST: case D_FCONST:
sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l); sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l);
break; break;

View file

@ -419,14 +419,15 @@ void
objfile(char *file) objfile(char *file)
{ {
int32 off, esym, cnt, l; int32 off, esym, cnt, l;
int f, work; int work;
Biobuf *f;
Sym *s; Sym *s;
char magbuf[SARMAG]; char magbuf[SARMAG];
char name[100], pname[150]; char name[100], pname[150];
struct ar_hdr arhdr; struct ar_hdr arhdr;
char *e, *start, *stop; char *e, *start, *stop;
if(file[0] == '-' && file[1] == 'l') { if(file[0] == '-' && file[1] == 'l') { // TODO: fix this
if(debug['9']) if(debug['9'])
sprint(name, "/%s/lib/lib", thestring); sprint(name, "/%s/lib/lib", thestring);
else else
@ -438,22 +439,22 @@ objfile(char *file)
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
Bflush(&bso); Bflush(&bso);
f = open(file, 0); f = Bopen(file, 0);
if(f < 0) { if(f == nil) {
diag("cannot open file: %s", file); diag("cannot open file: %s", file);
errorexit(); errorexit();
} }
l = read(f, magbuf, SARMAG); l = Bread(f, magbuf, SARMAG);
if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
/* load it as a regular file */ /* load it as a regular file */
l = seek(f, 0L, 2); l = Bseek(f, 0L, 2);
seek(f, 0L, 0); Bseek(f, 0L, 0);
ldobj(f, l, file); ldobj(f, l, file);
close(f); Bterm(f);
return; return;
} }
l = read(f, &arhdr, SAR_HDR); l = Bread(f, &arhdr, SAR_HDR);
if(l != SAR_HDR) { if(l != SAR_HDR) {
diag("%s: short read on archive file symbol header", file); diag("%s: short read on archive file symbol header", file);
goto out; goto out;
@ -469,12 +470,12 @@ objfile(char *file)
/* /*
* just bang the whole symbol file into memory * just bang the whole symbol file into memory
*/ */
seek(f, off, 0); Bseek(f, off, 0);
cnt = esym - off; cnt = esym - off;
start = malloc(cnt + 10); start = malloc(cnt + 10);
cnt = read(f, start, cnt); cnt = Bread(f, start, cnt);
if(cnt <= 0){ if(cnt <= 0){
close(f); Bterm(f);
return; return;
} }
stop = &start[cnt]; stop = &start[cnt];
@ -498,12 +499,16 @@ objfile(char *file)
l |= (e[2] & 0xff) << 8; l |= (e[2] & 0xff) << 8;
l |= (e[3] & 0xff) << 16; l |= (e[3] & 0xff) << 16;
l |= (e[4] & 0xff) << 24; l |= (e[4] & 0xff) << 24;
seek(f, l, 0); Bseek(f, l, 0);
l = read(f, &arhdr, SAR_HDR); l = Bread(f, &arhdr, SAR_HDR);
if(l != SAR_HDR) if(l != SAR_HDR)
goto bad; goto bad;
if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
goto bad; goto bad;
l = SARNAME;
while(l > 0 && arhdr.name[l-1] == ' ')
l--;
sprint(pname, "%s(%.*s)", file, l, arhdr.name);
l = atolwhex(arhdr.size); l = atolwhex(arhdr.size);
ldobj(f, l, pname); ldobj(f, l, pname);
if(s->type == SXREF) { if(s->type == SXREF) {
@ -519,85 +524,87 @@ objfile(char *file)
bad: bad:
diag("%s: bad or out of date archive", file); diag("%s: bad or out of date archive", file);
out: out:
close(f); Bterm(f);
} }
int int32
zaddr(uchar *p, Adr *a, Sym *h[]) 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; int32 l;
Sym *s; Sym *s;
Auto *u; Auto *u;
t = p[0]; t = Bgetc(f);
c = 1;
if(t & T_INDEX) { if(t & T_INDEX) {
a->index = p[c]; a->index = Bgetc(f);
a->scale = p[c+1]; a->scale = Bgetc(f);
c += 2;
} else { } else {
a->index = D_NONE; a->index = D_NONE;
a->scale = 0; a->scale = 0;
} }
a->type = D_NONE;
a->offset = 0; a->offset = 0;
if(t & T_OFFSET) { if(t & T_OFFSET)
a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); a->offset = Bget4(f);
c += 4; a->offset2 = 0;
if(t & T_OFFSET2) {
a->offset2 = Bget4(f);
a->type = D_CONST2;
} }
a->sym = S; a->sym = S;
if(t & T_SYM) { if(t & T_SYM)
a->sym = h[p[c]]; a->sym = h[Bgetc(f)];
c++;
}
a->type = D_NONE;
if(t & T_FCONST) { if(t & T_FCONST) {
a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); a->ieee.l = Bget4(f);
a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); a->ieee.h = Bget4(f);
c += 8;
a->type = D_FCONST; a->type = D_FCONST;
} else } else
if(t & T_SCONST) { if(t & T_SCONST) {
for(i=0; i<NSNAME; i++) Bread(f, a->scon, NSNAME);
a->scon[i] = p[c+i];
c += NSNAME;
a->type = D_SCONST; a->type = D_SCONST;
} }
if(t & T_TYPE) { if(t & T_TYPE)
a->type = p[c]; a->type = Bgetc(f);
c++;
}
s = a->sym; s = a->sym;
if(s == S) if(s == S)
return c; return;
t = a->type; t = a->type;
if(t != D_AUTO && t != D_PARAM) if(t != D_AUTO && t != D_PARAM)
return c; return;
l = a->offset; l = a->offset;
for(u=curauto; u; u=u->link) { for(u=curauto; u; u=u->link) {
if(u->asym == s) if(u->asym == s)
if(u->type == t) { if(u->type == t) {
if(u->aoffset > l) if(u->aoffset > l)
u->aoffset = l; u->aoffset = l;
return c; return;
} }
} }
u = mal(sizeof(Auto)); u = mal(sizeof(*u));
u->link = curauto; u->link = curauto;
curauto = u; curauto = u;
u->asym = s; u->asym = s;
u->aoffset = l; u->aoffset = l;
u->type = t; u->type = t;
return c;
} }
void void
addlib(char *obj) addlib(char *src, char *obj)
{ {
char name[1024], comp[256], *p; char name[1024], comp[256], *p, *q;
int i; int i;
if(histfrogp <= 0) if(histfrogp <= 0)
@ -645,6 +652,23 @@ addlib(char *obj)
strcat(name, "/"); strcat(name, "/");
strcat(name, comp); 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++) for(i=0; i<libraryp; i++)
if(strcmp(name, library[i]) == 0) if(strcmp(name, library[i]) == 0)
return; return;
@ -662,6 +686,22 @@ addlib(char *obj)
libraryp++; libraryp++;
} }
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 void
addhist(int32 line, int type) addhist(int32 line, int type)
{ {
@ -679,6 +719,7 @@ addhist(int32 line, int type)
u->link = curhist; u->link = curhist;
curhist = u; curhist = u;
s->name[0] = 0;
j = 1; j = 1;
for(i=0; i<histfrogp; i++) { for(i=0; i<histfrogp; i++) {
k = histfrog[i]->value; k = histfrog[i]->value;
@ -686,6 +727,8 @@ addhist(int32 line, int type)
s->name[j+1] = k; s->name[j+1] = k;
j += 2; j += 2;
} }
s->name[j] = 0;
s->name[j+1] = 0;
} }
void void
@ -746,35 +789,27 @@ nopout(Prog *p)
p->to.type = D_NONE; 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 void
ldobj(int f, int32 c, char *pn) ldobj(Biobuf *f, int32 len, char *pn)
{ {
int32 ipc; int32 ipc;
Prog *p, *t; Prog *p, *t;
uchar *bloc, *bsize, *stop;
int v, o, r, skip; int v, o, r, skip;
Sym *h[NSYM], *s, *di; Sym *h[NSYM], *s, *di;
uint32 sig; uint32 sig;
static int files; static int files;
static char **filen; static char **filen;
char **nfilen; 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){ if((files&15) == 0){
nfilen = malloc((files+16)*sizeof(char*)); nfilen = malloc((files+16)*sizeof(char*));
@ -782,12 +817,48 @@ ldobj(int f, int32 c, char *pn)
free(filen); free(filen);
filen = nfilen; filen = nfilen;
} }
filen[files++] = strdup(pn); pn = strdup(pn);
filen[files++] = pn;
bsize = buf.xbuf;
bloc = buf.xbuf;
di = S; 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: newloop:
memset(h, 0, sizeof(h)); memset(h, 0, sizeof(h));
version++; version++;
@ -796,61 +867,46 @@ newloop:
skip = 0; skip = 0;
loop: loop:
if(c <= 0) if(f->state == Bracteof || Boffset(f) >= eof)
goto eof; goto eof;
r = bsize - bloc; o = Bgetc(f);
if(r < 100 && r < c) { /* enough for largest prog */ if(o == Beof)
bsize = readsome(f, buf.xbuf, bloc, bsize, c);
if(bsize == 0)
goto eof; goto eof;
bloc = buf.xbuf; o |= Bgetc(f) << 8;
goto loop;
}
o = bloc[0] | (bloc[1] << 8);
if(o <= AXXX || o >= ALAST) { if(o <= AXXX || o >= ALAST) {
if(o < 0) if(o < 0)
goto eof; goto eof;
diag("%s: opcode out of range %d", pn, o); diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o);
print(" probably not a .8 file\n"); print(" probably not a .%c file\n", thechar);
errorexit(); errorexit();
} }
if(o == ANAME || o == ASIGNAME) { if(o == ANAME || o == ASIGNAME) {
sig = 0; sig = 0;
if(o == ASIGNAME) { if(o == ASIGNAME)
sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); sig = Bget4(f);
bloc += 4; v = Bgetc(f); /* type */
c -= 4; o = Bgetc(f); /* sym */
}
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;
r = 0; r = 0;
if(v == D_STATIC) if(v == D_STATIC)
r = version; r = version;
s = lookup((char*)bloc, r); name = Brdline(f, '\0');
c -= &stop[1] - bloc; if(name == nil) {
bloc = stop + 1; if(Blinelen(f) > 0) {
fprint(2, "%s: name too long\n", pn);
errorexit();
}
goto eof;
}
s = lookup(name, r);
if(debug['S'] && r == 0) if(debug['S'] && r == 0)
sig = 1729; sig = 1729;
if(sig != 0){ if(sig != 0){
if(s->sig != 0 && s->sig != sig) 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->sig = sig;
s->file = files-1; s->file = files-1;
} }
@ -877,12 +933,10 @@ loop:
p = mal(sizeof(*p)); p = mal(sizeof(*p));
p->as = o; p->as = o;
p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24); p->line = Bget4(f);
p->back = 2; p->back = 2;
r = zaddr(bloc+6, &p->from, h) + 6; zaddr(f, &p->from, h);
r += zaddr(bloc+r, &p->to, h); zaddr(f, &p->to, h);
bloc += r;
c -= r;
if(debug['W']) if(debug['W'])
print("%P\n", p); print("%P\n", p);
@ -890,10 +944,12 @@ loop:
switch(p->as) { switch(p->as) {
case AHISTORY: case AHISTORY:
if(p->to.offset == -1) { if(p->to.offset == -1) {
addlib(pn); addlib(src, pn);
histfrogp = 0; histfrogp = 0;
goto loop; goto loop;
} }
if(src[0] == '\0')
copyhistfrog(src, sizeof src);
addhist(p->line, D_FILE); /* 'z' */ addhist(p->line, D_FILE); /* 'z' */
if(p->to.offset) if(p->to.offset)
addhist(p->to.offset, D_FILE1); /* 'Z' */ addhist(p->to.offset, D_FILE1); /* 'Z' */
@ -906,9 +962,9 @@ loop:
curtext->to.autom = curauto; curtext->to.autom = curauto;
curauto = 0; curauto = 0;
curtext = P; curtext = P;
if(c) if(Boffset(f) == eof)
goto newloop;
return; return;
goto newloop;
case AGLOBL: case AGLOBL:
s = p->from.sym; s = p->from.sym;
@ -983,6 +1039,17 @@ loop:
goto loop; goto loop;
case ATEXT: 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) { if(curtext != P) {
histtoauto(); histtoauto();
curtext->to.autom = curauto; curtext->to.autom = curauto;
@ -990,11 +1057,6 @@ loop:
} }
skip = 0; skip = 0;
curtext = p; 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(s->type != 0 && s->type != SXREF) {
if(p->from.scale & DUPOK) { if(p->from.scale & DUPOK) {
skip = 1; skip = 1;

View file

@ -173,6 +173,11 @@ uchar yml_rl[] =
Yml, Yrl, Zm_r, 1, Yml, Yrl, Zm_r, 1,
0 0
}; };
uchar yrb_mb[] =
{
Yrb, Ymb, Zr_m, 1,
0
};
uchar yrl_ml[] = uchar yrl_ml[] =
{ {
Yrl, Yml, Zr_m, 1, Yrl, Yml, Zr_m, 1,
@ -383,6 +388,9 @@ Optab optab[] =
{ ACMPSB, ynone, Pb, 0xa6 }, { ACMPSB, ynone, Pb, 0xa6 },
{ ACMPSL, ynone, Px, 0xa7 }, { ACMPSL, ynone, Px, 0xa7 },
{ ACMPSW, ynone, Pe, 0xa7 }, { ACMPSW, ynone, Pe, 0xa7 },
{ ACMPXCHGB, yrb_mb, Pm, 0xb0 },
{ ACMPXCHGL, yrl_ml, Pm, 0xb1 },
{ ACMPXCHGW, yrl_ml, Pm, 0xb1 },
{ ADAA, ynone, Px, 0x27 }, { ADAA, ynone, Px, 0x27 },
{ ADAS, ynone, Px, 0x2f }, { ADAS, ynone, Px, 0x2f },
{ ADATA }, { ADATA },

View file

@ -165,7 +165,7 @@ loop:
if(p->as == ATEXT) if(p->as == ATEXT)
curtext = p; curtext = p;
if(p->as == AJMP) if(p->as == AJMP)
if((q = p->pcond) != P) { if((q = p->pcond) != P && q->as != ATEXT) {
p->mark = 1; p->mark = 1;
p = q; p = q;
if(p->mark == 0) if(p->mark == 0)
@ -331,14 +331,15 @@ patch(void)
for(p = firstp; p != P; p = p->link) { for(p = firstp; p != P; p = p->link) {
if(p->as == ATEXT) if(p->as == ATEXT)
curtext = p; 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; s = p->to.sym;
if(s) { if(s) {
if(debug['c']) if(debug['c'])
Bprint(&bso, "%s calls %s\n", TNAME, s->name); Bprint(&bso, "%s calls %s\n", TNAME, s->name);
switch(s->type) { switch(s->type) {
default: default:
diag("undefined: %s in %s", s->name, TNAME); /* diag prints TNAME first */
diag("%s is undefined", s->name);
s->type = STEXT; s->type = STEXT;
s->value = vexit; s->value = vexit;
break; /* or fall through to set offset? */ break; /* or fall through to set offset? */
@ -440,9 +441,27 @@ brloop(Prog *p)
void void
dostkoff(void) dostkoff(void)
{ {
Prog *p, *q; Prog *p, *q, *q1;
int32 autoffset, deltasp; int32 autoffset, deltasp;
int a, f, curframe, curbecome, maxbecome; 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; curframe = 0;
curbecome = 0; curbecome = 0;
@ -521,11 +540,122 @@ dostkoff(void)
autoffset = p->to.offset; autoffset = p->to.offset;
if(autoffset < 0) if(autoffset < 0)
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) { if(autoffset) {
p = appendp(p); p = appendp(p);
p->as = AADJSP; p->as = AADJSP;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = autoffset; p->from.offset = autoffset;
if(q != P)
q->pcond = p;
} }
deltasp = autoffset; deltasp = autoffset;
} }

View file

@ -148,7 +148,10 @@ xdefine(char *p, int t, int32 v)
void void
putsymb(char *s, int t, int32 v, int ver) putsymb(char *s, int t, int32 v, int ver)
{ {
int i, f; int i, j, f;
char *go;
go = nil; // TODO
if(t == 'f') if(t == 'f')
s++; s++;
@ -172,7 +175,14 @@ putsymb(char *s, int t, int32 v, int ver)
cput(s[i]); cput(s[i]);
cput(0); 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(debug['n']) {
if(t == 'z' || t == 'Z') { if(t == 'z' || t == 'Z') {
@ -333,6 +343,24 @@ asmlc(void)
Bflush(&bso); 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 int
oclass(Adr *a) oclass(Adr *a)
{ {
@ -447,6 +475,7 @@ oclass(Adr *a)
return Ym; return Ym;
case D_CONST: case D_CONST:
case D_CONST2:
case D_ADDR: case D_ADDR:
if(a->sym == S) { if(a->sym == S) {
v = a->offset; v = a->offset;
@ -636,7 +665,7 @@ asmand(Adr *a, int r)
} }
if(t >= D_INDIR) { if(t >= D_INDIR) {
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); *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
put4(v); put4(v);
return; return;
@ -851,7 +880,14 @@ doasm(Prog *p)
Prog *q, pp; Prog *q, pp;
uchar *t; uchar *t;
int z, op, ft, tt; 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]; o = &optab[p->as];
ft = oclass(&p->from) * Ymax; ft = oclass(&p->from) * Ymax;

View file

@ -262,6 +262,7 @@ enum
ODWHILE, ODWHILE,
OENUM, OENUM,
OEQ, OEQ,
OEXREG,
OFOR, OFOR,
OFUNC, OFUNC,
OGE, OGE,

View file

@ -638,6 +638,11 @@ tcomo(Node *n, int f)
n->addable = 1; n->addable = 1;
if(n->class == CEXREG) { if(n->class == CEXREG) {
n->op = OREGISTER; 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->reg = n->sym->offset;
n->xoffset = 0; n->xoffset = 0;
break; break;

View file

@ -1460,6 +1460,7 @@ Init onamesinit[] =
ODWHILE, 0, "DWHILE", ODWHILE, 0, "DWHILE",
OENUM, 0, "ENUM", OENUM, 0, "ENUM",
OEQ, 0, "EQ", OEQ, 0, "EQ",
OEXREG, 0, "EXREG",
OFOR, 0, "FOR", OFOR, 0, "FOR",
OFUNC, 0, "FUNC", OFUNC, 0, "FUNC",
OGE, 0, "GE", OGE, 0, "GE",