/* a lot of the machine dependent parts of the second pass */
# define BITMASK(n) ((1L<<n)-1)
fprintf( stderr, "%s, line %d: ", filename, lineno );
lineid( l, fn ) char *fn; {
/* identify line l and file fn */
printf( "# line %d, file %s\n", l, fn );
OFFSZ spoff; /* offset from stack pointer */
extern int ftlab1, ftlab2;
if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
printf( "L%d:\n", ftlab1);
printf( " subl2 $%ld,sp\n", spoff);
printf( " movab -%ld(sp),sp\n", spoff);
printf( " jbr L%d\n", ftlab2);
struct hoptab { int opmask; char * opstring; } ioptab[] = {
/* output the appropriate string from the above table */
register struct hoptab *q;
for( q = ioptab; q->opmask>=0; ++q ){
printf( "%s", q->opstring );
if( f == 'F' ) printf( "e" );
else if( f == 'D' ) printf( "d" );
printf("%c", tolower(f));
cerror( "no hoptab for %s", opst[o] );
rnames[] = { /* keyed to register number tokens */
"r6", "r7", "r8", "r9", "r10", "r11",
SAREG|STAREG, SAREG|STAREG,
SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
SAREG, SAREG, SAREG, SAREG,
mixtypes(p, q) NODE *p, *q;
return( (tp==FLOAT || tp==DOUBLE) !=
(tq==FLOAT || tq==DOUBLE) );
if ( !ISPTR( n->type ) ) cerror("zzzcode- bad type");
zzzcode( p, c ) register NODE *p; {
case 'N': /* logical ops, turned into 0-1 */
/* use register given by register 1 */
cbgen( 0, m=getlab(), 'I' );
printf( " clrl %s\n", rnames[getlr( p, '1' )->rval] );
cbgen( p->op, p->label, c );
if (xdebug) eprint(p, 0, &val, &val);
if (optype(p->op) == LTYPE || p->op == UNARY MUL)
l->type = (r->type==FLOAT || r->type==DOUBLE ? DOUBLE : INT);
if (r->op == ICON && r->name[0] == '\0')
if (r->lval < 0 && r->lval >= -63)
: (r->lval >= -32768 ? SHORT
r->type = (r->lval >= 0 ?
: ( r->lval <= 127 ? CHAR
: (r->lval <= 255 ? UCHAR
: (r->lval <= 32767 ? SHORT
: (r->lval <= 65535 ? USHORT
if (l->op == REG && l->type != FLOAT && l->type != DOUBLE)
else if (tlen(l) > tlen(r) && ISUNSIGNED(r->type))
case 'C': /* num words pushed on arg stack */
if (xdebug) printf("->%d<-",gc_numbytes);
printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
case 'D': /* INCR and DECR */
case 'E': /* INCR and DECR, FOREFF */
printf("%s", (p->op == INCR ? "inc" : "dec") );
printf("%s", (p->op == INCR ? "add" : "sub") );
case 'F': /* register type of right operand */
if (xdebug) printf("->%d<-", ty);
if ( ty==DOUBLE) printf("d");
else if ( ty==FLOAT ) printf("f");
case 'L': /* type of left operand */
case 'R': /* type of right operand */
if (xdebug) printf("->%d<-", n->type);
case 'Z': /* complement mask for bit instr */
printf("$%ld", ~p->right->lval);
case 'U': /* 32 - n, for unsigned right shifts */
printf("$%d", 32 - p->right->lval );
case 'T': /* rounded structure length for arguments */
case 'S': /* structure assignment */
else if( p->op == STARG ){ /* store an arg into a temporary */
else cerror( "STASG bad" );
if( r->op == ICON ) r->op = NAME;
else if( r->op == REG ) r->op = OREG;
else if( r->op != OREG ) cerror( "STASG-r" );
if( size <= 0 || size > 65535 )
cerror("structure size <0=0 or >65535");
printf(" movc3 $%d,", size);
if( r->op == NAME ) r->op = ICON;
else if( r->op == OREG ) r->op = REG;
cerror( "illegal zzzcode" );
(t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
rnames[rs], rnames[rt] );
INTAREG|INTBREG, INTAREG|INTBREG,
INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
setregs(){ /* set up temporary registers */
fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
szty(t){ /* size, in registers, needed to hold thing of type t */
return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
base( p ) register NODE *p; {
if( (o==ICON && p->name[0] != '\0')) return( 100 ); /* ie no base reg */
if( o==REG ) return( p->rval );
if( (o==PLUS || o==MINUS) && p->left->op == REG && p->right->op==ICON)
if( o==OREG && !R2TEST(p->rval) && (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
return( p->rval + 0200*1 );
if( o==INCR && p->left->op==REG ) return( p->left->rval + 0200*2 );
if( o==ASG MINUS && p->left->op==REG) return( p->left->rval + 0200*4 );
if( o==UNARY MUL && p->left->op==INCR && p->left->left->op==REG
&& (p->type==INT || p->type==UNSIGNED || ISPTR(p->type)) )
return( p->left->left->rval + 0200*(1+2) );
offset( p, tyl ) register NODE *p; int tyl; {
if( tyl==1 && p->op==REG && (p->type==INT || p->type==UNSIGNED) ) return( p->rval );
if( (p->op==LS && p->left->op==REG && (p->left->type==INT || p->left->type==UNSIGNED) &&
(p->right->op==ICON && p->right->name[0]=='\0')
&& (1<<p->right->lval)==tyl))
makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
f = p->left; /* have to free this subtree later */
q->right->lval = -q->right->lval;
cerror("illegal makeor2");
p->rval = R2PACK( (b & 0177), o, (b>>7) );
if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->left)) ) return(1);
shltype( o, p ) register NODE *p; {
return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->left)) );
flshape( p ) register NODE *p; {
return( p->op == REG || p->op == NAME || p->op == ICON ||
(p->op == OREG && (!R2TEST(p->rval) || tlen(p) == 1)) );
shtemp( p ) register NODE *p; {
if( p->op == STARG ) p = p->left;
return( p->op==NAME || p->op ==ICON || p->op == OREG || (p->op==UNARY MUL && shumul(p->left)) );
shumul( p ) register NODE *p; {
printf("\nshumul:op=%d,lop=%d,rop=%d", p->op, p->left->op, p->right->op);
printf(" prname=%s,plty=%d, prlval=%D\n", p->right->name, p->left->type, p->right->lval);
if( o == NAME || (o == OREG && !R2TEST(p->rval)) || o == ICON ) return( STARNM );
if( ( o == INCR || o == ASG MINUS ) &&
( p->left->op == REG && p->right->op == ICON ) &&
p->right->name[0] == '\0' )
if ( ISPTR(p->left->type) ) {
return( p->right->lval == o ? STARREG : 0);
adrcon( val ) CONSZ val; {
conput( p ) register NODE *p; {
printf( "%s", rnames[p->rval] );
cerror( "illegal conput" );
insput( p ) register NODE *p; {
upput( p ) register NODE *p; {
adrput( p ) register NODE *p; {
/* output an address, with offsets, from p */
/* addressable value of the constant */
printf( "%s", rnames[p->rval] );
if( R2TEST(r) ){ /* double indexing */
if( flags & 1 ) printf("*");
if( flags & 4 ) printf("-");
if( p->lval != 0 || p->name[0] != '\0' ) acon(p);
if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
if( flags & 2 ) printf("+");
printf( "[%s]", rnames[R2UPK2(r)] );
if( r == AP ){ /* in the argument region */
if( p->lval <= 0 || p->name[0] != '\0' ) werror( "bad arg temp" );
printf( CONFMT, p->lval );
if( p->lval != 0 || p->name[0] != '\0') acon( p );
printf( "(%s)", rnames[p->rval] );
/* STARNM or STARREG found */
if( tshape(p, STARNM) ) {
else { /* STARREG - really auto inc or dec */
printf("%c(%s)%c", (p->left->op==INCR ? '\0' : '-'),
rnames[p->left->left->rval],
(p->left->op==INCR ? '+' : '\0') );
p->rval = p->left->left->rval;
p->lval = (p->left->op == INCR ? -p->left->right->lval : 0);
cerror( "illegal address" );
acon( p ) register NODE *p; { /* print out a constant */
if( p->name[0] == '\0' ){
printf( CONFMT, p->lval);
else if( p->lval == 0 ) {
printf( "%.8s", p->name );
printf( "%.8s+", p->name );
printf( CONFMT, p->lval );
aacon( p ) register NODE *p; { /* print out a constant */
if( p->name[0] == '\0' ){
printf( CONFMT, p->lval);
else if( p->lval == 0 ) {
printf( "$%.8s", p->name );
printf( CONFMT, p->lval );
printf( "%.8s)", p->name );
genscall( p, cookie ) register NODE *p; {
/* structure valued call */
return( gencall( p, cookie ) );
gencall( p, cookie ) register NODE *p; {
/* generate the call given by p */
register NODE *p1, *ptemp;
if( p->right ) temp = argsize( p->right );
if( p->op == STCALL || p->op == UNARY STCALL ){
/* set aside room for structure return */
if( p->stsize > temp ) temp1 = p->stsize;
if( temp > maxargs ) maxargs = temp;
if( p->right ){ /* make temp node, put offset in, and generate args */
genargs( p->right, ptemp );
if( p1->op != OREG || R2TEST(p1->rval) ){
if( p1->op == REG && p->rval == R5 ){
cerror( "call register overwrite" );
setup gc_numbytes so reference to ZC works */
m = match( p, INTAREG|INTBREG );
printf( " tst (sp)+\n" );
printf( " cmp (sp)+,(sp)+\n" );
printf( " add $%d,sp\n", temp);
cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
if( o == 0 ) printf( " jbr L%d\n", lab );
if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
printf( ccbranches[o-EQ], lab );
nextcook( p, cookie ) NODE *p; {
/* we have failed to match p with cookie; try another */
if( cookie == FORREW ) return( 0 ); /* hopeless! */
if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
if( !(cookie&INTEMP) && asgop(p->op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
lastchance( p, cook ) NODE *p; {
optim2( p ) register NODE *p; {
/* do local tree transformations and optimizations */
/* commute L and R to eliminate compliments and constants */
if( (p->left->op==ICON&&p->left->name[0]==0) || p->left->op==COMPL ) {
/* change meaning of AND to ~R&L - bic on pdp11 */
if( r->op==ICON && r->name[0]==0 ) { /* compliment constant */
else if( r->op==COMPL ) { /* ~~A => A */
else { /* insert complement node */
p->right->type = r->type;
main( argc, argv ) char *argv[]; {
return( mainp2( argc, argv ) );