import updated compilers from sources

front
cinap_lenrek 2012-07-30 19:11:16 +02:00
parent fcc5e75d07
commit 4f33c88a51
129 changed files with 20341 additions and 375 deletions

View File

@ -2,6 +2,7 @@
#include <string.h>
#include <stdio.h>
void
main(int argc, char **argv)
{
char *f, *b, *s;

View File

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

View File

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

View File

@ -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 */

View File

@ -613,7 +613,7 @@ c_brkcont(wp)
}
unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
/*NOTREACHED*/
return 0; /*NOTREACHED*/
}
int

View File

@ -20,6 +20,7 @@ uchar bittab[] = {
128
};
void
main(int argc, char **argv)
{

View File

@ -30,6 +30,7 @@ prword(char *w)
fputs(w, stdout);
}
void
main(int argc, char **argv)
{
struct utsname u;

View File

@ -123,7 +123,7 @@ static double q4[] = {
1.0,
};
static
static void
asympt(double arg)
{
double zsq, n, d;

View File

@ -125,7 +125,7 @@ static double q4[] = {
1.0,
};
static
static void
asympt(double arg)
{
double zsq, n, d;

View File

@ -469,4 +469,5 @@ copynotehandler(void *u, char *msg)
if(_finishing)
_finish(0, 0);
_NOTED(1);
return 0;
}

View File

@ -111,6 +111,7 @@ _notehandler(Ureg *u, char *msg)
}
_doatexits();
_NOTED(1); /* NDFLT */
return 0;
}
int

View File

@ -144,6 +144,7 @@ tcsetpgrp(int fd, pid_t pgrpid)
_syserrno();
return -1;
}
return 0;
}
pid_t

View File

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

View File

@ -103,4 +103,5 @@ strerror_r(int n, char *buf, int len)
{
strncpy(buf, strerror(n), len);
buf[len-1] = 0;
return buf;
}

View File

@ -109,6 +109,7 @@ listenproc(Rock *r, int fd)
close(dfd);
}
exit(0);
return 0;
}
int

View File

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

View File

@ -461,6 +461,7 @@ static double Time_F(int s)
}
# endif
#endif
return 0;
}
#endif /* if defined(OPENSSL_SYS_NETWARE) */

View File

@ -1,3 +1,4 @@
void
nap(int n)
{
register i;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, "/???");
}
}

View File

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

View File

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

View File

@ -94,5 +94,11 @@ char* anames[] =
"BXRET",
"DWORD",
"SIGNAME",
"SQRTF",
"SQRTD",
"LDREX",
"STREX",
"LDREXD",
"STREXD",
"LAST",
};

View File

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

View File

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

View File

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

View File

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

View File

@ -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() */

View File

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

View File

@ -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 */

View File

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

View File

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

195
sys/src/cmd/6a/a.h Normal file
View File

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

562
sys/src/cmd/6a/a.y Normal file
View File

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

1289
sys/src/cmd/6a/lex.c Normal file

File diff suppressed because it is too large Load Diff

26
sys/src/cmd/6a/mkfile Normal file
View File

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

820
sys/src/cmd/6c/6.out.h Normal file
View File

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

1942
sys/src/cmd/6c/cgen.c Normal file

File diff suppressed because it is too large Load Diff

206
sys/src/cmd/6c/div.c Normal file
View File

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

669
sys/src/cmd/6c/enam.c Normal file
View File

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

381
sys/src/cmd/6c/gc.h Normal file
View File

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

337
sys/src/cmd/6c/list.c Normal file
View File

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

78
sys/src/cmd/6c/machcap.c Normal file
View File

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

15
sys/src/cmd/6c/mkenam Normal file
View File

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

38
sys/src/cmd/6c/mkfile Normal file
View File

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

428
sys/src/cmd/6c/mul.c Normal file
View File

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

846
sys/src/cmd/6c/peep.c Normal file
View File

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

1356
sys/src/cmd/6c/reg.c Normal file

File diff suppressed because it is too large Load Diff

435
sys/src/cmd/6c/sgen.c Normal file
View File

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

530
sys/src/cmd/6c/swt.c Normal file
View File

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

106
sys/src/cmd/6c/sys.c Normal file
View File

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

1515
sys/src/cmd/6c/txt.c Normal file

File diff suppressed because it is too large Load Diff

746
sys/src/cmd/6c/vlrt.c Normal file
View File

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

461
sys/src/cmd/6l/asm.c Normal file
View File

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

55
sys/src/cmd/6l/compat.c Normal file
View File

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

390
sys/src/cmd/6l/l.h Normal file
View File

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

350
sys/src/cmd/6l/list.c Normal file
View File

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

31
sys/src/cmd/6l/mkfile Normal file
View File

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

1595
sys/src/cmd/6l/obj.c Normal file

File diff suppressed because it is too large Load Diff

1183
sys/src/cmd/6l/optab.c Normal file

File diff suppressed because it is too large Load Diff

790
sys/src/cmd/6l/pass.c Normal file
View File

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

1746
sys/src/cmd/6l/span.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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); */
}

View File

@ -72,6 +72,7 @@ struct Gen
double dval;
char sval[8];
long offset;
long offset2;
Sym* sym;
short type;
short index;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
*/

View File

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

View File

@ -53,6 +53,7 @@ machcap(Node *n)
case OANDAND:
case OOROR:
case ONOT:
case ODOT:
return 1;
case OASADD:

View File

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

View File

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

View File

@ -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'])

View File

@ -88,6 +88,10 @@ xcom(Node *n)
n->addable = 11;
break;
case OEXREG:
n->addable = 12;
break;
case OREGISTER:
n->addable = 12;
break;

View File

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

View File

@ -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, &regnode, o->left);
regalloc(n->right, &regnode, o->right);
} else {
regalloc(n->left, &regnode, Z);
regalloc(n->right, &regnode, 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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -289,5 +289,5 @@ main(int argc, char **argv)
fclose(outf);
}
close_infile();
exit(0);
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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