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