1*15896Ssam static char *sccsid ="@(#)code.c 1.2 (Berkeley) 01/25/84"; 29700Slinton # include "mfile1" 39700Slinton # include <sys/types.h> 49700Slinton # include <a.out.h> 59700Slinton # include <stab.h> 69700Slinton 79700Slinton int proflg = 0; /* are we generating profiling code? */ 89700Slinton int strftn = 0; /* is the current function one which returns a value */ 99700Slinton int gdebug; 109700Slinton int fdefflag; /* are we within a function definition ? */ 119700Slinton char NULLNAME[8]; 129700Slinton int labelno; 139700Slinton 149700Slinton branch( n ){ 159700Slinton /* output a branch to label n */ 169700Slinton /* exception is an ordinary function branching to retlab: then, return */ 179700Slinton if( n == retlab && !strftn ){ 189700Slinton printf( " ret\n" ); 199700Slinton } 209700Slinton else printf( " jbr L%d\n", n ); 219700Slinton } 229700Slinton 239700Slinton int lastloc = { -1 }; 249700Slinton 259700Slinton short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; 269700Slinton #define LOG2SZ 9 279700Slinton 289700Slinton defalign(n) { 299700Slinton /* cause the alignment to become a multiple of n */ 309700Slinton n /= SZCHAR; 319700Slinton if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 ); 329700Slinton } 339700Slinton 349700Slinton locctr( l ){ 359700Slinton register temp; 369700Slinton /* l is PROG, ADATA, DATA, STRNG, ISTRNG, or STAB */ 379700Slinton 389700Slinton if( l == lastloc ) return(l); 399700Slinton temp = lastloc; 409700Slinton lastloc = l; 419700Slinton switch( l ){ 429700Slinton 439700Slinton case PROG: 449700Slinton printf( " .text\n" ); 459700Slinton psline(); 469700Slinton break; 479700Slinton 489700Slinton case DATA: 499700Slinton case ADATA: 509700Slinton printf( " .data\n" ); 519700Slinton break; 529700Slinton 539700Slinton case STRNG: 549700Slinton printf( " .data 1\n" ); 559700Slinton break; 569700Slinton 579700Slinton case ISTRNG: 589700Slinton printf( " .data 2\n" ); 599700Slinton break; 609700Slinton 619700Slinton case STAB: 629700Slinton printf( " .stab\n" ); 639700Slinton break; 649700Slinton 659700Slinton default: 669700Slinton cerror( "illegal location counter" ); 679700Slinton } 689700Slinton 699700Slinton return( temp ); 709700Slinton } 719700Slinton 729700Slinton deflab( n ){ 739700Slinton /* output something to define the current position as label n */ 749700Slinton printf( "L%d:\n", n ); 759700Slinton } 769700Slinton 779700Slinton int crslab = 10; 789700Slinton 799700Slinton getlab(){ 809700Slinton /* return a number usable for a label */ 819700Slinton return( ++crslab ); 829700Slinton } 839700Slinton 849700Slinton 859700Slinton int ent_mask[] = { 869700Slinton 0,0,0,0,0, 0xfc0, 0xf80, 0xf00, 0xe00, 0xc00, 0x800, 0}; 879700Slinton 889700Slinton int reg_use = 11; 899700Slinton 909700Slinton efcode(){ 919700Slinton /* code for the end of a function */ 929700Slinton 939700Slinton if( strftn ){ /* copy output (in R2) to caller */ 949700Slinton register NODE *l, *r; 959700Slinton register struct symtab *p; 969700Slinton register TWORD t; 979700Slinton register int j; 989700Slinton int i; 999700Slinton 1009700Slinton p = &stab[curftn]; 1019700Slinton t = p->stype; 1029700Slinton t = DECREF(t); 1039700Slinton 1049700Slinton deflab( retlab ); 1059700Slinton 1069700Slinton i = getlab(); /* label for return area */ 1079700Slinton #ifndef LCOMM 1089700Slinton printf(" .data\n" ); 1099700Slinton printf(" .align 2\n" ); 1109700Slinton printf("L%d: .space %d\n", i, tsize(t, p->dimoff, p->sizoff)/SZCHAR ); 1119700Slinton printf(" .text\n" ); 1129700Slinton #else 1139700Slinton { int sz = tsize(t, p->dimoff, p->sizoff) / SZCHAR; 1149700Slinton if (sz % sizeof (int)) 1159700Slinton sz += sizeof (int) - (sz % sizeof (int)); 1169700Slinton printf(" .lcomm L%d,%d\n", i, sz); 1179700Slinton } 1189700Slinton #endif 1199700Slinton psline(); 1209700Slinton printf(" movab L%d,r1\n", i); 1219700Slinton 1229700Slinton reached = 1; 1239700Slinton l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 1249700Slinton l->tn.rval = 1; /* R1 */ 1259700Slinton l->tn.lval = 0; /* no offset */ 1269700Slinton r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 1279700Slinton r->tn.rval = 0; /* R0 */ 1289700Slinton r->tn.lval = 0; 1299700Slinton l = buildtree( UNARY MUL, l, NIL ); 1309700Slinton r = buildtree( UNARY MUL, r, NIL ); 1319700Slinton l = buildtree( ASSIGN, l, r ); 1329700Slinton l->in.op = FREE; 1339700Slinton ecomp( l->in.left ); 1349700Slinton printf( " movab L%d,r0\n", i ); 1359700Slinton /* turn off strftn flag, so return sequence will be generated */ 1369700Slinton strftn = 0; 1379700Slinton } 1389700Slinton branch( retlab ); 1399700Slinton #ifndef VMS 1409700Slinton printf( " .set L%d,0x%x\n", ftnno, ent_mask[reg_use] ); 1419700Slinton #else 1429700Slinton printf( " .set L%d,%d # Hex = 0x%x\n", ftnno, 0x3c| ent_mask[reg_use], ent_mask[reg_use] ); 1439700Slinton /* KLS kludge, under VMS if you use regs 2-5, you must save them. */ 1449700Slinton #endif 1459700Slinton reg_use = 11; 1469700Slinton p2bend(); 1479700Slinton fdefflag = 0; 1489700Slinton } 1499700Slinton 1509700Slinton int ftlab1, ftlab2; 1519700Slinton 1529700Slinton bfcode( a, n ) int a[]; { 1539700Slinton /* code for the beginning of a function; a is an array of 1549700Slinton indices in stab for the arguments; n is the number */ 1559700Slinton register i; 1569700Slinton register temp; 1579700Slinton register struct symtab *p; 1589700Slinton int off; 1599700Slinton char *toreg(); 1609700Slinton 1619700Slinton locctr( PROG ); 1629700Slinton p = &stab[curftn]; 1639700Slinton printf( " .align 1\n"); 1649700Slinton defnam( p ); 1659700Slinton temp = p->stype; 1669700Slinton temp = DECREF(temp); 1679700Slinton strftn = (temp==STRTY) || (temp==UNIONTY); 1689700Slinton 1699700Slinton retlab = getlab(); 1709700Slinton 1719700Slinton /* routine prolog */ 1729700Slinton 1739700Slinton printf( " .word L%d\n", ftnno); 1749700Slinton ftlab1 = getlab(); 1759700Slinton ftlab2 = getlab(); 1769700Slinton printf( " jbr L%d\n", ftlab1); 1779700Slinton printf( "L%d:\n", ftlab2); 1789700Slinton if( proflg ) { /* profile code */ 1799700Slinton i = getlab(); 1809700Slinton printf(" movab L%d,r0\n", i); 1819700Slinton printf(" jsb mcount\n"); 1829700Slinton printf(" .data\n"); 1839700Slinton printf(" .align 2\n"); 1849700Slinton printf("L%d: .long 0\n", i); 1859700Slinton printf(" .text\n"); 1869700Slinton psline(); 1879700Slinton } 1889700Slinton 1899700Slinton off = ARGINIT; 1909700Slinton 1919700Slinton for( i=0; i<n; ++i ){ 1929700Slinton p = &stab[a[i]]; 1939700Slinton if( p->sclass == REGISTER ){ 1949700Slinton temp = p->offset; /* save register number */ 1959700Slinton p->sclass = PARAM; /* forget that it is a register */ 1969700Slinton p->offset = NOOFFSET; 1979700Slinton oalloc( p, &off ); 1989700Slinton /*tbl*/ printf( " %s %d(ap),r%d\n", toreg(p->stype), p->offset/SZCHAR, temp ); 1999700Slinton p->offset = temp; /* remember register number */ 2009700Slinton p->sclass = REGISTER; /* remember that it is a register */ 2019700Slinton } 2029700Slinton else if( p->stype == STRTY || p->stype == UNIONTY ) { 2039700Slinton p->offset = NOOFFSET; 2049700Slinton if( oalloc( p, &off ) ) cerror( "bad argument" ); 2059700Slinton SETOFF( off, ALSTACK ); 2069700Slinton } 2079700Slinton else { 2089700Slinton if( oalloc( p, &off ) ) cerror( "bad argument" ); 2099700Slinton } 2109700Slinton 2119700Slinton } 212*15896Ssam if (gdebug) { 213*15896Ssam #ifdef STABDOT 214*15896Ssam pstabdot(N_SLINE, lineno); 215*15896Ssam #else 216*15896Ssam pstab(NULLNAME, N_SLINE); 217*15896Ssam printf("0,%d,LL%d\n", lineno, labelno); 218*15896Ssam printf("LL%d:\n", labelno++); 219*15896Ssam #endif 220*15896Ssam } 2219700Slinton fdefflag = 1; 2229700Slinton } 2239700Slinton 2249700Slinton bccode(){ /* called just before the first executable statment */ 2259700Slinton /* by now, the automatics and register variables are allocated */ 2269700Slinton SETOFF( autooff, SZINT ); 2279700Slinton /* set aside store area offset */ 2289700Slinton p2bbeg( autooff, regvar ); 2299700Slinton reg_use = (reg_use > regvar ? regvar : reg_use); 2309700Slinton } 2319700Slinton 2329700Slinton ejobcode( flag ){ 2339700Slinton /* called just before final exit */ 2349700Slinton /* flag is 1 if errors, 0 if none */ 2359700Slinton } 2369700Slinton 2379700Slinton aobeg(){ 2389700Slinton /* called before removing automatics from stab */ 2399700Slinton } 2409700Slinton 2419700Slinton aocode(p) struct symtab *p; { 2429700Slinton /* called when automatic p removed from stab */ 2439700Slinton } 2449700Slinton 2459700Slinton aoend(){ 2469700Slinton /* called after removing all automatics from stab */ 2479700Slinton } 2489700Slinton 2499700Slinton defnam( p ) register struct symtab *p; { 2509700Slinton /* define the current location as the name p->sname */ 2519700Slinton 2529700Slinton if( p->sclass == EXTDEF ){ 2539700Slinton printf( " .globl %s\n", exname( p->sname ) ); 2549700Slinton } 2559700Slinton if( p->sclass == STATIC && p->slevel>1 ) deflab( p->offset ); 2569700Slinton else printf( "%s:\n", exname( p->sname ) ); 2579700Slinton 2589700Slinton } 2599700Slinton 2609700Slinton bycode( t, i ){ 2619700Slinton #ifdef ASSTRINGS 2629700Slinton static int lastoctal = 0; 2639700Slinton #endif 2649700Slinton 2659700Slinton /* put byte i+1 in a string */ 2669700Slinton 2679700Slinton #ifdef ASSTRINGS 2689700Slinton 2699700Slinton i &= 077; 2709700Slinton if ( t < 0 ){ 2719700Slinton if ( i != 0 ) printf( "\"\n" ); 2729700Slinton } else { 2739700Slinton if ( i == 0 ) printf("\t.ascii\t\""); 2749700Slinton if ( t == '\\' || t == '"'){ 2759700Slinton lastoctal = 0; 2769700Slinton printf("\\%c", t); 2779700Slinton } 2789700Slinton /* 2799700Slinton * We escape the colon in strings so that 2809700Slinton * c2 will, in its infinite wisdom, interpret 2819700Slinton * the characters preceding the colon as a label. 2829700Slinton * If we didn't escape the colon, c2 would 2839700Slinton * throw away any trailing blanks or tabs after 2849700Slinton * the colon, but reconstruct a assembly 2859700Slinton * language semantically correct program. 2869700Slinton * C2 hasn't been taught about strings. 2879700Slinton */ 2889700Slinton else if ( t == ':' || t < 040 || t >= 0177 ){ 2899700Slinton lastoctal++; 2909700Slinton printf("\\%o",t); 2919700Slinton } 2929700Slinton else if ( lastoctal && '0' <= t && t <= '9' ){ 2939700Slinton lastoctal = 0; 2949700Slinton printf("\"\n\t.ascii\t\"%c", t ); 2959700Slinton } 2969700Slinton else 2979700Slinton { 2989700Slinton lastoctal = 0; 2999700Slinton putchar(t); 3009700Slinton } 3019700Slinton if ( i == 077 ) printf("\"\n"); 3029700Slinton } 3039700Slinton #else 3049700Slinton 3059700Slinton i &= 07; 3069700Slinton if( t < 0 ){ /* end of the string */ 3079700Slinton if( i != 0 ) printf( "\n" ); 3089700Slinton } 3099700Slinton 3109700Slinton else { /* stash byte t into string */ 3119700Slinton if( i == 0 ) printf( " .byte " ); 3129700Slinton else printf( "," ); 3139700Slinton printf( "0x%x", t ); 3149700Slinton if( i == 07 ) printf( "\n" ); 3159700Slinton } 3169700Slinton #endif 3179700Slinton } 3189700Slinton 3199700Slinton zecode( n ){ 3209700Slinton /* n integer words of zeros */ 3219700Slinton OFFSZ temp; 3229700Slinton if( n <= 0 ) return; 3239700Slinton printf( " .space %d\n", (SZINT/SZCHAR)*n ); 3249700Slinton temp = n; 3259700Slinton inoff += temp*SZINT; 3269700Slinton } 3279700Slinton 3289700Slinton fldal( t ) unsigned t; { /* return the alignment of field of type t */ 3299700Slinton uerror( "illegal field type" ); 3309700Slinton return( ALINT ); 3319700Slinton } 3329700Slinton 3339700Slinton fldty( p ) struct symtab *p; { /* fix up type of field p */ 3349700Slinton ; 3359700Slinton } 3369700Slinton 3379700Slinton where(c){ /* print location of error */ 3389700Slinton /* c is either 'u', 'c', or 'w' */ 3399700Slinton /* GCOS version */ 3409700Slinton fprintf( stderr, "%s, line %d: ", ftitle, lineno ); 3419700Slinton } 3429700Slinton 3439700Slinton 3449700Slinton /* tbl - toreg() returns a pointer to a char string 3459700Slinton which is the correct "register move" for the passed type 3469700Slinton */ 3479700Slinton struct type_move {TWORD fromtype; char tostrng[8];} toreg_strs[] = 3489700Slinton { 3499700Slinton CHAR, "cvtbl", 3509700Slinton SHORT, "cvtwl", 3519700Slinton INT, "movl", 3529700Slinton LONG, "movl", 3539700Slinton FLOAT, "movf", 3549700Slinton DOUBLE, "movd", 3559700Slinton UCHAR, "movzbl", 3569700Slinton USHORT, "movzwl", 3579700Slinton UNSIGNED, "movl", 3589700Slinton ULONG, "movl", 3599700Slinton -1, "" 3609700Slinton }; 3619700Slinton 3629700Slinton char 3639700Slinton *toreg(type) 3649700Slinton TWORD type; 3659700Slinton { 3669700Slinton struct type_move *p; 3679700Slinton 3689700Slinton for ( p=toreg_strs; p->fromtype > 0; p++) 3699700Slinton if (p->fromtype == type) return(p->tostrng); 3709700Slinton 3719700Slinton /* type not found, must be a pointer type */ 3729700Slinton return("movl"); 3739700Slinton } 3749700Slinton /* tbl */ 3759700Slinton 3769700Slinton 3779700Slinton main( argc, argv ) char *argv[]; { 3789700Slinton #ifdef BUFSTDERR 3799700Slinton char errbuf[BUFSIZ]; 3809700Slinton setbuf(stderr, errbuf); 3819700Slinton #endif 3829700Slinton return(mainp1( argc, argv )); 3839700Slinton } 3849700Slinton 3859700Slinton struct sw heapsw[SWITSZ]; /* heap for switches */ 3869700Slinton 3879700Slinton genswitch(p,n) register struct sw *p;{ 3889700Slinton /* p points to an array of structures, each consisting 3899700Slinton of a constant value and a label. 3909700Slinton The first is >=0 if there is a default label; 3919700Slinton its value is the label number 3929700Slinton The entries p[1] to p[n] are the nontrivial cases 3939700Slinton */ 3949700Slinton register i; 3959700Slinton register CONSZ j, range; 3969700Slinton register dlab, swlab; 3979700Slinton 3989700Slinton range = p[n].sval-p[1].sval; 3999700Slinton 4009700Slinton if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ 4019700Slinton 4029700Slinton swlab = getlab(); 4039700Slinton dlab = p->slab >= 0 ? p->slab : getlab(); 4049700Slinton 4059700Slinton /* already in r0 */ 4069700Slinton printf(" casel r0,$%ld,$%ld\n", p[1].sval, range); 4079700Slinton printf("L%d:\n", swlab); 4089700Slinton for( i=1,j=p[1].sval; i<=n; j++) { 4099700Slinton printf(" .word L%d-L%d\n", (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab), 4109700Slinton swlab); 4119700Slinton } 4129700Slinton 4139700Slinton if( p->slab >= 0 ) branch( dlab ); 4149700Slinton else printf("L%d:\n", dlab); 4159700Slinton return; 4169700Slinton 4179700Slinton } 4189700Slinton 4199700Slinton if( n>8 ) { /* heap switch */ 4209700Slinton 4219700Slinton heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); 4229700Slinton makeheap(p, n, 1); /* build heap */ 4239700Slinton 4249700Slinton walkheap(1, n); /* produce code */ 4259700Slinton 4269700Slinton if( p->slab >= 0 ) 4279700Slinton branch( dlab ); 4289700Slinton else 4299700Slinton printf("L%d:\n", dlab); 4309700Slinton return; 4319700Slinton } 4329700Slinton 4339700Slinton /* debugging code */ 4349700Slinton 4359700Slinton /* out for the moment 4369700Slinton if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); 4379700Slinton */ 4389700Slinton 4399700Slinton /* simple switch code */ 4409700Slinton 4419700Slinton for( i=1; i<=n; ++i ){ 4429700Slinton /* already in r0 */ 4439700Slinton 4449700Slinton printf( " cmpl r0,$" ); 4459700Slinton printf( CONFMT, p[i].sval ); 4469700Slinton printf( "\n jeql L%d\n", p[i].slab ); 4479700Slinton } 4489700Slinton 4499700Slinton if( p->slab>=0 ) branch( p->slab ); 4509700Slinton } 4519700Slinton 4529700Slinton makeheap(p, m, n) 4539700Slinton register struct sw *p; 4549700Slinton { 4559700Slinton register int q; 4569700Slinton 4579700Slinton q = select(m); 4589700Slinton heapsw[n] = p[q]; 4599700Slinton if( q>1 ) makeheap(p, q-1, 2*n); 4609700Slinton if( q<m ) makeheap(p+q, m-q, 2*n+1); 4619700Slinton } 4629700Slinton 4639700Slinton select(m) { 4649700Slinton register int l,i,k; 4659700Slinton 4669700Slinton for(i=1; ; i*=2) 4679700Slinton if( (i-1) > m ) break; 4689700Slinton l = ((k = i/2 - 1) + 1)/2; 4699700Slinton return( l + (m-k < l ? m-k : l)); 4709700Slinton } 4719700Slinton 4729700Slinton walkheap(start, limit) 4739700Slinton { 4749700Slinton int label; 4759700Slinton 4769700Slinton 4779700Slinton if( start > limit ) return; 4789700Slinton printf(" cmpl r0,$%d\n", heapsw[start].sval); 4799700Slinton printf(" jeql L%d\n", heapsw[start].slab); 4809700Slinton if( (2*start) > limit ) { 4819700Slinton printf(" jbr L%d\n", heapsw[0].slab); 4829700Slinton return; 4839700Slinton } 4849700Slinton if( (2*start+1) <= limit ) { 4859700Slinton label = getlab(); 4869700Slinton printf(" jgtr L%d\n", label); 4879700Slinton } else 4889700Slinton printf(" jgtr L%d\n", heapsw[0].slab); 4899700Slinton walkheap( 2*start, limit); 4909700Slinton if( (2*start+1) <= limit ) { 4919700Slinton printf("L%d:\n", label); 4929700Slinton walkheap( 2*start+1, limit); 4939700Slinton } 4949700Slinton } 495