mirror of
https://github.com/golang/go
synced 2024-11-25 07:47:56 -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:
parent
c1e748bd2e
commit
2bd101c4b1
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -66,6 +66,7 @@ EXTERN struct
|
||||
struct Adr
|
||||
{
|
||||
int32 offset;
|
||||
int32 offset2;
|
||||
double dval;
|
||||
char sval[NSNAME];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
304
src/cmd/8l/obj.c
304
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; 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)
|
||||
o = Bgetc(f);
|
||||
if(o == Beof)
|
||||
goto eof;
|
||||
bloc = buf.xbuf;
|
||||
goto loop;
|
||||
}
|
||||
o = bloc[0] | (bloc[1] << 8);
|
||||
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;
|
||||
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;
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -262,6 +262,7 @@ enum
|
||||
ODWHILE,
|
||||
OENUM,
|
||||
OEQ,
|
||||
OEXREG,
|
||||
OFOR,
|
||||
OFUNC,
|
||||
OGE,
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user