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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)cgen.h 1.7 12/28/83
*/
#include "machine.h"
#ifdef WHITESM
# include <stdio.h>
# include <klib.h>
# undef putchar
# define putchar xputchar
# undef ferror
# define ferror xferror
# define printf xprintf
# define VAX11
#endif
#ifdef CPM
# include <stdio.h>
# include <klib.h>
# undef putchar
# define putchar xputchar
# undef ferror
# define ferror xferror
# define printf xprintf
#endif
#ifndef DECC
# include "icode.h"
#else
/* ICODE equivilent to icode.h, vprintf printf for vax/vms */
# include "ICODE"
# define printf vprintf
# define VAX11
#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 NOTLOFFSET 0
/*tcopy + outaexpr flags - generate prefix operators, postfix operators*/
#define A_DOPRE 1
#define A_DOPOST 2
#define A_DOIMMED 4
#define A_NOIMMED 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*/
long 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*/
long 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;
long t_offset; /* [vlh] 4.3, was a short !!! */
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,250 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)cgen.h 1.7 12/28/83
*/
#include "machine.h"
#ifdef WHITESM
# include <stdio.h>
# include <klib.h>
# undef putchar
# define putchar xputchar
# undef ferror
# define ferror xferror
# define printf xprintf
#endif
#ifdef CPM
# include <stdio.h>
# include <klib.h>
# undef putchar
# define putchar xputchar
# undef ferror
# define ferror xferror
# define printf xprintf
#endif
#ifndef DECC
# include "icode.h"
#else
/* ICODE equivilent to icode.h, vprintf printf for vax/vms */
# include "ICODE"
# define printf vprintf
# define VAX11
#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 NOTLOFFSET 0
/*tcopy + outaexpr flags - generate prefix operators, postfix operators*/
#define A_DOPRE 1
#define A_DOPOST 2
#define A_DOIMMED 4
#define A_NOIMMED 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*/
long 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*/
long 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;
long t_offset; /* [vlh] 4.3, was a short !!! */
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,846 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)codegen.c 1.13 12/30/83
*/
#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,A_DOPRE);/* [mac] 4.2 c[i=+1]++ & c[*p++]++ */
*(*clp)++ = tcopy(tp,A_DOPOST);
return( stp );
}
if( BINOP(op) )
tp->t_right = addptree(tp->t_right,clp);
tp->t_left = addptree(tp->t_left,clp);
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("move.l #");
outaexpr(ltp,A_NOIMMED);
printf(",-(sp)\ntst.l (sp)+\n");
return(reg);
}
break;
case ASSIGN: /* 4.3 [mac] */
if ((BASETYPE(tp->t_left->t_type) == CHAR) && cookie == FORREG &&
ISAREG(reg))
reg = DREG(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);
}
if (cookie == FORREG && ISAREG(reg)) { /* 4.3 [mac] */
reg = DREG(reg);
codegen(tp,cookie,reg);
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 {
if(tp->t_type != STRUCT) /* [vlh] 4.3 */
error("no code table for %s",opname[tp->t_op]);
else
error("illegal structure operation");
}
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,(long)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,(long)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*/
{
register char *p;
register short op, lab1, lab2;
short islong;
#ifdef DEBUG
if (cflag)
printf("hardrel: cookie=%d op=%d reg=%d\n",cookie,tp->t_op,reg);
#endif
op = tp->t_op;
if (RELOP(op) && tp->t_left->t_type == CHAR &&
(p=constant(tp->t_right,&islong))) {
if (islong)
tp->t_left = tnalloc(LOAD,LONG,SU_EASY,0,tp->t_left,null);
else if (p->t_value > 255 || p->t_value < -128)
tp->t_left = tnalloc(LOAD,INT,SU_EASY,0,tp->t_left,null);
} /* [vlh] 4.3, if char compared to large constant.... */
if (cookie != FORCC && (RELOP(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(outdbra(dir,op,ltp,rtp,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 DIV:
case MOD:
if( rtp->t_left->t_type==LONG && ltp->t_type==INT )
return(change); /* [vlh]4.3, ri = rl / 10 */
case MULT:
if( (rtp->t_left->t_type==INT || rtp->t_left->t_op==INT2L)
&& (rtp->t_right->t_type==INT || rtp->t_right->t_op==INT2L)
&& ltp->t_type==LONG)
return(change); /* [vlh]4.3, rl = i * i */
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,845 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)codegen.c 1.13 12/30/83
*/
#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,A_DOPRE);/* [mac] 4.2 c[i=+1]++ & c[*p++]++ */
*(*clp)++ = tcopy(tp,A_DOPOST);
return( stp );
}
if( BINOP(op) )
tp->t_right = addptree(tp->t_right,clp);
tp->t_left = addptree(tp->t_left,clp);
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("move.l #");
outaexpr(ltp,A_NOIMMED);
printf(",-(sp)\ntst.l (sp)+\n");
return(reg);
}
break;
case ASSIGN: /* 4.3 [mac] */
if ((BASETYPE(tp->t_left->t_type) == CHAR) && cookie == FORREG &&
ISAREG(reg))
reg = DREG(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);
}
if (cookie == FORREG && ISAREG(reg)) { /* 4.3 [mac] */
reg = DREG(reg);
codegen(tp,cookie,reg);
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 {
if(tp->t_type != STRUCT) /* [vlh] 4.3 */
error("no code table for %s",opname[tp->t_op]);
else
error("illegal structure operation");
}
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,(long)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,(long)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*/
{
register char *p;
register short op, lab1, lab2;
short islong;
#ifdef DEBUG
if (cflag)
printf("hardrel: cookie=%d op=%d reg=%d\n",cookie,tp->t_op,reg);
#endif
op = tp->t_op;
if (RELOP(op) && tp->t_left->t_type == CHAR &&
(p=constant(tp->t_right,&islong))) {
if (islong)
tp->t_left = tnalloc(LOAD,LONG,SU_EASY,0,tp->t_left,null);
else if (p->t_value > 255 || p->t_value < -128)
tp->t_left = tnalloc(LOAD,INT,SU_EASY,0,tp->t_left,null);
} /* [vlh] 4.3, if char compared to large constant.... */
if (cookie != FORCC && (RELOP(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(outdbra(dir,op,ltp,rtp,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 DIV:
case MOD:
if( rtp->t_left->t_type==LONG && ltp->t_type==INT )
return(change); /* [vlh]4.3, ri = rl / 10 */
case MULT:
if( (rtp->t_left->t_type==INT || rtp->t_left->t_op==INT2L)
&& (rtp->t_right->t_type==INT || rtp->t_right->t_op==INT2L)
&& ltp->t_type==LONG)
return(change); /* [vlh]4.3, rl = i * i */
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;
};

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
$ diff/out=CANON CANON.C [-.orgc168]CANON.C
$ diff/out=CODEGEN CODEGEN.C [-.orgc168]CODEGEN.C
$ diff/out=CSKELS CSKELS.C [-.orgc168]CSKELS.C
$ diff/out=INTERF INTERF.C [-.orgc168]INTERF.C
$ diff/out=MAIN MAIN.C [-.orgc168]MAIN.C
$ diff/out=OPTAB OPTAB.C [-.orgc168]OPTAB.C
$ diff/out=PUTEXPR PUTEXPR.C [-.orgc168]PUTEXPR.C
$ diff/out=SMATCH SMATCH.C [-.orgc168]SMATCH.C
$ diff/out=SUCOMP SUCOMP.C [-.orgc168]SUCOMP.C
$ diff/out=TABL TABL.C [-.orgc168]TABL.C
$ diff/out=UTIL UTIL.C [-.orgc168]UTIL.C
$ diff/out=VERSION VERSION.C [-.orgc168]VERSION.C
$ diff/out=CGEN CGEN.H [-.orgc168]CGEN.H
$ diff/out=CSKEL CSKEL.H [-.orgc168]CSKEL.H
$ diff/out=ICODE ICODE.H [-.orgc168]ICODE.H

View File

@@ -0,0 +1,245 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/*
* intermediate code operators
* 0=>EOF, special operator
*/
#define EOF 0
/*1-59=>operators that generate code (entries in code gen optab)*/
#define ADD 1
#define SUB 2
#define MULT 3
#define DIV 4
#define MOD 5
#define RSH 6
#define LSH 7
#define AND 8
#define OR 9
#define XOR 10
#define NOT 11
#define UMINUS 12
#define COMPL 13
#define PREDEC 14
#define PREINC 15
#define POSTDEC 16
#define POSTINC 17
#define ASSIGN 18
#define EQADD 19
#define EQSUB 20
#define EQMULT 21
#define EQDIV 22
#define EQMOD 23
#define EQRSH 24
#define EQLSH 25
#define EQAND 26
#define EQOR 27
#define EQXOR 28
#define FJSR 29
#define EQUALS 30
#define NEQUALS 31
#define GREAT 32
#define GREATEQ 33
#define LESS 34
#define LESSEQ 35
#define INT2L 36
#define LONG2I 37
/*machine dependent operators that generate code*/
#define BTST 38
#define LOAD 39
#define LMULT 40
#define LDIV 41
#define LMOD 42
#define LEQMULT 43
#define LEQDIV 44
#define LEQMOD 45
#define EQADDR 46
#define EQNOT 47
#define EQNEG 48
#define DOCAST 49
#define STASSIGN 50 /*[vlh]*/
#define LONG2F 51 /*[vlh] 3.4*/
#define FLOAT2L 52 /*[vlh] 3.4*/
#define INT2F 53 /*[vlh] 3.4*/
#define FLOAT2I 54 /*[vlh] 3.4*/
#define TOCHAR 55 /*[vlh] 4.1*/
#define LCGENOP 56 /*change if adding more operators...*/
/*intermediate code operators that do not generate code*/
#define ADDR 60
#define INDR 61
#define LAND 62
#define LOR 63
#define QMARK 64
#define COLON 65
#define COMMA 66
#define CINT 67
#define CLONG 68
#define SYMBOL 69
#define AUTOINC 70
#define AUTODEC 71
#define CALL 72
#define NACALL 73
#define BFIELD 74
#define IFGOTO 75
#define INIT 76
#define CFORREG 77
#define DCLONG 78
#define CFLOAT 79 /*[vlh] 3.4*/
/*operators local to parser*/
#define CAST 80
#define SEMI 81
#define LCURBR 82
#define RCURBR 83
#define LBRACK 84
#define RBRACK 85
#define LPAREN 86
#define RPAREN 87
#define STRING 88
#define RESWORD 89
#define APTR 90
#define PERIOD 91
#define SIZEOF 92
#define MPARENS 93
#define FRETURN 94
#define ASM 95 /* [vlh] 4.2 */
#define STACKEND 100
/*data types*/
#define TYPELESS 0
#define CHAR 01
#define SHORT 02
#define INT 03
#define LONG 04
#define UCHAR 05
#define USHORT 06
#define UNSIGNED 07
#define ULONG 010
#define FLOAT 011
#define DOUBLE 012
/*data types local to parser*/
#define STRUCT 013
#define FRSTRUCT 014
#define LLABEL 015
/*type flags and definitions*/
#define TYPE 017
#define SUPTYP 060
#define ALLTYPE 077
#define POINTER 020
#define FUNCTION 040
#define ARRAY 060
#define SUTYPLEN 2
/*data registers*/
#define DREG0 0
#define DREG2 2
#define DREG3 3
#define DREG4 4
#define DREG5 5
#define DREG6 6
#define DREG7 7
#define AREG3 11
#define AREG4 12
#define AREG5 13
/*storage classes*/
#define AUTO 1
#define REGISTER 2
#define EXTERNAL 3
#define STATIC 4
#define REGOFF 5
#define EXTOFF 6
#define STATOFF 7
#define INDEXED 8
/*exclusively code generator storage classes*/
#define CINDR 9
#define CLINDR 10
#define CFINDR 11 /* [vlh] 3.4 */
/*exclusively parser storage classes*/
#define STRPROTO 9
#define PDECLIST 10
#define PARMLIST 11
#define BFIELDCL 12
#define UNELCL 13
#define STELCL 14
#define PDECREG 15 /* [vlh] 4.3, PDECLIST register variable */
#define DEXTERN 16 /* [vlh] 4.3, explicitly defined extern */
/*opinfo table bits*/
#define OPPRI 077
#define OPBIN 0100
#define OPLVAL 0200
#define OPREL 0400
#define OPASSIGN 01000
#define OPLWORD 02000
#define OPRWORD 04000
#define OPCOM 010000
#define OPRAS 020000
#define OPTERM 040000
#define OPCONVS 0100000
/*68000 definitions*/
#define PTRSIZE 4
#define LONGSIZE 4
#define INTSIZE 2
#define CHARSIZE 1
#define SSIZE 8 /* chars per symbol */
#define TRUE 1
#define FALSE 0
#define TABC '\t' /* tab character */
#define EOLC '\n' /* end of line character */
#define BITSPBYTE 8
/*operator class priorities*/
#define TRMPRI 0 /* terminal nodes */
#define RPNPRI 1 /* ) and ] */
#define CALPRI 2 /* in-stack call, ( or [ */
#define COLPRI 3 /* init or case priority for : or , */
#define STKPRI 4 /* priority of end of stack */
#define COMPRI 5 /* normal priority for , */
#define ASGPRI 6 /* =, +=, -=, *=, /=, %=, ... */
#define QMKPRI 7 /* ?: */
#define LORPRI 8 /* || */
#define LNDPRI 9 /* && */
#define ORPRI 10 /* |, ^ */
#define ANDPRI 11 /* & */
#define EQLPRI 12 /* ==, != */
#define RELPRI 13 /* >, <, >=, <= */
#define SHFPRI 14 /* <<, >> */
#define ADDPRI 15 /* +, - */
#define MULPRI 16 /* *, /, % */
#define UNOPRI 17 /* !, ++, --, &, *, -, ~, sizeof */
#define LPNPRI 18 /* ., ->, [, (, function call */
#define PSTPRI 19 /* in-stack post--, post++ */
#ifndef VAX11
struct { short hiword; short loword; };
#else
# ifndef VMS
# define UNIX 1
# endif
struct { short loword; short hiword; };
#endif
#ifdef PDP11
# define UNIX 1
#endif
#define EXPSIZE 4096 /* EXPSIZE enlarged [vlh] 4.1 */
char exprarea[EXPSIZE]; /* made char [vlh] 4.2 */
/* v6io buffer declaration */
#define BLEN 512

View File

@@ -0,0 +1,245 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
*/
/*
* intermediate code operators
* 0=>EOF, special operator
*/
#define EOF 0
/*1-59=>operators that generate code (entries in code gen optab)*/
#define ADD 1
#define SUB 2
#define MULT 3
#define DIV 4
#define MOD 5
#define RSH 6
#define LSH 7
#define AND 8
#define OR 9
#define XOR 10
#define NOT 11
#define UMINUS 12
#define COMPL 13
#define PREDEC 14
#define PREINC 15
#define POSTDEC 16
#define POSTINC 17
#define ASSIGN 18
#define EQADD 19
#define EQSUB 20
#define EQMULT 21
#define EQDIV 22
#define EQMOD 23
#define EQRSH 24
#define EQLSH 25
#define EQAND 26
#define EQOR 27
#define EQXOR 28
#define FJSR 29
#define EQUALS 30
#define NEQUALS 31
#define GREAT 32
#define GREATEQ 33
#define LESS 34
#define LESSEQ 35
#define INT2L 36
#define LONG2I 37
/*machine dependent operators that generate code*/
#define BTST 38
#define LOAD 39
#define LMULT 40
#define LDIV 41
#define LMOD 42
#define LEQMULT 43
#define LEQDIV 44
#define LEQMOD 45
#define EQADDR 46
#define EQNOT 47
#define EQNEG 48
#define DOCAST 49
#define STASSIGN 50 /*[vlh]*/
#define LONG2F 51 /*[vlh] 3.4*/
#define FLOAT2L 52 /*[vlh] 3.4*/
#define INT2F 53 /*[vlh] 3.4*/
#define FLOAT2I 54 /*[vlh] 3.4*/
#define TOCHAR 55 /*[vlh] 4.1*/
#define LCGENOP 56 /*change if adding more operators...*/
/*intermediate code operators that do not generate code*/
#define ADDR 60
#define INDR 61
#define LAND 62
#define LOR 63
#define QMARK 64
#define COLON 65
#define COMMA 66
#define CINT 67
#define CLONG 68
#define SYMBOL 69
#define AUTOINC 70
#define AUTODEC 71
#define CALL 72
#define NACALL 73
#define BFIELD 74
#define IFGOTO 75
#define INIT 76
#define CFORREG 77
#define DCLONG 78
#define CFLOAT 79 /*[vlh] 3.4*/
/*operators local to parser*/
#define CAST 80
#define SEMI 81
#define LCURBR 82
#define RCURBR 83
#define LBRACK 84
#define RBRACK 85
#define LPAREN 86
#define RPAREN 87
#define STRING 88
#define RESWORD 89
#define APTR 90
#define PERIOD 91
#define SIZEOF 92
#define MPARENS 93
#define FRETURN 94
#define ASM 95 /* [vlh] 4.2 */
#define STACKEND 100
/*data types*/
#define TYPELESS 0
#define CHAR 01
#define SHORT 02
#define INT 03
#define LONG 04
#define UCHAR 05
#define USHORT 06
#define UNSIGNED 07
#define ULONG 010
#define FLOAT 011
#define DOUBLE 012
/*data types local to parser*/
#define STRUCT 013
#define FRSTRUCT 014
#define LLABEL 015
/*type flags and definitions*/
#define TYPE 017
#define SUPTYP 060
#define ALLTYPE 077
#define POINTER 020
#define FUNCTION 040
#define ARRAY 060
#define SUTYPLEN 2
/*data registers*/
#define DREG0 0
#define DREG2 2
#define DREG3 3
#define DREG4 4
#define DREG5 5
#define DREG6 6
#define DREG7 7
#define AREG3 11
#define AREG4 12
#define AREG5 13
/*storage classes*/
#define AUTO 1
#define REGISTER 2
#define EXTERNAL 3
#define STATIC 4
#define REGOFF 5
#define EXTOFF 6
#define STATOFF 7
#define INDEXED 8
/*exclusively code generator storage classes*/
#define CINDR 9
#define CLINDR 10
#define CFINDR 11 /* [vlh] 3.4 */
/*exclusively parser storage classes*/
#define STRPROTO 9
#define PDECLIST 10
#define PARMLIST 11
#define BFIELDCL 12
#define UNELCL 13
#define STELCL 14
#define PDECREG 15 /* [vlh] 4.3, PDECLIST register variable */
#define DEXTERN 16 /* [vlh] 4.3, explicitly defined extern */
/*opinfo table bits*/
#define OPPRI 077
#define OPBIN 0100
#define OPLVAL 0200
#define OPREL 0400
#define OPASSIGN 01000
#define OPLWORD 02000
#define OPRWORD 04000
#define OPCOM 010000
#define OPRAS 020000
#define OPTERM 040000
#define OPCONVS 0100000
/*68000 definitions*/
#define PTRSIZE 4
#define LONGSIZE 4
#define INTSIZE 2
#define CHARSIZE 1
#define SSIZE 8 /* chars per symbol */
#define TRUE 1
#define FALSE 0
#define TABC '\t' /* tab character */
#define EOLC '\n' /* end of line character */
#define BITSPBYTE 8
/*operator class priorities*/
#define TRMPRI 0 /* terminal nodes */
#define RPNPRI 1 /* ) and ] */
#define CALPRI 2 /* in-stack call, ( or [ */
#define COLPRI 3 /* init or case priority for : or , */
#define STKPRI 4 /* priority of end of stack */
#define COMPRI 5 /* normal priority for , */
#define ASGPRI 6 /* =, +=, -=, *=, /=, %=, ... */
#define QMKPRI 7 /* ?: */
#define LORPRI 8 /* || */
#define LNDPRI 9 /* && */
#define ORPRI 10 /* |, ^ */
#define ANDPRI 11 /* & */
#define EQLPRI 12 /* ==, != */
#define RELPRI 13 /* >, <, >=, <= */
#define SHFPRI 14 /* <<, >> */
#define ADDPRI 15 /* +, - */
#define MULPRI 16 /* *, /, % */
#define UNOPRI 17 /* !, ++, --, &, *, -, ~, sizeof */
#define LPNPRI 18 /* ., ->, [, (, function call */
#define PSTPRI 19 /* in-stack post--, post++ */
#ifndef VAX11
struct { short hiword; short loword; };
#else
# ifndef VMS
# define UNIX 1
# endif
struct { short loword; short hiword; };
#endif
#ifdef PDP11
# define UNIX 1
#endif
#define EXPSIZE 4096 /* EXPSIZE enlarged [vlh] 4.1 */
char exprarea[EXPSIZE]; /* made char [vlh] 4.2 */
/* v6io buffer declaration */
#define BLEN 512

View File

@@ -0,0 +1,144 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)interf.c 1.5 12/14/83
*/
#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,A_NOIMMED); /* [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*/
long 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,144 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)interf.c 1.5 12/14/83
*/
#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,A_NOIMMED); /* [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*/
long 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,2 @@
$2lo68 -s -r -f $1 -o c168.rel -u_nofloat 0$1s.o *.o 0$2klib 0$2clib
era *.o

View File

@@ -0,0 +1 @@
lo68 -r -f $1 -o c168.rel -unofloat 0$1s.o *.o 0:klib 0:clib

View File

@@ -0,0 +1,45 @@
$ num
CANON.C
CANON.lis
$ num
CODEGEN.C
CODEGEN.lis
$ num
CSKELS.C
CSKELS.lis
$ num
INTERF.C
INTERF.lis
$ num
MAIN.C
MAIN.lis
$ num
OPTAB.C
OPTAB.lis
$ num
PUTEXPR.C
PUTEXPR.lis
$ num
SMATCH.C
SMATCH.lis
$ num
SUCOMP.C
SUCOMP.lis
$ num
TABL.C
TABL.lis
$ num
UTIL.C
UTIL.lis
$ num
VERSION.C
VERSION.lis
$ num
CGEN.H
CGEN.lst
$ num
CSKEL.H
CSKEL.lst
$ num
ICODE.H
ICODE.lst

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
#define MC68000 1 /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
#define CPM 1 /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
#define MC68000 1 /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
#define CPM 1 /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,737 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)main.c 1.7 12/28/83
*/
char *version = "@(#)main.c 1.7 12/28/83";
/**
* 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] = "";
#ifdef VERSADOS
int inerr;
#endif
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++;
#ifdef CPM
calledby = "c168";
#endif
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 'f':
fflag++;
continue;
case 'g': /* [vlh] 4.2 generate line labels for cdb */
gflag++;
continue;
case 'D':
case 'd': /*sw*/
dflag++;
continue;
#ifdef DEBUG
case 'c':
cflag++;
continue;
case 'e':
eflag++;
continue;
case 'm':
mflag++;
continue;
case 'o':
oflag++;
continue;
#endif
case 'L': /* [vlh] 4.2, OBSOLETE */
case 'l': /*sw*/
lflag++;
continue;
case 'T': /* [vlh] 4.2 generates code for the 68010 */
case 't': /*sw*/
m68010++;
continue;
case '\0':
break;
default:
#ifndef VERSADOS
usage(calledby);
#else
break;
#endif
}
break;
}
}
readicode();
xfflush(&obuf); /*sw Name conflict with klib*/
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,(long)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 'A': /*sw Hex in upper case as well...*/
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++;
#ifdef REGULUS
if( lineno != 0 )
printf((char *)STDERR,"\"%s\", ** %d: ",source,lineno);
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
cputc('\n',STDERR);
#endif
#ifdef VERSADOS
inerr = 1;
if( lineno != 0 )
printf("\"%s\", ** %d: ",source,lineno);
printf(s,x1,x2,x3,x4,x5,x6);
printf("\n");
inerr = 0;
#endif
#ifdef CPM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef WHITESM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef UNIX
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
}
/* warning - output a warning message*/
warning(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
#ifdef REGULUS
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);
#endif
#ifdef VERSADOS
inerr = 1;
if( lineno != 0 )
printf("\"%s\", ** %d: (warning) ",source,lineno);
else
printf("(warning) ");
printf(s,x1,x2,x3,x4,x5,x6);
printf("\n");
inerr = 0;
#endif
#ifdef CPM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef WHITESM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef UNIX
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
}
/* 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 - output usage message*/
usage(calledby,num)
char *calledby;
int num;
{
#ifdef DEBUG
ferror("usage: %s icode link asm [-DTacemov]",calledby);
#else
ferror("usage: %s icode link asm [-Tav]",calledby);
#endif
}
/* 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*/
{
#ifdef VERSADOS
if (inerr) {
versaputchar(c);
return;
}
#endif
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
xfflush(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 CPM
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
#ifdef WHITESM
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,736 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)main.c 1.7 12/28/83
*/
char *version = "@(#)main.c 1.7 12/28/83";
/**
* 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] = "";
#ifdef VERSADOS
int inerr;
#endif
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++;
#ifdef CPM
calledby = "c168";
#endif
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 'f':
fflag++;
continue;
case 'g': /* [vlh] 4.2 generate line labels for cdb */
gflag++;
continue;
case 'D':
case 'd': /*sw*/
dflag++;
continue;
#ifdef DEBUG
case 'c':
cflag++;
continue;
case 'e':
eflag++;
continue;
case 'm':
mflag++;
continue;
case 'o':
oflag++;
continue;
#endif
case 'L': /* [vlh] 4.2, OBSOLETE */
case 'l': /*sw*/
lflag++;
continue;
case 'T': /* [vlh] 4.2 generates code for the 68010 */
case 't': /*sw*/
m68010++;
continue;
case '\0':
break;
default:
#ifndef VERSADOS
usage(calledby);
#else
break;
#endif
}
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,(long)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 'A': /*sw Hex in upper case as well...*/
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++;
#ifdef REGULUS
if( lineno != 0 )
printf((char *)STDERR,"\"%s\", ** %d: ",source,lineno);
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
cputc('\n',STDERR);
#endif
#ifdef VERSADOS
inerr = 1;
if( lineno != 0 )
printf("\"%s\", ** %d: ",source,lineno);
printf(s,x1,x2,x3,x4,x5,x6);
printf("\n");
inerr = 0;
#endif
#ifdef CPM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef WHITESM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef UNIX
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: ",source,lineno);
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
}
/* warning - output a warning message*/
warning(s,x1,x2,x3,x4,x5,x6)
char *s;
int x1, x2, x3, x4, x5, x6;
{
#ifdef REGULUS
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);
#endif
#ifdef VERSADOS
inerr = 1;
if( lineno != 0 )
printf("\"%s\", ** %d: (warning) ",source,lineno);
else
printf("(warning) ");
printf(s,x1,x2,x3,x4,x5,x6);
printf("\n");
inerr = 0;
#endif
#ifdef CPM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef WHITESM
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
#ifdef UNIX
if( lineno != 0 )
fprintf(stderr,"\"%s\", ** %d: (warning) ",source,lineno);
else
fprintf(stderr,"(warning) ");
fprintf(stderr,s,x1,x2,x3,x4,x5,x6);
fprintf(stderr,"\n");
#endif
}
/* 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 - output usage message*/
usage(calledby,num)
char *calledby;
int num;
{
#ifdef DEBUG
ferror("usage: %s icode link asm [-DTacemov]",calledby);
#else
ferror("usage: %s icode link asm [-Tav]",calledby);
#endif
}
/* 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*/
{
#ifdef VERSADOS
if (inerr) {
versaputchar(c);
return;
}
#endif
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 CPM
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
#ifdef WHITESM
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,89 @@
pip machine.h=machine.68k
cp68 -i 0$1 canon.c $1canon.i
c068 $1canon.i $1canon.ic $1canon.st -f
era $1canon.i
era $1canon.st
c168 $1canon.ic canon.s -ld
era $1canon.ic
as68 -s 0$1 -f $1 -l -u canon.s
cp68 -i 0$1 codegen.c $1codegen.i
c068 $1codegen.i $1codegen.ic $1codegen.st -f
era $1codegen.i
era $1codegen.st
c168 $1codegen.ic codegen.s -ld
era $1codegen.ic
as68 -s 0$1 -f $1 -l -u codegen.s
cp68 -i 0$1 cskels.c $1cskels.i
c068 $1cskels.i $1cskels.ic $1cskels.st -f
era $1cskels.i
era $1cskels.st
c168 $1cskels.ic cskels.s -ld
era $1cskels.ic
as68 -s 0$1 -f $1 -l -u cskels.s
cp68 -i 0$1 interf.c $1interf.i
c068 $1interf.i $1interf.ic $1interf.st -f
era $1interf.i
era $1interf.st
c168 $1interf.ic interf.s -ld
era $1interf.ic
as68 -s 0$1 -f $1 -l -u interf.s
cp68 -i 0$1 main.c $1main.i
c068 $1main.i $1main.ic $1main.st -f
era $1main.i
era $1main.st
c168 $1main.ic main.s -ld
era $1main.ic
as68 -s 0$1 -f $1 -l -u main.s
cp68 -i 0$1 optab.c $1optab.i
c068 $1optab.i $1optab.ic $1optab.st -f
era $1optab.i
era $1optab.st
c168 $1optab.ic optab.s -ld
era $1optab.ic
as68 -s 0$1 -f $1 -l -u optab.s
cp68 -i 0$1 putexpr.c $1putexpr.i
c068 $1putexpr.i $1putexpr.ic $1putexpr.st -f
era $1putexpr.i
era $1putexpr.st
c168 $1putexpr.ic putexpr.s -ld
era $1putexpr.ic
as68 -s 0$1 -f $1 -l -u putexpr.s
cp68 -i 0$1 smatch.c $1smatch.i
c068 $1smatch.i $1smatch.ic $1smatch.st -f
era $1smatch.i
era $1smatch.st
c168 $1smatch.ic smatch.s -ld
era $1smatch.ic
as68 -s 0$1 -f $1 -l -u smatch.s
cp68 -i 0$1 sucomp.c $1sucomp.i
c068 $1sucomp.i $1sucomp.ic $1sucomp.st -f
era $1sucomp.i
era $1sucomp.st
c168 $1sucomp.ic sucomp.s -ld
era $1sucomp.ic
as68 -s 0$1 -f $1 -l -u sucomp.s
cp68 -i 0$1 tabl.c $1tabl.i
c068 $1tabl.i $1tabl.ic $1tabl.st -f
era $1tabl.i
era $1tabl.st
c168 $1tabl.ic tabl.s -ld
era $1tabl.ic
as68 -s 0$1 -f $1 -l -u tabl.s
cp68 -i 0$1 util.c $1util.i
c068 $1util.i $1util.ic $1util.st -f
era $1util.i
era $1util.st
c168 $1util.ic util.s -ld
era $1util.ic
as68 -s 0$1 -f $1 -l -u util.s

View File

@@ -0,0 +1,328 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)optab.c 1.5 11/21/83
*/
#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
#define FR_LDIV 42
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[], /* 24=FR_EQXOR */
fr_call[], /* 25=FR_CALL */
fr_itl[], /* 26=FR_ITL */
fr_lti[], /* 27=FR_LTI */
fr_ld[], /* 28=FR_LD */
fr_eqaddr[], /* 29=FR_EQADDR */
fr_eqnot[], /* 30=FR_EQNOT */
fe_eqnot[], /* 31=FE_EQNOT */
fr_docast[], /* 32=FR_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 */
fr_ldiv[]; /* 42=FR_LDIV */
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*/
fr_ldiv, /*42=FR_LDIV*/
};
/*
*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_LDIV, /*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,257 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)putexpr.c 1.4 12/15/83
*/
#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(" %ld\n",tp->t_offset);
break;
case CLINDR:
case CFINDR: /* [vlh] 3.4 */
printf(" %lx.",tp->t_offset);
printf("%x\n",tp->t_ssp);
break;
case REGOFF:
printf(" %ld",tp->t_offset);
printf("(R%d)",tp->t_reg);
break;
case EXTERNAL:
case EXTOFF:
printf(" %s+%ld",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+%ld",tp->t_label,tp->t_offset);
if( tp->t_sc == STATOFF )
printf("(R%d)",tp->t_reg);
break;
case INDEXED:
printf(" %ld",tp->t_offset);
printf("(R%d,R%d)",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,257 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)putexpr.c 1.4 12/15/83
*/
#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(" %ld\n",tp->t_offset);
break;
case CLINDR:
case CFINDR: /* [vlh] 3.4 */
printf(" %lx.",tp->t_offset);
printf("%x\n",tp->t_ssp);
break;
case REGOFF:
printf(" %ld",tp->t_offset);
printf("(R%d)",tp->t_reg);
break;
case EXTERNAL:
case EXTOFF:
printf(" %s+%ld",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+%ld",tp->t_label,tp->t_offset);
if( tp->t_sc == STATOFF )
printf("(R%d)",tp->t_reg);
break;
case INDEXED:
printf(" %ld",tp->t_offset);
printf("(R%d,R%d)",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,22 @@
$1vsend canon.c
$1vsend codegen.c
$1vsend cskels.c
$1vsend interf.c
$1vsend main.c
$1vsend optab.c
$1vsend putexpr.c
$1vsend smatch.c
$1vsend sucomp.c
$1vsend tabl.c
$1vsend util.c
$1vsend version.c
$1vsend cgen.h
$1vsend cskel.h
$1vsend make.sub
$1vsend icode.h
$1vsend link.sub
$1vsend send.sub
$1vsend c168.rel
$1vsend machine.68k
$1vsend machine.h
$1vsend done

View File

@@ -0,0 +1,547 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)smatch.c 1.9 11/22/83
*/
/* 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);
if( *macro == '+' ) {
macro++;
outaexpr(p,A_DOPOST|A_DOIMMED);
}
else if( *macro == '-' ) {
macro++;
outaexpr(p,A_DOPRE|A_DOIMMED);
}
else
outaexpr(p,A_DOIMMED|A_DOPRE|A_DOPOST);
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,A_NOIMMED);
break;
case MODSWAP:
switch( op ) {
case LMOD:
case LEQMOD:
extf++;
case MOD:
case EQMOD:
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) ) {
rtp = tp->t_right;
if( CONVOP(ltp->t_op) ) {
if(op!=LSH && NOTCONVOP(rtp->t_op)
&& cookie != FORSTACK && cookie!=FORSP && cookie!=FORCREG) {
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,546 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)smatch.c 1.9 11/22/83
*/
/* 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);
if( *macro == '+' ) {
macro++;
outaexpr(p,A_DOPOST|A_DOIMMED);
}
else if( *macro == '-' ) {
macro++;
outaexpr(p,A_DOPRE|A_DOIMMED);
}
else
outaexpr(p,A_DOIMMED|A_DOPRE|A_DOPOST);
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,A_NOIMMED);
break;
case MODSWAP:
switch( op ) {
case LMOD:
case LEQMOD:
extf++;
case MOD:
case EQMOD:
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) ) {
rtp = tp->t_right;
if( CONVOP(ltp->t_op) ) {
if(op!=LSH && NOTCONVOP(rtp->t_op)
&& cookie != FORSTACK && cookie!=FORSP && cookie!=FORCREG) {
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,117 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)sucomp.c 1.3 11/2/83
*/
#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 = sucomp(rtp,nregs,flag);
i = sucomp(ltp,nregs,flag);
su = MAX(su,i);
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 ) {
i = sucomp(rtp,nregs,flag);
su = MAX(su,i);
}
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,117 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)sucomp.c 1.3 11/2/83
*/
#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 = sucomp(rtp,nregs,flag);
i = sucomp(ltp,nregs,flag);
su = MAX(su,i);
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 ) {
i = sucomp(rtp,nregs,flag);
su = MAX(su,i);
}
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,120 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)tabl.c 1.3 11/2/83
*/
#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,120 @@
/*
Copyright 1982
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)tabl.c 1.3 11/2/83
*/
#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,429 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)util.c 1.7 12/15/83
*/
#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*/
long 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; /* {A_DOPRE,A_DOPOST} */
{
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,0L,0,0);
if( op == AUTODEC ) {
if( (autof&A_DOPRE) != 0 )
p->t_op = AUTODEC;
}
else if( op == AUTOINC ) {
if( (autof&A_DOPOST) != 0 )
p->t_op = AUTOINC;
}
p->t_reg = tp->t_reg;
return(p);
case POSTINC:
case POSTDEC:
if( (autof&A_DOPOST) == 0 )
return(tcopy(tp->t_left,autof));
goto copyop;
case PREINC:
case PREDEC:
if( (autof&A_DOPRE) == 0 )
return(tcopy(tp->t_left,autof));
copyop:
default:
if( ISASGOP(op) ) {
if( (autof&A_DOPRE) == 0 )
return(tcopy(tp->t_left,autof));
autof |= A_DOPOST; /*We'll come this way only once*/
}
p = tnalloc(op,tp->t_type,0,0,null,null);
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 reg, lab;
register long off;
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:
if( (flags&A_DOPOST) != 0 )
printf("(R%d)+",reg);
else
printf("(R%d)",reg);
break;
case AUTODEC:
if( (flags&A_DOPRE) != 0 )
printf("-(R%d)",reg);
else
printf("(R%d)",reg);
break;
case CINT:
if( (flags&A_DOIMMED) != 0 )
putchar('#');
printf("%d",tp->t_value);
break;
case DCLONG:
case CLONG:
case CFLOAT: /*[vlh] 3.4 */
if( (flags&A_DOIMMED) != 0 )
putchar('#');
outlval(tp->t_lvalue);
break;
case SYMBOL:
if( off ) {
switch( tp->t_sc ) {
default:
printf("%ld+",off);
break;
case REGOFF:
printf("%ld",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("%ld(R",off); /* [vlh] 4.3, long offset */
printf("%d,R%d",reg,tp->t_xreg);
outatype(tp->t_xtype);
putchar(')');
break;
case CINDR:
printf("%ld",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 = (short)tp->t_offset; l.loword = tp->t_ssp;*/
l = tp->t_offset; /* [vlh] 4.3, changed to long !!! */
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("move");
outtype(type);
printf(" (R%d),R0\n",rreg);
printf("cmp");
outtype(type);
printf(" (R%d),R0\n",lreg);
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,%s\n",reg,pflag?"-(sp)":"(sp)");
}
outdbra(dir,op,ltp,rtp,lab)
int dir, op, lab;
struct tnode *ltp, *rtp;
{
if (!( (dir!=0 && op==NEQUALS) || (dir==0 && op==EQUALS)))
return(0);
if(!(ltp->t_op==PREDEC && rtp->t_op==CINT && rtp->t_value == -1 &&
ISDREG(ltp->t_left->t_reg) && ltp->t_left->t_type==INT &&
ltp->t_left->t_sc == REGISTER))
return(0);
printf("dbra R%d,L%d\n",ltp->t_left->t_reg,lab);
return(1);
}
/* 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,429 @@
/*
Copyright 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)util.c 1.7 12/15/83
*/
#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*/
long 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; /* {A_DOPRE,A_DOPOST} */
{
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,0L,0,0);
if( op == AUTODEC ) {
if( (autof&A_DOPRE) != 0 )
p->t_op = AUTODEC;
}
else if( op == AUTOINC ) {
if( (autof&A_DOPOST) != 0 )
p->t_op = AUTOINC;
}
p->t_reg = tp->t_reg;
return(p);
case POSTINC:
case POSTDEC:
if( (autof&A_DOPOST) == 0 )
return(tcopy(tp->t_left,autof));
goto copyop;
case PREINC:
case PREDEC:
if( (autof&A_DOPRE) == 0 )
return(tcopy(tp->t_left,autof));
copyop:
default:
if( ISASGOP(op) ) {
if( (autof&A_DOPRE) == 0 )
return(tcopy(tp->t_left,autof));
autof |= A_DOPOST; /*We'll come this way only once*/
}
p = tnalloc(op,tp->t_type,0,0,null,null);
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 reg, lab;
register long off;
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:
if( (flags&A_DOPOST) != 0 )
printf("(R%d)+",reg);
else
printf("(R%d)",reg);
break;
case AUTODEC:
if( (flags&A_DOPRE) != 0 )
printf("-(R%d)",reg);
else
printf("(R%d)",reg);
break;
case CINT:
if( (flags&A_DOIMMED) != 0 )
putchar('#');
printf("%d",tp->t_value);
break;
case DCLONG:
case CLONG:
case CFLOAT: /*[vlh] 3.4 */
if( (flags&A_DOIMMED) != 0 )
putchar('#');
outlval(tp->t_lvalue);
break;
case SYMBOL:
if( off ) {
switch( tp->t_sc ) {
default:
printf("%ld+",off);
break;
case REGOFF:
printf("%ld",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("%ld(R",off); /* [vlh] 4.3, long offset */
printf("%d,R%d",reg,tp->t_xreg);
outatype(tp->t_xtype);
putchar(')');
break;
case CINDR:
printf("%ld",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 = (short)tp->t_offset; l.loword = tp->t_ssp;*/
l = tp->t_offset; /* [vlh] 4.3, changed to long !!! */
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("move");
outtype(type);
printf(" (R%d),R0\n",rreg);
printf("cmp");
outtype(type);
printf(" (R%d),R0\n",lreg);
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,%s\n",reg,pflag?"-(sp)":"(sp)");
}
outdbra(dir,op,ltp,rtp,lab)
int dir, op, lab;
struct tnode *ltp, *rtp;
{
if (!( (dir!=0 && op==NEQUALS) || (dir==0 && op==EQUALS)))
return(0);
if(!(ltp->t_op==PREDEC && rtp->t_op==CINT && rtp->t_value == -1 &&
ISDREG(ltp->t_left->t_reg) && ltp->t_left->t_type==INT &&
ltp->t_left->t_sc == REGISTER))
return(0);
printf("dbra R%d,L%d\n",ltp->t_left->t_reg,lab);
return(1);
}
/* 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 4.3 - Fri Dec 30 14:15 1983";

View File

@@ -0,0 +1 @@
char *compiled = "@(#) Code Generator 4.3 - Fri Dec 30 14:15 1983";