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