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