import updated compilers from sources
parent
fcc5e75d07
commit
4f33c88a51
|
@ -2,6 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *f, *b, *s;
|
||||
|
|
|
@ -164,7 +164,7 @@ for(i=0, procp=procstack; i<nproc; ++i, ++procp)
|
|||
|
||||
sprintf(junk, "spurious return from process %d", pid);
|
||||
fatal(junk);
|
||||
/*NOTREACHED*/
|
||||
return -1;/*NOTREACHED*/
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -438,4 +438,5 @@ char buf[100];
|
|||
sprintf(buf, "line %d of file %s: %s",
|
||||
yylineno, filestack[ninclude-1].fname, s);
|
||||
fatal(buf);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ if( p = (int *) calloc(1,n) )
|
|||
return p;
|
||||
|
||||
fatal("out of memory");
|
||||
/* NOTREACHED */
|
||||
return 0;/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* copy string a into b, substituting for arguments */
|
||||
|
|
|
@ -613,7 +613,7 @@ c_brkcont(wp)
|
|||
}
|
||||
|
||||
unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
|
||||
/*NOTREACHED*/
|
||||
return 0; /*NOTREACHED*/
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -20,6 +20,7 @@ uchar bittab[] = {
|
|||
128
|
||||
};
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ prword(char *w)
|
|||
fputs(w, stdout);
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct utsname u;
|
||||
|
|
|
@ -123,7 +123,7 @@ static double q4[] = {
|
|||
1.0,
|
||||
};
|
||||
|
||||
static
|
||||
static void
|
||||
asympt(double arg)
|
||||
{
|
||||
double zsq, n, d;
|
||||
|
|
|
@ -125,7 +125,7 @@ static double q4[] = {
|
|||
1.0,
|
||||
};
|
||||
|
||||
static
|
||||
static void
|
||||
asympt(double arg)
|
||||
{
|
||||
double zsq, n, d;
|
||||
|
|
|
@ -469,4 +469,5 @@ copynotehandler(void *u, char *msg)
|
|||
if(_finishing)
|
||||
_finish(0, 0);
|
||||
_NOTED(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ _notehandler(Ureg *u, char *msg)
|
|||
}
|
||||
_doatexits();
|
||||
_NOTED(1); /* NDFLT */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -144,6 +144,7 @@ tcsetpgrp(int fd, pid_t pgrpid)
|
|||
_syserrno();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t
|
||||
|
|
|
@ -13,6 +13,7 @@ static char line[BUFSIZ+1];
|
|||
static struct group group;
|
||||
static char *gr_mem[MAXGRP];
|
||||
|
||||
void
|
||||
setgrent()
|
||||
{
|
||||
if( !grf )
|
||||
|
@ -21,6 +22,7 @@ setgrent()
|
|||
rewind( grf );
|
||||
}
|
||||
|
||||
void
|
||||
endgrent()
|
||||
{
|
||||
if( grf ){
|
||||
|
|
|
@ -103,4 +103,5 @@ strerror_r(int n, char *buf, int len)
|
|||
{
|
||||
strncpy(buf, strerror(n), len);
|
||||
buf[len-1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ listenproc(Rock *r, int fd)
|
|||
close(dfd);
|
||||
}
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -362,7 +362,8 @@ end:
|
|||
bio_err=NULL;
|
||||
}
|
||||
OPENSSL_EXIT(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LIST_STANDARD_COMMANDS "list-standard-commands"
|
||||
#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands"
|
||||
|
|
|
@ -461,6 +461,7 @@ static double Time_F(int s)
|
|||
}
|
||||
# endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* if defined(OPENSSL_SYS_NETWARE) */
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
void
|
||||
nap(int n)
|
||||
{
|
||||
register i;
|
||||
|
|
|
@ -67,7 +67,7 @@ struct Txt
|
|||
|
||||
struct Cases
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
uchar def;
|
||||
Case* link;
|
||||
|
@ -131,7 +131,7 @@ struct Multab
|
|||
|
||||
struct C1
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ doswit(int g, Node *n)
|
|||
def = breakpc;
|
||||
for(i=0; i<nc-1; i++)
|
||||
if(iq[i].val == iq[i+1].val)
|
||||
diag(n, "duplicate cases in switch %ld", iq[i].val);
|
||||
diag(n, "duplicate cases in switch %lld", iq[i].val);
|
||||
swit1(iq, nc, def, g, n);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ struct Txt
|
|||
|
||||
struct Cases
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
uchar def;
|
||||
Case* link;
|
||||
|
@ -147,7 +147,7 @@ struct Multab
|
|||
|
||||
struct C1
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ doswit(int g, Node *n)
|
|||
def = breakpc;
|
||||
for(i=0; i<nc-1; i++)
|
||||
if(iq[i].val == iq[i+1].val)
|
||||
diag(n, "duplicate cases in switch %ld", iq[i].val);
|
||||
diag(n, "duplicate cases in switch %lld", iq[i].val);
|
||||
swit1(iq, nc, def, g, n);
|
||||
}
|
||||
|
||||
|
|
|
@ -175,9 +175,5 @@ int mywait(int*);
|
|||
int mycreat(char*, int);
|
||||
int systemtype(int);
|
||||
int pathchar(void);
|
||||
char* mygetwd(char*, int);
|
||||
int myexec(char*, char*[]);
|
||||
int mydup(int, int);
|
||||
int myfork(void);
|
||||
int mypipe(int*);
|
||||
void* mysbrk(ulong);
|
||||
|
|
|
@ -311,6 +311,11 @@ struct
|
|||
"MOVWD", LTYPE3, AMOVWD,
|
||||
"MOVWF", LTYPE3, AMOVWF,
|
||||
|
||||
"LDREX", LTYPE3, ALDREX,
|
||||
"LDREXD", LTYPE3, ALDREXD,
|
||||
"STREX", LTYPE9, ASTREX,
|
||||
"STREXD", LTYPE9, ASTREXD,
|
||||
|
||||
/*
|
||||
"ABSF", LTYPEI, AABSF,
|
||||
"ABSD", LTYPEI, AABSD,
|
||||
|
@ -326,6 +331,8 @@ struct
|
|||
"NRMD", LTYPEI, ANRMD,
|
||||
*/
|
||||
|
||||
"SQRTF", LTYPEI, ASQRTF,
|
||||
"SQRTD", LTYPEI, ASQRTD,
|
||||
"CMPF", LTYPEL, ACMPF,
|
||||
"CMPD", LTYPEL, ACMPD,
|
||||
"ADDF", LTYPEK, AADDF,
|
||||
|
@ -417,9 +424,9 @@ cinit(void)
|
|||
}
|
||||
|
||||
pathname = allocn(pathname, 0, 100);
|
||||
if(mygetwd(pathname, 99) == 0) {
|
||||
if(getwd(pathname, 99) == 0) {
|
||||
pathname = allocn(pathname, 100, 900);
|
||||
if(mygetwd(pathname, 999) == 0)
|
||||
if(getwd(pathname, 999) == 0)
|
||||
strcpy(pathname, "/???");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,4 +16,4 @@ BIN=/$objtype/bin
|
|||
< /sys/src/cmd/mkone
|
||||
YFLAGS=-D1 -d
|
||||
|
||||
lex.$O: ../cc/macbody ../cc/lexbody ../cc/compat
|
||||
lex.$O: ../cc/macbody ../cc/lexbody
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define NFREG 8
|
||||
#define FREGRET 0
|
||||
#define FREGEXT 7
|
||||
#define FREGTMP 15
|
||||
/* compiler allocates register variables F0 up */
|
||||
/* compiler allocates external registers F7 down */
|
||||
|
||||
|
@ -92,6 +93,8 @@ enum as
|
|||
AMULD,
|
||||
ADIVF,
|
||||
ADIVD,
|
||||
// ASQRTF,
|
||||
// ASQRTD,
|
||||
|
||||
ASRL,
|
||||
ASRA,
|
||||
|
@ -143,6 +146,16 @@ enum as
|
|||
|
||||
ASIGNAME,
|
||||
|
||||
/* moved here to preserve values of older identifiers */
|
||||
ASQRTF,
|
||||
ASQRTD,
|
||||
|
||||
ALDREX,
|
||||
ASTREX,
|
||||
|
||||
ALDREXD,
|
||||
ASTREXD,
|
||||
|
||||
ALAST,
|
||||
};
|
||||
|
||||
|
@ -173,7 +186,8 @@ enum as
|
|||
|
||||
#define D_SHIFT (D_NONE+19)
|
||||
#define D_FPCR (D_NONE+20)
|
||||
#define D_REGREG (D_NONE+21)
|
||||
#define D_REGREG (D_NONE+21)
|
||||
#define D_ADDR (D_NONE+22)
|
||||
|
||||
/* name */
|
||||
#define D_EXTERN (D_NONE+3)
|
||||
|
|
|
@ -94,5 +94,11 @@ char* anames[] =
|
|||
"BXRET",
|
||||
"DWORD",
|
||||
"SIGNAME",
|
||||
"SQRTF",
|
||||
"SQRTD",
|
||||
"LDREX",
|
||||
"STREX",
|
||||
"LDREXD",
|
||||
"STREXD",
|
||||
"LAST",
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
/*
|
||||
* 5c/arm
|
||||
* Arm 7500
|
||||
* Arm
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
|
@ -59,7 +59,7 @@ struct Prog
|
|||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
|
@ -68,7 +68,7 @@ struct Case
|
|||
|
||||
struct C1
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,3 +36,6 @@ t:V: $O.out
|
|||
$O.out -S t
|
||||
$LD -o t.out t.$O
|
||||
t.out
|
||||
|
||||
enam.c: 5.out.h
|
||||
rc mkenam
|
||||
|
|
|
@ -1069,7 +1069,7 @@ copyu(Prog *p, Adr *v, Adr *s)
|
|||
if(v->type == D_REG) {
|
||||
if(v->reg <= REGEXT && v->reg > exregoffset)
|
||||
return 2;
|
||||
if(v->reg == REGARG)
|
||||
if(v->reg == (uchar)REGARG)
|
||||
return 2;
|
||||
}
|
||||
if(v->type == D_FREG)
|
||||
|
@ -1087,7 +1087,7 @@ copyu(Prog *p, Adr *v, Adr *s)
|
|||
|
||||
case ATEXT: /* funny */
|
||||
if(v->type == D_REG)
|
||||
if(v->reg == REGARG)
|
||||
if(v->reg == (uchar)REGARG)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1125,7 +1125,7 @@ RtoB(int r)
|
|||
int
|
||||
BtoR(long b)
|
||||
{
|
||||
b &= 0x01fcL;
|
||||
b &= 0x01fcL; // excluded R9 and R10 for m and g
|
||||
if(b == 0)
|
||||
return 0;
|
||||
return bitno(b);
|
||||
|
|
|
@ -26,7 +26,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8lux\n", q->val);
|
||||
print("case = %.8llux\n", q->val);
|
||||
gopcode(OEQ, nodconst(q->val), n, Z);
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
|
@ -39,7 +39,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8lux\n", r->val);
|
||||
print("case > %.8llux\n", r->val);
|
||||
gopcode(OGT, nodconst(r->val), n, Z);
|
||||
sp = p;
|
||||
gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */
|
||||
|
@ -47,7 +47,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
swit2(q, i, def, n, tn);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8lux\n", r->val);
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n, tn);
|
||||
return;
|
||||
|
@ -60,7 +60,7 @@ direct:
|
|||
patch(p, def);
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8lux\n", q->val);
|
||||
print("case = %.8llux\n", q->val);
|
||||
while(q->val != v) {
|
||||
nextpc();
|
||||
p->as = ABCASE;
|
||||
|
@ -579,7 +579,7 @@ align(long i, Type *t, int op)
|
|||
w = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial allign of struct element */
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
w = ewidth[v->etype];
|
||||
|
@ -600,7 +600,7 @@ align(long i, Type *t, int op)
|
|||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial allign of parameter */
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_LONG) {
|
||||
w = SZ_LONG;
|
||||
|
@ -614,7 +614,7 @@ align(long i, Type *t, int op)
|
|||
w = SZ_LONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total allign of automatic */
|
||||
case Aaut3: /* total align of automatic */
|
||||
o = align(o, t, Ael2);
|
||||
o = align(o, t, Ael1);
|
||||
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
|
||||
|
|
|
@ -147,6 +147,15 @@ initstk(int argc, char *argv[])
|
|||
initmap();
|
||||
tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */
|
||||
sp = tos;
|
||||
for (i = 0; i < sizeof(Tos)*2; i++)
|
||||
putmem_b(tos + i, 0);
|
||||
|
||||
/*
|
||||
* pid is second word from end of tos and needs to be set for nsec().
|
||||
* we know arm is a 32-bit cpu, so we'll assume knowledge of the Tos
|
||||
* struct for now, and use our pid.
|
||||
*/
|
||||
putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid());
|
||||
|
||||
/* Build exec stack */
|
||||
size = strlen(file)+1+BY2WD+BY2WD+BY2WD;
|
||||
|
@ -157,7 +166,7 @@ initstk(int argc, char *argv[])
|
|||
sp &= ~7;
|
||||
reg.r[0] = tos;
|
||||
reg.r[13] = sp;
|
||||
reg.r[1] = STACKTOP-4; /* Plan 9 profiling clock */
|
||||
reg.r[1] = STACKTOP-4; /* Plan 9 profiling clock (why & why in R1?) */
|
||||
|
||||
/* Push argc */
|
||||
putmem_w(sp, argc+1);
|
||||
|
|
|
@ -77,11 +77,6 @@ asmb(void)
|
|||
curtext = P;
|
||||
switch(HEADTYPE) {
|
||||
case 0:
|
||||
if(debug['P']){
|
||||
OFFSET = rnd(textsize, INITRND);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
case 5:
|
||||
|
@ -89,6 +84,7 @@ asmb(void)
|
|||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 3:
|
||||
case 6: /* no header, padded segments */
|
||||
OFFSET = rnd(HEADR+textsize, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
|
@ -124,6 +120,7 @@ asmb(void)
|
|||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
case 3:
|
||||
case 6: /* no header, padded segments */
|
||||
OFFSET += rnd(datsize, 4096);
|
||||
seek(cout, OFFSET, 0);
|
||||
break;
|
||||
|
@ -152,6 +149,7 @@ asmb(void)
|
|||
seek(cout, OFFSET, 0);
|
||||
switch(HEADTYPE) {
|
||||
case 0: /* no header */
|
||||
case 6: /* no header, padded segments */
|
||||
break;
|
||||
case 1: /* aif for risc os */
|
||||
lputl(0xe1a00000); /* NOP - decompress code */
|
||||
|
|
|
@ -19,6 +19,9 @@ HFILES=\
|
|||
BIN=/$objtype/bin
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
../5c/enam.c: ../5c/5.out.h
|
||||
@ { cd ../5c; mk enam.c }
|
||||
|
||||
enam.$O: ../5c/enam.c
|
||||
$CC $CFLAGS ../5c/enam.c
|
||||
|
||||
|
|
|
@ -12,11 +12,13 @@ char thechar = '5';
|
|||
char *thestring = "arm";
|
||||
|
||||
/*
|
||||
* -H0 no header
|
||||
* -H1 -T0x10005000 -R4 is aif for risc os
|
||||
* -H2 -T4128 -R4096 is plan9 format
|
||||
* -H3 -T0xF0000020 -R4 is NetBSD format
|
||||
* -H4 is IXP1200 (raw)
|
||||
* -H5 -T0xC0008010 -R1024 is ipaq
|
||||
* -H6 -R4096 no header with segments padded to pages
|
||||
*/
|
||||
|
||||
static int
|
||||
|
@ -127,6 +129,7 @@ main(int argc, char *argv[])
|
|||
diag("unknown -H option");
|
||||
errorexit();
|
||||
case 0: /* no header */
|
||||
case 6: /* no header, padded segments */
|
||||
HEADR = 0L;
|
||||
if(INITTEXT == -1)
|
||||
INITTEXT = 0;
|
||||
|
@ -1226,6 +1229,8 @@ doprof1(void)
|
|||
s->value = n*4;
|
||||
}
|
||||
|
||||
static int brcond[] = {ABEQ, ABNE, ABCS, ABCC, ABMI, ABPL, ABVS, ABVC, ABHI, ABLS, ABGE, ABLT, ABGT, ABLE};
|
||||
|
||||
void
|
||||
doprof2(void)
|
||||
{
|
||||
|
@ -1280,7 +1285,7 @@ doprof2(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* BL profin, R2
|
||||
* BL profin
|
||||
*/
|
||||
q = prg();
|
||||
q->line = p->line;
|
||||
|
@ -1320,6 +1325,7 @@ doprof2(void)
|
|||
p->link = q;
|
||||
p = q;
|
||||
}
|
||||
|
||||
/*
|
||||
* RET
|
||||
*/
|
||||
|
@ -1327,21 +1333,46 @@ doprof2(void)
|
|||
q->as = ARET;
|
||||
q->from = p->from;
|
||||
q->to = p->to;
|
||||
q->cond = p->cond;
|
||||
q->link = p->link;
|
||||
q->reg = p->reg;
|
||||
p->link = q;
|
||||
|
||||
/*
|
||||
* BL profout
|
||||
*/
|
||||
p->as = ABL;
|
||||
p->from = zprg.from;
|
||||
p->to = zprg.to;
|
||||
p->to.type = D_BRANCH;
|
||||
p->cond = ps4;
|
||||
p->to.sym = s4;
|
||||
if(p->scond != 14) {
|
||||
q = prg();
|
||||
q->as = ABL;
|
||||
q->from = zprg.from;
|
||||
q->to = zprg.to;
|
||||
q->to.type = D_BRANCH;
|
||||
q->cond = ps4;
|
||||
q->to.sym = s4;
|
||||
q->link = p->link;
|
||||
p->link = q;
|
||||
|
||||
p = q;
|
||||
p->as = brcond[p->scond^1]; /* complement */
|
||||
p->scond = 14;
|
||||
p->from = zprg.from;
|
||||
p->to = zprg.to;
|
||||
p->to.type = D_BRANCH;
|
||||
p->cond = q->link->link; /* successor of RET */
|
||||
p->to.offset = q->link->link->pc;
|
||||
|
||||
p = q->link->link;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* BL profout
|
||||
*/
|
||||
p->as = ABL;
|
||||
p->from = zprg.from;
|
||||
p->to = zprg.to;
|
||||
p->to.type = D_BRANCH;
|
||||
p->cond = ps4;
|
||||
p->to.sym = s4;
|
||||
p->scond = 14;
|
||||
|
||||
p = q;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../6c/6.out.h"
|
||||
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Ref Ref;
|
||||
typedef struct Gen Gen;
|
||||
typedef struct Io Io;
|
||||
typedef struct Hist Hist;
|
||||
typedef struct Gen2 Gen2;
|
||||
|
||||
#define MAXALIGN 7
|
||||
#define FPCHIP 1
|
||||
#define NSYMB 500
|
||||
#define BUFSIZ 8192
|
||||
#define HISTSZ 20
|
||||
#define NINCLUDE 10
|
||||
#define NHUNK 10000
|
||||
#define EOF (-1)
|
||||
#define IGN (-2)
|
||||
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
|
||||
#define NHASH 503
|
||||
#define STRINGSZ 200
|
||||
#define NMACRO 10
|
||||
|
||||
struct Sym
|
||||
{
|
||||
Sym* link;
|
||||
Ref* ref;
|
||||
char* macro;
|
||||
vlong value;
|
||||
ushort type;
|
||||
char *name;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
struct Ref
|
||||
{
|
||||
int class;
|
||||
};
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
char* p;
|
||||
int c;
|
||||
} fi;
|
||||
|
||||
struct Io
|
||||
{
|
||||
Io* link;
|
||||
char b[BUFSIZ];
|
||||
char* p;
|
||||
short c;
|
||||
short f;
|
||||
};
|
||||
#define I ((Io*)0)
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Sym* sym;
|
||||
short type;
|
||||
} h[NSYM];
|
||||
|
||||
struct Gen
|
||||
{
|
||||
double dval;
|
||||
char sval[8];
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
short type;
|
||||
short index;
|
||||
short scale;
|
||||
};
|
||||
struct Gen2
|
||||
{
|
||||
Gen from;
|
||||
Gen to;
|
||||
};
|
||||
|
||||
struct Hist
|
||||
{
|
||||
Hist* link;
|
||||
char* name;
|
||||
long line;
|
||||
vlong offset;
|
||||
};
|
||||
#define H ((Hist*)0)
|
||||
|
||||
enum
|
||||
{
|
||||
CLAST,
|
||||
CMACARG,
|
||||
CMACRO,
|
||||
CPREPROC,
|
||||
};
|
||||
|
||||
|
||||
EXTERN char debug[256];
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN char* Dlist[30];
|
||||
EXTERN int nDlist;
|
||||
EXTERN Hist* ehist;
|
||||
EXTERN int newflag;
|
||||
EXTERN Hist* hist;
|
||||
EXTERN char* hunk;
|
||||
EXTERN char* include[NINCLUDE];
|
||||
EXTERN Io* iofree;
|
||||
EXTERN Io* ionext;
|
||||
EXTERN Io* iostack;
|
||||
EXTERN long lineno;
|
||||
EXTERN int nerrors;
|
||||
EXTERN long nhunk;
|
||||
EXTERN int ninclude;
|
||||
EXTERN Gen nullgen;
|
||||
EXTERN char* outfile;
|
||||
EXTERN int pass;
|
||||
EXTERN char* pathname;
|
||||
EXTERN long pc;
|
||||
EXTERN int peekc;
|
||||
EXTERN int sym;
|
||||
EXTERN char symb[NSYMB];
|
||||
EXTERN int thechar;
|
||||
EXTERN char* thestring;
|
||||
EXTERN long thunk;
|
||||
EXTERN Biobuf obuf;
|
||||
|
||||
void* allocn(void*, long, long);
|
||||
void errorexit(void);
|
||||
void pushio(void);
|
||||
void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
void syminit(Sym*);
|
||||
long yylex(void);
|
||||
int getc(void);
|
||||
int getnsc(void);
|
||||
void unget(int);
|
||||
int escchar(int);
|
||||
void cinit(void);
|
||||
void checkscale(int);
|
||||
void pinit(char*);
|
||||
void cclean(void);
|
||||
int isreg(Gen*);
|
||||
void outcode(int, Gen2*);
|
||||
void outhist(void);
|
||||
void zaddr(Gen*, int);
|
||||
void zname(char*, int, int);
|
||||
void ieeedtod(Ieee*, double);
|
||||
int filbuf(void);
|
||||
Sym* getsym(void);
|
||||
void domacro(void);
|
||||
void macund(void);
|
||||
void macdef(void);
|
||||
void macexpand(Sym*, char*);
|
||||
void macinc(void);
|
||||
void macprag(void);
|
||||
void maclin(void);
|
||||
void macif(int);
|
||||
void macend(void);
|
||||
void dodefine(char*);
|
||||
void prfile(long);
|
||||
void linehist(char*, int);
|
||||
void gethunk(void);
|
||||
void yyerror(char*, ...);
|
||||
int yyparse(void);
|
||||
void setinclude(char*);
|
||||
int assemble(char*);
|
||||
|
||||
/*
|
||||
* Posix.c/Inferno.c/Nt.c
|
||||
*/
|
||||
enum /* keep in synch with ../cc/cc.h */
|
||||
{
|
||||
Plan9 = 1<<0,
|
||||
Unix = 1<<1,
|
||||
Windows = 1<<2
|
||||
};
|
||||
int mywait(int*);
|
||||
int mycreat(char*, int);
|
||||
int systemtype(int);
|
||||
int pathchar(void);
|
||||
char* mygetwd(char*, int);
|
||||
int myexec(char*, char*[]);
|
||||
int mydup(int, int);
|
||||
int myfork(void);
|
||||
int mypipe(int*);
|
||||
void* mysbrk(ulong);
|
|
@ -0,0 +1,562 @@
|
|||
%{
|
||||
#include "a.h"
|
||||
%}
|
||||
%union {
|
||||
Sym *sym;
|
||||
vlong lval;
|
||||
double dval;
|
||||
char sval[8];
|
||||
Gen gen;
|
||||
Gen2 gen2;
|
||||
}
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
%left '<' '>'
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
|
||||
%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT
|
||||
%token <lval> LCONST LFP LPC LSB
|
||||
%token <lval> LBREG LLREG LSREG LFREG LMREG LXREG
|
||||
%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 <gen2> nonnon nonrel nonrem rimnon rimrem remrim spec10
|
||||
%type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
|
||||
%%
|
||||
prog:
|
||||
| prog line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
{
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| ';'
|
||||
| inst ';'
|
||||
| error ';'
|
||||
|
||||
inst:
|
||||
LNAME '=' expr
|
||||
{
|
||||
$1->type = LVAR;
|
||||
$1->value = $3;
|
||||
}
|
||||
| LVAR '=' expr
|
||||
{
|
||||
if($1->value != $3)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = $3;
|
||||
}
|
||||
| LTYPE0 nonnon { outcode($1, &$2); }
|
||||
| LTYPE1 nonrem { outcode($1, &$2); }
|
||||
| LTYPE2 rimnon { outcode($1, &$2); }
|
||||
| LTYPE3 rimrem { outcode($1, &$2); }
|
||||
| LTYPE4 remrim { outcode($1, &$2); }
|
||||
| LTYPER nonrel { outcode($1, &$2); }
|
||||
| LTYPED spec1 { outcode($1, &$2); }
|
||||
| LTYPET spec2 { outcode($1, &$2); }
|
||||
| LTYPEC spec3 { outcode($1, &$2); }
|
||||
| LTYPEN spec4 { outcode($1, &$2); }
|
||||
| LTYPES spec5 { outcode($1, &$2); }
|
||||
| LTYPEM spec6 { outcode($1, &$2); }
|
||||
| LTYPEI spec7 { outcode($1, &$2); }
|
||||
| LTYPEXC spec8 { outcode($1, &$2); }
|
||||
| LTYPEX spec9 { outcode($1, &$2); }
|
||||
| LTYPERT spec10 { outcode($1, &$2); }
|
||||
|
||||
nonnon:
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| ','
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
rimrem:
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
remrim:
|
||||
rem ',' rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
rimnon:
|
||||
rim ','
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
nonrem:
|
||||
',' rem
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rem
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
nonrel:
|
||||
',' rel
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rel
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
spec1: /* DATA */
|
||||
nam '/' con ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
}
|
||||
|
||||
spec2: /* TEXT */
|
||||
mem ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| mem ',' con ',' imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.from.scale = $3;
|
||||
$$.to = $5;
|
||||
}
|
||||
|
||||
spec3: /* JMP/CALL */
|
||||
',' rom
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $2;
|
||||
}
|
||||
| rom
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = $1;
|
||||
}
|
||||
|
||||
spec4: /* NOP */
|
||||
nonnon
|
||||
| nonrem
|
||||
|
||||
spec5: /* SHL/SHR */
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| rim ',' rem ':' LLREG
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
if($$.from.index != D_NONE)
|
||||
yyerror("dp shift with lhs index");
|
||||
$$.from.index = $5;
|
||||
}
|
||||
|
||||
spec6: /* MOVW/MOVL */
|
||||
rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
| rim ',' rem ':' LSREG
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
if($$.to.index != D_NONE)
|
||||
yyerror("dp move with lhs index");
|
||||
$$.to.index = $5;
|
||||
}
|
||||
|
||||
spec7:
|
||||
rim ','
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| rim ',' rem
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
}
|
||||
|
||||
spec8: /* CMPPS/CMPPD */
|
||||
reg ',' rem ',' con
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = $3;
|
||||
$$.from.offset = $5;
|
||||
}
|
||||
|
||||
spec9: /* shufl */
|
||||
imm ',' rem ',' reg
|
||||
{
|
||||
$$.from = $3;
|
||||
$$.to = $5;
|
||||
if($1.type != D_CONST)
|
||||
yyerror("illegal constant");
|
||||
$$.to.offset = $1.offset;
|
||||
}
|
||||
|
||||
spec10: /* RET/RETF */
|
||||
{
|
||||
$$.from = nullgen;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
| imm
|
||||
{
|
||||
$$.from = $1;
|
||||
$$.to = nullgen;
|
||||
}
|
||||
|
||||
rem:
|
||||
reg
|
||||
| mem
|
||||
|
||||
rom:
|
||||
rel
|
||||
| nmem
|
||||
| '*' reg
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '*' omem
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| reg
|
||||
| omem
|
||||
|
||||
rim:
|
||||
rem
|
||||
| imm
|
||||
|
||||
rel:
|
||||
con '(' LPC ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1 + pc;
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
reg:
|
||||
LBREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LFREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LLREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LMREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LSP
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_SP;
|
||||
}
|
||||
| LSREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
| LXREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $1;
|
||||
}
|
||||
|
||||
imm:
|
||||
'$' con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_CONST;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| '$' nam
|
||||
{
|
||||
$$ = $2;
|
||||
$$.index = $2.type;
|
||||
$$.type = D_ADDR;
|
||||
/*
|
||||
if($2.type == D_AUTO || $2.type == D_PARAM)
|
||||
yyerror("constant cannot be automatic: %s",
|
||||
$2.sym->name);
|
||||
*/
|
||||
}
|
||||
| '$' LSCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_SCONST;
|
||||
memcpy($$.sval, $2, sizeof($$.sval));
|
||||
}
|
||||
| '$' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = $2;
|
||||
}
|
||||
| '$' '(' LFCONST ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = $3;
|
||||
}
|
||||
| '$' '-' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = -$3;
|
||||
}
|
||||
|
||||
mem:
|
||||
omem
|
||||
| nmem
|
||||
|
||||
omem:
|
||||
con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LLREG ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$3;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LSP ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_SP;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| con '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.offset = $1;
|
||||
$$.index = $3;
|
||||
$$.scale = $5;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| con '(' LLREG ')' '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$3;
|
||||
$$.offset = $1;
|
||||
$$.index = $6;
|
||||
$$.scale = $8;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| '(' LLREG ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$2;
|
||||
}
|
||||
| '(' LSP ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_SP;
|
||||
}
|
||||
| '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_NONE;
|
||||
$$.index = $2;
|
||||
$$.scale = $4;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
| '(' LLREG ')' '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$2;
|
||||
$$.index = $5;
|
||||
$$.scale = $7;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
|
||||
nmem:
|
||||
nam
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| nam '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = $1;
|
||||
$$.index = $3;
|
||||
$$.scale = $5;
|
||||
checkscale($$.scale);
|
||||
}
|
||||
|
||||
nam:
|
||||
LNAME offset '(' pointer ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = $4;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LNAME '<' '>' offset '(' LSB ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_STATIC;
|
||||
$$.sym = $1;
|
||||
$$.offset = $4;
|
||||
}
|
||||
|
||||
offset:
|
||||
{
|
||||
$$ = 0;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
|
||||
pointer:
|
||||
LSB
|
||||
| LSP
|
||||
{
|
||||
$$ = D_AUTO;
|
||||
}
|
||||
| LFP
|
||||
|
||||
con:
|
||||
LCONST
|
||||
| LVAR
|
||||
{
|
||||
$$ = $1->value;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '~' con
|
||||
{
|
||||
$$ = ~$2;
|
||||
}
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
expr:
|
||||
con
|
||||
| expr '+' expr
|
||||
{
|
||||
$$ = $1 + $3;
|
||||
}
|
||||
| expr '-' expr
|
||||
{
|
||||
$$ = $1 - $3;
|
||||
}
|
||||
| expr '*' expr
|
||||
{
|
||||
$$ = $1 * $3;
|
||||
}
|
||||
| expr '/' expr
|
||||
{
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| expr '%' expr
|
||||
{
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| expr '<' '<' expr
|
||||
{
|
||||
$$ = $1 << $4;
|
||||
}
|
||||
| expr '>' '>' expr
|
||||
{
|
||||
$$ = $1 >> $4;
|
||||
}
|
||||
| expr '&' expr
|
||||
{
|
||||
$$ = $1 & $3;
|
||||
}
|
||||
| expr '^' expr
|
||||
{
|
||||
$$ = $1 ^ $3;
|
||||
}
|
||||
| expr '|' expr
|
||||
{
|
||||
$$ = $1 | $3;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=6a
|
||||
OFILES=\
|
||||
y.tab.$O\
|
||||
lex.$O\
|
||||
|
||||
HFILES=\
|
||||
../6c/6.out.h\
|
||||
y.tab.h\
|
||||
a.h\
|
||||
|
||||
YFILES=a.y\
|
||||
|
||||
BIN=/$objtype/bin
|
||||
UPDATE=\
|
||||
mkfile\
|
||||
a.y\
|
||||
lex.c\
|
||||
a.h\
|
||||
${TARG:%=/386/bin/%}\
|
||||
|
||||
< /sys/src/cmd/mkone
|
||||
YFLAGS=-D1 -d
|
||||
|
||||
lex.$O: ../cc/macbody ../cc/lexbody ../cc/compat
|
|
@ -0,0 +1,820 @@
|
|||
#define NSYM 50
|
||||
#define NSNAME 8
|
||||
#define NOPROF (1<<0)
|
||||
#define DUPOK (1<<1)
|
||||
|
||||
/*
|
||||
* amd64
|
||||
*/
|
||||
|
||||
enum as
|
||||
{
|
||||
AXXX,
|
||||
AAAA,
|
||||
AAAD,
|
||||
AAAM,
|
||||
AAAS,
|
||||
AADCB,
|
||||
AADCL,
|
||||
AADCW,
|
||||
AADDB,
|
||||
AADDL,
|
||||
AADDW,
|
||||
AADJSP,
|
||||
AANDB,
|
||||
AANDL,
|
||||
AANDW,
|
||||
AARPL,
|
||||
ABOUNDL,
|
||||
ABOUNDW,
|
||||
ABSFL,
|
||||
ABSFW,
|
||||
ABSRL,
|
||||
ABSRW,
|
||||
ABTL,
|
||||
ABTW,
|
||||
ABTCL,
|
||||
ABTCW,
|
||||
ABTRL,
|
||||
ABTRW,
|
||||
ABTSL,
|
||||
ABTSW,
|
||||
ABYTE,
|
||||
ACALL,
|
||||
ACLC,
|
||||
ACLD,
|
||||
ACLI,
|
||||
ACLTS,
|
||||
ACMC,
|
||||
ACMPB,
|
||||
ACMPL,
|
||||
ACMPW,
|
||||
ACMPSB,
|
||||
ACMPSL,
|
||||
ACMPSW,
|
||||
ADAA,
|
||||
ADAS,
|
||||
ADATA,
|
||||
ADECB,
|
||||
ADECL,
|
||||
ADECQ,
|
||||
ADECW,
|
||||
ADIVB,
|
||||
ADIVL,
|
||||
ADIVW,
|
||||
AENTER,
|
||||
AGLOBL,
|
||||
AGOK,
|
||||
AHISTORY,
|
||||
AHLT,
|
||||
AIDIVB,
|
||||
AIDIVL,
|
||||
AIDIVW,
|
||||
AIMULB,
|
||||
AIMULL,
|
||||
AIMULW,
|
||||
AINB,
|
||||
AINL,
|
||||
AINW,
|
||||
AINCB,
|
||||
AINCL,
|
||||
AINCQ,
|
||||
AINCW,
|
||||
AINSB,
|
||||
AINSL,
|
||||
AINSW,
|
||||
AINT,
|
||||
AINTO,
|
||||
AIRETL,
|
||||
AIRETW,
|
||||
AJCC,
|
||||
AJCS,
|
||||
AJCXZ,
|
||||
AJEQ,
|
||||
AJGE,
|
||||
AJGT,
|
||||
AJHI,
|
||||
AJLE,
|
||||
AJLS,
|
||||
AJLT,
|
||||
AJMI,
|
||||
AJMP,
|
||||
AJNE,
|
||||
AJOC,
|
||||
AJOS,
|
||||
AJPC,
|
||||
AJPL,
|
||||
AJPS,
|
||||
ALAHF,
|
||||
ALARL,
|
||||
ALARW,
|
||||
ALEAL,
|
||||
ALEAW,
|
||||
ALEAVEL,
|
||||
ALEAVEW,
|
||||
ALOCK,
|
||||
ALODSB,
|
||||
ALODSL,
|
||||
ALODSW,
|
||||
ALONG,
|
||||
ALOOP,
|
||||
ALOOPEQ,
|
||||
ALOOPNE,
|
||||
ALSLL,
|
||||
ALSLW,
|
||||
AMOVB,
|
||||
AMOVL,
|
||||
AMOVW,
|
||||
AMOVBLSX,
|
||||
AMOVBLZX,
|
||||
AMOVBQSX,
|
||||
AMOVBQZX,
|
||||
AMOVBWSX,
|
||||
AMOVBWZX,
|
||||
AMOVWLSX,
|
||||
AMOVWLZX,
|
||||
AMOVWQSX,
|
||||
AMOVWQZX,
|
||||
AMOVSB,
|
||||
AMOVSL,
|
||||
AMOVSW,
|
||||
AMULB,
|
||||
AMULL,
|
||||
AMULW,
|
||||
ANAME,
|
||||
ANEGB,
|
||||
ANEGL,
|
||||
ANEGW,
|
||||
ANOP,
|
||||
ANOTB,
|
||||
ANOTL,
|
||||
ANOTW,
|
||||
AORB,
|
||||
AORL,
|
||||
AORW,
|
||||
AOUTB,
|
||||
AOUTL,
|
||||
AOUTW,
|
||||
AOUTSB,
|
||||
AOUTSL,
|
||||
AOUTSW,
|
||||
APOPAL,
|
||||
APOPAW,
|
||||
APOPFL,
|
||||
APOPFW,
|
||||
APOPL,
|
||||
APOPW,
|
||||
APUSHAL,
|
||||
APUSHAW,
|
||||
APUSHFL,
|
||||
APUSHFW,
|
||||
APUSHL,
|
||||
APUSHW,
|
||||
ARCLB,
|
||||
ARCLL,
|
||||
ARCLW,
|
||||
ARCRB,
|
||||
ARCRL,
|
||||
ARCRW,
|
||||
AREP,
|
||||
AREPN,
|
||||
ARET,
|
||||
AROLB,
|
||||
AROLL,
|
||||
AROLW,
|
||||
ARORB,
|
||||
ARORL,
|
||||
ARORW,
|
||||
ASAHF,
|
||||
ASALB,
|
||||
ASALL,
|
||||
ASALW,
|
||||
ASARB,
|
||||
ASARL,
|
||||
ASARW,
|
||||
ASBBB,
|
||||
ASBBL,
|
||||
ASBBW,
|
||||
ASCASB,
|
||||
ASCASL,
|
||||
ASCASW,
|
||||
ASETCC,
|
||||
ASETCS,
|
||||
ASETEQ,
|
||||
ASETGE,
|
||||
ASETGT,
|
||||
ASETHI,
|
||||
ASETLE,
|
||||
ASETLS,
|
||||
ASETLT,
|
||||
ASETMI,
|
||||
ASETNE,
|
||||
ASETOC,
|
||||
ASETOS,
|
||||
ASETPC,
|
||||
ASETPL,
|
||||
ASETPS,
|
||||
ACDQ,
|
||||
ACWD,
|
||||
ASHLB,
|
||||
ASHLL,
|
||||
ASHLW,
|
||||
ASHRB,
|
||||
ASHRL,
|
||||
ASHRW,
|
||||
ASTC,
|
||||
ASTD,
|
||||
ASTI,
|
||||
ASTOSB,
|
||||
ASTOSL,
|
||||
ASTOSW,
|
||||
ASUBB,
|
||||
ASUBL,
|
||||
ASUBW,
|
||||
ASYSCALL,
|
||||
ATESTB,
|
||||
ATESTL,
|
||||
ATESTW,
|
||||
ATEXT,
|
||||
AVERR,
|
||||
AVERW,
|
||||
AWAIT,
|
||||
AWORD,
|
||||
AXCHGB,
|
||||
AXCHGL,
|
||||
AXCHGW,
|
||||
AXLAT,
|
||||
AXORB,
|
||||
AXORL,
|
||||
AXORW,
|
||||
|
||||
AFMOVB,
|
||||
AFMOVBP,
|
||||
AFMOVD,
|
||||
AFMOVDP,
|
||||
AFMOVF,
|
||||
AFMOVFP,
|
||||
AFMOVL,
|
||||
AFMOVLP,
|
||||
AFMOVV,
|
||||
AFMOVVP,
|
||||
AFMOVW,
|
||||
AFMOVWP,
|
||||
AFMOVX,
|
||||
AFMOVXP,
|
||||
|
||||
AFCOMB,
|
||||
AFCOMBP,
|
||||
AFCOMD,
|
||||
AFCOMDP,
|
||||
AFCOMDPP,
|
||||
AFCOMF,
|
||||
AFCOMFP,
|
||||
AFCOML,
|
||||
AFCOMLP,
|
||||
AFCOMW,
|
||||
AFCOMWP,
|
||||
AFUCOM,
|
||||
AFUCOMP,
|
||||
AFUCOMPP,
|
||||
|
||||
AFADDDP,
|
||||
AFADDW,
|
||||
AFADDL,
|
||||
AFADDF,
|
||||
AFADDD,
|
||||
|
||||
AFMULDP,
|
||||
AFMULW,
|
||||
AFMULL,
|
||||
AFMULF,
|
||||
AFMULD,
|
||||
|
||||
AFSUBDP,
|
||||
AFSUBW,
|
||||
AFSUBL,
|
||||
AFSUBF,
|
||||
AFSUBD,
|
||||
|
||||
AFSUBRDP,
|
||||
AFSUBRW,
|
||||
AFSUBRL,
|
||||
AFSUBRF,
|
||||
AFSUBRD,
|
||||
|
||||
AFDIVDP,
|
||||
AFDIVW,
|
||||
AFDIVL,
|
||||
AFDIVF,
|
||||
AFDIVD,
|
||||
|
||||
AFDIVRDP,
|
||||
AFDIVRW,
|
||||
AFDIVRL,
|
||||
AFDIVRF,
|
||||
AFDIVRD,
|
||||
|
||||
AFXCHD,
|
||||
AFFREE,
|
||||
|
||||
AFLDCW,
|
||||
AFLDENV,
|
||||
AFRSTOR,
|
||||
AFSAVE,
|
||||
AFSTCW,
|
||||
AFSTENV,
|
||||
AFSTSW,
|
||||
|
||||
AF2XM1,
|
||||
AFABS,
|
||||
AFCHS,
|
||||
AFCLEX,
|
||||
AFCOS,
|
||||
AFDECSTP,
|
||||
AFINCSTP,
|
||||
AFINIT,
|
||||
AFLD1,
|
||||
AFLDL2E,
|
||||
AFLDL2T,
|
||||
AFLDLG2,
|
||||
AFLDLN2,
|
||||
AFLDPI,
|
||||
AFLDZ,
|
||||
AFNOP,
|
||||
AFPATAN,
|
||||
AFPREM,
|
||||
AFPREM1,
|
||||
AFPTAN,
|
||||
AFRNDINT,
|
||||
AFSCALE,
|
||||
AFSIN,
|
||||
AFSINCOS,
|
||||
AFSQRT,
|
||||
AFTST,
|
||||
AFXAM,
|
||||
AFXTRACT,
|
||||
AFYL2X,
|
||||
AFYL2XP1,
|
||||
|
||||
AEND,
|
||||
|
||||
ADYNT,
|
||||
AINIT,
|
||||
|
||||
ASIGNAME,
|
||||
|
||||
/* extra 32-bit operations */
|
||||
ACMPXCHGB,
|
||||
ACMPXCHGL,
|
||||
ACMPXCHGW,
|
||||
ACMPXCHG8B,
|
||||
ACPUID,
|
||||
AINVD,
|
||||
AINVLPG,
|
||||
ALFENCE,
|
||||
AMFENCE,
|
||||
AMOVNTIL,
|
||||
ARDMSR,
|
||||
ARDPMC,
|
||||
ARDTSC,
|
||||
ARSM,
|
||||
ASFENCE,
|
||||
ASYSRET,
|
||||
AWBINVD,
|
||||
AWRMSR,
|
||||
AXADDB,
|
||||
AXADDL,
|
||||
AXADDW,
|
||||
|
||||
/* conditional move */
|
||||
ACMOVLCC,
|
||||
ACMOVLCS,
|
||||
ACMOVLEQ,
|
||||
ACMOVLGE,
|
||||
ACMOVLGT,
|
||||
ACMOVLHI,
|
||||
ACMOVLLE,
|
||||
ACMOVLLS,
|
||||
ACMOVLLT,
|
||||
ACMOVLMI,
|
||||
ACMOVLNE,
|
||||
ACMOVLOC,
|
||||
ACMOVLOS,
|
||||
ACMOVLPC,
|
||||
ACMOVLPL,
|
||||
ACMOVLPS,
|
||||
ACMOVQCC,
|
||||
ACMOVQCS,
|
||||
ACMOVQEQ,
|
||||
ACMOVQGE,
|
||||
ACMOVQGT,
|
||||
ACMOVQHI,
|
||||
ACMOVQLE,
|
||||
ACMOVQLS,
|
||||
ACMOVQLT,
|
||||
ACMOVQMI,
|
||||
ACMOVQNE,
|
||||
ACMOVQOC,
|
||||
ACMOVQOS,
|
||||
ACMOVQPC,
|
||||
ACMOVQPL,
|
||||
ACMOVQPS,
|
||||
ACMOVWCC,
|
||||
ACMOVWCS,
|
||||
ACMOVWEQ,
|
||||
ACMOVWGE,
|
||||
ACMOVWGT,
|
||||
ACMOVWHI,
|
||||
ACMOVWLE,
|
||||
ACMOVWLS,
|
||||
ACMOVWLT,
|
||||
ACMOVWMI,
|
||||
ACMOVWNE,
|
||||
ACMOVWOC,
|
||||
ACMOVWOS,
|
||||
ACMOVWPC,
|
||||
ACMOVWPL,
|
||||
ACMOVWPS,
|
||||
|
||||
/* 64-bit */
|
||||
AADCQ,
|
||||
AADDQ,
|
||||
AANDQ,
|
||||
ABSFQ,
|
||||
ABSRQ,
|
||||
ABTCQ,
|
||||
ABTQ,
|
||||
ABTRQ,
|
||||
ABTSQ,
|
||||
ACMPQ,
|
||||
ACMPSQ,
|
||||
ACMPXCHGQ,
|
||||
ACQO,
|
||||
ADIVQ,
|
||||
AIDIVQ,
|
||||
AIMULQ,
|
||||
AIRETQ,
|
||||
ALEAQ,
|
||||
ALEAVEQ,
|
||||
ALODSQ,
|
||||
AMOVQ,
|
||||
AMOVLQSX,
|
||||
AMOVLQZX,
|
||||
AMOVNTIQ,
|
||||
AMOVSQ,
|
||||
AMULQ,
|
||||
ANEGQ,
|
||||
ANOTQ,
|
||||
AORQ,
|
||||
APOPFQ,
|
||||
APOPQ,
|
||||
APUSHFQ,
|
||||
APUSHQ,
|
||||
ARCLQ,
|
||||
ARCRQ,
|
||||
AROLQ,
|
||||
ARORQ,
|
||||
AQUAD,
|
||||
ASALQ,
|
||||
ASARQ,
|
||||
ASBBQ,
|
||||
ASCASQ,
|
||||
ASHLQ,
|
||||
ASHRQ,
|
||||
ASTOSQ,
|
||||
ASUBQ,
|
||||
ATESTQ,
|
||||
AXADDQ,
|
||||
AXCHGQ,
|
||||
AXORQ,
|
||||
|
||||
/* media */
|
||||
AADDPD,
|
||||
AADDPS,
|
||||
AADDSD,
|
||||
AADDSS,
|
||||
AANDNPD,
|
||||
AANDNPS,
|
||||
AANDPD,
|
||||
AANDPS,
|
||||
ACMPPD,
|
||||
ACMPPS,
|
||||
ACMPSD,
|
||||
ACMPSS,
|
||||
ACOMISD,
|
||||
ACOMISS,
|
||||
ACVTPD2PL,
|
||||
ACVTPD2PS,
|
||||
ACVTPL2PD,
|
||||
ACVTPL2PS,
|
||||
ACVTPS2PD,
|
||||
ACVTPS2PL,
|
||||
ACVTSD2SL,
|
||||
ACVTSD2SQ,
|
||||
ACVTSD2SS,
|
||||
ACVTSL2SD,
|
||||
ACVTSL2SS,
|
||||
ACVTSQ2SD,
|
||||
ACVTSQ2SS,
|
||||
ACVTSS2SD,
|
||||
ACVTSS2SL,
|
||||
ACVTSS2SQ,
|
||||
ACVTTPD2PL,
|
||||
ACVTTPS2PL,
|
||||
ACVTTSD2SL,
|
||||
ACVTTSD2SQ,
|
||||
ACVTTSS2SL,
|
||||
ACVTTSS2SQ,
|
||||
ADIVPD,
|
||||
ADIVPS,
|
||||
ADIVSD,
|
||||
ADIVSS,
|
||||
AEMMS,
|
||||
AFXRSTOR,
|
||||
AFXRSTOR64,
|
||||
AFXSAVE,
|
||||
AFXSAVE64,
|
||||
ALDMXCSR,
|
||||
AMASKMOVOU,
|
||||
AMASKMOVQ,
|
||||
AMAXPD,
|
||||
AMAXPS,
|
||||
AMAXSD,
|
||||
AMAXSS,
|
||||
AMINPD,
|
||||
AMINPS,
|
||||
AMINSD,
|
||||
AMINSS,
|
||||
AMOVAPD,
|
||||
AMOVAPS,
|
||||
AMOVOU,
|
||||
AMOVHLPS,
|
||||
AMOVHPD,
|
||||
AMOVHPS,
|
||||
AMOVLHPS,
|
||||
AMOVLPD,
|
||||
AMOVLPS,
|
||||
AMOVMSKPD,
|
||||
AMOVMSKPS,
|
||||
AMOVNTO,
|
||||
AMOVNTPD,
|
||||
AMOVNTPS,
|
||||
AMOVNTQ,
|
||||
AMOVO,
|
||||
AMOVQOZX,
|
||||
AMOVSD,
|
||||
AMOVSS,
|
||||
AMOVUPD,
|
||||
AMOVUPS,
|
||||
AMULPD,
|
||||
AMULPS,
|
||||
AMULSD,
|
||||
AMULSS,
|
||||
AORPD,
|
||||
AORPS,
|
||||
APACKSSLW,
|
||||
APACKSSWB,
|
||||
APACKUSWB,
|
||||
APADDB,
|
||||
APADDL,
|
||||
APADDQ,
|
||||
APADDSB,
|
||||
APADDSW,
|
||||
APADDUSB,
|
||||
APADDUSW,
|
||||
APADDW,
|
||||
APANDB,
|
||||
APANDL,
|
||||
APANDSB,
|
||||
APANDSW,
|
||||
APANDUSB,
|
||||
APANDUSW,
|
||||
APANDW,
|
||||
APAND,
|
||||
APANDN,
|
||||
APAVGB,
|
||||
APAVGW,
|
||||
APCMPEQB,
|
||||
APCMPEQL,
|
||||
APCMPEQW,
|
||||
APCMPGTB,
|
||||
APCMPGTL,
|
||||
APCMPGTW,
|
||||
APEXTRW,
|
||||
APFACC,
|
||||
APFADD,
|
||||
APFCMPEQ,
|
||||
APFCMPGE,
|
||||
APFCMPGT,
|
||||
APFMAX,
|
||||
APFMIN,
|
||||
APFMUL,
|
||||
APFNACC,
|
||||
APFPNACC,
|
||||
APFRCP,
|
||||
APFRCPIT1,
|
||||
APFRCPI2T,
|
||||
APFRSQIT1,
|
||||
APFRSQRT,
|
||||
APFSUB,
|
||||
APFSUBR,
|
||||
APINSRW,
|
||||
APMADDWL,
|
||||
APMAXSW,
|
||||
APMAXUB,
|
||||
APMINSW,
|
||||
APMINUB,
|
||||
APMOVMSKB,
|
||||
APMULHRW,
|
||||
APMULHUW,
|
||||
APMULHW,
|
||||
APMULLW,
|
||||
APMULULQ,
|
||||
APOR,
|
||||
APSADBW,
|
||||
APSHUFHW,
|
||||
APSHUFL,
|
||||
APSHUFLW,
|
||||
APSHUFW,
|
||||
APSLLO,
|
||||
APSLLL,
|
||||
APSLLQ,
|
||||
APSLLW,
|
||||
APSRAL,
|
||||
APSRAW,
|
||||
APSRLO,
|
||||
APSRLL,
|
||||
APSRLQ,
|
||||
APSRLW,
|
||||
APSUBB,
|
||||
APSUBL,
|
||||
APSUBQ,
|
||||
APSUBSB,
|
||||
APSUBSW,
|
||||
APSUBUSB,
|
||||
APSUBUSW,
|
||||
APSUBW,
|
||||
APSWAPL,
|
||||
APUNPCKHBW,
|
||||
APUNPCKHLQ,
|
||||
APUNPCKHQDQ,
|
||||
APUNPCKHWL,
|
||||
APUNPCKLBW,
|
||||
APUNPCKLLQ,
|
||||
APUNPCKLQDQ,
|
||||
APUNPCKLWL,
|
||||
APXOR,
|
||||
ARCPPS,
|
||||
ARCPSS,
|
||||
ARSQRTPS,
|
||||
ARSQRTSS,
|
||||
ASHUFPD,
|
||||
ASHUFPS,
|
||||
ASQRTPD,
|
||||
ASQRTPS,
|
||||
ASQRTSD,
|
||||
ASQRTSS,
|
||||
ASTMXCSR,
|
||||
ASUBPD,
|
||||
ASUBPS,
|
||||
ASUBSD,
|
||||
ASUBSS,
|
||||
AUCOMISD,
|
||||
AUCOMISS,
|
||||
AUNPCKHPD,
|
||||
AUNPCKHPS,
|
||||
AUNPCKLPD,
|
||||
AUNPCKLPS,
|
||||
AXORPD,
|
||||
AXORPS,
|
||||
|
||||
APF2IW,
|
||||
APF2IL,
|
||||
API2FW,
|
||||
API2FL,
|
||||
ARETFW,
|
||||
ARETFL,
|
||||
ARETFQ,
|
||||
ASWAPGS,
|
||||
|
||||
AMODE,
|
||||
|
||||
ALAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
D_AL = 0,
|
||||
D_CL,
|
||||
D_DL,
|
||||
D_BL,
|
||||
D_SPB,
|
||||
D_BPB,
|
||||
D_SIB,
|
||||
D_DIB,
|
||||
D_R8B,
|
||||
D_R9B,
|
||||
D_R10B,
|
||||
D_R11B,
|
||||
D_R12B,
|
||||
D_R13B,
|
||||
D_R14B,
|
||||
D_R15B,
|
||||
|
||||
D_AX = 16,
|
||||
D_CX,
|
||||
D_DX,
|
||||
D_BX,
|
||||
D_SP,
|
||||
D_BP,
|
||||
D_SI,
|
||||
D_DI,
|
||||
D_R8,
|
||||
D_R9,
|
||||
D_R10,
|
||||
D_R11,
|
||||
D_R12,
|
||||
D_R13,
|
||||
D_R14,
|
||||
D_R15,
|
||||
|
||||
D_AH = 32,
|
||||
D_CH,
|
||||
D_DH,
|
||||
D_BH,
|
||||
|
||||
D_F0 = 36,
|
||||
|
||||
D_M0 = 44,
|
||||
|
||||
D_X0 = 52,
|
||||
|
||||
D_CS = 68,
|
||||
D_SS,
|
||||
D_DS,
|
||||
D_ES,
|
||||
D_FS,
|
||||
D_GS,
|
||||
|
||||
D_GDTR, /* global descriptor table register */
|
||||
D_IDTR, /* interrupt descriptor table register */
|
||||
D_LDTR, /* local descriptor table register */
|
||||
D_MSW, /* machine status word */
|
||||
D_TASK, /* task register */
|
||||
|
||||
D_CR = 79,
|
||||
D_DR = 95,
|
||||
D_TR = 103,
|
||||
|
||||
D_NONE = 111,
|
||||
|
||||
D_BRANCH = 112,
|
||||
D_EXTERN = 113,
|
||||
D_STATIC = 114,
|
||||
D_AUTO = 115,
|
||||
D_PARAM = 116,
|
||||
D_CONST = 117,
|
||||
D_FCONST = 118,
|
||||
D_SCONST = 119,
|
||||
D_ADDR = 120,
|
||||
|
||||
D_FILE,
|
||||
D_FILE1,
|
||||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
T_FCONST = 1<<3,
|
||||
T_SYM = 1<<4,
|
||||
T_SCONST = 1<<5,
|
||||
T_64 = 1<<6,
|
||||
|
||||
REGARG = D_BP, /* MIGHT CHANGE */
|
||||
REGRET = D_AX,
|
||||
FREGRET = D_X0,
|
||||
REGSP = D_SP,
|
||||
REGTMP = D_DI,
|
||||
REGEXT = D_R15, /* compiler allocates external registers R15 down */
|
||||
FREGMIN = D_X0+5, /* first register variable */
|
||||
FREGEXT = D_X0+7 /* first external register */
|
||||
};
|
||||
|
||||
/*
|
||||
* this is the ranlib header
|
||||
*/
|
||||
#define SYMDEF "__.SYMDEF"
|
||||
|
||||
/*
|
||||
* this is the simulated IEEE floating point
|
||||
*/
|
||||
typedef struct ieee Ieee;
|
||||
struct ieee
|
||||
{
|
||||
long l; /* contains ls-man 0xffffffff */
|
||||
long h; /* contains sign 0x80000000
|
||||
exp 0x7ff00000
|
||||
ms-man 0x000fffff */
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,206 @@
|
|||
#include "gc.h"
|
||||
|
||||
/*
|
||||
* Based on: Granlund, T.; Montgomery, P.L.
|
||||
* "Division by Invariant Integers using Multiplication".
|
||||
* SIGPLAN Notices, Vol. 29, June 1994, page 61.
|
||||
*/
|
||||
|
||||
#define TN(n) ((uvlong)1 << (n))
|
||||
#define T31 TN(31)
|
||||
#define T32 TN(32)
|
||||
|
||||
int
|
||||
multiplier(ulong d, int p, uvlong *mp)
|
||||
{
|
||||
int l;
|
||||
uvlong mlo, mhi, tlo, thi;
|
||||
|
||||
l = topbit(d - 1) + 1;
|
||||
mlo = (((TN(l) - d) << 32) / d) + T32;
|
||||
if(l + p == 64)
|
||||
mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
|
||||
else
|
||||
mhi = (TN(32 + l) + TN(32 + l - p)) / d;
|
||||
/*assert(mlo < mhi);*/
|
||||
while(l > 0) {
|
||||
tlo = mlo >> 1;
|
||||
thi = mhi >> 1;
|
||||
if(tlo == thi)
|
||||
break;
|
||||
mlo = tlo;
|
||||
mhi = thi;
|
||||
l--;
|
||||
}
|
||||
*mp = mhi;
|
||||
return l;
|
||||
}
|
||||
|
||||
int
|
||||
sdiv(ulong d, ulong *mp, int *sp)
|
||||
{
|
||||
int s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32 - 1, &m);
|
||||
*mp = m;
|
||||
*sp = s;
|
||||
if(m >= T31)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udiv(ulong d, ulong *mp, int *sp, int *pp)
|
||||
{
|
||||
int p, s;
|
||||
uvlong m;
|
||||
|
||||
s = multiplier(d, 32, &m);
|
||||
p = 0;
|
||||
if(m >= T32) {
|
||||
while((d & 1) == 0) {
|
||||
d >>= 1;
|
||||
p++;
|
||||
}
|
||||
s = multiplier(d, 32 - p, &m);
|
||||
}
|
||||
*mp = m;
|
||||
*pp = p;
|
||||
if(m >= T32) {
|
||||
/*assert(p == 0);*/
|
||||
*sp = s - 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
*sp = s;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s;
|
||||
ulong m;
|
||||
vlong c;
|
||||
|
||||
c = r->vconst;
|
||||
if(c < 0)
|
||||
c = -c;
|
||||
a = sdiv(c, &m, &s);
|
||||
//print("a=%d i=%ld s=%d m=%lux\n", a, (long)r->vconst, s, m);
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AIMULL, l, Z);
|
||||
gins(AMOVL, l, ax);
|
||||
if(a)
|
||||
gins(AADDL, ax, dx);
|
||||
gins(ASHRL, nodconst(31), ax);
|
||||
gins(ASARL, nodconst(s), dx);
|
||||
gins(AADDL, ax, dx);
|
||||
if(r->vconst < 0)
|
||||
gins(ANEGL, Z, dx);
|
||||
}
|
||||
|
||||
void
|
||||
udivgen(Node *l, Node *r, Node *ax, Node *dx)
|
||||
{
|
||||
int a, s, t;
|
||||
ulong m;
|
||||
Node nod;
|
||||
|
||||
a = udiv(r->vconst, &m, &s, &t);
|
||||
//print("a=%ud i=%ld p=%d s=%d m=%lux\n", a, (long)r->vconst, t, s, m);
|
||||
if(t != 0) {
|
||||
gins(AMOVL, l, ax);
|
||||
gins(ASHRL, nodconst(t), ax);
|
||||
gins(AMOVL, nodconst(m), dx);
|
||||
gins(AMULL, dx, Z);
|
||||
}
|
||||
else if(a) {
|
||||
if(l->op != OREGISTER) {
|
||||
regalloc(&nod, l, Z);
|
||||
gins(AMOVL, l, &nod);
|
||||
l = &nod;
|
||||
}
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
gins(AADDL, l, dx);
|
||||
gins(ARCRL, nodconst(1), dx);
|
||||
if(l == &nod)
|
||||
regfree(l);
|
||||
}
|
||||
else {
|
||||
gins(AMOVL, nodconst(m), ax);
|
||||
gins(AMULL, l, Z);
|
||||
}
|
||||
if(s != 0)
|
||||
gins(ASHRL, nodconst(s), dx);
|
||||
}
|
||||
|
||||
void
|
||||
sext(Node *d, Node *s, Node *l)
|
||||
{
|
||||
if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
|
||||
reg[D_DX]++;
|
||||
gins(ACDQ, Z, Z);
|
||||
}
|
||||
else {
|
||||
regalloc(d, l, Z);
|
||||
gins(AMOVL, s, d);
|
||||
gins(ASARL, nodconst(31), d);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sdiv2(long c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(v > 0) {
|
||||
if(v > 1) {
|
||||
sext(&nod, n, l);
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
regfree(&nod);
|
||||
}
|
||||
else {
|
||||
gins(ACMPL, n, nodconst(0x80000000));
|
||||
gins(ASBBL, nodconst(-1), n);
|
||||
}
|
||||
gins(ASARL, nodconst(v), n);
|
||||
}
|
||||
if(c < 0)
|
||||
gins(ANEGL, Z, n);
|
||||
}
|
||||
|
||||
void
|
||||
smod2(long c, int v, Node *l, Node *n)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(c == 1) {
|
||||
zeroregm(n);
|
||||
return;
|
||||
}
|
||||
|
||||
sext(&nod, n, l);
|
||||
if(v == 0) {
|
||||
zeroregm(n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else if(v > 1) {
|
||||
gins(AANDL, nodconst((1 << v) - 1), &nod);
|
||||
gins(AADDL, &nod, n);
|
||||
gins(AANDL, nodconst((1 << v) - 1), n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
else {
|
||||
gins(AANDL, nodconst(1), n);
|
||||
gins(AXORL, &nod, n);
|
||||
gins(ASUBL, &nod, n);
|
||||
}
|
||||
regfree(&nod);
|
||||
}
|
|
@ -0,0 +1,669 @@
|
|||
char* anames[] =
|
||||
{
|
||||
"XXX",
|
||||
"AAA",
|
||||
"AAD",
|
||||
"AAM",
|
||||
"AAS",
|
||||
"ADCB",
|
||||
"ADCL",
|
||||
"ADCW",
|
||||
"ADDB",
|
||||
"ADDL",
|
||||
"ADDW",
|
||||
"ADJSP",
|
||||
"ANDB",
|
||||
"ANDL",
|
||||
"ANDW",
|
||||
"ARPL",
|
||||
"BOUNDL",
|
||||
"BOUNDW",
|
||||
"BSFL",
|
||||
"BSFW",
|
||||
"BSRL",
|
||||
"BSRW",
|
||||
"BTL",
|
||||
"BTW",
|
||||
"BTCL",
|
||||
"BTCW",
|
||||
"BTRL",
|
||||
"BTRW",
|
||||
"BTSL",
|
||||
"BTSW",
|
||||
"BYTE",
|
||||
"CALL",
|
||||
"CLC",
|
||||
"CLD",
|
||||
"CLI",
|
||||
"CLTS",
|
||||
"CMC",
|
||||
"CMPB",
|
||||
"CMPL",
|
||||
"CMPW",
|
||||
"CMPSB",
|
||||
"CMPSL",
|
||||
"CMPSW",
|
||||
"DAA",
|
||||
"DAS",
|
||||
"DATA",
|
||||
"DECB",
|
||||
"DECL",
|
||||
"DECQ",
|
||||
"DECW",
|
||||
"DIVB",
|
||||
"DIVL",
|
||||
"DIVW",
|
||||
"ENTER",
|
||||
"GLOBL",
|
||||
"GOK",
|
||||
"HISTORY",
|
||||
"HLT",
|
||||
"IDIVB",
|
||||
"IDIVL",
|
||||
"IDIVW",
|
||||
"IMULB",
|
||||
"IMULL",
|
||||
"IMULW",
|
||||
"INB",
|
||||
"INL",
|
||||
"INW",
|
||||
"INCB",
|
||||
"INCL",
|
||||
"INCQ",
|
||||
"INCW",
|
||||
"INSB",
|
||||
"INSL",
|
||||
"INSW",
|
||||
"INT",
|
||||
"INTO",
|
||||
"IRETL",
|
||||
"IRETW",
|
||||
"JCC",
|
||||
"JCS",
|
||||
"JCXZ",
|
||||
"JEQ",
|
||||
"JGE",
|
||||
"JGT",
|
||||
"JHI",
|
||||
"JLE",
|
||||
"JLS",
|
||||
"JLT",
|
||||
"JMI",
|
||||
"JMP",
|
||||
"JNE",
|
||||
"JOC",
|
||||
"JOS",
|
||||
"JPC",
|
||||
"JPL",
|
||||
"JPS",
|
||||
"LAHF",
|
||||
"LARL",
|
||||
"LARW",
|
||||
"LEAL",
|
||||
"LEAW",
|
||||
"LEAVEL",
|
||||
"LEAVEW",
|
||||
"LOCK",
|
||||
"LODSB",
|
||||
"LODSL",
|
||||
"LODSW",
|
||||
"LONG",
|
||||
"LOOP",
|
||||
"LOOPEQ",
|
||||
"LOOPNE",
|
||||
"LSLL",
|
||||
"LSLW",
|
||||
"MOVB",
|
||||
"MOVL",
|
||||
"MOVW",
|
||||
"MOVBLSX",
|
||||
"MOVBLZX",
|
||||
"MOVBQSX",
|
||||
"MOVBQZX",
|
||||
"MOVBWSX",
|
||||
"MOVBWZX",
|
||||
"MOVWLSX",
|
||||
"MOVWLZX",
|
||||
"MOVWQSX",
|
||||
"MOVWQZX",
|
||||
"MOVSB",
|
||||
"MOVSL",
|
||||
"MOVSW",
|
||||
"MULB",
|
||||
"MULL",
|
||||
"MULW",
|
||||
"NAME",
|
||||
"NEGB",
|
||||
"NEGL",
|
||||
"NEGW",
|
||||
"NOP",
|
||||
"NOTB",
|
||||
"NOTL",
|
||||
"NOTW",
|
||||
"ORB",
|
||||
"ORL",
|
||||
"ORW",
|
||||
"OUTB",
|
||||
"OUTL",
|
||||
"OUTW",
|
||||
"OUTSB",
|
||||
"OUTSL",
|
||||
"OUTSW",
|
||||
"POPAL",
|
||||
"POPAW",
|
||||
"POPFL",
|
||||
"POPFW",
|
||||
"POPL",
|
||||
"POPW",
|
||||
"PUSHAL",
|
||||
"PUSHAW",
|
||||
"PUSHFL",
|
||||
"PUSHFW",
|
||||
"PUSHL",
|
||||
"PUSHW",
|
||||
"RCLB",
|
||||
"RCLL",
|
||||
"RCLW",
|
||||
"RCRB",
|
||||
"RCRL",
|
||||
"RCRW",
|
||||
"REP",
|
||||
"REPN",
|
||||
"RET",
|
||||
"ROLB",
|
||||
"ROLL",
|
||||
"ROLW",
|
||||
"RORB",
|
||||
"RORL",
|
||||
"RORW",
|
||||
"SAHF",
|
||||
"SALB",
|
||||
"SALL",
|
||||
"SALW",
|
||||
"SARB",
|
||||
"SARL",
|
||||
"SARW",
|
||||
"SBBB",
|
||||
"SBBL",
|
||||
"SBBW",
|
||||
"SCASB",
|
||||
"SCASL",
|
||||
"SCASW",
|
||||
"SETCC",
|
||||
"SETCS",
|
||||
"SETEQ",
|
||||
"SETGE",
|
||||
"SETGT",
|
||||
"SETHI",
|
||||
"SETLE",
|
||||
"SETLS",
|
||||
"SETLT",
|
||||
"SETMI",
|
||||
"SETNE",
|
||||
"SETOC",
|
||||
"SETOS",
|
||||
"SETPC",
|
||||
"SETPL",
|
||||
"SETPS",
|
||||
"CDQ",
|
||||
"CWD",
|
||||
"SHLB",
|
||||
"SHLL",
|
||||
"SHLW",
|
||||
"SHRB",
|
||||
"SHRL",
|
||||
"SHRW",
|
||||
"STC",
|
||||
"STD",
|
||||
"STI",
|
||||
"STOSB",
|
||||
"STOSL",
|
||||
"STOSW",
|
||||
"SUBB",
|
||||
"SUBL",
|
||||
"SUBW",
|
||||
"SYSCALL",
|
||||
"TESTB",
|
||||
"TESTL",
|
||||
"TESTW",
|
||||
"TEXT",
|
||||
"VERR",
|
||||
"VERW",
|
||||
"WAIT",
|
||||
"WORD",
|
||||
"XCHGB",
|
||||
"XCHGL",
|
||||
"XCHGW",
|
||||
"XLAT",
|
||||
"XORB",
|
||||
"XORL",
|
||||
"XORW",
|
||||
"FMOVB",
|
||||
"FMOVBP",
|
||||
"FMOVD",
|
||||
"FMOVDP",
|
||||
"FMOVF",
|
||||
"FMOVFP",
|
||||
"FMOVL",
|
||||
"FMOVLP",
|
||||
"FMOVV",
|
||||
"FMOVVP",
|
||||
"FMOVW",
|
||||
"FMOVWP",
|
||||
"FMOVX",
|
||||
"FMOVXP",
|
||||
"FCOMB",
|
||||
"FCOMBP",
|
||||
"FCOMD",
|
||||
"FCOMDP",
|
||||
"FCOMDPP",
|
||||
"FCOMF",
|
||||
"FCOMFP",
|
||||
"FCOML",
|
||||
"FCOMLP",
|
||||
"FCOMW",
|
||||
"FCOMWP",
|
||||
"FUCOM",
|
||||
"FUCOMP",
|
||||
"FUCOMPP",
|
||||
"FADDDP",
|
||||
"FADDW",
|
||||
"FADDL",
|
||||
"FADDF",
|
||||
"FADDD",
|
||||
"FMULDP",
|
||||
"FMULW",
|
||||
"FMULL",
|
||||
"FMULF",
|
||||
"FMULD",
|
||||
"FSUBDP",
|
||||
"FSUBW",
|
||||
"FSUBL",
|
||||
"FSUBF",
|
||||
"FSUBD",
|
||||
"FSUBRDP",
|
||||
"FSUBRW",
|
||||
"FSUBRL",
|
||||
"FSUBRF",
|
||||
"FSUBRD",
|
||||
"FDIVDP",
|
||||
"FDIVW",
|
||||
"FDIVL",
|
||||
"FDIVF",
|
||||
"FDIVD",
|
||||
"FDIVRDP",
|
||||
"FDIVRW",
|
||||
"FDIVRL",
|
||||
"FDIVRF",
|
||||
"FDIVRD",
|
||||
"FXCHD",
|
||||
"FFREE",
|
||||
"FLDCW",
|
||||
"FLDENV",
|
||||
"FRSTOR",
|
||||
"FSAVE",
|
||||
"FSTCW",
|
||||
"FSTENV",
|
||||
"FSTSW",
|
||||
"F2XM1",
|
||||
"FABS",
|
||||
"FCHS",
|
||||
"FCLEX",
|
||||
"FCOS",
|
||||
"FDECSTP",
|
||||
"FINCSTP",
|
||||
"FINIT",
|
||||
"FLD1",
|
||||
"FLDL2E",
|
||||
"FLDL2T",
|
||||
"FLDLG2",
|
||||
"FLDLN2",
|
||||
"FLDPI",
|
||||
"FLDZ",
|
||||
"FNOP",
|
||||
"FPATAN",
|
||||
"FPREM",
|
||||
"FPREM1",
|
||||
"FPTAN",
|
||||
"FRNDINT",
|
||||
"FSCALE",
|
||||
"FSIN",
|
||||
"FSINCOS",
|
||||
"FSQRT",
|
||||
"FTST",
|
||||
"FXAM",
|
||||
"FXTRACT",
|
||||
"FYL2X",
|
||||
"FYL2XP1",
|
||||
"END",
|
||||
"DYNT",
|
||||
"INIT",
|
||||
"SIGNAME",
|
||||
"CMPXCHGB",
|
||||
"CMPXCHGL",
|
||||
"CMPXCHGW",
|
||||
"CMPXCHG8B",
|
||||
"CPUID",
|
||||
"INVD",
|
||||
"INVLPG",
|
||||
"LFENCE",
|
||||
"MFENCE",
|
||||
"MOVNTIL",
|
||||
"RDMSR",
|
||||
"RDPMC",
|
||||
"RDTSC",
|
||||
"RSM",
|
||||
"SFENCE",
|
||||
"SYSRET",
|
||||
"WBINVD",
|
||||
"WRMSR",
|
||||
"XADDB",
|
||||
"XADDL",
|
||||
"XADDW",
|
||||
"CMOVLCC",
|
||||
"CMOVLCS",
|
||||
"CMOVLEQ",
|
||||
"CMOVLGE",
|
||||
"CMOVLGT",
|
||||
"CMOVLHI",
|
||||
"CMOVLLE",
|
||||
"CMOVLLS",
|
||||
"CMOVLLT",
|
||||
"CMOVLMI",
|
||||
"CMOVLNE",
|
||||
"CMOVLOC",
|
||||
"CMOVLOS",
|
||||
"CMOVLPC",
|
||||
"CMOVLPL",
|
||||
"CMOVLPS",
|
||||
"CMOVQCC",
|
||||
"CMOVQCS",
|
||||
"CMOVQEQ",
|
||||
"CMOVQGE",
|
||||
"CMOVQGT",
|
||||
"CMOVQHI",
|
||||
"CMOVQLE",
|
||||
"CMOVQLS",
|
||||
"CMOVQLT",
|
||||
"CMOVQMI",
|
||||
"CMOVQNE",
|
||||
"CMOVQOC",
|
||||
"CMOVQOS",
|
||||
"CMOVQPC",
|
||||
"CMOVQPL",
|
||||
"CMOVQPS",
|
||||
"CMOVWCC",
|
||||
"CMOVWCS",
|
||||
"CMOVWEQ",
|
||||
"CMOVWGE",
|
||||
"CMOVWGT",
|
||||
"CMOVWHI",
|
||||
"CMOVWLE",
|
||||
"CMOVWLS",
|
||||
"CMOVWLT",
|
||||
"CMOVWMI",
|
||||
"CMOVWNE",
|
||||
"CMOVWOC",
|
||||
"CMOVWOS",
|
||||
"CMOVWPC",
|
||||
"CMOVWPL",
|
||||
"CMOVWPS",
|
||||
"ADCQ",
|
||||
"ADDQ",
|
||||
"ANDQ",
|
||||
"BSFQ",
|
||||
"BSRQ",
|
||||
"BTCQ",
|
||||
"BTQ",
|
||||
"BTRQ",
|
||||
"BTSQ",
|
||||
"CMPQ",
|
||||
"CMPSQ",
|
||||
"CMPXCHGQ",
|
||||
"CQO",
|
||||
"DIVQ",
|
||||
"IDIVQ",
|
||||
"IMULQ",
|
||||
"IRETQ",
|
||||
"LEAQ",
|
||||
"LEAVEQ",
|
||||
"LODSQ",
|
||||
"MOVQ",
|
||||
"MOVLQSX",
|
||||
"MOVLQZX",
|
||||
"MOVNTIQ",
|
||||
"MOVSQ",
|
||||
"MULQ",
|
||||
"NEGQ",
|
||||
"NOTQ",
|
||||
"ORQ",
|
||||
"POPFQ",
|
||||
"POPQ",
|
||||
"PUSHFQ",
|
||||
"PUSHQ",
|
||||
"RCLQ",
|
||||
"RCRQ",
|
||||
"ROLQ",
|
||||
"RORQ",
|
||||
"QUAD",
|
||||
"SALQ",
|
||||
"SARQ",
|
||||
"SBBQ",
|
||||
"SCASQ",
|
||||
"SHLQ",
|
||||
"SHRQ",
|
||||
"STOSQ",
|
||||
"SUBQ",
|
||||
"TESTQ",
|
||||
"XADDQ",
|
||||
"XCHGQ",
|
||||
"XORQ",
|
||||
"ADDPD",
|
||||
"ADDPS",
|
||||
"ADDSD",
|
||||
"ADDSS",
|
||||
"ANDNPD",
|
||||
"ANDNPS",
|
||||
"ANDPD",
|
||||
"ANDPS",
|
||||
"CMPPD",
|
||||
"CMPPS",
|
||||
"CMPSD",
|
||||
"CMPSS",
|
||||
"COMISD",
|
||||
"COMISS",
|
||||
"CVTPD2PL",
|
||||
"CVTPD2PS",
|
||||
"CVTPL2PD",
|
||||
"CVTPL2PS",
|
||||
"CVTPS2PD",
|
||||
"CVTPS2PL",
|
||||
"CVTSD2SL",
|
||||
"CVTSD2SQ",
|
||||
"CVTSD2SS",
|
||||
"CVTSL2SD",
|
||||
"CVTSL2SS",
|
||||
"CVTSQ2SD",
|
||||
"CVTSQ2SS",
|
||||
"CVTSS2SD",
|
||||
"CVTSS2SL",
|
||||
"CVTSS2SQ",
|
||||
"CVTTPD2PL",
|
||||
"CVTTPS2PL",
|
||||
"CVTTSD2SL",
|
||||
"CVTTSD2SQ",
|
||||
"CVTTSS2SL",
|
||||
"CVTTSS2SQ",
|
||||
"DIVPD",
|
||||
"DIVPS",
|
||||
"DIVSD",
|
||||
"DIVSS",
|
||||
"EMMS",
|
||||
"FXRSTOR",
|
||||
"FXRSTOR64",
|
||||
"FXSAVE",
|
||||
"FXSAVE64",
|
||||
"LDMXCSR",
|
||||
"MASKMOVOU",
|
||||
"MASKMOVQ",
|
||||
"MAXPD",
|
||||
"MAXPS",
|
||||
"MAXSD",
|
||||
"MAXSS",
|
||||
"MINPD",
|
||||
"MINPS",
|
||||
"MINSD",
|
||||
"MINSS",
|
||||
"MOVAPD",
|
||||
"MOVAPS",
|
||||
"MOVOU",
|
||||
"MOVHLPS",
|
||||
"MOVHPD",
|
||||
"MOVHPS",
|
||||
"MOVLHPS",
|
||||
"MOVLPD",
|
||||
"MOVLPS",
|
||||
"MOVMSKPD",
|
||||
"MOVMSKPS",
|
||||
"MOVNTO",
|
||||
"MOVNTPD",
|
||||
"MOVNTPS",
|
||||
"MOVNTQ",
|
||||
"MOVO",
|
||||
"MOVQOZX",
|
||||
"MOVSD",
|
||||
"MOVSS",
|
||||
"MOVUPD",
|
||||
"MOVUPS",
|
||||
"MULPD",
|
||||
"MULPS",
|
||||
"MULSD",
|
||||
"MULSS",
|
||||
"ORPD",
|
||||
"ORPS",
|
||||
"PACKSSLW",
|
||||
"PACKSSWB",
|
||||
"PACKUSWB",
|
||||
"PADDB",
|
||||
"PADDL",
|
||||
"PADDQ",
|
||||
"PADDSB",
|
||||
"PADDSW",
|
||||
"PADDUSB",
|
||||
"PADDUSW",
|
||||
"PADDW",
|
||||
"PANDB",
|
||||
"PANDL",
|
||||
"PANDSB",
|
||||
"PANDSW",
|
||||
"PANDUSB",
|
||||
"PANDUSW",
|
||||
"PANDW",
|
||||
"PAND",
|
||||
"PANDN",
|
||||
"PAVGB",
|
||||
"PAVGW",
|
||||
"PCMPEQB",
|
||||
"PCMPEQL",
|
||||
"PCMPEQW",
|
||||
"PCMPGTB",
|
||||
"PCMPGTL",
|
||||
"PCMPGTW",
|
||||
"PEXTRW",
|
||||
"PFACC",
|
||||
"PFADD",
|
||||
"PFCMPEQ",
|
||||
"PFCMPGE",
|
||||
"PFCMPGT",
|
||||
"PFMAX",
|
||||
"PFMIN",
|
||||
"PFMUL",
|
||||
"PFNACC",
|
||||
"PFPNACC",
|
||||
"PFRCP",
|
||||
"PFRCPIT1",
|
||||
"PFRCPI2T",
|
||||
"PFRSQIT1",
|
||||
"PFRSQRT",
|
||||
"PFSUB",
|
||||
"PFSUBR",
|
||||
"PINSRW",
|
||||
"PMADDWL",
|
||||
"PMAXSW",
|
||||
"PMAXUB",
|
||||
"PMINSW",
|
||||
"PMINUB",
|
||||
"PMOVMSKB",
|
||||
"PMULHRW",
|
||||
"PMULHUW",
|
||||
"PMULHW",
|
||||
"PMULLW",
|
||||
"PMULULQ",
|
||||
"POR",
|
||||
"PSADBW",
|
||||
"PSHUFHW",
|
||||
"PSHUFL",
|
||||
"PSHUFLW",
|
||||
"PSHUFW",
|
||||
"PSLLO",
|
||||
"PSLLL",
|
||||
"PSLLQ",
|
||||
"PSLLW",
|
||||
"PSRAL",
|
||||
"PSRAW",
|
||||
"PSRLO",
|
||||
"PSRLL",
|
||||
"PSRLQ",
|
||||
"PSRLW",
|
||||
"PSUBB",
|
||||
"PSUBL",
|
||||
"PSUBQ",
|
||||
"PSUBSB",
|
||||
"PSUBSW",
|
||||
"PSUBUSB",
|
||||
"PSUBUSW",
|
||||
"PSUBW",
|
||||
"PSWAPL",
|
||||
"PUNPCKHBW",
|
||||
"PUNPCKHLQ",
|
||||
"PUNPCKHQDQ",
|
||||
"PUNPCKHWL",
|
||||
"PUNPCKLBW",
|
||||
"PUNPCKLLQ",
|
||||
"PUNPCKLQDQ",
|
||||
"PUNPCKLWL",
|
||||
"PXOR",
|
||||
"RCPPS",
|
||||
"RCPSS",
|
||||
"RSQRTPS",
|
||||
"RSQRTSS",
|
||||
"SHUFPD",
|
||||
"SHUFPS",
|
||||
"SQRTPD",
|
||||
"SQRTPS",
|
||||
"SQRTSD",
|
||||
"SQRTSS",
|
||||
"STMXCSR",
|
||||
"SUBPD",
|
||||
"SUBPS",
|
||||
"SUBSD",
|
||||
"SUBSS",
|
||||
"UCOMISD",
|
||||
"UCOMISS",
|
||||
"UNPCKHPD",
|
||||
"UNPCKHPS",
|
||||
"UNPCKLPD",
|
||||
"UNPCKLPS",
|
||||
"XORPD",
|
||||
"XORPS",
|
||||
"PF2IW",
|
||||
"PF2IL",
|
||||
"PI2FW",
|
||||
"PI2FL",
|
||||
"RETFW",
|
||||
"RETFL",
|
||||
"RETFQ",
|
||||
"SWAPGS",
|
||||
"MODE",
|
||||
"LAST",
|
||||
};
|
|
@ -0,0 +1,381 @@
|
|||
#include "../cc/cc.h"
|
||||
#include "../6c/6.out.h"
|
||||
|
||||
/*
|
||||
* 6c/amd64
|
||||
* Intel 386 with AMD64 extensions
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 8
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Var Var;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
typedef struct Renv Renv;
|
||||
|
||||
EXTERN struct
|
||||
{
|
||||
Node* regtree;
|
||||
Node* basetree;
|
||||
short scale;
|
||||
short reg;
|
||||
short ptr;
|
||||
} idx;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
vlong offset;
|
||||
double dval;
|
||||
char sval[NSNAME];
|
||||
|
||||
Sym* sym;
|
||||
uchar type;
|
||||
uchar index;
|
||||
uchar etype;
|
||||
uchar scale; /* doubles as width in DATA op */
|
||||
};
|
||||
#define A ((Adr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr to;
|
||||
Prog* link;
|
||||
long lineno;
|
||||
short as;
|
||||
};
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
struct Var
|
||||
{
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
long pc;
|
||||
long rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
long regu;
|
||||
long loop; /* could be shorter */
|
||||
|
||||
Reg* log5;
|
||||
long active;
|
||||
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
struct Renv
|
||||
{
|
||||
int safe;
|
||||
Node base;
|
||||
Node* saved;
|
||||
Node* scope;
|
||||
};
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN long breakpc;
|
||||
EXTERN long nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN Node vconstnode;
|
||||
EXTERN long continpc;
|
||||
EXTERN long curarg;
|
||||
EXTERN long cursafe;
|
||||
EXTERN Prog* firstp;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN long nrathole;
|
||||
EXTERN long nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN long pc;
|
||||
EXTERN Node lregnode;
|
||||
EXTERN Node qregnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN long exregoffset;
|
||||
EXTERN long exfregoffset;
|
||||
EXTERN uchar typechlpv[NTYPE];
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 5
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
|
||||
EXTERN long regbits;
|
||||
EXTERN long exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Var var[NVAR];
|
||||
EXTERN long* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN long maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void noretval(int);
|
||||
void usedset(Node*, int);
|
||||
void xcom(Node*);
|
||||
void indx(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void zeroregm(Node*);
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, long);
|
||||
int needreg(Node*, int);
|
||||
int hardconst(Node*);
|
||||
int immconst(Node*);
|
||||
|
||||
/*
|
||||
* cgen64.c
|
||||
*/
|
||||
int vaddr(Node*, int);
|
||||
void loadpair(Node*, Node*);
|
||||
int cgen64(Node*, Node*);
|
||||
void testv(Node*, int);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(long);
|
||||
Node* nodfconst(double);
|
||||
Node* nodgconst(vlong, Type*);
|
||||
int nodreg(Node*, Node*, int);
|
||||
int isreg(Node*, int);
|
||||
void regret(Node*, Node*);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void naddr(Node*, Adr*);
|
||||
void gcmp(int, Node*, vlong);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Type*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, long);
|
||||
int sconst(Node*);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(const void*, const void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, long, Node*);
|
||||
void casf(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
long outstring(char*, long);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, long, long);
|
||||
void gextern(Sym*, Node*, long, long);
|
||||
void outcode(void);
|
||||
void ieeedtod(Ieee*, double);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
int Pconv(Fmt*);
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Xconv(Fmt*);
|
||||
int Bconv(Fmt*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, long);
|
||||
void synch(Reg*, Bits);
|
||||
ulong allreg(ulong, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
ulong paint2(Reg*, int);
|
||||
void paint3(Reg*, int, long, int);
|
||||
void addreg(Adr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Adr*);
|
||||
int anyvar(Adr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Adr*, Adr*, Reg*, int);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int copyas(Adr*, Adr*);
|
||||
int copyau(Adr*, Adr*);
|
||||
int copysub(Adr*, Adr*, Adr*, int);
|
||||
int copysub1(Prog*, Adr*, Adr*, int);
|
||||
|
||||
long RtoB(int);
|
||||
long FtoB(int);
|
||||
int BtoR(long);
|
||||
int BtoF(long);
|
||||
|
||||
#define D_HI D_NONE
|
||||
#define D_LO D_NONE
|
||||
|
||||
#define isregtype(t) ((t)>= D_AX && (t)<=D_R15)
|
||||
|
||||
/*
|
||||
* bound
|
||||
*/
|
||||
void comtarg(void);
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
int cond(int);
|
||||
int com64(Node*);
|
||||
void com64init(void);
|
||||
void bool64(Node*);
|
||||
long lo64v(Node*);
|
||||
long hi64v(Node*);
|
||||
Node* lo64(Node*);
|
||||
Node* hi64(Node*);
|
||||
|
||||
/*
|
||||
* div/mul
|
||||
*/
|
||||
void sdivgen(Node*, Node*, Node*, Node*);
|
||||
void udivgen(Node*, Node*, Node*, Node*);
|
||||
void sdiv2(long, int, Node*, Node*);
|
||||
void smod2(long, int, Node*, Node*);
|
||||
void mulgen(Type*, Node*, Node*);
|
||||
void genmuladd(Node*, Node*, int, Node*);
|
||||
void shiftit(Type*, Node*, Node*);
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "B" Bits
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
#define D_X7 (D_X0+7)
|
||||
|
||||
void fgopcode(int, Node*, Node*, int, int);
|
|
@ -0,0 +1,337 @@
|
|||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('B', Bconv);
|
||||
fmtinstall('P', Pconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('D', Dconv);
|
||||
fmtinstall('R', Rconv);
|
||||
}
|
||||
|
||||
int
|
||||
Bconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ], ss[STRINGSZ], *s;
|
||||
Bits bits;
|
||||
int i;
|
||||
|
||||
str[0] = 0;
|
||||
bits = va_arg(fp->args, Bits);
|
||||
while(bany(&bits)) {
|
||||
i = bnum(bits);
|
||||
if(str[0])
|
||||
strcat(str, " ");
|
||||
if(var[i].sym == S) {
|
||||
sprint(ss, "$%lld", var[i].offset);
|
||||
s = ss;
|
||||
} else
|
||||
s = var[i].sym->name;
|
||||
if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
|
||||
break;
|
||||
strcat(str, s);
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Prog *p;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
if(p->as == ADATA)
|
||||
sprint(str, " %A %D/%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else if(p->as == ATEXT)
|
||||
sprint(str, " %A %D,%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else
|
||||
sprint(str, " %A %D,%D",
|
||||
p->as, &p->from, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = va_arg(fp->args, int);
|
||||
return fmtstrcpy(fp, anames[i]);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
Adr *a;
|
||||
int i;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%lld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
sprint(str, "%lld(PC)", a->offset-pc);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%s<>+%lld(SB)", a->sym->name,
|
||||
a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym)
|
||||
sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%lld(FP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.17e)", a->dval);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->sval);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
char* regstr[] =
|
||||
{
|
||||
"AL", /* [D_AL] */
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
|
||||
"AX", /* [D_AX] */
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
|
||||
"F0", /* [D_F0] */
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
|
||||
"CS", /* [D_CS] */
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
|
||||
"GDTR", /* [D_GDTR] */
|
||||
"IDTR", /* [D_IDTR] */
|
||||
"LDTR", /* [D_LDTR] */
|
||||
"MSW", /* [D_MSW] */
|
||||
"TASK", /* [D_TASK] */
|
||||
|
||||
"CR0", /* [D_CR] */
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
|
||||
"DR0", /* [D_DR] */
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
|
||||
"TR0", /* [D_TR] */
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
|
||||
"NONE", /* [D_NONE] */
|
||||
};
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char str[20];
|
||||
int r;
|
||||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[30], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sizeof(double); i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
default:
|
||||
if(c < 040 || c >= 0177)
|
||||
break; /* not portable */
|
||||
p[-1] = c;
|
||||
continue;
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#include "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
|
||||
if(n == Z)
|
||||
return 1; /* test */
|
||||
|
||||
switch(n->op) {
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
if(typechl[n->type->etype])
|
||||
return 1;
|
||||
if(typev[n->type->etype]) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OCOM:
|
||||
case ONEG:
|
||||
case OADD:
|
||||
case OAND:
|
||||
case OOR:
|
||||
case OSUB:
|
||||
case OXOR:
|
||||
case OASHL:
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
if(typechlv[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
return 1;
|
||||
|
||||
case OCOND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASOR:
|
||||
case OASXOR:
|
||||
return 1;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
return 1;
|
||||
|
||||
case OPOSTINC:
|
||||
case OPOSTDEC:
|
||||
case OPREINC:
|
||||
case OPREDEC:
|
||||
return 1;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OGT:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
ed - ../6c/6.out.h <<'!'
|
||||
v/^ A/d
|
||||
,s/^ A/ "/
|
||||
g/ .*$/s///
|
||||
,s/,*$/",/
|
||||
1i
|
||||
char* anames[] =
|
||||
{
|
||||
.
|
||||
$a
|
||||
};
|
||||
.
|
||||
w enam.c
|
||||
Q
|
||||
!
|
|
@ -0,0 +1,38 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=6c
|
||||
OFILES=\
|
||||
cgen.$O\
|
||||
enam.$O\
|
||||
list.$O\
|
||||
sgen.$O\
|
||||
swt.$O\
|
||||
txt.$O\
|
||||
reg.$O\
|
||||
peep.$O\
|
||||
pgen.$O\
|
||||
pswt.$O\
|
||||
machcap.$O\
|
||||
div.$O\
|
||||
mul.$O\
|
||||
|
||||
HFILES=\
|
||||
gc.h\
|
||||
6.out.h\
|
||||
../cc/cc.h\
|
||||
|
||||
LIB=../cc/cc.a$O
|
||||
|
||||
BIN=/$objtype/bin
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
$LIB:
|
||||
cd ../cc
|
||||
mk install
|
||||
mk clean
|
||||
|
||||
%.$O: ../cc/%.c
|
||||
$CC $CFLAGS ../cc/$stem.c
|
||||
|
||||
bound.$O: bound.h
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
#include "gc.h"
|
||||
|
||||
typedef struct Malg Malg;
|
||||
typedef struct Mparam Mparam;
|
||||
|
||||
struct Malg
|
||||
{
|
||||
char vals[10];
|
||||
};
|
||||
|
||||
struct Mparam
|
||||
{
|
||||
ulong value;
|
||||
char alg;
|
||||
char neg;
|
||||
char shift;
|
||||
char arg;
|
||||
char off;
|
||||
};
|
||||
|
||||
static Mparam multab[32];
|
||||
static int mulptr;
|
||||
|
||||
static Malg malgs[] =
|
||||
{
|
||||
{0, 100},
|
||||
{-1, 1, 100},
|
||||
{-9, -5, -3, 3, 5, 9, 100},
|
||||
{6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
|
||||
{-8, -4, -2, 2, 4, 8, 100},
|
||||
};
|
||||
|
||||
/*
|
||||
* return position of lowest 1
|
||||
*/
|
||||
int
|
||||
lowbit(ulong v)
|
||||
{
|
||||
int s, i;
|
||||
ulong m;
|
||||
|
||||
s = 0;
|
||||
m = 0xFFFFFFFFUL;
|
||||
for(i = 16; i > 0; i >>= 1) {
|
||||
m >>= i;
|
||||
if((v & m) == 0) {
|
||||
v >>= i;
|
||||
s += i;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
genmuladd(Node *d, Node *s, int m, Node *a)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
nod.op = OINDEX;
|
||||
nod.left = a;
|
||||
nod.right = s;
|
||||
nod.scale = m;
|
||||
nod.type = types[TIND];
|
||||
nod.xoffset = 0;
|
||||
xcom(&nod);
|
||||
gopcode(OADDR, d->type, &nod, d);
|
||||
}
|
||||
|
||||
void
|
||||
mulparam(ulong m, Mparam *mp)
|
||||
{
|
||||
int c, i, j, n, o, q, s;
|
||||
int bc, bi, bn, bo, bq, bs, bt;
|
||||
char *p;
|
||||
long u;
|
||||
ulong t;
|
||||
|
||||
bc = bq = 10;
|
||||
bi = bn = bo = bs = bt = 0;
|
||||
for(i = 0; i < nelem(malgs); i++) {
|
||||
for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
|
||||
for(s = 0; s < 2; s++) {
|
||||
c = 10;
|
||||
q = 10;
|
||||
u = m - o;
|
||||
if(u == 0)
|
||||
continue;
|
||||
if(s) {
|
||||
o = -o;
|
||||
if(o > 0)
|
||||
continue;
|
||||
u = -u;
|
||||
}
|
||||
n = lowbit(u);
|
||||
t = (ulong)u >> n;
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(t == 1) {
|
||||
c = s + 1;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = s + 1;
|
||||
if(n)
|
||||
c++;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
if(s)
|
||||
break;
|
||||
switch(t) {
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
c = 2;
|
||||
if(n)
|
||||
c++;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 3;
|
||||
break;
|
||||
}
|
||||
switch(t) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(s)
|
||||
break;
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(t == 1) {
|
||||
c = 3;
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(c < bc || (c == bc && q > bq)) {
|
||||
bc = c;
|
||||
bi = i;
|
||||
bn = n;
|
||||
bo = o;
|
||||
bq = q;
|
||||
bs = s;
|
||||
bt = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
mp->value = m;
|
||||
if(bc <= 3) {
|
||||
mp->alg = bi;
|
||||
mp->shift = bn;
|
||||
mp->off = bo;
|
||||
mp->neg = bs;
|
||||
mp->arg = bt;
|
||||
}
|
||||
else
|
||||
mp->alg = -1;
|
||||
}
|
||||
|
||||
int
|
||||
m0(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case -2:
|
||||
case 2:
|
||||
return 2;
|
||||
case -3:
|
||||
case 3:
|
||||
return 2;
|
||||
case -4:
|
||||
case 4:
|
||||
return 4;
|
||||
case -5:
|
||||
case 5:
|
||||
return 4;
|
||||
case 6:
|
||||
return 2;
|
||||
case -8:
|
||||
case 8:
|
||||
return 8;
|
||||
case -9:
|
||||
case 9:
|
||||
return 8;
|
||||
case 10:
|
||||
return 4;
|
||||
case 12:
|
||||
return 2;
|
||||
case 15:
|
||||
return 2;
|
||||
case 18:
|
||||
return 8;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 2;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 2;
|
||||
case 36:
|
||||
return 8;
|
||||
case 40:
|
||||
return 4;
|
||||
case 45:
|
||||
return 4;
|
||||
case 72:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m1(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 15:
|
||||
return 4;
|
||||
case 25:
|
||||
return 4;
|
||||
case 27:
|
||||
return 8;
|
||||
case 45:
|
||||
return 8;
|
||||
case 81:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
m2(int a)
|
||||
{
|
||||
switch(a) {
|
||||
case 6:
|
||||
return 2;
|
||||
case 10:
|
||||
return 2;
|
||||
case 12:
|
||||
return 4;
|
||||
case 18:
|
||||
return 2;
|
||||
case 20:
|
||||
return 4;
|
||||
case 24:
|
||||
return 8;
|
||||
case 36:
|
||||
return 4;
|
||||
case 40:
|
||||
return 8;
|
||||
case 72:
|
||||
return 8;
|
||||
}
|
||||
diag(Z, "bad m2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
shiftit(Type *t, Node *s, Node *d)
|
||||
{
|
||||
long c;
|
||||
|
||||
c = (long)s->vconst & 31;
|
||||
switch(c) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
gopcode(OADD, t, d, d);
|
||||
break;
|
||||
default:
|
||||
gopcode(OASHL, t, s, d);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mulgen1(ulong v, Node *n)
|
||||
{
|
||||
int i, o;
|
||||
Mparam *p;
|
||||
Node nod, nods;
|
||||
|
||||
for(i = 0; i < nelem(multab); i++) {
|
||||
p = &multab[i];
|
||||
if(p->value == v)
|
||||
goto found;
|
||||
}
|
||||
|
||||
p = &multab[mulptr];
|
||||
if(++mulptr == nelem(multab))
|
||||
mulptr = 0;
|
||||
|
||||
mulparam(v, p);
|
||||
|
||||
found:
|
||||
// print("v=%.lx a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
|
||||
if(p->alg < 0)
|
||||
return 0;
|
||||
|
||||
nods = *nodconst(p->shift);
|
||||
|
||||
o = OADD;
|
||||
if(p->alg > 0) {
|
||||
regalloc(&nod, n, Z);
|
||||
if(p->off < 0)
|
||||
o = OSUB;
|
||||
}
|
||||
|
||||
switch(p->alg) {
|
||||
case 0:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
case 15:
|
||||
case 25:
|
||||
case 27:
|
||||
case 45:
|
||||
case 81:
|
||||
genmuladd(n, n, m1(p->arg), n);
|
||||
/* fall thru */
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(n, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg == 1)
|
||||
gins(ANEGL, Z, n);
|
||||
break;
|
||||
case 1:
|
||||
switch(p->arg) {
|
||||
case 1:
|
||||
gmove(n, &nod);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 9:
|
||||
genmuladd(&nod, n, m0(p->arg), n);
|
||||
shiftit(n->type, &nods, &nod);
|
||||
break;
|
||||
default:
|
||||
goto bad;
|
||||
}
|
||||
if(p->neg)
|
||||
gopcode(o, n->type, &nod, n);
|
||||
else {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
case 3:
|
||||
genmuladd(&nod, n, m0(p->off), n);
|
||||
shiftit(n->type, &nods, n);
|
||||
genmuladd(n, &nod, m2(p->off), n);
|
||||
break;
|
||||
case 4:
|
||||
genmuladd(&nod, n, m0(p->off), nodconst(0));
|
||||
shiftit(n->type, &nods, n);
|
||||
goto comop;
|
||||
default:
|
||||
diag(Z, "bad mul alg");
|
||||
break;
|
||||
comop:
|
||||
if(p->neg) {
|
||||
gopcode(o, n->type, n, &nod);
|
||||
gmove(&nod, n);
|
||||
}
|
||||
else
|
||||
gopcode(o, n->type, &nod, n);
|
||||
}
|
||||
|
||||
if(p->alg > 0)
|
||||
regfree(&nod);
|
||||
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
diag(Z, "mulgen botch");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mulgen(Type *t, Node *r, Node *n)
|
||||
{
|
||||
if(!mulgen1(r->vconst, n))
|
||||
gopcode(OMUL, t, r, n);
|
||||
}
|
|
@ -0,0 +1,846 @@
|
|||
#include "gc.h"
|
||||
|
||||
static int
|
||||
needc(Prog *p)
|
||||
{
|
||||
while(p != P) {
|
||||
switch(p->as) {
|
||||
case AADCL:
|
||||
case AADCQ:
|
||||
case ASBBL:
|
||||
case ASBBQ:
|
||||
case ARCRL:
|
||||
case ARCRQ:
|
||||
return 1;
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case ACALL:
|
||||
return 0;
|
||||
default:
|
||||
if(p->to.type == D_BRANCH)
|
||||
return 0;
|
||||
}
|
||||
p = p->link;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Reg*
|
||||
rnops(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
Reg *r1;
|
||||
|
||||
if(r != R)
|
||||
for(;;){
|
||||
p = r->prog;
|
||||
if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
|
||||
break;
|
||||
r1 = uniqs(r);
|
||||
if(r1 == R)
|
||||
break;
|
||||
r = r1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
peep(void)
|
||||
{
|
||||
Reg *r, *r1, *r2;
|
||||
Prog *p, *p1;
|
||||
int t;
|
||||
|
||||
/*
|
||||
* complete R structure
|
||||
*/
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r1) {
|
||||
r1 = r->link;
|
||||
if(r1 == R)
|
||||
break;
|
||||
p = r->prog->link;
|
||||
while(p != r1->prog)
|
||||
switch(p->as) {
|
||||
default:
|
||||
r2 = rega();
|
||||
r->link = r2;
|
||||
r2->link = r1;
|
||||
|
||||
r2->prog = p;
|
||||
r2->p1 = r;
|
||||
r->s1 = r2;
|
||||
r2->s1 = r1;
|
||||
r1->p1 = r2;
|
||||
|
||||
r = r2;
|
||||
t++;
|
||||
|
||||
case ADATA:
|
||||
case AGLOBL:
|
||||
case ANAME:
|
||||
case ASIGNAME:
|
||||
p = p->link;
|
||||
}
|
||||
}
|
||||
|
||||
pc = 0; /* speculating it won't kill */
|
||||
|
||||
loop1:
|
||||
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
if(regtyp(&p->to))
|
||||
if(regtyp(&p->from)) {
|
||||
if(copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
} else
|
||||
if(subprop(r) && copyprop(r)) {
|
||||
excise(r);
|
||||
t++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBLZX:
|
||||
case AMOVWLZX:
|
||||
case AMOVBLSX:
|
||||
case AMOVWLSX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVL;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
if(regtyp(&p->to)) {
|
||||
r1 = rnops(uniqs(r));
|
||||
if(r1 != R) {
|
||||
p1 = r1->prog;
|
||||
if(p->as == p1->as && p->to.type == p1->from.type){
|
||||
p1->as = AMOVQ;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == AADDQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == AADDL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
if(p->from.type != D_CONST || needc(p->link))
|
||||
break;
|
||||
if(p->from.offset == -1) {
|
||||
if(p->as == ASUBQ)
|
||||
p->as = AINCQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = AINCL;
|
||||
else
|
||||
p->as = AINCW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
else if(p->from.offset == 1){
|
||||
if(p->as == ASUBQ)
|
||||
p->as = ADECQ;
|
||||
else if(p->as == ASUBL)
|
||||
p->as = ADECL;
|
||||
else
|
||||
p->as = ADECW;
|
||||
p->from = zprog.from;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(t)
|
||||
goto loop1;
|
||||
}
|
||||
|
||||
void
|
||||
excise(Reg *r)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = r->prog;
|
||||
p->as = ANOP;
|
||||
p->from = zprog.from;
|
||||
p->to = zprog.to;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqp(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->p1;
|
||||
if(r1 == R) {
|
||||
r1 = r->p2;
|
||||
if(r1 == R || r1->p2link != R)
|
||||
return R;
|
||||
} else
|
||||
if(r->p2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
Reg*
|
||||
uniqs(Reg *r)
|
||||
{
|
||||
Reg *r1;
|
||||
|
||||
r1 = r->s1;
|
||||
if(r1 == R) {
|
||||
r1 = r->s2;
|
||||
if(r1 == R)
|
||||
return R;
|
||||
} else
|
||||
if(r->s2 != R)
|
||||
return R;
|
||||
return r1;
|
||||
}
|
||||
|
||||
int
|
||||
regtyp(Adr *a)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = a->type;
|
||||
if(t >= D_AX && t <= D_R15)
|
||||
return 1;
|
||||
if(t >= D_X0 && t <= D_X0+15)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the idea is to substitute
|
||||
* one register for another
|
||||
* from one MOV to another
|
||||
* MOV a, R0
|
||||
* ADD b, R0 / no use of R1
|
||||
* MOV R0, R1
|
||||
* would be converted to
|
||||
* MOV a, R1
|
||||
* ADD b, R1
|
||||
* MOV R1, R0
|
||||
* hopefully, then the former or latter MOV
|
||||
* will be eliminated by copy propagation.
|
||||
*/
|
||||
int
|
||||
subprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Adr *v1, *v2;
|
||||
Reg *r;
|
||||
int t;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
if(!regtyp(v1))
|
||||
return 0;
|
||||
v2 = &p->to;
|
||||
if(!regtyp(v2))
|
||||
return 0;
|
||||
for(r=uniqp(r0); r!=R; r=uniqp(r)) {
|
||||
if(uniqs(r) == R)
|
||||
break;
|
||||
p = r->prog;
|
||||
switch(p->as) {
|
||||
case ACALL:
|
||||
return 0;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE)
|
||||
break;
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
|
||||
case AREP:
|
||||
case AREPN:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
return 0;
|
||||
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
if(p->to.type == v1->type)
|
||||
goto gotit;
|
||||
break;
|
||||
}
|
||||
if(copyau(&p->from, v2) ||
|
||||
copyau(&p->to, v2))
|
||||
break;
|
||||
if(copysub(&p->from, v1, v2, 0) ||
|
||||
copysub(&p->to, v1, v2, 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
gotit:
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P']) {
|
||||
print("gotit: %D->%D\n%P", v1, v2, r->prog);
|
||||
if(p->from.type == v2->type)
|
||||
print(" excise");
|
||||
print("\n");
|
||||
}
|
||||
for(r=uniqs(r); r!=r0; r=uniqs(r)) {
|
||||
p = r->prog;
|
||||
copysub(&p->from, v1, v2, 1);
|
||||
copysub(&p->to, v1, v2, 1);
|
||||
if(debug['P'])
|
||||
print("%P\n", r->prog);
|
||||
}
|
||||
t = v1->type;
|
||||
v1->type = v2->type;
|
||||
v2->type = t;
|
||||
if(debug['P'])
|
||||
print("%P last\n", r->prog);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The idea is to remove redundant copies.
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* use v2 return fail
|
||||
* -----------------
|
||||
* v1->v2 F=0
|
||||
* (use v2 s/v2/v1/)*
|
||||
* set v1 F=1
|
||||
* set v2 return success
|
||||
*/
|
||||
int
|
||||
copyprop(Reg *r0)
|
||||
{
|
||||
Prog *p;
|
||||
Adr *v1, *v2;
|
||||
Reg *r;
|
||||
|
||||
p = r0->prog;
|
||||
v1 = &p->from;
|
||||
v2 = &p->to;
|
||||
if(copyas(v1, v2))
|
||||
return 1;
|
||||
for(r=firstr; r!=R; r=r->link)
|
||||
r->active = 0;
|
||||
return copy1(v1, v2, r0->s1, 0);
|
||||
}
|
||||
|
||||
int
|
||||
copy1(Adr *v1, Adr *v2, Reg *r, int f)
|
||||
{
|
||||
int t;
|
||||
Prog *p;
|
||||
|
||||
if(r->active) {
|
||||
if(debug['P'])
|
||||
print("act set; return 1\n");
|
||||
return 1;
|
||||
}
|
||||
r->active = 1;
|
||||
if(debug['P'])
|
||||
print("copy %D->%D f=%d\n", v1, v2, f);
|
||||
for(; r != R; r = r->s1) {
|
||||
p = r->prog;
|
||||
if(debug['P'])
|
||||
print("%P", p);
|
||||
if(!f && uniqp(r) == R) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; merge; f=%d", f);
|
||||
}
|
||||
t = copyu(p, v2, A);
|
||||
switch(t) {
|
||||
case 2: /* rar, cant split */
|
||||
if(debug['P'])
|
||||
print("; %D rar; return 0\n", v2);
|
||||
return 0;
|
||||
|
||||
case 3: /* set */
|
||||
if(debug['P'])
|
||||
print("; %D set; return 1\n", v2);
|
||||
return 1;
|
||||
|
||||
case 1: /* used, substitute */
|
||||
case 4: /* use and set */
|
||||
if(f) {
|
||||
if(!debug['P'])
|
||||
return 0;
|
||||
if(t == 4)
|
||||
print("; %D used+set and f=%d; return 0\n", v2, f);
|
||||
else
|
||||
print("; %D used and f=%d; return 0\n", v2, f);
|
||||
return 0;
|
||||
}
|
||||
if(copyu(p, v2, v1)) {
|
||||
if(debug['P'])
|
||||
print("; sub fail; return 0\n");
|
||||
return 0;
|
||||
}
|
||||
if(debug['P'])
|
||||
print("; sub %D/%D", v2, v1);
|
||||
if(t == 4) {
|
||||
if(debug['P'])
|
||||
print("; %D used+set; return 1\n", v2);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!f) {
|
||||
t = copyu(p, v1, A);
|
||||
if(!f && (t == 2 || t == 3 || t == 4)) {
|
||||
f = 1;
|
||||
if(debug['P'])
|
||||
print("; %D set and !f; f=%d", v1, f);
|
||||
}
|
||||
}
|
||||
if(debug['P'])
|
||||
print("\n");
|
||||
if(r->s2)
|
||||
if(!copy1(v1, v2, r->s2, f))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* return
|
||||
* 1 if v only used (and substitute),
|
||||
* 2 if read-alter-rewrite
|
||||
* 3 if set
|
||||
* 4 if set and used
|
||||
* 0 otherwise (not touched)
|
||||
*/
|
||||
int
|
||||
copyu(Prog *p, Adr *v, Adr *s)
|
||||
{
|
||||
|
||||
switch(p->as) {
|
||||
|
||||
default:
|
||||
if(debug['P'])
|
||||
print("unknown op %A\n", p->as);
|
||||
/* SBBL; ADCL; FLD1; SAHF */
|
||||
return 2;
|
||||
|
||||
|
||||
case ANEGB:
|
||||
case ANEGW:
|
||||
case ANEGL:
|
||||
case ANEGQ:
|
||||
case ANOTB:
|
||||
case ANOTW:
|
||||
case ANOTL:
|
||||
case ANOTQ:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
break;
|
||||
|
||||
case ALEAL: /* lhs addr, rhs store */
|
||||
case ALEAQ:
|
||||
if(copyas(&p->from, v))
|
||||
return 2;
|
||||
|
||||
|
||||
case ANOP: /* rhs store */
|
||||
case AMOVL:
|
||||
case AMOVQ:
|
||||
case AMOVBLSX:
|
||||
case AMOVBLZX:
|
||||
case AMOVBQSX:
|
||||
case AMOVBQZX:
|
||||
case AMOVLQSX:
|
||||
case AMOVLQZX:
|
||||
case AMOVWLSX:
|
||||
case AMOVWLZX:
|
||||
case AMOVWQSX:
|
||||
case AMOVWQZX:
|
||||
|
||||
case AMOVSS:
|
||||
case AMOVSD:
|
||||
case ACVTSD2SL:
|
||||
case ACVTSD2SQ:
|
||||
case ACVTSD2SS:
|
||||
case ACVTSL2SD:
|
||||
case ACVTSL2SS:
|
||||
case ACVTSQ2SD:
|
||||
case ACVTSQ2SS:
|
||||
case ACVTSS2SD:
|
||||
case ACVTSS2SL:
|
||||
case ACVTSS2SQ:
|
||||
case ACVTTSD2SL:
|
||||
case ACVTTSD2SQ:
|
||||
case ACVTTSS2SL:
|
||||
case ACVTTSS2SQ:
|
||||
if(copyas(&p->to, v)) {
|
||||
if(s != A)
|
||||
return copysub(&p->from, v, s, 1);
|
||||
if(copyau(&p->from, v))
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
goto caseread;
|
||||
|
||||
case AROLB:
|
||||
case AROLL:
|
||||
case AROLQ:
|
||||
case AROLW:
|
||||
case ARORB:
|
||||
case ARORL:
|
||||
case ARORQ:
|
||||
case ARORW:
|
||||
case ASALB:
|
||||
case ASALL:
|
||||
case ASALQ:
|
||||
case ASALW:
|
||||
case ASARB:
|
||||
case ASARL:
|
||||
case ASARQ:
|
||||
case ASARW:
|
||||
case ASHLB:
|
||||
case ASHLL:
|
||||
case ASHLQ:
|
||||
case ASHLW:
|
||||
case ASHRB:
|
||||
case ASHRL:
|
||||
case ASHRQ:
|
||||
case ASHRW:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
if(copyas(&p->from, v))
|
||||
if(p->from.type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AADDB: /* rhs rar */
|
||||
case AADDL:
|
||||
case AADDQ:
|
||||
case AADDW:
|
||||
case AANDB:
|
||||
case AANDL:
|
||||
case AANDQ:
|
||||
case AANDW:
|
||||
case ADECL:
|
||||
case ADECQ:
|
||||
case ADECW:
|
||||
case AINCL:
|
||||
case AINCQ:
|
||||
case AINCW:
|
||||
case ASUBB:
|
||||
case ASUBL:
|
||||
case ASUBQ:
|
||||
case ASUBW:
|
||||
case AORB:
|
||||
case AORL:
|
||||
case AORQ:
|
||||
case AORW:
|
||||
case AXORB:
|
||||
case AXORL:
|
||||
case AXORQ:
|
||||
case AXORW:
|
||||
case AMOVB:
|
||||
case AMOVW:
|
||||
|
||||
case AADDSD:
|
||||
case AADDSS:
|
||||
case ACMPSD:
|
||||
case ACMPSS:
|
||||
case ADIVSD:
|
||||
case ADIVSS:
|
||||
case AMAXSD:
|
||||
case AMAXSS:
|
||||
case AMINSD:
|
||||
case AMINSS:
|
||||
case AMULSD:
|
||||
case AMULSS:
|
||||
case ARCPSS:
|
||||
case ARSQRTSS:
|
||||
case ASQRTSD:
|
||||
case ASQRTSS:
|
||||
case ASUBSD:
|
||||
case ASUBSS:
|
||||
case AXORPD:
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ACMPL: /* read only */
|
||||
case ACMPW:
|
||||
case ACMPB:
|
||||
case ACMPQ:
|
||||
|
||||
case ACOMISD:
|
||||
case ACOMISS:
|
||||
case AUCOMISD:
|
||||
case AUCOMISS:
|
||||
caseread:
|
||||
if(s != A) {
|
||||
if(copysub(&p->from, v, s, 1))
|
||||
return 1;
|
||||
return copysub(&p->to, v, s, 1);
|
||||
}
|
||||
if(copyau(&p->from, v))
|
||||
return 1;
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case AJGE: /* no reference */
|
||||
case AJNE:
|
||||
case AJLE:
|
||||
case AJEQ:
|
||||
case AJHI:
|
||||
case AJLS:
|
||||
case AJMI:
|
||||
case AJPL:
|
||||
case AJGT:
|
||||
case AJLT:
|
||||
case AJCC:
|
||||
case AJCS:
|
||||
|
||||
case AADJSP:
|
||||
case AWAIT:
|
||||
case ACLD:
|
||||
break;
|
||||
|
||||
case AIMULL:
|
||||
case AIMULQ:
|
||||
case AIMULW:
|
||||
if(p->to.type != D_NONE) {
|
||||
if(copyas(&p->to, v))
|
||||
return 2;
|
||||
goto caseread;
|
||||
}
|
||||
|
||||
case ADIVB:
|
||||
case ADIVL:
|
||||
case ADIVQ:
|
||||
case ADIVW:
|
||||
case AIDIVB:
|
||||
case AIDIVL:
|
||||
case AIDIVQ:
|
||||
case AIDIVW:
|
||||
case AIMULB:
|
||||
case AMULB:
|
||||
case AMULL:
|
||||
case AMULQ:
|
||||
case AMULW:
|
||||
|
||||
case ACWD:
|
||||
case ACDQ:
|
||||
case ACQO:
|
||||
if(v->type == D_AX || v->type == D_DX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSL:
|
||||
case AMOVSQ:
|
||||
case AREP:
|
||||
case AREPN:
|
||||
if(v->type == D_CX || v->type == D_DI || v->type == D_SI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AJMP: /* funny */
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case ARET: /* funny */
|
||||
if(v->type == REGRET || v->type == FREGRET)
|
||||
return 2;
|
||||
if(s != A)
|
||||
return 1;
|
||||
return 3;
|
||||
|
||||
case ACALL: /* funny */
|
||||
if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
|
||||
return 2;
|
||||
if(REGARG && v->type == REGARG)
|
||||
return 2;
|
||||
|
||||
if(s != A) {
|
||||
if(copysub(&p->to, v, s, 1))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
if(copyau(&p->to, v))
|
||||
return 4;
|
||||
return 3;
|
||||
|
||||
case ATEXT: /* funny */
|
||||
if(REGARG && v->type == REGARG)
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* direct reference,
|
||||
* could be set/use depending on
|
||||
* semantics
|
||||
*/
|
||||
int
|
||||
copyas(Adr *a, Adr *v)
|
||||
{
|
||||
if(a->type != v->type)
|
||||
return 0;
|
||||
if(regtyp(v))
|
||||
return 1;
|
||||
if(v->type == D_AUTO || v->type == D_PARAM)
|
||||
if(v->offset == a->offset)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* either direct or indirect
|
||||
*/
|
||||
int
|
||||
copyau(Adr *a, Adr *v)
|
||||
{
|
||||
|
||||
if(copyas(a, v))
|
||||
return 1;
|
||||
if(regtyp(v)) {
|
||||
if(a->type-D_INDIR == v->type)
|
||||
return 1;
|
||||
if(a->index == v->type)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* substitute s for v in a
|
||||
* return failure to substitute
|
||||
*/
|
||||
int
|
||||
copysub(Adr *a, Adr *v, Adr *s, int f)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(copyas(a, v)) {
|
||||
t = s->type;
|
||||
if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
|
||||
if(f)
|
||||
a->type = t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(regtyp(v)) {
|
||||
t = v->type;
|
||||
if(a->type == t+D_INDIR) {
|
||||
if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
|
||||
return 1; /* can't use BP-base with index */
|
||||
if(f)
|
||||
a->type = s->type+D_INDIR;
|
||||
// return 0;
|
||||
}
|
||||
if(a->index == t) {
|
||||
if(f)
|
||||
a->index = s->type;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,435 @@
|
|||
#include "gc.h"
|
||||
|
||||
void
|
||||
noretval(int n)
|
||||
{
|
||||
|
||||
if(n & 1) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = REGRET;
|
||||
}
|
||||
if(n & 2) {
|
||||
gins(ANOP, Z, Z);
|
||||
p->to.type = FREGRET;
|
||||
}
|
||||
}
|
||||
|
||||
/* welcome to commute */
|
||||
static void
|
||||
commute(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(r->complex > l->complex) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indexshift(Node *n)
|
||||
{
|
||||
int g;
|
||||
|
||||
if(!typechlpv[n->type->etype])
|
||||
return;
|
||||
simplifyshift(n);
|
||||
if(n->op == OASHL && n->right->op == OCONST){
|
||||
g = vconst(n->right);
|
||||
if(g >= 0 && g <= 3)
|
||||
n->addable = 7;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate addressability as follows
|
||||
* NAME ==> 10/11 name+value(SB/SP)
|
||||
* REGISTER ==> 12 register
|
||||
* CONST ==> 20 $value
|
||||
* *(20) ==> 21 value
|
||||
* &(10) ==> 13 $name+value(SB)
|
||||
* &(11) ==> 1 $name+value(SP)
|
||||
* (13) + (20) ==> 13 fold constants
|
||||
* (1) + (20) ==> 1 fold constants
|
||||
* *(13) ==> 10 back to name
|
||||
* *(1) ==> 11 back to name
|
||||
*
|
||||
* (20) * (X) ==> 7 multiplier in indexing
|
||||
* (X,7) + (13,1) ==> 8 adder in indexing (addresses)
|
||||
* (8) ==> &9(OINDEX) index, almost addressable
|
||||
*
|
||||
* calculate complexity (number of registers)
|
||||
*/
|
||||
void
|
||||
xcom(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
int g;
|
||||
|
||||
if(n == Z)
|
||||
return;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
n->complex = 0;
|
||||
n->addable = 0;
|
||||
switch(n->op) {
|
||||
case OCONST:
|
||||
n->addable = 20;
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
n->addable = 10;
|
||||
if(n->class == CPARAM || n->class == CAUTO)
|
||||
n->addable = 11;
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OINDREG:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
xcom(l);
|
||||
if(l->addable == 10)
|
||||
n->addable = 13;
|
||||
else
|
||||
if(l->addable == 11)
|
||||
n->addable = 1;
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(n->type->etype != TIND)
|
||||
break;
|
||||
|
||||
switch(r->addable) {
|
||||
case 20:
|
||||
switch(l->addable) {
|
||||
case 1:
|
||||
case 13:
|
||||
commadd:
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
l = new(0, Z, Z);
|
||||
*l = *(n->left);
|
||||
l->xoffset += r->vconst;
|
||||
n->left = l;
|
||||
r = n->right;
|
||||
goto brk;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 13:
|
||||
case 10:
|
||||
case 11:
|
||||
/* l is the base, r is the index */
|
||||
if(l->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
switch(r->addable) {
|
||||
case 13:
|
||||
case 1:
|
||||
r = n->left;
|
||||
l = n->right;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
goto commadd;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13:
|
||||
case 1:
|
||||
case 10:
|
||||
case 11:
|
||||
/* r is the base, l is the index */
|
||||
if(r->addable != 20)
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
if(n->addable == 8 && !side(n)) {
|
||||
indx(n);
|
||||
l = new1(OINDEX, idx.basetree, idx.regtree);
|
||||
l->scale = idx.scale;
|
||||
l->addable = 9;
|
||||
l->complex = l->right->complex;
|
||||
l->type = l->left->type;
|
||||
n->op = OADDR;
|
||||
n->left = l;
|
||||
n->right = Z;
|
||||
n->addable = 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OINDEX:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
n->addable = 9;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
xcom(l);
|
||||
if(l->op == OADDR) {
|
||||
l = l->left;
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
return;
|
||||
}
|
||||
switch(l->addable) {
|
||||
case 20:
|
||||
n->addable = 21;
|
||||
break;
|
||||
case 1:
|
||||
n->addable = 11;
|
||||
break;
|
||||
case 13:
|
||||
n->addable = 10;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASHL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(l);
|
||||
if(g >= 0) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASHL;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
commute(n);
|
||||
break;
|
||||
|
||||
case OASLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
break;
|
||||
|
||||
case OLDIV:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OLSHR;
|
||||
r->vconst = g;
|
||||
r->type = types[TINT];
|
||||
indexshift(n);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OAND;
|
||||
r->vconst--;
|
||||
}
|
||||
break;
|
||||
|
||||
case OASMUL:
|
||||
case OASLMUL:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
g = vlog(r);
|
||||
if(g >= 0) {
|
||||
n->op = OASASHL;
|
||||
r->vconst = g;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
indexshift(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
if(r != Z)
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
brk:
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
if(r->complex == n->complex)
|
||||
n->complex = r->complex+1;
|
||||
else
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
}
|
||||
if(n->complex == 0)
|
||||
n->complex++;
|
||||
|
||||
switch(n->op) {
|
||||
|
||||
case OFUNC:
|
||||
n->complex = FNX;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(l->type->etype == TUVLONG && typefd[n->type->etype])
|
||||
n->complex += 2;
|
||||
break;
|
||||
|
||||
case OLMOD:
|
||||
case OMOD:
|
||||
case OLMUL:
|
||||
case OLDIV:
|
||||
case OMUL:
|
||||
case ODIV:
|
||||
case OASLMUL:
|
||||
case OASLDIV:
|
||||
case OASLMOD:
|
||||
case OASMUL:
|
||||
case OASDIV:
|
||||
case OASMOD:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 3;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 3;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case OASLSHR:
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
if(r->complex >= l->complex) {
|
||||
n->complex = l->complex + 2;
|
||||
if(r->complex > n->complex)
|
||||
n->complex = r->complex;
|
||||
} else {
|
||||
n->complex = r->complex + 2;
|
||||
if(l->complex > n->complex)
|
||||
n->complex = l->complex;
|
||||
}
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OXOR:
|
||||
case OAND:
|
||||
case OOR:
|
||||
/*
|
||||
* immediate operators, make const on right
|
||||
*/
|
||||
if(l->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
}
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
case ONE:
|
||||
case OLE:
|
||||
case OLT:
|
||||
case OGE:
|
||||
case OGT:
|
||||
case OHI:
|
||||
case OHS:
|
||||
case OLO:
|
||||
case OLS:
|
||||
/*
|
||||
* compare operators, make const on left
|
||||
*/
|
||||
if(r->op == OCONST) {
|
||||
n->left = r;
|
||||
n->right = l;
|
||||
n->op = invrel[relindex(n->op)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
indx(Node *n)
|
||||
{
|
||||
Node *l, *r;
|
||||
|
||||
if(debug['x'])
|
||||
prtree(n, "indx");
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
|
||||
n->right = l;
|
||||
n->left = r;
|
||||
l = r;
|
||||
r = n->right;
|
||||
}
|
||||
if(l->addable != 7) {
|
||||
idx.regtree = l;
|
||||
idx.scale = 1;
|
||||
} else
|
||||
if(l->right->addable == 20) {
|
||||
idx.regtree = l->left;
|
||||
idx.scale = 1 << l->right->vconst;
|
||||
} else
|
||||
if(l->left->addable == 20) {
|
||||
idx.regtree = l->right;
|
||||
idx.scale = 1 << l->left->vconst;
|
||||
} else
|
||||
diag(n, "bad index");
|
||||
|
||||
idx.basetree = r;
|
||||
if(debug['x']) {
|
||||
print("scale = %d\n", idx.scale);
|
||||
prtree(idx.regtree, "index");
|
||||
prtree(idx.basetree, "base");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,530 @@
|
|||
#include "gc.h"
|
||||
|
||||
void
|
||||
swit1(C1 *q, int nc, long def, Node *n)
|
||||
{
|
||||
C1 *r;
|
||||
int i;
|
||||
Prog *sp;
|
||||
|
||||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8llux\n", q->val);
|
||||
gcmp(OEQ, n, q->val);
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
}
|
||||
gbranch(OGOTO);
|
||||
patch(p, def);
|
||||
return;
|
||||
}
|
||||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8llux\n", r->val);
|
||||
gcmp(OGT, n, r->val);
|
||||
sp = p;
|
||||
gbranch(OGOTO);
|
||||
p->as = AJEQ;
|
||||
patch(p, r->label);
|
||||
swit1(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit1(r+1, nc-i-1, def, n);
|
||||
}
|
||||
|
||||
void
|
||||
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
int sh;
|
||||
long v;
|
||||
Node *l;
|
||||
|
||||
/*
|
||||
* n1 gets adjusted/masked value
|
||||
* n2 gets address of cell
|
||||
* n3 gets contents of cell
|
||||
*/
|
||||
l = b->left;
|
||||
if(n2 != Z) {
|
||||
regalloc(n1, l, nn);
|
||||
reglcgen(n2, l, Z);
|
||||
regalloc(n3, l, Z);
|
||||
gmove(n2, n3);
|
||||
gmove(n3, n1);
|
||||
} else {
|
||||
regalloc(n1, l, nn);
|
||||
cgen(l, n1);
|
||||
}
|
||||
if(b->type->shift == 0 && typeu[b->type->etype]) {
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, tfield, nodconst(v), n1);
|
||||
} else {
|
||||
sh = 32 - b->type->shift - b->type->nbits;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, tfield, nodconst(sh), n1);
|
||||
sh += b->type->shift;
|
||||
if(sh > 0)
|
||||
if(typeu[b->type->etype])
|
||||
gopcode(OLSHR, tfield, nodconst(sh), n1);
|
||||
else
|
||||
gopcode(OASHR, tfield, nodconst(sh), n1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
|
||||
{
|
||||
long v;
|
||||
Node nod;
|
||||
int sh;
|
||||
|
||||
regalloc(&nod, b->left, Z);
|
||||
v = ~0 + (1L << b->type->nbits);
|
||||
gopcode(OAND, types[TLONG], nodconst(v), n1);
|
||||
gmove(n1, &nod);
|
||||
if(nn != Z)
|
||||
gmove(n1, nn);
|
||||
sh = b->type->shift;
|
||||
if(sh > 0)
|
||||
gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
|
||||
v <<= sh;
|
||||
gopcode(OAND, types[TLONG], nodconst(~v), n3);
|
||||
gopcode(OOR, types[TLONG], n3, &nod);
|
||||
gmove(&nod, n2);
|
||||
|
||||
regfree(&nod);
|
||||
regfree(n1);
|
||||
regfree(n2);
|
||||
regfree(n3);
|
||||
}
|
||||
|
||||
long
|
||||
outstring(char *s, long n)
|
||||
{
|
||||
long r;
|
||||
|
||||
if(suppress)
|
||||
return nstring;
|
||||
r = nstring;
|
||||
while(n) {
|
||||
string[mnstring] = *s++;
|
||||
mnstring++;
|
||||
nstring++;
|
||||
if(mnstring >= NSNAME) {
|
||||
gpseudo(ADATA, symstring, nodconst(0L));
|
||||
p->from.offset += nstring - NSNAME;
|
||||
p->from.scale = NSNAME;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.sval, string, NSNAME);
|
||||
mnstring = 0;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sextern(Sym *s, Node *a, long o, long w)
|
||||
{
|
||||
long e, lw;
|
||||
|
||||
for(e=0; e<w; e+=NSNAME) {
|
||||
lw = NSNAME;
|
||||
if(w-e < lw)
|
||||
lw = w-e;
|
||||
gpseudo(ADATA, s, nodconst(0L));
|
||||
p->from.offset += o+e;
|
||||
p->from.scale = lw;
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.sval, a->cstring+e, lw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gextern(Sym *s, Node *a, long o, long w)
|
||||
{
|
||||
if(0 && a->op == OCONST && typev[a->type->etype]) {
|
||||
gpseudo(ADATA, s, lo64(a));
|
||||
p->from.offset += o;
|
||||
p->from.scale = 4;
|
||||
gpseudo(ADATA, s, hi64(a));
|
||||
p->from.offset += o + 4;
|
||||
p->from.scale = 4;
|
||||
return;
|
||||
}
|
||||
gpseudo(ADATA, s, a);
|
||||
p->from.offset += o;
|
||||
p->from.scale = w;
|
||||
switch(p->to.type) {
|
||||
default:
|
||||
p->to.index = p->to.type;
|
||||
p->to.type = D_ADDR;
|
||||
case D_CONST:
|
||||
case D_FCONST:
|
||||
case D_ADDR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void zname(Biobuf*, Sym*, int);
|
||||
void zaddr(Biobuf*, Adr*, int);
|
||||
void outhist(Biobuf*);
|
||||
|
||||
void
|
||||
outcode(void)
|
||||
{
|
||||
struct { Sym *sym; short type; } h[NSYM];
|
||||
Prog *p;
|
||||
Sym *s;
|
||||
int f, sf, st, t, sym;
|
||||
Biobuf b;
|
||||
|
||||
if(debug['S']) {
|
||||
for(p = firstp; p != P; p = p->link)
|
||||
if(p->as != ADATA && p->as != AGLOBL)
|
||||
pc--;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
print("%P\n", p);
|
||||
if(p->as != ADATA && p->as != AGLOBL)
|
||||
pc++;
|
||||
}
|
||||
}
|
||||
f = open(outfile, OWRITE);
|
||||
if(f < 0) {
|
||||
diag(Z, "cannot open %s", outfile);
|
||||
return;
|
||||
}
|
||||
Binit(&b, f, OWRITE);
|
||||
Bseek(&b, 0L, 2);
|
||||
outhist(&b);
|
||||
for(sym=0; sym<NSYM; sym++) {
|
||||
h[sym].sym = S;
|
||||
h[sym].type = 0;
|
||||
}
|
||||
sym = 1;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
jackpot:
|
||||
sf = 0;
|
||||
s = p->from.sym;
|
||||
while(s != S) {
|
||||
sf = s->sym;
|
||||
if(sf < 0 || sf >= NSYM)
|
||||
sf = 0;
|
||||
t = p->from.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->from.index;
|
||||
if(h[sf].type == t)
|
||||
if(h[sf].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(&b, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
sf = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
break;
|
||||
}
|
||||
st = 0;
|
||||
s = p->to.sym;
|
||||
while(s != S) {
|
||||
st = s->sym;
|
||||
if(st < 0 || st >= NSYM)
|
||||
st = 0;
|
||||
t = p->to.type;
|
||||
if(t == D_ADDR)
|
||||
t = p->to.index;
|
||||
if(h[st].type == t)
|
||||
if(h[st].sym == s)
|
||||
break;
|
||||
s->sym = sym;
|
||||
zname(&b, s, t);
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
st = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
if(st == sf)
|
||||
goto jackpot;
|
||||
break;
|
||||
}
|
||||
Bputc(&b, p->as);
|
||||
Bputc(&b, p->as>>8);
|
||||
Bputc(&b, p->lineno);
|
||||
Bputc(&b, p->lineno>>8);
|
||||
Bputc(&b, p->lineno>>16);
|
||||
Bputc(&b, p->lineno>>24);
|
||||
zaddr(&b, &p->from, sf);
|
||||
zaddr(&b, &p->to, st);
|
||||
}
|
||||
Bflush(&b);
|
||||
close(f);
|
||||
firstp = P;
|
||||
lastp = P;
|
||||
}
|
||||
|
||||
void
|
||||
outhist(Biobuf *b)
|
||||
{
|
||||
Hist *h;
|
||||
char *p, *q, *op, c;
|
||||
Prog pg;
|
||||
int n;
|
||||
|
||||
pg = zprog;
|
||||
pg.as = AHISTORY;
|
||||
c = pathchar();
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
op = 0;
|
||||
/* on windows skip drive specifier in pathname */
|
||||
if(systemtype(Windows) && p && p[1] == ':'){
|
||||
p += 2;
|
||||
c = *p;
|
||||
}
|
||||
if(p && p[0] != c && h->offset == 0 && pathname){
|
||||
/* on windows skip drive specifier in pathname */
|
||||
if(systemtype(Windows) && pathname[1] == ':') {
|
||||
op = p;
|
||||
p = pathname+2;
|
||||
c = *p;
|
||||
} else if(pathname[0] == c){
|
||||
op = p;
|
||||
p = pathname;
|
||||
}
|
||||
}
|
||||
while(p) {
|
||||
q = utfrune(p, c);
|
||||
if(q) {
|
||||
n = q-p;
|
||||
if(n == 0){
|
||||
n = 1; /* leading "/" */
|
||||
*p = '/'; /* don't emit "\" on windows */
|
||||
}
|
||||
q++;
|
||||
} else {
|
||||
n = strlen(p);
|
||||
q = 0;
|
||||
}
|
||||
if(n) {
|
||||
Bputc(b, ANAME);
|
||||
Bputc(b, ANAME>>8);
|
||||
Bputc(b, D_FILE);
|
||||
Bputc(b, 1);
|
||||
Bputc(b, '<');
|
||||
Bwrite(b, p, n);
|
||||
Bputc(b, 0);
|
||||
}
|
||||
p = q;
|
||||
if(p == 0 && op) {
|
||||
p = op;
|
||||
op = 0;
|
||||
}
|
||||
}
|
||||
pg.lineno = h->line;
|
||||
pg.to.type = zprog.to.type;
|
||||
pg.to.offset = h->offset;
|
||||
if(h->offset)
|
||||
pg.to.type = D_CONST;
|
||||
|
||||
Bputc(b, pg.as);
|
||||
Bputc(b, pg.as>>8);
|
||||
Bputc(b, pg.lineno);
|
||||
Bputc(b, pg.lineno>>8);
|
||||
Bputc(b, pg.lineno>>16);
|
||||
Bputc(b, pg.lineno>>24);
|
||||
zaddr(b, &pg.from, 0);
|
||||
zaddr(b, &pg.to, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
zname(Biobuf *b, Sym *s, int t)
|
||||
{
|
||||
char *n;
|
||||
ulong sig;
|
||||
|
||||
if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
|
||||
sig = sign(s);
|
||||
Bputc(b, ASIGNAME);
|
||||
Bputc(b, ASIGNAME>>8);
|
||||
Bputc(b, sig);
|
||||
Bputc(b, sig>>8);
|
||||
Bputc(b, sig>>16);
|
||||
Bputc(b, sig>>24);
|
||||
s->sig = SIGDONE;
|
||||
}
|
||||
else{
|
||||
Bputc(b, ANAME); /* as */
|
||||
Bputc(b, ANAME>>8); /* as */
|
||||
}
|
||||
Bputc(b, t); /* type */
|
||||
Bputc(b, s->sym); /* sym */
|
||||
n = s->name;
|
||||
while(*n) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
Bputc(b, 0);
|
||||
}
|
||||
|
||||
void
|
||||
zaddr(Biobuf *b, Adr *a, int s)
|
||||
{
|
||||
long l;
|
||||
int i, t;
|
||||
char *n;
|
||||
Ieee e;
|
||||
|
||||
t = 0;
|
||||
if(a->index != D_NONE || a->scale != 0)
|
||||
t |= T_INDEX;
|
||||
if(s != 0)
|
||||
t |= T_SYM;
|
||||
|
||||
switch(a->type) {
|
||||
default:
|
||||
t |= T_TYPE;
|
||||
case D_NONE:
|
||||
if(a->offset != 0) {
|
||||
t |= T_OFFSET;
|
||||
l = a->offset;
|
||||
if((vlong)l != a->offset)
|
||||
t |= T_64;
|
||||
}
|
||||
break;
|
||||
case D_FCONST:
|
||||
t |= T_FCONST;
|
||||
break;
|
||||
case D_SCONST:
|
||||
t |= T_SCONST;
|
||||
break;
|
||||
}
|
||||
Bputc(b, t);
|
||||
|
||||
if(t & T_INDEX) { /* implies index, scale */
|
||||
Bputc(b, a->index);
|
||||
Bputc(b, a->scale);
|
||||
}
|
||||
if(t & T_OFFSET) { /* implies offset */
|
||||
l = a->offset;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
if(t & T_64) {
|
||||
l = a->offset>>32;
|
||||
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) {
|
||||
ieeedtod(&e, a->dval);
|
||||
l = e.l;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
l = e.h;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
return;
|
||||
}
|
||||
if(t & T_SCONST) {
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(t & T_TYPE)
|
||||
Bputc(b, a->type);
|
||||
}
|
||||
|
||||
long
|
||||
align(long i, Type *t, int op)
|
||||
{
|
||||
long o;
|
||||
Type *v;
|
||||
int w;
|
||||
|
||||
o = i;
|
||||
w = 1;
|
||||
switch(op) {
|
||||
default:
|
||||
diag(Z, "unknown align opcode %d", op);
|
||||
break;
|
||||
|
||||
case Asu2: /* padding at end of a struct */
|
||||
w = SZ_VLONG;
|
||||
if(packflg)
|
||||
w = packflg;
|
||||
break;
|
||||
|
||||
case Ael1: /* initial align of struct element */
|
||||
for(v=t; v->etype==TARRAY; v=v->link)
|
||||
;
|
||||
w = ewidth[v->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG)
|
||||
w = SZ_VLONG;
|
||||
if(packflg)
|
||||
w = packflg;
|
||||
break;
|
||||
|
||||
case Ael2: /* width of a struct element */
|
||||
o += t->width;
|
||||
break;
|
||||
|
||||
case Aarg0: /* initial passbyptr argument in arg list */
|
||||
if(typesu[t->etype]) {
|
||||
o = align(o, types[TIND], Aarg1);
|
||||
o = align(o, types[TIND], Aarg2);
|
||||
}
|
||||
break;
|
||||
|
||||
case Aarg1: /* initial align of parameter */
|
||||
w = ewidth[t->etype];
|
||||
if(w <= 0 || w >= SZ_VLONG) {
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
}
|
||||
w = 1; /* little endian no adjustment */
|
||||
break;
|
||||
|
||||
case Aarg2: /* width of a parameter */
|
||||
o += t->width;
|
||||
w = SZ_VLONG;
|
||||
break;
|
||||
|
||||
case Aaut3: /* total allign of automatic */
|
||||
o = align(o, t, Ael1);
|
||||
o = align(o, t, Ael2);
|
||||
break;
|
||||
}
|
||||
o = round(o, w);
|
||||
if(debug['A'])
|
||||
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
long
|
||||
maxround(long max, long v)
|
||||
{
|
||||
v += SZ_VLONG-1;
|
||||
if(v > max)
|
||||
max = round(v, SZ_VLONG);
|
||||
return max;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "/sys/src/libc/9syscall/sys.h"
|
||||
|
||||
vlong _sysargs[6*4];
|
||||
vlong _callsys(void);
|
||||
|
||||
/*
|
||||
* syscalls
|
||||
*/
|
||||
|
||||
int
|
||||
getpid(void)
|
||||
{
|
||||
_sysargs[0] = -1;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
long
|
||||
pread(int fd, void *a, long n, vlong)
|
||||
{
|
||||
_sysargs[0] = PREAD;
|
||||
_sysargs[1] = fd;
|
||||
_sysargs[2] = (vlong)a;
|
||||
_sysargs[3] = n;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
long
|
||||
pwrite(int fd, void *a, long n, vlong)
|
||||
{
|
||||
_sysargs[0] = PWRITE;
|
||||
_sysargs[1] = fd;
|
||||
_sysargs[2] = (vlong)a;
|
||||
_sysargs[3] = n;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
int
|
||||
close(int fd)
|
||||
{
|
||||
_sysargs[0] = CLOSE;
|
||||
_sysargs[1] = fd;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
int
|
||||
open(char *name, int mode)
|
||||
{
|
||||
_sysargs[0] = OPEN;
|
||||
_sysargs[1] = (vlong)name;
|
||||
_sysargs[2] = mode;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
int
|
||||
create(char *f, int mode, ulong perm)
|
||||
{
|
||||
_sysargs[0] = CREATE;
|
||||
_sysargs[1] = (vlong)f;
|
||||
_sysargs[2] = mode;
|
||||
_sysargs[3] = perm;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
void
|
||||
_exits(char *s)
|
||||
{
|
||||
_sysargs[0] = EXITS;
|
||||
_sysargs[1] = s!=nil? strlen(s): 0;
|
||||
_callsys();
|
||||
}
|
||||
|
||||
int
|
||||
dup(int f, int t)
|
||||
{
|
||||
_sysargs[0] = DUP;
|
||||
_sysargs[1] = f;
|
||||
_sysargs[2] = t;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
int
|
||||
errstr(char *buf, uint n)
|
||||
{
|
||||
_sysargs[0] = ERRSTR;
|
||||
_sysargs[1] = (vlong)buf;
|
||||
_sysargs[2] = n;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
int
|
||||
brk_(void *a)
|
||||
{
|
||||
_sysargs[0] = BRK_;
|
||||
_sysargs[1] = (vlong)a;
|
||||
return _callsys();
|
||||
}
|
||||
|
||||
void*
|
||||
sbrk(ulong n)
|
||||
{
|
||||
_sysargs[0] = -2;
|
||||
_sysargs[1] = n;
|
||||
return (void*)_callsys();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,746 @@
|
|||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
typedef signed char schar;
|
||||
|
||||
#define SIGN(n) (1UL<<(n-1))
|
||||
|
||||
typedef struct Vlong Vlong;
|
||||
struct Vlong
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint lo;
|
||||
uint hi;
|
||||
};
|
||||
struct
|
||||
{
|
||||
ushort lols;
|
||||
ushort loms;
|
||||
ushort hils;
|
||||
ushort hims;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void abort(void);
|
||||
|
||||
void _subv(Vlong*, Vlong, Vlong);
|
||||
|
||||
void
|
||||
_d2v(Vlong *y, double d)
|
||||
{
|
||||
union { double d; struct Vlong; } x;
|
||||
uint xhi, xlo, ylo, yhi;
|
||||
int sh;
|
||||
|
||||
x.d = d;
|
||||
|
||||
xhi = (x.hi & 0xfffff) | 0x100000;
|
||||
xlo = x.lo;
|
||||
sh = 1075 - ((x.hi >> 20) & 0x7ff);
|
||||
|
||||
ylo = 0;
|
||||
yhi = 0;
|
||||
if(sh >= 0) {
|
||||
/* v = (hi||lo) >> sh */
|
||||
if(sh < 32) {
|
||||
if(sh == 0) {
|
||||
ylo = xlo;
|
||||
yhi = xhi;
|
||||
} else {
|
||||
ylo = (xlo >> sh) | (xhi << (32-sh));
|
||||
yhi = xhi >> sh;
|
||||
}
|
||||
} else {
|
||||
if(sh == 32) {
|
||||
ylo = xhi;
|
||||
} else
|
||||
if(sh < 64) {
|
||||
ylo = xhi >> (sh-32);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* v = (hi||lo) << -sh */
|
||||
sh = -sh;
|
||||
if(sh <= 10) {
|
||||
ylo = xlo << sh;
|
||||
yhi = (xhi << sh) | (xlo >> (32-sh));
|
||||
} else {
|
||||
/* overflow */
|
||||
yhi = d; /* causes something awful */
|
||||
}
|
||||
}
|
||||
if(x.hi & SIGN(32)) {
|
||||
if(ylo != 0) {
|
||||
ylo = -ylo;
|
||||
yhi = ~yhi;
|
||||
} else
|
||||
yhi = -yhi;
|
||||
}
|
||||
|
||||
y->hi = yhi;
|
||||
y->lo = ylo;
|
||||
}
|
||||
|
||||
void
|
||||
_f2v(Vlong *y, float f)
|
||||
{
|
||||
|
||||
_d2v(y, f);
|
||||
}
|
||||
|
||||
double
|
||||
_v2d(Vlong x)
|
||||
{
|
||||
if(x.hi & SIGN(32)) {
|
||||
if(x.lo) {
|
||||
x.lo = -x.lo;
|
||||
x.hi = ~x.hi;
|
||||
} else
|
||||
x.hi = -x.hi;
|
||||
return -((long)x.hi*4294967296. + x.lo);
|
||||
}
|
||||
return (long)x.hi*4294967296. + x.lo;
|
||||
}
|
||||
|
||||
float
|
||||
_v2f(Vlong x)
|
||||
{
|
||||
return _v2d(x);
|
||||
}
|
||||
|
||||
uint _div64by32(Vlong, uint, uint*);
|
||||
void _mul64by32(Vlong*, Vlong, uint);
|
||||
|
||||
static void
|
||||
slowdodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
|
||||
{
|
||||
uint numlo, numhi, denhi, denlo, quohi, quolo, t;
|
||||
int i;
|
||||
|
||||
numhi = num.hi;
|
||||
numlo = num.lo;
|
||||
denhi = den.hi;
|
||||
denlo = den.lo;
|
||||
|
||||
/*
|
||||
* get a divide by zero
|
||||
*/
|
||||
if(denlo==0 && denhi==0) {
|
||||
numlo = numlo / denlo;
|
||||
}
|
||||
|
||||
/*
|
||||
* set up the divisor and find the number of iterations needed
|
||||
*/
|
||||
if(numhi >= SIGN(32)) {
|
||||
quohi = SIGN(32);
|
||||
quolo = 0;
|
||||
} else {
|
||||
quohi = numhi;
|
||||
quolo = numlo;
|
||||
}
|
||||
i = 0;
|
||||
while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
|
||||
denhi = (denhi<<1) | (denlo>>31);
|
||||
denlo <<= 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
quohi = 0;
|
||||
quolo = 0;
|
||||
for(; i >= 0; i--) {
|
||||
quohi = (quohi<<1) | (quolo>>31);
|
||||
quolo <<= 1;
|
||||
if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
|
||||
t = numlo;
|
||||
numlo -= denlo;
|
||||
if(numlo > t)
|
||||
numhi--;
|
||||
numhi -= denhi;
|
||||
quolo |= 1;
|
||||
}
|
||||
denlo = (denlo>>1) | (denhi<<31);
|
||||
denhi >>= 1;
|
||||
}
|
||||
|
||||
if(q) {
|
||||
q->lo = quolo;
|
||||
q->hi = quohi;
|
||||
}
|
||||
if(r) {
|
||||
r->lo = numlo;
|
||||
r->hi = numhi;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp)
|
||||
{
|
||||
uint n;
|
||||
Vlong x, q, r;
|
||||
|
||||
if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){
|
||||
if(qp) {
|
||||
qp->hi = 0;
|
||||
qp->lo = 0;
|
||||
}
|
||||
if(rp) {
|
||||
rp->hi = num.hi;
|
||||
rp->lo = num.lo;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(den.hi != 0){
|
||||
q.hi = 0;
|
||||
n = num.hi/den.hi;
|
||||
_mul64by32(&x, den, n);
|
||||
if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo))
|
||||
slowdodiv(num, den, &q, &r);
|
||||
else {
|
||||
q.lo = n;
|
||||
_subv(&r, num, x);
|
||||
}
|
||||
} else {
|
||||
if(num.hi >= den.lo){
|
||||
q.hi = n = num.hi/den.lo;
|
||||
num.hi -= den.lo*n;
|
||||
} else {
|
||||
q.hi = 0;
|
||||
}
|
||||
q.lo = _div64by32(num, den.lo, &r.lo);
|
||||
r.hi = 0;
|
||||
}
|
||||
if(qp) {
|
||||
qp->lo = q.lo;
|
||||
qp->hi = q.hi;
|
||||
}
|
||||
if(rp) {
|
||||
rp->lo = r.lo;
|
||||
rp->hi = r.hi;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_divvu(Vlong *q, Vlong n, Vlong d)
|
||||
{
|
||||
|
||||
if(n.hi == 0 && d.hi == 0) {
|
||||
q->hi = 0;
|
||||
q->lo = n.lo / d.lo;
|
||||
return;
|
||||
}
|
||||
dodiv(n, d, q, 0);
|
||||
}
|
||||
|
||||
void
|
||||
_modvu(Vlong *r, Vlong n, Vlong d)
|
||||
{
|
||||
|
||||
if(n.hi == 0 && d.hi == 0) {
|
||||
r->hi = 0;
|
||||
r->lo = n.lo % d.lo;
|
||||
return;
|
||||
}
|
||||
dodiv(n, d, 0, r);
|
||||
}
|
||||
|
||||
static void
|
||||
vneg(Vlong *v)
|
||||
{
|
||||
|
||||
if(v->lo == 0) {
|
||||
v->hi = -v->hi;
|
||||
return;
|
||||
}
|
||||
v->lo = -v->lo;
|
||||
v->hi = ~v->hi;
|
||||
}
|
||||
|
||||
void
|
||||
_divv(Vlong *q, Vlong n, Vlong d)
|
||||
{
|
||||
long nneg, dneg;
|
||||
|
||||
if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
|
||||
q->lo = (long)n.lo / (long)d.lo;
|
||||
q->hi = ((long)q->lo) >> 31;
|
||||
return;
|
||||
}
|
||||
nneg = n.hi >> 31;
|
||||
if(nneg)
|
||||
vneg(&n);
|
||||
dneg = d.hi >> 31;
|
||||
if(dneg)
|
||||
vneg(&d);
|
||||
dodiv(n, d, q, 0);
|
||||
if(nneg != dneg)
|
||||
vneg(q);
|
||||
}
|
||||
|
||||
void
|
||||
_modv(Vlong *r, Vlong n, Vlong d)
|
||||
{
|
||||
long nneg, dneg;
|
||||
|
||||
if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
|
||||
r->lo = (long)n.lo % (long)d.lo;
|
||||
r->hi = ((long)r->lo) >> 31;
|
||||
return;
|
||||
}
|
||||
nneg = n.hi >> 31;
|
||||
if(nneg)
|
||||
vneg(&n);
|
||||
dneg = d.hi >> 31;
|
||||
if(dneg)
|
||||
vneg(&d);
|
||||
dodiv(n, d, 0, r);
|
||||
if(nneg)
|
||||
vneg(r);
|
||||
}
|
||||
|
||||
void
|
||||
_rshav(Vlong *r, Vlong a, int b)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = a.hi;
|
||||
if(b >= 32) {
|
||||
r->hi = t>>31;
|
||||
if(b >= 64) {
|
||||
/* this is illegal re C standard */
|
||||
r->lo = t>>31;
|
||||
return;
|
||||
}
|
||||
r->lo = t >> (b-32);
|
||||
return;
|
||||
}
|
||||
if(b <= 0) {
|
||||
r->hi = t;
|
||||
r->lo = a.lo;
|
||||
return;
|
||||
}
|
||||
r->hi = t >> b;
|
||||
r->lo = (t << (32-b)) | (a.lo >> b);
|
||||
}
|
||||
|
||||
void
|
||||
_rshlv(Vlong *r, Vlong a, int b)
|
||||
{
|
||||
uint t;
|
||||
|
||||
t = a.hi;
|
||||
if(b >= 32) {
|
||||
r->hi = 0;
|
||||
if(b >= 64) {
|
||||
/* this is illegal re C standard */
|
||||
r->lo = 0;
|
||||
return;
|
||||
}
|
||||
r->lo = t >> (b-32);
|
||||
return;
|
||||
}
|
||||
if(b <= 0) {
|
||||
r->hi = t;
|
||||
r->lo = a.lo;
|
||||
return;
|
||||
}
|
||||
r->hi = t >> b;
|
||||
r->lo = (t << (32-b)) | (a.lo >> b);
|
||||
}
|
||||
|
||||
void
|
||||
_lshv(Vlong *r, Vlong a, int b)
|
||||
{
|
||||
uint t;
|
||||
|
||||
t = a.lo;
|
||||
if(b >= 32) {
|
||||
r->lo = 0;
|
||||
if(b >= 64) {
|
||||
/* this is illegal re C standard */
|
||||
r->hi = 0;
|
||||
return;
|
||||
}
|
||||
r->hi = t << (b-32);
|
||||
return;
|
||||
}
|
||||
if(b <= 0) {
|
||||
r->lo = t;
|
||||
r->hi = a.hi;
|
||||
return;
|
||||
}
|
||||
r->lo = t << b;
|
||||
r->hi = (t >> (32-b)) | (a.hi << b);
|
||||
}
|
||||
|
||||
void
|
||||
_andv(Vlong *r, Vlong a, Vlong b)
|
||||
{
|
||||
r->hi = a.hi & b.hi;
|
||||
r->lo = a.lo & b.lo;
|
||||
}
|
||||
|
||||
void
|
||||
_orv(Vlong *r, Vlong a, Vlong b)
|
||||
{
|
||||
r->hi = a.hi | b.hi;
|
||||
r->lo = a.lo | b.lo;
|
||||
}
|
||||
|
||||
void
|
||||
_xorv(Vlong *r, Vlong a, Vlong b)
|
||||
{
|
||||
r->hi = a.hi ^ b.hi;
|
||||
r->lo = a.lo ^ b.lo;
|
||||
}
|
||||
|
||||
void
|
||||
_vpp(Vlong *l, Vlong *r)
|
||||
{
|
||||
|
||||
l->hi = r->hi;
|
||||
l->lo = r->lo;
|
||||
r->lo++;
|
||||
if(r->lo == 0)
|
||||
r->hi++;
|
||||
}
|
||||
|
||||
void
|
||||
_vmm(Vlong *l, Vlong *r)
|
||||
{
|
||||
|
||||
l->hi = r->hi;
|
||||
l->lo = r->lo;
|
||||
if(r->lo == 0)
|
||||
r->hi--;
|
||||
r->lo--;
|
||||
}
|
||||
|
||||
void
|
||||
_ppv(Vlong *l, Vlong *r)
|
||||
{
|
||||
|
||||
r->lo++;
|
||||
if(r->lo == 0)
|
||||
r->hi++;
|
||||
l->hi = r->hi;
|
||||
l->lo = r->lo;
|
||||
}
|
||||
|
||||
void
|
||||
_mmv(Vlong *l, Vlong *r)
|
||||
{
|
||||
|
||||
if(r->lo == 0)
|
||||
r->hi--;
|
||||
r->lo--;
|
||||
l->hi = r->hi;
|
||||
l->lo = r->lo;
|
||||
}
|
||||
|
||||
void
|
||||
_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
|
||||
{
|
||||
Vlong t, u;
|
||||
|
||||
u.lo = 0;
|
||||
u.hi = 0;
|
||||
switch(type) {
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
|
||||
case 1: /* schar */
|
||||
t.lo = *(schar*)lv;
|
||||
t.hi = t.lo >> 31;
|
||||
fn(&u, t, rv);
|
||||
*(schar*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 2: /* uchar */
|
||||
t.lo = *(uchar*)lv;
|
||||
t.hi = 0;
|
||||
fn(&u, t, rv);
|
||||
*(uchar*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 3: /* short */
|
||||
t.lo = *(short*)lv;
|
||||
t.hi = t.lo >> 31;
|
||||
fn(&u, t, rv);
|
||||
*(short*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 4: /* ushort */
|
||||
t.lo = *(ushort*)lv;
|
||||
t.hi = 0;
|
||||
fn(&u, t, rv);
|
||||
*(ushort*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 9: /* int */
|
||||
t.lo = *(int*)lv;
|
||||
t.hi = t.lo >> 31;
|
||||
fn(&u, t, rv);
|
||||
*(int*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 10: /* uint */
|
||||
t.lo = *(uint*)lv;
|
||||
t.hi = 0;
|
||||
fn(&u, t, rv);
|
||||
*(uint*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 5: /* long */
|
||||
t.lo = *(long*)lv;
|
||||
t.hi = t.lo >> 31;
|
||||
fn(&u, t, rv);
|
||||
*(long*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 6: /* uint */
|
||||
t.lo = *(uint*)lv;
|
||||
t.hi = 0;
|
||||
fn(&u, t, rv);
|
||||
*(uint*)lv = u.lo;
|
||||
break;
|
||||
|
||||
case 7: /* vlong */
|
||||
case 8: /* uvlong */
|
||||
fn(&u, *(Vlong*)lv, rv);
|
||||
*(Vlong*)lv = u;
|
||||
break;
|
||||
}
|
||||
*ret = u;
|
||||
}
|
||||
|
||||
void
|
||||
_p2v(Vlong *ret, void *p)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = (uint)p;
|
||||
ret->lo = t;
|
||||
ret->hi = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_sl2v(Vlong *ret, long sl)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = sl;
|
||||
ret->lo = t;
|
||||
ret->hi = t >> 31;
|
||||
}
|
||||
|
||||
void
|
||||
_ul2v(Vlong *ret, uint ul)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = ul;
|
||||
ret->lo = t;
|
||||
ret->hi = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_si2v(Vlong *ret, int si)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = si;
|
||||
ret->lo = t;
|
||||
ret->hi = t >> 31;
|
||||
}
|
||||
|
||||
void
|
||||
_ui2v(Vlong *ret, uint ui)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = ui;
|
||||
ret->lo = t;
|
||||
ret->hi = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_sh2v(Vlong *ret, long sh)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = (sh << 16) >> 16;
|
||||
ret->lo = t;
|
||||
ret->hi = t >> 31;
|
||||
}
|
||||
|
||||
void
|
||||
_uh2v(Vlong *ret, uint ul)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = ul & 0xffff;
|
||||
ret->lo = t;
|
||||
ret->hi = 0;
|
||||
}
|
||||
|
||||
void
|
||||
_sc2v(Vlong *ret, long uc)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = (uc << 24) >> 24;
|
||||
ret->lo = t;
|
||||
ret->hi = t >> 31;
|
||||
}
|
||||
|
||||
void
|
||||
_uc2v(Vlong *ret, uint ul)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = ul & 0xff;
|
||||
ret->lo = t;
|
||||
ret->hi = 0;
|
||||
}
|
||||
|
||||
long
|
||||
_v2sc(Vlong rv)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = rv.lo & 0xff;
|
||||
return (t << 24) >> 24;
|
||||
}
|
||||
|
||||
long
|
||||
_v2uc(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo & 0xff;
|
||||
}
|
||||
|
||||
long
|
||||
_v2sh(Vlong rv)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = rv.lo & 0xffff;
|
||||
return (t << 16) >> 16;
|
||||
}
|
||||
|
||||
long
|
||||
_v2uh(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo & 0xffff;
|
||||
}
|
||||
|
||||
long
|
||||
_v2sl(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo;
|
||||
}
|
||||
|
||||
long
|
||||
_v2ul(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo;
|
||||
}
|
||||
|
||||
long
|
||||
_v2si(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo;
|
||||
}
|
||||
|
||||
long
|
||||
_v2ui(Vlong rv)
|
||||
{
|
||||
|
||||
return rv.lo;
|
||||
}
|
||||
|
||||
int
|
||||
_testv(Vlong rv)
|
||||
{
|
||||
return rv.lo || rv.hi;
|
||||
}
|
||||
|
||||
int
|
||||
_eqv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.lo == rv.lo && lv.hi == rv.hi;
|
||||
}
|
||||
|
||||
int
|
||||
_nev(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.lo != rv.lo || lv.hi != rv.hi;
|
||||
}
|
||||
|
||||
int
|
||||
_ltv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return (long)lv.hi < (long)rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo < rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_lev(Vlong lv, Vlong rv)
|
||||
{
|
||||
return (long)lv.hi < (long)rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo <= rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_gtv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return (long)lv.hi > (long)rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo > rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_gev(Vlong lv, Vlong rv)
|
||||
{
|
||||
return (long)lv.hi > (long)rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo >= rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_lov(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.hi < rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo < rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_lsv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.hi < rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo <= rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_hiv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.hi > rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo > rv.lo);
|
||||
}
|
||||
|
||||
int
|
||||
_hsv(Vlong lv, Vlong rv)
|
||||
{
|
||||
return lv.hi > rv.hi ||
|
||||
(lv.hi == rv.hi && lv.lo >= rv.lo);
|
||||
}
|
|
@ -0,0 +1,461 @@
|
|||
#include "l.h"
|
||||
|
||||
#define Dbufslop 100
|
||||
|
||||
#define PADDR(a) ((a) & ~0xfffffffff0000000ull)
|
||||
|
||||
vlong
|
||||
entryvalue(void)
|
||||
{
|
||||
char *a;
|
||||
Sym *s;
|
||||
|
||||
a = INITENTRY;
|
||||
if(*a >= '0' && *a <= '9')
|
||||
return atolwhex(a);
|
||||
s = lookup(a, 0);
|
||||
if(s->type == 0)
|
||||
return INITTEXT;
|
||||
switch(s->type) {
|
||||
case STEXT:
|
||||
break;
|
||||
case SDATA:
|
||||
if(dlm)
|
||||
return s->value+INITDAT;
|
||||
default:
|
||||
diag("entry not text: %s", s->name);
|
||||
}
|
||||
return s->value;
|
||||
}
|
||||
|
||||
void
|
||||
wputl(ushort w)
|
||||
{
|
||||
cput(w);
|
||||
cput(w>>8);
|
||||
}
|
||||
|
||||
void
|
||||
wput(ushort w)
|
||||
{
|
||||
cput(w>>8);
|
||||
cput(w);
|
||||
}
|
||||
|
||||
void
|
||||
lput(long l)
|
||||
{
|
||||
cput(l>>24);
|
||||
cput(l>>16);
|
||||
cput(l>>8);
|
||||
cput(l);
|
||||
}
|
||||
|
||||
void
|
||||
llput(vlong v)
|
||||
{
|
||||
lput(v>>32);
|
||||
lput(v);
|
||||
}
|
||||
|
||||
void
|
||||
lputl(long l)
|
||||
{
|
||||
cput(l);
|
||||
cput(l>>8);
|
||||
cput(l>>16);
|
||||
cput(l>>24);
|
||||
}
|
||||
|
||||
void
|
||||
strnput(char *s, int n)
|
||||
{
|
||||
for(; *s && n > 0; s++){
|
||||
cput(*s);
|
||||
n--;
|
||||
}
|
||||
while(n > 0){
|
||||
cput(0);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
asmb(void)
|
||||
{
|
||||
Prog *p;
|
||||
long v, magic;
|
||||
int a;
|
||||
uchar *op1;
|
||||
vlong vl;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f asmb\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
seek(cout, HEADR, 0);
|
||||
pc = INITTEXT;
|
||||
curp = firstp;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->pc != pc) {
|
||||
if(!debug['a'])
|
||||
print("%P\n", curp);
|
||||
diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
|
||||
pc = p->pc;
|
||||
}
|
||||
curp = p;
|
||||
asmins(p);
|
||||
a = (andptr - and);
|
||||
if(cbc < a)
|
||||
cflush();
|
||||
if(debug['a']) {
|
||||
Bprint(&bso, pcstr, pc);
|
||||
for(op1 = and; op1 < andptr; op1++)
|
||||
Bprint(&bso, "%.2ux", *op1 & 0xff);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
if(dlm) {
|
||||
if(p->as == ATEXT)
|
||||
reloca = nil;
|
||||
else if(reloca != nil)
|
||||
diag("reloc failure: %P", curp);
|
||||
}
|
||||
memmove(cbp, and, a);
|
||||
cbp += a;
|
||||
pc += a;
|
||||
cbc -= a;
|
||||
}
|
||||
cflush();
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
diag("unknown header type %ld", HEADTYPE);
|
||||
case 2:
|
||||
case 5:
|
||||
seek(cout, HEADR+textsize, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f datblk\n", cputime());
|
||||
Bflush(&bso);
|
||||
|
||||
if(dlm){
|
||||
char buf[8];
|
||||
|
||||
write(cout, buf, INITDAT-textsize);
|
||||
textsize = INITDAT;
|
||||
}
|
||||
|
||||
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
|
||||
if(datsize-v > sizeof(buf)-Dbufslop)
|
||||
datblk(v, sizeof(buf)-Dbufslop);
|
||||
else
|
||||
datblk(v, datsize-v);
|
||||
}
|
||||
|
||||
symsize = 0;
|
||||
spsize = 0;
|
||||
lcsize = 0;
|
||||
if(!debug['s']) {
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f sym\n", cputime());
|
||||
Bflush(&bso);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
case 2:
|
||||
case 5:
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
break;
|
||||
}
|
||||
if(!debug['s'])
|
||||
asmsym();
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f sp\n", cputime());
|
||||
Bflush(&bso);
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f pc\n", cputime());
|
||||
Bflush(&bso);
|
||||
if(!debug['s'])
|
||||
asmlc();
|
||||
if(dlm)
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
else if(dlm){
|
||||
seek(cout, HEADR+textsize+datsize, 0);
|
||||
asmdyn();
|
||||
cflush();
|
||||
}
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f headr\n", cputime());
|
||||
Bflush(&bso);
|
||||
seek(cout, 0L, 0);
|
||||
switch(HEADTYPE) {
|
||||
default:
|
||||
case 2: /* plan9 */
|
||||
magic = 4*26*26+7;
|
||||
magic |= 0x00008000; /* fat header */
|
||||
if(dlm)
|
||||
magic |= 0x80000000; /* dlm */
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(symsize); /* nsyms */
|
||||
vl = entryvalue();
|
||||
lput(PADDR(vl)); /* va of entry */
|
||||
lput(spsize); /* sp offsets */
|
||||
lput(lcsize); /* line offsets */
|
||||
llput(vl); /* va of entry */
|
||||
break;
|
||||
case 3: /* plan9 */
|
||||
magic = 4*26*26+7;
|
||||
if(dlm)
|
||||
magic |= 0x80000000;
|
||||
lput(magic); /* magic */
|
||||
lput(textsize); /* sizes */
|
||||
lput(datsize);
|
||||
lput(bsssize);
|
||||
lput(symsize); /* nsyms */
|
||||
lput(entryvalue()); /* va of entry */
|
||||
lput(spsize); /* sp offsets */
|
||||
lput(lcsize); /* line offsets */
|
||||
break;
|
||||
case 5:
|
||||
strnput("\177ELF", 4); /* e_ident */
|
||||
cput(1); /* class = 32 bit */
|
||||
cput(1); /* data = LSB */
|
||||
cput(1); /* version = CURRENT */
|
||||
strnput("", 9);
|
||||
wputl(2); /* type = EXEC */
|
||||
if(debug['8'])
|
||||
wputl(3); /* machine = 386 */
|
||||
else
|
||||
wputl(62); /* machine = AMD64 */
|
||||
lputl(1L); /* version = CURRENT */
|
||||
lputl(PADDR(entryvalue())); /* entry vaddr */
|
||||
lputl(52L); /* offset to first phdr */
|
||||
lputl(0L); /* offset to first shdr */
|
||||
lputl(0L); /* processor specific flags */
|
||||
wputl(52); /* Ehdr size */
|
||||
wputl(32); /* Phdr size */
|
||||
wputl(3); /* # of Phdrs */
|
||||
wputl(0); /* Shdr size */
|
||||
wputl(0); /* # of Shdrs */
|
||||
wputl(0); /* Shdr string size */
|
||||
|
||||
lputl(1L); /* text - type = PT_LOAD */
|
||||
lputl(HEADR); /* file offset */
|
||||
lputl(INITTEXT); /* vaddr */
|
||||
lputl(PADDR(INITTEXT)); /* paddr */
|
||||
lputl(textsize); /* file size */
|
||||
lputl(textsize); /* memory size */
|
||||
lputl(0x05L); /* protections = RX */
|
||||
lputl(INITRND); /* alignment */
|
||||
|
||||
lputl(1L); /* data - type = PT_LOAD */
|
||||
lputl(HEADR+textsize); /* file offset */
|
||||
lputl(INITDAT); /* vaddr */
|
||||
lputl(PADDR(INITDAT)); /* paddr */
|
||||
lputl(datsize); /* file size */
|
||||
lputl(datsize+bsssize); /* memory size */
|
||||
lputl(0x06L); /* protections = RW */
|
||||
lputl(INITRND); /* alignment */
|
||||
|
||||
lputl(0L); /* symbols - type = PT_NULL */
|
||||
lputl(HEADR+textsize+datsize); /* file offset */
|
||||
lputl(0L);
|
||||
lputl(0L);
|
||||
lputl(symsize); /* symbol table size */
|
||||
lputl(lcsize); /* line number size */
|
||||
lputl(0x04L); /* protections = R */
|
||||
lputl(0x04L); /* alignment */
|
||||
break;
|
||||
}
|
||||
cflush();
|
||||
}
|
||||
|
||||
void
|
||||
cflush(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = sizeof(buf.cbuf) - cbc;
|
||||
if(n)
|
||||
write(cout, buf.cbuf, n);
|
||||
cbp = buf.cbuf;
|
||||
cbc = sizeof(buf.cbuf);
|
||||
}
|
||||
|
||||
void
|
||||
datblk(long s, long n)
|
||||
{
|
||||
Prog *p;
|
||||
uchar *cast;
|
||||
long l, fl, j;
|
||||
vlong o;
|
||||
int i, c;
|
||||
|
||||
memset(buf.dbuf, 0, n+Dbufslop);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
curp = p;
|
||||
l = p->from.sym->value + p->from.offset - s;
|
||||
c = p->from.scale;
|
||||
i = 0;
|
||||
if(l < 0) {
|
||||
if(l+c <= 0)
|
||||
continue;
|
||||
while(l < 0) {
|
||||
l++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(l >= n)
|
||||
continue;
|
||||
if(p->as != AINIT && p->as != ADYNT) {
|
||||
for(j=l+(c-i)-1; j>=l; j--)
|
||||
if(buf.dbuf[j]) {
|
||||
print("%P\n", p);
|
||||
diag("multiple initialization");
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(p->to.type) {
|
||||
case D_FCONST:
|
||||
switch(c) {
|
||||
default:
|
||||
case 4:
|
||||
fl = ieeedtof(&p->to.ieee);
|
||||
cast = (uchar*)&fl;
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
cast = (uchar*)&p->to.ieee;
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[fnuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = p->to.scon[i];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
o = p->to.offset;
|
||||
if(p->to.type == D_ADDR) {
|
||||
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
|
||||
diag("DADDR type%P", p);
|
||||
if(p->to.sym) {
|
||||
if(p->to.sym->type == SUNDEF)
|
||||
ckoff(p->to.sym, o);
|
||||
o += p->to.sym->value;
|
||||
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
|
||||
o += INITDAT;
|
||||
if(dlm)
|
||||
dynreloc(p->to.sym, l+s+INITDAT, 1);
|
||||
}
|
||||
}
|
||||
fl = o;
|
||||
cast = (uchar*)&fl;
|
||||
switch(c) {
|
||||
default:
|
||||
diag("bad nuxi %d %d\n%P", c, i, curp);
|
||||
break;
|
||||
case 1:
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi1[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi2[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi4[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
cast = (uchar*)&o;
|
||||
if(debug['a'] && i == 0) {
|
||||
Bprint(&bso, pcstr, l+s+INITDAT);
|
||||
for(j=0; j<c; j++)
|
||||
Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
|
||||
Bprint(&bso, "\t%P\n", curp);
|
||||
}
|
||||
for(; i<c; i++) {
|
||||
buf.dbuf[l] = cast[inuxi8[i]];
|
||||
l++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
write(cout, buf.dbuf, n);
|
||||
}
|
||||
|
||||
vlong
|
||||
rnd(vlong v, vlong r)
|
||||
{
|
||||
vlong c;
|
||||
|
||||
if(r <= 0)
|
||||
return v;
|
||||
v += r - 1;
|
||||
c = v % r;
|
||||
if(c < 0)
|
||||
c += r;
|
||||
v -= c;
|
||||
return v;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#include "l.h"
|
||||
|
||||
/*
|
||||
* fake malloc
|
||||
*/
|
||||
void*
|
||||
malloc(ulong n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
while(n & 7)
|
||||
n++;
|
||||
while(nhunk < n)
|
||||
gethunk();
|
||||
p = hunk;
|
||||
nhunk -= n;
|
||||
hunk += n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
free(void *p)
|
||||
{
|
||||
USED(p);
|
||||
}
|
||||
|
||||
void*
|
||||
calloc(ulong m, ulong n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
n *= m;
|
||||
p = malloc(n);
|
||||
memset(p, 0, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void*
|
||||
realloc(void*, ulong)
|
||||
{
|
||||
fprint(2, "realloc called\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void*
|
||||
mysbrk(ulong size)
|
||||
{
|
||||
return sbrk(size);
|
||||
}
|
||||
|
||||
void
|
||||
setmalloctag(void*, ulong)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,390 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../6c/6.out.h"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define P ((Prog*)0)
|
||||
#define S ((Sym*)0)
|
||||
#define TNAME (curtext?curtext->from.sym->name:noname)
|
||||
#define cput(c)\
|
||||
{ *cbp++ = c;\
|
||||
if(--cbc <= 0)\
|
||||
cflush(); }
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Auto Auto;
|
||||
typedef struct Optab Optab;
|
||||
typedef struct Movtab Movtab;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
union
|
||||
{
|
||||
vlong u0offset;
|
||||
char u0scon[8];
|
||||
Prog *u0cond; /* not used, but should be D_BRANCH */
|
||||
Ieee u0ieee;
|
||||
} u0;
|
||||
union
|
||||
{
|
||||
Auto* u1autom;
|
||||
Sym* u1sym;
|
||||
} u1;
|
||||
short type;
|
||||
char index;
|
||||
char scale;
|
||||
};
|
||||
|
||||
#define offset u0.u0offset
|
||||
#define scon u0.u0scon
|
||||
#define cond u0.u0cond
|
||||
#define ieee u0.u0ieee
|
||||
|
||||
#define autom u1.u1autom
|
||||
#define sym u1.u1sym
|
||||
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr to;
|
||||
Prog *forwd;
|
||||
Prog* link;
|
||||
Prog* pcond; /* work on this */
|
||||
vlong pc;
|
||||
long line;
|
||||
uchar mark; /* work on these */
|
||||
uchar back;
|
||||
|
||||
short as;
|
||||
char width; /* fake for DATA */
|
||||
char mode; /* 16, 32, or 64 */
|
||||
};
|
||||
struct Auto
|
||||
{
|
||||
Sym* asym;
|
||||
Auto* link;
|
||||
long aoffset;
|
||||
short type;
|
||||
};
|
||||
struct Sym
|
||||
{
|
||||
char *name;
|
||||
short type;
|
||||
short version;
|
||||
short become;
|
||||
short frame;
|
||||
uchar subtype;
|
||||
ushort file;
|
||||
vlong value;
|
||||
long sig;
|
||||
Sym* link;
|
||||
};
|
||||
struct Optab
|
||||
{
|
||||
short as;
|
||||
uchar* ytab;
|
||||
uchar prefix;
|
||||
uchar op[20];
|
||||
};
|
||||
struct Movtab
|
||||
{
|
||||
short as;
|
||||
uchar ft;
|
||||
uchar tt;
|
||||
uchar code;
|
||||
uchar op[4];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
STEXT = 1,
|
||||
SDATA,
|
||||
SBSS,
|
||||
SDATA1,
|
||||
SXREF,
|
||||
SFILE,
|
||||
SCONST,
|
||||
SUNDEF,
|
||||
|
||||
SIMPORT,
|
||||
SEXPORT,
|
||||
|
||||
NHASH = 10007,
|
||||
NHUNK = 100000,
|
||||
MINSIZ = 8,
|
||||
STRINGSZ = 200,
|
||||
MINLC = 1,
|
||||
MAXIO = 8192,
|
||||
MAXHIST = 20, /* limit of path elements for history symbols */
|
||||
|
||||
Yxxx = 0,
|
||||
Ynone,
|
||||
Yi0,
|
||||
Yi1,
|
||||
Yi8,
|
||||
Ys32,
|
||||
Yi32,
|
||||
Yi64,
|
||||
Yiauto,
|
||||
Yal,
|
||||
Ycl,
|
||||
Yax,
|
||||
Ycx,
|
||||
Yrb,
|
||||
Yrl,
|
||||
Yrf,
|
||||
Yf0,
|
||||
Yrx,
|
||||
Ymb,
|
||||
Yml,
|
||||
Ym,
|
||||
Ybr,
|
||||
Ycol,
|
||||
|
||||
Ycs, Yss, Yds, Yes, Yfs, Ygs,
|
||||
Ygdtr, Yidtr, Yldtr, Ymsw, Ytask,
|
||||
Ycr0, Ycr1, Ycr2, Ycr3, Ycr4, Ycr5, Ycr6, Ycr7, Ycr8,
|
||||
Ydr0, Ydr1, Ydr2, Ydr3, Ydr4, Ydr5, Ydr6, Ydr7,
|
||||
Ytr0, Ytr1, Ytr2, Ytr3, Ytr4, Ytr5, Ytr6, Ytr7, Yrl32, Yrl64,
|
||||
Ymr, Ymm,
|
||||
Yxr, Yxm,
|
||||
Ymax,
|
||||
|
||||
Zxxx = 0,
|
||||
|
||||
Zlit,
|
||||
Z_rp,
|
||||
Zbr,
|
||||
Zcall,
|
||||
Zib_,
|
||||
Zib_rp,
|
||||
Zibo_m,
|
||||
Zibo_m_xm,
|
||||
Zil_,
|
||||
Zil_rp,
|
||||
Ziq_rp,
|
||||
Zilo_m,
|
||||
Ziqo_m,
|
||||
Zjmp,
|
||||
Zloop,
|
||||
Zo_iw,
|
||||
Zm_o,
|
||||
Zm_r,
|
||||
Zm_r_xm,
|
||||
Zm_r_i_xm,
|
||||
Zm_r_3d,
|
||||
Zm_r_xm_nr,
|
||||
Zr_m_xm_nr,
|
||||
Zibm_r, /* mmx1,mmx2/mem64,imm8 */
|
||||
Zmb_r,
|
||||
Zaut_r,
|
||||
Zo_m,
|
||||
Zo_m64,
|
||||
Zpseudo,
|
||||
Zr_m,
|
||||
Zr_m_xm,
|
||||
Zr_m_i_xm,
|
||||
Zrp_,
|
||||
Z_ib,
|
||||
Z_il,
|
||||
Zm_ibo,
|
||||
Zm_ilo,
|
||||
Zib_rr,
|
||||
Zil_rr,
|
||||
Zclr,
|
||||
Zbyte,
|
||||
Zmax,
|
||||
|
||||
Px = 0,
|
||||
P32 = 0x32, /* 32-bit only */
|
||||
Pe = 0x66, /* operand escape */
|
||||
Pm = 0x0f, /* 2byte opcode escape */
|
||||
Pq = 0xff, /* both escape */
|
||||
Pb = 0xfe, /* byte operands */
|
||||
Pf2 = 0xf2, /* xmm escape 1 */
|
||||
Pf3 = 0xf3, /* xmm escape 2 */
|
||||
Pw = 0x48, /* Rex.w */
|
||||
Py = 0x80, /* defaults to 64-bit mode */
|
||||
|
||||
Rxf = 1<<9, /* internal flag for Rxr on from */
|
||||
Rxt = 1<<8, /* internal flag for Rxr on to */
|
||||
Rxw = 1<<3, /* =1, 64-bit operand size */
|
||||
Rxr = 1<<2, /* extend modrm reg */
|
||||
Rxx = 1<<1, /* extend sib index */
|
||||
Rxb = 1<<0, /* extend modrm r/m, sib base, or opcode reg */
|
||||
|
||||
Roffset = 22, /* no. bits for offset in relocation address */
|
||||
Rindex = 10, /* no. bits for index in relocation address */
|
||||
};
|
||||
|
||||
EXTERN union
|
||||
{
|
||||
struct
|
||||
{
|
||||
char obuf[MAXIO]; /* output buffer */
|
||||
uchar ibuf[MAXIO]; /* input buffer */
|
||||
} u;
|
||||
char dbuf[1];
|
||||
} buf;
|
||||
|
||||
#define cbuf u.obuf
|
||||
#define xbuf u.ibuf
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "A" uint
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
#pragma varargck argpos diag 1
|
||||
|
||||
EXTERN long HEADR;
|
||||
EXTERN long HEADTYPE;
|
||||
EXTERN vlong INITDAT;
|
||||
EXTERN long INITRND;
|
||||
EXTERN vlong INITTEXT;
|
||||
EXTERN char* INITENTRY; /* entry point */
|
||||
EXTERN Biobuf bso;
|
||||
EXTERN long bsssize;
|
||||
EXTERN int cbc;
|
||||
EXTERN char* cbp;
|
||||
EXTERN char* pcstr;
|
||||
EXTERN int cout;
|
||||
EXTERN Auto* curauto;
|
||||
EXTERN Auto* curhist;
|
||||
EXTERN Prog* curp;
|
||||
EXTERN Prog* curtext;
|
||||
EXTERN Prog* datap;
|
||||
EXTERN Prog* edatap;
|
||||
EXTERN vlong datsize;
|
||||
EXTERN char debug[128];
|
||||
EXTERN char literal[32];
|
||||
EXTERN Prog* etextp;
|
||||
EXTERN Prog* firstp;
|
||||
EXTERN uchar fnuxi8[8];
|
||||
EXTERN uchar fnuxi4[4];
|
||||
EXTERN Sym* hash[NHASH];
|
||||
EXTERN Sym* histfrog[MAXHIST];
|
||||
EXTERN int histfrogp;
|
||||
EXTERN int histgen;
|
||||
EXTERN char* library[50];
|
||||
EXTERN char* libraryobj[50];
|
||||
EXTERN int libraryp;
|
||||
EXTERN int xrefresolv;
|
||||
EXTERN char* hunk;
|
||||
EXTERN uchar inuxi1[1];
|
||||
EXTERN uchar inuxi2[2];
|
||||
EXTERN uchar inuxi4[4];
|
||||
EXTERN uchar inuxi8[8];
|
||||
EXTERN char ycover[Ymax*Ymax];
|
||||
EXTERN uchar* andptr;
|
||||
EXTERN uchar* rexptr;
|
||||
EXTERN uchar and[30];
|
||||
EXTERN int reg[D_NONE];
|
||||
EXTERN int regrex[D_NONE+1];
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long lcsize;
|
||||
EXTERN int nerrors;
|
||||
EXTERN long nhunk;
|
||||
EXTERN long nsymbol;
|
||||
EXTERN char* noname;
|
||||
EXTERN char* outfile;
|
||||
EXTERN vlong pc;
|
||||
EXTERN long spsize;
|
||||
EXTERN Sym* symlist;
|
||||
EXTERN long symsize;
|
||||
EXTERN Prog* textp;
|
||||
EXTERN vlong textsize;
|
||||
EXTERN long thunk;
|
||||
EXTERN int version;
|
||||
EXTERN Prog zprg;
|
||||
EXTERN int dtype;
|
||||
EXTERN char* paramspace;
|
||||
|
||||
EXTERN Adr* reloca;
|
||||
EXTERN int doexp, dlm;
|
||||
EXTERN int imports, nimports;
|
||||
EXTERN int exports, nexports;
|
||||
EXTERN char* EXPTAB;
|
||||
EXTERN Prog undefp;
|
||||
|
||||
#define UP (&undefp)
|
||||
|
||||
extern Optab optab[];
|
||||
extern Optab* opindex[];
|
||||
extern char* anames[];
|
||||
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Pconv(Fmt*);
|
||||
int Rconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
void addhist(long, int);
|
||||
Prog* appendp(Prog*);
|
||||
void asmb(void);
|
||||
void asmdyn(void);
|
||||
void asmins(Prog*);
|
||||
void asmlc(void);
|
||||
void asmsp(void);
|
||||
void asmsym(void);
|
||||
vlong atolwhex(char*);
|
||||
Prog* brchain(Prog*);
|
||||
Prog* brloop(Prog*);
|
||||
void buildop(void);
|
||||
void cflush(void);
|
||||
void ckoff(Sym*, long);
|
||||
Prog* copyp(Prog*);
|
||||
double cputime(void);
|
||||
void datblk(long, long);
|
||||
void diag(char*, ...);
|
||||
void dodata(void);
|
||||
void doinit(void);
|
||||
void doprof1(void);
|
||||
void doprof2(void);
|
||||
void dostkoff(void);
|
||||
void dynreloc(Sym*, ulong, int);
|
||||
vlong entryvalue(void);
|
||||
void errorexit(void);
|
||||
void export(void);
|
||||
int find1(long, int);
|
||||
int find2(long, int);
|
||||
void follow(void);
|
||||
void gethunk(void);
|
||||
void histtoauto(void);
|
||||
double ieeedtod(Ieee*);
|
||||
long ieeedtof(Ieee*);
|
||||
void import(void);
|
||||
void ldobj(int, long, char*);
|
||||
void loadlib(void);
|
||||
void listinit(void);
|
||||
Sym* lookup(char*, int);
|
||||
void lput(long);
|
||||
void lputl(long);
|
||||
void main(int, char*[]);
|
||||
void mkfwd(void);
|
||||
void* mysbrk(ulong);
|
||||
void nuxiinit(void);
|
||||
void objfile(char*);
|
||||
int opsize(Prog*);
|
||||
void patch(void);
|
||||
Prog* prg(void);
|
||||
void readundefs(char*, int);
|
||||
int relinv(int);
|
||||
long reuse(Prog*, Sym*);
|
||||
vlong rnd(vlong, vlong);
|
||||
void span(void);
|
||||
void undef(void);
|
||||
void undefsym(Sym*);
|
||||
vlong vaddr(Adr*);
|
||||
void wput(ushort);
|
||||
void xdefine(char*, int, vlong);
|
||||
void xfol(Prog*);
|
||||
int zaddr(uchar*, Adr*, Sym*[]);
|
||||
void zerosig(char*);
|
|
@ -0,0 +1,350 @@
|
|||
#include "l.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('R', Rconv);
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('D', Dconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('P', Pconv);
|
||||
}
|
||||
|
||||
static Prog *bigP;
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Prog *p;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(p->from.scale) {
|
||||
sprint(str, "(%ld) %A %D,%d,%D",
|
||||
p->line, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sprint(str, "(%ld) %A %D,%D",
|
||||
p->line, p->as, &p->from, &p->to);
|
||||
break;
|
||||
case ADATA:
|
||||
case AINIT:
|
||||
case ADYNT:
|
||||
sprint(str, "(%ld) %A %D/%d,%D",
|
||||
p->line, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
bigP = P;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = va_arg(fp->args, int);
|
||||
return fmtstrcpy(fp, anames[i]);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
Adr *a;
|
||||
int i;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%lld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
if(bigP != P && bigP->pcond != P)
|
||||
if(a->sym != S)
|
||||
sprint(str, "%llux+%s", bigP->pcond->pc,
|
||||
a->sym->name);
|
||||
else
|
||||
sprint(str, "%llux", bigP->pcond->pc);
|
||||
else
|
||||
sprint(str, "%lld(PC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%s<%d>+%lld(SB)", a->sym->name,
|
||||
a->sym->version, a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym)
|
||||
sprint(str, "%s+%lld(%s)", a->sym->name, a->offset, paramspace);
|
||||
else
|
||||
sprint(str, "%lld(%s)", a->offset, paramspace);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->scon);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", a->index, a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
char* regstr[] =
|
||||
{
|
||||
"AL", /* [D_AL] */
|
||||
"CL",
|
||||
"DL",
|
||||
"BL",
|
||||
"SPB",
|
||||
"BPB",
|
||||
"SIB",
|
||||
"DIB",
|
||||
"R8B",
|
||||
"R9B",
|
||||
"R10B",
|
||||
"R11B",
|
||||
"R12B",
|
||||
"R13B",
|
||||
"R14B",
|
||||
"R15B",
|
||||
|
||||
"AX", /* [D_AX] */
|
||||
"CX",
|
||||
"DX",
|
||||
"BX",
|
||||
"SP",
|
||||
"BP",
|
||||
"SI",
|
||||
"DI",
|
||||
"R8",
|
||||
"R9",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
|
||||
"AH",
|
||||
"CH",
|
||||
"DH",
|
||||
"BH",
|
||||
|
||||
"F0", /* [D_F0] */
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
|
||||
"M0",
|
||||
"M1",
|
||||
"M2",
|
||||
"M3",
|
||||
"M4",
|
||||
"M5",
|
||||
"M6",
|
||||
"M7",
|
||||
|
||||
"X0",
|
||||
"X1",
|
||||
"X2",
|
||||
"X3",
|
||||
"X4",
|
||||
"X5",
|
||||
"X6",
|
||||
"X7",
|
||||
"X8",
|
||||
"X9",
|
||||
"X10",
|
||||
"X11",
|
||||
"X12",
|
||||
"X13",
|
||||
"X14",
|
||||
"X15",
|
||||
|
||||
"CS", /* [D_CS] */
|
||||
"SS",
|
||||
"DS",
|
||||
"ES",
|
||||
"FS",
|
||||
"GS",
|
||||
|
||||
"GDTR", /* [D_GDTR] */
|
||||
"IDTR", /* [D_IDTR] */
|
||||
"LDTR", /* [D_LDTR] */
|
||||
"MSW", /* [D_MSW] */
|
||||
"TASK", /* [D_TASK] */
|
||||
|
||||
"CR0", /* [D_CR] */
|
||||
"CR1",
|
||||
"CR2",
|
||||
"CR3",
|
||||
"CR4",
|
||||
"CR5",
|
||||
"CR6",
|
||||
"CR7",
|
||||
"CR8",
|
||||
"CR9",
|
||||
"CR10",
|
||||
"CR11",
|
||||
"CR12",
|
||||
"CR13",
|
||||
"CR14",
|
||||
"CR15",
|
||||
|
||||
"DR0", /* [D_DR] */
|
||||
"DR1",
|
||||
"DR2",
|
||||
"DR3",
|
||||
"DR4",
|
||||
"DR5",
|
||||
"DR6",
|
||||
"DR7",
|
||||
|
||||
"TR0", /* [D_TR] */
|
||||
"TR1",
|
||||
"TR2",
|
||||
"TR3",
|
||||
"TR4",
|
||||
"TR5",
|
||||
"TR6",
|
||||
"TR7",
|
||||
|
||||
"NONE", /* [D_NONE] */
|
||||
};
|
||||
|
||||
int
|
||||
Rconv(Fmt *fp)
|
||||
{
|
||||
char str[20];
|
||||
int r;
|
||||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[30], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<sizeof(double); i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
default:
|
||||
if(c < 040 || c >= 0177)
|
||||
break; /* not portable */
|
||||
p[-1] = c;
|
||||
continue;
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
void
|
||||
diag(char *fmt, ...)
|
||||
{
|
||||
char buf[STRINGSZ], *tn;
|
||||
va_list arg;
|
||||
|
||||
tn = "??none??";
|
||||
if(curtext != P && curtext->from.sym != S)
|
||||
tn = curtext->from.sym->name;
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+sizeof(buf), fmt, arg);
|
||||
va_end(arg);
|
||||
print("%s: %s\n", tn, buf);
|
||||
|
||||
nerrors++;
|
||||
if(nerrors > 20) {
|
||||
print("too many errors\n");
|
||||
errorexit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=6l
|
||||
OFILES=\
|
||||
asm.$O\
|
||||
obj.$O\
|
||||
optab.$O\
|
||||
pass.$O\
|
||||
span.$O\
|
||||
list.$O\
|
||||
enam.$O\
|
||||
compat.$O\
|
||||
|
||||
HFILES=\
|
||||
l.h\
|
||||
../6c/6.out.h\
|
||||
|
||||
BIN=/$objtype/bin
|
||||
CFILES=${OFILES:%.$O=%.c}
|
||||
CFILES=${CFILES:enam.c=../6c/enam.c}
|
||||
UPDATE=\
|
||||
mkfile\
|
||||
$HFILES\
|
||||
$CFILES\
|
||||
${TARG:%=/386/bin/%}\
|
||||
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
enam.$O: ../6c/enam.c
|
||||
$CC $CFLAGS ../6c/enam.c
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,790 @@
|
|||
#include "l.h"
|
||||
|
||||
void
|
||||
dodata(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
long t, u;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f dodata\n", cputime());
|
||||
Bflush(&bso);
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
s = p->from.sym;
|
||||
if(p->as == ADYNT || p->as == AINIT)
|
||||
s->value = dtype;
|
||||
if(s->type == SBSS)
|
||||
s->type = SDATA;
|
||||
if(s->type != SDATA)
|
||||
diag("initialize non-data (%d): %s\n%P",
|
||||
s->type, s->name, p);
|
||||
t = p->from.offset + p->width;
|
||||
if(t > s->value)
|
||||
diag("initialize bounds (%lld): %s\n%P",
|
||||
s->value, s->name, p);
|
||||
}
|
||||
/* allocate small guys */
|
||||
datsize = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SDATA)
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t == 0) {
|
||||
diag("%s: no size", s->name);
|
||||
t = 1;
|
||||
}
|
||||
t = rnd(t, 4);
|
||||
s->value = t;
|
||||
if(t > MINSIZ)
|
||||
continue;
|
||||
if(t >= 8)
|
||||
datsize = rnd(datsize, 8);
|
||||
s->value = datsize;
|
||||
datsize += t;
|
||||
s->type = SDATA1;
|
||||
}
|
||||
|
||||
/* allocate the rest of the data */
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SDATA) {
|
||||
if(s->type == SDATA1)
|
||||
s->type = SDATA;
|
||||
continue;
|
||||
}
|
||||
t = s->value;
|
||||
if(t >= 8)
|
||||
datsize = rnd(datsize, 8);
|
||||
s->value = datsize;
|
||||
datsize += t;
|
||||
}
|
||||
if(datsize)
|
||||
datsize = rnd(datsize, 8);
|
||||
|
||||
if(debug['j']) {
|
||||
/*
|
||||
* pad data with bss that fits up to next
|
||||
* 8k boundary, then push data to 8k
|
||||
*/
|
||||
u = rnd(datsize, 8192);
|
||||
u -= datsize;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t > u)
|
||||
continue;
|
||||
u -= t;
|
||||
s->value = datsize;
|
||||
s->type = SDATA;
|
||||
datsize += t;
|
||||
}
|
||||
datsize += u;
|
||||
}
|
||||
|
||||
/* now the bss */
|
||||
bsssize = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link) {
|
||||
if(s->type != SBSS)
|
||||
continue;
|
||||
t = s->value;
|
||||
if(t >= 8)
|
||||
bsssize = rnd(bsssize, 8);
|
||||
s->value = bsssize + datsize;
|
||||
bsssize += t;
|
||||
}
|
||||
xdefine("edata", SBSS, datsize);
|
||||
xdefine("end", SBSS, bsssize + datsize);
|
||||
}
|
||||
|
||||
Prog*
|
||||
brchain(Prog *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<20; i++) {
|
||||
if(p == P || p->as != AJMP)
|
||||
return p;
|
||||
p = p->pcond;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
void
|
||||
follow(void)
|
||||
{
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f follow\n", cputime());
|
||||
Bflush(&bso);
|
||||
firstp = prg();
|
||||
lastp = firstp;
|
||||
xfol(textp);
|
||||
lastp->link = P;
|
||||
firstp = firstp->link;
|
||||
}
|
||||
|
||||
void
|
||||
xfol(Prog *p)
|
||||
{
|
||||
Prog *q;
|
||||
int i;
|
||||
enum as a;
|
||||
|
||||
loop:
|
||||
if(p == P)
|
||||
return;
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->as == AJMP)
|
||||
if((q = p->pcond) != P) {
|
||||
p->mark = 1;
|
||||
p = q;
|
||||
if(p->mark == 0)
|
||||
goto loop;
|
||||
}
|
||||
if(p->mark) {
|
||||
/* copy up to 4 instructions to avoid branch */
|
||||
for(i=0,q=p; i<4; i++,q=q->link) {
|
||||
if(q == P)
|
||||
break;
|
||||
if(q == lastp)
|
||||
break;
|
||||
a = q->as;
|
||||
if(a == ANOP) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
switch(a) {
|
||||
case AJMP:
|
||||
case ARET:
|
||||
case AIRETL:
|
||||
case AIRETQ:
|
||||
case AIRETW:
|
||||
case ARETFL:
|
||||
case ARETFQ:
|
||||
case ARETFW:
|
||||
|
||||
case APUSHL:
|
||||
case APUSHFL:
|
||||
case APUSHQ:
|
||||
case APUSHFQ:
|
||||
case APUSHW:
|
||||
case APUSHFW:
|
||||
case APOPL:
|
||||
case APOPFL:
|
||||
case APOPQ:
|
||||
case APOPFQ:
|
||||
case APOPW:
|
||||
case APOPFW:
|
||||
goto brk;
|
||||
}
|
||||
if(q->pcond == P || q->pcond->mark)
|
||||
continue;
|
||||
if(a == ACALL || a == ALOOP)
|
||||
continue;
|
||||
for(;;) {
|
||||
if(p->as == ANOP) {
|
||||
p = p->link;
|
||||
continue;
|
||||
}
|
||||
q = copyp(p);
|
||||
p = p->link;
|
||||
q->mark = 1;
|
||||
lastp->link = q;
|
||||
lastp = q;
|
||||
if(q->as != a || q->pcond == P || q->pcond->mark)
|
||||
continue;
|
||||
|
||||
q->as = relinv(q->as);
|
||||
p = q->pcond;
|
||||
q->pcond = q->link;
|
||||
q->link = p;
|
||||
xfol(q->link);
|
||||
p = q->link;
|
||||
if(p->mark)
|
||||
return;
|
||||
goto loop;
|
||||
}
|
||||
} /* */
|
||||
brk:;
|
||||
q = prg();
|
||||
q->as = AJMP;
|
||||
q->line = p->line;
|
||||
q->to.type = D_BRANCH;
|
||||
q->to.offset = p->pc;
|
||||
q->pcond = p;
|
||||
p = q;
|
||||
}
|
||||
p->mark = 1;
|
||||
lastp->link = p;
|
||||
lastp = p;
|
||||
a = p->as;
|
||||
if(a == AJMP || a == ARET || a == AIRETL || a == AIRETQ || a == AIRETW ||
|
||||
a == ARETFL || a == ARETFQ || a == ARETFW)
|
||||
return;
|
||||
if(p->pcond != P)
|
||||
if(a != ACALL) {
|
||||
q = brchain(p->link);
|
||||
if(q != P && q->mark)
|
||||
if(a != ALOOP) {
|
||||
p->as = relinv(a);
|
||||
p->link = p->pcond;
|
||||
p->pcond = q;
|
||||
}
|
||||
xfol(p->link);
|
||||
q = brchain(p->pcond);
|
||||
if(q->mark) {
|
||||
p->pcond = q;
|
||||
return;
|
||||
}
|
||||
p = q;
|
||||
goto loop;
|
||||
}
|
||||
p = p->link;
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
relinv(int a)
|
||||
{
|
||||
|
||||
switch(a) {
|
||||
case AJEQ: return AJNE;
|
||||
case AJNE: return AJEQ;
|
||||
case AJLE: return AJGT;
|
||||
case AJLS: return AJHI;
|
||||
case AJLT: return AJGE;
|
||||
case AJMI: return AJPL;
|
||||
case AJGE: return AJLT;
|
||||
case AJPL: return AJMI;
|
||||
case AJGT: return AJLE;
|
||||
case AJHI: return AJLS;
|
||||
case AJCS: return AJCC;
|
||||
case AJCC: return AJCS;
|
||||
case AJPS: return AJPC;
|
||||
case AJPC: return AJPS;
|
||||
case AJOS: return AJOC;
|
||||
case AJOC: return AJOS;
|
||||
}
|
||||
diag("unknown relation: %s in %s", anames[a], TNAME);
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
doinit(void)
|
||||
{
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
int x;
|
||||
|
||||
for(p = datap; p != P; p = p->link) {
|
||||
x = p->to.type;
|
||||
if(x != D_EXTERN && x != D_STATIC)
|
||||
continue;
|
||||
s = p->to.sym;
|
||||
if(s->type == 0 || s->type == SXREF)
|
||||
diag("undefined %s initializer of %s",
|
||||
s->name, p->from.sym->name);
|
||||
p->to.offset += s->value;
|
||||
p->to.type = D_CONST;
|
||||
if(s->type == SDATA || s->type == SBSS)
|
||||
p->to.offset += INITDAT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
patch(void)
|
||||
{
|
||||
long c;
|
||||
Prog *p, *q;
|
||||
Sym *s;
|
||||
long vexit;
|
||||
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f mkfwd\n", cputime());
|
||||
Bflush(&bso);
|
||||
mkfwd();
|
||||
if(debug['v'])
|
||||
Bprint(&bso, "%5.2f patch\n", cputime());
|
||||
Bflush(&bso);
|
||||
s = lookup("exit", 0);
|
||||
vexit = s->value;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
if(p->as == ACALL || p->as == ARET) {
|
||||
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);
|
||||
s->type = STEXT;
|
||||
s->value = vexit;
|
||||
break; /* or fall through to set offset? */
|
||||
case STEXT:
|
||||
p->to.offset = s->value;
|
||||
break;
|
||||
case SUNDEF:
|
||||
p->pcond = UP;
|
||||
p->to.offset = 0;
|
||||
break;
|
||||
}
|
||||
p->to.type = D_BRANCH;
|
||||
}
|
||||
}
|
||||
if(p->to.type != D_BRANCH || p->pcond == UP)
|
||||
continue;
|
||||
c = p->to.offset;
|
||||
for(q = firstp; q != P;) {
|
||||
if(q->forwd != P)
|
||||
if(c >= q->forwd->pc) {
|
||||
q = q->forwd;
|
||||
continue;
|
||||
}
|
||||
if(c == q->pc)
|
||||
break;
|
||||
q = q->link;
|
||||
}
|
||||
if(q == P) {
|
||||
diag("branch out of range in %s\n%P", TNAME, p);
|
||||
p->to.type = D_NONE;
|
||||
}
|
||||
p->pcond = q;
|
||||
}
|
||||
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
p->mark = 0; /* initialization for follow */
|
||||
if(p->pcond != P && p->pcond != UP) {
|
||||
p->pcond = brloop(p->pcond);
|
||||
if(p->pcond != P)
|
||||
if(p->to.type == D_BRANCH)
|
||||
p->to.offset = p->pcond->pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LOG 5
|
||||
void
|
||||
mkfwd(void)
|
||||
{
|
||||
Prog *p;
|
||||
int i;
|
||||
long dwn[LOG], cnt[LOG];
|
||||
Prog *lst[LOG];
|
||||
|
||||
for(i=0; i<LOG; i++) {
|
||||
if(i == 0)
|
||||
cnt[i] = 1; else
|
||||
cnt[i] = LOG * cnt[i-1];
|
||||
dwn[i] = 1;
|
||||
lst[i] = P;
|
||||
}
|
||||
i = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT)
|
||||
curtext = p;
|
||||
i--;
|
||||
if(i < 0)
|
||||
i = LOG-1;
|
||||
p->forwd = P;
|
||||
dwn[i]--;
|
||||
if(dwn[i] <= 0) {
|
||||
dwn[i] = cnt[i];
|
||||
if(lst[i] != P)
|
||||
lst[i]->forwd = p;
|
||||
lst[i] = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Prog*
|
||||
brloop(Prog *p)
|
||||
{
|
||||
int c;
|
||||
Prog *q;
|
||||
|
||||
c = 0;
|
||||
for(q = p; q != P; q = q->pcond) {
|
||||
if(q->as != AJMP)
|
||||
break;
|
||||
c++;
|
||||
if(c >= 5000)
|
||||
return P;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
dostkoff(void)
|
||||
{
|
||||
Prog *p, *q;
|
||||
long autoffset, deltasp;
|
||||
int a, f, curframe, curbecome, maxbecome, pcsize;
|
||||
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
maxbecome = 0;
|
||||
curtext = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
|
||||
/* find out how much arg space is used in this TEXT */
|
||||
if(p->to.type == (D_INDIR+D_SP))
|
||||
if(p->to.offset > curframe)
|
||||
curframe = p->to.offset;
|
||||
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
curframe = 0;
|
||||
curbecome = 0;
|
||||
|
||||
curtext = p;
|
||||
break;
|
||||
|
||||
case ARET:
|
||||
/* special form of RET is BECOME */
|
||||
if(p->from.type == D_CONST)
|
||||
if(p->from.offset > curbecome)
|
||||
curbecome = p->from.offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(curtext && curtext->from.sym) {
|
||||
curtext->from.sym->frame = curframe;
|
||||
curtext->from.sym->become = curbecome;
|
||||
if(curbecome > maxbecome)
|
||||
maxbecome = curbecome;
|
||||
}
|
||||
|
||||
if(debug['b'])
|
||||
print("max become = %d\n", maxbecome);
|
||||
xdefine("ALEFbecome", STEXT, maxbecome);
|
||||
|
||||
curtext = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
switch(p->as) {
|
||||
case ATEXT:
|
||||
curtext = p;
|
||||
break;
|
||||
case ACALL:
|
||||
if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
|
||||
f = maxbecome - curtext->from.sym->frame;
|
||||
if(f <= 0)
|
||||
break;
|
||||
/* calling a become or calling a variable */
|
||||
if(p->to.sym == S || p->to.sym->become) {
|
||||
curtext->to.offset += f;
|
||||
if(debug['b']) {
|
||||
curp = p;
|
||||
print("%D calling %D increase %d\n",
|
||||
&curtext->from, &p->to, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
autoffset = 0;
|
||||
deltasp = 0;
|
||||
for(p = firstp; p != P; p = p->link) {
|
||||
if(p->as == ATEXT) {
|
||||
curtext = p;
|
||||
autoffset = p->to.offset;
|
||||
if(autoffset < 0)
|
||||
autoffset = 0;
|
||||
if(autoffset) {
|
||||
p = appendp(p);
|
||||
p->as = AADJSP;
|
||||
p->from.type = D_CONST;
|
||||
p->from.offset = autoffset;
|
||||
}
|
||||
deltasp = autoffset;
|
||||
}
|
||||
pcsize = p->mode/8;
|
||||
a = p->from.type;
|
||||
if(a == D_AUTO)
|
||||
p->from.offset += deltasp;
|
||||
if(a == D_PARAM)
|
||||
p->from.offset += deltasp + pcsize;
|
||||
a = p->to.type;
|
||||
if(a == D_AUTO)
|
||||
p->to.offset += deltasp;
|
||||
if(a == D_PARAM)
|
||||
p->to.offset += deltasp + pcsize;
|
||||
|
||||
switch(p->as) {
|
||||
default:
|
||||
continue;
|
||||
case APUSHL:
|
||||
case APUSHFL:
|
||||
deltasp += 4;
|
||||
continue;
|
||||
case APUSHQ:
|
||||
case APUSHFQ:
|
||||
deltasp += 8;
|
||||
continue;
|
||||
case APUSHW:
|
||||
case APUSHFW:
|
||||
deltasp += 2;
|
||||
continue;
|
||||
case APOPL:
|
||||
case APOPFL:
|
||||
deltasp -= 4;
|
||||
continue;
|
||||
case APOPQ:
|
||||
case APOPFQ:
|
||||
deltasp -= 8;
|
||||
continue;
|
||||
case APOPW:
|
||||
case APOPFW:
|
||||
deltasp -= 2;
|
||||
continue;
|
||||
case ARET:
|
||||
break;
|
||||
}
|
||||
|
||||
if(autoffset != deltasp)
|
||||
diag("unbalanced PUSH/POP");
|
||||
if(p->from.type == D_CONST)
|
||||
goto become;
|
||||
|
||||
if(autoffset) {
|
||||
q = p;
|
||||
p = appendp(p);
|
||||
p->as = ARET;
|
||||
|
||||
q->as = AADJSP;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = -autoffset;
|
||||
}
|
||||
continue;
|
||||
|
||||
become:
|
||||
q = p;
|
||||
p = appendp(p);
|
||||
p->as = AJMP;
|
||||
p->to = q->to;
|
||||
p->pcond = q->pcond;
|
||||
|
||||
q->as = AADJSP;
|
||||
q->from = zprg.from;
|
||||
q->from.type = D_CONST;
|
||||
q->from.offset = -autoffset;
|
||||
q->to = zprg.to;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vlong
|
||||
atolwhex(char *s)
|
||||
{
|
||||
vlong n;
|
||||
int f;
|
||||
|
||||
n = 0;
|
||||
f = 0;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
if(*s == '-' || *s == '+') {
|
||||
if(*s++ == '-')
|
||||
f = 1;
|
||||
while(*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
}
|
||||
if(s[0]=='0' && s[1]){
|
||||
if(s[1]=='x' || s[1]=='X'){
|
||||
s += 2;
|
||||
for(;;){
|
||||
if(*s >= '0' && *s <= '9')
|
||||
n = n*16 + *s++ - '0';
|
||||
else if(*s >= 'a' && *s <= 'f')
|
||||
n = n*16 + *s++ - 'a' + 10;
|
||||
else if(*s >= 'A' && *s <= 'F')
|
||||
n = n*16 + *s++ - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else
|
||||
while(*s >= '0' && *s <= '7')
|
||||
n = n*8 + *s++ - '0';
|
||||
} else
|
||||
while(*s >= '0' && *s <= '9')
|
||||
n = n*10 + *s++ - '0';
|
||||
if(f)
|
||||
n = -n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
undef(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i=0; i<NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->type == SXREF)
|
||||
diag("%s: not defined", s->name);
|
||||
}
|
||||
|
||||
void
|
||||
import(void)
|
||||
{
|
||||
int i;
|
||||
Sym *s;
|
||||
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
|
||||
if(s->value != 0)
|
||||
diag("value != 0 on SXREF");
|
||||
undefsym(s);
|
||||
Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, s->value);
|
||||
if(debug['S'])
|
||||
s->sig = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ckoff(Sym *s, long v)
|
||||
{
|
||||
if(v < 0 || v >= 1<<Roffset)
|
||||
diag("relocation offset %ld for %s out of range", v, s->name);
|
||||
}
|
||||
|
||||
static Prog*
|
||||
newdata(Sym *s, int o, int w, int t)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = prg();
|
||||
if(edatap == P)
|
||||
datap = p;
|
||||
else
|
||||
edatap->link = p;
|
||||
edatap = p;
|
||||
p->as = ADATA;
|
||||
p->width = w;
|
||||
p->from.scale = w;
|
||||
p->from.type = t;
|
||||
p->from.sym = s;
|
||||
p->from.offset = o;
|
||||
p->to.type = D_CONST;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
export(void)
|
||||
{
|
||||
int i, j, n, off, nb, sv, ne;
|
||||
Sym *s, *et, *str, **esyms;
|
||||
Prog *p;
|
||||
char buf[NSNAME], *t;
|
||||
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
n++;
|
||||
esyms = malloc(n*sizeof(Sym*));
|
||||
ne = n;
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
esyms[n++] = s;
|
||||
for(i = 0; i < ne-1; i++)
|
||||
for(j = i+1; j < ne; j++)
|
||||
if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
|
||||
s = esyms[i];
|
||||
esyms[i] = esyms[j];
|
||||
esyms[j] = s;
|
||||
}
|
||||
|
||||
nb = 0;
|
||||
off = 0;
|
||||
et = lookup(EXPTAB, 0);
|
||||
if(et->type != 0 && et->type != SXREF)
|
||||
diag("%s already defined", EXPTAB);
|
||||
et->type = SDATA;
|
||||
str = lookup(".string", 0);
|
||||
if(str->type == 0)
|
||||
str->type = SDATA;
|
||||
sv = str->value;
|
||||
for(i = 0; i < ne; i++){
|
||||
s = esyms[i];
|
||||
if(debug['S'])
|
||||
s->sig = 0;
|
||||
/* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */
|
||||
|
||||
/* signature */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.offset = s->sig;
|
||||
|
||||
/* address */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.type = D_ADDR;
|
||||
p->to.index = D_EXTERN;
|
||||
p->to.sym = s;
|
||||
|
||||
/* string */
|
||||
t = s->name;
|
||||
n = strlen(t)+1;
|
||||
for(;;){
|
||||
buf[nb++] = *t;
|
||||
sv++;
|
||||
if(nb >= NSNAME){
|
||||
p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.scon, buf, NSNAME);
|
||||
nb = 0;
|
||||
}
|
||||
if(*t++ == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* name */
|
||||
p = newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
p->to.type = D_ADDR;
|
||||
p->to.index = D_STATIC;
|
||||
p->to.sym = str;
|
||||
p->to.offset = sv-n;
|
||||
}
|
||||
|
||||
if(nb > 0){
|
||||
p = newdata(str, sv-nb, nb, D_STATIC);
|
||||
p->to.type = D_SCONST;
|
||||
memmove(p->to.scon, buf, nb);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
newdata(et, off, sizeof(long), D_EXTERN);
|
||||
off += sizeof(long);
|
||||
}
|
||||
et->value = off;
|
||||
if(sv == 0)
|
||||
sv = 1;
|
||||
str->value = sv;
|
||||
exports = ne;
|
||||
free(esyms);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -58,7 +58,7 @@ struct Prog
|
|||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
|
@ -67,7 +67,7 @@ struct Case
|
|||
|
||||
struct C1
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8lux\n", q->val);
|
||||
print("case = %.8llux\n", q->val);
|
||||
if(bval(q->val)) {
|
||||
gopcode(OEQ, n, Z, nodconst(q->val));
|
||||
} else {
|
||||
|
@ -53,7 +53,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
swit2(r, nc-i, def, n, tn);
|
||||
}
|
||||
/* if(debug['W'])
|
||||
print("case > %.8lux\n", r->val);
|
||||
print("case > %.8llux\n", r->val);
|
||||
gmove(nodconst(r->val), tn);
|
||||
gopcode(OLT, tn, n, Z);
|
||||
sp = p;
|
||||
|
@ -62,7 +62,7 @@ swit2(C1 *q, int nc, long def, Node *n, Node *tn)
|
|||
swit2(q, i, def, n, tn);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8lux\n", r->val);
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit2(r+1, nc-i-1, def, n, tn); */
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ struct Gen
|
|||
double dval;
|
||||
char sval[8];
|
||||
long offset;
|
||||
long offset2;
|
||||
Sym* sym;
|
||||
short type;
|
||||
short index;
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
%union {
|
||||
Sym *sym;
|
||||
long lval;
|
||||
struct {
|
||||
long v1;
|
||||
long v2;
|
||||
} con2;
|
||||
double dval;
|
||||
char sval[8];
|
||||
Gen gen;
|
||||
|
@ -16,16 +20,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
|
||||
|
@ -73,6 +78,7 @@ inst:
|
|||
| LTYPES spec5 { outcode($1, &$2); }
|
||||
| LTYPEM spec6 { outcode($1, &$2); }
|
||||
| LTYPEI spec7 { outcode($1, &$2); }
|
||||
| LTYPEG spec8 { outcode($1, &$2); }
|
||||
|
||||
nonnon:
|
||||
{
|
||||
|
@ -219,6 +225,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
|
||||
|
@ -236,6 +255,7 @@ rom:
|
|||
}
|
||||
| reg
|
||||
| omem
|
||||
| imm
|
||||
|
||||
rim:
|
||||
rem
|
||||
|
@ -335,6 +355,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
|
||||
|
@ -386,6 +437,12 @@ omem:
|
|||
$$ = nullgen;
|
||||
$$.type = D_INDIR+D_SP;
|
||||
}
|
||||
| con '(' LSREG ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_INDIR+$3;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| '(' LLREG '*' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
|
|
|
@ -221,7 +221,7 @@ TEXT mode32bit(SB),$0
|
|||
* 16 meg of physical memory
|
||||
*/
|
||||
LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
|
||||
ADDL $(BY2PG-1),AX /* must be page alligned */
|
||||
ADDL $(BY2PG-1),AX /* must be page aligned */
|
||||
ANDL $(~(BY2PG-1)),AX /* ... */
|
||||
MOVL $(4*1024),CX /* pte's per page */
|
||||
MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
|
||||
|
|
|
@ -274,6 +274,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,
|
||||
|
@ -285,14 +288,14 @@ 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,
|
||||
"IDIVW", LTYPE2, AIDIVW,
|
||||
"IMULB", LTYPE2, AIMULB,
|
||||
"IMULL", LTYPE2, AIMULL,
|
||||
"IMULW", LTYPE2, AIMULW,
|
||||
"IMULB", LTYPEI, AIMULB,
|
||||
"IMULL", LTYPEI, AIMULL,
|
||||
"IMULW", LTYPEI, AIMULW,
|
||||
"INB", LTYPE0, AINB,
|
||||
"INL", LTYPE0, AINL,
|
||||
"INW", LTYPE0, AINW,
|
||||
|
@ -493,6 +496,39 @@ struct
|
|||
"XORL", LTYPE3, AXORL,
|
||||
"XORW", LTYPE3, AXORW,
|
||||
|
||||
"CMOVLCC", LTYPE3, ACMOVLCC,
|
||||
"CMOVLCS", LTYPE3, ACMOVLCS,
|
||||
"CMOVLEQ", LTYPE3, ACMOVLEQ,
|
||||
"CMOVLGE", LTYPE3, ACMOVLGE,
|
||||
"CMOVLGT", LTYPE3, ACMOVLGT,
|
||||
"CMOVLHI", LTYPE3, ACMOVLHI,
|
||||
"CMOVLLE", LTYPE3, ACMOVLLE,
|
||||
"CMOVLLS", LTYPE3, ACMOVLLS,
|
||||
"CMOVLLT", LTYPE3, ACMOVLLT,
|
||||
"CMOVLMI", LTYPE3, ACMOVLMI,
|
||||
"CMOVLNE", LTYPE3, ACMOVLNE,
|
||||
"CMOVLOC", LTYPE3, ACMOVLOC,
|
||||
"CMOVLOS", LTYPE3, ACMOVLOS,
|
||||
"CMOVLPC", LTYPE3, ACMOVLPC,
|
||||
"CMOVLPL", LTYPE3, ACMOVLPL,
|
||||
"CMOVLPS", LTYPE3, ACMOVLPS,
|
||||
"CMOVWCC", LTYPE3, ACMOVWCC,
|
||||
"CMOVWCS", LTYPE3, ACMOVWCS,
|
||||
"CMOVWEQ", LTYPE3, ACMOVWEQ,
|
||||
"CMOVWGE", LTYPE3, ACMOVWGE,
|
||||
"CMOVWGT", LTYPE3, ACMOVWGT,
|
||||
"CMOVWHI", LTYPE3, ACMOVWHI,
|
||||
"CMOVWLE", LTYPE3, ACMOVWLE,
|
||||
"CMOVWLS", LTYPE3, ACMOVWLS,
|
||||
"CMOVWLT", LTYPE3, ACMOVWLT,
|
||||
"CMOVWMI", LTYPE3, ACMOVWMI,
|
||||
"CMOVWNE", LTYPE3, ACMOVWNE,
|
||||
"CMOVWOC", LTYPE3, ACMOVWOC,
|
||||
"CMOVWOS", LTYPE3, ACMOVWOS,
|
||||
"CMOVWPC", LTYPE3, ACMOVWPC,
|
||||
"CMOVWPL", LTYPE3, ACMOVWPL,
|
||||
"CMOVWPS", LTYPE3, ACMOVWPS,
|
||||
|
||||
"FMOVB", LTYPE3, AFMOVB,
|
||||
"FMOVBP", LTYPE3, AFMOVBP,
|
||||
"FMOVD", LTYPE3, AFMOVD,
|
||||
|
@ -507,6 +543,14 @@ struct
|
|||
"FMOVWP", LTYPE3, AFMOVWP,
|
||||
"FMOVX", LTYPE3, AFMOVX,
|
||||
"FMOVXP", LTYPE3, AFMOVXP,
|
||||
"FCMOVCC", LTYPE3, AFCMOVCC,
|
||||
"FCMOVCS", LTYPE3, AFCMOVCS,
|
||||
"FCMOVEQ", LTYPE3, AFCMOVEQ,
|
||||
"FCMOVHI", LTYPE3, AFCMOVHI,
|
||||
"FCMOVLS", LTYPE3, AFCMOVLS,
|
||||
"FCMOVNE", LTYPE3, AFCMOVNE,
|
||||
"FCMOVNU", LTYPE3, AFCMOVNU,
|
||||
"FCMOVUN", LTYPE3, AFCMOVUN,
|
||||
"FCOMB", LTYPE3, AFCOMB,
|
||||
"FCOMBP", LTYPE3, AFCOMBP,
|
||||
"FCOMD", LTYPE3, AFCOMD,
|
||||
|
@ -514,11 +558,15 @@ struct
|
|||
"FCOMDPP", LTYPE3, AFCOMDPP,
|
||||
"FCOMF", LTYPE3, AFCOMF,
|
||||
"FCOMFP", LTYPE3, AFCOMFP,
|
||||
"FCOMI", LTYPE3, AFCOMI,
|
||||
"FCOMIP", LTYPE3, AFCOMIP,
|
||||
"FCOML", LTYPE3, AFCOML,
|
||||
"FCOMLP", LTYPE3, AFCOMLP,
|
||||
"FCOMW", LTYPE3, AFCOMW,
|
||||
"FCOMWP", LTYPE3, AFCOMWP,
|
||||
"FUCOM", LTYPE3, AFUCOM,
|
||||
"FUCOMI", LTYPE3, AFUCOMI,
|
||||
"FUCOMIP", LTYPE3, AFUCOMIP,
|
||||
"FUCOMP", LTYPE3, AFUCOMP,
|
||||
"FUCOMPP", LTYPE3, AFUCOMPP,
|
||||
"FADDW", LTYPE3, AFADDW,
|
||||
|
@ -704,6 +752,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;
|
||||
|
@ -723,6 +774,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) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define NSNAME 8
|
||||
#define NOPROF (1<<0)
|
||||
#define DUPOK (1<<1)
|
||||
#define NOSPLIT (1<<2)
|
||||
|
||||
enum as
|
||||
{
|
||||
|
@ -353,6 +354,58 @@ enum as
|
|||
|
||||
ASIGNAME,
|
||||
|
||||
AFCOMI,
|
||||
AFCOMIP,
|
||||
AFUCOMI,
|
||||
AFUCOMIP,
|
||||
ACMPXCHGB,
|
||||
ACMPXCHGL,
|
||||
ACMPXCHGW,
|
||||
|
||||
/* conditional move */
|
||||
ACMOVLCC,
|
||||
ACMOVLCS,
|
||||
ACMOVLEQ,
|
||||
ACMOVLGE,
|
||||
ACMOVLGT,
|
||||
ACMOVLHI,
|
||||
ACMOVLLE,
|
||||
ACMOVLLS,
|
||||
ACMOVLLT,
|
||||
ACMOVLMI,
|
||||
ACMOVLNE,
|
||||
ACMOVLOC,
|
||||
ACMOVLOS,
|
||||
ACMOVLPC,
|
||||
ACMOVLPL,
|
||||
ACMOVLPS,
|
||||
ACMOVWCC,
|
||||
ACMOVWCS,
|
||||
ACMOVWEQ,
|
||||
ACMOVWGE,
|
||||
ACMOVWGT,
|
||||
ACMOVWHI,
|
||||
ACMOVWLE,
|
||||
ACMOVWLS,
|
||||
ACMOVWLT,
|
||||
ACMOVWMI,
|
||||
ACMOVWNE,
|
||||
ACMOVWOC,
|
||||
ACMOVWOS,
|
||||
ACMOVWPC,
|
||||
ACMOVWPL,
|
||||
ACMOVWPS,
|
||||
|
||||
AFCMOVCC,
|
||||
AFCMOVCS,
|
||||
AFCMOVEQ,
|
||||
AFCMOVHI,
|
||||
AFCMOVLS,
|
||||
AFCMOVNE,
|
||||
AFCMOVNU,
|
||||
AFCMOVUN,
|
||||
|
||||
/* add new operations here. nowhere else. here. */
|
||||
ALAST
|
||||
};
|
||||
|
||||
|
@ -378,6 +431,7 @@ enum
|
|||
D_DI,
|
||||
|
||||
D_F0 = 16,
|
||||
D_F7 = D_F0 + 7,
|
||||
|
||||
D_CS = 24,
|
||||
D_SS,
|
||||
|
@ -413,12 +467,18 @@ enum
|
|||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
D_CONST2 = D_INDIR+D_INDIR,
|
||||
|
||||
D_SIZE, /* 8l internal */
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
T_FCONST = 1<<3,
|
||||
T_SYM = 1<<4,
|
||||
T_SCONST = 1<<5,
|
||||
T_OFFSET2 = 1<<6,
|
||||
T_GOTYPE = 1<<7,
|
||||
|
||||
REGARG = -1,
|
||||
REGRET = D_AX,
|
||||
|
|
|
@ -25,6 +25,12 @@ cgen(Node *n, Node *nn)
|
|||
l = n->left;
|
||||
r = n->right;
|
||||
o = n->op;
|
||||
// Go's version does the following, but it's the wrong place: doesn't allow assignment
|
||||
// if(o == OEXREG || nn != Z && nn->op == OEXREG) {
|
||||
// gmove(n, nn);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if(n->addable >= INDEXED) {
|
||||
if(nn == Z) {
|
||||
switch(o) {
|
||||
|
@ -244,7 +250,7 @@ cgen(Node *n, Node *nn)
|
|||
if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
|
||||
&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
|
||||
c = l->right->vconst;
|
||||
if(c > 0 && c <= 3) {
|
||||
if(c > 0 && c <= 3 && nareg(1) >= 4) {
|
||||
if(l->left->complex >= r->complex) {
|
||||
regalloc(&nod, l->left, nn);
|
||||
cgen(l->left, &nod);
|
||||
|
@ -887,6 +893,7 @@ cgen(Node *n, Node *nn)
|
|||
break;
|
||||
|
||||
case OFUNC:
|
||||
l = uncomma(l);
|
||||
if(l->complex >= FNX) {
|
||||
if(l->op != OIND)
|
||||
diag(n, "bad function call");
|
||||
|
@ -1824,6 +1831,12 @@ copy:
|
|||
gins(ACLD, Z, Z);
|
||||
gins(AREP, Z, Z);
|
||||
gins(AMOVSL, Z, Z);
|
||||
if(w & (SZ_LONG-1)) {
|
||||
/* odd length of packed structure */
|
||||
gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
|
||||
gins(AREP, Z, Z);
|
||||
gins(AMOVSB, Z, Z);
|
||||
}
|
||||
if(c & 4) {
|
||||
gins(APOPL, Z, &nod3);
|
||||
reg[D_CX]--;
|
||||
|
|
|
@ -188,70 +188,6 @@ storepair(Node *n, Node *nn, int f)
|
|||
freepair(n);
|
||||
}
|
||||
|
||||
/* generate a cast t from n to tt */
|
||||
static void
|
||||
cast(Node *n, Type *t, Node *nn)
|
||||
{
|
||||
Node *r;
|
||||
|
||||
r = new(OCAST, n, Z);
|
||||
r->type = t;
|
||||
sugen(r, nn, 8);
|
||||
}
|
||||
|
||||
static void
|
||||
swapregs(Node *a, Node *b)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = a->reg;
|
||||
a->reg = b->reg;
|
||||
b->reg = t;
|
||||
}
|
||||
|
||||
static void
|
||||
swappairs(Node *a, Node *b)
|
||||
{
|
||||
swapregs(a->left, b->left);
|
||||
swapregs(a->right, b->right);
|
||||
}
|
||||
|
||||
static int
|
||||
saveme(Node *n)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = n->reg;
|
||||
return r >= D_AX && r <= D_DI;
|
||||
}
|
||||
|
||||
static void
|
||||
saveit(Node *n, Node *t, Node *r)
|
||||
{
|
||||
Node nod;
|
||||
|
||||
if(saveme(n)) {
|
||||
t->reg = n->reg;
|
||||
gins(AMOVL, t, r);
|
||||
r->xoffset += SZ_LONG;
|
||||
if(n->reg == D_AX) {
|
||||
regalloc(&nod, n, Z);
|
||||
regfree(n);
|
||||
n->reg = nod.reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
restoreit(Node *n, Node *t, Node *r)
|
||||
{
|
||||
if(saveme(n)) {
|
||||
t->reg = n->reg;
|
||||
gins(AMOVL, r, t);
|
||||
r->xoffset += SZ_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
/* 4 only, see WW */
|
||||
|
@ -319,26 +255,6 @@ vfunc(Node *n, Node *nn)
|
|||
return t;
|
||||
}
|
||||
|
||||
static int
|
||||
forcereg(Node *d, int r, int o, Node *t)
|
||||
{
|
||||
int a;
|
||||
|
||||
if(d->reg != D_NONE)
|
||||
diag(Z, "force alloc");
|
||||
d->reg = r;
|
||||
a = 0;
|
||||
if(reg[r]) {
|
||||
reg[o]++;
|
||||
regalloc(t, d, Z);
|
||||
a = 1;
|
||||
gins(AMOVL, d, t);
|
||||
reg[o]--;
|
||||
}
|
||||
reg[r]++;
|
||||
return a;
|
||||
}
|
||||
|
||||
/* try to steal a reg */
|
||||
static int
|
||||
getreg(Node **np, Node *t, int r)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* SIGPLAN Notices, Vol. 29, June 1994, page 61.
|
||||
*/
|
||||
|
||||
#define TN(n) (1ULL << (n))
|
||||
#define TN(n) ((uvlong)1 << (n))
|
||||
#define T31 TN(31)
|
||||
#define T32 TN(32)
|
||||
|
||||
|
|
|
@ -333,5 +333,52 @@ char* anames[] =
|
|||
"DYNT",
|
||||
"INIT",
|
||||
"SIGNAME",
|
||||
"FCOMI",
|
||||
"FCOMIP",
|
||||
"FUCOMI",
|
||||
"FUCOMIP",
|
||||
"CMPXCHGB",
|
||||
"CMPXCHGL",
|
||||
"CMPXCHGW",
|
||||
"CMOVLCC",
|
||||
"CMOVLCS",
|
||||
"CMOVLEQ",
|
||||
"CMOVLGE",
|
||||
"CMOVLGT",
|
||||
"CMOVLHI",
|
||||
"CMOVLLE",
|
||||
"CMOVLLS",
|
||||
"CMOVLLT",
|
||||
"CMOVLMI",
|
||||
"CMOVLNE",
|
||||
"CMOVLOC",
|
||||
"CMOVLOS",
|
||||
"CMOVLPC",
|
||||
"CMOVLPL",
|
||||
"CMOVLPS",
|
||||
"CMOVWCC",
|
||||
"CMOVWCS",
|
||||
"CMOVWEQ",
|
||||
"CMOVWGE",
|
||||
"CMOVWGT",
|
||||
"CMOVWHI",
|
||||
"CMOVWLE",
|
||||
"CMOVWLS",
|
||||
"CMOVWLT",
|
||||
"CMOVWMI",
|
||||
"CMOVWNE",
|
||||
"CMOVWOC",
|
||||
"CMOVWOS",
|
||||
"CMOVWPC",
|
||||
"CMOVWPL",
|
||||
"CMOVWPS",
|
||||
"FCMOVCC",
|
||||
"FCMOVCS",
|
||||
"FCMOVEQ",
|
||||
"FCMOVHI",
|
||||
"FCMOVLS",
|
||||
"FCMOVNE",
|
||||
"FCMOVNU",
|
||||
"FCMOVUN",
|
||||
"LAST",
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ struct Prog
|
|||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
|
@ -70,7 +70,7 @@ struct Case
|
|||
|
||||
struct C1
|
||||
{
|
||||
long val;
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
|
@ -240,6 +240,7 @@ void nextpc(void);
|
|||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(long);
|
||||
int nareg(int);
|
||||
Node* nodfconst(double);
|
||||
int nodreg(Node*, Node*, int);
|
||||
int isreg(Node*, int);
|
||||
|
@ -298,7 +299,7 @@ Reg* rega(void);
|
|||
int rcmp(const void*, const void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Reg*, Adr*);
|
||||
Bits mkvar(Reg*, Adr*, int);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, long);
|
||||
void synch(Reg*, Bits);
|
||||
|
@ -335,11 +336,6 @@ int BtoF(long);
|
|||
#define D_HI D_NONE
|
||||
#define D_LO D_NONE
|
||||
|
||||
/*
|
||||
* bound
|
||||
*/
|
||||
void comtarg(void);
|
||||
|
||||
/*
|
||||
* com64
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ Bconv(Fmt *fp)
|
|||
if(str[0])
|
||||
strcat(str, " ");
|
||||
if(var[i].sym == S) {
|
||||
sprint(ss, "$%ld", var[i].offset);
|
||||
snprint(ss, sizeof(ss), "$%ld", var[i].offset);
|
||||
s = ss;
|
||||
} else
|
||||
s = var[i].sym->name;
|
||||
|
@ -47,13 +47,13 @@ Pconv(Fmt *fp)
|
|||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
if(p->as == ADATA)
|
||||
sprint(str, " %A %D/%d,%D",
|
||||
snprint(str, sizeof(str), " %A %D/%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else if(p->as == ATEXT)
|
||||
sprint(str, " %A %D,%d,%D",
|
||||
snprint(str, sizeof(str), " %A %D,%d,%D",
|
||||
p->as, &p->from, p->from.scale, &p->to);
|
||||
else
|
||||
sprint(str, " %A %D,%D",
|
||||
snprint(str, sizeof(str), " %A %D,%D",
|
||||
p->as, &p->from, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
@ -78,18 +78,18 @@ Dconv(Fmt *fp)
|
|||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%ld(%R)", a->offset, i-D_INDIR);
|
||||
snprint(str, sizeof(str), "%ld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
snprint(str, sizeof(str), "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
if(a->offset)
|
||||
sprint(str, "$%ld,%R", a->offset, i);
|
||||
snprint(str, sizeof(str), "$%ld,%R", a->offset, i);
|
||||
else
|
||||
sprint(str, "%R", i);
|
||||
snprint(str, sizeof(str), "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
|
@ -97,53 +97,54 @@ Dconv(Fmt *fp)
|
|||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
sprint(str, "%ld(PC)", a->offset-pc);
|
||||
snprint(str, sizeof(str), "%ld(PC)", a->offset-pc);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%s+%ld(SB)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%s<>+%ld(SB)", a->sym->name,
|
||||
snprint(str, sizeof(str), "%s<>+%ld(SB)", a->sym->name,
|
||||
a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
sprint(str, "%s+%ld(SP)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym)
|
||||
sprint(str, "%s+%ld(FP)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(FP)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%ld(FP)", a->offset);
|
||||
snprint(str, sizeof(str), "%ld(FP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%ld", a->offset);
|
||||
snprint(str, sizeof(str), "$%ld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.17e)", a->dval);
|
||||
snprint(str, sizeof(str), "$(%.17e)", a->dval);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->sval);
|
||||
snprint(str, sizeof(str), "$\"%S\"", a->sval);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
snprint(str, sizeof(str), "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
|
||||
strcat(str, s);
|
||||
fmtstrcpy(fp, str);
|
||||
snprint(s, sizeof(s), "(%R*%d)", (int)a->index, (int)a->scale);
|
||||
return fmtstrcpy(fp, s);
|
||||
}
|
||||
conv:
|
||||
return fmtstrcpy(fp, str);
|
||||
|
@ -229,9 +230,9 @@ Rconv(Fmt *fp)
|
|||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
snprint(str, sizeof(str), "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
snprint(str, sizeof(str), "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ machcap(Node *n)
|
|||
case OANDAND:
|
||||
case OOROR:
|
||||
case ONOT:
|
||||
case ODOT:
|
||||
return 1;
|
||||
|
||||
case OASADD:
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
TARG=8c
|
||||
OFILES=\
|
||||
bound.$O\
|
||||
cgen.$O\
|
||||
cgen64.$O\
|
||||
div.$O\
|
||||
|
@ -33,7 +32,6 @@ $LIB:
|
|||
mk install
|
||||
mk clean
|
||||
|
||||
bound.$O: bound.h
|
||||
|
||||
%.$O: ../cc/%.c
|
||||
$CC $CFLAGS ../cc/$stem.c
|
||||
|
|
|
@ -67,8 +67,6 @@ peep(void)
|
|||
pc = 0; /* speculating it won't kill */
|
||||
|
||||
loop1:
|
||||
if(debug['b'])
|
||||
comtarg();
|
||||
|
||||
t = 0;
|
||||
for(r=firstr; r!=R; r=r->link) {
|
||||
|
@ -277,6 +275,9 @@ subprop(Reg *r0)
|
|||
case ACWD:
|
||||
case ACDQ:
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
case AFSTSW:
|
||||
return 0;
|
||||
|
@ -641,10 +642,21 @@ copyu(Prog *p, Adr *v, Adr *s)
|
|||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSL:
|
||||
case AREP:
|
||||
case AREPN:
|
||||
if(v->type == D_CX || v->type == D_DI || v->type == D_SI)
|
||||
if(v->type == D_CX)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case AMOVSB:
|
||||
case AMOVSL:
|
||||
if(v->type == D_DI || v->type == D_SI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
case ASTOSB:
|
||||
case ASTOSL:
|
||||
if(v->type == D_AX || v->type == D_DI)
|
||||
return 2;
|
||||
goto caseread;
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ regopt(Prog *p)
|
|||
r1->s1 = R;
|
||||
}
|
||||
|
||||
bit = mkvar(r, &p->from);
|
||||
bit = mkvar(r, &p->from, p->as==AMOVL);
|
||||
if(bany(&bit))
|
||||
switch(p->as) {
|
||||
/*
|
||||
|
@ -139,7 +139,7 @@ regopt(Prog *p)
|
|||
break;
|
||||
}
|
||||
|
||||
bit = mkvar(r, &p->to);
|
||||
bit = mkvar(r, &p->to, 0);
|
||||
if(bany(&bit))
|
||||
switch(p->as) {
|
||||
default:
|
||||
|
@ -224,7 +224,9 @@ regopt(Prog *p)
|
|||
*/
|
||||
case AFMOVDP:
|
||||
case AFMOVFP:
|
||||
case AFMOVLP:
|
||||
case AFMOVVP:
|
||||
case AFMOVWP:
|
||||
case ACALL:
|
||||
for(z=0; z<BITS; z++)
|
||||
addrs.b[z] |= bit.b[z];
|
||||
|
@ -637,7 +639,7 @@ doregbits(int r)
|
|||
}
|
||||
|
||||
Bits
|
||||
mkvar(Reg *r, Adr *a)
|
||||
mkvar(Reg *r, Adr *a, int isro)
|
||||
{
|
||||
Var *v;
|
||||
int i, t, n, et, z;
|
||||
|
@ -651,13 +653,21 @@ mkvar(Reg *r, Adr *a)
|
|||
t = a->type;
|
||||
r->regu |= doregbits(t);
|
||||
r->regu |= doregbits(a->index);
|
||||
et = a->etype;
|
||||
|
||||
switch(t) {
|
||||
default:
|
||||
goto none;
|
||||
case D_INDIR+D_GS:
|
||||
if(!isro || 1)
|
||||
goto none;
|
||||
n = t;
|
||||
{static Sym er; a->sym = &er;}
|
||||
a->sym->name = "$extreg";
|
||||
break;
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
bit = mkvar(r, a);
|
||||
bit = mkvar(r, a, 0);
|
||||
for(z=0; z<BITS; z++)
|
||||
addrs.b[z] |= bit.b[z];
|
||||
a->type = t;
|
||||
|
@ -674,7 +684,6 @@ mkvar(Reg *r, Adr *a)
|
|||
goto none;
|
||||
if(s->name[0] == '.')
|
||||
goto none;
|
||||
et = a->etype;
|
||||
o = a->offset;
|
||||
v = var;
|
||||
for(i=0; i<nvar; i++) {
|
||||
|
@ -1008,7 +1017,7 @@ paint1(Reg *r, int bn)
|
|||
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->loop;
|
||||
if(p->as == AFMOVL)
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
if(debug['R'] && debug['v'])
|
||||
|
@ -1018,7 +1027,7 @@ paint1(Reg *r, int bn)
|
|||
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->loop;
|
||||
if(p->as == AFMOVL)
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
if(debug['R'] && debug['v'])
|
||||
|
@ -1028,7 +1037,7 @@ paint1(Reg *r, int bn)
|
|||
|
||||
if(STORE(r) & r->regdiff.b[z] & bb) {
|
||||
change -= CLOAD * r->loop;
|
||||
if(p->as == AFMOVL)
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
if(debug['R'] && debug['v'])
|
||||
|
|
|
@ -88,6 +88,10 @@ xcom(Node *n)
|
|||
n->addable = 11;
|
||||
break;
|
||||
|
||||
case OEXREG:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
||||
case OREGISTER:
|
||||
n->addable = 12;
|
||||
break;
|
||||
|
|
|
@ -10,7 +10,7 @@ swit1(C1 *q, int nc, long def, Node *n)
|
|||
if(nc < 5) {
|
||||
for(i=0; i<nc; i++) {
|
||||
if(debug['W'])
|
||||
print("case = %.8lux\n", q->val);
|
||||
print("case = %.8llux\n", q->val);
|
||||
gopcode(OEQ, n->type, n, nodconst(q->val));
|
||||
patch(p, q->label);
|
||||
q++;
|
||||
|
@ -22,7 +22,7 @@ swit1(C1 *q, int nc, long def, Node *n)
|
|||
i = nc / 2;
|
||||
r = q+i;
|
||||
if(debug['W'])
|
||||
print("case > %.8lux\n", r->val);
|
||||
print("case > %.8llux\n", r->val);
|
||||
gopcode(OGT, n->type, n, nodconst(r->val));
|
||||
sp = p;
|
||||
gbranch(OGOTO);
|
||||
|
@ -31,7 +31,7 @@ swit1(C1 *q, int nc, long def, Node *n)
|
|||
swit1(q, i, def, n);
|
||||
|
||||
if(debug['W'])
|
||||
print("case < %.8lux\n", r->val);
|
||||
print("case < %.8llux\n", r->val);
|
||||
patch(sp, pc);
|
||||
swit1(r+1, nc-i-1, def, n);
|
||||
}
|
||||
|
@ -199,7 +199,6 @@ outcode(void)
|
|||
return;
|
||||
}
|
||||
Binit(&b, f, OWRITE);
|
||||
Blethal(&b, nil);
|
||||
Bseek(&b, 0L, 2);
|
||||
outhist(&b);
|
||||
for(sym=0; sym<NSYM; sym++) {
|
||||
|
|
|
@ -22,6 +22,8 @@ ginit(void)
|
|||
lastp = P;
|
||||
tfield = types[TLONG];
|
||||
|
||||
typeswitch = typechlv;
|
||||
|
||||
zprog.link = P;
|
||||
zprog.as = AGOK;
|
||||
zprog.from.type = D_NONE;
|
||||
|
@ -158,7 +160,8 @@ gargs(Node *n, Node *tn1, Node *tn2)
|
|||
cursafe = regs;
|
||||
}
|
||||
|
||||
int nareg(void)
|
||||
int
|
||||
nareg(int notbp)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
|
@ -166,6 +169,8 @@ int nareg(void)
|
|||
for(i=D_AX; i<=D_DI; i++)
|
||||
if(reg[i] == 0)
|
||||
n++;
|
||||
if(notbp && reg[D_BP] == 0)
|
||||
n--;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -306,13 +311,34 @@ regalloc(Node *n, Node *tn, Node *o)
|
|||
if(reg[i] == 0)
|
||||
goto out;
|
||||
diag(tn, "out of fixed registers");
|
||||
abort();
|
||||
goto err;
|
||||
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
case TVLONG:
|
||||
i = D_F0;
|
||||
goto out;
|
||||
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
n->op = OREGPAIR;
|
||||
n->complex = 0; /* already in registers */
|
||||
n->addable = 11;
|
||||
n->type = tn->type;
|
||||
n->lineno = nearln;
|
||||
n->left = alloc(sizeof(Node));
|
||||
n->right = alloc(sizeof(Node));
|
||||
if(o != Z && o->op == OREGPAIR) {
|
||||
regalloc(n->left, ®node, o->left);
|
||||
regalloc(n->right, ®node, o->right);
|
||||
} else {
|
||||
regalloc(n->left, ®node, Z);
|
||||
regalloc(n->right, ®node, Z);
|
||||
}
|
||||
n->right->type = types[TULONG];
|
||||
if(tn->type->etype == TUVLONG)
|
||||
n->left->type = types[TULONG];
|
||||
return;
|
||||
}
|
||||
diag(tn, "unknown type in regalloc: %T", tn->type);
|
||||
err:
|
||||
|
@ -339,6 +365,12 @@ regfree(Node *n)
|
|||
{
|
||||
int i;
|
||||
|
||||
if(n->op == OREGPAIR) {
|
||||
regfree(n->left);
|
||||
regfree(n->right);
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if(n->op != OREGISTER && n->op != OINDREG)
|
||||
goto err;
|
||||
|
@ -430,6 +462,11 @@ naddr(Node *n, Adr *a)
|
|||
a->sym = S;
|
||||
break;
|
||||
|
||||
case OEXREG:
|
||||
a->type = D_INDIR + D_GS;
|
||||
a->offset = n->reg - 1;
|
||||
a->etype = n->etype;
|
||||
break;
|
||||
|
||||
case OIND:
|
||||
naddr(n->left, a);
|
||||
|
@ -609,9 +646,6 @@ gmove(Node *f, Node *t)
|
|||
case TDOUBLE:
|
||||
gins(AFMOVD, f, t);
|
||||
return;
|
||||
case TVLONG:
|
||||
gins(AFMOVV, f, t);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -650,9 +684,6 @@ gmove(Node *f, Node *t)
|
|||
case TDOUBLE:
|
||||
gins(AFMOVDP, f, t);
|
||||
return;
|
||||
case TVLONG:
|
||||
gins(AFMOVVP, f, t);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -980,7 +1011,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
|
|||
if(et == TFLOAT)
|
||||
a = AFADDF;
|
||||
else
|
||||
if(et == TDOUBLE || et == TVLONG) {
|
||||
if(et == TDOUBLE) {
|
||||
a = AFADDD;
|
||||
if(pop)
|
||||
a = AFADDDP;
|
||||
|
@ -994,7 +1025,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
|
|||
if(rev)
|
||||
a = AFSUBRF;
|
||||
} else
|
||||
if(et == TDOUBLE || et == TVLONG) {
|
||||
if(et == TDOUBLE) {
|
||||
a = AFSUBD;
|
||||
if(pop)
|
||||
a = AFSUBDP;
|
||||
|
@ -1011,7 +1042,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
|
|||
if(et == TFLOAT)
|
||||
a = AFMULF;
|
||||
else
|
||||
if(et == TDOUBLE || et == TVLONG) {
|
||||
if(et == TDOUBLE) {
|
||||
a = AFMULD;
|
||||
if(pop)
|
||||
a = AFMULDP;
|
||||
|
@ -1027,7 +1058,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
|
|||
if(rev)
|
||||
a = AFDIVRF;
|
||||
} else
|
||||
if(et == TDOUBLE || et == TVLONG) {
|
||||
if(et == TDOUBLE) {
|
||||
a = AFDIVD;
|
||||
if(pop)
|
||||
a = AFDIVDP;
|
||||
|
@ -1054,7 +1085,7 @@ fgopcode(int o, Node *f, Node *t, int pop, int rev)
|
|||
a = AGOK;
|
||||
}
|
||||
} else
|
||||
if(et == TDOUBLE || et == TVLONG) {
|
||||
if(et == TDOUBLE) {
|
||||
a = AFCOMF;
|
||||
if(pop) {
|
||||
a = AFCOMDP;
|
||||
|
@ -1355,7 +1386,15 @@ long
|
|||
exreg(Type *t)
|
||||
{
|
||||
|
||||
USED(t);
|
||||
int 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. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ struct Adr
|
|||
Sym* u1sym;
|
||||
} u1;
|
||||
short type;
|
||||
char index;
|
||||
uchar index;
|
||||
char scale;
|
||||
};
|
||||
|
||||
|
@ -58,11 +58,12 @@ struct Prog
|
|||
Prog* pcond; /* work on this */
|
||||
long pc;
|
||||
long line;
|
||||
uchar mark; /* work on these */
|
||||
uchar back;
|
||||
|
||||
short as;
|
||||
char width; /* fake for DATA */
|
||||
char ft; /* oclass cache */
|
||||
char tt;
|
||||
uchar mark; /* work on these */
|
||||
uchar back;
|
||||
};
|
||||
struct Auto
|
||||
{
|
||||
|
@ -203,6 +204,7 @@ EXTERN union
|
|||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "R" uint
|
||||
#pragma varargck type "S" char*
|
||||
|
||||
#pragma varargck argpos diag 1
|
||||
|
@ -270,7 +272,7 @@ EXTERN int dtype;
|
|||
EXTERN Adr* reloca;
|
||||
EXTERN int doexp, dlm;
|
||||
EXTERN int imports, nimports;
|
||||
EXTERN int exports, nexports;
|
||||
EXTERN int exports, nexports, allexport;
|
||||
EXTERN char* EXPTAB;
|
||||
EXTERN Prog undefp;
|
||||
|
||||
|
@ -345,3 +347,8 @@ void xdefine(char*, int, long);
|
|||
void xfol(Prog*);
|
||||
int zaddr(uchar*, Adr*, Sym*[]);
|
||||
void zerosig(char*);
|
||||
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "R" int
|
||||
#pragma varargck type "A" int
|
||||
|
|
|
@ -24,18 +24,18 @@ Pconv(Fmt *fp)
|
|||
switch(p->as) {
|
||||
case ATEXT:
|
||||
if(p->from.scale) {
|
||||
sprint(str, "(%ld) %A %D,%d,%D",
|
||||
snprint(str, sizeof(str), "(%ld) %A %D,%d,%D",
|
||||
p->line, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sprint(str, "(%ld) %A %D,%D",
|
||||
snprint(str, sizeof(str), "(%ld) %A %D,%D",
|
||||
p->line, p->as, &p->from, &p->to);
|
||||
break;
|
||||
case ADATA:
|
||||
case AINIT:
|
||||
case ADYNT:
|
||||
sprint(str, "(%ld) %A %D/%d,%D",
|
||||
snprint(str, sizeof(str), "(%ld) %A %D/%d,%D",
|
||||
p->line, p->as, &p->from, p->from.scale, &p->to);
|
||||
break;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ Aconv(Fmt *fp)
|
|||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[40], s[20];
|
||||
char str[STRINGSZ+40], s[20];
|
||||
Adr *a;
|
||||
int i;
|
||||
|
||||
|
@ -63,15 +63,15 @@ Dconv(Fmt *fp)
|
|||
i = a->type;
|
||||
if(i >= D_INDIR) {
|
||||
if(a->offset)
|
||||
sprint(str, "%ld(%R)", a->offset, i-D_INDIR);
|
||||
snprint(str, sizeof(str), "%ld(%R)", a->offset, i-D_INDIR);
|
||||
else
|
||||
sprint(str, "(%R)", i-D_INDIR);
|
||||
snprint(str, sizeof(str), "(%R)", i-D_INDIR);
|
||||
goto brk;
|
||||
}
|
||||
switch(i) {
|
||||
|
||||
default:
|
||||
sprint(str, "%R", i);
|
||||
snprint(str, sizeof(str), "%R", i);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
|
@ -81,57 +81,57 @@ Dconv(Fmt *fp)
|
|||
case D_BRANCH:
|
||||
if(bigP != P && bigP->pcond != P)
|
||||
if(a->sym != S)
|
||||
sprint(str, "%lux+%s", bigP->pcond->pc,
|
||||
snprint(str, sizeof(str), "%lux+%s", bigP->pcond->pc,
|
||||
a->sym->name);
|
||||
else
|
||||
sprint(str, "%lux", bigP->pcond->pc);
|
||||
snprint(str, sizeof(str), "%lux", bigP->pcond->pc);
|
||||
else
|
||||
sprint(str, "%ld(PC)", a->offset);
|
||||
snprint(str, sizeof(str), "%ld(PC)", a->offset);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
sprint(str, "%s+%ld(SB)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(SB)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
sprint(str, "%s<%d>+%ld(SB)", a->sym->name,
|
||||
snprint(str, sizeof(str), "%s<%d>+%ld(SB)", a->sym->name,
|
||||
a->sym->version, a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
sprint(str, "%s+%ld(SP)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(SP)", a->sym->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
if(a->sym)
|
||||
sprint(str, "%s+%ld(FP)", a->sym->name, a->offset);
|
||||
snprint(str, sizeof(str), "%s+%ld(FP)", a->sym->name, a->offset);
|
||||
else
|
||||
sprint(str, "%ld(FP)", a->offset);
|
||||
snprint(str, sizeof(str), "%ld(FP)", a->offset);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
sprint(str, "$%ld", a->offset);
|
||||
snprint(str, sizeof(str), "$%ld", a->offset);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
sprint(str, "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l);
|
||||
snprint(str, sizeof(str), "$(%.8lux,%.8lux)", a->ieee.h, a->ieee.l);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
sprint(str, "$\"%S\"", a->scon);
|
||||
snprint(str, sizeof(str), "$\"%S\"", a->scon);
|
||||
break;
|
||||
|
||||
case D_ADDR:
|
||||
a->type = a->index;
|
||||
a->index = D_NONE;
|
||||
sprint(str, "$%D", a);
|
||||
snprint(str, sizeof(str), "$%D", a);
|
||||
a->index = a->type;
|
||||
a->type = D_ADDR;
|
||||
goto conv;
|
||||
}
|
||||
brk:
|
||||
if(a->index != D_NONE) {
|
||||
sprint(s, "(%R*%d)", a->index, a->scale);
|
||||
snprint(s, sizeof(s), "(%R*%d)", a->index, a->scale);
|
||||
strcat(str, s);
|
||||
}
|
||||
conv:
|
||||
|
@ -218,9 +218,9 @@ Rconv(Fmt *fp)
|
|||
|
||||
r = va_arg(fp->args, int);
|
||||
if(r >= D_AL && r <= D_NONE)
|
||||
sprint(str, "%s", regstr[r-D_AL]);
|
||||
snprint(str, sizeof(str), "%s", regstr[r-D_AL]);
|
||||
else
|
||||
sprint(str, "gok(%d)", r);
|
||||
snprint(str, sizeof(str), "gok(%d)", r);
|
||||
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
|
|
@ -95,8 +95,13 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
case 'x': /* produce export table */
|
||||
doexp = 1;
|
||||
if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
|
||||
readundefs(ARGF(), SEXPORT);
|
||||
if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])){
|
||||
a = ARGF();
|
||||
if(strcmp(a, "*") == 0)
|
||||
allexport = 1;
|
||||
else
|
||||
readundefs(a, SEXPORT);
|
||||
}
|
||||
break;
|
||||
case 'u': /* produce dynamically loadable module */
|
||||
dlm = 1;
|
||||
|
|
|
@ -311,7 +311,7 @@ patch(void)
|
|||
switch(s->type) {
|
||||
default:
|
||||
/* diag prints TNAME first */
|
||||
diag("%s is undefined", s->name);
|
||||
diag("undefined: %s", s->name);
|
||||
s->type = STEXT;
|
||||
s->value = vexit;
|
||||
break; /* or fall through to set offset? */
|
||||
|
@ -678,14 +678,14 @@ export(void)
|
|||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
|
||||
n++;
|
||||
esyms = malloc(n*sizeof(Sym*));
|
||||
ne = n;
|
||||
n = 0;
|
||||
for(i = 0; i < NHASH; i++)
|
||||
for(s = hash[i]; s != S; s = s->link)
|
||||
if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
|
||||
if(s->type != SXREF && s->type != SUNDEF && (nexports == 0 && s->sig != 0 || s->subtype == SEXPORT || allexport))
|
||||
esyms[n++] = s;
|
||||
for(i = 0; i < ne-1; i++)
|
||||
for(j = i+1; j < ne; j++)
|
||||
|
|
|
@ -303,6 +303,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)
|
||||
{
|
||||
|
@ -334,6 +352,8 @@ oclass(Adr *a)
|
|||
return Yax;
|
||||
|
||||
case D_CL:
|
||||
return Ycl;
|
||||
|
||||
case D_DL:
|
||||
case D_BL:
|
||||
case D_AH:
|
||||
|
@ -606,7 +626,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;
|
||||
|
@ -767,6 +787,7 @@ uchar ymovtab[] =
|
|||
ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0,
|
||||
|
||||
/* extra imul */
|
||||
AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0,
|
||||
AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
|
||||
0
|
||||
};
|
||||
|
@ -821,7 +842,14 @@ doasm(Prog *p)
|
|||
Prog *q, pp;
|
||||
uchar *t;
|
||||
int z, op, ft, tt;
|
||||
long v;
|
||||
long 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;
|
||||
|
@ -1061,7 +1089,7 @@ found:
|
|||
q = p->pcond;
|
||||
if(q) {
|
||||
v = q->pc - p->pc - 2;
|
||||
if(v < -128 && v > 127)
|
||||
if(v < -128 || v > 127)
|
||||
diag("loop too far: %P", p);
|
||||
*andptr++ = op;
|
||||
*andptr++ = v;
|
||||
|
|
|
@ -289,5 +289,5 @@ main(int argc, char **argv)
|
|||
fclose(outf);
|
||||
}
|
||||
close_infile();
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -302,7 +302,6 @@ getbits(DState *s, int lll, int *vvv, int nnn)
|
|||
if (s->strm->total_in_lo32 == 0)
|
||||
s->strm->total_in_hi32++;
|
||||
}
|
||||
return -1; /* KEN */
|
||||
}
|
||||
|
||||
#define GET_UCHAR(lll,uuu) \
|
||||
|
|
|
@ -90,6 +90,8 @@ acidinit(void)
|
|||
if(types[TINT]->width != types[TSHORT]->width)
|
||||
warn(Z, "acidmember int not long or short");
|
||||
}
|
||||
if(types[TIND]->width == types[TUVLONG]->width)
|
||||
acidchar[TIND] = 'Y';
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -22,15 +22,15 @@ typedef struct Bits Bits;
|
|||
|
||||
#define NHUNK 50000L
|
||||
#define BUFSIZ 8192
|
||||
#define NSYMB 500
|
||||
#define NSYMB 1500
|
||||
#define NHASH 1024
|
||||
#define STRINGSZ 200
|
||||
#define HISTSZ 20
|
||||
#define YYMAXDEPTH 500
|
||||
#define YYMAXDEPTH 1500
|
||||
#define NTERM 10
|
||||
#define MAXALIGN 7
|
||||
|
||||
#define SIGN(n) ((vlong)1<<(n-1))
|
||||
#define SIGN(n) (1ULL<<(n-1))
|
||||
#define MASK(n) (SIGN(n)|(SIGN(n)-1))
|
||||
|
||||
#define BITS 5
|
||||
|
@ -294,6 +294,7 @@ enum
|
|||
OINDEX,
|
||||
OFAS,
|
||||
OREGPAIR,
|
||||
OEXREG,
|
||||
|
||||
OEND
|
||||
};
|
||||
|
@ -477,6 +478,7 @@ EXTERN int packflg;
|
|||
EXTERN int fproundflg;
|
||||
EXTERN int profileflg;
|
||||
EXTERN int ncontin;
|
||||
EXTERN int newvlongcode;
|
||||
EXTERN int canreach;
|
||||
EXTERN int warnreach;
|
||||
EXTERN Bits zbits;
|
||||
|
@ -507,6 +509,7 @@ extern char typechlvp[];
|
|||
extern char typechlp[];
|
||||
extern char typechlpfd[];
|
||||
|
||||
EXTERN char* typeswitch;
|
||||
EXTERN char* typeword;
|
||||
EXTERN char* typecmplx;
|
||||
|
||||
|
@ -614,7 +617,7 @@ int rsametype(Type*, Type*, int, int);
|
|||
int sametype(Type*, Type*);
|
||||
ulong sign(Sym*);
|
||||
ulong signature(Type*);
|
||||
void suallign(Type*);
|
||||
void sualign(Type*);
|
||||
void tmerge(Type*, Sym*);
|
||||
void walkparam(Node*, int);
|
||||
void xdecl(int, Type*, Sym*);
|
||||
|
@ -632,6 +635,8 @@ int tcomo(Node*, int);
|
|||
int tcomx(Node*);
|
||||
int tlvalue(Node*);
|
||||
void constas(Node*, Type*, Type*);
|
||||
Node* uncomma(Node*);
|
||||
Node* uncomargs(Node*);
|
||||
|
||||
/*
|
||||
* con.c
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
struct
|
||||
{
|
||||
Type* t;
|
||||
char c;
|
||||
uchar c;
|
||||
} tycl;
|
||||
struct
|
||||
{
|
||||
Type* t1;
|
||||
Type* t2;
|
||||
Type* t3;
|
||||
uchar c;
|
||||
} tyty;
|
||||
struct
|
||||
{
|
||||
|
@ -895,16 +897,22 @@ sbody:
|
|||
{
|
||||
$<tyty>$.t1 = strf;
|
||||
$<tyty>$.t2 = strl;
|
||||
$<tyty>$.t3 = lasttype;
|
||||
$<tyty>$.c = lastclass;
|
||||
strf = T;
|
||||
strl = T;
|
||||
lastbit = 0;
|
||||
firstbit = 1;
|
||||
lastclass = CXXX;
|
||||
lasttype = T;
|
||||
}
|
||||
edecl '}'
|
||||
{
|
||||
$$ = strf;
|
||||
strf = $<tyty>2.t1;
|
||||
strl = $<tyty>2.t2;
|
||||
lasttype = $<tyty>2.t3;
|
||||
lastclass = $<tyty>2.c;
|
||||
}
|
||||
|
||||
zctlist:
|
||||
|
@ -995,7 +1003,7 @@ complex:
|
|||
if($$->link != T)
|
||||
diag(Z, "redeclare tag: %s", $2->name);
|
||||
$$->link = $4;
|
||||
suallign($$);
|
||||
sualign($$);
|
||||
}
|
||||
| LSTRUCT sbody
|
||||
{
|
||||
|
@ -1003,7 +1011,7 @@ complex:
|
|||
sprint(symb, "_%d_", taggen);
|
||||
$$ = dotag(lookup(), TSTRUCT, autobn);
|
||||
$$->link = $2;
|
||||
suallign($$);
|
||||
sualign($$);
|
||||
}
|
||||
| LUNION ltag
|
||||
{
|
||||
|
@ -1020,7 +1028,7 @@ complex:
|
|||
if($$->link != T)
|
||||
diag(Z, "redeclare tag: %s", $2->name);
|
||||
$$->link = $4;
|
||||
suallign($$);
|
||||
sualign($$);
|
||||
}
|
||||
| LUNION sbody
|
||||
{
|
||||
|
@ -1028,7 +1036,7 @@ complex:
|
|||
sprint(symb, "_%d_", taggen);
|
||||
$$ = dotag(lookup(), TUNION, autobn);
|
||||
$$->link = $2;
|
||||
suallign($$);
|
||||
sualign($$);
|
||||
}
|
||||
| LENUM ltag
|
||||
{
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
#include "cc.h"
|
||||
|
||||
typedef struct Com Com;
|
||||
struct Com
|
||||
{
|
||||
int n;
|
||||
Node *t[500];
|
||||
};
|
||||
|
||||
int compar(Node*, int);
|
||||
static void comma(Node*);
|
||||
static Node* commas(Com*, Node*);
|
||||
|
||||
void
|
||||
complex(Node *n)
|
||||
|
@ -15,6 +24,8 @@ complex(Node *n)
|
|||
prtree(n, "pre complex");
|
||||
if(tcom(n))
|
||||
return;
|
||||
if(debug['y'] || 1)
|
||||
comma(n);
|
||||
if(debug['t'])
|
||||
if(n->op != OCONST)
|
||||
prtree(n, "t complex");
|
||||
|
@ -273,8 +284,11 @@ tcomo(Node *n, int f)
|
|||
goto bad;
|
||||
n->type = l->type;
|
||||
if(n->type->etype == TIND)
|
||||
if(n->type->link->width < 1)
|
||||
diag(n, "inc/dec of a void pointer");
|
||||
if(n->type->link->width < 1) {
|
||||
snap(n->type->link);
|
||||
if(n->type->link->width < 1)
|
||||
diag(n, "inc/dec of a void pointer");
|
||||
}
|
||||
break;
|
||||
|
||||
case OEQ:
|
||||
|
@ -610,6 +624,8 @@ tcomo(Node *n, int f)
|
|||
n->addable = 1;
|
||||
if(n->class == CEXREG) {
|
||||
n->op = OREGISTER;
|
||||
if(thechar == '8')
|
||||
n->op = OEXREG;
|
||||
n->reg = n->sym->offset;
|
||||
n->xoffset = 0;
|
||||
break;
|
||||
|
@ -881,6 +897,101 @@ tlvalue(Node *n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* hoist comma operators out of expressions
|
||||
* (a,b) OP c => (a, b OP c)
|
||||
* OP(a,b) => (a, OP b)
|
||||
* a OP (b,c) => (b, a OP c)
|
||||
*/
|
||||
|
||||
static Node*
|
||||
comargs(Com *com, Node *n)
|
||||
{
|
||||
if(n != Z && n->op == OLIST){
|
||||
n->left = comargs(com, n->left);
|
||||
n->right = comargs(com, n->right);
|
||||
}
|
||||
return commas(com, n);
|
||||
}
|
||||
|
||||
static Node*
|
||||
commas(Com *com, Node *n)
|
||||
{
|
||||
Node *t;
|
||||
|
||||
if(n == Z)
|
||||
return n;
|
||||
switch(n->op){
|
||||
case OREGISTER:
|
||||
case OINDREG:
|
||||
case OCONST:
|
||||
case ONAME:
|
||||
case OSTRING:
|
||||
/* leaf */
|
||||
return n;
|
||||
|
||||
case OCOMMA:
|
||||
t = commas(com, n->left);
|
||||
if(com->n >= nelem(com->t))
|
||||
fatal(n, "comma list overflow");
|
||||
com->t[com->n++] = t;
|
||||
return commas(com, n->right);
|
||||
|
||||
case OFUNC:
|
||||
n->left = commas(com, n->left);
|
||||
n->right = comargs(com, n->right);
|
||||
return n;
|
||||
|
||||
case OCOND:
|
||||
n->left = commas(com, n->left);
|
||||
comma(n->right->left);
|
||||
comma(n->right->right);
|
||||
return n;
|
||||
|
||||
case OANDAND:
|
||||
case OOROR:
|
||||
n->left = commas(com, n->left);
|
||||
comma(n->right);
|
||||
return n;
|
||||
|
||||
case ORETURN:
|
||||
comma(n->left);
|
||||
return n;
|
||||
}
|
||||
n->left = commas(com, n->left);
|
||||
if(n->right != Z)
|
||||
n->right = commas(com, n->right);
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
comma(Node *n)
|
||||
{
|
||||
Com com;
|
||||
Node *nn;
|
||||
|
||||
com.n = 0;
|
||||
nn = commas(&com, n);
|
||||
if(com.n > 0){
|
||||
if(debug['y'])print("n=%d\n", com.n);
|
||||
if(debug['y']) prtree(nn, "res");
|
||||
if(nn != n)
|
||||
*n = *nn;
|
||||
while(com.n > 0){
|
||||
if(debug['y']) prtree(com.t[com.n-1], "tree");
|
||||
nn = new1(OXXX, Z, Z);
|
||||
*nn = *n;
|
||||
n->op = OCOMMA;
|
||||
n->type = nn->type;
|
||||
n->left = com.t[--com.n];
|
||||
n->right = nn;
|
||||
n->lineno = n->left->lineno;
|
||||
}
|
||||
if(debug['y']) prtree(n, "final");
|
||||
}else if(n != nn)
|
||||
fatal(n, "odd tree");
|
||||
}
|
||||
|
||||
/*
|
||||
* general rewrite
|
||||
* (IND(ADDR x)) ==> x
|
||||
|
@ -934,7 +1045,8 @@ loop:
|
|||
if(n->op == OCONST)
|
||||
break;
|
||||
}
|
||||
if(nocast(l->type, n->type)) {
|
||||
if(nocast(l->type, n->type) &&
|
||||
(!typefd[l->type->etype] || typeu[l->type->etype] && typeu[n->type->etype])) {
|
||||
l->type = n->type;
|
||||
*n = *l;
|
||||
}
|
||||
|
@ -1342,6 +1454,7 @@ useless:
|
|||
else
|
||||
snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",
|
||||
lt, cmps[relindex(n->op)], xbuf);
|
||||
if(debug['y']) prtree(n, "strange");
|
||||
warn(n, "useless or misleading comparison: %s", cmpbuf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -274,8 +274,8 @@ com64(Node *n)
|
|||
case ORETURN:
|
||||
case OAS:
|
||||
case OIND:
|
||||
case OCOMMA:
|
||||
case OLIST:
|
||||
case OCOMMA:
|
||||
return 1;
|
||||
case OADD:
|
||||
a = nodaddv;
|
||||
|
|
|
@ -519,7 +519,7 @@ newlist(Node *l, Node *r)
|
|||
}
|
||||
|
||||
void
|
||||
suallign(Type *t)
|
||||
sualign(Type *t)
|
||||
{
|
||||
Type *l;
|
||||
long o, w;
|
||||
|
@ -581,7 +581,7 @@ suallign(Type *t)
|
|||
return;
|
||||
|
||||
default:
|
||||
diag(Z, "unknown type in suallign: %T", t);
|
||||
diag(Z, "unknown type in sualign: %T", t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1180,12 +1180,6 @@ paramconv(Type *t, int f)
|
|||
{
|
||||
|
||||
switch(t->etype) {
|
||||
case TUNION:
|
||||
case TSTRUCT:
|
||||
if(t->width <= 0)
|
||||
diag(Z, "incomplete structure: %s", t->tag->name);
|
||||
break;
|
||||
|
||||
case TARRAY:
|
||||
t = typ(TIND, t->link);
|
||||
t->width = types[TIND]->width;
|
||||
|
@ -1283,6 +1277,8 @@ pdecl(int c, Type *t, Sym *s)
|
|||
diag(Z, "parameter cannot have class: %s", s->name);
|
||||
c = CPARAM;
|
||||
}
|
||||
if(typesu[t->etype] && t->width <= 0)
|
||||
diag(Z, "incomplete structure: %s", t->tag->name);
|
||||
adecl(c, t, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -1262,9 +1262,7 @@ loop:
|
|||
if(i->f < 0)
|
||||
goto pop;
|
||||
fi.c = read(i->f, i->b, BUFSIZ) - 1;
|
||||
if(fi.c < -1)
|
||||
sysfatal("read error: %r");
|
||||
if(fi.c == -1) {
|
||||
if(fi.c < 0) {
|
||||
close(i->f);
|
||||
linehist(0, 0);
|
||||
goto pop;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue