mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
c68 -L -r -DMC68000 -DDEBUG -c canon.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c codegen.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c interf.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c main.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c optab.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c putexpr.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c smatch.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c sucomp.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c tabl.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c util.c
|
||||
c68 -L -r -DMC68000 -DDEBUG -c cskels.c
|
||||
mkver -e "Code Generator -"
|
||||
c68 -n -r -L -r -DMC68000 -DDEBUG version.c canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -o c168.4k -l6
|
||||
setstack c168.4k 8000 8000
|
||||
@@ -0,0 +1,14 @@
|
||||
mkver -e "Code Generator -"
|
||||
cc -DPDP11 -DDEBUG -c canon.c
|
||||
cc -DPDP11 -DDEBUG -c codegen.c
|
||||
cc -DPDP11 -DDEBUG -c interf.c
|
||||
cc -DPDP11 -DDEBUG -c main.c
|
||||
cc -DPDP11 -DDEBUG -c optab.c
|
||||
cc -DPDP11 -DDEBUG -c putexpr.c
|
||||
cc -DPDP11 -DDEBUG -c smatch.c
|
||||
cc -DPDP11 -DDEBUG -c sucomp.c
|
||||
cc -DPDP11 -DDEBUG -c tabl.c
|
||||
cc -DPDP11 -DDEBUG -c util.c
|
||||
cc -DPDP11 -DDEBUG -c cskels.c
|
||||
cc -DPDP11 -DDEBUG -c version.c
|
||||
cc version.o canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -l6 -o c168.pdp
|
||||
@@ -0,0 +1,14 @@
|
||||
mkver -e "Code Generator -"
|
||||
cc -O -w -DVAX11 -DDEBUG -c canon.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c codegen.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c interf.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c main.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c optab.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c putexpr.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c smatch.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c sucomp.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c tabl.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c util.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c cskels.c
|
||||
cc -O -w -DVAX11 -DDEBUG -c version.c
|
||||
cc -n version.o canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o tabl.o util.o cskels.o -o c168.vax
|
||||
@@ -0,0 +1,15 @@
|
||||
mkver -e "C68 Code Generator -"
|
||||
c68 -S -L -DVERSADOS -DMC68000 canon.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 codegen.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 cskels.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 interf.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 main.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 optab.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 putexpr.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 smatch.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 sucomp.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 tabl.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 util.c
|
||||
c68 -S -L -DVERSADOS -DMC68000 version.c
|
||||
mv *.s vst
|
||||
|
||||
1008
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/canon.c
Normal file
1008
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/canon.c
Normal file
File diff suppressed because it is too large
Load Diff
229
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cgen.h
Normal file
229
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cgen.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "../icode.h"
|
||||
|
||||
#ifdef DRI
|
||||
# include <stdio.h>
|
||||
# include <klib.h>
|
||||
# undef putchar
|
||||
# define putchar xputchar
|
||||
# undef ferror
|
||||
# define ferror xferror
|
||||
# define printf xprintf
|
||||
#endif
|
||||
|
||||
#define QUICKVAL 8
|
||||
#define LEP 14
|
||||
#define FORCC 1
|
||||
#define FOREFF 2
|
||||
#define FORSTACK 3
|
||||
#define FORCREG 4
|
||||
#define FORSP 5
|
||||
#define FORREG 4
|
||||
#define HICREG 2
|
||||
#define NCREGS 3
|
||||
#define AREGLO 8
|
||||
#define IMMED 1
|
||||
#define NOTIMMED 0
|
||||
#define NOTLOFFSET 0
|
||||
#define NOAUTO 1
|
||||
#define DOAUTO 0
|
||||
|
||||
#define STDERR 2
|
||||
#define PATHSIZE 128
|
||||
|
||||
char brtab[][2];
|
||||
short invrel[];
|
||||
short swaprel[];
|
||||
char *strtab[];
|
||||
|
||||
/*operator tree node for unary and binary operators*/
|
||||
struct tnode {
|
||||
short t_op; /*operator*/
|
||||
short t_type; /*data type of result*/
|
||||
short t_su; /*Sethy-Ullman number*/
|
||||
short t_ssp;
|
||||
struct tnode *t_left; /*left sub-tree*/
|
||||
struct tnode *t_right; /*right sub-tree (undefined if unary)*/
|
||||
};
|
||||
|
||||
/*constant terminal node*/
|
||||
struct conode {
|
||||
short t_op; /*operator*/
|
||||
short t_type; /*type*/
|
||||
short t_su; /*Sethy-Ullman number*/
|
||||
short t_ssp;
|
||||
short t_value; /*value or label number*/
|
||||
};
|
||||
|
||||
/*long constant terminal node*/
|
||||
struct lconode {
|
||||
short t_op; /*operator*/
|
||||
short t_type; /*type*/
|
||||
short t_su; /*Sethy-Ullman number*/
|
||||
short t_ssp;
|
||||
long t_lvalue; /*value or label number*/
|
||||
};
|
||||
|
||||
/*local symbol terminal node*/
|
||||
struct symnode {
|
||||
short t_op; /*operator*/
|
||||
short t_type; /*symbol data type*/
|
||||
short t_su; /*Sethy-Ullman number*/
|
||||
short t_ssp;
|
||||
short t_sc; /*storage class*/
|
||||
short t_offset; /*register offset*/
|
||||
short t_reg; /*register number*/
|
||||
short t_label; /*label number if static*/
|
||||
};
|
||||
|
||||
/*external symbol reference node*/
|
||||
struct extnode {
|
||||
short t_op; /*operator*/
|
||||
short t_type; /*symbol data type*/
|
||||
short t_su; /*Sethy-Ullman number*/
|
||||
short t_ssp;
|
||||
short t_sc; /*storage class*/
|
||||
short t_offset; /*register offset*/
|
||||
short t_reg; /*register number*/
|
||||
char t_symbol[SSIZE]; /*symbol name*/
|
||||
};
|
||||
|
||||
/*68000 special - indexed symbol node*/
|
||||
/*this is used to generate a An(off,Xn.type) address*/
|
||||
struct indexnode {
|
||||
short t_op;
|
||||
short t_type;
|
||||
short t_su;
|
||||
short t_ssp;
|
||||
short t_sc;
|
||||
short t_offset;
|
||||
short t_reg;
|
||||
short t_xreg;
|
||||
short t_xtype;
|
||||
};
|
||||
|
||||
/* io buffer declaration */
|
||||
#define BSIZE 512
|
||||
struct iob {
|
||||
int fd;
|
||||
int cc;
|
||||
char *cp;
|
||||
char cbuf[BSIZE];
|
||||
} ibuf, lbuf, obuf;
|
||||
|
||||
/* Code generation argument flags */
|
||||
short dflag;
|
||||
short mflag;
|
||||
short cflag;
|
||||
short eflag;
|
||||
short fflag;
|
||||
short oflag;
|
||||
short lflag;
|
||||
short m68010; /* [vlh] 4.2, differentiate between chip destination */
|
||||
|
||||
/* Miscellaneous variables */
|
||||
short lineno;
|
||||
short errcnt;
|
||||
short opinfo[];
|
||||
short nextlabel;
|
||||
char optab[][6];
|
||||
char *mnemonics[];
|
||||
char *codeskels[];
|
||||
short stacksize;
|
||||
|
||||
/* general define macros */
|
||||
#define WALLIGN(add) ((add+1)&(~1))
|
||||
#define ISARRAY(type) ((type&SUPTYP)==ARRAY)
|
||||
#define ISFUNCTION(type) ((type&SUPTYP)==FUNCTION)
|
||||
#define ISPOINTER(type) ((type&SUPTYP)==POINTER)
|
||||
#define NOTARRAY(type) ((type&SUPTYP)!=ARRAY)
|
||||
#define NOTFUNCTION(type) ((type&SUPTYP)!=FUNCTION)
|
||||
#define NOTPOINTER(type) ((type&SUPTYP)!=POINTER)
|
||||
#define ISFLOAT(type) (type==FLOAT)
|
||||
#define BTYPE(type) (type&TYPE)
|
||||
#define SUPTYPE(type) (type&SUPTYP)
|
||||
#define ISALLTYPE(type) (type&(SUPTYP|TYPE))
|
||||
#define ISASGOP(op) ((opinfo[op]&OPASSIGN)!=0)
|
||||
#define RELOP(op) ((opinfo[op]&OPREL)!=0)
|
||||
#define LINTEGRAL(op) ((opinfo[op]&OPLWORD)!=0)
|
||||
#define RINTEGRAL(op) ((opinfo[op]&OPRWORD)!=0)
|
||||
#define RASOP(op) ((opinfo[op]&OPRAS)!=0)
|
||||
#define BINOP(op) ((opinfo[op]&OPBIN)!=0)
|
||||
#define UNARYOP(op) ((opinfo[op]&(OPBIN|OPTERM))==0)
|
||||
#define LEAFOP(op) ((opinfo[op]&OPTERM)!=0)
|
||||
#define NOTLEAFOP(op) ((opinfo[op]&OPTERM)==0)
|
||||
#define LVALOP(op) ((opinfo[op]&OPLVAL)!=0)
|
||||
#define OPPRIORITY(op) (opinfo[op]&OPPRI)
|
||||
#define COMMOP(op) ((opinfo[op]&OPCOM)!=0)
|
||||
#define CONVOP(op) ((opinfo[op]&OPCONVS)!=0)
|
||||
#define NOTCONVOP(op) ((opinfo[op]&OPCONVS)==0)
|
||||
#define MAX(a,b) (a>b?a:b)
|
||||
#define MIN(a,b) (a<b?a:b)
|
||||
|
||||
/* one line routines turned into defines [vlh] for speed */
|
||||
|
||||
/*outgoto - output "bra L[labno]"*/
|
||||
#define OUTGOTO(lab) if (lab>0) printf("bra L%d\n",lab)
|
||||
/*outlab - output "L[labno]:"*/
|
||||
#define OUTLAB(lab) if (lab>0) printf("L%d:",lab)
|
||||
|
||||
/*outext - output register sign extension*/
|
||||
#define OUTEXT(reg) printf("ext.l R%d\n",reg)
|
||||
/*outuext - output unsigned to long register extension*/
|
||||
#define OUTUEXT(reg) printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg)
|
||||
/*outswap - output swap register instruction*/
|
||||
#define OUTSWAP(reg) printf("swap R%d\n",reg)
|
||||
/*outaddr - output "add [type] R1 R2" instruction*/
|
||||
#define OUTADDR(r1,r2,tp) outrr("add",r1,r2,(tp))
|
||||
/*outccsave - ouput instruction to move cc's to register*/
|
||||
#define OUTSRSAVE(reg) printf("move sr,R%d\n",reg)
|
||||
#define OUTCCSAVE(reg) printf("move ccr,R%d\n",reg)
|
||||
/*outccrestore - output instruction to restore cc's from register*/
|
||||
#define OUTCCRESTORE(reg) printf("move R%d,ccr\n",reg)
|
||||
/*basetype - get the btype info sans unsigned*/
|
||||
#define BASETYPE(type) ((type==UNSIGNED) ? INT : type)
|
||||
#define UNSIGN(type) ((type) == UNSIGNED)
|
||||
#define LONGORPTR(type) (type==LONG || (type&SUPTYP))
|
||||
#define UNORPTR(type) (type==UNSIGNED || (type&SUPTYP))
|
||||
#define DREG(reg) ((reg) & (~AREGLO))
|
||||
#define AREG(reg) ((reg) | AREGLO)
|
||||
#define ISAREG(reg) ((reg) >= AREGLO)
|
||||
#define ISDREG(reg) ((reg) < AREGLO)
|
||||
#define ISREG(tp) ((tp)->t_op == SYMBOL && (tp)->t_sc == REGISTER)
|
||||
|
||||
#define CONSTZERO(ltyp,p) ((ltyp && !p->t_lvalue) || (!ltyp && !p->t_value))
|
||||
#define SETVAL(ltyp,p,val) if (ltyp) p->t_lvalue = val; else p->t_value = val
|
||||
|
||||
#ifdef DEBUG
|
||||
# define PUTEXPR(cond,id_str,node_ptr) if (cond) putexpr(id_str,node_ptr)
|
||||
#else
|
||||
# define PUTEXPR(cond,id_str,node_ptr)
|
||||
#endif
|
||||
|
||||
/* Functions pre-declared */
|
||||
char *tnalloc();
|
||||
char *snalloc();
|
||||
char *cenalloc();
|
||||
char *xnalloc();
|
||||
char *talloc();
|
||||
char *cnalloc();
|
||||
char *lcnalloc();
|
||||
char *fpcnalloc();
|
||||
char *canon();
|
||||
char *commute();
|
||||
char *constant();
|
||||
char *match();
|
||||
char *addptree();
|
||||
char *fixbfield();
|
||||
char *coffset();
|
||||
char *tcopy();
|
||||
char *fixptree();
|
||||
long readlong();
|
||||
short readshort();
|
||||
|
||||
841
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/codegen.c
Normal file
841
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/codegen.c
Normal file
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
char null[];
|
||||
char *opname[];
|
||||
|
||||
/* scodegen - over-all code generation for expression*/
|
||||
/* Picks off post-fix ++, --.*/
|
||||
scodegen(tp,cookie,reg) /* returns register result is in*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
struct tnode *clist[20];
|
||||
struct tnode **clp;
|
||||
register struct tnode **cp;
|
||||
register short r, ccflag;
|
||||
short lconst;
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == COMMA ) {
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
return(scodegen(tp->t_right,cookie,reg));
|
||||
}
|
||||
ccflag = 0;
|
||||
clp = clist;
|
||||
tp = addptree(tp,&clp);
|
||||
if( clp > clist ) {
|
||||
/*
|
||||
* post ++, -- in tree. We need to compile the tree post operators
|
||||
* then generate code to do the post operators, then do any fix up of
|
||||
* condition codes since the Stupid 68000 architect was a nimnul.
|
||||
*/
|
||||
if( cookie == FORCC ) {
|
||||
/*
|
||||
* here we make the observation that if we are comparing something with
|
||||
* zero OR the top operator of the tree is not a comparison operator,
|
||||
* we can compile the tree to a register, and then set the condition
|
||||
* codes OK with a tst instruction at the end.
|
||||
*/
|
||||
if( RELOP(tp->t_op) ) {
|
||||
if( (rtp=constant(tp->t_right,&lconst)) &&
|
||||
CONSTZERO(lconst,rtp)) { /* [vlh] */
|
||||
ccflag = 1;
|
||||
tp = tp->t_left;
|
||||
cookie = FORREG;
|
||||
}
|
||||
else
|
||||
ccflag = 2;
|
||||
}
|
||||
else {
|
||||
ccflag = 1;
|
||||
cookie = FORREG;
|
||||
}
|
||||
}
|
||||
}
|
||||
r = codegen(tp,cookie,reg);
|
||||
if( clp > clist ) {
|
||||
if( ccflag == 2 ) {
|
||||
if (!m68010) /* [vlh] 4.2, added differentiation */
|
||||
OUTSRSAVE(r);
|
||||
else
|
||||
OUTCCSAVE(r);
|
||||
}
|
||||
for( cp = clist; cp < clp; cp++ )
|
||||
codegen(*cp,FOREFF,r+1);
|
||||
if( ccflag == 1 )
|
||||
outcmp0(r,tp);
|
||||
else if( ccflag == 2 )
|
||||
OUTCCRESTORE(r);
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* addptree - prune off postfix ++, -- from expression tree*/
|
||||
/* This prunes off ++, -- and collects those expressions for*/
|
||||
/* scodegen.*/
|
||||
char *
|
||||
addptree(tp,clp) /* returns pointer to pruned tree*/
|
||||
struct tnode *tp;
|
||||
struct tnode ***clp;
|
||||
{
|
||||
register short op;
|
||||
register struct tnode *stp;
|
||||
|
||||
op = tp->t_op;
|
||||
if( LEAFOP(op) || op == QMARK || op == LAND || op == LOR ) /* [mac] 4.2 */
|
||||
return(tp);
|
||||
if( op == POSTINC || op == POSTDEC ) {
|
||||
stp = tcopy(tp->t_left,NOAUTO); /* [mac] 4.2 c[i=+1]++ & c[*p++]++ */
|
||||
*(*clp)++ = fixptree(tp);
|
||||
return( stp );
|
||||
}
|
||||
if( BINOP(op) )
|
||||
tp->t_right = addptree(tp->t_right,clp);
|
||||
tp->t_left = addptree(tp->t_left,clp);
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* fixptree - fix post-fix tree */
|
||||
/* This eliminates assignment operators from post-fix tree so that */
|
||||
/* c[i=+1]++ will only evaluate i=+1 once */
|
||||
char *
|
||||
fixptree(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register short op;
|
||||
|
||||
op = tp->t_op;
|
||||
if( LEAFOP(op) )
|
||||
return(tp);
|
||||
|
||||
/* This prevents assignments and pre-operators from being evaluated
|
||||
twice... */
|
||||
|
||||
if( ISASGOP(op) || op == PREDEC || op == PREINC )
|
||||
return( fixptree(tp->t_left) );
|
||||
if( BINOP(op) )
|
||||
tp->t_right = fixptree(tp->t_right);
|
||||
tp->t_left = fixptree(tp->t_left);
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* codegen - generate code for expression*/
|
||||
/* This calls up rcodegen, which prunes off any special register*/
|
||||
/* optimization code, then calls ucodegen (unrecursive) code*/
|
||||
/* generation.*/
|
||||
codegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* tree pointer*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register short savestk, ssize, r, i;
|
||||
register struct tnode *rtp;
|
||||
|
||||
#ifdef DEBUG
|
||||
if( cflag )
|
||||
printf("codegen op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
|
||||
#endif
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CALL:
|
||||
case NACALL:
|
||||
ssize = 0;
|
||||
savestk = stacksize;
|
||||
if( tp->t_left->t_op != SYMBOL )
|
||||
stacksize++;
|
||||
if( tp->t_op == CALL ) {
|
||||
rtp = tp->t_right;
|
||||
while( rtp->t_op == COMMA ) {
|
||||
ssize += dofarg(rtp->t_right);
|
||||
rtp = rtp->t_left;
|
||||
}
|
||||
ssize += dofarg(rtp);
|
||||
}
|
||||
tp->t_op = FJSR; /*generate JSR (unary op)*/
|
||||
codegen(tp,FORREG,reg);
|
||||
popstack(ssize);
|
||||
stacksize = savestk;
|
||||
fixresult(tp,cookie,0);
|
||||
return(0); /*result in R0*/
|
||||
|
||||
case COMMA:
|
||||
codegen(tp->t_left,FOREFF,reg);
|
||||
return(codegen(tp->t_right,cookie,reg));
|
||||
|
||||
case AND:
|
||||
if( cookie == FORCC && (i=isonebit(tp->t_right)) >= 0 &&
|
||||
(i=dobitadd(tp->t_left,i)) >= 0 ) {
|
||||
if( CONVOP(tp->t_right->t_op) )
|
||||
tp->t_right = tp->t_right->t_left;
|
||||
tp->t_right->t_value = i;
|
||||
tp->t_right->t_op = CINT; /* [vlh] 4.1 */
|
||||
tp->t_right->t_type = INT; /* [vlh] 4.1 */
|
||||
tp->t_op = BTST;
|
||||
tp = canon(tp);
|
||||
sucomp(tp,reg,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( rcodegen(&tp,cookie,reg) ) {
|
||||
if( cookie == FORCC && tp->t_op == SYMBOL && tp->t_sc == REGISTER
|
||||
&& ISDREG(tp->t_reg))
|
||||
return(reg);
|
||||
}
|
||||
r = ucodegen(tp,cookie,reg);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* fixresult - fix result of code generation*/
|
||||
fixresult(tp,cookie,reg) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
int cookie; /* wanted this cookie*/
|
||||
int reg;
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (cflag)
|
||||
printf("fixresult cookie=%d reg=%d op=%d\n",cookie,reg,tp->t_op);
|
||||
#endif
|
||||
switch( cookie ) {
|
||||
|
||||
case FORCC:
|
||||
outcmp0(reg,tp);
|
||||
break;
|
||||
|
||||
case FORSP:
|
||||
case FORSTACK:
|
||||
stacksize++;
|
||||
outrpush(reg,tp,cookie==FORSTACK);
|
||||
break;
|
||||
|
||||
}
|
||||
return(reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* ucodegen - generate code for tree given cookie and starting register
|
||||
* Handles the matching of the expression tree node with the
|
||||
* corresponding code generation table. When a match is found,
|
||||
* expand is called to expand the code skeleton macro.
|
||||
**/
|
||||
ucodegen(tp,cookie,reg) /* returns reg result is in*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int cookie; /* (FORCC,FOREFF,FORREG,FORSTACK)*/
|
||||
int reg; /* first available register*/
|
||||
{
|
||||
register short r;
|
||||
register char *p;
|
||||
register struct tnode *ltp;
|
||||
short lconst;
|
||||
|
||||
PUTEXPR(cflag,"ucodegen",tp);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case ADDR: /* 4.2 */
|
||||
ltp = tp->t_left;
|
||||
if(cookie==FORCC && ltp->t_op==SYMBOL &&
|
||||
(ltp->t_sc==EXTERNAL || ltp->t_sc==STATIC)) {
|
||||
warning("function existence test");
|
||||
printf("tst.l ");
|
||||
outaexpr(ltp,NOTIMMED);
|
||||
printf("\n");
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case STASSIGN: /*[vlh]*/
|
||||
outstrcpy(codegen(tp->t_left,FORREG,AREG(reg)),
|
||||
codegen(tp->t_right,FORREG,AREG(reg+1)),tp->t_type);
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( cookie == FOREFF )
|
||||
return(reg);
|
||||
break;
|
||||
|
||||
case LSH:
|
||||
if( (ISAREG(reg)) && (p=constant(tp->t_right,&lconst)) &&
|
||||
!(UNSIGN(tp->t_left->t_type)) &&
|
||||
((!lconst && (p->t_value == 1 || p->t_value == 2) ) ||
|
||||
(lconst && (p->t_lvalue == 1 || p->t_lvalue == 2) ))) {
|
||||
r = codegen(tp->t_left,FORREG,reg);
|
||||
outmovr(r,reg,tp->t_left);
|
||||
if( p->t_value == 2 )
|
||||
OUTADDR(reg,reg,tp);
|
||||
OUTADDR(reg,reg,tp);
|
||||
fixresult(tp,cookie,reg);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case EQMULT:
|
||||
case EQDIV:
|
||||
case LEQMULT:
|
||||
case LEQDIV:
|
||||
case EQMOD:
|
||||
case LEQMOD:
|
||||
case EQRSH:
|
||||
case EQLSH:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
if( indexreg(tp->t_left) ) {
|
||||
reg = DREG(reg);
|
||||
outmovr(r=tp->t_left->t_reg,reg,tp);
|
||||
tp->t_left->t_reg = reg;
|
||||
codegen(tp,cookie,reg+1);
|
||||
outmovr(reg,r,tp);
|
||||
return(reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case ADD:
|
||||
case EQADD:
|
||||
if( (p=constant(tp->t_right,&lconst)))
|
||||
if (!lconst && (p->t_value < 0 && p->t_value >= -QUICKVAL)) {
|
||||
p->t_value = - p->t_value;
|
||||
tp->t_op += (SUB-ADD);
|
||||
}
|
||||
else if (lconst && p->t_lvalue<0 && p->t_lvalue >= -QUICKVAL) {
|
||||
p->t_lvalue = -p->t_lvalue;
|
||||
tp->t_op += (SUB-ADD);
|
||||
}
|
||||
break;
|
||||
} /* end of case statement..... */
|
||||
|
||||
sucomp(tp,reg,1);
|
||||
if( (r=loadexpr(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=cqmark(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( (r=hardrel(tp,cookie,reg)) >= 0 )
|
||||
return(r);
|
||||
if( cookie == FORCC && (p=match(tp,FOREFF,reg)) != 0 ) {
|
||||
r = expand(tp,FOREFF,reg,p);
|
||||
if( ISASGOP(tp->t_op) && indexreg(tp->t_left) )
|
||||
outcmp0(tp->t_left->t_reg,tp->t_left);
|
||||
}
|
||||
else if( p = match(tp,cookie,reg) )
|
||||
r = expand(tp,cookie,reg,p);
|
||||
else if( cookie != FORREG )
|
||||
r = fixresult(tp,cookie,ucodegen(tp,FORREG,reg));
|
||||
else
|
||||
error("no code table for %s",opname[tp->t_op]);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* outstrcpy - output structure copy */
|
||||
outstrcpy(lr,rr,size) /*[vlh]*/
|
||||
int lr, rr; /* left register, right register */
|
||||
int size; /* structure size to copy */
|
||||
{
|
||||
register short lab;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cflag) printf("size is %d\n",size);
|
||||
#endif
|
||||
if (ISDREG(lr)) {
|
||||
printf("move.l r%d,r%d\n",lr,AREG(lr));
|
||||
lr = AREG(lr);
|
||||
}
|
||||
if (ISDREG(rr)) {
|
||||
printf("move.l r%d,r%d\n",rr,AREG(rr));
|
||||
rr = AREG(rr);
|
||||
}
|
||||
lab = nextlabel++;
|
||||
printf("move #%d,r%d\n",(size/INTSIZE)-1,DREG(lr));
|
||||
OUTLAB(lab);
|
||||
printf("move (r%d)+,(r%d)+\ndbra r%d,L%d\n",rr,lr,DREG(lr),lab);
|
||||
}
|
||||
|
||||
/**
|
||||
* loadexpr - load an addressable expression into a register
|
||||
* This checks for any possible usage of the register indexed
|
||||
* addressing mode. Note that this relies on the good graces of the
|
||||
* load code skeletons not to muck up the compiler registers before
|
||||
* loading an addressable expression...
|
||||
**/
|
||||
loadexpr(tp,cookie,reg) /* returns register loaded or -1*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int reg; /* register to load*/
|
||||
{
|
||||
register struct tnode *rtp, *ltp, *xtp, *atp;
|
||||
register short off, r, type, nr, ar, xr, xt;
|
||||
|
||||
if( tp->t_op == INDR || LOADABLE(tp) ) {
|
||||
PUTEXPR((cflag>1),"loadexpr",tp);
|
||||
type = tp->t_type;
|
||||
if( tp->t_op == INDR && (ltp=tp->t_left)->t_op == ADD ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
off = 0;
|
||||
if( rtp->t_op == CINT && ((off=rtp->t_value) < -128 ||
|
||||
off > 127 || ltp->t_op != ADD ) ) {
|
||||
tp = snalloc(type,AUTO,off,0,0);
|
||||
if( indexreg(ltp) )
|
||||
tp->t_reg = ltp->t_reg;
|
||||
else {
|
||||
r = codegen(ltp,FORREG,AREG(reg));
|
||||
if( ISDREG(r) )
|
||||
outmovr(r,AREG(r),ltp);
|
||||
tp->t_reg = AREG(r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( rtp->t_op == CINT ) {
|
||||
rtp = ltp->t_right;
|
||||
ltp = ltp->t_left;
|
||||
}
|
||||
if(indexreg(rtp) || (!(indexreg(ltp)) && (ISREG(rtp)))) {
|
||||
xtp = ltp;
|
||||
ltp = rtp;
|
||||
rtp = xtp;
|
||||
}
|
||||
xtp = atp = 0;
|
||||
if( indexreg(ltp) ) {
|
||||
ar = ltp->t_reg;
|
||||
if( (ISREG(rtp)) && rtp->t_type != CHAR ) {
|
||||
xr = rtp->t_reg;
|
||||
xt = rtp->t_type;
|
||||
}
|
||||
else
|
||||
xtp = rtp;
|
||||
}
|
||||
else if( (ISREG(ltp)) && ltp->t_type != CHAR &&
|
||||
(lflag || rtp->t_op != ADDR) ) {
|
||||
xr = ltp->t_reg;
|
||||
xt = ltp->t_type;
|
||||
atp = rtp;
|
||||
}
|
||||
else if( rtp->t_op == ADDR ) {
|
||||
atp = ltp;
|
||||
xtp = rtp;
|
||||
}
|
||||
else {
|
||||
atp = rtp;
|
||||
xtp = ltp;
|
||||
}
|
||||
nr = 0;
|
||||
if( atp )
|
||||
nr++;
|
||||
if( xtp && (xtp->t_op != ADDR || lflag ) )
|
||||
nr++;
|
||||
if( DREG(nr+reg) <= HICREG ) {
|
||||
r = reg;
|
||||
if( atp ) {
|
||||
ar = codegen(atp,FORREG,AREG(r));
|
||||
if( ISDREG(ar) ) {
|
||||
outmovr(ar,AREG(ar),atp);
|
||||
ar = AREG(ar);
|
||||
}
|
||||
r++;
|
||||
}
|
||||
if( xtp && xtp->t_op == ADDR && !lflag ) {
|
||||
tp = xtp->t_left;
|
||||
tp->t_sc += (EXTOFF-EXTERNAL);
|
||||
tp->t_offset += off;
|
||||
tp->t_reg = ar;
|
||||
}
|
||||
else {
|
||||
if( xtp ) {
|
||||
xr = codegen(xtp,FORREG,AREG(r));
|
||||
xt = xtp->t_type;
|
||||
}
|
||||
tp = xnalloc(type,ar,off,xr,xt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( (ISAREG(reg)) && tp->t_type == CHAR )
|
||||
reg = DREG(reg);
|
||||
tp = tnalloc(LOAD,tp->t_type,SU_EASY,0,tp,null);
|
||||
PUTEXPR((cflag>1),"loadexpr final",tp);
|
||||
return( codegen(tp,cookie,reg) );
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* coffset - check offset for addressable node*/
|
||||
char *coffset(tp) /* returns ptr to const off node*/
|
||||
struct tnode *tp; /* pointer to node*/
|
||||
{
|
||||
register struct tnode *rtp;
|
||||
|
||||
if( tp->t_op == ADD ) {
|
||||
rtp = tp->t_right;
|
||||
if( rtp->t_op == CINT )
|
||||
return(rtp);
|
||||
if(!lflag) {
|
||||
if( rtp->t_op == ADDR )
|
||||
return(rtp->t_left);
|
||||
rtp = tp->t_left;
|
||||
if( rtp->t_op == ADDR ) {
|
||||
tp->t_left = tp->t_right;
|
||||
tp->t_right = rtp;
|
||||
return(rtp->t_left);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* hardrel - do relationals returning a value*/
|
||||
hardrel(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int cookie; /* cookie for code generation*/
|
||||
int reg; /* low register*/
|
||||
{
|
||||
char *p;
|
||||
short op, lab1, lab2;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cflag)
|
||||
printf("hardrel: cookie=%d op=%d reg=%d\n",cookie,tp->t_op,reg);
|
||||
#endif
|
||||
if( cookie != FORCC && (RELOP(op=tp->t_op) || op == LOR ||
|
||||
op == LAND || op == NOT) ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp,TRUE,lab1,reg);
|
||||
p = canon(cnalloc(INT,0));
|
||||
codegen(p,cookie,reg);
|
||||
lab2 = nextlabel++;
|
||||
OUTGOTO(lab2);
|
||||
OUTLAB(lab1);
|
||||
p = canon(cnalloc(INT,1));
|
||||
codegen(p,cookie,reg);
|
||||
OUTLAB(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* cqmark - compile question mark operator*/
|
||||
/* This does the compilation of the question mark operator.*/
|
||||
cqmark(tp,cookie,reg) /* returns reg or -1*/
|
||||
struct tnode *tp;
|
||||
int cookie;
|
||||
int reg;
|
||||
{
|
||||
register short lab1, lab2, savestk, r;
|
||||
|
||||
if( tp->t_op == QMARK && cookie != FORCC ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(tp->t_left,FALSE,lab1,reg);
|
||||
savestk = stacksize;
|
||||
r = scodegen(tp->t_right->t_left,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
stacksize = savestk;
|
||||
OUTGOTO(lab2=nextlabel++);
|
||||
OUTLAB(lab1);
|
||||
r = scodegen(tp->t_right->t_right,cookie,reg); /* [mc] 4.0 */
|
||||
outmovr(r,reg,tp);
|
||||
OUTLAB(lab2);
|
||||
return(reg);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* condbr - handle conditional branch code generation
|
||||
* This handles the conditional branch code generation, handling
|
||||
* the special cases for constants, ||, &&, ! and generating the
|
||||
* correct conditional branch instruction.
|
||||
**/
|
||||
condbr(tp,dir,lab,reg)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
int reg;
|
||||
{
|
||||
register struct tnode *ltp, *rtp;
|
||||
register short lab1, optype, op, subdir;
|
||||
|
||||
ltp = tp->t_left;
|
||||
if( BINOP(op=tp->t_op) )
|
||||
rtp = tp->t_right;
|
||||
subdir = dir; /*set up for LOR*/
|
||||
#ifdef DEBUG
|
||||
if (cflag)
|
||||
printf("condbr: dir = %d, lab = %d, reg = %d\n",dir,lab,reg);
|
||||
#endif
|
||||
switch( op ) {
|
||||
|
||||
case CINT:
|
||||
if( !tp->t_value ) {
|
||||
if( dir == FALSE )
|
||||
OUTGOTO(lab);
|
||||
}
|
||||
else if( dir != FALSE )
|
||||
OUTGOTO(lab);
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
condbr(ltp,!dir,lab,reg);
|
||||
break;
|
||||
|
||||
case LAND:
|
||||
dir = !dir;
|
||||
case LOR:
|
||||
if( dir == FALSE ) {
|
||||
lab1 = nextlabel++;
|
||||
condbr(ltp,!subdir,lab1,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
OUTLAB(lab1);
|
||||
}
|
||||
else {
|
||||
condbr(ltp,subdir,lab,reg);
|
||||
condbr(rtp,subdir,lab,reg);
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMA:
|
||||
scodegen(tp->t_left,FOREFF,reg);
|
||||
condbr(tp->t_right,dir,lab,reg);
|
||||
break;
|
||||
|
||||
default: /* [mc] 4.2.b */
|
||||
if( ((dir!=0 && op==NEQUALS) || (dir==0 && op==EQUALS)) &&
|
||||
ltp->t_op==PREDEC && rtp->t_op==CINT && rtp->t_value == -1 &&
|
||||
ISDREG(ltp->t_left->t_reg) && ltp->t_left->t_type==INT) {
|
||||
outdbra(ltp->t_left->t_reg,lab);
|
||||
break;
|
||||
}
|
||||
if( RELOP(op) && ltp->t_op == AUTOINC && rtp->t_op == AUTOINC &&
|
||||
ltp->t_type == rtp->t_type )
|
||||
outcmpm(tp);
|
||||
else
|
||||
scodegen(tp,FORCC,reg);
|
||||
optype = 0;
|
||||
if( RELOP(op) ) {
|
||||
if( UNORPTR(ltp->t_type) || UNORPTR(rtp->t_type) )
|
||||
optype++;
|
||||
}
|
||||
else
|
||||
op = NEQUALS;
|
||||
if(!dir)
|
||||
op = invrel[op-EQUALS];
|
||||
optype = brtab[op-EQUALS][optype];
|
||||
printf("%s L%d\n",mnemonics[optype],lab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rcodegen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation cookie*/
|
||||
int reg; /* register to use for code*/
|
||||
{
|
||||
register short change, op;
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = *tpp;
|
||||
op = tp->t_op;
|
||||
change = 0;
|
||||
if (NOTLEAFOP(op) && op!=COMMA && op!=QMARK && op!=LAND && op!=LOR &&
|
||||
op!=LESS && op!=LESSEQ && op!=GREAT && op!=GREATEQ) {
|
||||
change += rcodegen(&tp->t_left,cookie,reg);
|
||||
if( BINOP(op) )
|
||||
change += rcodegen(&tp->t_right,cookie,reg);
|
||||
change += rcgen(tpp,cookie,reg);
|
||||
} /* [vlh] 4.2 stop getting to this code on <, >, <=, >= */
|
||||
if( change )
|
||||
*tpp = canon(*tpp);
|
||||
return(change);
|
||||
}
|
||||
|
||||
rcgen(tpp,cookie,reg) /* returns changed flag*/
|
||||
struct tnode **tpp; /* pointer to tree*/
|
||||
int cookie; /* code generation goals*/
|
||||
int reg; /* register to use*/
|
||||
{
|
||||
register struct tnode *tp, *p, *ltp, *rtp;
|
||||
register short op, change;
|
||||
|
||||
change = 0;
|
||||
for( tp = *tpp ; BINOP(op=tp->t_op); *tpp=tp=canon(tp), change++ ) {
|
||||
ltp = tp->t_left;
|
||||
if( ltp->t_op != SYMBOL )
|
||||
break;
|
||||
rtp = tp->t_right;
|
||||
switch( op ) {
|
||||
|
||||
case ASSIGN:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
switch( rtp->t_op ) {
|
||||
|
||||
case MULT:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case AND:
|
||||
case OR:
|
||||
case XOR:
|
||||
case LSH:
|
||||
case RSH:
|
||||
if( ISAREG(ltp->t_reg) )
|
||||
return(change);
|
||||
case ADD:
|
||||
case SUB:
|
||||
p = rtp->t_right;
|
||||
if(NOTADDRESSABLE(ltp) || !noref(rtp->t_right,ltp->t_reg))
|
||||
return(change);
|
||||
p = rtp->t_left;
|
||||
if( p->t_op != SYMBOL || p->t_sc != REGISTER ||
|
||||
p->t_reg != ltp->t_reg ) {
|
||||
tp->t_right = p;
|
||||
PUTEXPR((cflag>1),"rcgen",tp);
|
||||
codegen(tp,FOREFF,reg);
|
||||
}
|
||||
tp->t_right = rtp->t_right;
|
||||
tp->t_op = rtp->t_op + (EQADD-ADD);
|
||||
continue;
|
||||
}
|
||||
case EQLSH:
|
||||
case EQRSH:
|
||||
if( ltp->t_sc != REGISTER )
|
||||
return(change);
|
||||
case EQADD:
|
||||
case EQSUB:
|
||||
case EQAND:
|
||||
case EQOR:
|
||||
case EQXOR:
|
||||
PUTEXPR((cflag>1),"rcgen EQOP",tp);
|
||||
if( ltp->t_type == CHAR ) {
|
||||
#ifdef DEBUG
|
||||
if (cflag>1) printf("exiting rcgen with ltp type CHAR change %d\n",change);
|
||||
#endif
|
||||
return(change);
|
||||
}
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
|
||||
case PREDEC:
|
||||
case PREINC:
|
||||
if(cookie==FORCC || ltp->t_type==CHAR)
|
||||
return(change);
|
||||
ucodegen(tp,FOREFF,reg);
|
||||
tp = ltp;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(change);
|
||||
}
|
||||
|
||||
noref(tp,reg) /* 4.0 change */
|
||||
struct tnode *tp; /* returns 1 if no reference in tree to reg */
|
||||
int reg;
|
||||
{
|
||||
if ( LEAFOP(tp->t_op) ) {
|
||||
if (tp->t_op == SYMBOL && tp->t_sc == REGISTER && tp->t_reg == reg)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
if ( !noref(tp->t_left,reg) )
|
||||
return(0);
|
||||
if (BINOP(tp->t_op))
|
||||
return( noref(tp->t_right,reg) );
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* cdsize - compute size of data item*/
|
||||
cdsize(tp) /* returns data size in bytes*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register short type;
|
||||
|
||||
type = tp->t_type;
|
||||
if( SUPTYPE(type) )
|
||||
return(PTRSIZE);
|
||||
switch( type ) {
|
||||
|
||||
case INT:
|
||||
case CHAR:
|
||||
case UCHAR: /* [vlh] 4.2 */
|
||||
case UNSIGNED:
|
||||
return(INTSIZE);
|
||||
|
||||
case LONG:
|
||||
case ULONG: /* [vlh] 4.2 */
|
||||
case FLOAT: /* [vlh] 3.4 */
|
||||
return(LONGSIZE);
|
||||
}
|
||||
error("cdsize: invalid type %d",type);
|
||||
return(0);
|
||||
}
|
||||
|
||||
dofarg(tp) /* returns number of bytes pushed*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
{
|
||||
register short nb;
|
||||
|
||||
nb = 0;
|
||||
if( tp->t_op == SYMBOL && tp->t_sc == STRUCT )
|
||||
error("structure operation not implemented");
|
||||
else if( stacksize ) {
|
||||
codegen(tp,FORSTACK,0);
|
||||
nb = cdsize(tp);
|
||||
}
|
||||
else
|
||||
codegen(tp,FORSP,0);
|
||||
return( nb );
|
||||
}
|
||||
|
||||
/* dobitadd - do bit operation address checking and fixup*/
|
||||
dobitadd(tp,bitno) /* returns -1 if can't or bitno*/
|
||||
struct tnode *tp;
|
||||
int bitno;
|
||||
{
|
||||
register short offset;
|
||||
|
||||
if( tp->t_type == CHAR )
|
||||
offset = 0;
|
||||
else
|
||||
offset = cdsize(tp) - (bitno/BITSPBYTE) - 1;
|
||||
if( tp->t_op == SYMBOL ) {
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
if( ISDREG(tp->t_reg) )
|
||||
return(bitno);
|
||||
default:
|
||||
return(-1);
|
||||
|
||||
case EXTERNAL:
|
||||
case STATIC:
|
||||
case REGOFF:
|
||||
case STATOFF:
|
||||
case EXTOFF:
|
||||
tp->t_offset += offset;
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
}
|
||||
else if( tp->t_op == INDR ) {
|
||||
tp->t_left = tnalloc(ADD,tp->t_left->t_type,0,0,tp->t_left,
|
||||
cnalloc(INT,offset));
|
||||
return( bitno % BITSPBYTE );
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
isonebit(tp) /* returns -1 if not 1 bit, else bitno*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
{
|
||||
short lconst;
|
||||
long bvalue;
|
||||
|
||||
if (!(tp = constant(tp,&lconst))) /* [vlh] 4.1 added long... */
|
||||
return(-1);
|
||||
bvalue = (lconst) ? tp->t_lvalue : (long) tp->t_value;
|
||||
return(onebit(bvalue));
|
||||
}
|
||||
93
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cskel.h
Normal file
93
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cskel.h
Normal 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;
|
||||
};
|
||||
1486
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cskels.c
Normal file
1486
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/cskels.c
Normal file
File diff suppressed because it is too large
Load Diff
18
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/errors
Normal file
18
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/errors
Normal file
@@ -0,0 +1,18 @@
|
||||
can't create (filename)
|
||||
can't open (filename)
|
||||
cdsize: invalid type (number)
|
||||
code skeleton error: (number)
|
||||
divide by zero
|
||||
expression too complex
|
||||
expression too complex
|
||||
intermediate code error (number,number)
|
||||
invalid floating op (number)
|
||||
invalid initialization
|
||||
invalid operator (number)
|
||||
invalid register expression
|
||||
invalid storage class (number)
|
||||
modulus by zero
|
||||
no code table for (number)
|
||||
opcall bad op (number)
|
||||
structure operation not implemented
|
||||
usage: c168 icode asm [-DLmec]
|
||||
142
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/interf.c
Normal file
142
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/interf.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
|
||||
short bol;
|
||||
short gflag;
|
||||
short onepass;
|
||||
|
||||
/* outexpr - output expression*/
|
||||
outexpr(tp) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree node*/
|
||||
{
|
||||
outline();
|
||||
if( exprok(tp) ) {
|
||||
#ifdef DEBUG
|
||||
if (cflag) printf("outexpr 1: type is %d\n",tp->t_type);
|
||||
#endif
|
||||
scodegen(canon(tp),FOREFF,0);
|
||||
#ifdef DEBUG
|
||||
if (cflag) printf("outexpr 2: type is %d\n",tp->t_type);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
outifgoto(tp,dir,lab)
|
||||
struct tnode *tp;
|
||||
int dir;
|
||||
int lab;
|
||||
{
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
condbr(canon(tp),dir,lab,0);
|
||||
}
|
||||
|
||||
outcforreg(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
outline();
|
||||
if( exprok(tp) )
|
||||
outmovr(scodegen(canon(tp),FORREG,0),0,tp);
|
||||
}
|
||||
|
||||
outinit(tp) /* returns - none*/
|
||||
struct tnode *tp;
|
||||
{
|
||||
register short typeout;
|
||||
|
||||
outline();
|
||||
if( exprok(tp) ) {
|
||||
typeout = tp->t_type;
|
||||
tp = canon(tp);
|
||||
if( tp->t_op == ADDR )
|
||||
tp = tp->t_left;
|
||||
if( tp->t_op == CINT || tp->t_op == CLONG || tp->t_op == SYMBOL ) {
|
||||
if( tp->t_op != CINT ) /* [vlh] 4.1 added CLONG... */
|
||||
printf(".dc.l ");
|
||||
else {
|
||||
printf(".dc");
|
||||
outtype(typeout);
|
||||
putchar(' ');
|
||||
}
|
||||
outaexpr(tp,NOTIMMED); /* [vlh] 4.0 not immed... */
|
||||
}
|
||||
else
|
||||
error("invalid initialization");
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* snalloc - code generator symbol node allocation*/
|
||||
/* This might be coalesced into parser snalloc.*/
|
||||
char *snalloc(type,sc,offset,dp,ssp) /* returns ptr to node alloced*/
|
||||
int type; /* type of symbol*/
|
||||
int sc; /* storage class*/
|
||||
int offset; /* offset from Local Environment Ptr*/
|
||||
int dp; /*for compatability with parser*/
|
||||
int ssp; /*for compatability with parser*/
|
||||
{
|
||||
register struct symnode *sp;
|
||||
|
||||
sp = talloc(sizeof(*sp));
|
||||
sp->t_op = SYMBOL;
|
||||
sp->t_type = type;
|
||||
sp->t_su = dp;
|
||||
sp->t_ssp = ssp;
|
||||
sp->t_sc = sc;
|
||||
switch( sc ) {
|
||||
|
||||
case STATIC:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = offset;
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
sp->t_offset = 0;
|
||||
sp->t_reg = offset;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
case AUTO:
|
||||
sp->t_sc = REGOFF;
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = LEP;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
sp->t_offset = offset;
|
||||
sp->t_reg = 0;
|
||||
sp->t_label = 0;
|
||||
break;
|
||||
}
|
||||
return(sp);
|
||||
}
|
||||
|
||||
exprok(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( tp < exprarea || tp > &exprarea[EXPSIZE] )
|
||||
return(0);
|
||||
if( LEAFOP(tp->t_op) )
|
||||
return(1);
|
||||
if( BINOP(tp->t_op) && !exprok(tp->t_right) )
|
||||
return(0);
|
||||
return( exprok(tp->t_left) );
|
||||
}
|
||||
|
||||
outline()
|
||||
{
|
||||
if( onepass && !bol )
|
||||
putchar('\n');
|
||||
if (!gflag)
|
||||
printf("*line %d\n",lineno);
|
||||
else
|
||||
printf("~_lN%d:\n",lineno);
|
||||
}
|
||||
372
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/log
Normal file
372
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/log
Normal file
@@ -0,0 +1,372 @@
|
||||
.he "C68 Code Generator"Change Log"Page %"
|
||||
.de bg
|
||||
.sp
|
||||
.in +5
|
||||
..
|
||||
.de eg
|
||||
.sp
|
||||
.in -5
|
||||
..
|
||||
1. 7/20/82 - Post fix operators
|
||||
.bg
|
||||
Post fix operators were being handled a la PDP-11, i.e. if( x++ ) ...
|
||||
would be true if the result of the post-increment were true rather than
|
||||
the original value of x.
|
||||
Also, if( --x ) ... would generate an unnecessary test instruction.
|
||||
Added scodegen (delay???) routine to pick off post-fix operators,
|
||||
call codegen to generate the code for the pruned tree, then generate code
|
||||
for the post-fix operators.
|
||||
This will generate horrendous code for something like: if( x[i]++ );
|
||||
but t.s.
|
||||
.eg
|
||||
2. 7/21/82 - divide by long constant
|
||||
.bg
|
||||
The construct: x / 10L did not generate a ldiv call because long constants
|
||||
Sethy-Ullman numbers are being calculated normally.
|
||||
Added DCLONG operator and check in canon to check for this case.
|
||||
This prevents sucomp from incorrectly computing the Sethy-Ullman number.
|
||||
.eg
|
||||
3. 7/23/82 - shifting long or byte address by 1
|
||||
.bg
|
||||
The construct: x =<< 1 generated an invalid assembly instruction if x
|
||||
was an automatic or static byte or long.
|
||||
This is because you may only shift words in memory (The 68000
|
||||
clone strikes again!!!).
|
||||
Changed code skeletons for eqshft to only match for addressable words.
|
||||
.eg
|
||||
4. 8/7/82 - complex long divide/modulus expressions
|
||||
.bg
|
||||
Complex expressions involving long over short divides or modulus would
|
||||
not work, not consistently sign extending word result.
|
||||
Changed test in expand to check for DIV or MOD operators in long tree
|
||||
and set extf flag.
|
||||
.eg
|
||||
5. 8/7/82 - add of quick negative did not generate subq
|
||||
.bg
|
||||
The expression: x = y - 1; with x & y registers generated an add #-1,Rx
|
||||
rather than suq #1,Rx. This was because rcgen was turning ADD into EQADD.
|
||||
Added test in ucodegen for both ADD and EQADD.
|
||||
.eg
|
||||
6. 8/12/82 - multiply(divide) by -1
|
||||
.bg
|
||||
The expression: x =* -1; was being "optimized" to negate x, however it
|
||||
did not store the result in x.
|
||||
This is because of multiply/divide by -1 optimization in canon not
|
||||
checking for =* or =/.
|
||||
Added checks.
|
||||
.eg
|
||||
7. 8/27/82 - character array assigned function value
|
||||
.bg
|
||||
The expression: x[i] = f(i); did not generate correct code, the address
|
||||
register for x[i] was computed, but not saved on stack, then f was called.
|
||||
This resulted in all further function calls using the first argument
|
||||
push rather than a move.
|
||||
In ucodegen, when optimizing for address register shifted left by 1 or 2
|
||||
did not do fixresult call which would have saved register on stack.
|
||||
Added this call.
|
||||
Also added code skeleton to compile the function expression to the stack,
|
||||
then move that directly to the computed address.
|
||||
.eg
|
||||
8. 9/1/82 - address-indexed addressing mode used .b index
|
||||
.bg
|
||||
If the index register used in an address-indexed addressing mode
|
||||
operand was byte, the index register was given a .b extension even
|
||||
though it had correctly extended the register to a word.
|
||||
In outaexpr for INDEXED addressing mode an outatype of the index
|
||||
type should have been used rather than outtype.
|
||||
.eg
|
||||
9. 9/1/82 - x =* -1, x =/ -1, x=^ -1 optimizations
|
||||
.bg
|
||||
Added EQNEG and EQNOT operators and added checks in canon so that
|
||||
x =* -1 and x =/ -1 are changed to neg operations and x =^ -1 is
|
||||
changed to not operation.
|
||||
.eg
|
||||
10. 9/15/82 - function redeclaration bug
|
||||
.bg
|
||||
If an external function was redeclared in a function body, a
|
||||
redeclaration error occured.
|
||||
This was fixed in dodecl by checking for a function of AUTO type
|
||||
and changing it to a function of EXTERNAL type.
|
||||
.eg
|
||||
11. 9/15/82 - Hard long to register fix
|
||||
.bg
|
||||
The syntax: b =* x; where b was a long register would give an error
|
||||
"hard long to register".
|
||||
This was because the lamul function expected to do the assignment to
|
||||
a memory location.
|
||||
Changed canon so that hard =*, =/ and =% would be changed to use
|
||||
the normal long multiply and divide routines, and then do an assignment.
|
||||
.eg
|
||||
12. 9/15/82 - Casting Problems (Not fixed)
|
||||
.bg
|
||||
The syntax: i = (char) i; where i is not a register would result in
|
||||
i being assigned the high-order byte of i.
|
||||
This also is a problem for any cast where the cast type is smaller
|
||||
than the type being cast.
|
||||
Generally this should be solved by moving the expression into a data
|
||||
register, and then obtaining the result from there.
|
||||
Added DOCAST operator to handle these problems.
|
||||
However, this is all tightly interwined with conversions in the parser.
|
||||
.eg
|
||||
13. 11/24/82 - More than two constants couldn't be combined
|
||||
.bg
|
||||
Constant optimization failed to mathematically compute constant
|
||||
arithmetic fully (the results were lost) thus yielding the result
|
||||
as the computation of the last two constants in the expression
|
||||
only.
|
||||
.eg
|
||||
14. 12/13/82 - structure assignments
|
||||
.bg
|
||||
One structure may be assigned to another provided that the one on
|
||||
the right is smaller than or equal to the left one in size.
|
||||
.eg
|
||||
15. 1/10/83 - floating point
|
||||
.bg
|
||||
Floating point handling including constants, conversions and operations
|
||||
added.
|
||||
.eg
|
||||
16. 1/14/83 - pop stack instruction
|
||||
.bg
|
||||
The popstack instruction of 1..8 was turned into an addq.w which only
|
||||
affected half of the sp register. The "add #d,sp" has been replaced
|
||||
by either "addq.l #d,sp" or "adda.l #d,sp".
|
||||
.eg
|
||||
17. 1/14/83 - optimization eqmult, eqdiv, eqmod
|
||||
.bg
|
||||
Generated a new code skeleton entry to deal with register integer mults,
|
||||
divs, and mods (eg. register int i; i =* 34;).
|
||||
.eg
|
||||
18. 1/17/83 - return of 0L
|
||||
.bg
|
||||
Code skeletons generated a clr R0 regardless of operand type.
|
||||
.eg
|
||||
19. 1/21/83 - prefix ++, -- problems with bytes
|
||||
.bg
|
||||
The code skeletons for fr_eqop were a total mess, particularly for
|
||||
the left hand side being a character.
|
||||
Rewrote all fr_eqop and fr_eqmult code skeletons to handle these cases.
|
||||
Unfortunately rcgen also gets into the act turning all =+, =-, =&, =| and
|
||||
pre++, pre-- compiled for register into compiled for effect then returning
|
||||
the left hand side symbol.
|
||||
This is probably OK for word and long LHS but for byte it results in
|
||||
lost precision.
|
||||
Changed rcgen to check for CHAR LHS and not to compile for effect if so.
|
||||
.eg
|
||||
20. 2/2/83 - long eq_shift int
|
||||
.bg
|
||||
Bad code was generated for long's left shifted by integer values.
|
||||
.eg
|
||||
21. 2/23/83 - longs divided by integers
|
||||
.bg
|
||||
Ext.l was not always done.
|
||||
.eg
|
||||
22. 3/1/83 - casting to char
|
||||
.bg
|
||||
Added the docast operator, forces the variable to be put into a register
|
||||
and an ext.w to be acted upon it.
|
||||
.eg
|
||||
23. 3/2/83 - casting register char * to int
|
||||
.bg
|
||||
Bad code was generated for casting a character to an integer if the
|
||||
character was pointed to by a register character pointer.
|
||||
.eg
|
||||
24. 3/3/83 - Compiling complex indirect into A Reg.
|
||||
.bg
|
||||
The construct: *p->q->r generated an intermediate load into a D reg
|
||||
then move to A reg, rather than compiling directly into A reg.
|
||||
This was because of some hysterical PDP-11 code in expand checking
|
||||
for whether an A register is appropriate.
|
||||
.eg
|
||||
25. 3/3/83 - dbra instruction
|
||||
.bg
|
||||
The construct: if( --i != -1 ) goto x; now generates a dbra i,x
|
||||
instruction. This combined with the new for and while loops easily
|
||||
enables you to generate dbra instructions for loops. This affected
|
||||
code in condbr to check for the specific expression tree above.
|
||||
.eg
|
||||
26. 3/3/83 - Bit field assigned to bit field
|
||||
.bg
|
||||
The construct: x.bf1 = x.bf2 failed due to fixbfield not fixing up
|
||||
the RHS of the expression. Added recursive call to fixbfield to
|
||||
fix up RHS's of equal operators.
|
||||
.eg
|
||||
27. 3/4/83 - Post increment with ?: op
|
||||
.bg
|
||||
Post increment and post decrement operations can not be delayed in the
|
||||
case of a ?: operation. The post operation was taking place regardless
|
||||
of whether the case in question was executed.
|
||||
.eg
|
||||
28. 3/7/83 - long div/mod/mul/sub/add const 1L or const 0L
|
||||
.bg
|
||||
Added optimization handling for long constant zero and one handling.
|
||||
An error is now generated is a mod or div 0 is found. Add/Sub of
|
||||
a consant 0 does not generate any code. Mult/Div 1 does not generate
|
||||
any code
|
||||
.eg
|
||||
29. 3/8/83 - eqmod 1 and eqmult 0
|
||||
.bg
|
||||
Incorrect storage of simple expressions eqmod 1 and eqmult 0 which
|
||||
result in a zero store. Also added for the long case.
|
||||
.eg
|
||||
30. 3/18/83 - reg ptr assign and character compare
|
||||
.bg
|
||||
The statement if (*(regptr = str)); did not do the test for the character
|
||||
pointed to but rather the result of the assignment. This was caused
|
||||
by a codegen optimization which should not include a-registers.
|
||||
.eg
|
||||
31. 3/21/83 - Complex assignment to character array
|
||||
.bg
|
||||
The expression: ca[i] = f(); would move i to the stack as a word and pop
|
||||
it as a long.
|
||||
This was caused by the code skeleton macro (S_FORSTACK + S_INDR) assuming
|
||||
what was going on the stack will always be a long.
|
||||
Did quick and dirty fix in expand to extend an int sub-tree to a long
|
||||
if compiling subtree FORSTACK+INDR.
|
||||
.eg
|
||||
32. 4/4/83 - unary operations on address registers [vlh] 4.1
|
||||
.bg
|
||||
Operations involving unary operations on addresses was not forcing the
|
||||
use of a temporary data register to do the actual operation. This
|
||||
was causing bad code to be generated for certain expressions, eg.
|
||||
array[-i], or array[~i].
|
||||
.eg
|
||||
33. 5/23/83 - long constant optimizations [vlh] 4.1
|
||||
.bg
|
||||
Changed all the constant optimizations to handle longs as well as
|
||||
ints. This will make life more difficult on the pdp-11 but makes
|
||||
for more optimal code (eg. l *= 2...).
|
||||
.eg
|
||||
34. 5/25/83 - pre-operators over &&, ||, ? [vlh] 4.1
|
||||
.bg
|
||||
Preincrement/decrement were not working correctly over &&, || and ?
|
||||
operators.
|
||||
This was due to rcgen generating code for preinc/dec even if && or ||
|
||||
was seen in tree.
|
||||
Added test in rcodegen to stop trying for register optimizations over &&, ||
|
||||
and ?.
|
||||
.eg
|
||||
35. 5/25/83 - post-operators over &&, ||. [vlh] 4.1
|
||||
.bg
|
||||
Postincrement/decrement operators were not working correctly over && and ||.
|
||||
This was due to scodegen/addptree pulling out all post-operators over && and
|
||||
|| operators. Added check in addptree to stop at && and ||.
|
||||
Condbr then does an scodegen over the && and || to do the post-operators.
|
||||
.eg
|
||||
36. 5/25/83 - post-increments over assigns and autoinc/dec [mc] 4.1
|
||||
.bg
|
||||
Postincrement/decrement over expressions involving assignment operators and
|
||||
autoinc/autodec did not work correctly. For example: c[i=+1]++ and c[*p++]++;
|
||||
This was because the sub-expression tree which is copied did not adjust for
|
||||
things which are being altered in the sub-expression.
|
||||
Fixed tcopy, addptree and fixbfield to fix this problem.
|
||||
This is not guaranteed to work in extremely complicated code involving
|
||||
assignment and post-op operators, for example, something like:
|
||||
c[c[i=+1]++]++; And is especially not guaranteed to work with bit-fields
|
||||
in something like: (c[i=+1]++)->bitfield.
|
||||
.eg
|
||||
37. 6/1/83 - long multiplication/division as array subscripts [vlh] 4.1
|
||||
.bg
|
||||
Array subscripts which involved long operations which required calls to function
|
||||
routines expected the results to be left in the first address register rather
|
||||
than the first data register. This caused bad code to be generated.
|
||||
.eg
|
||||
38. 6/1/83 - allow long array indices [vlh] 4.1
|
||||
.bg
|
||||
In order to generate arrays which are as big as memory the arrays must be larger
|
||||
than an int in side we need to also allow array indices to be longs. This was
|
||||
tied in with the long constant evaluation.
|
||||
.eg
|
||||
39. 6/21/83 - link file [vlh] 4.2
|
||||
.bg
|
||||
Added the link file as an input file, this is necessary for auto inits
|
||||
and block variables.
|
||||
Added the symbol "%" as a readicode symbol to signify the need to pull
|
||||
an entry out of the link file which is being created by the parser.
|
||||
.eg
|
||||
40. 7/6/83 - dbra instruction 4.2
|
||||
.bg
|
||||
Fixed the dbra conditional test to not be used in the case of a complex
|
||||
expression (eg. while(--regi != -1 && *l != '\n'); )..
|
||||
.eg
|
||||
41. 7/11/83 - if test float [vlh] 4.2
|
||||
.bg
|
||||
The testing for float true was not being handled. The construction
|
||||
if (fp); now does a test for the floating point value being a non zero
|
||||
32 bit value. This is taking advantage of the fact that both floating
|
||||
point constructs denote the value zero as a zero.
|
||||
.eg
|
||||
42. 7/13/83 - short vs. long vs. int [vlh] 4.2
|
||||
.bg
|
||||
For the sake of portability and the likelihood of generating the same
|
||||
code on the vax which supports a 16 bit short, a 32 bit int and a 32
|
||||
bit long versus Regulus which supports a 16 bit short, a 16 bit int and
|
||||
a 32 bit long the code generator has been changed to use only longs
|
||||
and shorts on the theory that most machines support 16 bit shorts and
|
||||
32 bit longs.
|
||||
.eg
|
||||
43. 7/20/83 - symbolic debugger flag [vlh] 4.2
|
||||
.bg
|
||||
Added the '-g' flag. Required a change to the outline routine to outline
|
||||
cdb type line number identifying lables rather than the standard sort.
|
||||
Also altered readicode to output a line number identifier on a null
|
||||
expression (allows a line number to be placed previous to asm() code
|
||||
as well as loops).
|
||||
.eg
|
||||
44. 7/22/83 - Suppress optimization which gens bad code [vlh] 4.2
|
||||
.bg
|
||||
Changed rcodegen to not do the rcgen call if the operator is less-than,
|
||||
or greater-than. This keeps certain expressions from being evaluated
|
||||
in the wrong order. In particular ((regi=f(3)) > f(1)).
|
||||
.eg
|
||||
45. 7/25/83 - unsigned char/long [vlh] 4.2
|
||||
.bg
|
||||
Initial work required to generate code for unsigned char and unsigned
|
||||
long types.
|
||||
.eg
|
||||
46. 7/26/83 - preinc/dec, postinc/dec floats [vlh] 4.2
|
||||
.bg
|
||||
Added OPCALL entries for preinc/predec and postinc/postdec.
|
||||
.eg
|
||||
47. 8/2/83 - bad optimizations [vlh] 4.2
|
||||
.bg
|
||||
An expression anded (&) with a 0 or an expression multiplied (*) by a
|
||||
zero in which the expression has side effects (eg. function call which
|
||||
changes global variables) would cause bad code to be generated. This
|
||||
has been a problem in a number of other compilers and was noted on the
|
||||
usenet by DMR himself.
|
||||
.eg
|
||||
48. 8/3/83 - 68010 changes [vlh] 4.2
|
||||
.bg
|
||||
Added the 68010 flag (called m68010). Code now generates a "move cc"
|
||||
instead of "move sr" in scodegen if the 68010 flag is specified. An
|
||||
alternative routine fakecmpm has been added because the 68010 does not
|
||||
properly handle the cmpm instruction.
|
||||
.eg
|
||||
49. 8/9/83 - source file [vlh] 4.2
|
||||
.bg
|
||||
Fixed readicode to pick up a source filename as well as the current line
|
||||
number, for use in error reporting.
|
||||
.eg
|
||||
50. 8/10/83 - int cast pushed on stack as long [vlh] 4.2
|
||||
.bg
|
||||
Fixed match() so that it would not optimize out conversion operators on
|
||||
items destined to be put on the stack (eg. f(((int)l)&0xff);). Required
|
||||
adding a test for cookie != FORSP.
|
||||
.eg
|
||||
51. 8/23/83 - long indexes [vlh] 4.2
|
||||
.bg
|
||||
Fixed optim to not optimize long constant offsets into arrays into 16 bit
|
||||
displacements.
|
||||
.eg
|
||||
52. 8/26/83 - constant int/long assigned to char [vlh] 4.2
|
||||
.bg
|
||||
Added code to optim to truncate Constant integers and longs which were
|
||||
being assigned to character values via ops: equal, eqadd, eqsub, eqand,
|
||||
eqor, eqxor.
|
||||
.eg
|
||||
53. 8/30/83 - if (main)... [vlh] 4.2
|
||||
.bg
|
||||
Altered outaexpr to not generate the '#' preceding a symbol expression
|
||||
which does not have an offset and is and external or static variable
|
||||
being generated for condition codes.
|
||||
.eg
|
||||
623
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/main.c
Normal file
623
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/main.c
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
char *version = "@(#)c168 code generator 4.2 - Sep 6, 1983";
|
||||
|
||||
/**
|
||||
* ALCYON C Compiler for the Motorola 68000 - Code Generator
|
||||
*
|
||||
* Called from c68:
|
||||
*
|
||||
* c168 icode link asm
|
||||
*
|
||||
* icode: parsed intermediate code with some assembly code
|
||||
* preceded by left parens.
|
||||
*
|
||||
* link: contains the procedure link and movem instructions.
|
||||
*
|
||||
* asm: output assembler code for as68.
|
||||
*
|
||||
* The basic structure of the code generator is as follows:
|
||||
*
|
||||
* main - main routine
|
||||
* readicode - code generation driven by intermediate code
|
||||
*
|
||||
**/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
char *opap;
|
||||
short gflag;
|
||||
short nextlabel = 10000;
|
||||
char null[] = "";
|
||||
short lflag = 1;
|
||||
char source[PATHSIZE] = "";
|
||||
|
||||
char *readtree();
|
||||
char *readsym();
|
||||
|
||||
/* main - main routine, handles arguments and files*/
|
||||
main(argc,argv) /* returns - none*/
|
||||
int argc; /* arg count*/
|
||||
char **argv; /* arg pointers*/
|
||||
{
|
||||
register char *q, *calledby;
|
||||
|
||||
calledby = *argv++;
|
||||
if( argc < 4 )
|
||||
usage(calledby);
|
||||
if( fopen(*argv,&ibuf,0) < 0 ) /* 3rd arg for versados */
|
||||
ferror("can't open %s",*argv);
|
||||
if( fopen(*++argv,&lbuf,0) < 0)
|
||||
ferror("can't open %s",*argv);
|
||||
if( fcreat(*++argv,&obuf,0) < 0 )
|
||||
ferror("can't create %s",*argv);
|
||||
|
||||
for( argc -= 4; argc--; ) {
|
||||
q = *++argv;
|
||||
if( *q++ != '-' )
|
||||
usage(calledby);
|
||||
while( 1 ) {
|
||||
switch( *q++ ) {
|
||||
|
||||
case 'a': /* [vlh] 4.2, alter ego of the '-L' flag */
|
||||
lflag = 0;
|
||||
continue;
|
||||
|
||||
case 'c':
|
||||
cflag++;
|
||||
continue;
|
||||
|
||||
case 'e':
|
||||
eflag++;
|
||||
continue;
|
||||
|
||||
case 'f':
|
||||
fflag++;
|
||||
continue;
|
||||
|
||||
case 'g': /* [vlh] 4.2 generate line labels for cdb */
|
||||
gflag++;
|
||||
continue;
|
||||
|
||||
case 'm':
|
||||
mflag++;
|
||||
continue;
|
||||
|
||||
case 'o':
|
||||
oflag++;
|
||||
continue;
|
||||
|
||||
case 'D':
|
||||
dflag++;
|
||||
continue;
|
||||
|
||||
case 'L': /* [vlh] 4.2, OBSOLETE */
|
||||
lflag++;
|
||||
continue;
|
||||
|
||||
case 'T': /* [vlh] 4.2 generates code for the 68010 */
|
||||
m68010++;
|
||||
continue;
|
||||
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(calledby);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
readicode();
|
||||
myfflush(&obuf);
|
||||
exit(errcnt!=0);
|
||||
}
|
||||
|
||||
/* readicode - read intermediate code and dispatch output*/
|
||||
/* This copies assembler lines beginning with '(' to assembler*/
|
||||
/* output and builds trees starting with '.' line.*/
|
||||
readicode() /*returns - none*/
|
||||
{
|
||||
register short c;
|
||||
register struct tnode *tp;
|
||||
|
||||
while( (c=getc(&ibuf)) > 0 ) {
|
||||
switch(c) {
|
||||
|
||||
case '.':
|
||||
lineno = readshort();
|
||||
readfid();
|
||||
opap = exprarea;
|
||||
if( tp = readtree() ) {
|
||||
PUTEXPR(cflag,"readicode",tp);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case INIT:
|
||||
outinit(tp->t_left);
|
||||
break;
|
||||
|
||||
case CFORREG:
|
||||
outcforreg(tp->t_left);
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
outifgoto(tp->t_left,tp->t_type,tp->t_su);
|
||||
break;
|
||||
|
||||
default:
|
||||
outexpr(tp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
outline();
|
||||
break;
|
||||
|
||||
case '(':
|
||||
while( (c=getc(&ibuf)) != '\n' )
|
||||
putchar(c);
|
||||
putchar(c);
|
||||
break;
|
||||
|
||||
case '%': /* [vlh] 4.2 */
|
||||
while( (c=getc(&ibuf)) != '\n' )
|
||||
; /* skip over carriage return */
|
||||
while( (c=getc(&lbuf)) != '%' && c != -1)
|
||||
putchar(c);
|
||||
if (c == -1)
|
||||
ferror("early termination of link file");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("intermediate code error %c,%d",c,c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readtree - recursive intermediate code tree read*/
|
||||
char *
|
||||
readtree() /* returns ptr to expression tree*/
|
||||
{
|
||||
register short op, type, sc;
|
||||
register struct tnode *tp, *rtp;
|
||||
char sym[SSIZE];
|
||||
|
||||
if( (op=readshort()) <= 0 )
|
||||
return(0);
|
||||
type = readshort();
|
||||
switch( op ) {
|
||||
|
||||
case SYMBOL:
|
||||
if( (sc=readshort()) == EXTERNAL )
|
||||
tp = cenalloc(type,sc,readsym(sym));
|
||||
else
|
||||
tp = snalloc(type,sc,readshort(),0,0);
|
||||
break;
|
||||
|
||||
case CINT:
|
||||
tp = cnalloc(type,readshort());
|
||||
break;
|
||||
|
||||
case CLONG:
|
||||
tp = lcnalloc(type,readlong()); /* [vlh] 4.1 was two readshort's */
|
||||
break;
|
||||
|
||||
case CFLOAT: /* [vlh] 3.4 */
|
||||
tp = fpcnalloc(type,readlong()); /* [vlh] 4.1 was two readshort's */
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
case BFIELD:
|
||||
sc = readshort();
|
||||
if( tp = readtree() )
|
||||
tp = tnalloc(op,type,sc,0,tp,null);
|
||||
break;
|
||||
|
||||
default:
|
||||
if( BINOP(op) ) {
|
||||
if( !(tp=readtree()) )
|
||||
return(0);
|
||||
if( !(rtp=readtree()) )
|
||||
return(0);
|
||||
tp = tnalloc(op,type,0,0,tp,rtp);
|
||||
}
|
||||
else if( tp = readtree() )
|
||||
tp = tnalloc(op,type,0,0,tp,null);
|
||||
break;
|
||||
}
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* readfid - read source filename out of intermediate file */
|
||||
readfid()
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = &source[0];
|
||||
while( (*p = getc(&ibuf)) != '\n')
|
||||
p++;
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
/* readshort - reads an integer value from intermediate code*/
|
||||
short
|
||||
readshort()
|
||||
{
|
||||
register short c;
|
||||
register short i;
|
||||
|
||||
i = 0;
|
||||
while(1) {
|
||||
switch( c = getc(&ibuf) ) {
|
||||
|
||||
case '.':
|
||||
case '\n':
|
||||
return(i);
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
i <<= 4;
|
||||
i += (c-'0');
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
i <<= 4;
|
||||
i += (c-('a'-10));
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
i <<= 4;
|
||||
i += (c-('A'-10));
|
||||
break;
|
||||
|
||||
default:
|
||||
error("intermediate code error - %c,%d",c,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readlong - reads a long value from intermediate code*/
|
||||
long
|
||||
readlong() /* [vlh] 4.1 */
|
||||
{
|
||||
long l;
|
||||
register unsigned short w1, w2;
|
||||
register short c, onedot;
|
||||
|
||||
w2 = 0; onedot = 0;
|
||||
while(1) {
|
||||
switch( c = getc(&ibuf) ) {
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
w2 <<= 4;
|
||||
w2 += (c-'0');
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
w2 <<= 4;
|
||||
w2 += (c-('a'-10));
|
||||
break;
|
||||
|
||||
case '.':
|
||||
if (!onedot++) {
|
||||
w1 = w2;
|
||||
w2 = 0;
|
||||
continue;
|
||||
}
|
||||
case '\n':
|
||||
if (onedot) {
|
||||
l.hiword = w1;
|
||||
l.loword = w2;
|
||||
return(l);
|
||||
}
|
||||
default:
|
||||
error("intermediate code error - %c,%d",c,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* readsym - read a symbol from intermediate code*/
|
||||
char *readsym(sym)
|
||||
char *sym;
|
||||
{
|
||||
register short i, c;
|
||||
register char *s;
|
||||
|
||||
for( i = SSIZE, s = sym; (c=getc(&ibuf)) != '\n'; )
|
||||
if( --i >= 0 )
|
||||
*s++ = c;
|
||||
if( i > 0 )
|
||||
*s = '\0';
|
||||
return(sym);
|
||||
}
|
||||
|
||||
/* error - output an error message*/
|
||||
error(s,x1,x2,x3,x4,x5,x6)
|
||||
char *s;
|
||||
int x1, x2, x3, x4, x5, x6;
|
||||
{
|
||||
errcnt++;
|
||||
if( lineno != 0 )
|
||||
printf((char *)STDERR,"\"%s\", ** %d: ",source,lineno);
|
||||
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
|
||||
cputc('\n',STDERR);
|
||||
}
|
||||
|
||||
/* warning - output a warning message*/
|
||||
warning(s,x1,x2,x3,x4,x5,x6)
|
||||
char *s;
|
||||
int x1, x2, x3, x4, x5, x6;
|
||||
{
|
||||
if( lineno != 0 )
|
||||
printf((char *)STDERR,"\"%s\", ** %d: (warning) ",source,lineno);
|
||||
else
|
||||
printf((char *)STDERR,"(warning) ");
|
||||
printf((char *)STDERR,s,x1,x2,x3,x4,x5,x6);
|
||||
cputc('\n',STDERR);
|
||||
}
|
||||
|
||||
/* ferror - output error message and die*/
|
||||
ferror(s,x1,x2,x3,x4,x5,x6)
|
||||
char *s;
|
||||
int x1, x2, x3, x4, x5, x6;
|
||||
{
|
||||
error(s,x1,x2,x3,x4,x5,x6);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* tnalloc - allocate binary expression tree node*/
|
||||
/* returns ptr to node made.*/
|
||||
char *tnalloc(op,type,info,dummy,left,right)
|
||||
int op; /* operator*/
|
||||
int type; /* resultant node type*/
|
||||
int info; /* info field*/
|
||||
int dummy; /* dummy field - used to match pass1 args*/
|
||||
struct tnode *left; /* left sub-tree*/
|
||||
struct tnode *right; /* righst sub-tree*/
|
||||
{
|
||||
register struct tnode *tp;
|
||||
|
||||
tp = talloc(sizeof(*tp));
|
||||
tp->t_op = op;
|
||||
tp->t_type = type;
|
||||
tp->t_su = info; /* info for bit-field & condbr's*/
|
||||
tp->t_left = left;
|
||||
tp->t_right = right;
|
||||
return(tp);
|
||||
}
|
||||
|
||||
/* cnalloc - allocate constant expression tree node*/
|
||||
char *cnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
int value; /* value of constant*/
|
||||
{
|
||||
register struct conode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CINT;
|
||||
cp->t_type = type;
|
||||
cp->t_value = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* lcnalloc - allocate constant expression tree node*/
|
||||
char *lcnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
long value; /* value of constant*/
|
||||
{
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CLONG;
|
||||
cp->t_type = type;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* fpcnalloc - allocate constant expression tree node*/
|
||||
char *fpcnalloc(type,value) /* returns pointer to node alloced*/
|
||||
int type; /* type of constant*/
|
||||
long value; /* value of constant*/
|
||||
{ /* [vlh] 3.4 */
|
||||
register struct lconode *cp;
|
||||
|
||||
cp = talloc(sizeof(*cp));
|
||||
cp->t_op = CFLOAT;
|
||||
cp->t_type = type;
|
||||
cp->t_lvalue = value;
|
||||
return(cp);
|
||||
}
|
||||
|
||||
/* talloc - allocate expression tree area*/
|
||||
char *talloc(size) /* returns pointer to area alloced*/
|
||||
int size; /* number of bytes to alloc*/
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = opap;
|
||||
if( p + size >= &exprarea[EXPSIZE] )
|
||||
ferror("expression too complex");
|
||||
opap = p + size;
|
||||
return(p);
|
||||
}
|
||||
|
||||
/* symcopy - copy symbol*/
|
||||
symcopy(sym1,sym2) /* returns - none*/
|
||||
char *sym1; /* from symbol*/
|
||||
char *sym2; /* to symbol*/
|
||||
{
|
||||
register char *p, *q;
|
||||
register short i;
|
||||
|
||||
for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
||||
*q++ = (*p ? *p++ : '\0');
|
||||
}
|
||||
|
||||
/* usage - ouput usage message*/
|
||||
usage(calledby)
|
||||
char *calledby;
|
||||
{
|
||||
ferror("usage: %s icode link asm [-DLameco]",calledby);
|
||||
}
|
||||
|
||||
/* cputc - put a character to a file descriptor (used by error) */
|
||||
cputc(c, fn)
|
||||
char c;
|
||||
int fn;
|
||||
{
|
||||
#ifdef VERSADOS
|
||||
versaputchar(c);
|
||||
#else
|
||||
if (fn == STDERR)
|
||||
write(STDERR, &c, 1);
|
||||
else
|
||||
putchar(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* putchar - special version
|
||||
* This allows the use of printf for error messages, debugging
|
||||
* output and normal output.
|
||||
**/
|
||||
putchar(c) /* returns - none*/
|
||||
char c; /* character to output*/
|
||||
{
|
||||
if( dflag > 1 )
|
||||
write(1,&c,1); /*to standard output*/
|
||||
putc(c,&obuf); /*put to assembler file*/
|
||||
}
|
||||
|
||||
#ifdef VERSADOS
|
||||
|
||||
#define STDOUT 1
|
||||
|
||||
struct iob versfout { STDOUT, BSIZE, &versfout.cbuf[0]};
|
||||
|
||||
versaputchar(c)
|
||||
char c;
|
||||
{
|
||||
if (c == '\n') { /* end of line */
|
||||
if (versaflush()) /* write one line */
|
||||
return(-1);
|
||||
return(c);
|
||||
}
|
||||
|
||||
/* buffered output */
|
||||
if (versfout.cc <= 0) {
|
||||
versfout.cp = &(versfout.cbuf[0]);
|
||||
if (write(versfout.fd,versfout.cp,BSIZE) != BSIZE)
|
||||
return(-1);
|
||||
versfout.cc = BSIZE;
|
||||
}
|
||||
*(versfout.cp)++ = c;
|
||||
versfout.cc--;
|
||||
return(c);
|
||||
}
|
||||
|
||||
versaflush()
|
||||
{
|
||||
register short size, fildes;
|
||||
|
||||
if ((size = (BSIZE - versfout.cc)) == 0)
|
||||
return(0);
|
||||
versfout.cc = BSIZE;
|
||||
versfout.cp = &(versfout.cbuf[0]);
|
||||
fildes = (versfout.fd <= STDERR) ? 6 : versfout.fd;
|
||||
if (write(fildes,versfout.cp,size) < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
#else
|
||||
# ifdef VAX11
|
||||
getc(ibuf)
|
||||
struct iob *ibuf;
|
||||
{
|
||||
if (ibuf->cc <= 0) {
|
||||
ibuf->cp = &(ibuf->cbuf[0]);
|
||||
ibuf->cc = read(ibuf->fd,ibuf->cp,BSIZE);
|
||||
}
|
||||
if (ibuf->cc <= 0)
|
||||
return(-1);
|
||||
ibuf->cc--;
|
||||
return((int)(*(ibuf->cp)++)&0xff);
|
||||
}
|
||||
|
||||
fopen(fname,ibuf)
|
||||
char *fname;
|
||||
register struct iob *ibuf;
|
||||
{
|
||||
ibuf->cc = 0; /* no chars */
|
||||
ibuf->fd = open(fname,0);
|
||||
return(ibuf->fd);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
myfflush(mybuf)
|
||||
register struct iob *mybuf;
|
||||
{
|
||||
register i;
|
||||
|
||||
i = BSIZE - mybuf->cc;
|
||||
mybuf->cc = BSIZE;
|
||||
mybuf->cp = &(mybuf->cbuf[0]);
|
||||
if (write(mybuf->fd,mybuf->cp,i) != i)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef DRI
|
||||
printf(string,a,b,c,d,e,f,g)
|
||||
char *string;
|
||||
int a,b,c,d,e,f,g;
|
||||
{
|
||||
char area[256];
|
||||
register char *p;
|
||||
|
||||
sprintf(area,string,a,b,c,d,e,f,g);
|
||||
for(p = &area[0]; *p ; p++ )
|
||||
putchar(*p);
|
||||
}
|
||||
#endif
|
||||
|
||||
116
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/makefile
Normal file
116
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/makefile
Normal file
@@ -0,0 +1,116 @@
|
||||
CC = cc
|
||||
C68 = nc68
|
||||
VAXOBJS = vaxobj/canon.o \
|
||||
vaxobj/codegen.o \
|
||||
vaxobj/interf.o \
|
||||
vaxobj/main.o \
|
||||
vaxobj/optab.o \
|
||||
vaxobj/putexpr.o \
|
||||
vaxobj/smatch.o \
|
||||
vaxobj/sucomp.o \
|
||||
vaxobj/tabl.o \
|
||||
vaxobj/util.o \
|
||||
vaxobj/cskels.o
|
||||
C68OBJS = 68obj/canon.o \
|
||||
68obj/codegen.o \
|
||||
68obj/interf.o \
|
||||
68obj/main.o \
|
||||
68obj/optab.o \
|
||||
68obj/putexpr.o \
|
||||
68obj/smatch.o \
|
||||
68obj/sucomp.o \
|
||||
68obj/tabl.o \
|
||||
68obj/util.o \
|
||||
68obj/cskels.o
|
||||
CFLAGS = -O -w -DVAX11 -DDEBUG
|
||||
C68FLAGS = -L -r -DMC68000 -DDEBUG -t0 -t1
|
||||
LIB = -lV6
|
||||
C68LIB = -l6
|
||||
.IGNORE:
|
||||
|
||||
vax: ${VAXOBJS}
|
||||
mkver -e "Code Generator -"
|
||||
${CC} ${CFLAGS} version.c ${VAXOBJS} -o c168.vax ${LIB}
|
||||
|
||||
c168: ${C68OBJS}
|
||||
mkver -e "Code Generator -"
|
||||
${C68} -r ${C68FLAGS} version.c ${C68OBJS} -o c168.68 ${C68LIB}
|
||||
setstack c168.68 8000 8000
|
||||
|
||||
2k: ${C68OBJS}
|
||||
mkver -e "Code Generator -"
|
||||
${C68} -n2 -r ${C68FLAGS} version.c ${C68OBJS} -o c168.2k ${C68LIB}
|
||||
setstack c168.2k 8000 8000
|
||||
|
||||
4k: ${C68OBJS}
|
||||
mkver -e "Code Generator -"
|
||||
${C68} -n -r ${C68FLAGS} version.c ${C68OBJS} -o c168.4k ${C68LIB}
|
||||
setstack c168.4k 8000 8000
|
||||
|
||||
all: vax 4k
|
||||
|
||||
vaxobj/canon.o: canon.c
|
||||
${CC} ${CFLAGS} -c canon.c;mv -f canon.o vaxobj/canon.o
|
||||
|
||||
vaxobj/codegen.o: codegen.c
|
||||
${CC} ${CFLAGS} -c codegen.c;mv -f codegen.o vaxobj/codegen.o
|
||||
|
||||
vaxobj/interf.o: interf.c
|
||||
${CC} ${CFLAGS} -c interf.c;mv -f interf.o vaxobj/interf.o
|
||||
|
||||
vaxobj/main.o: main.c
|
||||
${CC} ${CFLAGS} -c main.c;mv -f main.o vaxobj/main.o
|
||||
|
||||
vaxobj/optab.o: optab.c
|
||||
${CC} ${CFLAGS} -c optab.c;mv -f optab.o vaxobj/optab.o
|
||||
|
||||
vaxobj/putexpr.o: putexpr.c
|
||||
${CC} ${CFLAGS} -c putexpr.c;mv -f putexpr.o vaxobj/putexpr.o
|
||||
|
||||
vaxobj/smatch.o: smatch.c
|
||||
${CC} ${CFLAGS} -c smatch.c;mv -f smatch.o vaxobj/smatch.o
|
||||
|
||||
vaxobj/sucomp.o: sucomp.c
|
||||
${CC} ${CFLAGS} -c sucomp.c;mv -f sucomp.o vaxobj/sucomp.o
|
||||
|
||||
vaxobj/tabl.o: tabl.c
|
||||
${CC} ${CFLAGS} -c tabl.c;mv -f tabl.o vaxobj/tabl.o
|
||||
|
||||
vaxobj/util.o: util.c
|
||||
${CC} ${CFLAGS} -c util.c;mv -f util.o vaxobj/util.o
|
||||
|
||||
vaxobj/cskels.o: cskels.c
|
||||
${CC} ${CFLAGS} -c cskels.c;mv -f cskels.o vaxobj/cskels.o
|
||||
|
||||
68obj/canon.o: canon.c
|
||||
${C68} ${C68FLAGS} -c canon.c;mv -f canon.o 68obj/canon.o
|
||||
|
||||
68obj/codegen.o: codegen.c
|
||||
${C68} ${C68FLAGS} -c codegen.c;mv -f codegen.o 68obj/codegen.o
|
||||
|
||||
68obj/interf.o: interf.c
|
||||
${C68} ${C68FLAGS} -c interf.c;mv -f interf.o 68obj/interf.o
|
||||
|
||||
68obj/main.o: main.c
|
||||
${C68} ${C68FLAGS} -c main.c;mv -f main.o 68obj/main.o
|
||||
|
||||
68obj/optab.o: optab.c
|
||||
${C68} ${C68FLAGS} -c optab.c;mv -f optab.o 68obj/optab.o
|
||||
|
||||
68obj/putexpr.o: putexpr.c
|
||||
${C68} ${C68FLAGS} -c putexpr.c;mv -f putexpr.o 68obj/putexpr.o
|
||||
|
||||
68obj/smatch.o: smatch.c
|
||||
${C68} ${C68FLAGS} -c smatch.c;mv -f smatch.o 68obj/smatch.o
|
||||
|
||||
68obj/sucomp.o: sucomp.c
|
||||
${C68} ${C68FLAGS} -c sucomp.c;mv -f sucomp.o 68obj/sucomp.o
|
||||
|
||||
68obj/tabl.o: tabl.c
|
||||
${C68} ${C68FLAGS} -c tabl.c;mv -f tabl.o 68obj/tabl.o
|
||||
|
||||
68obj/util.o: util.c
|
||||
${C68} ${C68FLAGS} -c util.c;mv -f util.o 68obj/util.o
|
||||
|
||||
68obj/cskels.o: cskels.c
|
||||
${C68} ${C68FLAGS} -c cskels.c;mv -f cskels.o 68obj/cskels.o
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
CC = c68
|
||||
OBJS = canon.o codegen.o interf.o main.o optab.o putexpr.o smatch.o sucomp.o \
|
||||
tabl.o util.o cskels.o
|
||||
CFLAGS = -L -r
|
||||
LIB = -l6
|
||||
|
||||
st: ${OBJS}
|
||||
@mkver -e "code generator - "
|
||||
${CC} ${CFLAGS} -n ${OBJS} version.c ${LIB} -o c168.st
|
||||
@setstack c168.st 8192 8192 ; size c168.st
|
||||
|
||||
c068: ${OBJS}
|
||||
@mkver -e "code generator - "
|
||||
${CC} ${CFLAGS} ${OBJS} version.c ${LIB} -o c168.68
|
||||
@setstack c168.68 8192 8192 ; size c168.68
|
||||
16
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/mout
Normal file
16
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/mout
Normal file
@@ -0,0 +1,16 @@
|
||||
>mkver -e "C68 Code Generator -"
|
||||
char *compiled = "@(#) C68 Code Generator - Wed Sep 7 16:05 1983";
|
||||
>c68 -S -L -DVERSADOS -DMC68000 canon.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 codegen.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 cskels.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 interf.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 main.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 optab.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 putexpr.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 smatch.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 sucomp.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 tabl.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 util.c
|
||||
>c68 -S -L -DVERSADOS -DMC68000 version.c
|
||||
>mv *.s vst
|
||||
>
|
||||
323
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/optab.c
Normal file
323
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/optab.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
#define I_NULL 0
|
||||
#define I_ADD 1
|
||||
#define I_INC 2
|
||||
#define I_SUB 3
|
||||
#define I_DEC 4
|
||||
#define I_MULS 5
|
||||
#define I_MULU 6
|
||||
#define I_DIVS 7
|
||||
#define I_DIVU 8
|
||||
#define I_ASR 9
|
||||
#define I_LSR 10
|
||||
#define I_ASL 11
|
||||
#define I_LSL 12
|
||||
#define I_AND 13
|
||||
#define I_OR 14
|
||||
#define I_EOR 15
|
||||
#define I_NEG 16
|
||||
#define I_NOT 17
|
||||
#define I_MOVE 18
|
||||
#define I_CLR 19
|
||||
#define I_CMP 20
|
||||
#define I_TST 21
|
||||
#define I_LMUL 22
|
||||
#define I_LDIV 23
|
||||
#define I_LREM 24
|
||||
#define I_LEML 25
|
||||
#define I_LERM 27
|
||||
#define I_BEQ 28
|
||||
#define I_BNE 29
|
||||
#define I_BGT 30
|
||||
#define I_BGE 31
|
||||
#define I_BLT 32
|
||||
#define I_BLE 33
|
||||
#define I_BLS 34
|
||||
#define I_BLO 35
|
||||
#define I_BCC 36
|
||||
#define I_BHI 37
|
||||
#define I_BRA 38
|
||||
#define I_NOP 39
|
||||
#define I_BTST 40
|
||||
|
||||
char *mnemonics[] = {
|
||||
"",
|
||||
"add",
|
||||
"inc",
|
||||
"sub",
|
||||
"dec",
|
||||
"muls",
|
||||
"mulu",
|
||||
"divs",
|
||||
"divu",
|
||||
"asr",
|
||||
"lsr",
|
||||
"asl",
|
||||
"lsl",
|
||||
"and",
|
||||
"or",
|
||||
"eor",
|
||||
"neg",
|
||||
"not",
|
||||
"move",
|
||||
"clr",
|
||||
"cmp",
|
||||
"tst",
|
||||
"lmul",
|
||||
"_ldiv",
|
||||
"lrem",
|
||||
"almul",
|
||||
"aldiv",
|
||||
"alrem",
|
||||
"beq",
|
||||
"bne",
|
||||
"bgt",
|
||||
"bge",
|
||||
"blt",
|
||||
"ble",
|
||||
"bls",
|
||||
"blo",
|
||||
"bcc",
|
||||
"bhi",
|
||||
"jmp",
|
||||
"*nop",
|
||||
"btst",
|
||||
};
|
||||
|
||||
#define FE_EQOP 1
|
||||
#define FE_ASSIGN 2
|
||||
#define FE_EQSHFT 3
|
||||
#define FE_EQXOR 4
|
||||
#define FE_EQADDR 5
|
||||
#define FC_FIX 6
|
||||
#define FC_REL 7
|
||||
#define FC_BTST 8
|
||||
#define FS_OP 9
|
||||
#define FS_ITL 10
|
||||
#define FS_LD 11
|
||||
#define FR_ADD 12
|
||||
#define FR_MULT 13
|
||||
#define FR_DIV 14
|
||||
#define FR_SHFT 15
|
||||
#define FR_XOR 16
|
||||
#define FR_NEG 17
|
||||
#define FR_EQOP 18
|
||||
#define FR_POSTOP 19
|
||||
#define FR_ASSIGN 20
|
||||
#define FR_EQMULT 21
|
||||
#define FR_EQDIV 22
|
||||
#define FR_EQSHFT 23
|
||||
#define FR_EQXOR 24
|
||||
#define FR_CALL 25
|
||||
#define FR_ITL 26
|
||||
#define FR_LTI 27
|
||||
#define FR_LD 28
|
||||
#define FR_EQADDR 29
|
||||
#define FR_EQNOT 30
|
||||
#define FE_EQNOT 31
|
||||
#define FR_DOCAST 32
|
||||
#define FS_DOCAST 33
|
||||
#define FR_FTOL 34
|
||||
#define FR_LTOF 35
|
||||
#define FR_FTOI 36
|
||||
#define FR_ITOF 37
|
||||
#define FE_EQMULT 38
|
||||
#define FE_EQDIV 39
|
||||
#define FE_EQMOD 40
|
||||
#define FR_TOCHAR 41
|
||||
|
||||
extern struct skeleton /*char /* really struct skeleton.... */
|
||||
fe_eqop[], /* 1=FE_EQOP */
|
||||
fe_assign[], /* 2=FE_ASSIGN */
|
||||
fe_eqshft[], /* 3=FE_EQSHFT */
|
||||
fe_eqxor[], /* 4=FE_EQXOR */
|
||||
fe_eqaddr[], /* 5=FE_EQADDR */
|
||||
fc_fix[], /* 6=FC_FIX */
|
||||
fc_rel[], /* 7=FC_REL */
|
||||
fc_btst[], /* 8=FC_BTST */
|
||||
fs_op[], /* 9=FS_OP */
|
||||
fs_itl[], /* 10=FS_ITL */
|
||||
fs_ld[], /* 11=FS_LD */
|
||||
fr_op[], /* 12=FR_OP */
|
||||
fr_mult[], /* 13=FR_MULT */
|
||||
fr_div[], /* 14=FR_DIV */
|
||||
fr_shft[], /* 15=FR_SHFT */
|
||||
fr_xor[], /* 16=FR_XOR */
|
||||
fr_neg[], /* 17=FR_NEG */
|
||||
fr_eqop[], /* 18=FR_EQOP */
|
||||
fr_postop[], /* 19=FR_POSTOP */
|
||||
fr_assign[], /* 20=FR_ASSIGN */
|
||||
fr_eqmult[], /* 21=FR_EQMULT */
|
||||
fr_eqdiv[], /* 22=FR_EQDIV */
|
||||
fr_eqshft[], /* 23=FR_EQSHFT */
|
||||
fr_eqxor[], /* 23=FR_EQXOR */
|
||||
fr_call[], /* 24=FR_CALL */
|
||||
fr_itl[], /* 25=FR_ITL */
|
||||
fr_lti[], /* 26=FR_LTI */
|
||||
fr_ld[], /* 27=FR_LD */
|
||||
fr_eqaddr[], /* 28=FR_EQADDR */
|
||||
fr_eqnot[], /* 29=FR_EQNOT */
|
||||
fe_eqnot[], /* 30=FE_EQNOT */
|
||||
fr_docast[], /* 31=FR_DOCAST */
|
||||
fs_docast[], /* 32=FS_DOCAST */
|
||||
fr_ftol[], /* 34=FE_FTOL */
|
||||
fr_ltof[], /* 35=FE_LTOF */
|
||||
fr_ftoi[], /* 36=FE_FTOI */
|
||||
fr_itof[], /* 37=FE_ITOF */
|
||||
fe_eqmult[], /* 38=FE_EQMULT */
|
||||
fe_eqdiv[], /* 39=FE_EQDIV */
|
||||
fe_eqmod[], /* 40=FE_EQMOD */
|
||||
fr_tochar[]; /* 41=FR_TOCHAR */
|
||||
|
||||
char *codeskels[] = {
|
||||
0, /*NULL*/
|
||||
fe_eqop, /*1=FE_EQOP*/
|
||||
fe_assign, /*2=FE_ASSIGN*/
|
||||
fe_eqshft, /*3=FE_EQSHFT*/
|
||||
fe_eqxor, /*4=FE_EQXOR*/
|
||||
fe_eqaddr, /*5=FE_EQADDR*/
|
||||
fc_fix, /*6=FC_FIX*/
|
||||
fc_rel, /*7=FC_REL*/
|
||||
fc_btst, /*8=FC_BTST*/
|
||||
fs_op, /*9=FS_OP*/
|
||||
fs_itl, /*10=FS_ITL*/
|
||||
fs_ld, /*11=FS_LD*/
|
||||
fr_op, /*12=FR_OP*/
|
||||
fr_mult, /*13=FR_MULT*/
|
||||
fr_div, /*14=FR_DIV*/
|
||||
fr_shft, /*15=FR_SHFT*/
|
||||
fr_xor, /*16=FR_XOR*/
|
||||
fr_neg, /*17=FR_NEG*/
|
||||
fr_eqop, /*18=FR_EQOP*/
|
||||
fr_postop, /*19=FR_POSTOP*/
|
||||
fr_assign, /*20=FR_ASSIGN*/
|
||||
fr_eqmult, /*21=FR_EQMULT*/
|
||||
fr_eqdiv, /*22=FR_EQDIV*/
|
||||
fr_eqshft, /*23=FR_EQSHFT*/
|
||||
fr_eqxor, /*24=FR_EQXOR*/
|
||||
fr_call, /*25=FR_CALL*/
|
||||
fr_itl, /*26=FR_ITL*/
|
||||
fr_lti, /*27=FR_LTI*/
|
||||
fr_ld, /*28=FE_LD*/
|
||||
fr_eqaddr, /*29=FE_EQADDR*/
|
||||
fr_eqnot, /*30=FE_EQNOT*/
|
||||
fe_eqnot, /*31=FE_EQNOT*/
|
||||
fr_docast, /*32=FE_DOCAST*/
|
||||
fs_docast, /*33=FS_DOCAST*/
|
||||
fr_ftol, /*34=FE_FTOL*/
|
||||
fr_ltof, /*35=FE_LTOF*/
|
||||
fr_ftoi, /*36=FE_FTOI*/
|
||||
fr_itof, /*37=FE_ITOF*/
|
||||
fe_eqmult, /*38=FE_EQMULT*/
|
||||
fe_eqdiv, /*39=FE_EQDIV*/
|
||||
fe_eqmod, /*40=FE_EQMOD*/
|
||||
fr_tochar, /*41=FR_TOCHAR*/
|
||||
};
|
||||
/*
|
||||
*This is the major table directing the code generation process.
|
||||
*It is indexed by an O_op operator, which is obtained from the
|
||||
*opinfo table for an intermediate code operator. The actual
|
||||
*code skeleton macros are in cskels.c, which are in a linked
|
||||
*list in order of decreasing order of difficulty.
|
||||
*/
|
||||
char optab[][6] = {
|
||||
|
||||
/* I I2 effect cc's stack register*/
|
||||
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*0=NULL*/
|
||||
I_ADD, I_INC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*1=ADD*/
|
||||
I_SUB, I_DEC, I_NULL, FC_FIX, FS_OP, FR_ADD, /*2=SUB*/
|
||||
I_MULS, I_MULU, I_NULL, FC_FIX, I_NULL, FR_MULT, /*3=MULT*/
|
||||
I_DIVS, I_DIVU, I_NULL, FC_FIX, I_NULL, FR_DIV, /*4=DIV*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*5=MOD*/
|
||||
I_ASR, I_LSR, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*6=RSH*/
|
||||
I_ASL, I_LSL, I_NULL, FC_FIX, I_NULL, FR_SHFT, /*7=LSH*/
|
||||
I_AND, I_AND, I_NULL, FC_FIX, FS_OP, FR_ADD, /*8=AND*/
|
||||
I_OR, I_OR, I_NULL, FC_FIX, FS_OP, FR_ADD, /*9=OR*/
|
||||
I_EOR, I_EOR, I_NULL, FC_FIX, I_NULL, FR_XOR, /*10=XOR*/
|
||||
I_NULL, I_NULL, I_NULL, FC_FIX, I_NULL, I_NULL, /*11=NOT*/
|
||||
I_NEG, I_NEG, I_NULL, FC_FIX, I_NULL, FR_NEG, /*12=NEG*/
|
||||
I_NOT, I_NOT, I_NULL, I_NULL, I_NULL, FR_NEG, /*13=COMPL*/
|
||||
I_SUB, I_DEC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*14=PREDEC*/
|
||||
I_ADD, I_INC, FE_EQOP, FC_FIX, I_NULL, FR_EQOP, /*15=PREINC*/
|
||||
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*16=POSTDEC*/
|
||||
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_POSTOP, /*17=POSTINC*/
|
||||
I_MOVE, I_CLR, FE_ASSIGN, I_NULL, I_NULL, FR_ASSIGN, /*18=ASSIGN*/
|
||||
I_ADD, I_INC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*19=EQADD*/
|
||||
I_SUB, I_DEC, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*20=EQSUB*/
|
||||
I_MULS, I_MULU, FE_EQMULT, FC_FIX, I_NULL, FR_EQMULT, /*21=EQMULT*/
|
||||
I_DIVS, I_DIVU, FE_EQDIV, FC_FIX, I_NULL, FR_EQDIV, /*22=EQDIV*/
|
||||
I_DIVS, I_DIVU, FE_EQMOD, I_NULL, I_NULL, FR_EQDIV, /*23=EQMOD*/
|
||||
I_ASR, I_LSR, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*24=EQRSH*/
|
||||
I_ASL, I_LSL, FE_EQSHFT, I_NULL, I_NULL, FR_EQSHFT, /*25=EQLSH*/
|
||||
I_AND, I_AND, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*26=EQAND*/
|
||||
I_OR, I_OR, FE_EQOP, I_NULL, I_NULL, FR_EQOP, /*27=EQOR*/
|
||||
I_EOR, I_EOR, FE_EQXOR, FC_FIX, I_NULL, FR_EQXOR, /*28=EQXOR*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_CALL, /*29=FJSR*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*30=EQUALS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*31=NEQUALS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*32=GREAT*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*33=GREATEQ*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*34=LESS*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, I_NULL, I_NULL, /*35=LESSEQ*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, FS_ITL, FR_ITL, /*36=INT2L*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTI, /*37=LONG2I*/
|
||||
I_BTST, I_BTST, I_NULL, FC_BTST, I_NULL, I_NULL, /*38=BTST*/
|
||||
I_CMP, I_TST, I_NULL, FC_REL, FS_LD, FR_LD, /*39=LOAD*/
|
||||
I_MULS, I_MULU, I_NULL, I_NULL, I_NULL, FR_MULT, /*40=LMULT*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*41=LDIV*/
|
||||
I_DIVS, I_DIVU, I_NULL, I_NULL, I_NULL, FR_DIV, /*42=LMOD*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*43=NULL*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*44=NULL*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*45=NULL*/
|
||||
I_NULL, I_NULL, FE_EQADDR, I_NULL, I_NULL, FR_EQADDR, /*46=EQADDR*/
|
||||
I_NOT, I_NOT, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*47=EQNOT*/
|
||||
I_NEG, I_NEG, FE_EQNOT, I_NULL, I_NULL, FR_EQNOT, /*48=EQNEG*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, FS_DOCAST, FR_DOCAST, /*49=DOCAST*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, /*50=STASSIGN*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_LTOF, /*51=LONG2F*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOL, /*52=FLOAT2L*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_ITOF, /*53=INT2F*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_FTOI, /*54=FLOAT2I*/
|
||||
I_NULL, I_NULL, I_NULL, I_NULL, I_NULL, FR_TOCHAR, /*55=TOCHAR*/
|
||||
};
|
||||
|
||||
|
||||
/*this maps comparison operators and comparison types into the*/
|
||||
/*actual branch opcode used.*/
|
||||
char brtab[][2] = {
|
||||
I_BEQ, I_BEQ, /*EQUALS*/
|
||||
I_BNE, I_BNE, /*NEQUALS*/
|
||||
I_BGT, I_BHI, /*GREAT*/
|
||||
I_BGE, I_BCC, /*GREATEQ*/
|
||||
I_BLT, I_BLO, /*LESS*/
|
||||
I_BLE, I_BLS, /*LESSEQ*/
|
||||
};
|
||||
|
||||
/*turns !x>y into x<=y*/
|
||||
short invrel[] = { NEQUALS, EQUALS, LESSEQ, LESS, GREATEQ, GREAT };
|
||||
|
||||
/*turns x>y into y<=x*/
|
||||
short swaprel[] = { EQUALS, NEQUALS, LESS, LESSEQ, GREAT, GREATEQ };
|
||||
|
||||
/*code skeleton built-in strings*/
|
||||
char *strtab[] = {
|
||||
"move", /*MOV*/
|
||||
"move.l", /*MOVL*/
|
||||
"jsr", /*JSR*/
|
||||
"clr", /*CLR*/
|
||||
"clr.l", /*CLRL*/
|
||||
"ext.w", /*EXTW*/
|
||||
"ext.l", /*EXTL*/
|
||||
"lea", /*LEA*/
|
||||
"(sp)", /*STK*/
|
||||
};
|
||||
252
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/putexpr.c
Normal file
252
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/putexpr.c
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
|
||||
char invalid[] = "INVALID";
|
||||
|
||||
char *opname[] = {
|
||||
invalid, /*0*/
|
||||
"+", /*1*/
|
||||
"-", /*2*/
|
||||
"*", /*3*/
|
||||
"/", /*4*/
|
||||
"%", /*5*/
|
||||
">>", /*6*/
|
||||
"<<", /*7*/
|
||||
"&", /*8*/
|
||||
"|", /*9*/
|
||||
"^", /*10*/
|
||||
"!", /*11*/
|
||||
"U-", /*12*/
|
||||
"~", /*13*/
|
||||
"--p", /*14*/
|
||||
"++p", /*15*/
|
||||
"p--", /*16*/
|
||||
"p++", /*17*/
|
||||
"=", /*18*/
|
||||
"+=", /*19*/
|
||||
"-=", /*20*/
|
||||
"*=", /*21*/
|
||||
"/=", /*22*/
|
||||
"%=", /*23*/
|
||||
">>=", /*24*/
|
||||
"<<=", /*25*/
|
||||
"&=", /*26*/
|
||||
"|=", /*27*/
|
||||
"^=", /*28*/
|
||||
"jsr", /*29*/
|
||||
"==", /*30*/
|
||||
"!=", /*31*/
|
||||
">", /*32*/
|
||||
">=", /*33*/
|
||||
"<", /*34*/
|
||||
"<=", /*35*/
|
||||
"int->long", /*36*/
|
||||
"long->int", /*37*/
|
||||
"btst", /*38*/
|
||||
"load", /*39*/
|
||||
"long*", /*40*/
|
||||
"long/", /*41*/
|
||||
"long%", /*42*/
|
||||
"long*=", /*43*/
|
||||
"long/=", /*44*/
|
||||
"long%=", /*45*/
|
||||
"=addr", /*46*/
|
||||
"=not", /*47*/
|
||||
"=neg", /*48*/
|
||||
"docast", /*49*/
|
||||
"st=", /*50*/
|
||||
"long->float", /*51*/
|
||||
"float->long", /*52*/
|
||||
"int->float", /*53*/
|
||||
"float->int", /*54*/
|
||||
"tochar", /*55*/
|
||||
invalid, /*56*/
|
||||
invalid, /*57*/
|
||||
invalid, /*58*/
|
||||
invalid, /*59*/
|
||||
"U&", /*60 ADDR*/
|
||||
"U*", /*61 INDR*/
|
||||
"&&", /*62*/
|
||||
"||", /*63*/
|
||||
"?", /*64*/
|
||||
":", /*65*/
|
||||
",", /*66*/
|
||||
"cint", /*67*/
|
||||
"clong", /*68*/
|
||||
"symbol", /*69*/
|
||||
"++a", /*70*/
|
||||
"a--", /*71*/
|
||||
"call", /*72*/
|
||||
"call()", /*73*/
|
||||
"bitfield", /*74*/
|
||||
"if", /*75*/
|
||||
"init", /*76*/
|
||||
"loadR0", /*77*/
|
||||
"divlong", /*78*/
|
||||
};
|
||||
#ifdef DEBUG
|
||||
|
||||
char *types[] = {
|
||||
"typeless-invalid", /*0=TYPELESS*/
|
||||
"char", /*1=CHAR*/
|
||||
"short", /*2=SHORT*/
|
||||
"int", /*3=INT*/
|
||||
"long", /*4=LONG*/
|
||||
"uchar-invalid", /*5=UCHAR*/
|
||||
"ushort-invalid", /*6=USHORT*/
|
||||
"uint", /*7=UINT*/
|
||||
"ulong-invalid", /*8=ULONG*/
|
||||
"float", /*9=FLOAT*/
|
||||
"double", /*10=DOUBLE*/
|
||||
"struct", /*11=STRUCT*/
|
||||
invalid, /*12=undefined*/
|
||||
invalid, /*13=undefined*/
|
||||
invalid, /*14=undefined*/
|
||||
invalid, /*15=undefined*/
|
||||
};
|
||||
|
||||
char *suvals[] = {
|
||||
"zero",
|
||||
"one",
|
||||
"quick",
|
||||
"small",
|
||||
"constant",
|
||||
"Areg",
|
||||
"Dreg",
|
||||
"addressable",
|
||||
"loadable",
|
||||
"easy",
|
||||
"hard",
|
||||
"veryhard",
|
||||
};
|
||||
|
||||
short level;
|
||||
|
||||
putexpr(name,tp)
|
||||
char *name;
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("%s\n",name);
|
||||
putsexpr(tp);
|
||||
}
|
||||
|
||||
putsexpr(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
level++;
|
||||
outlevel();
|
||||
printf("%s ",opname[tp->t_op]);
|
||||
if( tp->t_op == BFIELD || tp->t_op == IFGOTO ) {
|
||||
if( tp->t_op == BFIELD )
|
||||
printf("off=%d len=%d\n",(tp->t_su>>8)&0377,tp->t_su&0377);
|
||||
else
|
||||
printf("%s goto L%d\n",tp->t_type?"TRUE":"FALSE",tp->t_su);
|
||||
putsexpr(tp->t_left);
|
||||
level--;
|
||||
return;
|
||||
}
|
||||
puttsu(tp);
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case DCLONG:
|
||||
case CLONG:
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_lvalue.hiword,tp->t_lvalue.loword);
|
||||
break;
|
||||
|
||||
case CINT:
|
||||
printf(" %d\n",tp->t_value);
|
||||
break;
|
||||
|
||||
case AUTODEC:
|
||||
case AUTOINC:
|
||||
printf(" R%d\n",tp->t_reg);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
printf(" R%d",tp->t_reg);
|
||||
break;
|
||||
|
||||
case CINDR:
|
||||
printf(" %d\n",tp->t_offset);
|
||||
break;
|
||||
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
printf(" %x.%x\n",tp->t_offset,tp->t_ssp);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf(" %d(R%d)",tp->t_offset,tp->t_reg);
|
||||
break;
|
||||
|
||||
case EXTERNAL:
|
||||
case EXTOFF:
|
||||
printf(" %s+%d",tp->t_symbol,tp->t_offset);
|
||||
if( tp->t_sc == EXTOFF )
|
||||
printf("(R%d)",tp->t_reg);
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
case STATOFF:
|
||||
printf(" L%d+%d",tp->t_label,tp->t_offset);
|
||||
if( tp->t_sc == STATOFF )
|
||||
printf("(R%d)",tp->t_reg);
|
||||
break;
|
||||
|
||||
case INDEXED:
|
||||
printf(" %d(R%d,R%d)",tp->t_offset,tp->t_reg,tp->t_xreg);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
break;
|
||||
|
||||
case IFGOTO:
|
||||
putsexpr(tp->t_left);
|
||||
break;
|
||||
|
||||
default:
|
||||
putchar('\n');
|
||||
putsexpr(tp->t_left);
|
||||
if( BINOP(tp->t_op) )
|
||||
putsexpr(tp->t_right);
|
||||
break;
|
||||
}
|
||||
level--;
|
||||
}
|
||||
|
||||
outlevel()
|
||||
{
|
||||
register short i;
|
||||
|
||||
for( i = 0; i < level; i++ ) {
|
||||
putchar(' ');putchar(' ');putchar(' ');putchar(' ');
|
||||
}
|
||||
}
|
||||
|
||||
puttsu(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register short i;
|
||||
|
||||
if( SUPTYPE(tp->t_type) )
|
||||
putchar('*');
|
||||
printf("%s ",types[BTYPE(tp->t_type)]);
|
||||
if( tp->t_su != 0 || (tp->t_op == CINT && tp->t_value == 0) ) {
|
||||
i = tp->t_su >> 8;
|
||||
if( i > 15 || i < 0 )
|
||||
printf("INVALID");
|
||||
else
|
||||
printf("%s",suvals[tp->t_su>>8]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
535
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/smatch.c
Normal file
535
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/smatch.c
Normal file
@@ -0,0 +1,535 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
/* Code Skeleton expansion and matching */
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
#define SK_TYPE(x) (x&017)
|
||||
|
||||
/* expand - code skeleton expansion*/
|
||||
/* Handles the expansion of code skeleton macros.*/
|
||||
expand(tp,cookie,freg,skp) /* returns register result is in*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int cookie; /* goal of expression tree*/
|
||||
int freg; /* register to leave results in*/
|
||||
struct skeleton *skp; /* pointer to code skeleton*/
|
||||
{
|
||||
register short op, nreg, reg;
|
||||
register short c;
|
||||
register short extf, i2f;
|
||||
register struct tnode *ltp, *rtp;
|
||||
register char *p;
|
||||
register short i, sreg, flag, subtrees, scookie;
|
||||
register char *macro;
|
||||
|
||||
/**
|
||||
* This is a kludge because not all of the arithmetic operators
|
||||
* will work on address registers - the 68000 clone strikes again
|
||||
**/
|
||||
op = tp->t_op;
|
||||
#ifdef DEBUG
|
||||
if(eflag) printf("expand op=%d left=%x right=%x skp=%lo\n",op,
|
||||
skp->sk_left,skp->sk_right,skp);
|
||||
#endif
|
||||
if(((op>=MULT && op<=COMPL) || (op>=LMULT && op<=LMOD)) || tp->t_type==CHAR)
|
||||
freg = DREG(freg); /* [vlh] 4.1 added UMINUS, COMPL, LMUL, LDIV */
|
||||
macro = skp->sk_def;
|
||||
i2f = extf = 0;
|
||||
rtp = ltp = tp->t_left;
|
||||
subtrees = 1;
|
||||
if( BINOP(op) ) {
|
||||
subtrees++;
|
||||
rtp = tp->t_right;
|
||||
if( (LONGORPTR(tp->t_type)) && (op == DIV || op == MOD ||
|
||||
(op != MULT && (ISDREG(freg)) &&
|
||||
!(LONGORPTR(ltp->t_type)) && !(LONGORPTR(rtp->t_type)))) )
|
||||
extf++;
|
||||
switch( op ) {
|
||||
|
||||
case RSH:
|
||||
case LSH:
|
||||
case EQLSH:
|
||||
case EQRSH:
|
||||
if( UNSIGN(ltp->t_type) )
|
||||
i2f++;
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
case EQMULT:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case EQDIV:
|
||||
case EQMOD:
|
||||
if( UNSIGN(ltp->t_type) || UNSIGN(rtp->t_type) )
|
||||
i2f++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nreg = freg + 1;
|
||||
while( c = *macro++ ) {
|
||||
c &= 0xff;
|
||||
switch( c ) {
|
||||
|
||||
default:
|
||||
putchar(c);
|
||||
break;
|
||||
|
||||
case POP:
|
||||
stacksize--;
|
||||
printf("(sp)+");
|
||||
break;
|
||||
|
||||
case POP4:
|
||||
stacksize--;
|
||||
popstack(4);
|
||||
break;
|
||||
|
||||
case POP8:
|
||||
stacksize -= 2;
|
||||
popstack(8);
|
||||
break;
|
||||
|
||||
case PSH:
|
||||
if( cookie == FORSP ) /*don't affect sp*/
|
||||
printf("(sp)");
|
||||
else
|
||||
printf("-(sp)");
|
||||
stacksize++;
|
||||
break;
|
||||
|
||||
case MOV:
|
||||
case MOVL:
|
||||
case JSR:
|
||||
case CLR:
|
||||
case CLRL:
|
||||
case EXTW:
|
||||
case EXTL:
|
||||
case LEA:
|
||||
case STK:
|
||||
printf("%s",strtab[c-128]);
|
||||
break;
|
||||
|
||||
case OPCALL:
|
||||
op_expand(op,tp->t_type,ltp->t_type);
|
||||
break;
|
||||
|
||||
case TLEFT:
|
||||
outtype( LEAFOP(op) ? tp->t_type : ltp->t_type );
|
||||
break;
|
||||
|
||||
case TLEFTL:
|
||||
outatype( LEAFOP(op) ? tp->t_type : ltp->t_type );
|
||||
break;
|
||||
|
||||
case TEITHER:
|
||||
if( LONGORPTR(rtp->t_type) || LONGORPTR(ltp->t_type) )
|
||||
outtype(LONG);
|
||||
break;
|
||||
|
||||
case TRIGHT:
|
||||
outtype(rtp->t_type);
|
||||
break;
|
||||
|
||||
case OP:
|
||||
case AOP:
|
||||
if( c == AOP || i2f )
|
||||
i = optab[op][1];
|
||||
else
|
||||
i = optab[op][0];
|
||||
printf(mnemonics[i]);
|
||||
break;
|
||||
|
||||
case LADDR:
|
||||
case RADDR:
|
||||
p = ((c==RADDR) ? rtp : ltp);
|
||||
outaexpr(p,IMMED);
|
||||
break;
|
||||
|
||||
case CR:
|
||||
outcreg(freg);
|
||||
break;
|
||||
|
||||
case NR:
|
||||
outcreg(nreg);
|
||||
break;
|
||||
|
||||
case CAR:
|
||||
outcreg(AREG(freg));
|
||||
break;
|
||||
|
||||
case NAR:
|
||||
outcreg(AREG(nreg));
|
||||
break;
|
||||
|
||||
case EXL:
|
||||
outextend(ltp,LONG,freg);
|
||||
break;
|
||||
|
||||
case EXRL:
|
||||
case EXRLN:
|
||||
outextend(rtp,ltp->t_type,c==EXRL?freg:nreg);
|
||||
break;
|
||||
|
||||
case EXLR:
|
||||
case EXLRN:
|
||||
outextend(ltp,rtp->t_type,c==EXLR?freg:nreg);
|
||||
break;
|
||||
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
subtrees--;
|
||||
case TREE:
|
||||
p = (c==LEFT?ltp:c==RIGHT?rtp:tp);
|
||||
flag = *macro++;
|
||||
scookie = FORREG;
|
||||
if( flag & S_STACK ) {
|
||||
if( cookie == FORSP )
|
||||
scookie = FORSP;
|
||||
else
|
||||
scookie = FORSTACK;
|
||||
}
|
||||
else if( flag & S_FORCC )
|
||||
scookie = FORCC;
|
||||
if( flag & S_NEXT )
|
||||
reg = nreg;
|
||||
else
|
||||
reg = freg;
|
||||
if( flag & S_INDR ) {
|
||||
if( p->t_op != INDR )
|
||||
error("code skeleton error: %d\n",op);
|
||||
p = p->t_left; /*skip INDR*/
|
||||
if( coffset(p) ) {
|
||||
p = p->t_left;
|
||||
if( LONGORPTR(p->t_type) == 0 && (flag&S_STACK) != 0 )
|
||||
p = tnalloc(INT2L,LONG,0,0,p);
|
||||
}
|
||||
reg = AREG(reg); /*no qualifications before...*/
|
||||
#ifdef DEBUG
|
||||
if (eflag)
|
||||
printf("reg = %d, nreg = %d, freg = %d\n",reg,nreg,freg);
|
||||
#endif
|
||||
}
|
||||
sreg = codegen(p,scookie,reg); /*code for subtree*/
|
||||
if( scookie == FORREG ) {
|
||||
if( flag & S_INDR ) {
|
||||
if( ISDREG(sreg) )
|
||||
outmovr(sreg,AREG(reg),p);
|
||||
}
|
||||
else if( flag & S_NEXT )
|
||||
nreg = sreg;
|
||||
else if( sreg != reg ) {
|
||||
/*
|
||||
* result was not in expected register, if remaining sub-tree can be
|
||||
* compiled using the remaining registers, update current and next
|
||||
* registers, saving us the trouble of moving the register.
|
||||
*/
|
||||
if( c == TREE || ((ISDREG(sreg)) && subtrees > 0 &&
|
||||
((c == LEFT &&
|
||||
sucomp(rtp,sreg,0) <= skp->sk_right &&
|
||||
sucomp(rtp,sreg,1) <= SU_ANY) ||
|
||||
( c == RIGHT &&
|
||||
sucomp(ltp,sreg,0) <= skp->sk_left &&
|
||||
sucomp(ltp,sreg,1) <= SU_ANY))) ) {
|
||||
freg = DREG(sreg);
|
||||
nreg = freg + 1;
|
||||
}
|
||||
else
|
||||
outmovr(sreg,DREG(freg),p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LOFFSET:
|
||||
case ROFFSET:
|
||||
p = (c==LOFFSET) ? ltp->t_left : rtp->t_left;
|
||||
if((p=coffset(p)) != 0 && (p->t_op != CINT || p->t_value != 0))
|
||||
outaexpr(p,NOTIMMED);
|
||||
break;
|
||||
|
||||
case MODSWAP:
|
||||
switch( op ) {
|
||||
|
||||
case MOD:
|
||||
case EQMOD:
|
||||
case LMOD:
|
||||
case LEQMOD:
|
||||
OUTSWAP(freg);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if( extf && cookie == FORREG && (ISDREG(freg)) ) {
|
||||
if( UNSIGN(ltp->t_type) || UNSIGN(rtp->t_type) )
|
||||
OUTUEXT(freg);
|
||||
else
|
||||
OUTEXT(freg);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if(eflag) printf("ending expand skp=%lo\n",skp);
|
||||
#endif
|
||||
return(freg);
|
||||
}
|
||||
|
||||
/* op_expand - printf out the subroutine being called */
|
||||
op_expand(op,type,ltype)
|
||||
int op, type,ltype;
|
||||
{
|
||||
if( ISFLOAT(type) || ISFLOAT(ltype) ) {
|
||||
switch( op ) {
|
||||
|
||||
case ADD:
|
||||
case EQADD:
|
||||
case PREINC: /* [vlh] 4.2 */
|
||||
case POSTINC: /* [vlh] 4.2 */
|
||||
printf("_fpadd");
|
||||
break;
|
||||
|
||||
case SUB:
|
||||
case EQSUB:
|
||||
case PREDEC: /* [vlh] 4.2 */
|
||||
case POSTDEC: /* [vlh] 4.2 */
|
||||
printf("_fpsub");
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
case EQMULT:
|
||||
printf("_fpmult");
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case EQDIV:
|
||||
printf("_fpdiv");
|
||||
break;
|
||||
|
||||
case UMINUS:
|
||||
case EQNEG:
|
||||
printf("_fpneg");
|
||||
break;
|
||||
|
||||
case FLOAT2L:
|
||||
case FLOAT2I:
|
||||
printf("_fpftol");
|
||||
break;
|
||||
|
||||
case LONG2F:
|
||||
case INT2F:
|
||||
printf("_fpltof");
|
||||
break;
|
||||
|
||||
case EQUALS:
|
||||
case NEQUALS:
|
||||
case GREAT:
|
||||
case GREATEQ:
|
||||
case LESS:
|
||||
case LESSEQ:
|
||||
printf("_fpcmp");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid floating point op %d\n",op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch( op ) {
|
||||
|
||||
case MULT:
|
||||
case LMULT:
|
||||
printf("lmul");
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case LDIV:
|
||||
printf("ldiv");
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
case LMOD:
|
||||
printf("lrem");
|
||||
break;
|
||||
|
||||
default:
|
||||
error("opcall bad op %d",op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* match - try to match expression tree with code skeleton
|
||||
* Given the expression tree, tries to match the given tree with
|
||||
* the appropriate code skeleton. The code skeleton list is
|
||||
* gotten from the root operator and the cookie value. The code
|
||||
* skeleton list is then searched, checking the Sethy-Ullman numbers
|
||||
* of the sub-trees against the Sethy-Ullman numbers in the code
|
||||
* skeleton list. If the Sethy-Ullman numbers are OK, then the
|
||||
* left and right sub-trees are checked for compatability, e.g.
|
||||
* integer pointers, etc. If a match is found, the code skeleton
|
||||
* list pointer is returned.
|
||||
*/
|
||||
char * /* returns ptr to code skeleton*/
|
||||
match(tp,cookie,reg) /* or 0 if no skeleton*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int cookie; /* goal for code expansion*/
|
||||
int reg; /* register to use*/
|
||||
{
|
||||
register struct skeleton *skp;
|
||||
register short op, bop;
|
||||
short i;
|
||||
register struct tnode *ltp, *rtp;
|
||||
|
||||
#ifdef DEBUG
|
||||
if(mflag) printf("match op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
|
||||
#endif
|
||||
PUTEXPR(mflag,"match",tp);
|
||||
if( (op=tp->t_op) >= LCGENOP )
|
||||
return(0);
|
||||
if( LEAFOP(op) )
|
||||
ltp = tp;
|
||||
else
|
||||
ltp = tp->t_left;
|
||||
if( (bop=BINOP(op)) && cookie!=FORSP) { /* [vlh] 4.2 !FORSP */
|
||||
rtp = tp->t_right;
|
||||
if( CONVOP(ltp->t_op) ) {
|
||||
if( op != LSH && NOTCONVOP(rtp->t_op) ) {
|
||||
if( !(UNSIGN(ltp->t_left->t_type)) || op == ASSIGN ) {
|
||||
tp->t_left = ltp->t_left;
|
||||
if( (skp=match(tp,cookie,reg)) != 0 )
|
||||
return(skp);
|
||||
tp->t_left = ltp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( CONVOP(rtp->t_op) ) {
|
||||
if( !(UNSIGN(rtp->t_left->t_type)) || op == ASSIGN ) {
|
||||
tp->t_right = rtp->t_left;
|
||||
if( (skp=match(tp,cookie,reg)) != 0 )
|
||||
return(skp);
|
||||
tp->t_right = rtp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( cookie ) {
|
||||
case FORCC:
|
||||
i = 3;
|
||||
break;
|
||||
|
||||
case FOREFF:
|
||||
i = 2;
|
||||
break;
|
||||
|
||||
case FORSTACK:
|
||||
case FORSP:
|
||||
i = 4;
|
||||
break;
|
||||
|
||||
case FORREG:
|
||||
i = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
error("match cookie=%d\n",cookie);
|
||||
return(0);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if(mflag) printf("match op=%d i=%d ",op,i);
|
||||
#endif
|
||||
if( !(i=optab[op][i]) )
|
||||
return(0);
|
||||
skp = codeskels[i];
|
||||
#ifdef DEBUG
|
||||
if(mflag) printf("codeskels[%d]=%o\n",i,skp);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if(mflag) {
|
||||
printf("match LEFT ");
|
||||
puttsu(ltp);
|
||||
if(bop) {
|
||||
printf(" RIGHT ");
|
||||
puttsu(rtp);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
for( ; skp->sk_left != 0; skp++ ) {
|
||||
#ifdef DEBUG
|
||||
if( mflag > 1 )
|
||||
printf("sk_left=%x sk_right=%x\n",skp->sk_left,skp->sk_right);
|
||||
#endif
|
||||
if( !(skelmatch(ltp,skp->sk_left)) )
|
||||
continue;
|
||||
if( bop && !(skelmatch(rtp,skp->sk_right)) )
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
if( mflag )
|
||||
printf("match found skp=%o left=%x right=%x\n",skp,
|
||||
skp->sk_left,skp->sk_right);
|
||||
#endif
|
||||
return(skp);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* skelmatch - sub-tree type matching for match*/
|
||||
/* This checks a subtree for type compatability in match.*/
|
||||
skelmatch(tp,skinfo) /* returns 1 if matched, else 0*/
|
||||
struct tnode *tp; /* pointer to expression tree*/
|
||||
int skinfo;
|
||||
{
|
||||
register short type, unsignf, const, stype;
|
||||
|
||||
if( tp->t_su > skinfo || ((skinfo&T_INDR) && tp->t_op != INDR) )
|
||||
return(0);
|
||||
stype = SK_TYPE(skinfo);
|
||||
type = tp->t_type;
|
||||
if( ISFUNCTION(type) )
|
||||
type = BTYPE(type);
|
||||
if( unsignf = UNSIGN(type) )
|
||||
type = BASETYPE(type);
|
||||
const = 0;
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case CFLOAT: /* [vlh] 3.4 */
|
||||
case CLONG:
|
||||
if( tp->t_su > SU_CONST )
|
||||
break;
|
||||
case CINT:
|
||||
const++;
|
||||
break;
|
||||
}
|
||||
switch( stype ) {
|
||||
|
||||
case T_CHAR:
|
||||
return( type == CHAR );
|
||||
|
||||
case T_ANY: /*either short or char*/
|
||||
if( type == CHAR )
|
||||
return(1);
|
||||
case T_INT:
|
||||
return( type == INT || const );
|
||||
|
||||
case T_UNSN:
|
||||
case T_UANY: /* [vlh] 4.2 */
|
||||
case T_UCHAR: /* [vlh] 4.2 */
|
||||
case T_ULONG: /* [vlh] 4.2 */
|
||||
return( unsignf );
|
||||
|
||||
case T_LONG:
|
||||
return( LONGORPTR(type) );
|
||||
|
||||
case T_FLOAT:
|
||||
return( ISFLOAT(type) );
|
||||
|
||||
default:
|
||||
error("skelmatch type: %x",stype);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
110
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/sucomp.c
Normal file
110
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/sucomp.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
/* sucomp - Sethy-Ullman expression complexity measure computation*/
|
||||
/* This is a heuristic computation of the Sethy-Ullman numbers*/
|
||||
/* for expressions. This gives an approximation of the complexity*/
|
||||
/* of the expression. The code generation scheme works best if*/
|
||||
/* the most complex expressions are done first.*/
|
||||
sucomp(tp,nregs,flag) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int nregs; /* number of registers left*/
|
||||
int flag; /* 1=>set values in tree, 0=>return*/
|
||||
{
|
||||
register short su, sur, op, i;
|
||||
register struct tnode *ltp, *rtp;
|
||||
|
||||
nregs = DREG(nregs);
|
||||
if( BINOP(op=tp->t_op) ) {
|
||||
ltp = tp->t_left;
|
||||
rtp = tp->t_right;
|
||||
}
|
||||
else if( UNARYOP(op) )
|
||||
ltp = tp->t_left;
|
||||
switch( op ) {
|
||||
|
||||
case CLONG:
|
||||
if( tp->t_lvalue >= 0x8000L || tp->t_lvalue <= 0xffff8000L ) {
|
||||
su = SU_ADDR;
|
||||
break;
|
||||
}
|
||||
i = tp->t_lvalue;
|
||||
case CINT:
|
||||
if( op == CINT )
|
||||
i = tp->t_value;
|
||||
if( i == 0 )
|
||||
su = SU_ZERO;
|
||||
else if( i == 1 )
|
||||
su = SU_ONE;
|
||||
else if( i >= 1 && i <= QUICKVAL )
|
||||
su = SU_SMALL;
|
||||
else if( i >= -128 && i <= 127 )
|
||||
su = SU_QUICK;
|
||||
else
|
||||
su = SU_CONST;
|
||||
break;
|
||||
|
||||
case COMMA:
|
||||
su = MAX(sucomp(rtp,nregs,flag),sucomp(ltp,nregs,flag));
|
||||
su = MAX(su,SU_EASY);
|
||||
break;
|
||||
|
||||
case ADDR:
|
||||
su = sucomp(ltp,nregs,flag);
|
||||
break;
|
||||
|
||||
case CFLOAT:
|
||||
case DCLONG:
|
||||
case AUTOINC:
|
||||
case AUTODEC:
|
||||
su = SU_ADDR;
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( tp->t_sc != REGISTER )
|
||||
su = SU_ADDR;
|
||||
else if( ISDREG(tp->t_reg) )
|
||||
su = SU_REG;
|
||||
else
|
||||
su = SU_AREG;
|
||||
break;
|
||||
|
||||
case LDIV:
|
||||
case LMOD:
|
||||
case LMULT:
|
||||
case CALL:
|
||||
sucomp(rtp,nregs,flag);
|
||||
case NACALL:
|
||||
sucomp(ltp,nregs,flag);
|
||||
su = SU_VHARD; /*very hard*/
|
||||
break;
|
||||
|
||||
default:
|
||||
su = sucomp(ltp,nregs,flag);
|
||||
if( BINOP(op) ) {
|
||||
if( su <= SU_ADDR )
|
||||
su = MAX(su,sucomp(rtp,nregs,flag));
|
||||
else {
|
||||
sur = sucomp(rtp,nregs+1,flag);
|
||||
if( sur > SU_ADDR && nregs > HICREG )
|
||||
su = MAX(su,SU_HARD);
|
||||
}
|
||||
su = MAX(SU_EASY,su);
|
||||
}
|
||||
else if( su <= SU_XREG )
|
||||
su = MAX(SU_EASY,su);
|
||||
if( ISFLOAT(tp->t_type) )
|
||||
su = SU_VHARD;
|
||||
break;
|
||||
}
|
||||
if( flag )
|
||||
tp->t_su = su;
|
||||
return(su);
|
||||
}
|
||||
118
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/tabl.c
Normal file
118
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/tabl.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright 1982
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#define ASGOP OPRAS|OPASSIGN|OPLVAL|OPBIN
|
||||
|
||||
/*info on operators:*/
|
||||
/*000077-- OPPRI - priority*/
|
||||
/*000100-- OPBIN - binary operator*/
|
||||
/*000200-- OPLVAL - left operand must be lvalue*/
|
||||
/*000400-- OPREL - relational operator*/
|
||||
/*001000-- OPASSIGN - assignment operator*/
|
||||
/*002000-- OPLWORD - short required on left*/
|
||||
/*004000-- OPRWORD - short required on right*/
|
||||
/*010000-- OPCOM commutative*/
|
||||
/*020000-- OPRAS - right associative*/
|
||||
/*040000-- OPTERM - termination node*/
|
||||
/*100000 - OPCONVS - conversion operator*/
|
||||
short opinfo[] = {
|
||||
TRMPRI, /*EOF*/
|
||||
ADDPRI|OPCOM|OPBIN, /*ADD - expr + expr*/
|
||||
ADDPRI|OPBIN, /*SUB - expr - expr*/
|
||||
MULPRI|OPCOM|OPBIN, /*MULT - expr * expr*/
|
||||
MULPRI|OPBIN, /*DIV - expr / expr*/
|
||||
MULPRI|OPBIN, /*MOD - expr % expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*RSH - expr >> expr*/
|
||||
SHFPRI|OPLWORD|OPRWORD|OPBIN, /*LSH - expr << expr*/
|
||||
ANDPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*AND - expr & expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*OR - expr | expr*/
|
||||
ORPRI|OPCOM|OPLWORD|OPRWORD|OPBIN, /*XOR - expr ^ expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*NOT - ! expr*/
|
||||
UNOPRI|OPRAS, /*UMINUS - - expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*COMPL - ~ expr*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREDEC - --lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*PREINC - ++lvalue*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTDEC - lvalue--*/
|
||||
UNOPRI|OPRAS|OPLVAL|OPBIN, /*POSTINC - lvalue++*/
|
||||
ASGPRI|ASGOP, /*ASSIGN - lvalue = expr*/
|
||||
ASGPRI|ASGOP, /*EQADD - lvalue += expr*/
|
||||
ASGPRI|ASGOP, /*EQSUB - lvalue -= expr*/
|
||||
ASGPRI|ASGOP, /*EQMULT - lvalue *= expr*/
|
||||
ASGPRI|ASGOP, /*EQDIV - lvalue /= expr*/
|
||||
ASGPRI|ASGOP, /*EQMOD - lvalue %= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQRSH - lvalue >>= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQLSH - lvalue <<= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQAND - lvalue &= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQOR - lvalue |= expr*/
|
||||
ASGPRI|ASGOP|OPLWORD|OPRWORD, /*EQXOR - lvalue ^= expr*/
|
||||
TRMPRI, /*FJSR - generate function jsr*/
|
||||
EQLPRI|OPREL|OPBIN, /*EQUALS - expr == expr*/
|
||||
EQLPRI|OPREL|OPBIN, /*NEQUALS - expr != expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREAT - expr > expr*/
|
||||
RELPRI|OPREL|OPBIN, /*GREATEQ - expr >= expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESS - expr < expr*/
|
||||
RELPRI|OPREL|OPBIN, /*LESSEQ - expr <= expr*/
|
||||
TRMPRI|OPCONVS, /*INT2L*/
|
||||
TRMPRI|OPCONVS, /*LONG2I*/
|
||||
TRMPRI|OPBIN, /*BTST*/
|
||||
TRMPRI, /*LOAD*/
|
||||
TRMPRI|OPBIN, /*LMULT*/
|
||||
TRMPRI|OPBIN, /*LDIV*/
|
||||
TRMPRI|OPBIN, /*LMOD*/
|
||||
TRMPRI|OPBIN, /*LEQMULT*/
|
||||
TRMPRI|OPBIN, /*LEQDIV*/
|
||||
TRMPRI|OPBIN, /*LEQMOD*/
|
||||
TRMPRI|ASGOP, /*EQADDR*/
|
||||
TRMPRI, /*EQNOT*/
|
||||
TRMPRI, /*EQNEG*/
|
||||
TRMPRI|OPBIN, /*DOCAST*/
|
||||
ASGPRI|ASGOP, /*STASSIGN [vlh]*/
|
||||
TRMPRI|OPCONVS, /*LONG2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2L [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*INT2F [vlh] 3.4*/
|
||||
TRMPRI|OPCONVS, /*FLOAT2I [vlh] 3.4*/
|
||||
UNOPRI|OPRAS, /*TOCHAR [vlh] 4.0*/
|
||||
TRMPRI, /*unused - 56*/
|
||||
TRMPRI, /*unused - 57*/
|
||||
TRMPRI, /*unused - 58*/
|
||||
TRMPRI, /*unused - 59*/
|
||||
UNOPRI|OPRAS|OPLVAL, /*ADDR - & expr*/
|
||||
UNOPRI|OPRAS|OPLWORD, /*INDR - * expr*/
|
||||
LNDPRI|OPBIN, /*LAND - expr && expr*/
|
||||
LORPRI|OPBIN, /*LOR - expr || expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*QMARK - expr ? expr : expr*/
|
||||
QMKPRI|OPRAS|OPBIN, /*COLON*/
|
||||
COMPRI|OPBIN, /*COMMA*/
|
||||
TRMPRI|OPTERM, /*CINT*/
|
||||
TRMPRI|OPTERM, /*CLONG*/
|
||||
TRMPRI|OPTERM, /*SYMBOL*/
|
||||
TRMPRI|OPTERM, /*AUTOINC*/
|
||||
TRMPRI|OPTERM, /*AUTODEC*/
|
||||
LPNPRI|OPBIN, /*CALL - call with arguments*/
|
||||
LPNPRI, /*NACALL - no argument call*/
|
||||
TRMPRI, /*BFIELD - field selection*/
|
||||
TRMPRI, /*CONDBR*/
|
||||
TRMPRI, /*INIT*/
|
||||
TRMPRI, /*LOADREG*/
|
||||
TRMPRI|OPTERM, /*DCLONG - divide const long*/
|
||||
TRMPRI|OPTERM, /*CFLOAT [vlh] 3.4*/
|
||||
UNOPRI|OPRAS|OPASSIGN|OPBIN, /*CAST*/
|
||||
TRMPRI, /*SEMI*/
|
||||
TRMPRI, /*LCURBR - {*/
|
||||
TRMPRI, /*RCURBR - }*/
|
||||
LPNPRI, /*LBRACK - [*/
|
||||
RPNPRI, /*RBRACK - ]*/
|
||||
LPNPRI, /*LPAREN - )*/
|
||||
RPNPRI, /*RPAREN - )*/
|
||||
TRMPRI|OPTERM, /*STRING*/
|
||||
TRMPRI, /*RESWORD*/
|
||||
LPNPRI|OPBIN, /*APTR - expr -> symbol*/
|
||||
LPNPRI|OPBIN, /*PERIOD - expr . symbol*/
|
||||
UNOPRI|OPRAS, /*SIZEOF - sizeof expr*/
|
||||
LPNPRI|OPBIN, /*MPARENS - matching parens ()*/
|
||||
};
|
||||
389
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/util.c
Normal file
389
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/util.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
Copyright 1983
|
||||
Alcyon Corporation
|
||||
8716 Production Ave.
|
||||
San Diego, Ca. 92121
|
||||
*/
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cskel.h"
|
||||
|
||||
char null[];
|
||||
char *opname[];
|
||||
|
||||
/* xnalloc - allocate address-indexed node*/
|
||||
char *xnalloc(type,ar,off,xr,xt) /* returns ptr to node alloced*/
|
||||
int type; /* data type*/
|
||||
int ar; /* address register*/
|
||||
int off; /* 8-bit offset*/
|
||||
int xr; /* index register*/
|
||||
int xt; /* index register type*/
|
||||
{
|
||||
register struct indexnode *xp;
|
||||
|
||||
xp = talloc(sizeof(*xp));
|
||||
xp->t_op = SYMBOL;
|
||||
xp->t_type = type;
|
||||
xp->t_sc = INDEXED;
|
||||
xp->t_reg = ar;
|
||||
xp->t_su = SU_ADDR;
|
||||
xp->t_offset = off;
|
||||
xp->t_xreg = xr;
|
||||
xp->t_xtype = xt;
|
||||
return(xp);
|
||||
}
|
||||
|
||||
/* tcopy - expression tree copy*/
|
||||
char *tcopy(tp,autof) /* returns ptr to copied tree*/
|
||||
struct tnode *tp;
|
||||
int autof; /* can do AUTOINC and AUTODEC? */
|
||||
{
|
||||
register char *p;
|
||||
register short op;
|
||||
|
||||
op = tp->t_op;
|
||||
switch( op ) {
|
||||
|
||||
case SYMBOL:
|
||||
if( tp->t_sc == EXTERNAL || tp->t_sc == EXTOFF )
|
||||
p = cenalloc(tp->t_type,tp->t_sc,tp->t_symbol);
|
||||
else {
|
||||
p = snalloc(tp->t_type,tp->t_sc,tp->t_offset,0,0);
|
||||
p->t_label = tp->t_label;
|
||||
}
|
||||
p->t_offset = tp->t_offset;
|
||||
p->t_reg = tp->t_reg;
|
||||
return(p);
|
||||
|
||||
case CINT:
|
||||
return(cnalloc(tp->t_type,tp->t_value));
|
||||
|
||||
case CLONG:
|
||||
return(lcnalloc(tp->t_type,tp->t_lvalue));
|
||||
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
return(fpcnalloc(tp->t_type,tp->t_lvalue));
|
||||
|
||||
case DCLONG:
|
||||
p = lcnalloc(tp->t_type,tp->t_lvalue);
|
||||
p->t_op = DCLONG;
|
||||
return(p);
|
||||
|
||||
case AUTOINC: /*[mac] 4.2*/
|
||||
case AUTODEC:
|
||||
p = snalloc(tp->t_type,AUTO,0,0,0);
|
||||
if( autof == DOAUTO )
|
||||
p->t_op = op;
|
||||
p->t_reg = tp->t_reg;
|
||||
return(p);
|
||||
|
||||
default:
|
||||
p = tnalloc(op,tp->t_type,0,0,null,null);
|
||||
if( ISASGOP(op) || op == PREINC || op == PREDEC ) /* [mac] 4.2 */
|
||||
p->t_right = tcopy(tp->t_right,DOAUTO);
|
||||
else if( BINOP(op) )
|
||||
p->t_right = tcopy(tp->t_right,autof);
|
||||
p->t_left = tcopy(tp->t_left,autof);
|
||||
return(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* outaexpr - output address expression*/
|
||||
outaexpr(tp,flags) /* returns - none*/
|
||||
struct tnode *tp; /* pointer to tree*/
|
||||
int flags; /* flags (IMMED,LOFFSET,...)*/
|
||||
{
|
||||
register short off, reg, lab;
|
||||
long l;
|
||||
|
||||
if( tp->t_op == ADDR ) {
|
||||
tp = tp->t_left;
|
||||
putchar('#');
|
||||
}
|
||||
off = tp->t_offset;
|
||||
reg = tp->t_reg;
|
||||
lab = tp->t_label;
|
||||
switch( tp->t_op ) {
|
||||
|
||||
case AUTOINC:
|
||||
printf("(R%d)+",reg);
|
||||
break;
|
||||
|
||||
case AUTODEC:
|
||||
printf("-(R%d)",reg);
|
||||
break;
|
||||
|
||||
case CINT:
|
||||
if( flags & IMMED )
|
||||
putchar('#');
|
||||
printf("%d",tp->t_value);
|
||||
break;
|
||||
|
||||
case DCLONG:
|
||||
case CLONG:
|
||||
case CFLOAT: /*[vlh] 3.4 */
|
||||
if( flags & IMMED )
|
||||
putchar('#');
|
||||
outlval(tp->t_lvalue);
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
if( off ) {
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
default:
|
||||
printf("%d+",off);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf("%d",off);
|
||||
case CINDR:
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
case INDEXED:
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
error("invalid register expression");
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( tp->t_sc ) {
|
||||
|
||||
case REGISTER:
|
||||
printf("R%d",reg);
|
||||
break;
|
||||
|
||||
case REGOFF:
|
||||
printf("(R%d)",reg);
|
||||
break;
|
||||
|
||||
case EXTERNAL:
|
||||
printf("_%.8s",tp->t_symbol);
|
||||
break;
|
||||
|
||||
case EXTOFF:
|
||||
printf("_%.8s(R%d)",tp->t_symbol,reg);
|
||||
break;
|
||||
|
||||
case STATIC:
|
||||
printf("L%d",lab);
|
||||
break;
|
||||
|
||||
case STATOFF:
|
||||
printf("L%d(R%d)",lab,reg);
|
||||
break;
|
||||
|
||||
case INDEXED:
|
||||
printf("%d(R%d,R%d",off,reg,tp->t_xreg);
|
||||
outatype(tp->t_xtype);
|
||||
putchar(')');
|
||||
break;
|
||||
|
||||
case CINDR:
|
||||
printf("%d",off);
|
||||
break;
|
||||
/*
|
||||
* the following will work on: PDP-11, 68000, IBM-360, VAX, etc.
|
||||
* it will not work on word machines or on machines where either
|
||||
* longs two ints or two shorts.
|
||||
*/
|
||||
case CLINDR:
|
||||
case CFINDR: /* [vlh] 3.4 */
|
||||
l.hiword = tp->t_offset;
|
||||
l.loword = tp->t_ssp;
|
||||
outlval(l);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid storage class %d\n",tp->t_sc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("invalid operator %s\n",opname[tp->t_op]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* outlval - output long value*/
|
||||
/* This is a big pain because the PDP-11 doesn't do long divides*/
|
||||
/* in hardware.*/
|
||||
outlval(lval)
|
||||
long lval;
|
||||
{
|
||||
char digs[8];
|
||||
register short i, c;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
digs[i++] = lval & 0xf;
|
||||
lval >>= 4;
|
||||
lval &= 0xfffffff;
|
||||
} while ( lval );
|
||||
putchar('$');
|
||||
while( --i >= 0 ) {
|
||||
c = digs[i];
|
||||
putchar(c>=10?c+('a'-10):c+'0');
|
||||
}
|
||||
}
|
||||
|
||||
/* outtype - output 68000 type (null, .b, .l) depending on data type*/
|
||||
outtype(type)
|
||||
int type;
|
||||
{
|
||||
if( ISFLOAT(type) || LONGORPTR(type) )
|
||||
printf(".l");
|
||||
else if( type == CHAR )
|
||||
printf(".b");
|
||||
}
|
||||
|
||||
/* outatype - output address type (.l or null) depending on data type*/
|
||||
outatype(type)
|
||||
int type;
|
||||
{
|
||||
if( LONGORPTR(type) || ISFLOAT(type) )
|
||||
printf(".l");
|
||||
}
|
||||
|
||||
/* outextend - output register extension to long depending on type*/
|
||||
outextend(tp,type,reg) /* returns - none*/
|
||||
struct tnode *tp; /* tree to convert from*/
|
||||
int type; /* type to convert to*/
|
||||
int reg; /* register to convert*/
|
||||
{
|
||||
if( (ISDREG(reg)) && !(LONGORPTR(tp->t_type)) && (LONGORPTR(type)) ) {
|
||||
if( UNSIGN(tp->t_type) )
|
||||
OUTUEXT(reg);
|
||||
else
|
||||
OUTEXT(reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* outrr - output register to register instruction*/
|
||||
outrr(ins,r1,r2,tp)
|
||||
char *ins;
|
||||
int r1;
|
||||
int r2;
|
||||
struct tnode *tp;
|
||||
{
|
||||
printf("%s",ins);
|
||||
if( ISAREG(r1) || ISAREG(r2) )
|
||||
outatype(tp->t_type);
|
||||
else
|
||||
outtype(tp->t_type);
|
||||
printf(" R%d,R%d\n",r1,r2);
|
||||
}
|
||||
|
||||
/* outmovr - output "move[type] R1,R2" instruction*/
|
||||
outmovr(r1,r2,tp)
|
||||
int r1;
|
||||
int r2;
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( r1 != r2 )
|
||||
outrr("move",r1,r2,tp);
|
||||
}
|
||||
|
||||
/* outcmpm - output "cmpm[type] (R1)+,(R2)+"*/
|
||||
outcmpm(tp)
|
||||
struct tnode *tp;
|
||||
{
|
||||
register int lreg, rreg;
|
||||
|
||||
if (!m68010) { /* 68000 version cmpm ok !!! */
|
||||
printf("cmpm");
|
||||
outtype(tp->t_left->t_type);
|
||||
printf(" (R%d)+,(R%d)+\n",tp->t_left->t_reg,tp->t_right->t_reg);
|
||||
}
|
||||
else /* generating code for 68010, micro code is bad for cmpm */
|
||||
fakecmpm(tp->t_left->t_type,tp->t_left->t_reg,tp->t_right->t_reg);
|
||||
}
|
||||
|
||||
/* fakecmpm - output 68010 fake cmpm for bad microcode [vlh] 4.2 */
|
||||
fakecmpm(type,lreg,rreg)
|
||||
int type,lreg,rreg;
|
||||
{
|
||||
printf("cmp");
|
||||
outtype(type);
|
||||
printf(" (R%d),(R%d)\n",lreg,rreg);
|
||||
if( ISFLOAT(type) || LONGORPTR(type) )
|
||||
printf("addq #4,R%d\naddq #4,R%d\n",lreg,rreg);
|
||||
else if( type == CHAR )
|
||||
printf("addq #1,R%d\naddq #1,R%d\n",lreg,rreg);
|
||||
else
|
||||
printf("addq #2,R%d\naddq #2,R%d\n",lreg,rreg);
|
||||
}
|
||||
|
||||
/* outcreg - output reference to compiler temp register*/
|
||||
outcreg(reg)
|
||||
int reg;
|
||||
{
|
||||
if( (DREG(reg)) > HICREG )
|
||||
error("expression too complex");
|
||||
printf("R%d",reg);
|
||||
}
|
||||
|
||||
/* outcmp0 - output a compare with 0, special for address register*/
|
||||
outcmp0(reg,tp)
|
||||
int reg;
|
||||
struct tnode *tp;
|
||||
{
|
||||
if( ISAREG(reg) ) {
|
||||
printf("cmp");
|
||||
outatype(tp->t_type);
|
||||
printf(" #0,R%d\n",reg);
|
||||
}
|
||||
else {
|
||||
printf("tst");
|
||||
outtype(tp->t_type);
|
||||
printf(" R%d\n",reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* outrpush - output "move[type] R1,[-](sp)"*/
|
||||
outrpush(reg,tp,pflag)
|
||||
int reg;
|
||||
struct tnode *tp;
|
||||
int pflag;
|
||||
{
|
||||
printf("move");
|
||||
outatype(tp->t_type);
|
||||
printf(" R%d,%c(sp)\n",reg,pflag?'-':'\0');
|
||||
}
|
||||
|
||||
outdbra(reg,lab)
|
||||
int reg;
|
||||
int lab;
|
||||
{
|
||||
printf("dbra R%d,L%d\n",reg,lab);
|
||||
}
|
||||
|
||||
/* cenalloc - code generator external node allocation*/
|
||||
/* This may be coalesced into enalloc in parser.*/
|
||||
char *cenalloc(type,sc,sym) /* returns ptr to node alloced*/
|
||||
int type; /* type of symbol*/
|
||||
int sc; /* storage class*/
|
||||
char *sym; /* symbol name*/
|
||||
{
|
||||
register struct extnode *ep;
|
||||
|
||||
ep = talloc(sizeof(*ep));
|
||||
ep->t_op = SYMBOL;
|
||||
ep->t_type = type;
|
||||
ep->t_sc = sc;
|
||||
ep->t_su = 0;
|
||||
ep->t_offset = 0;
|
||||
symcopy(sym,ep->t_symbol);
|
||||
return(ep);
|
||||
}
|
||||
|
||||
/*popstack - clear off the stack after a call if necessary */
|
||||
popstack(nb)
|
||||
{
|
||||
if (nb > 0 && nb <= 8)
|
||||
printf("addq.l #%d,sp\n",nb);
|
||||
else if (nb > 0)
|
||||
printf("adda.l #%d,sp\n",nb);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
char *compiled = "@(#) Code Generator - Tue Sep 6 14:30 1983";
|
||||
BIN
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/version.o
Normal file
BIN
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cgen/version.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user