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