1File: UTIL.C Page 1 1 /* 2 Copyright 1982 3 Alcyon Corporation 4 8716 Production Ave. 5 San Diego, Ca. 92121 6 */ 7 8 #include "cgen.h" 9 #include "cskel.h" 10 11 /* xnalloc - allocate address-indexed node*/ 12 char *xnalloc(type,ar,off,xr,xt) /* returns ptr to node alloced*/ 13 int type; /* data type*/ 14 int ar; /* address register*/ 15 int off; /* 8-bit offset*/ 16 int xr; /* index register*/ 17 int xt; /* index register type*/ 18 { 19 register struct indexnode *xp; 20 21 xp = talloc(sizeof(*xp)); 22 xp->t_op = SYMBOL; 23 xp->t_type = type; 24 xp->t_sc = INDEXED; 25 xp->t_reg = ar; 26 xp->t_su = SU_ADDR; 27 xp->t_offset = off; 28 xp->t_xreg = xr; 29 xp->t_xtype = xt; 30 return(xp); 31 } 32 33 /* tcopy - expression tree copy*/ 34 char *tcopy(tp) /* returns ptr to copied tree*/ 35 struct tnode *tp; 36 { 37 register char *p; 38 39 switch( tp->t_op ) { 40 41 case SYMBOL: 42 if( tp->t_sc == EXTERNAL || tp->t_sc == EXTOFF ) 43 p = cenalloc(tp->t_type,tp->t_sc,tp->t_symbol); 44 else { 45 p = snalloc(tp->t_type,tp->t_sc,tp->t_offset,0,0); 46 p->t_label = tp->t_label; 47 } 48 p->t_offset = tp->t_offset; 49 p->t_reg = tp->t_reg; 50 return(p); 51 52 case CINT: 53 return(cnalloc(tp->t_type,tp->t_value)); 54 55 case CLONG: 56 return(lcnalloc(tp->t_type,tp->t_lvalue)); 57 58 case CFLOAT: /*[vlh] 3.4 */ 59 return(fpcnalloc(tp->t_type,tp->t_lvalue)); 1File: UTIL.C Page 2 60 61 case DCLONG: 62 p = lcnalloc(tp->t_type,tp->t_lvalue); 63 p->t_op = DCLONG; 64 return(p); 65 66 default: 67 if( binop(tp->t_op) ) 68 return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left), 69 tcopy(tp->t_right))); 70 if( unaryop(tp->t_op) ) 71 return(tnalloc(tp->t_op,tp->t_type,0,0,tcopy(tp->t_left), 72 null)); 73 error("tcopy op=%d",tp->t_op); 74 return(tp); 75 } 76 } 77 78 /* outaexpr - output address expression*/ 79 outaexpr(tp,flags) /* returns - none*/ 80 struct tnode *tp; /* pointer to tree*/ 81 int flags; /* flags (IMMED,LOFFSET,...)*/ 82 { 83 register int off, reg, lab; 84 long l; 85 86 if( tp->t_op == ADDR ) { 87 tp = tp->t_left; 88 putchar('#'); 89 } 90 off = tp->t_offset; 91 reg = tp->t_reg; 92 lab = tp->t_label; 93 switch( tp->t_op ) { 94 95 case AUTOINC: 96 printf("(R%d)+",reg); 97 break; 98 99 case AUTODEC: 100 printf("-(R%d)",reg); 101 break; 102 103 case CINT: 104 if( flags & IMMED ) 105 putchar('#'); 106 printf("%d",tp->t_value); 107 break; 108 109 case DCLONG: 110 case CLONG: 111 case CFLOAT: /*[vlh] 3.4 */ 112 if( flags & IMMED ) 113 putchar('#'); 114 outlval(tp->t_lvalue); 115 break; 116 117 case SYMBOL: 118 if( off ) { 1File: UTIL.C Page 3 119 switch( tp->t_sc ) { 120 121 default: 122 printf("%d+",off); 123 break; 124 125 case REGOFF: 126 printf("%d",off); 127 case CINDR: 128 case CLINDR: 129 case CFINDR: /* [vlh] 3.4 */ 130 case INDEXED: 131 break; 132 133 case REGISTER: 134 error("invalid register expression"); 135 break; 136 } 137 } 138 switch( tp->t_sc ) { 139 140 case REGISTER: 141 printf("R%d",reg); 142 break; 143 144 case REGOFF: 145 printf("(R%d)",reg); 146 break; 147 148 case EXTERNAL: 149 printf("_%.8s",tp->t_symbol); 150 break; 151 152 case EXTOFF: 153 printf("_%.8s(R%d)",tp->t_symbol,reg); 154 break; 155 156 case STATIC: 157 printf("L%d",lab); 158 break; 159 160 case STATOFF: 161 printf("L%d(R%d)",lab,reg); 162 break; 163 164 case INDEXED: 165 printf("%d(R%d,R%d",off,reg,tp->t_xreg); 166 outatype(tp->t_xtype); 167 putchar(')'); 168 break; 169 170 case CINDR: 171 printf("%d",off); 172 break; 173 /* 174 * the following will work on: PDP-11, 68000, IBM-360, VAX, etc. 175 * it will not work on word machines or on machines where either 176 * longs two ints or two shorts. 177 */ 1File: UTIL.C Page 4 178 case CLINDR: 179 case CFINDR: /* [vlh] 3.4 */ 180 l.hiword = tp->t_offset; 181 l.loword = tp->t_ssp; 182 outlval(l); 183 break; 184 185 default: 186 error("invalid storage class %d\n",tp->t_sc); 187 break; 188 } 189 break; 190 191 default: 192 error("invalid operator %d\n",tp->t_op); 193 break; 194 } 195 } 196 197 /* outlval - output long value*/ 198 /* This is a big pain because the PDP-11 doesn't do long divides*/ 199 /* in hardware.*/ 200 outlval(lval) 201 long lval; 202 { 203 char digs[8]; 204 register int i, c; 205 206 i = 0; 207 do { 208 digs[i++] = lval & 0xf; 209 lval =>> 4; 210 lval =& 0xfffffff; 211 } while ( lval ); 212 putchar('$'); 213 while( --i >= 0 ) { 214 c = digs[i]; 215 putchar(c>=10?c+('a'-10):c+'0'); 216 } 217 } 218 219 /* outtype - output 68000 type (null, .b, .l) depending on data type*/ 220 outtype(type) 221 int type; 222 { 223 if( isfloat(type) ) 224 printf(".l"); 225 else if( longorptr(type) ) 226 printf(".l"); 227 else if( type == CHAR ) 228 printf(".b"); 229 } 230 231 /* outatype - output address type (.l or null) depending on data type*/ 232 outatype(type) 233 int type; 234 { 235 if( longorptr(type) || isfloat(type) ) 236 printf(".l"); 1File: UTIL.C Page 5 237 } 238 239 /* outextend - output register extension to long depending on type*/ 240 outextend(tp,type,reg) /* returns - none*/ 241 struct tnode *tp; /* tree to convert from*/ 242 int type; /* type to convert to*/ 243 int reg; /* register to convert*/ 244 { 245 if( (isdreg(reg)) && !(longorptr(tp->t_type)) && (longorptr(type)) ) { 246 if( unsign(tp->t_type) ) 247 outuext(reg); 248 else 249 outext(reg); 250 } 251 } 252 253 /* outrr - output register to register instruction*/ 254 outrr(ins,r1,r2,tp) 255 char *ins; 256 int r1; 257 int r2; 258 struct tnode *tp; 259 { 260 printf("%s",ins); 261 if( isareg(r1) || isareg(r2) ) 262 outatype(tp->t_type); 263 else 264 outtype(tp->t_type); 265 printf(" R%d,R%d\n",r1,r2); 266 } 267 268 /* outmovr - output "move[type] R1,R2" instruction*/ 269 outmovr(r1,r2,tp) 270 int r1; 271 int r2; 272 struct tnode *tp; 273 { 274 if( r1 != r2 ) 275 outrr("move",r1,r2,tp); 276 } 277 278 /* outcmpm - output "cmpm[type] (R1)+,(R2)+"*/ 279 outcmpm(tp) 280 struct tnode *tp; 281 { 282 printf("cmpm"); 283 outtype(tp->t_left->t_type); 284 printf(" (R%d)+,(R%d)+\n",tp->t_left->t_reg,tp->t_right->t_reg); 285 } 286 287 /* outcreg - output reference to compiler temp register*/ 288 outcreg(reg) 289 int reg; 290 { 291 if( (dreg(reg)) > HICREG ) 292 error("expression too complex"); 293 printf("R%d",reg); 294 } 295 1File: UTIL.C Page 6 296 /* outcmp0 - output a compare with 0, special for address register*/ 297 outcmp0(reg,tp) 298 int reg; 299 struct tnode *tp; 300 { 301 if( isareg(reg) ) { 302 printf("cmp"); 303 outatype(tp->t_type); 304 printf(" #0,R%d\n",reg); 305 } 306 else { 307 printf("tst"); 308 outtype(tp->t_type); 309 printf(" R%d\n",reg); 310 } 311 } 312 313 /* outrpush - output "move[type] R1,[-](sp)"*/ 314 outrpush(reg,tp,pflag) 315 int reg; 316 struct tnode *tp; 317 int pflag; 318 { 319 printf("move"); 320 outatype(tp->t_type); 321 printf(" R%d,%c(sp)\n",reg,pflag?'-':'\0'); 322 } 323 324 outdbra(reg,lab) 325 int reg; 326 int lab; 327 { 328 printf("dbra R%d,L%d\n",reg,lab); 329 } 330 331 /* cenalloc - code generator external node allocation*/ 332 /* This may be coalesced into enalloc in parser.*/ 333 char *cenalloc(type,sc,sym) /* returns ptr to node alloced*/ 334 int type; /* type of symbol*/ 335 int sc; /* storage class*/ 336 char *sym; /* symbol name*/ 337 { 338 register struct extnode *ep; 339 340 ep = talloc(sizeof(*ep)); 341 ep->t_op = SYMBOL; 342 ep->t_type = type; 343 ep->t_sc = sc; 344 ep->t_su = 0; 345 ep->t_offset = 0; 346 symcopy(sym,ep->t_symbol); 347 return(ep); 348 } 349 350 /*popstack - clear off the stack after a call if necessary */ 351 popstack(nb) 352 { 353 if (nb > 0 && nb <= 8) 354 printf("addq.l #%d,sp\n",nb); 1File: UTIL.C Page 7 355 else if (nb > 0) 356 printf("adda.l #%d,sp\n",nb); 357 }