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