/* Copyright 1981 Alcyon Corporation 8474 Commerce Av. San Diego, Ca. 92121 */ #include "cgen.h" #include "cskel.h" /* 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) /* returns ptr to copied tree*/ struct tnode *tp; { register char *p; switch( tp->t_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 DCLONG: p = lcnalloc(tp->t_type,tp->t_lvalue); p->t_op = DCLONG; return(p); default: if( binop(tp->t_op) ) return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left), tcopy(tp->t_right))); if( unaryop(tp->t_op) ) return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left), null)); error("tcopy op=%d",tp->t_op); return(tp); } } /* outaexpr - output address expression*/ outaexpr(tp,flags) /* returns - none*/ struct tnode *tp; /* pointer to tree*/ int flags; /* flags (IMMED,LOFFSET,...)*/ { register int 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: 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 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: 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 %d\n",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 int 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( 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) ) printf(".l"); } /* outext - output register sign extension*/ outext(reg) int reg; { printf("ext.l R%d\n",reg); } /* outuext - output unsigned to long register extension*/ outuext(reg) int reg; { printf("swap R%d\nclr R%d\nswap R%d\n",reg,reg,reg); } /* 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) == 0 && longorptr(type) ) { if( unsign(tp->t_type) ) outuext(reg); else outext(reg); } } /* outswap - output swap register instruction*/ outswap(reg) int reg; { printf("swap R%d\n",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); } /* outaddr - output "add[type] R1,R2" instruction*/ outaddr(r1,r2,tp) int r1; int r2; struct tnode *tp; { outrr("add",r1,r2,tp); } /* outcmpm - output "cmpm[type] (R1)+,(R2)+"*/ outcmpm(tp) struct tnode *tp; { printf("cmpm"); outtype(tp->t_left->t_type); printf(" (R%d)+,(R%d)+\n",tp->t_left->t_reg,tp->t_right->t_reg); } /* 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'); } /* popstack - output instruction to pop stack desired number of bytes*/ /* Makes use of special case instructions to save a word.*/ popstack(nb) /* returns - none*/ int nb; /* number of bytes to pop*/ { if( nb > 0 ) printf("add #%d,sp\n",nb); } /* 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); } /* outccsave - output instruction to move cc's to register.*/ outccsave(reg) int reg; { printf("move sr,R%d\n",reg); } /* outccrestore - output instruction to restore cc's from register*/ outccrestore(reg) int reg; { printf("move R%d,ccr\n",reg); }