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