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