|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.