Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
c68 -L -r -DMC68000 -DDEBUG -c canon.c
c68 -L -r -DMC68000 -DDEBUG -c codegen.c
c68 -L -r -DMC68000 -DDEBUG -c interf.c
c68 -L -r -DMC68000 -DDEBUG -c main.c
c68 -L -r -DMC68000 -DDEBUG -c optab.c
c68 -L -r -DMC68000 -DDEBUG -c putexpr.c
c68 -L -r -DMC68000 -DDEBUG -c smatch.c
c68 -L -r -DMC68000 -DDEBUG -c sucomp.c
c68 -L -r -DMC68000 -DDEBUG -c tabl.c
c68 -L -r -DMC68000 -DDEBUG -c util.c
c68 -L -r -DMC68000 -DDEBUG -c cskels.c
mkver -e "Code Generator -"
c68 -n -r -L -r -DMC68000 -DDEBUG version.c canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -o c168.4k -l6
setstack c168.4k 8000 8000

View File

@@ -0,0 +1,14 @@
mkver -e "Code Generator -"
cc -DPDP11 -DDEBUG -c canon.c
cc -DPDP11 -DDEBUG -c codegen.c
cc -DPDP11 -DDEBUG -c interf.c
cc -DPDP11 -DDEBUG -c main.c
cc -DPDP11 -DDEBUG -c optab.c
cc -DPDP11 -DDEBUG -c putexpr.c
cc -DPDP11 -DDEBUG -c smatch.c
cc -DPDP11 -DDEBUG -c sucomp.c
cc -DPDP11 -DDEBUG -c tabl.c
cc -DPDP11 -DDEBUG -c util.c
cc -DPDP11 -DDEBUG -c cskels.c
cc -DPDP11 -DDEBUG -c version.c
cc version.o canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -l6 -o c168.pdp

View File

@@ -0,0 +1,14 @@
mkver -e "Code Generator -"
cc -O -w -DVAX11 -DDEBUG -c canon.c
cc -O -w -DVAX11 -DDEBUG -c codegen.c
cc -O -w -DVAX11 -DDEBUG -c interf.c
cc -O -w -DVAX11 -DDEBUG -c main.c
cc -O -w -DVAX11 -DDEBUG -c optab.c
cc -O -w -DVAX11 -DDEBUG -c putexpr.c
cc -O -w -DVAX11 -DDEBUG -c smatch.c
cc -O -w -DVAX11 -DDEBUG -c sucomp.c
cc -O -w -DVAX11 -DDEBUG -c tabl.c
cc -O -w -DVAX11 -DDEBUG -c util.c
cc -O -w -DVAX11 -DDEBUG -c cskels.c
cc -O -w -DVAX11 -DDEBUG -c version.c
cc -n version.o canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -o c168.vax

View File

@@ -0,0 +1,15 @@
mkver -e "C68 Code Generator -"
c68 -S -L -DVERSADOS -DMC68000 canon.c
c68 -S -L -DVERSADOS -DMC68000 codegen.c
c68 -S -L -DVERSADOS -DMC68000 cskels.c
c68 -S -L -DVERSADOS -DMC68000 interf.c
c68 -S -L -DVERSADOS -DMC68000 main.c
c68 -S -L -DVERSADOS -DMC68000 optab.c
c68 -S -L -DVERSADOS -DMC68000 putexpr.c
c68 -S -L -DVERSADOS -DMC68000 smatch.c
c68 -S -L -DVERSADOS -DMC68000 sucomp.c
c68 -S -L -DVERSADOS -DMC68000 tabl.c
c68 -S -L -DVERSADOS -DMC68000 util.c
c68 -S -L -DVERSADOS -DMC68000 version.c
mv *.s vst

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "../icode.h"
#ifdef DRI
# include <stdio.h>
# include <klib.h>
# undef putchar
# define putchar xputchar
# undef ferror
# define ferror xferror
# define printf xprintf
#endif
#define QUICKVAL 8
#define LEP 14
#define FORCC 1
#define FOREFF 2
#define FORSTACK 3
#define FORCREG 4
#define FORSP 5
#define FORREG 4
#define HICREG 2
#define NCREGS 3
#define AREGLO 8
#define IMMED 1
#define NOTIMMED 0
#define NOTLOFFSET 0
#define NOAUTO 1
#define DOAUTO 0
#define STDERR 2
#define PATHSIZE 128
char brtab[][2];
short invrel[];
short swaprel[];
char *strtab[];
/*operator tree node for unary and binary operators*/
struct tnode {
short t_op; /*operator*/
short t_type; /*data type of result*/
short t_su; /*Sethy-Ullman number*/
short t_ssp;
struct tnode *t_left; /*left sub-tree*/
struct tnode *t_right; /*right sub-tree (undefined if unary)*/
};
/*constant terminal node*/
struct conode {
short t_op; /*operator*/
short t_type; /*type*/
short t_su; /*Sethy-Ullman number*/
short t_ssp;
short t_value; /*value or label number*/
};
/*long constant terminal node*/
struct lconode {
short t_op; /*operator*/
short t_type; /*type*/
short t_su; /*Sethy-Ullman number*/
short t_ssp;
long t_lvalue; /*value or label number*/
};
/*local symbol terminal node*/
struct symnode {
short t_op; /*operator*/
short t_type; /*symbol data type*/
short t_su; /*Sethy-Ullman number*/
short t_ssp;
short t_sc; /*storage class*/
short t_offset; /*register offset*/
short t_reg; /*register number*/
short t_label; /*label number if static*/
};
/*external symbol reference node*/
struct extnode {
short t_op; /*operator*/
short t_type; /*symbol data type*/
short t_su; /*Sethy-Ullman number*/
short t_ssp;
short t_sc; /*storage class*/
short t_offset; /*register offset*/
short t_reg; /*register number*/
char t_symbol[SSIZE]; /*symbol name*/
};
/*68000 special - indexed symbol node*/
/*this is used to generate a An(off,Xn.type) address*/
struct indexnode {
short t_op;
short t_type;
short t_su;
short t_ssp;
short t_sc;
short t_offset;
short t_reg;
short t_xreg;
short t_xtype;
};
/* io buffer declaration */
#define BSIZE 512
struct iob {
int fd;
int cc;
char *cp;
char cbuf[BSIZE];
} ibuf, lbuf, obuf;
/* Code generation argument flags */
short dflag;
short mflag;
short cflag;
short eflag;
short fflag;
short oflag;
short lflag;
short m68010; /* [vlh] 4.2, differentiate between chip destination */
/* Miscellaneous variables */
short lineno;
short errcnt;
short opinfo[];
short nextlabel;
char optab[][6];
char *mnemonics[];
char *codeskels[];
short stacksize;
/* general define macros */
#define WALLIGN(add) ((add+1)&(~1))
#define ISARRAY(type) ((type&SUPTYP)==ARRAY)
#define ISFUNCTION(type) ((type&SUPTYP)==FUNCTION)
#define ISPOINTER(type) ((type&SUPTYP)==POINTER)
#define NOTARRAY(type) ((type&SUPTYP)!=ARRAY)
#define NOTFUNCTION(type) ((type&SUPTYP)!=FUNCTION)
#define NOTPOINTER(type) ((type&SUPTYP)!=POINTER)
#define ISFLOAT(type) (type==FLOAT)
#define BTYPE(type) (type&TYPE)
#define SUPTYPE(type) (type&SUPTYP)
#define ISALLTYPE(type) (type&(SUPTYP|TYPE))
#define ISASGOP(op) ((opinfo[op]&OPASSIGN)!=0)
#define RELOP(op) ((opinfo[op]&OPREL)!=0)
#define LINTEGRAL(op) ((opinfo[op]&OPLWORD)!=0)
#define RINTEGRAL(op) ((opinfo[op]&OPRWORD)!=0)
#define RASOP(op) ((opinfo[op]&OPRAS)!=0)
#define BINOP(op) ((opinfo[op]&OPBIN)!=0)
#define UNARYOP(op) ((opinfo[op]&(OPBIN|OPTERM))==0)
#define LEAFOP(op) ((opinfo[op]&OPTERM)!=0)
#define NOTLEAFOP(op) ((opinfo[op]&OPTERM)==0)
#define LVALOP(op) ((opinfo[op]&OPLVAL)!=0)
#define OPPRIORITY(op) (opinfo[op]&OPPRI)
#define COMMOP(op) ((opinfo[op]&OPCOM)!=0)
#define CONVOP(op) ((opinfo[op]&OPCONVS)!=0)
#define NOTCONVOP(op) ((opinfo[op]&OPCONVS)==0)
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
/* one line routines turned into defines [vlh] for speed */
/*outgoto - output "bra L[labno]"*/
#define OUTGOTO(lab) if (lab>0) printf("bra L%d\n",lab)
/*outlab - output "L[labno]:"*/
#define OUTLAB(lab) if (lab>0) printf("L%d:",lab)
/*outext - output register sign extension*/
#define OUTEXT(reg) printf("ext.l R%d\n",reg)
/*outuext - output unsigned to long register extension*/
#define OUTUEXT(reg) printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg)
/*outswap - output swap register instruction*/
#define OUTSWAP(reg) printf("swap R%d\n",reg)
/*outaddr - output "add [type] R1 R2" instruction*/
#define OUTADDR(r1,r2,tp) outrr("add",r1,r2,(tp))
/*outccsave - ouput instruction to move cc's to register*/
#define OUTSRSAVE(reg) printf("move sr,R%d\n",reg)
#define OUTCCSAVE(reg) printf("move ccr,R%d\n",reg)
/*outccrestore - output instruction to restore cc's from register*/
#define OUTCCRESTORE(reg) printf("move R%d,ccr\n",reg)
/*basetype - get the btype info sans unsigned*/
#define BASETYPE(type) ((type==UNSIGNED) ? INT : type)
#define UNSIGN(type) ((type) == UNSIGNED)
#define LONGORPTR(type) (type==LONG || (type&SUPTYP))
#define UNORPTR(type) (type==UNSIGNED || (type&SUPTYP))
#define DREG(reg) ((reg) & (~AREGLO))
#define AREG(reg) ((reg) | AREGLO)
#define ISAREG(reg) ((reg) >= AREGLO)
#define ISDREG(reg) ((reg) < AREGLO)
#define ISREG(tp) ((tp)->t_op == SYMBOL && (tp)->t_sc == REGISTER)
#define CONSTZERO(ltyp,p) ((ltyp && !p->t_lvalue) || (!ltyp && !p->t_value))
#define SETVAL(ltyp,p,val) if (ltyp) p->t_lvalue = val; else p->t_value = val
#ifdef DEBUG
# define PUTEXPR(cond,id_str,node_ptr) if (cond) putexpr(id_str,node_ptr)
#else
# define PUTEXPR(cond,id_str,node_ptr)
#endif
/* Functions pre-declared */
char *tnalloc();
char *snalloc();
char *cenalloc();
char *xnalloc();
char *talloc();
char *cnalloc();
char *lcnalloc();
char *fpcnalloc();
char *canon();
char *commute();
char *constant();
char *match();
char *addptree();
char *fixbfield();
char *coffset();
char *tcopy();
char *fixptree();
long readlong();
short readshort();

View File

@@ -0,0 +1,841 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
#include "cskel.h"
char null[];
char *opname[];
/* scodegen - over-all code generation for expression*/
/* Picks off post-fix ++, --.*/
scodegen(tp,cookie,reg) /* returns register result is in*/
struct tnode *tp;
int cookie;
int reg;
{
struct tnode *clist[20];
struct tnode **clp;
register struct tnode **cp;
register short r, ccflag;
short lconst;
register struct tnode *rtp;
if( tp->t_op == COMMA ) {
scodegen(tp->t_left,FOREFF,reg);
return(scodegen(tp->t_right,cookie,reg));
}
ccflag = 0;
clp = clist;
tp = addptree(tp,&clp);
if( clp > clist ) {
/*
* post ++, -- in tree. We need to compile the tree post operators
* then generate code to do the post operators, then do any fix up of
* condition codes since the Stupid 68000 architect was a nimnul.
*/
if( cookie == FORCC ) {
/*
* here we make the observation that if we are comparing something with
* zero OR the top operator of the tree is not a comparison operator,
* we can compile the tree to a register, and then set the condition
* codes OK with a tst instruction at the end.
*/
if( RELOP(tp->t_op) ) {
if( (rtp=constant(tp->t_right,&lconst)) &&
CONSTZERO(lconst,rtp)) { /* [vlh] */
ccflag = 1;
tp = tp->t_left;
cookie = FORREG;
}
else
ccflag = 2;
}
else {
ccflag = 1;
cookie = FORREG;
}
}
}
r = codegen(tp,cookie,reg);
if( clp > clist ) {
if( ccflag == 2 ) {
if (!m68010) /* [vlh] 4.2, added differentiation */
OUTSRSAVE(r);
else
OUTCCSAVE(r);
}
for( cp = clist; cp < clp; cp++ )
codegen(*cp,FOREFF,r+1);
if( ccflag == 1 )
outcmp0(r,tp);
else if( ccflag == 2 )
OUTCCRESTORE(r);
}
return(r);
}
/* addptree - prune off postfix ++, -- from expression tree*/
/* This prunes off ++, -- and collects those expressions for*/
/* scodegen.*/
char *
addptree(tp,clp) /* returns pointer to pruned tree*/
struct tnode *tp;
struct tnode ***clp;
{
register short op;
register struct tnode *stp;
op = tp->t_op;
if( LEAFOP(op) || op == QMARK || op == LAND || op == LOR ) /* [mac] 4.2 */
return(tp);
if( op == POSTINC || op == POSTDEC ) {
stp = tcopy(tp->t_left,NOAUTO); /* [mac] 4.2 c[i=+1]++ & c[*p++]++ */
*(*clp)++ = fixptree(tp);
return( stp );
}
if( BINOP(op) )
tp->t_right = addptree(tp->t_right,clp);
tp->t_left = addptree(tp->t_left,clp);
return(tp);
}
/* fixptree - fix post-fix tree */
/* This eliminates assignment operators from post-fix tree so that */
/* c[i=+1]++ will only evaluate i=+1 once */
char *
fixptree(tp)
struct tnode *tp;
{
register short op;
op = tp->t_op;
if( LEAFOP(op) )
return(tp);
/* This prevents assignments and pre-operators from being evaluated
twice... */
if( ISASGOP(op) || op == PREDEC || op == PREINC )
return( fixptree(tp->t_left) );
if( BINOP(op) )
tp->t_right = fixptree(tp->t_right);
tp->t_left = fixptree(tp->t_left);
return(tp);
}
/* codegen - generate code for expression*/
/* This calls up rcodegen, which prunes off any special register*/
/* optimization code, then calls ucodegen (unrecursive) code*/
/* generation.*/
codegen(tp,cookie,reg) /* returns reg result is in*/
struct tnode *tp; /* tree pointer*/
int cookie; /* code generation goals*/
int reg; /* first available register*/
{
register short savestk, ssize, r, i;
register struct tnode *rtp;
#ifdef DEBUG
if( cflag )
printf("codegen op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
#endif
switch( tp->t_op ) {
case CALL:
case NACALL:
ssize = 0;
savestk = stacksize;
if( tp->t_left->t_op != SYMBOL )
stacksize++;
if( tp->t_op == CALL ) {
rtp = tp->t_right;
while( rtp->t_op == COMMA ) {
ssize += dofarg(rtp->t_right);
rtp = rtp->t_left;
}
ssize += dofarg(rtp);
}
tp->t_op = FJSR; /*generate JSR (unary op)*/
codegen(tp,FORREG,reg);
popstack(ssize);
stacksize = savestk;
fixresult(tp,cookie,0);
return(0); /*result in R0*/
case COMMA:
codegen(tp->t_left,FOREFF,reg);
return(codegen(tp->t_right,cookie,reg));
case AND:
if( cookie == FORCC && (i=isonebit(tp->t_right)) >= 0 &&
(i=dobitadd(tp->t_left,i)) >= 0 ) {
if( CONVOP(tp->t_right->t_op) )
tp->t_right = tp->t_right->t_left;
tp->t_right->t_value = i;
tp->t_right->t_op = CINT; /* [vlh] 4.1 */
tp->t_right->t_type = INT; /* [vlh] 4.1 */
tp->t_op = BTST;
tp = canon(tp);
sucomp(tp,reg,1);
}
break;
}
if( rcodegen(&tp,cookie,reg) ) {
if( cookie == FORCC && tp->t_op == SYMBOL && tp->t_sc == REGISTER
&& ISDREG(tp->t_reg))
return(reg);
}
r = ucodegen(tp,cookie,reg);
return(r);
}
/* fixresult - fix result of code generation*/
fixresult(tp,cookie,reg) /* returns - none*/
struct tnode *tp;
int cookie; /* wanted this cookie*/
int reg;
{
#ifdef DEBUG
if (cflag)
printf("fixresult cookie=%d reg=%d op=%d\n",cookie,reg,tp->t_op);
#endif
switch( cookie ) {
case FORCC:
outcmp0(reg,tp);
break;
case FORSP:
case FORSTACK:
stacksize++;
outrpush(reg,tp,cookie==FORSTACK);
break;
}
return(reg);
}
/**
* ucodegen - generate code for tree given cookie and starting register
* Handles the matching of the expression tree node with the
* corresponding code generation table. When a match is found,
* expand is called to expand the code skeleton macro.
**/
ucodegen(tp,cookie,reg) /* returns reg result is in*/
struct tnode *tp; /* pointer to expression tree*/
int cookie; /* (FORCC,FOREFF,FORREG,FORSTACK)*/
int reg; /* first available register*/
{
register short r;
register char *p;
register struct tnode *ltp;
short lconst;
PUTEXPR(cflag,"ucodegen",tp);
switch( tp->t_op ) {
case ADDR: /* 4.2 */
ltp = tp->t_left;
if(cookie==FORCC && ltp->t_op==SYMBOL &&
(ltp->t_sc==EXTERNAL || ltp->t_sc==STATIC)) {
warning("function existence test");
printf("tst.l ");
outaexpr(ltp,NOTIMMED);
printf("\n");
return(reg);
}
break;
case STASSIGN: /*[vlh]*/
outstrcpy(codegen(tp->t_left,FORREG,AREG(reg)),
codegen(tp->t_right,FORREG,AREG(reg+1)),tp->t_type);
return(reg);
break;
case SYMBOL:
if( cookie == FOREFF )
return(reg);
break;
case LSH:
if( (ISAREG(reg)) && (p=constant(tp->t_right,&lconst)) &&
!(UNSIGN(tp->t_left->t_type)) &&
((!lconst && (p->t_value == 1 || p->t_value == 2) ) ||
(lconst && (p->t_lvalue == 1 || p->t_lvalue == 2) ))) {
r = codegen(tp->t_left,FORREG,reg);
outmovr(r,reg,tp->t_left);
if( p->t_value == 2 )
OUTADDR(reg,reg,tp);
OUTADDR(reg,reg,tp);
fixresult(tp,cookie,reg);
return(reg);
}
break;
case EQMULT:
case EQDIV:
case LEQMULT:
case LEQDIV:
case EQMOD:
case LEQMOD:
case EQRSH:
case EQLSH:
case EQAND:
case EQOR:
case EQXOR:
if( indexreg(tp->t_left) ) {
reg = DREG(reg);
outmovr(r=tp->t_left->t_reg,reg,tp);
tp->t_left->t_reg = reg;
codegen(tp,cookie,reg+1);
outmovr(reg,r,tp);
return(reg);
}
break;
case ADD:
case EQADD:
if( (p=constant(tp->t_right,&lconst)))
if (!lconst && (p->t_value < 0 && p->t_value >= -QUICKVAL)) {
p->t_value = - p->t_value;
tp->t_op += (SUB-ADD);
}
else if (lconst && p->t_lvalue<0 && p->t_lvalue >= -QUICKVAL) {
p->t_lvalue = -p->t_lvalue;
tp->t_op += (SUB-ADD);
}
break;
} /* end of case statement..... */
sucomp(tp,reg,1);
if( (r=loadexpr(tp,cookie,reg)) >= 0 )
return(r);
if( (r=cqmark(tp,cookie,reg)) >= 0 )
return(r);
if( (r=hardrel(tp,cookie,reg)) >= 0 )
return(r);
if( cookie == FORCC && (p=match(tp,FOREFF,reg)) != 0 ) {
r = expand(tp,FOREFF,reg,p);
if( ISASGOP(tp->t_op) && indexreg(tp->t_left) )
outcmp0(tp->t_left->t_reg,tp->t_left);
}
else if( p = match(tp,cookie,reg) )
r = expand(tp,cookie,reg,p);
else if( cookie != FORREG )
r = fixresult(tp,cookie,ucodegen(tp,FORREG,reg));
else
error("no code table for %s",opname[tp->t_op]);
return(r);
}
/* outstrcpy - output structure copy */
outstrcpy(lr,rr,size) /*[vlh]*/
int lr, rr; /* left register, right register */
int size; /* structure size to copy */
{
register short lab;
#ifdef DEBUG
if (cflag) printf("size is %d\n",size);
#endif
if (ISDREG(lr)) {
printf("move.l r%d,r%d\n",lr,AREG(lr));
lr = AREG(lr);
}
if (ISDREG(rr)) {
printf("move.l r%d,r%d\n",rr,AREG(rr));
rr = AREG(rr);
}
lab = nextlabel++;
printf("move #%d,r%d\n",(size/INTSIZE)-1,DREG(lr));
OUTLAB(lab);
printf("move (r%d)+,(r%d)+\ndbra r%d,L%d\n",rr,lr,DREG(lr),lab);
}
/**
* loadexpr - load an addressable expression into a register
* This checks for any possible usage of the register indexed
* addressing mode. Note that this relies on the good graces of the
* load code skeletons not to muck up the compiler registers before
* loading an addressable expression...
**/
loadexpr(tp,cookie,reg) /* returns register loaded or -1*/
struct tnode *tp; /* pointer to expression tree*/
int reg; /* register to load*/
{
register struct tnode *rtp, *ltp, *xtp, *atp;
register short off, r, type, nr, ar, xr, xt;
if( tp->t_op == INDR || LOADABLE(tp) ) {
PUTEXPR((cflag>1),"loadexpr",tp);
type = tp->t_type;
if( tp->t_op == INDR && (ltp=tp->t_left)->t_op == ADD ) {
rtp = ltp->t_right;
ltp = ltp->t_left;
off = 0;
if( rtp->t_op == CINT && ((off=rtp->t_value) < -128 ||
off > 127 || ltp->t_op != ADD ) ) {
tp = snalloc(type,AUTO,off,0,0);
if( indexreg(ltp) )
tp->t_reg = ltp->t_reg;
else {
r = codegen(ltp,FORREG,AREG(reg));
if( ISDREG(r) )
outmovr(r,AREG(r),ltp);
tp->t_reg = AREG(r);
}
}
else {
if( rtp->t_op == CINT ) {
rtp = ltp->t_right;
ltp = ltp->t_left;
}
if(indexreg(rtp) || (!(indexreg(ltp)) && (ISREG(rtp)))) {
xtp = ltp;
ltp = rtp;
rtp = xtp;
}
xtp = atp = 0;
if( indexreg(ltp) ) {
ar = ltp->t_reg;
if( (ISREG(rtp)) && rtp->t_type != CHAR ) {
xr = rtp->t_reg;
xt = rtp->t_type;
}
else
xtp = rtp;
}
else if( (ISREG(ltp)) && ltp->t_type != CHAR &&
(lflag || rtp->t_op != ADDR) ) {
xr = ltp->t_reg;
xt = ltp->t_type;
atp = rtp;
}
else if( rtp->t_op == ADDR ) {
atp = ltp;
xtp = rtp;
}
else {
atp = rtp;
xtp = ltp;
}
nr = 0;
if( atp )
nr++;
if( xtp && (xtp->t_op != ADDR || lflag ) )
nr++;
if( DREG(nr+reg) <= HICREG ) {
r = reg;
if( atp ) {
ar = codegen(atp,FORREG,AREG(r));
if( ISDREG(ar) ) {
outmovr(ar,AREG(ar),atp);
ar = AREG(ar);
}
r++;
}
if( xtp && xtp->t_op == ADDR && !lflag ) {
tp = xtp->t_left;
tp->t_sc += (EXTOFF-EXTERNAL);
tp->t_offset += off;
tp->t_reg = ar;
}
else {
if( xtp ) {
xr = codegen(xtp,FORREG,AREG(r));
xt = xtp->t_type;
}
tp = xnalloc(type,ar,off,xr,xt);
}
}
}
}
if( (ISAREG(reg)) && tp->t_type == CHAR )
reg = DREG(reg);
tp = tnalloc(LOAD,tp->t_type,SU_EASY,0,tp,null);
PUTEXPR((cflag>1),"loadexpr final",tp);
return( codegen(tp,cookie,reg) );
}
return(-1);
}
/* coffset - check offset for addressable node*/
char *coffset(tp) /* returns ptr to const off node*/
struct tnode *tp; /* pointer to node*/
{
register struct tnode *rtp;
if( tp->t_op == ADD ) {
rtp = tp->t_right;
if( rtp->t_op == CINT )
return(rtp);
if(!lflag) {
if( rtp->t_op == ADDR )
return(rtp->t_left);
rtp = tp->t_left;
if( rtp->t_op == ADDR ) {
tp->t_left = tp->t_right;
tp->t_right = rtp;
return(rtp->t_left);
}
}
}
return(0);
}
/* hardrel - do relationals returning a value*/
hardrel(tp,cookie,reg) /* returns reg or -1*/
struct tnode *tp; /* pointer to tree*/
int cookie; /* cookie for code generation*/
int reg; /* low register*/
{
char *p;
short op, lab1, lab2;
#ifdef DEBUG
if (cflag)
printf("hardrel: cookie=%d op=%d reg=%d\n",cookie,tp->t_op,reg);
#endif
if( cookie != FORCC && (RELOP(op=tp->t_op) || op == LOR ||
op == LAND || op == NOT) ) {
lab1 = nextlabel++;
condbr(tp,TRUE,lab1,reg);
p = canon(cnalloc(INT,0));
codegen(p,cookie,reg);
lab2 = nextlabel++;
OUTGOTO(lab2);
OUTLAB(lab1);
p = canon(cnalloc(INT,1));
codegen(p,cookie,reg);
OUTLAB(lab2);
return(reg);
}
return(-1);
}
/* cqmark - compile question mark operator*/
/* This does the compilation of the question mark operator.*/
cqmark(tp,cookie,reg) /* returns reg or -1*/
struct tnode *tp;
int cookie;
int reg;
{
register short lab1, lab2, savestk, r;
if( tp->t_op == QMARK && cookie != FORCC ) {
lab1 = nextlabel++;
condbr(tp->t_left,FALSE,lab1,reg);
savestk = stacksize;
r = scodegen(tp->t_right->t_left,cookie,reg); /* [mc] 4.0 */
outmovr(r,reg,tp);
stacksize = savestk;
OUTGOTO(lab2=nextlabel++);
OUTLAB(lab1);
r = scodegen(tp->t_right->t_right,cookie,reg); /* [mc] 4.0 */
outmovr(r,reg,tp);
OUTLAB(lab2);
return(reg);
}
return(-1);
}
/**
* condbr - handle conditional branch code generation
* This handles the conditional branch code generation, handling
* the special cases for constants, ||, &&, ! and generating the
* correct conditional branch instruction.
**/
condbr(tp,dir,lab,reg)
struct tnode *tp;
int dir;
int lab;
int reg;
{
register struct tnode *ltp, *rtp;
register short lab1, optype, op, subdir;
ltp = tp->t_left;
if( BINOP(op=tp->t_op) )
rtp = tp->t_right;
subdir = dir; /*set up for LOR*/
#ifdef DEBUG
if (cflag)
printf("condbr: dir = %d, lab = %d, reg = %d\n",dir,lab,reg);
#endif
switch( op ) {
case CINT:
if( !tp->t_value ) {
if( dir == FALSE )
OUTGOTO(lab);
}
else if( dir != FALSE )
OUTGOTO(lab);
break;
case NOT:
condbr(ltp,!dir,lab,reg);
break;
case LAND:
dir = !dir;
case LOR:
if( dir == FALSE ) {
lab1 = nextlabel++;
condbr(ltp,!subdir,lab1,reg);
condbr(rtp,subdir,lab,reg);
OUTLAB(lab1);
}
else {
condbr(ltp,subdir,lab,reg);
condbr(rtp,subdir,lab,reg);
}
break;
case COMMA:
scodegen(tp->t_left,FOREFF,reg);
condbr(tp->t_right,dir,lab,reg);
break;
default: /* [mc] 4.2.b */
if( ((dir!=0 && op==NEQUALS) || (dir==0 && op==EQUALS)) &&
ltp->t_op==PREDEC && rtp->t_op==CINT && rtp->t_value == -1 &&
ISDREG(ltp->t_left->t_reg) && ltp->t_left->t_type==INT) {
outdbra(ltp->t_left->t_reg,lab);
break;
}
if( RELOP(op) && ltp->t_op == AUTOINC && rtp->t_op == AUTOINC &&
ltp->t_type == rtp->t_type )
outcmpm(tp);
else
scodegen(tp,FORCC,reg);
optype = 0;
if( RELOP(op) ) {
if( UNORPTR(ltp->t_type) || UNORPTR(rtp->t_type) )
optype++;
}
else
op = NEQUALS;
if(!dir)
op = invrel[op-EQUALS];
optype = brtab[op-EQUALS][optype];
printf("%s L%d\n",mnemonics[optype],lab);
break;
}
}
rcodegen(tpp,cookie,reg) /* returns changed flag*/
struct tnode **tpp; /* pointer to tree*/
int cookie; /* code generation cookie*/
int reg; /* register to use for code*/
{
register short change, op;
register struct tnode *tp;
tp = *tpp;
op = tp->t_op;
change = 0;
if (NOTLEAFOP(op) && op!=COMMA && op!=QMARK && op!=LAND && op!=LOR &&
op!=LESS && op!=LESSEQ && op!=GREAT && op!=GREATEQ) {
change += rcodegen(&tp->t_left,cookie,reg);
if( BINOP(op) )
change += rcodegen(&tp->t_right,cookie,reg);
change += rcgen(tpp,cookie,reg);
} /* [vlh] 4.2 stop getting to this code on <, >, <=, >= */
if( change )
*tpp = canon(*tpp);
return(change);
}
rcgen(tpp,cookie,reg) /* returns changed flag*/
struct tnode **tpp; /* pointer to tree*/
int cookie; /* code generation goals*/
int reg; /* register to use*/
{
register struct tnode *tp, *p, *ltp, *rtp;
register short op, change;
change = 0;
for( tp = *tpp ; BINOP(op=tp->t_op); *tpp=tp=canon(tp), change++ ) {
ltp = tp->t_left;
if( ltp->t_op != SYMBOL )
break;
rtp = tp->t_right;
switch( op ) {
case ASSIGN:
if( ltp->t_sc != REGISTER )
return(change);
switch( rtp->t_op ) {
case MULT:
case DIV:
case MOD:
case AND:
case OR:
case XOR:
case LSH:
case RSH:
if( ISAREG(ltp->t_reg) )
return(change);
case ADD:
case SUB:
p = rtp->t_right;
if(NOTADDRESSABLE(ltp) || !noref(rtp->t_right,ltp->t_reg))
return(change);
p = rtp->t_left;
if( p->t_op != SYMBOL || p->t_sc != REGISTER ||
p->t_reg != ltp->t_reg ) {
tp->t_right = p;
PUTEXPR((cflag>1),"rcgen",tp);
codegen(tp,FOREFF,reg);
}
tp->t_right = rtp->t_right;
tp->t_op = rtp->t_op + (EQADD-ADD);
continue;
}
case EQLSH:
case EQRSH:
if( ltp->t_sc != REGISTER )
return(change);
case EQADD:
case EQSUB:
case EQAND:
case EQOR:
case EQXOR:
PUTEXPR((cflag>1),"rcgen EQOP",tp);
if( ltp->t_type == CHAR ) {
#ifdef DEBUG
if (cflag>1) printf("exiting rcgen with ltp type CHAR change %d\n",change);
#endif
return(change);
}
ucodegen(tp,FOREFF,reg);
tp = ltp;
continue;
case PREDEC:
case PREINC:
if(cookie==FORCC || ltp->t_type==CHAR)
return(change);
ucodegen(tp,FOREFF,reg);
tp = ltp;
continue;
}
break;
}
return(change);
}
noref(tp,reg) /* 4.0 change */
struct tnode *tp; /* returns 1 if no reference in tree to reg */
int reg;
{
if ( LEAFOP(tp->t_op) ) {
if (tp->t_op == SYMBOL && tp->t_sc == REGISTER && tp->t_reg == reg)
return(0);
return(1);
}
if ( !noref(tp->t_left,reg) )
return(0);
if (BINOP(tp->t_op))
return( noref(tp->t_right,reg) );
return(1);
}
/* cdsize - compute size of data item*/
cdsize(tp) /* returns data size in bytes*/
struct tnode *tp;
{
register short type;
type = tp->t_type;
if( SUPTYPE(type) )
return(PTRSIZE);
switch( type ) {
case INT:
case CHAR:
case UCHAR: /* [vlh] 4.2 */
case UNSIGNED:
return(INTSIZE);
case LONG:
case ULONG: /* [vlh] 4.2 */
case FLOAT: /* [vlh] 3.4 */
return(LONGSIZE);
}
error("cdsize: invalid type %d",type);
return(0);
}
dofarg(tp) /* returns number of bytes pushed*/
struct tnode *tp; /* pointer to expression tree*/
{
register short nb;
nb = 0;
if( tp->t_op == SYMBOL && tp->t_sc == STRUCT )
error("structure operation not implemented");
else if( stacksize ) {
codegen(tp,FORSTACK,0);
nb = cdsize(tp);
}
else
codegen(tp,FORSP,0);
return( nb );
}
/* dobitadd - do bit operation address checking and fixup*/
dobitadd(tp,bitno) /* returns -1 if can't or bitno*/
struct tnode *tp;
int bitno;
{
register short offset;
if( tp->t_type == CHAR )
offset = 0;
else
offset = cdsize(tp) - (bitno/BITSPBYTE) - 1;
if( tp->t_op == SYMBOL ) {
switch( tp->t_sc ) {
case REGISTER:
if( ISDREG(tp->t_reg) )
return(bitno);
default:
return(-1);
case EXTERNAL:
case STATIC:
case REGOFF:
case STATOFF:
case EXTOFF:
tp->t_offset += offset;
return( bitno % BITSPBYTE );
}
}
else if( tp->t_op == INDR ) {
tp->t_left = tnalloc(ADD,tp->t_left->t_type,0,0,tp->t_left,
cnalloc(INT,offset));
return( bitno % BITSPBYTE );
}
return(-1);
}
isonebit(tp) /* returns -1 if not 1 bit, else bitno*/
struct tnode *tp; /* pointer to tree*/
{
short lconst;
long bvalue;
if (!(tp = constant(tp,&lconst))) /* [vlh] 4.1 added long... */
return(-1);
bvalue = (lconst) ? tp->t_lvalue : (long) tp->t_value;
return(onebit(bvalue));
}

View File

@@ -0,0 +1,93 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave
San Diego, Ca. 92121
*/
/*built-in literals*/
#define MOV 128
#define MOVL 129
#define JSR 130
#define CLR 131
#define CLRL 132
#define EXTW 133
#define EXTL 134
#define LEA 135
#define STK 136
/*built-in macros*/
#define TREE 141
#define LEFT 142
#define RIGHT 143
#define LOFFSET 144
#define ROFFSET 145
#define LADDR 146
#define RADDR 147
#define CR 148
#define NR 149
#define CAR 150
#define NAR 151
#define TLEFT 152
#define TRIGHT 153
#define TEITHER 154
#define TLEFTL 155
#define OP 156
#define AOP 157
#define MODSWAP 158
#define EXL 159
#define EXLR 160
#define EXLRN 161
#define EXRL 162
#define EXRLN 163
#define PSH 164
#define POP 165
#define POP8 166
#define OPCALL 167
#define POP4 169
#define LADDRP 168
/*modifiers for compiling sub-trees*/
#define S_INDR 1 /*indirection*/
#define S_STACK 2 /*onto stack*/
#define S_FORCC 4 /*set condition codes*/
#define S_NEXT 8 /*into next register*/
/*Sethy-Ullman values*/
#define SU_ZERO 0x000 /*zero*/
#define SU_ONE 0x100 /*one*/
#define SU_SMALL 0x200 /*constant between 1 and 8*/
#define SU_QUICK 0x300 /*quick constant between -128 and 127*/
#define SU_CONST 0x400 /*any constant*/
#define SU_AREG 0x500 /*A register*/
#define SU_REG 0x600 /*register*/
#define SU_ADDR 0x700 /*addressable*/
#define SU_XREG 0x800 /*A register used as data...*/
#define SU_EASY 0x900 /*easy*/
#define SU_HARD 0xa00 /*hard*/
#define SU_VHARD 0xb00 /*very hard ... function calls, etc.*/
#define SU_ANY 0xf00 /*anything*/
#define ADDRESSABLE(x) (x->t_su<=SU_ADDR)
#define NOTADDRESSABLE(x) (x->t_su>SU_ADDR)
#define LOADABLE(x) (x->t_su<=SU_XREG)
/*flag byte (operand type):*/
#define T_CHAR 1 /*char only*/
#define T_SHORT 2 /*short*/
#define T_INT 3 /*int only*/
#define T_LONG 4 /*long*/
#define T_UCHAR 5 /*unsigned char*/
#define T_USHORT 6 /*unsigned short*/
#define T_UNSN 7 /*unsigned int*/
#define T_ULONG 8 /*unsigned long*/
#define T_FLOAT 9 /*float*/
#define T_DOUB 10 /*double*/
#define T_ANY 11 /*int or word (implied)*/
#define T_UANY 12 /*4.2 unsigned short or char*/
#define T_INDR 0x10 /*pointer type (bit)*/
struct skeleton {
short sk_left;
short sk_right;
char *sk_def;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
can't create (filename)
can't open (filename)
cdsize: invalid type (number)
code skeleton error: (number)
divide by zero
expression too complex
expression too complex
intermediate code error (number,number)
invalid floating op (number)
invalid initialization
invalid operator (number)
invalid register expression
invalid storage class (number)
modulus by zero
no code table for (number)
opcall bad op (number)
structure operation not implemented
usage: c168 icode asm [-DLmec]

View File

@@ -0,0 +1,142 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
short bol;
short gflag;
short onepass;
/* outexpr - output expression*/
outexpr(tp) /* returns - none*/
struct tnode *tp; /* pointer to tree node*/
{
outline();
if( exprok(tp) ) {
#ifdef DEBUG
if (cflag) printf("outexpr 1: type is %d\n",tp->t_type);
#endif
scodegen(canon(tp),FOREFF,0);
#ifdef DEBUG
if (cflag) printf("outexpr 2: type is %d\n",tp->t_type);
#endif
}
}
outifgoto(tp,dir,lab)
struct tnode *tp;
int dir;
int lab;
{
outline();
if( exprok(tp) )
condbr(canon(tp),dir,lab,0);
}
outcforreg(tp)
struct tnode *tp;
{
outline();
if( exprok(tp) )
outmovr(scodegen(canon(tp),FORREG,0),0,tp);
}
outinit(tp) /* returns - none*/
struct tnode *tp;
{
register short typeout;
outline();
if( exprok(tp) ) {
typeout = tp->t_type;
tp = canon(tp);
if( tp->t_op == ADDR )
tp = tp->t_left;
if( tp->t_op == CINT || tp->t_op == CLONG || tp->t_op == SYMBOL ) {
if( tp->t_op != CINT ) /* [vlh] 4.1 added CLONG... */
printf(".dc.l ");
else {
printf(".dc");
outtype(typeout);
putchar(' ');
}
outaexpr(tp,NOTIMMED); /* [vlh] 4.0 not immed... */
}
else
error("invalid initialization");
putchar('\n');
}
}
/* snalloc - code generator symbol node allocation*/
/* This might be coalesced into parser snalloc.*/
char *snalloc(type,sc,offset,dp,ssp) /* returns ptr to node alloced*/
int type; /* type of symbol*/
int sc; /* storage class*/
int offset; /* offset from Local Environment Ptr*/
int dp; /*for compatability with parser*/
int ssp; /*for compatability with parser*/
{
register struct symnode *sp;
sp = talloc(sizeof(*sp));
sp->t_op = SYMBOL;
sp->t_type = type;
sp->t_su = dp;
sp->t_ssp = ssp;
sp->t_sc = sc;
switch( sc ) {
case STATIC:
sp->t_offset = 0;
sp->t_reg = 0;
sp->t_label = offset;
break;
case REGISTER:
sp->t_offset = 0;
sp->t_reg = offset;
sp->t_label = 0;
break;
case AUTO:
sp->t_sc = REGOFF;
sp->t_offset = offset;
sp->t_reg = LEP;
sp->t_label = 0;
break;
default:
sp->t_offset = offset;
sp->t_reg = 0;
sp->t_label = 0;
break;
}
return(sp);
}
exprok(tp)
struct tnode *tp;
{
if( tp < exprarea || tp > &exprarea[EXPSIZE] )
return(0);
if( LEAFOP(tp->t_op) )
return(1);
if( BINOP(tp->t_op) && !exprok(tp->t_right) )
return(0);
return( exprok(tp->t_left) );
}
outline()
{
if( onepass && !bol )
putchar('\n');
if (!gflag)
printf("*line %d\n",lineno);
else
printf("~_lN%d:\n",lineno);
}

View File

@@ -0,0 +1,372 @@
.he "C68 Code Generator"Change Log"Page %"
.de bg
.sp
.in +5
..
.de eg
.sp
.in -5
..
1. 7/20/82 - Post fix operators
.bg
Post fix operators were being handled a la PDP-11, i.e. if( x++ ) ...
would be true if the result of the post-increment were true rather than
the original value of x.
Also, if( --x ) ... would generate an unnecessary test instruction.
Added scodegen (delay???) routine to pick off post-fix operators,
call codegen to generate the code for the pruned tree, then generate code
for the post-fix operators.
This will generate horrendous code for something like: if( x[i]++ );
but t.s.
.eg
2. 7/21/82 - divide by long constant
.bg
The construct: x / 10L did not generate a ldiv call because long constants
Sethy-Ullman numbers are being calculated normally.
Added DCLONG operator and check in canon to check for this case.
This prevents sucomp from incorrectly computing the Sethy-Ullman number.
.eg
3. 7/23/82 - shifting long or byte address by 1
.bg
The construct: x =<< 1 generated an invalid assembly instruction if x
was an automatic or static byte or long.
This is because you may only shift words in memory (The 68000
clone strikes again!!!).
Changed code skeletons for eqshft to only match for addressable words.
.eg
4. 8/7/82 - complex long divide/modulus expressions
.bg
Complex expressions involving long over short divides or modulus would
not work, not consistently sign extending word result.
Changed test in expand to check for DIV or MOD operators in long tree
and set extf flag.
.eg
5. 8/7/82 - add of quick negative did not generate subq
.bg
The expression: x = y - 1; with x & y registers generated an add #-1,Rx
rather than suq #1,Rx. This was because rcgen was turning ADD into EQADD.
Added test in ucodegen for both ADD and EQADD.
.eg
6. 8/12/82 - multiply(divide) by -1
.bg
The expression: x =* -1; was being "optimized" to negate x, however it
did not store the result in x.
This is because of multiply/divide by -1 optimization in canon not
checking for =* or =/.
Added checks.
.eg
7. 8/27/82 - character array assigned function value
.bg
The expression: x[i] = f(i); did not generate correct code, the address
register for x[i] was computed, but not saved on stack, then f was called.
This resulted in all further function calls using the first argument
push rather than a move.
In ucodegen, when optimizing for address register shifted left by 1 or 2
did not do fixresult call which would have saved register on stack.
Added this call.
Also added code skeleton to compile the function expression to the stack,
then move that directly to the computed address.
.eg
8. 9/1/82 - address-indexed addressing mode used .b index
.bg
If the index register used in an address-indexed addressing mode
operand was byte, the index register was given a .b extension even
though it had correctly extended the register to a word.
In outaexpr for INDEXED addressing mode an outatype of the index
type should have been used rather than outtype.
.eg
9. 9/1/82 - x =* -1, x =/ -1, x=^ -1 optimizations
.bg
Added EQNEG and EQNOT operators and added checks in canon so that
x =* -1 and x =/ -1 are changed to neg operations and x =^ -1 is
changed to not operation.
.eg
10. 9/15/82 - function redeclaration bug
.bg
If an external function was redeclared in a function body, a
redeclaration error occured.
This was fixed in dodecl by checking for a function of AUTO type
and changing it to a function of EXTERNAL type.
.eg
11. 9/15/82 - Hard long to register fix
.bg
The syntax: b =* x; where b was a long register would give an error
"hard long to register".
This was because the lamul function expected to do the assignment to
a memory location.
Changed canon so that hard =*, =/ and =% would be changed to use
the normal long multiply and divide routines, and then do an assignment.
.eg
12. 9/15/82 - Casting Problems (Not fixed)
.bg
The syntax: i = (char) i; where i is not a register would result in
i being assigned the high-order byte of i.
This also is a problem for any cast where the cast type is smaller
than the type being cast.
Generally this should be solved by moving the expression into a data
register, and then obtaining the result from there.
Added DOCAST operator to handle these problems.
However, this is all tightly interwined with conversions in the parser.
.eg
13. 11/24/82 - More than two constants couldn't be combined
.bg
Constant optimization failed to mathematically compute constant
arithmetic fully (the results were lost) thus yielding the result
as the computation of the last two constants in the expression
only.
.eg
14. 12/13/82 - structure assignments
.bg
One structure may be assigned to another provided that the one on
the right is smaller than or equal to the left one in size.
.eg
15. 1/10/83 - floating point
.bg
Floating point handling including constants, conversions and operations
added.
.eg
16. 1/14/83 - pop stack instruction
.bg
The popstack instruction of 1..8 was turned into an addq.w which only
affected half of the sp register. The "add #d,sp" has been replaced
by either "addq.l #d,sp" or "adda.l #d,sp".
.eg
17. 1/14/83 - optimization eqmult, eqdiv, eqmod
.bg
Generated a new code skeleton entry to deal with register integer mults,
divs, and mods (eg. register int i; i =* 34;).
.eg
18. 1/17/83 - return of 0L
.bg
Code skeletons generated a clr R0 regardless of operand type.
.eg
19. 1/21/83 - prefix ++, -- problems with bytes
.bg
The code skeletons for fr_eqop were a total mess, particularly for
the left hand side being a character.
Rewrote all fr_eqop and fr_eqmult code skeletons to handle these cases.
Unfortunately rcgen also gets into the act turning all =+, =-, =&, =| and
pre++, pre-- compiled for register into compiled for effect then returning
the left hand side symbol.
This is probably OK for word and long LHS but for byte it results in
lost precision.
Changed rcgen to check for CHAR LHS and not to compile for effect if so.
.eg
20. 2/2/83 - long eq_shift int
.bg
Bad code was generated for long's left shifted by integer values.
.eg
21. 2/23/83 - longs divided by integers
.bg
Ext.l was not always done.
.eg
22. 3/1/83 - casting to char
.bg
Added the docast operator, forces the variable to be put into a register
and an ext.w to be acted upon it.
.eg
23. 3/2/83 - casting register char * to int
.bg
Bad code was generated for casting a character to an integer if the
character was pointed to by a register character pointer.
.eg
24. 3/3/83 - Compiling complex indirect into A Reg.
.bg
The construct: *p->q->r generated an intermediate load into a D reg
then move to A reg, rather than compiling directly into A reg.
This was because of some hysterical PDP-11 code in expand checking
for whether an A register is appropriate.
.eg
25. 3/3/83 - dbra instruction
.bg
The construct: if( --i != -1 ) goto x; now generates a dbra i,x
instruction. This combined with the new for and while loops easily
enables you to generate dbra instructions for loops. This affected
code in condbr to check for the specific expression tree above.
.eg
26. 3/3/83 - Bit field assigned to bit field
.bg
The construct: x.bf1 = x.bf2 failed due to fixbfield not fixing up
the RHS of the expression. Added recursive call to fixbfield to
fix up RHS's of equal operators.
.eg
27. 3/4/83 - Post increment with ?: op
.bg
Post increment and post decrement operations can not be delayed in the
case of a ?: operation. The post operation was taking place regardless
of whether the case in question was executed.
.eg
28. 3/7/83 - long div/mod/mul/sub/add const 1L or const 0L
.bg
Added optimization handling for long constant zero and one handling.
An error is now generated is a mod or div 0 is found. Add/Sub of
a consant 0 does not generate any code. Mult/Div 1 does not generate
any code
.eg
29. 3/8/83 - eqmod 1 and eqmult 0
.bg
Incorrect storage of simple expressions eqmod 1 and eqmult 0 which
result in a zero store. Also added for the long case.
.eg
30. 3/18/83 - reg ptr assign and character compare
.bg
The statement if (*(regptr = str)); did not do the test for the character
pointed to but rather the result of the assignment. This was caused
by a codegen optimization which should not include a-registers.
.eg
31. 3/21/83 - Complex assignment to character array
.bg
The expression: ca[i] = f(); would move i to the stack as a word and pop
it as a long.
This was caused by the code skeleton macro (S_FORSTACK + S_INDR) assuming
what was going on the stack will always be a long.
Did quick and dirty fix in expand to extend an int sub-tree to a long
if compiling subtree FORSTACK+INDR.
.eg
32. 4/4/83 - unary operations on address registers [vlh] 4.1
.bg
Operations involving unary operations on addresses was not forcing the
use of a temporary data register to do the actual operation. This
was causing bad code to be generated for certain expressions, eg.
array[-i], or array[~i].
.eg
33. 5/23/83 - long constant optimizations [vlh] 4.1
.bg
Changed all the constant optimizations to handle longs as well as
ints. This will make life more difficult on the pdp-11 but makes
for more optimal code (eg. l *= 2...).
.eg
34. 5/25/83 - pre-operators over &&, ||, ? [vlh] 4.1
.bg
Preincrement/decrement were not working correctly over &&, || and ?
operators.
This was due to rcgen generating code for preinc/dec even if && or ||
was seen in tree.
Added test in rcodegen to stop trying for register optimizations over &&, ||
and ?.
.eg
35. 5/25/83 - post-operators over &&, ||. [vlh] 4.1
.bg
Postincrement/decrement operators were not working correctly over && and ||.
This was due to scodegen/addptree pulling out all post-operators over && and
|| operators. Added check in addptree to stop at && and ||.
Condbr then does an scodegen over the && and || to do the post-operators.
.eg
36. 5/25/83 - post-increments over assigns and autoinc/dec [mc] 4.1
.bg
Postincrement/decrement over expressions involving assignment operators and
autoinc/autodec did not work correctly. For example: c[i=+1]++ and c[*p++]++;
This was because the sub-expression tree which is copied did not adjust for
things which are being altered in the sub-expression.
Fixed tcopy, addptree and fixbfield to fix this problem.
This is not guaranteed to work in extremely complicated code involving
assignment and post-op operators, for example, something like:
c[c[i=+1]++]++; And is especially not guaranteed to work with bit-fields
in something like: (c[i=+1]++)->bitfield.
.eg
37. 6/1/83 - long multiplication/division as array subscripts [vlh] 4.1
.bg
Array subscripts which involved long operations which required calls to function
routines expected the results to be left in the first address register rather
than the first data register. This caused bad code to be generated.
.eg
38. 6/1/83 - allow long array indices [vlh] 4.1
.bg
In order to generate arrays which are as big as memory the arrays must be larger
than an int in side we need to also allow array indices to be longs. This was
tied in with the long constant evaluation.
.eg
39. 6/21/83 - link file [vlh] 4.2
.bg
Added the link file as an input file, this is necessary for auto inits
and block variables.
Added the symbol "%" as a readicode symbol to signify the need to pull
an entry out of the link file which is being created by the parser.
.eg
40. 7/6/83 - dbra instruction 4.2
.bg
Fixed the dbra conditional test to not be used in the case of a complex
expression (eg. while(--regi != -1 && *l != '\n'); )..
.eg
41. 7/11/83 - if test float [vlh] 4.2
.bg
The testing for float true was not being handled. The construction
if (fp); now does a test for the floating point value being a non zero
32 bit value. This is taking advantage of the fact that both floating
point constructs denote the value zero as a zero.
.eg
42. 7/13/83 - short vs. long vs. int [vlh] 4.2
.bg
For the sake of portability and the likelihood of generating the same
code on the vax which supports a 16 bit short, a 32 bit int and a 32
bit long versus Regulus which supports a 16 bit short, a 16 bit int and
a 32 bit long the code generator has been changed to use only longs
and shorts on the theory that most machines support 16 bit shorts and
32 bit longs.
.eg
43. 7/20/83 - symbolic debugger flag [vlh] 4.2
.bg
Added the '-g' flag. Required a change to the outline routine to outline
cdb type line number identifying lables rather than the standard sort.
Also altered readicode to output a line number identifier on a null
expression (allows a line number to be placed previous to asm() code
as well as loops).
.eg
44. 7/22/83 - Suppress optimization which gens bad code [vlh] 4.2
.bg
Changed rcodegen to not do the rcgen call if the operator is less-than,
or greater-than. This keeps certain expressions from being evaluated
in the wrong order. In particular ((regi=f(3)) > f(1)).
.eg
45. 7/25/83 - unsigned char/long [vlh] 4.2
.bg
Initial work required to generate code for unsigned char and unsigned
long types.
.eg
46. 7/26/83 - preinc/dec, postinc/dec floats [vlh] 4.2
.bg
Added OPCALL entries for preinc/predec and postinc/postdec.
.eg
47. 8/2/83 - bad optimizations [vlh] 4.2
.bg
An expression anded (&) with a 0 or an expression multiplied (*) by a
zero in which the expression has side effects (eg. function call which
changes global variables) would cause bad code to be generated. This
has been a problem in a number of other compilers and was noted on the
usenet by DMR himself.
.eg
48. 8/3/83 - 68010 changes [vlh] 4.2
.bg
Added the 68010 flag (called m68010). Code now generates a "move cc"
instead of "move sr" in scodegen if the 68010 flag is specified. An
alternative routine fakecmpm has been added because the 68010 does not
properly handle the cmpm instruction.
.eg
49. 8/9/83 - source file [vlh] 4.2
.bg
Fixed readicode to pick up a source filename as well as the current line
number, for use in error reporting.
.eg
50. 8/10/83 - int cast pushed on stack as long [vlh] 4.2
.bg
Fixed match() so that it would not optimize out conversion operators on
items destined to be put on the stack (eg. f(((int)l)&0xff);). Required
adding a test for cookie != FORSP.
.eg
51. 8/23/83 - long indexes [vlh] 4.2
.bg
Fixed optim to not optimize long constant offsets into arrays into 16 bit
displacements.
.eg
52. 8/26/83 - constant int/long assigned to char [vlh] 4.2
.bg
Added code to optim to truncate Constant integers and longs which were
being assigned to character values via ops: equal, eqadd, eqsub, eqand,
eqor, eqxor.
.eg
53. 8/30/83 - if (main)... [vlh] 4.2
.bg
Altered outaexpr to not generate the '#' preceding a symbol expression
which does not have an offset and is and external or static variable
being generated for condition codes.
.eg

View File

@@ -0,0 +1,623 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
char *version = "@(#)c168 code generator 4.2 - Sep 6, 1983";
/**
* ALCYON C Compiler for the Motorola 68000 - Code Generator
*
* Called from c68:
*
* c168 icode link asm
*
* icode: parsed intermediate code with some assembly code
* preceded by left parens.
*
* link: contains the procedure link and movem instructions.
*
* asm: output assembler code for as68.
*
* The basic structure of the code generator is as follows:
*
* main - main routine
* readicode - code generation driven by intermediate code
*
**/
#include "cgen.h"
#include "cskel.h"
char *opap;
short gflag;
short nextlabel = 10000;
char null[] = "";
short lflag = 1;
char source[PATHSIZE] = "";
char *readtree();
char *readsym();
/* main - main routine, handles arguments and files*/
main(argc,argv) /* returns - none*/
int argc; /* arg count*/
char **argv; /* arg pointers*/
{
register char *q, *calledby;
calledby = *argv++;
if( argc < 4 )
usage(calledby);
if( fopen(*argv,&ibuf,0) < 0 ) /* 3rd arg for versados */
ferror("can't open %s",*argv);
if( fopen(*++argv,&lbuf,0) < 0)
ferror("can't open %s",*argv);
if( fcreat(*++argv,&obuf,0) < 0 )
ferror("can't create %s",*argv);
for( argc -= 4; argc--; ) {
q = *++argv;
if( *q++ != '-' )
usage(calledby);
while( 1 ) {
switch( *q++ ) {
case 'a': /* [vlh] 4.2, alter ego of the '-L' flag */
lflag = 0;
continue;
case 'c':
cflag++;
continue;
case 'e':
eflag++;
continue;
case 'f':
fflag++;
continue;
case 'g': /* [vlh] 4.2 generate line labels for cdb */
gflag++;
continue;
case 'm':
mflag++;
continue;
case 'o':
oflag++;
continue;
case 'D':
dflag++;
continue;
case 'L': /* [vlh] 4.2, OBSOLETE */
lflag++;
continue;
case 'T': /* [vlh] 4.2 generates code for the 68010 */
m68010++;
continue;
case '\0':
break;
default:
usage(calledby);
}
break;
}
}
readicode();
myfflush(&obuf);
exit(errcnt!=0);
}
/* readicode - read intermediate code and dispatch output*/
/* This copies assembler lines beginning with '(' to assembler*/
/* output and builds trees starting with '.' line.*/
readicode() /*returns - none*/
{
register short c;
register struct tnode *tp;
while( (c=getc(&ibuf)) > 0 ) {
switch(c) {
case '.':
lineno = readshort();
readfid();
opap = exprarea;
if( tp = readtree() ) {
PUTEXPR(cflag,"readicode",tp);
switch( tp->t_op ) {
case INIT:
outinit(tp->t_left);
break;
case CFORREG:
outcforreg(tp->t_left);
break;
case IFGOTO:
outifgoto(tp->t_left,tp->t_type,tp->t_su);
break;
default:
outexpr(tp);
break;
}
}
else
outline();
break;
case '(':
while( (c=getc(&ibuf)) != '\n' )
putchar(c);
putchar(c);
break;
case '%': /* [vlh] 4.2 */
while( (c=getc(&ibuf)) != '\n' )
; /* skip over carriage return */
while( (c=getc(&lbuf)) != '%' && c != -1)
putchar(c);
if (c == -1)
ferror("early termination of link file");
break;
default:
error("intermediate code error %c,%d",c,c);
break;
}
}
}
/* readtree - recursive intermediate code tree read*/
char *
readtree() /* returns ptr to expression tree*/
{
register short op, type, sc;
register struct tnode *tp, *rtp;
char sym[SSIZE];
if( (op=readshort()) <= 0 )
return(0);
type = readshort();
switch( op ) {
case SYMBOL:
if( (sc=readshort()) == EXTERNAL )
tp = cenalloc(type,sc,readsym(sym));
else
tp = snalloc(type,sc,readshort(),0,0);
break;
case CINT:
tp = cnalloc(type,readshort());
break;
case CLONG:
tp = lcnalloc(type,readlong()); /* [vlh] 4.1 was two readshort's */
break;
case CFLOAT: /* [vlh] 3.4 */
tp = fpcnalloc(type,readlong()); /* [vlh] 4.1 was two readshort's */
break;
case IFGOTO:
case BFIELD:
sc = readshort();
if( tp = readtree() )
tp = tnalloc(op,type,sc,0,tp,null);
break;
default:
if( BINOP(op) ) {
if( !(tp=readtree()) )
return(0);
if( !(rtp=readtree()) )
return(0);
tp = tnalloc(op,type,0,0,tp,rtp);
}
else if( tp = readtree() )
tp = tnalloc(op,type,0,0,tp,null);
break;
}
return(tp);
}
/* readfid - read source filename out of intermediate file */
readfid()
{
register char *p;
p = &source[0];
while( (*p = getc(&ibuf)) != '\n')
p++;
*p = 0;
}
/* readshort - reads an integer value from intermediate code*/
short
readshort()
{
register short c;
register short i;
i = 0;
while(1) {
switch( c = getc(&ibuf) ) {
case '.':
case '\n':
return(i);
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
i <<= 4;
i += (c-'0');
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
i <<= 4;
i += (c-('a'-10));
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
i <<= 4;
i += (c-('A'-10));
break;
default:
error("intermediate code error - %c,%d",c,c);
}
}
}
/* readlong - reads a long value from intermediate code*/
long
readlong() /* [vlh] 4.1 */
{
long l;
register unsigned short w1, w2;
register short c, onedot;
w2 = 0; onedot = 0;
while(1) {
switch( c = getc(&ibuf) ) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
w2 <<= 4;
w2 += (c-'0');
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
w2 <<= 4;
w2 += (c-('a'-10));
break;
case '.':
if (!onedot++) {
w1 = w2;
w2 = 0;
continue;
}
case '\n':
if (onedot) {
l.hiword = w1;
l.loword = w2;
return(l);
}
default:
error("intermediate code error - %c,%d",c,c);
}
}
}
/* readsym - read a symbol from intermediate code*/
char *readsym(sym)
char *sym;
{
register short i, c;
register char *s;
for( i = SSIZE, s = sym; (c=getc(&ibuf)) != '\n'; )
if( --i >= 0 )
*s++ = c;
if( i > 0 )
*s = '\0';
return(sym);
}
/* error - output an error message*/
error(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
errcnt++;
if( lineno != 0 )
printf((char *)STDERR,"\"%s\", ** %d: ",source,lineno);
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
cputc('\n',STDERR);
}
/* warning - output a warning message*/
warning(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
if( lineno != 0 )
printf((char *)STDERR,"\"%s\", ** %d: (warning) ",source,lineno);
else
printf((char *)STDERR,"(warning) ");
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
cputc('\n',STDERR);
}
/* ferror - output error message and die*/
ferror(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
error(s,x1,x2,x3,x4,x5,x6);
exit(1);
}
/* tnalloc - allocate binary expression tree node*/
/* returns ptr to node made.*/
char *tnalloc(op,type,info,dummy,left,right)
int op; /* operator*/
int type; /* resultant node type*/
int info; /* info field*/
int dummy; /* dummy field - used to match pass1 args*/
struct tnode *left; /* left sub-tree*/
struct tnode *right; /* righst sub-tree*/
{
register struct tnode *tp;
tp = talloc(sizeof(*tp));
tp->t_op = op;
tp->t_type = type;
tp->t_su = info; /* info for bit-field & condbr's*/
tp->t_left = left;
tp->t_right = right;
return(tp);
}
/* cnalloc - allocate constant expression tree node*/
char *cnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
int value; /* value of constant*/
{
register struct conode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CINT;
cp->t_type = type;
cp->t_value = value;
return(cp);
}
/* lcnalloc - allocate constant expression tree node*/
char *lcnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
long value; /* value of constant*/
{
register struct lconode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CLONG;
cp->t_type = type;
cp->t_lvalue = value;
return(cp);
}
/* fpcnalloc - allocate constant expression tree node*/
char *fpcnalloc(type,value) /* returns pointer to node alloced*/
int type; /* type of constant*/
long value; /* value of constant*/
{ /* [vlh] 3.4 */
register struct lconode *cp;
cp = talloc(sizeof(*cp));
cp->t_op = CFLOAT;
cp->t_type = type;
cp->t_lvalue = value;
return(cp);
}
/* talloc - allocate expression tree area*/
char *talloc(size) /* returns pointer to area alloced*/
int size; /* number of bytes to alloc*/
{
register char *p;
p = opap;
if( p + size >= &exprarea[EXPSIZE] )
ferror("expression too complex");
opap = p + size;
return(p);
}
/* symcopy - copy symbol*/
symcopy(sym1,sym2) /* returns - none*/
char *sym1; /* from symbol*/
char *sym2; /* to symbol*/
{
register char *p, *q;
register short i;
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
*q++ = (*p ? *p++ : '\0');
}
/* usage - ouput usage message*/
usage(calledby)
char *calledby;
{
ferror("usage: %s icode link asm [-DLameco]",calledby);
}
/* cputc - put a character to a file descriptor (used by error) */
cputc(c, fn)
char c;
int fn;
{
#ifdef VERSADOS
versaputchar(c);
#else
if (fn == STDERR)
write(STDERR, &c, 1);
else
putchar(c);
#endif
}
/**
* putchar - special version
* This allows the use of printf for error messages, debugging
* output and normal output.
**/
putchar(c) /* returns - none*/
char c; /* character to output*/
{
if( dflag > 1 )
write(1,&c,1); /*to standard output*/
putc(c,&obuf); /*put to assembler file*/
}
#ifdef VERSADOS
#define STDOUT 1
struct iob versfout { STDOUT, BSIZE, &versfout.cbuf[0]};
versaputchar(c)
char c;
{
if (c == '\n') { /* end of line */
if (versaflush()) /* write one line */
return(-1);
return(c);
}
/* buffered output */
if (versfout.cc <= 0) {
versfout.cp = &(versfout.cbuf[0]);
if (write(versfout.fd,versfout.cp,BSIZE) != BSIZE)
return(-1);
versfout.cc = BSIZE;
}
*(versfout.cp)++ = c;
versfout.cc--;
return(c);
}
versaflush()
{
register short size, fildes;
if ((size = (BSIZE - versfout.cc)) == 0)
return(0);
versfout.cc = BSIZE;
versfout.cp = &(versfout.cbuf[0]);
fildes = (versfout.fd <= STDERR) ? 6 : versfout.fd;
if (write(fildes,versfout.cp,size) < 0)
return(-1);
return(0);
}
#else
# ifdef VAX11
getc(ibuf)
struct iob *ibuf;
{
if (ibuf->cc <= 0) {
ibuf->cp = &(ibuf->cbuf[0]);
ibuf->cc = read(ibuf->fd,ibuf->cp,BSIZE);
}
if (ibuf->cc <= 0)
return(-1);
ibuf->cc--;
return((int)(*(ibuf->cp)++)&0xff);
}
fopen(fname,ibuf)
char *fname;
register struct iob *ibuf;
{
ibuf->cc = 0; /* no chars */
ibuf->fd = open(fname,0);
return(ibuf->fd);
}
# endif
#endif
myfflush(mybuf)
register struct iob *mybuf;
{
register i;
i = BSIZE - mybuf->cc;
mybuf->cc = BSIZE;
mybuf->cp = &(mybuf->cbuf[0]);
if (write(mybuf->fd,mybuf->cp,i) != i)
return(-1);
return(0);
}
#ifdef DRI
printf(string,a,b,c,d,e,f,g)
char *string;
int a,b,c,d,e,f,g;
{
char area[256];
register char *p;
sprintf(area,string,a,b,c,d,e,f,g);
for(p = &area[0]; *p ; p++ )
putchar(*p);
}
#endif

View File

@@ -0,0 +1,116 @@
CC = cc
C68 = nc68
VAXOBJS = vaxobj/canon.o \
vaxobj/codegen.o \
vaxobj/interf.o \
vaxobj/main.o \
vaxobj/optab.o \
vaxobj/putexpr.o \
vaxobj/smatch.o \
vaxobj/sucomp.o \
vaxobj/tabl.o \
vaxobj/util.o \
vaxobj/cskels.o
C68OBJS = 68obj/canon.o \
68obj/codegen.o \
68obj/interf.o \
68obj/main.o \
68obj/optab.o \
68obj/putexpr.o \
68obj/smatch.o \
68obj/sucomp.o \
68obj/tabl.o \
68obj/util.o \
68obj/cskels.o
CFLAGS = -O -w -DVAX11 -DDEBUG
C68FLAGS = -L -r -DMC68000 -DDEBUG -t0 -t1
LIB = -lV6
C68LIB = -l6
.IGNORE:
vax: ${VAXOBJS}
mkver -e "Code Generator -"
${CC} ${CFLAGS} version.c ${VAXOBJS} -o c168.vax ${LIB}
c168: ${C68OBJS}
mkver -e "Code Generator -"
${C68} -r ${C68FLAGS} version.c ${C68OBJS} -o c168.68 ${C68LIB}
setstack c168.68 8000 8000
2k: ${C68OBJS}
mkver -e "Code Generator -"
${C68} -n2 -r ${C68FLAGS} version.c ${C68OBJS} -o c168.2k ${C68LIB}
setstack c168.2k 8000 8000
4k: ${C68OBJS}
mkver -e "Code Generator -"
${C68} -n -r ${C68FLAGS} version.c ${C68OBJS} -o c168.4k ${C68LIB}
setstack c168.4k 8000 8000
all: vax 4k
vaxobj/canon.o: canon.c
${CC} ${CFLAGS} -c canon.c;mv -f canon.o vaxobj/canon.o
vaxobj/codegen.o: codegen.c
${CC} ${CFLAGS} -c codegen.c;mv -f codegen.o vaxobj/codegen.o
vaxobj/interf.o: interf.c
${CC} ${CFLAGS} -c interf.c;mv -f interf.o vaxobj/interf.o
vaxobj/main.o: main.c
${CC} ${CFLAGS} -c main.c;mv -f main.o vaxobj/main.o
vaxobj/optab.o: optab.c
${CC} ${CFLAGS} -c optab.c;mv -f optab.o vaxobj/optab.o
vaxobj/putexpr.o: putexpr.c
${CC} ${CFLAGS} -c putexpr.c;mv -f putexpr.o vaxobj/putexpr.o
vaxobj/smatch.o: smatch.c
${CC} ${CFLAGS} -c smatch.c;mv -f smatch.o vaxobj/smatch.o
vaxobj/sucomp.o: sucomp.c
${CC} ${CFLAGS} -c sucomp.c;mv -f sucomp.o vaxobj/sucomp.o
vaxobj/tabl.o: tabl.c
${CC} ${CFLAGS} -c tabl.c;mv -f tabl.o vaxobj/tabl.o
vaxobj/util.o: util.c
${CC} ${CFLAGS} -c util.c;mv -f util.o vaxobj/util.o
vaxobj/cskels.o: cskels.c
${CC} ${CFLAGS} -c cskels.c;mv -f cskels.o vaxobj/cskels.o
68obj/canon.o: canon.c
${C68} ${C68FLAGS} -c canon.c;mv -f canon.o 68obj/canon.o
68obj/codegen.o: codegen.c
${C68} ${C68FLAGS} -c codegen.c;mv -f codegen.o 68obj/codegen.o
68obj/interf.o: interf.c
${C68} ${C68FLAGS} -c interf.c;mv -f interf.o 68obj/interf.o
68obj/main.o: main.c
${C68} ${C68FLAGS} -c main.c;mv -f main.o 68obj/main.o
68obj/optab.o: optab.c
${C68} ${C68FLAGS} -c optab.c;mv -f optab.o 68obj/optab.o
68obj/putexpr.o: putexpr.c
${C68} ${C68FLAGS} -c putexpr.c;mv -f putexpr.o 68obj/putexpr.o
68obj/smatch.o: smatch.c
${C68} ${C68FLAGS} -c smatch.c;mv -f smatch.o 68obj/smatch.o
68obj/sucomp.o: sucomp.c
${C68} ${C68FLAGS} -c sucomp.c;mv -f sucomp.o 68obj/sucomp.o
68obj/tabl.o: tabl.c
${C68} ${C68FLAGS} -c tabl.c;mv -f tabl.o 68obj/tabl.o
68obj/util.o: util.c
${C68} ${C68FLAGS} -c util.c;mv -f util.o 68obj/util.o
68obj/cskels.o: cskels.c
${C68} ${C68FLAGS} -c cskels.c;mv -f cskels.o 68obj/cskels.o

View File

@@ -0,0 +1,16 @@
CC = c68
OBJS = canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o \
tabl.o util.o cskels.o
CFLAGS = -L -r
LIB = -l6
st: ${OBJS}
@mkver -e "code generator - "
${CC} ${CFLAGS} -n ${OBJS} version.c ${LIB} -o c168.st
@setstack c168.st 8192 8192 ; size c168.st
c068: ${OBJS}
@mkver -e "code generator - "
${CC} ${CFLAGS} ${OBJS} version.c ${LIB} -o c168.68
@setstack c168.68 8192 8192 ; size c168.68

View File

@@ -0,0 +1,16 @@
>mkver -e "C68 Code Generator -"
char *compiled = "@(#) C68 Code Generator - Wed Sep 7 16:05 1983";
>c68 -S -L -DVERSADOS -DMC68000 canon.c
>c68 -S -L -DVERSADOS -DMC68000 codegen.c
>c68 -S -L -DVERSADOS -DMC68000 cskels.c
>c68 -S -L -DVERSADOS -DMC68000 interf.c
>c68 -S -L -DVERSADOS -DMC68000 main.c
>c68 -S -L -DVERSADOS -DMC68000 optab.c
>c68 -S -L -DVERSADOS -DMC68000 putexpr.c
>c68 -S -L -DVERSADOS -DMC68000 smatch.c
>c68 -S -L -DVERSADOS -DMC68000 sucomp.c
>c68 -S -L -DVERSADOS -DMC68000 tabl.c
>c68 -S -L -DVERSADOS -DMC68000 util.c
>c68 -S -L -DVERSADOS -DMC68000 version.c
>mv *.s vst
>

View File

@@ -0,0 +1,323 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
#include "cskel.h"
#define I_NULL 0
#define I_ADD 1
#define I_INC 2
#define I_SUB 3
#define I_DEC 4
#define I_MULS 5
#define I_MULU 6
#define I_DIVS 7
#define I_DIVU 8
#define I_ASR 9
#define I_LSR 10
#define I_ASL 11
#define I_LSL 12
#define I_AND 13
#define I_OR 14
#define I_EOR 15
#define I_NEG 16
#define I_NOT 17
#define I_MOVE 18
#define I_CLR 19
#define I_CMP 20
#define I_TST 21
#define I_LMUL 22
#define I_LDIV 23
#define I_LREM 24
#define I_LEML 25
#define I_LERM 27
#define I_BEQ 28
#define I_BNE 29
#define I_BGT 30
#define I_BGE 31
#define I_BLT 32
#define I_BLE 33
#define I_BLS 34
#define I_BLO 35
#define I_BCC 36
#define I_BHI 37
#define I_BRA 38
#define I_NOP 39
#define I_BTST 40
char *mnemonics[] = {
"",
"add",
"inc",
"sub",
"dec",
"muls",
"mulu",
"divs",
"divu",
"asr",
"lsr",
"asl",
"lsl",
"and",
"or",
"eor",
"neg",
"not",
"move",
"clr",
"cmp",
"tst",
"lmul",
"_ldiv",
"lrem",
"almul",
"aldiv",
"alrem",
"beq",
"bne",
"bgt",
"bge",
"blt",
"ble",
"bls",
"blo",
"bcc",
"bhi",
"jmp",
"*nop",
"btst",
};
#define FE_EQOP 1
#define FE_ASSIGN 2
#define FE_EQSHFT 3
#define FE_EQXOR 4
#define FE_EQADDR 5
#define FC_FIX 6
#define FC_REL 7
#define FC_BTST 8
#define FS_OP 9
#define FS_ITL 10
#define FS_LD 11
#define FR_ADD 12
#define FR_MULT 13
#define FR_DIV 14
#define FR_SHFT 15
#define FR_XOR 16
#define FR_NEG 17
#define FR_EQOP 18
#define FR_POSTOP 19
#define FR_ASSIGN 20
#define FR_EQMULT 21
#define FR_EQDIV 22
#define FR_EQSHFT 23
#define FR_EQXOR 24
#define FR_CALL 25
#define FR_ITL 26
#define FR_LTI 27
#define FR_LD 28
#define FR_EQADDR 29
#define FR_EQNOT 30
#define FE_EQNOT 31
#define FR_DOCAST 32
#define FS_DOCAST 33
#define FR_FTOL 34
#define FR_LTOF 35
#define FR_FTOI 36
#define FR_ITOF 37
#define FE_EQMULT 38
#define FE_EQDIV 39
#define FE_EQMOD 40
#define FR_TOCHAR 41
extern struct skeleton /*char /* really struct skeleton.... */
fe_eqop[], /* 1=FE_EQOP */
fe_assign[], /* 2=FE_ASSIGN */
fe_eqshft[], /* 3=FE_EQSHFT */
fe_eqxor[], /* 4=FE_EQXOR */
fe_eqaddr[], /* 5=FE_EQADDR */
fc_fix[], /* 6=FC_FIX */
fc_rel[], /* 7=FC_REL */
fc_btst[], /* 8=FC_BTST */
fs_op[], /* 9=FS_OP */
fs_itl[], /* 10=FS_ITL */
fs_ld[], /* 11=FS_LD */
fr_op[], /* 12=FR_OP */
fr_mult[], /* 13=FR_MULT */
fr_div[], /* 14=FR_DIV */
fr_shft[], /* 15=FR_SHFT */
fr_xor[], /* 16=FR_XOR */
fr_neg[], /* 17=FR_NEG */
fr_eqop[], /* 18=FR_EQOP */
fr_postop[], /* 19=FR_POSTOP */
fr_assign[], /* 20=FR_ASSIGN */
fr_eqmult[], /* 21=FR_EQMULT */
fr_eqdiv[], /* 22=FR_EQDIV */
fr_eqshft[], /* 23=FR_EQSHFT */
fr_eqxor[], /* 23=FR_EQXOR */
fr_call[], /* 24=FR_CALL */
fr_itl[], /* 25=FR_ITL */
fr_lti[], /* 26=FR_LTI */
fr_ld[], /* 27=FR_LD */
fr_eqaddr[], /* 28=FR_EQADDR */
fr_eqnot[], /* 29=FR_EQNOT */
fe_eqnot[], /* 30=FE_EQNOT */
fr_docast[], /* 31=FR_DOCAST */
fs_docast[], /* 32=FS_DOCAST */
fr_ftol[], /* 34=FE_FTOL */
fr_ltof[], /* 35=FE_LTOF */
fr_ftoi[], /* 36=FE_FTOI */
fr_itof[], /* 37=FE_ITOF */
fe_eqmult[], /* 38=FE_EQMULT */
fe_eqdiv[], /* 39=FE_EQDIV */
fe_eqmod[], /* 40=FE_EQMOD */
fr_tochar[]; /* 41=FR_TOCHAR */
char *codeskels[] = {
0, /*NULL*/
fe_eqop, /*1=FE_EQOP*/
fe_assign, /*2=FE_ASSIGN*/
fe_eqshft, /*3=FE_EQSHFT*/
fe_eqxor, /*4=FE_EQXOR*/
fe_eqaddr, /*5=FE_EQADDR*/
fc_fix, /*6=FC_FIX*/
fc_rel, /*7=FC_REL*/
fc_btst, /*8=FC_BTST*/
fs_op, /*9=FS_OP*/
fs_itl, /*10=FS_ITL*/
fs_ld, /*11=FS_LD*/
fr_op, /*12=FR_OP*/
fr_mult, /*13=FR_MULT*/
fr_div, /*14=FR_DIV*/
fr_shft, /*15=FR_SHFT*/
fr_xor, /*16=FR_XOR*/
fr_neg, /*17=FR_NEG*/
fr_eqop, /*18=FR_EQOP*/
fr_postop, /*19=FR_POSTOP*/
fr_assign, /*20=FR_ASSIGN*/
fr_eqmult, /*21=FR_EQMULT*/
fr_eqdiv, /*22=FR_EQDIV*/
fr_eqshft, /*23=FR_EQSHFT*/
fr_eqxor, /*24=FR_EQXOR*/
fr_call, /*25=FR_CALL*/
fr_itl, /*26=FR_ITL*/
fr_lti, /*27=FR_LTI*/
fr_ld, /*28=FE_LD*/
fr_eqaddr, /*29=FE_EQADDR*/
fr_eqnot, /*30=FE_EQNOT*/
fe_eqnot, /*31=FE_EQNOT*/
fr_docast, /*32=FE_DOCAST*/
fs_docast, /*33=FS_DOCAST*/
fr_ftol, /*34=FE_FTOL*/
fr_ltof, /*35=FE_LTOF*/
fr_ftoi, /*36=FE_FTOI*/
fr_itof, /*37=FE_ITOF*/
fe_eqmult, /*38=FE_EQMULT*/
fe_eqdiv, /*39=FE_EQDIV*/
fe_eqmod, /*40=FE_EQMOD*/
fr_tochar, /*41=FR_TOCHAR*/
};
/*
*This is the major table directing the code generation process.
*It is indexed by an O_op operator, which is obtained from the
*opinfo table for an intermediate code operator. The actual
*code skeleton macros are in cskels.c, which are in a linked
*list in order of decreasing order of difficulty.
*/
char optab[][6] = {
/* I I2 effect cc's stack register*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*0=NULL*/
I_ADD, I_INC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*1=ADD*/
I_SUB, I_DEC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*2=SUB*/
I_MULS, I_MULU, I_NULL, FC_FIX, I_NULL, FR_MULT, /*3=MULT*/
I_DIVS, I_DIVU, I_NULL, FC_FIX, I_NULL, FR_DIV, /*4=DIV*/
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*5=MOD*/
I_ASR, I_LSR, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*6=RSH*/
I_ASL, I_LSL, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*7=LSH*/
I_AND, I_AND, I_NULL, FC_FIX, FS_OP, FR_ADD, /*8=AND*/
I_OR, I_OR, I_NULL, FC_FIX, FS_OP, FR_ADD, /*9=OR*/
I_EOR, I_EOR, I_NULL, FC_FIX, I_NULL, FR_XOR, /*10=XOR*/
I_NULL, I_NULL, I_NULL, FC_FIX, I_NULL, I_NULL, /*11=NOT*/
I_NEG, I_NEG, I_NULL, FC_FIX, I_NULL, FR_NEG, /*12=NEG*/
I_NOT, I_NOT, I_NULL, I_NULL, I_NULL, FR_NEG, /*13=COMPL*/
I_SUB, I_DEC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*14=PREDEC*/
I_ADD, I_INC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*15=PREINC*/
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*16=POSTDEC*/
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*17=POSTINC*/
I_MOVE, I_CLR, FE_ASSIGN, I_NULL, I_NULL, FR_ASSIGN, /*18=ASSIGN*/
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*19=EQADD*/
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*20=EQSUB*/
I_MULS, I_MULU, FE_EQMULT, FC_FIX, I_NULL, FR_EQMULT, /*21=EQMULT*/
I_DIVS, I_DIVU, FE_EQDIV, FC_FIX, I_NULL, FR_EQDIV, /*22=EQDIV*/
I_DIVS, I_DIVU, FE_EQMOD, I_NULL, I_NULL, FR_EQDIV, /*23=EQMOD*/
I_ASR, I_LSR, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*24=EQRSH*/
I_ASL, I_LSL, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*25=EQLSH*/
I_AND, I_AND, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*26=EQAND*/
I_OR, I_OR, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*27=EQOR*/
I_EOR, I_EOR, FE_EQXOR, FC_FIX, I_NULL, FR_EQXOR, /*28=EQXOR*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_CALL, /*29=FJSR*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*30=EQUALS*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*31=NEQUALS*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*32=GREAT*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*33=GREATEQ*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*34=LESS*/
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*35=LESSEQ*/
I_NULL, I_NULL, I_NULL, I_NULL, FS_ITL, FR_ITL, /*36=INT2L*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTI, /*37=LONG2I*/
I_BTST, I_BTST, I_NULL, FC_BTST, I_NULL, I_NULL, /*38=BTST*/
I_CMP, I_TST, I_NULL, FC_REL, FS_LD, FR_LD, /*39=LOAD*/
I_MULS, I_MULU, I_NULL, I_NULL, I_NULL, FR_MULT, /*40=LMULT*/
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*41=LDIV*/
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*42=LMOD*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*43=NULL*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*44=NULL*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*45=NULL*/
I_NULL, I_NULL, FE_EQADDR, I_NULL, I_NULL, FR_EQADDR, /*46=EQADDR*/
I_NOT, I_NOT, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*47=EQNOT*/
I_NEG, I_NEG, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*48=EQNEG*/
I_NULL, I_NULL, I_NULL, I_NULL, FS_DOCAST, FR_DOCAST, /*49=DOCAST*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*50=STASSIGN*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTOF, /*51=LONG2F*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOL, /*52=FLOAT2L*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_ITOF, /*53=INT2F*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOI, /*54=FLOAT2I*/
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_TOCHAR, /*55=TOCHAR*/
};
/*this maps comparison operators and comparison types into the*/
/*actual branch opcode used.*/
char brtab[][2] = {
I_BEQ, I_BEQ, /*EQUALS*/
I_BNE, I_BNE, /*NEQUALS*/
I_BGT, I_BHI, /*GREAT*/
I_BGE, I_BCC, /*GREATEQ*/
I_BLT, I_BLO, /*LESS*/
I_BLE, I_BLS, /*LESSEQ*/
};
/*turns !x>y into x<=y*/
short invrel[] = { NEQUALS, EQUALS, LESSEQ, LESS, GREATEQ, GREAT };
/*turns x>y into y<=x*/
short swaprel[] = { EQUALS, NEQUALS, LESS, LESSEQ, GREAT, GREATEQ };
/*code skeleton built-in strings*/
char *strtab[] = {
"move", /*MOV*/
"move.l", /*MOVL*/
"jsr", /*JSR*/
"clr", /*CLR*/
"clr.l", /*CLRL*/
"ext.w", /*EXTW*/
"ext.l", /*EXTL*/
"lea", /*LEA*/
"(sp)", /*STK*/
};

View File

@@ -0,0 +1,252 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
char invalid[] = "INVALID";
char *opname[] = {
invalid, /*0*/
"+", /*1*/
"-", /*2*/
"*", /*3*/
"/", /*4*/
"%", /*5*/
">>", /*6*/
"<<", /*7*/
"&", /*8*/
"|", /*9*/
"^", /*10*/
"!", /*11*/
"U-", /*12*/
"~", /*13*/
"--p", /*14*/
"++p", /*15*/
"p--", /*16*/
"p++", /*17*/
"=", /*18*/
"+=", /*19*/
"-=", /*20*/
"*=", /*21*/
"/=", /*22*/
"%=", /*23*/
">>=", /*24*/
"<<=", /*25*/
"&=", /*26*/
"|=", /*27*/
"^=", /*28*/
"jsr", /*29*/
"==", /*30*/
"!=", /*31*/
">", /*32*/
">=", /*33*/
"<", /*34*/
"<=", /*35*/
"int->long", /*36*/
"long->int", /*37*/
"btst", /*38*/
"load", /*39*/
"long*", /*40*/
"long/", /*41*/
"long%", /*42*/
"long*=", /*43*/
"long/=", /*44*/
"long%=", /*45*/
"=addr", /*46*/
"=not", /*47*/
"=neg", /*48*/
"docast", /*49*/
"st=", /*50*/
"long->float", /*51*/
"float->long", /*52*/
"int->float", /*53*/
"float->int", /*54*/
"tochar", /*55*/
invalid, /*56*/
invalid, /*57*/
invalid, /*58*/
invalid, /*59*/
"U&", /*60 ADDR*/
"U*", /*61 INDR*/
"&&", /*62*/
"||", /*63*/
"?", /*64*/
":", /*65*/
",", /*66*/
"cint", /*67*/
"clong", /*68*/
"symbol", /*69*/
"++a", /*70*/
"a--", /*71*/
"call", /*72*/
"call()", /*73*/
"bitfield", /*74*/
"if", /*75*/
"init", /*76*/
"loadR0", /*77*/
"divlong", /*78*/
};
#ifdef DEBUG
char *types[] = {
"typeless-invalid", /*0=TYPELESS*/
"char", /*1=CHAR*/
"short", /*2=SHORT*/
"int", /*3=INT*/
"long", /*4=LONG*/
"uchar-invalid", /*5=UCHAR*/
"ushort-invalid", /*6=USHORT*/
"uint", /*7=UINT*/
"ulong-invalid", /*8=ULONG*/
"float", /*9=FLOAT*/
"double", /*10=DOUBLE*/
"struct", /*11=STRUCT*/
invalid, /*12=undefined*/
invalid, /*13=undefined*/
invalid, /*14=undefined*/
invalid, /*15=undefined*/
};
char *suvals[] = {
"zero",
"one",
"quick",
"small",
"constant",
"Areg",
"Dreg",
"addressable",
"loadable",
"easy",
"hard",
"veryhard",
};
short level;
putexpr(name,tp)
char *name;
struct tnode *tp;
{
printf("%s\n",name);
putsexpr(tp);
}
putsexpr(tp)
struct tnode *tp;
{
level++;
outlevel();
printf("%s ",opname[tp->t_op]);
if( tp->t_op == BFIELD || tp->t_op == IFGOTO ) {
if( tp->t_op == BFIELD )
printf("off=%d len=%d\n",(tp->t_su>>8)&0377,tp->t_su&0377);
else
printf("%s goto L%d\n",tp->t_type?"TRUE":"FALSE",tp->t_su);
putsexpr(tp->t_left);
level--;
return;
}
puttsu(tp);
switch( tp->t_op ) {
case DCLONG:
case CLONG:
case CFLOAT: /*[vlh] 3.4 */
printf(" %x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
break;
case CINT:
printf(" %d\n",tp->t_value);
break;
case AUTODEC:
case AUTOINC:
printf(" R%d\n",tp->t_reg);
break;
case SYMBOL:
switch( tp->t_sc ) {
case REGISTER:
printf(" R%d",tp->t_reg);
break;
case CINDR:
printf(" %d\n",tp->t_offset);
break;
case CLINDR:
case CFINDR: /* [vlh] 3.4 */
printf(" %x.%x\n",tp->t_offset,tp->t_ssp);
break;
case REGOFF:
printf(" %d(R%d)",tp->t_offset,tp->t_reg);
break;
case EXTERNAL:
case EXTOFF:
printf(" %s+%d",tp->t_symbol,tp->t_offset);
if( tp->t_sc == EXTOFF )
printf("(R%d)",tp->t_reg);
break;
case STATIC:
case STATOFF:
printf(" L%d+%d",tp->t_label,tp->t_offset);
if( tp->t_sc == STATOFF )
printf("(R%d)",tp->t_reg);
break;
case INDEXED:
printf(" %d(R%d,R%d)",tp->t_offset,tp->t_reg,tp->t_xreg);
break;
}
putchar('\n');
break;
case IFGOTO:
putsexpr(tp->t_left);
break;
default:
putchar('\n');
putsexpr(tp->t_left);
if( BINOP(tp->t_op) )
putsexpr(tp->t_right);
break;
}
level--;
}
outlevel()
{
register short i;
for( i = 0; i < level; i++ ) {
putchar(' ');putchar(' ');putchar(' ');putchar(' ');
}
}
puttsu(tp)
struct tnode *tp;
{
register short i;
if( SUPTYPE(tp->t_type) )
putchar('*');
printf("%s ",types[BTYPE(tp->t_type)]);
if( tp->t_su != 0 || (tp->t_op == CINT && tp->t_value == 0) ) {
i = tp->t_su >> 8;
if( i > 15 || i < 0 )
printf("INVALID");
else
printf("%s",suvals[tp->t_su>>8]);
}
}
#endif

View File

@@ -0,0 +1,535 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/* Code Skeleton expansion and matching */
#include "cgen.h"
#include "cskel.h"
#define SK_TYPE(x) (x&017)
/* expand - code skeleton expansion*/
/* Handles the expansion of code skeleton macros.*/
expand(tp,cookie,freg,skp) /* returns register result is in*/
struct tnode *tp; /* pointer to expression tree*/
int cookie; /* goal of expression tree*/
int freg; /* register to leave results in*/
struct skeleton *skp; /* pointer to code skeleton*/
{
register short op, nreg, reg;
register short c;
register short extf, i2f;
register struct tnode *ltp, *rtp;
register char *p;
register short i, sreg, flag, subtrees, scookie;
register char *macro;
/**
* This is a kludge because not all of the arithmetic operators
* will work on address registers - the 68000 clone strikes again
**/
op = tp->t_op;
#ifdef DEBUG
if(eflag) printf("expand op=%d left=%x right=%x skp=%lo\n",op,
skp->sk_left,skp->sk_right,skp);
#endif
if(((op>=MULT && op<=COMPL) || (op>=LMULT && op<=LMOD)) || tp->t_type==CHAR)
freg = DREG(freg); /* [vlh] 4.1 added UMINUS, COMPL, LMUL, LDIV */
macro = skp->sk_def;
i2f = extf = 0;
rtp = ltp = tp->t_left;
subtrees = 1;
if( BINOP(op) ) {
subtrees++;
rtp = tp->t_right;
if( (LONGORPTR(tp->t_type)) && (op == DIV || op == MOD ||
(op != MULT && (ISDREG(freg)) &&
!(LONGORPTR(ltp->t_type)) && !(LONGORPTR(rtp->t_type)))) )
extf++;
switch( op ) {
case RSH:
case LSH:
case EQLSH:
case EQRSH:
if( UNSIGN(ltp->t_type) )
i2f++;
break;
case MULT:
case EQMULT:
case DIV:
case MOD:
case EQDIV:
case EQMOD:
if( UNSIGN(ltp->t_type) || UNSIGN(rtp->t_type) )
i2f++;
break;
}
}
nreg = freg + 1;
while( c = *macro++ ) {
c &= 0xff;
switch( c ) {
default:
putchar(c);
break;
case POP:
stacksize--;
printf("(sp)+");
break;
case POP4:
stacksize--;
popstack(4);
break;
case POP8:
stacksize -= 2;
popstack(8);
break;
case PSH:
if( cookie == FORSP ) /*don't affect sp*/
printf("(sp)");
else
printf("-(sp)");
stacksize++;
break;
case MOV:
case MOVL:
case JSR:
case CLR:
case CLRL:
case EXTW:
case EXTL:
case LEA:
case STK:
printf("%s",strtab[c-128]);
break;
case OPCALL:
op_expand(op,tp->t_type,ltp->t_type);
break;
case TLEFT:
outtype( LEAFOP(op) ? tp->t_type : ltp->t_type );
break;
case TLEFTL:
outatype( LEAFOP(op) ? tp->t_type : ltp->t_type );
break;
case TEITHER:
if( LONGORPTR(rtp->t_type) || LONGORPTR(ltp->t_type) )
outtype(LONG);
break;
case TRIGHT:
outtype(rtp->t_type);
break;
case OP:
case AOP:
if( c == AOP || i2f )
i = optab[op][1];
else
i = optab[op][0];
printf(mnemonics[i]);
break;
case LADDR:
case RADDR:
p = ((c==RADDR) ? rtp : ltp);
outaexpr(p,IMMED);
break;
case CR:
outcreg(freg);
break;
case NR:
outcreg(nreg);
break;
case CAR:
outcreg(AREG(freg));
break;
case NAR:
outcreg(AREG(nreg));
break;
case EXL:
outextend(ltp,LONG,freg);
break;
case EXRL:
case EXRLN:
outextend(rtp,ltp->t_type,c==EXRL?freg:nreg);
break;
case EXLR:
case EXLRN:
outextend(ltp,rtp->t_type,c==EXLR?freg:nreg);
break;
case LEFT:
case RIGHT:
subtrees--;
case TREE:
p = (c==LEFT?ltp:c==RIGHT?rtp:tp);
flag = *macro++;
scookie = FORREG;
if( flag & S_STACK ) {
if( cookie == FORSP )
scookie = FORSP;
else
scookie = FORSTACK;
}
else if( flag & S_FORCC )
scookie = FORCC;
if( flag & S_NEXT )
reg = nreg;
else
reg = freg;
if( flag & S_INDR ) {
if( p->t_op != INDR )
error("code skeleton error: %d\n",op);
p = p->t_left; /*skip INDR*/
if( coffset(p) ) {
p = p->t_left;
if( LONGORPTR(p->t_type) == 0 && (flag&S_STACK) != 0 )
p = tnalloc(INT2L,LONG,0,0,p);
}
reg = AREG(reg); /*no qualifications before...*/
#ifdef DEBUG
if (eflag)
printf("reg = %d, nreg = %d, freg = %d\n",reg,nreg,freg);
#endif
}
sreg = codegen(p,scookie,reg); /*code for subtree*/
if( scookie == FORREG ) {
if( flag & S_INDR ) {
if( ISDREG(sreg) )
outmovr(sreg,AREG(reg),p);
}
else if( flag & S_NEXT )
nreg = sreg;
else if( sreg != reg ) {
/*
* result was not in expected register, if remaining sub-tree can be
* compiled using the remaining registers, update current and next
* registers, saving us the trouble of moving the register.
*/
if( c == TREE || ((ISDREG(sreg)) && subtrees > 0 &&
((c == LEFT &&
sucomp(rtp,sreg,0) <= skp->sk_right &&
sucomp(rtp,sreg,1) <= SU_ANY) ||
( c == RIGHT &&
sucomp(ltp,sreg,0) <= skp->sk_left &&
sucomp(ltp,sreg,1) <= SU_ANY))) ) {
freg = DREG(sreg);
nreg = freg + 1;
}
else
outmovr(sreg,DREG(freg),p);
}
}
break;
case LOFFSET:
case ROFFSET:
p = (c==LOFFSET) ? ltp->t_left : rtp->t_left;
if((p=coffset(p)) != 0 && (p->t_op != CINT || p->t_value != 0))
outaexpr(p,NOTIMMED);
break;
case MODSWAP:
switch( op ) {
case MOD:
case EQMOD:
case LMOD:
case LEQMOD:
OUTSWAP(freg);
}
break;
}
}
if( extf && cookie == FORREG && (ISDREG(freg)) ) {
if( UNSIGN(ltp->t_type) || UNSIGN(rtp->t_type) )
OUTUEXT(freg);
else
OUTEXT(freg);
}
#ifdef DEBUG
if(eflag) printf("ending expand skp=%lo\n",skp);
#endif
return(freg);
}
/* op_expand - printf out the subroutine being called */
op_expand(op,type,ltype)
int op, type,ltype;
{
if( ISFLOAT(type) || ISFLOAT(ltype) ) {
switch( op ) {
case ADD:
case EQADD:
case PREINC: /* [vlh] 4.2 */
case POSTINC: /* [vlh] 4.2 */
printf("_fpadd");
break;
case SUB:
case EQSUB:
case PREDEC: /* [vlh] 4.2 */
case POSTDEC: /* [vlh] 4.2 */
printf("_fpsub");
break;
case MULT:
case EQMULT:
printf("_fpmult");
break;
case DIV:
case EQDIV:
printf("_fpdiv");
break;
case UMINUS:
case EQNEG:
printf("_fpneg");
break;
case FLOAT2L:
case FLOAT2I:
printf("_fpftol");
break;
case LONG2F:
case INT2F:
printf("_fpltof");
break;
case EQUALS:
case NEQUALS:
case GREAT:
case GREATEQ:
case LESS:
case LESSEQ:
printf("_fpcmp");
break;
default:
error("invalid floating point op %d\n",op);
break;
}
}
else {
switch( op ) {
case MULT:
case LMULT:
printf("lmul");
break;
case DIV:
case LDIV:
printf("ldiv");
break;
case MOD:
case LMOD:
printf("lrem");
break;
default:
error("opcall bad op %d",op);
break;
}
}
}
/*
* match - try to match expression tree with code skeleton
* Given the expression tree, tries to match the given tree with
* the appropriate code skeleton. The code skeleton list is
* gotten from the root operator and the cookie value. The code
* skeleton list is then searched, checking the Sethy-Ullman numbers
* of the sub-trees against the Sethy-Ullman numbers in the code
* skeleton list. If the Sethy-Ullman numbers are OK, then the
* left and right sub-trees are checked for compatability, e.g.
* integer pointers, etc. If a match is found, the code skeleton
* list pointer is returned.
*/
char * /* returns ptr to code skeleton*/
match(tp,cookie,reg) /* or 0 if no skeleton*/
struct tnode *tp; /* pointer to tree*/
int cookie; /* goal for code expansion*/
int reg; /* register to use*/
{
register struct skeleton *skp;
register short op, bop;
short i;
register struct tnode *ltp, *rtp;
#ifdef DEBUG
if(mflag) printf("match op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
#endif
PUTEXPR(mflag,"match",tp);
if( (op=tp->t_op) >= LCGENOP )
return(0);
if( LEAFOP(op) )
ltp = tp;
else
ltp = tp->t_left;
if( (bop=BINOP(op)) && cookie!=FORSP) { /* [vlh] 4.2 !FORSP */
rtp = tp->t_right;
if( CONVOP(ltp->t_op) ) {
if( op != LSH && NOTCONVOP(rtp->t_op) ) {
if( !(UNSIGN(ltp->t_left->t_type)) || op == ASSIGN ) {
tp->t_left = ltp->t_left;
if( (skp=match(tp,cookie,reg)) != 0 )
return(skp);
tp->t_left = ltp;
}
}
}
else if( CONVOP(rtp->t_op) ) {
if( !(UNSIGN(rtp->t_left->t_type)) || op == ASSIGN ) {
tp->t_right = rtp->t_left;
if( (skp=match(tp,cookie,reg)) != 0 )
return(skp);
tp->t_right = rtp;
}
}
}
switch( cookie ) {
case FORCC:
i = 3;
break;
case FOREFF:
i = 2;
break;
case FORSTACK:
case FORSP:
i = 4;
break;
case FORREG:
i = 5;
break;
default:
error("match cookie=%d\n",cookie);
return(0);
}
#ifdef DEBUG
if(mflag) printf("match op=%d i=%d ",op,i);
#endif
if( !(i=optab[op][i]) )
return(0);
skp = codeskels[i];
#ifdef DEBUG
if(mflag) printf("codeskels[%d]=%o\n",i,skp);
#endif
#ifdef DEBUG
if(mflag) {
printf("match LEFT ");
puttsu(ltp);
if(bop) {
printf(" RIGHT ");
puttsu(rtp);
}
putchar('\n');
}
#endif
for( ; skp->sk_left != 0; skp++ ) {
#ifdef DEBUG
if( mflag > 1 )
printf("sk_left=%x sk_right=%x\n",skp->sk_left,skp->sk_right);
#endif
if( !(skelmatch(ltp,skp->sk_left)) )
continue;
if( bop && !(skelmatch(rtp,skp->sk_right)) )
continue;
#ifdef DEBUG
if( mflag )
printf("match found skp=%o left=%x right=%x\n",skp,
skp->sk_left,skp->sk_right);
#endif
return(skp);
}
return(0);
}
/* skelmatch - sub-tree type matching for match*/
/* This checks a subtree for type compatability in match.*/
skelmatch(tp,skinfo) /* returns 1 if matched, else 0*/
struct tnode *tp; /* pointer to expression tree*/
int skinfo;
{
register short type, unsignf, const, stype;
if( tp->t_su > skinfo || ((skinfo&T_INDR) && tp->t_op != INDR) )
return(0);
stype = SK_TYPE(skinfo);
type = tp->t_type;
if( ISFUNCTION(type) )
type = BTYPE(type);
if( unsignf = UNSIGN(type) )
type = BASETYPE(type);
const = 0;
switch( tp->t_op ) {
case CFLOAT: /* [vlh] 3.4 */
case CLONG:
if( tp->t_su > SU_CONST )
break;
case CINT:
const++;
break;
}
switch( stype ) {
case T_CHAR:
return( type == CHAR );
case T_ANY: /*either short or char*/
if( type == CHAR )
return(1);
case T_INT:
return( type == INT || const );
case T_UNSN:
case T_UANY: /* [vlh] 4.2 */
case T_UCHAR: /* [vlh] 4.2 */
case T_ULONG: /* [vlh] 4.2 */
return( unsignf );
case T_LONG:
return( LONGORPTR(type) );
case T_FLOAT:
return( ISFLOAT(type) );
default:
error("skelmatch type: %x",stype);
return(0);
}
}

View File

@@ -0,0 +1,110 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
#include "cskel.h"
/* sucomp - Sethy-Ullman expression complexity measure computation*/
/* This is a heuristic computation of the Sethy-Ullman numbers*/
/* for expressions. This gives an approximation of the complexity*/
/* of the expression. The code generation scheme works best if*/
/* the most complex expressions are done first.*/
sucomp(tp,nregs,flag) /* returns - none*/
struct tnode *tp; /* pointer to tree*/
int nregs; /* number of registers left*/
int flag; /* 1=>set values in tree, 0=>return*/
{
register short su, sur, op, i;
register struct tnode *ltp, *rtp;
nregs = DREG(nregs);
if( BINOP(op=tp->t_op) ) {
ltp = tp->t_left;
rtp = tp->t_right;
}
else if( UNARYOP(op) )
ltp = tp->t_left;
switch( op ) {
case CLONG:
if( tp->t_lvalue >= 0x8000L || tp->t_lvalue <= 0xffff8000L ) {
su = SU_ADDR;
break;
}
i = tp->t_lvalue;
case CINT:
if( op == CINT )
i = tp->t_value;
if( i == 0 )
su = SU_ZERO;
else if( i == 1 )
su = SU_ONE;
else if( i >= 1 && i <= QUICKVAL )
su = SU_SMALL;
else if( i >= -128 && i <= 127 )
su = SU_QUICK;
else
su = SU_CONST;
break;
case COMMA:
su = MAX(sucomp(rtp,nregs,flag),sucomp(ltp,nregs,flag));
su = MAX(su,SU_EASY);
break;
case ADDR:
su = sucomp(ltp,nregs,flag);
break;
case CFLOAT:
case DCLONG:
case AUTOINC:
case AUTODEC:
su = SU_ADDR;
break;
case SYMBOL:
if( tp->t_sc != REGISTER )
su = SU_ADDR;
else if( ISDREG(tp->t_reg) )
su = SU_REG;
else
su = SU_AREG;
break;
case LDIV:
case LMOD:
case LMULT:
case CALL:
sucomp(rtp,nregs,flag);
case NACALL:
sucomp(ltp,nregs,flag);
su = SU_VHARD; /*very hard*/
break;
default:
su = sucomp(ltp,nregs,flag);
if( BINOP(op) ) {
if( su <= SU_ADDR )
su = MAX(su,sucomp(rtp,nregs,flag));
else {
sur = sucomp(rtp,nregs+1,flag);
if( sur > SU_ADDR && nregs > HICREG )
su = MAX(su,SU_HARD);
}
su = MAX(SU_EASY,su);
}
else if( su <= SU_XREG )
su = MAX(SU_EASY,su);
if( ISFLOAT(tp->t_type) )
su = SU_VHARD;
break;
}
if( flag )
tp->t_su = su;
return(su);
}

View File

@@ -0,0 +1,118 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
#define ASGOP OPRAS|OPASSIGN|OPLVAL|OPBIN
/*info on operators:*/
/*000077-- OPPRI - priority*/
/*000100-- OPBIN - binary operator*/
/*000200-- OPLVAL - left operand must be lvalue*/
/*000400-- OPREL - relational operator*/
/*001000-- OPASSIGN - assignment operator*/
/*002000-- OPLWORD - short required on left*/
/*004000-- OPRWORD - short required on right*/
/*010000-- OPCOM commutative*/
/*020000-- OPRAS - right associative*/
/*040000-- OPTERM - termination node*/
/*100000 - OPCONVS - conversion operator*/
short opinfo[] = {
TRMPRI, /*EOF*/
ADDPRI|OPCOM|OPBIN, /*ADD - expr + expr*/
ADDPRI|OPBIN, /*SUB - expr - expr*/
MULPRI|OPCOM|OPBIN, /*MULT - expr * expr*/
MULPRI|OPBIN, /*DIV - expr / expr*/
MULPRI|OPBIN, /*MOD - expr % expr*/
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*RSH - expr >> expr*/
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*LSH - expr << expr*/
ANDPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*AND - expr & expr*/
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*OR - expr | expr*/
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*XOR - expr ^ expr*/
UNOPRI|OPRAS|OPLWORD, /*NOT - ! expr*/
UNOPRI|OPRAS, /*UMINUS - - expr*/
UNOPRI|OPRAS|OPLWORD, /*COMPL - ~ expr*/
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREDEC - --lvalue*/
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREINC - ++lvalue*/
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTDEC - lvalue--*/
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTINC - lvalue++*/
ASGPRI|ASGOP, /*ASSIGN - lvalue = expr*/
ASGPRI|ASGOP, /*EQADD - lvalue += expr*/
ASGPRI|ASGOP, /*EQSUB - lvalue -= expr*/
ASGPRI|ASGOP, /*EQMULT - lvalue *= expr*/
ASGPRI|ASGOP, /*EQDIV - lvalue /= expr*/
ASGPRI|ASGOP, /*EQMOD - lvalue %= expr*/
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQRSH - lvalue >>= expr*/
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQLSH - lvalue <<= expr*/
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQAND - lvalue &= expr*/
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQOR - lvalue |= expr*/
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQXOR - lvalue ^= expr*/
TRMPRI, /*FJSR - generate function jsr*/
EQLPRI|OPREL|OPBIN, /*EQUALS - expr == expr*/
EQLPRI|OPREL|OPBIN, /*NEQUALS - expr != expr*/
RELPRI|OPREL|OPBIN, /*GREAT - expr > expr*/
RELPRI|OPREL|OPBIN, /*GREATEQ - expr >= expr*/
RELPRI|OPREL|OPBIN, /*LESS - expr < expr*/
RELPRI|OPREL|OPBIN, /*LESSEQ - expr <= expr*/
TRMPRI|OPCONVS, /*INT2L*/
TRMPRI|OPCONVS, /*LONG2I*/
TRMPRI|OPBIN, /*BTST*/
TRMPRI, /*LOAD*/
TRMPRI|OPBIN, /*LMULT*/
TRMPRI|OPBIN, /*LDIV*/
TRMPRI|OPBIN, /*LMOD*/
TRMPRI|OPBIN, /*LEQMULT*/
TRMPRI|OPBIN, /*LEQDIV*/
TRMPRI|OPBIN, /*LEQMOD*/
TRMPRI|ASGOP, /*EQADDR*/
TRMPRI, /*EQNOT*/
TRMPRI, /*EQNEG*/
TRMPRI|OPBIN, /*DOCAST*/
ASGPRI|ASGOP, /*STASSIGN [vlh]*/
TRMPRI|OPCONVS, /*LONG2F [vlh] 3.4*/
TRMPRI|OPCONVS, /*FLOAT2L [vlh] 3.4*/
TRMPRI|OPCONVS, /*INT2F [vlh] 3.4*/
TRMPRI|OPCONVS, /*FLOAT2I [vlh] 3.4*/
UNOPRI|OPRAS, /*TOCHAR [vlh] 4.0*/
TRMPRI, /*unused - 56*/
TRMPRI, /*unused - 57*/
TRMPRI, /*unused - 58*/
TRMPRI, /*unused - 59*/
UNOPRI|OPRAS|OPLVAL, /*ADDR - & expr*/
UNOPRI|OPRAS|OPLWORD, /*INDR - * expr*/
LNDPRI|OPBIN, /*LAND - expr && expr*/
LORPRI|OPBIN, /*LOR - expr || expr*/
QMKPRI|OPRAS|OPBIN, /*QMARK - expr ? expr : expr*/
QMKPRI|OPRAS|OPBIN, /*COLON*/
COMPRI|OPBIN, /*COMMA*/
TRMPRI|OPTERM, /*CINT*/
TRMPRI|OPTERM, /*CLONG*/
TRMPRI|OPTERM, /*SYMBOL*/
TRMPRI|OPTERM, /*AUTOINC*/
TRMPRI|OPTERM, /*AUTODEC*/
LPNPRI|OPBIN, /*CALL - call with arguments*/
LPNPRI, /*NACALL - no argument call*/
TRMPRI, /*BFIELD - field selection*/
TRMPRI, /*CONDBR*/
TRMPRI, /*INIT*/
TRMPRI, /*LOADREG*/
TRMPRI|OPTERM, /*DCLONG - divide const long*/
TRMPRI|OPTERM, /*CFLOAT [vlh] 3.4*/
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*CAST*/
TRMPRI, /*SEMI*/
TRMPRI, /*LCURBR - {*/
TRMPRI, /*RCURBR - }*/
LPNPRI, /*LBRACK - [*/
RPNPRI, /*RBRACK - ]*/
LPNPRI, /*LPAREN - )*/
RPNPRI, /*RPAREN - )*/
TRMPRI|OPTERM, /*STRING*/
TRMPRI, /*RESWORD*/
LPNPRI|OPBIN, /*APTR - expr -> symbol*/
LPNPRI|OPBIN, /*PERIOD - expr . symbol*/
UNOPRI|OPRAS, /*SIZEOF - sizeof expr*/
LPNPRI|OPBIN, /*MPARENS - matching parens ()*/
};

View File

@@ -0,0 +1,389 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
#include "cgen.h"
#include "cskel.h"
char null[];
char *opname[];
/* xnalloc - allocate address-indexed node*/
char *xnalloc(type,ar,off,xr,xt) /* returns ptr to node alloced*/
int type; /* data type*/
int ar; /* address register*/
int off; /* 8-bit offset*/
int xr; /* index register*/
int xt; /* index register type*/
{
register struct indexnode *xp;
xp = talloc(sizeof(*xp));
xp->t_op = SYMBOL;
xp->t_type = type;
xp->t_sc = INDEXED;
xp->t_reg = ar;
xp->t_su = SU_ADDR;
xp->t_offset = off;
xp->t_xreg = xr;
xp->t_xtype = xt;
return(xp);
}
/* tcopy - expression tree copy*/
char *tcopy(tp,autof) /* returns ptr to copied tree*/
struct tnode *tp;
int autof; /* can do AUTOINC and AUTODEC? */
{
register char *p;
register short op;
op = tp->t_op;
switch( op ) {
case SYMBOL:
if( tp->t_sc == EXTERNAL || tp->t_sc == EXTOFF )
p = cenalloc(tp->t_type,tp->t_sc,tp->t_symbol);
else {
p = snalloc(tp->t_type,tp->t_sc,tp->t_offset,0,0);
p->t_label = tp->t_label;
}
p->t_offset = tp->t_offset;
p->t_reg = tp->t_reg;
return(p);
case CINT:
return(cnalloc(tp->t_type,tp->t_value));
case CLONG:
return(lcnalloc(tp->t_type,tp->t_lvalue));
case CFLOAT: /*[vlh] 3.4 */
return(fpcnalloc(tp->t_type,tp->t_lvalue));
case DCLONG:
p = lcnalloc(tp->t_type,tp->t_lvalue);
p->t_op = DCLONG;
return(p);
case AUTOINC: /*[mac] 4.2*/
case AUTODEC:
p = snalloc(tp->t_type,AUTO,0,0,0);
if( autof == DOAUTO )
p->t_op = op;
p->t_reg = tp->t_reg;
return(p);
default:
p = tnalloc(op,tp->t_type,0,0,null,null);
if( ISASGOP(op) || op == PREINC || op == PREDEC ) /* [mac] 4.2 */
p->t_right = tcopy(tp->t_right,DOAUTO);
else if( BINOP(op) )
p->t_right = tcopy(tp->t_right,autof);
p->t_left = tcopy(tp->t_left,autof);
return(p);
}
}
/* outaexpr - output address expression*/
outaexpr(tp,flags) /* returns - none*/
struct tnode *tp; /* pointer to tree*/
int flags; /* flags (IMMED,LOFFSET,...)*/
{
register short off, reg, lab;
long l;
if( tp->t_op == ADDR ) {
tp = tp->t_left;
putchar('#');
}
off = tp->t_offset;
reg = tp->t_reg;
lab = tp->t_label;
switch( tp->t_op ) {
case AUTOINC:
printf("(R%d)+",reg);
break;
case AUTODEC:
printf("-(R%d)",reg);
break;
case CINT:
if( flags & IMMED )
putchar('#');
printf("%d",tp->t_value);
break;
case DCLONG:
case CLONG:
case CFLOAT: /*[vlh] 3.4 */
if( flags & IMMED )
putchar('#');
outlval(tp->t_lvalue);
break;
case SYMBOL:
if( off ) {
switch( tp->t_sc ) {
default:
printf("%d+",off);
break;
case REGOFF:
printf("%d",off);
case CINDR:
case CLINDR:
case CFINDR: /* [vlh] 3.4 */
case INDEXED:
break;
case REGISTER:
error("invalid register expression");
break;
}
}
switch( tp->t_sc ) {
case REGISTER:
printf("R%d",reg);
break;
case REGOFF:
printf("(R%d)",reg);
break;
case EXTERNAL:
printf("_%.8s",tp->t_symbol);
break;
case EXTOFF:
printf("_%.8s(R%d)",tp->t_symbol,reg);
break;
case STATIC:
printf("L%d",lab);
break;
case STATOFF:
printf("L%d(R%d)",lab,reg);
break;
case INDEXED:
printf("%d(R%d,R%d",off,reg,tp->t_xreg);
outatype(tp->t_xtype);
putchar(')');
break;
case CINDR:
printf("%d",off);
break;
/*
* the following will work on: PDP-11, 68000, IBM-360, VAX, etc.
* it will not work on word machines or on machines where either
* longs two ints or two shorts.
*/
case CLINDR:
case CFINDR: /* [vlh] 3.4 */
l.hiword = tp->t_offset;
l.loword = tp->t_ssp;
outlval(l);
break;
default:
error("invalid storage class %d\n",tp->t_sc);
break;
}
break;
default:
error("invalid operator %s\n",opname[tp->t_op]);
break;
}
}
/* outlval - output long value*/
/* This is a big pain because the PDP-11 doesn't do long divides*/
/* in hardware.*/
outlval(lval)
long lval;
{
char digs[8];
register short i, c;
i = 0;
do {
digs[i++] = lval & 0xf;
lval >>= 4;
lval &= 0xfffffff;
} while ( lval );
putchar('$');
while( --i >= 0 ) {
c = digs[i];
putchar(c>=10?c+('a'-10):c+'0');
}
}
/* outtype - output 68000 type (null, .b, .l) depending on data type*/
outtype(type)
int type;
{
if( ISFLOAT(type) || LONGORPTR(type) )
printf(".l");
else if( type == CHAR )
printf(".b");
}
/* outatype - output address type (.l or null) depending on data type*/
outatype(type)
int type;
{
if( LONGORPTR(type) || ISFLOAT(type) )
printf(".l");
}
/* outextend - output register extension to long depending on type*/
outextend(tp,type,reg) /* returns - none*/
struct tnode *tp; /* tree to convert from*/
int type; /* type to convert to*/
int reg; /* register to convert*/
{
if( (ISDREG(reg)) && !(LONGORPTR(tp->t_type)) && (LONGORPTR(type)) ) {
if( UNSIGN(tp->t_type) )
OUTUEXT(reg);
else
OUTEXT(reg);
}
}
/* outrr - output register to register instruction*/
outrr(ins,r1,r2,tp)
char *ins;
int r1;
int r2;
struct tnode *tp;
{
printf("%s",ins);
if( ISAREG(r1) || ISAREG(r2) )
outatype(tp->t_type);
else
outtype(tp->t_type);
printf(" R%d,R%d\n",r1,r2);
}
/* outmovr - output "move[type] R1,R2" instruction*/
outmovr(r1,r2,tp)
int r1;
int r2;
struct tnode *tp;
{
if( r1 != r2 )
outrr("move",r1,r2,tp);
}
/* outcmpm - output "cmpm[type] (R1)+,(R2)+"*/
outcmpm(tp)
struct tnode *tp;
{
register int lreg, rreg;
if (!m68010) { /* 68000 version cmpm ok !!! */
printf("cmpm");
outtype(tp->t_left->t_type);
printf(" (R%d)+,(R%d)+\n",tp->t_left->t_reg,tp->t_right->t_reg);
}
else /* generating code for 68010, micro code is bad for cmpm */
fakecmpm(tp->t_left->t_type,tp->t_left->t_reg,tp->t_right->t_reg);
}
/* fakecmpm - output 68010 fake cmpm for bad microcode [vlh] 4.2 */
fakecmpm(type,lreg,rreg)
int type,lreg,rreg;
{
printf("cmp");
outtype(type);
printf(" (R%d),(R%d)\n",lreg,rreg);
if( ISFLOAT(type) || LONGORPTR(type) )
printf("addq #4,R%d\naddq #4,R%d\n",lreg,rreg);
else if( type == CHAR )
printf("addq #1,R%d\naddq #1,R%d\n",lreg,rreg);
else
printf("addq #2,R%d\naddq #2,R%d\n",lreg,rreg);
}
/* outcreg - output reference to compiler temp register*/
outcreg(reg)
int reg;
{
if( (DREG(reg)) > HICREG )
error("expression too complex");
printf("R%d",reg);
}
/* outcmp0 - output a compare with 0, special for address register*/
outcmp0(reg,tp)
int reg;
struct tnode *tp;
{
if( ISAREG(reg) ) {
printf("cmp");
outatype(tp->t_type);
printf(" #0,R%d\n",reg);
}
else {
printf("tst");
outtype(tp->t_type);
printf(" R%d\n",reg);
}
}
/* outrpush - output "move[type] R1,[-](sp)"*/
outrpush(reg,tp,pflag)
int reg;
struct tnode *tp;
int pflag;
{
printf("move");
outatype(tp->t_type);
printf(" R%d,%c(sp)\n",reg,pflag?'-':'\0');
}
outdbra(reg,lab)
int reg;
int lab;
{
printf("dbra R%d,L%d\n",reg,lab);
}
/* cenalloc - code generator external node allocation*/
/* This may be coalesced into enalloc in parser.*/
char *cenalloc(type,sc,sym) /* returns ptr to node alloced*/
int type; /* type of symbol*/
int sc; /* storage class*/
char *sym; /* symbol name*/
{
register struct extnode *ep;
ep = talloc(sizeof(*ep));
ep->t_op = SYMBOL;
ep->t_type = type;
ep->t_sc = sc;
ep->t_su = 0;
ep->t_offset = 0;
symcopy(sym,ep->t_symbol);
return(ep);
}
/*popstack - clear off the stack after a call if necessary */
popstack(nb)
{
if (nb > 0 && nb <= 8)
printf("addq.l #%d,sp\n",nb);
else if (nb > 0)
printf("adda.l #%d,sp\n",nb);
}

View File

@@ -0,0 +1 @@
char *compiled = "@(#) Code Generator - Tue Sep 6 14:30 1983";