|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid ="@(#)code.c 1.4 (Berkeley) 4/2/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: #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 int 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 int 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 int i; ! 161: register int 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 int i; ! 400: register CONSZ j; ! 401: register CONSZ unsigned range; ! 402: register int 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.