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