1
0
mirror of https://github.com/golang/go synced 2024-11-25 07:37:57 -07:00

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 <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;

View File

@ -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;

View File

@ -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();
@ -173,6 +176,8 @@ assemble(char *file)
return nerrors;
}
Bprint(&obuf, "\n!\n");
pass = 2;
outhist();
pinit(file);
@ -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) {

View File

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

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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; 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;
@ -662,6 +686,22 @@ addlib(char *obj)
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
addhist(int32 line, int type)
{
@ -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){
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;

View File

@ -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 },

View File

@ -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;
}

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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",