1 #ifndef lint 2 static char *sccsid ="@(#)code.c 1.4 (Berkeley) 04/02/85"; 3 #endif lint 4 5 # include "pass1.h" 6 # include <sys/types.h> 7 # include <a.out.h> 8 # include <stab.h> 9 10 int proflg = 0; /* are we generating profiling code? */ 11 int strftn = 0; /* is the current function one which returns a value */ 12 int gdebug; 13 int fdefflag; /* are we within a function definition ? */ 14 char NULLNAME[8]; 15 int labelno; 16 17 branch( n ){ 18 /* output a branch to label n */ 19 /* exception is an ordinary function branching to retlab: then, return */ 20 if( n == retlab && !strftn ){ 21 printf( " ret\n" ); 22 } 23 else printf( " jbr L%d\n", n ); 24 } 25 26 int lastloc = { -1 }; 27 28 short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; 29 #define LOG2SZ 9 30 31 defalign(n) { 32 /* cause the alignment to become a multiple of n */ 33 n /= SZCHAR; 34 if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 ); 35 } 36 37 locctr( l ){ 38 register temp; 39 /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */ 40 41 if( l == lastloc ) return(l); 42 temp = lastloc; 43 lastloc = l; 44 switch( l ){ 45 46 case PROG: 47 printf( " .text\n" ); 48 psline(); 49 break; 50 51 case DATA: 52 case ADATA: 53 printf( " .data\n" ); 54 break; 55 56 case STRNG: 57 printf( " .data 1\n" ); 58 break; 59 60 case ISTRNG: 61 printf( " .data 2\n" ); 62 break; 63 64 case STAB: 65 printf( " .stab\n" ); 66 break; 67 68 default: 69 cerror( "illegal location counter" ); 70 } 71 72 return( temp ); 73 } 74 75 deflab( n ){ 76 /* output something to define the current position as label n */ 77 printf( "L%d:\n", n ); 78 } 79 80 int crslab = 10; 81 82 getlab(){ 83 /* return a number usable for a label */ 84 return( ++crslab ); 85 } 86 87 88 int ent_mask[] = { 89 0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0}; 90 91 int reg_use = 11; 92 93 efcode(){ 94 /* code for the end of a function */ 95 96 if( strftn ){ /* copy output (in R2) to caller */ 97 register NODE *l, *r; 98 register struct symtab *p; 99 register TWORD t; 100 int i; 101 102 p = &stab[curftn]; 103 t = p->stype; 104 t = DECREF(t); 105 106 deflab( retlab ); 107 108 i = getlab(); /* label for return area */ 109 #ifndef LCOMM 110 printf(" .data\n" ); 111 printf(" .align 2\n" ); 112 printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR ); 113 printf(" .text\n" ); 114 #else 115 { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR; 116 if (sz % sizeof (int)) 117 sz += sizeof (int) - (sz % sizeof (int)); 118 printf(" .lcomm L%d,%d\n", i, sz); 119 } 120 #endif 121 psline(); 122 printf(" movab L%d,r1\n", i); 123 124 reached = 1; 125 l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 126 l->tn.rval = 1; /* R1 */ 127 l->tn.lval = 0; /* no offset */ 128 r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 129 r->tn.rval = 0; /* R0 */ 130 r->tn.lval = 0; 131 l = buildtree( UNARY MUL, l, NIL ); 132 r = buildtree( UNARY MUL, r, NIL ); 133 l = buildtree( ASSIGN, l, r ); 134 l->in.op = FREE; 135 ecomp( l->in.left ); 136 printf( " movab L%d,r0\n", i ); 137 /* turn off strftn flag, so return sequence will be generated */ 138 strftn = 0; 139 } 140 branch( retlab ); 141 #ifndef VMS 142 printf( " .set L%d,0x%x\n", ftnno, ent_mask[reg_use] ); 143 #else 144 printf( " .set L%d,%d # Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use] ); 145 /* KLS kludge, under VMS if you use regs 2-5, you must save them. */ 146 #endif 147 reg_use = 11; 148 p2bend(); 149 fdefflag = 0; 150 } 151 152 int ftlab1, ftlab2; 153 154 bfcode( a, n ) int a[]; { 155 /* code for the beginning of a function; a is an array of 156 indices in stab for the arguments; n is the number */ 157 register i; 158 register temp; 159 register struct symtab *p; 160 int off; 161 char *toreg(); 162 163 locctr( PROG ); 164 p = &stab[curftn]; 165 printf( " .align 1\n"); 166 defnam( p ); 167 temp = p->stype; 168 temp = DECREF(temp); 169 strftn = (temp==STRTY) || (temp==UNIONTY); 170 171 retlab = getlab(); 172 173 /* routine prolog */ 174 175 printf( " .word L%d\n", ftnno); 176 ftlab1 = getlab(); 177 ftlab2 = getlab(); 178 printf( " jbr L%d\n", ftlab1); 179 printf( "L%d:\n", ftlab2); 180 if( proflg ) { /* profile code */ 181 i = getlab(); 182 printf(" movab L%d,r0\n", i); 183 printf(" jsb mcount\n"); 184 printf(" .data\n"); 185 printf(" .align 2\n"); 186 printf("L%d: .long 0\n", i); 187 printf(" .text\n"); 188 psline(); 189 } 190 191 off = ARGINIT; 192 193 for( i=0; i<n; ++i ){ 194 p = &stab[a[i]]; 195 if( p->sclass == REGISTER ){ 196 temp = p->offset; /* save register number */ 197 p->sclass = PARAM; /* forget that it is a register */ 198 p->offset = NOOFFSET; 199 oalloc( p, &off ); 200 /*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp ); 201 p->offset = temp; /* remember register number */ 202 p->sclass = REGISTER; /* remember that it is a register */ 203 } 204 else if( p->stype == STRTY || p->stype == UNIONTY ) { 205 p->offset = NOOFFSET; 206 if( oalloc( p, &off ) ) cerror( "bad argument" ); 207 SETOFF( off, ALSTACK ); 208 } 209 else { 210 if( oalloc( p, &off ) ) cerror( "bad argument" ); 211 } 212 213 } 214 if (gdebug) { 215 #ifdef STABDOT 216 pstabdot(N_SLINE, lineno); 217 #else 218 pstab(NULLNAME, N_SLINE); 219 printf("0,%d,LL%d\n", lineno, labelno); 220 printf("LL%d:\n", labelno++); 221 #endif 222 } 223 fdefflag = 1; 224 } 225 226 bccode(){ /* called just before the first executable statment */ 227 /* by now, the automatics and register variables are allocated */ 228 SETOFF( autooff, SZINT ); 229 /* set aside store area offset */ 230 p2bbeg( autooff, regvar ); 231 reg_use = (reg_use > regvar ? regvar : reg_use); 232 } 233 234 ejobcode( flag ){ 235 /* called just before final exit */ 236 /* flag is 1 if errors, 0 if none */ 237 } 238 239 aobeg(){ 240 /* called before removing automatics from stab */ 241 } 242 243 aocode(p) struct symtab *p; { 244 /* called when automatic p removed from stab */ 245 } 246 247 aoend(){ 248 /* called after removing all automatics from stab */ 249 } 250 251 defnam( p ) register struct symtab *p; { 252 /* define the current location as the name p->sname */ 253 254 if( p->sclass == EXTDEF ){ 255 printf( " .globl %s\n", exname( p->sname ) ); 256 } 257 if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset ); 258 else printf( "%s:\n", exname( p->sname ) ); 259 260 } 261 262 bycode( t, i ){ 263 #ifdef ASSTRINGS 264 static int lastoctal = 0; 265 #endif 266 267 /* put byte i+1 in a string */ 268 269 #ifdef ASSTRINGS 270 271 i &= 077; 272 if ( t < 0 ){ 273 if ( i != 0 ) printf( "\"\n" ); 274 } else { 275 if ( i == 0 ) printf("\t.ascii\t\""); 276 if ( t == '\\' || t == '"'){ 277 lastoctal = 0; 278 printf("\\%c", t); 279 } 280 /* 281 * We escape the colon in strings so that 282 * c2 will, in its infinite wisdom, interpret 283 * the characters preceding the colon as a label. 284 * If we didn't escape the colon, c2 would 285 * throw away any trailing blanks or tabs after 286 * the colon, but reconstruct a assembly 287 * language semantically correct program. 288 * C2 hasn't been taught about strings. 289 */ 290 else if ( t == ':' || t < 040 || t >= 0177 ){ 291 lastoctal++; 292 printf("\\%o",t); 293 } 294 else if ( lastoctal && '0' <= t && t <= '9' ){ 295 lastoctal = 0; 296 printf("\"\n\t.ascii\t\"%c", t ); 297 } 298 else 299 { 300 lastoctal = 0; 301 putchar(t); 302 } 303 if ( i == 077 ) printf("\"\n"); 304 } 305 #else 306 307 i &= 07; 308 if( t < 0 ){ /* end of the string */ 309 if( i != 0 ) printf( "\n" ); 310 } 311 312 else { /* stash byte t into string */ 313 if( i == 0 ) printf( " .byte " ); 314 else printf( "," ); 315 printf( "0x%x", t ); 316 if( i == 07 ) printf( "\n" ); 317 } 318 #endif 319 } 320 321 zecode( n ){ 322 /* n integer words of zeros */ 323 OFFSZ temp; 324 if( n <= 0 ) return; 325 printf( " .space %d\n", (SZINT/SZCHAR)*n ); 326 temp = n; 327 inoff += temp*SZINT; 328 } 329 330 fldal( t ) unsigned t; { /* return the alignment of field of type t */ 331 uerror( "illegal field type" ); 332 return( ALINT ); 333 } 334 335 fldty( p ) struct symtab *p; { /* fix up type of field p */ 336 ; 337 } 338 339 where(c){ /* print location of error */ 340 /* c is either 'u', 'c', or 'w' */ 341 /* GCOS version */ 342 fprintf( stderr, "%s, line %d: ", ftitle, lineno ); 343 } 344 345 346 /* tbl - toreg() returns a pointer to a char string 347 which is the correct "register move" for the passed type 348 */ 349 struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] = 350 { 351 CHAR, "cvtbl", 352 SHORT, "cvtwl", 353 INT, "movl", 354 LONG, "movl", 355 FLOAT, "movf", 356 DOUBLE, "movd", 357 UCHAR, "movzbl", 358 USHORT, "movzwl", 359 UNSIGNED, "movl", 360 ULONG, "movl", 361 0, "" 362 }; 363 364 char 365 *toreg(type) 366 TWORD type; 367 { 368 struct type_move *p; 369 370 for ( p=toreg_strs; p->fromtype != 0; p++) 371 if (p->fromtype == type) return(p->tostrng); 372 373 /* type not found, must be a pointer type */ 374 return("movl"); 375 } 376 /* tbl */ 377 378 379 main( argc, argv ) char *argv[]; { 380 #ifdef BUFSTDERR 381 char errbuf[BUFSIZ]; 382 setbuf(stderr, errbuf); 383 #endif 384 return(mainp1( argc, argv )); 385 } 386 387 struct sw heapsw[SWITSZ]; /* heap for switches */ 388 389 genswitch(p,n) register struct sw *p;{ 390 /* p points to an array of structures, each consisting 391 of a constant value and a label. 392 The first is >=0 if there is a default label; 393 its value is the label number 394 The entries p[1] to p[n] are the nontrivial cases 395 */ 396 register i; 397 register CONSZ j, range; 398 register dlab, swlab; 399 400 range = p[n].sval-p[1].sval; 401 402 if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ 403 404 swlab = getlab(); 405 dlab = p->slab >= 0 ? p->slab : getlab(); 406 407 /* already in r0 */ 408 printf(" casel r0,$%ld,$%ld\n", p[1].sval, range); 409 printf("L%d:\n", swlab); 410 for( i=1,j=p[1].sval; i<=n; j++) { 411 printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab), 412 swlab); 413 } 414 415 if( p->slab >= 0 ) branch( dlab ); 416 else printf("L%d:\n", dlab); 417 return; 418 419 } 420 421 if( n>8 ) { /* heap switch */ 422 423 heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); 424 makeheap(p, n, 1); /* build heap */ 425 426 walkheap(1, n); /* produce code */ 427 428 if( p->slab >= 0 ) 429 branch( dlab ); 430 else 431 printf("L%d:\n", dlab); 432 return; 433 } 434 435 /* debugging code */ 436 437 /* out for the moment 438 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); 439 */ 440 441 /* simple switch code */ 442 443 for( i=1; i<=n; ++i ){ 444 /* already in r0 */ 445 446 printf( " cmpl r0,$" ); 447 printf( CONFMT, p[i].sval ); 448 printf( "\n jeql L%d\n", p[i].slab ); 449 } 450 451 if( p->slab>=0 ) branch( p->slab ); 452 } 453 454 makeheap(p, m, n) 455 register struct sw *p; 456 { 457 register int q; 458 459 q = select(m); 460 heapsw[n] = p[q]; 461 if( q>1 ) makeheap(p, q-1, 2*n); 462 if( q<m ) makeheap(p+q, m-q, 2*n+1); 463 } 464 465 select(m) { 466 register int l,i,k; 467 468 for(i=1; ; i*=2) 469 if( (i-1) > m ) break; 470 l = ((k = i/2 - 1) + 1)/2; 471 return( l + (m-k < l ? m-k : l)); 472 } 473 474 walkheap(start, limit) 475 { 476 int label; 477 478 479 if( start > limit ) return; 480 printf(" cmpl r0,$%d\n", heapsw[start].sval); 481 printf(" jeql L%d\n", heapsw[start].slab); 482 if( (2*start) > limit ) { 483 printf(" jbr L%d\n", heapsw[0].slab); 484 return; 485 } 486 if( (2*start+1) <= limit ) { 487 label = getlab(); 488 printf(" jgtr L%d\n", label); 489 } else 490 printf(" jgtr L%d\n", heapsw[0].slab); 491 walkheap( 2*start, limit); 492 if( (2*start+1) <= limit ) { 493 printf("L%d:\n", label); 494 walkheap( 2*start+1, limit); 495 } 496 } 497