117742Sralph # ifndef lint 2*32938Sdonn static char *sccsid ="@(#)local2.c 1.32 (Berkeley) 12/11/87"; 317742Sralph # endif 417742Sralph 518556Sralph # include "pass2.h" 632935Sdonn # include <ctype.h> 732935Sdonn 832935Sdonn # define putstr(s) fputs((s), stdout) 932935Sdonn 109702Slinton # ifdef FORT 119702Slinton int ftlab1, ftlab2; 129702Slinton # endif 139702Slinton /* a lot of the machine dependent parts of the second pass */ 149702Slinton 159702Slinton # define BITMASK(n) ((1L<<n)-1) 169702Slinton 1732924Sdonn /*ARGSUSED*/ 189702Slinton where(c){ 199702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno ); 209702Slinton } 219702Slinton 229702Slinton lineid( l, fn ) char *fn; { 239702Slinton /* identify line l and file fn */ 249702Slinton printf( "# line %d, file %s\n", l, fn ); 259702Slinton } 269702Slinton 279702Slinton 289702Slinton eobl2(){ 2932935Sdonn register OFFSZ spoff; /* offset from stack pointer */ 3032935Sdonn #ifndef FORT 3132935Sdonn extern int ftlab1, ftlab2; 3232935Sdonn #endif 3332935Sdonn 349702Slinton spoff = maxoff; 359702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 369702Slinton spoff /= SZCHAR; 379702Slinton SETOFF(spoff,4); 3832935Sdonn #ifdef FORT 399702Slinton #ifndef FLEXNAMES 409702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff ); 419702Slinton #else 429702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 439702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff ); 449702Slinton #endif 459702Slinton #else 469702Slinton printf( "L%d:\n", ftlab1); 479702Slinton if( spoff!=0 ) 489702Slinton if( spoff < 64 ) 499702Slinton printf( " subl2 $%ld,sp\n", spoff); 509702Slinton else 519702Slinton printf( " movab -%ld(sp),sp\n", spoff); 529702Slinton printf( " jbr L%d\n", ftlab2); 539702Slinton #endif 549702Slinton maxargs = -1; 559702Slinton } 569702Slinton 579702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = { 589702Slinton 599702Slinton PLUS, "add", 609702Slinton MINUS, "sub", 619702Slinton MUL, "mul", 629702Slinton DIV, "div", 639702Slinton OR, "bis", 649702Slinton ER, "xor", 659702Slinton AND, "bic", 669702Slinton -1, "" }; 679702Slinton 689702Slinton hopcode( f, o ){ 699702Slinton /* output the appropriate string from the above table */ 709702Slinton 719702Slinton register struct hoptab *q; 729702Slinton 7332935Sdonn if(asgop(o)) 7432935Sdonn o = NOASG o; 759702Slinton for( q = ioptab; q->opmask>=0; ++q ){ 769702Slinton if( q->opmask == o ){ 7732935Sdonn printf( "%s%c", q->opstring, tolower(f)); 789702Slinton return; 799702Slinton } 809702Slinton } 819702Slinton cerror( "no hoptab for %s", opst[o] ); 829702Slinton } 839702Slinton 849702Slinton char * 859702Slinton rnames[] = { /* keyed to register number tokens */ 869702Slinton 879702Slinton "r0", "r1", 889702Slinton "r2", "r3", "r4", "r5", 899702Slinton "r6", "r7", "r8", "r9", "r10", "r11", 909702Slinton "ap", "fp", "sp", "pc", 919702Slinton }; 929702Slinton 939702Slinton int rstatus[] = { 949702Slinton SAREG|STAREG, SAREG|STAREG, 959702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 969702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 979702Slinton SAREG, SAREG, SAREG, SAREG, 989702Slinton }; 999702Slinton 1009702Slinton tlen(p) NODE *p; 1019702Slinton { 1029702Slinton switch(p->in.type) { 1039702Slinton case CHAR: 1049702Slinton case UCHAR: 1059702Slinton return(1); 1069702Slinton 1079702Slinton case SHORT: 1089702Slinton case USHORT: 10932937Sdonn return(SZSHORT/SZCHAR); 1109702Slinton 1119702Slinton case DOUBLE: 11232937Sdonn return(SZDOUBLE/SZCHAR); 1139702Slinton 1149702Slinton default: 11532937Sdonn return(SZINT/SZCHAR); 1169702Slinton } 1179702Slinton } 1189702Slinton 1199702Slinton mixtypes(p, q) NODE *p, *q; 1209702Slinton { 12116181Sralph register TWORD tp, tq; 1229702Slinton 1239702Slinton tp = p->in.type; 1249702Slinton tq = q->in.type; 1259702Slinton 1269702Slinton return( (tp==FLOAT || tp==DOUBLE) != 1279702Slinton (tq==FLOAT || tq==DOUBLE) ); 1289702Slinton } 1299702Slinton 1309702Slinton prtype(n) NODE *n; 1319702Slinton { 1329702Slinton switch (n->in.type) 1339702Slinton { 13432935Sdonn 1359702Slinton case DOUBLE: 13624418Smckusick putchar('d'); 1379702Slinton return; 1389702Slinton 1399702Slinton case FLOAT: 14024418Smckusick putchar('f'); 1419702Slinton return; 1429702Slinton 1439702Slinton case LONG: 1449702Slinton case ULONG: 1459702Slinton case INT: 1469702Slinton case UNSIGNED: 14724418Smckusick putchar('l'); 1489702Slinton return; 1499702Slinton 1509702Slinton case SHORT: 1519702Slinton case USHORT: 15224418Smckusick putchar('w'); 1539702Slinton return; 1549702Slinton 1559702Slinton case CHAR: 1569702Slinton case UCHAR: 15724418Smckusick putchar('b'); 1589702Slinton return; 1599702Slinton 1609702Slinton default: 1619702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 1629702Slinton else { 16324418Smckusick putchar('l'); 1649702Slinton return; 1659702Slinton } 1669702Slinton } 1679702Slinton } 1689702Slinton 1699702Slinton zzzcode( p, c ) register NODE *p; { 17032935Sdonn register int m; 17132924Sdonn int val; 1729702Slinton switch( c ){ 1739702Slinton 1749702Slinton case 'N': /* logical ops, turned into 0-1 */ 1759702Slinton /* use register given by register 1 */ 1769702Slinton cbgen( 0, m=getlab(), 'I' ); 1779702Slinton deflab( p->bn.label ); 1789702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 1799702Slinton deflab( m ); 1809702Slinton return; 1819702Slinton 1829702Slinton case 'P': 1839702Slinton cbgen( p->in.op, p->bn.label, c ); 1849702Slinton return; 1859702Slinton 1869702Slinton case 'A': 18732935Sdonn case 'V': 18832935Sdonn sconv( p, c == 'V' ); 1899702Slinton return; 1909702Slinton 19125751Sdonn case 'G': /* i *= f; asgops with int lhs and float rhs */ 19225751Sdonn { 19325751Sdonn register NODE *l, *r, *s; 19425751Sdonn int rt; 19525751Sdonn 19625751Sdonn l = p->in.left; 19725751Sdonn r = p->in.right; 19825751Sdonn s = talloc(); 19925751Sdonn rt = r->in.type; 20025751Sdonn 20125751Sdonn s->in.op = SCONV; 20225751Sdonn s->in.left = l; 20325751Sdonn s->in.type = rt; 20425751Sdonn zzzcode(s, 'A'); 20525751Sdonn putstr("\n\t"); 20625751Sdonn 20725751Sdonn hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 20825751Sdonn putstr("2\t"); 20925751Sdonn adrput(r); 21025751Sdonn putchar(','); 21125751Sdonn adrput(resc); 21225751Sdonn putstr("\n\t"); 21325751Sdonn 21425751Sdonn s->in.op = ASSIGN; 21525751Sdonn s->in.left = l; 21625751Sdonn s->in.right = resc; 21725751Sdonn s->in.type = l->in.type; 21825751Sdonn zzzcode(s, 'A'); 21925751Sdonn 22025751Sdonn s->in.op = FREE; 22125751Sdonn return; 22225751Sdonn } 22325751Sdonn 22432928Sdonn case 'J': /* unsigned DIV/MOD with constant divisors */ 22532928Sdonn { 22632928Sdonn register int ck = INAREG; 22732928Sdonn int label1, label2; 22832928Sdonn 22932928Sdonn /* case constant <= 1 is handled by optim() in pass 1 */ 23032928Sdonn /* case constant < 0x80000000 is handled in table */ 23132928Sdonn switch( p->in.op ) { 232*32938Sdonn /* case DIV: handled in optim2() */ 23332928Sdonn case MOD: 23432928Sdonn if( p->in.left->in.op == REG && 23532928Sdonn p->in.left->tn.rval == resc->tn.rval ) 23632928Sdonn goto asgmod; 23732928Sdonn label1 = getlab(); 23832928Sdonn expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n"); 23932928Sdonn printf("\tjlssu\tL%d\n", label1); 24032928Sdonn expand(p, ck, "\tsubl2\tAR,A1\n"); 24132928Sdonn printf("L%d:", label1); 24232928Sdonn break; 24332928Sdonn case ASG DIV: 24432928Sdonn label1 = getlab(); 24532928Sdonn label2 = getlab(); 24632928Sdonn expand(p, ck, "cmpl\tAL,AR\n"); 24732928Sdonn printf("\tjgequ\tL%d\n", label1); 24832928Sdonn expand(p, ck, "\tmovl\t$1,AL\n"); 24932928Sdonn printf("\tjbr\tL%d\nL%d:\n", label2, label1); 25032928Sdonn expand(p, ck, "\tclrl\tAL\n"); 25132928Sdonn printf("L%d:", label2); 25232928Sdonn break; 25332928Sdonn case ASG MOD: 25432928Sdonn asgmod: 25532928Sdonn label1 = getlab(); 25632928Sdonn expand(p, ck, "cmpl\tAL,AR\n"); 25732928Sdonn printf("\tjlssu\tL%d\n", label1); 25832928Sdonn expand(p, ck, "\tsubl2\tAR,AL\n"); 25932928Sdonn printf("L%d:", label1); 26032928Sdonn break; 26132928Sdonn } 26232928Sdonn return; 26332928Sdonn } 26432928Sdonn 2659702Slinton case 'B': /* get oreg value in temp register for left shift */ 2669702Slinton { 2679702Slinton register NODE *r; 2689702Slinton if (xdebug) eprint(p, 0, &val, &val); 2699702Slinton r = p->in.right; 27032937Sdonn if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT ) 27124418Smckusick putstr("movl"); 2729702Slinton else { 27332935Sdonn putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); 2749702Slinton prtype(r); 27524418Smckusick putchar('l'); 2769702Slinton } 2779702Slinton return; 2789702Slinton } 2799702Slinton 2809702Slinton case 'C': /* num words pushed on arg stack */ 2819702Slinton { 2829702Slinton extern int gc_numbytes; 2839702Slinton extern int xdebug; 2849702Slinton 2859702Slinton if (xdebug) printf("->%d<-",gc_numbytes); 2869702Slinton 2879702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 2889702Slinton return; 2899702Slinton } 2909702Slinton 2919702Slinton case 'D': /* INCR and DECR */ 2929702Slinton zzzcode(p->in.left, 'A'); 29324418Smckusick putchar('\n'); 29424418Smckusick putchar('\t'); 2959702Slinton 2969702Slinton case 'E': /* INCR and DECR, FOREFF */ 29732934Sdonn if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1) 2989702Slinton { 29932935Sdonn putstr(p->in.op == INCR ? "inc" : "dec"); 3009702Slinton prtype(p->in.left); 30124418Smckusick putchar('\t'); 3029702Slinton adrput(p->in.left); 3039702Slinton return; 3049702Slinton } 30532935Sdonn putstr(p->in.op == INCR ? "add" : "sub"); 3069702Slinton prtype(p->in.left); 30724418Smckusick putchar('2'); 30824418Smckusick putchar('\t'); 3099702Slinton adrput(p->in.right); 31024418Smckusick putchar(','); 3119702Slinton adrput(p->in.left); 3129702Slinton return; 3139702Slinton 3149702Slinton case 'F': /* register type of right operand */ 3159702Slinton { 3169702Slinton register NODE *n; 3179702Slinton extern int xdebug; 3189702Slinton register int ty; 3199702Slinton 3209702Slinton n = getlr( p, 'R' ); 3219702Slinton ty = n->in.type; 3229702Slinton 3239702Slinton if (xdebug) printf("->%d<-", ty); 3249702Slinton 32524418Smckusick if ( ty==DOUBLE) putchar('d'); 32624418Smckusick else if ( ty==FLOAT ) putchar('f'); 32724418Smckusick else putchar('l'); 3289702Slinton return; 3299702Slinton } 3309702Slinton 3319702Slinton case 'L': /* type of left operand */ 3329702Slinton case 'R': /* type of right operand */ 3339702Slinton { 3349702Slinton register NODE *n; 3359702Slinton extern int xdebug; 3369702Slinton 33716181Sralph n = getlr( p, c ); 3389702Slinton if (xdebug) printf("->%d<-", n->in.type); 3399702Slinton 3409702Slinton prtype(n); 3419702Slinton return; 3429702Slinton } 3439702Slinton 344*32938Sdonn case 'Z': /* AND for CC with ICON -- lval is complemented */ 345*32938Sdonn { 346*32938Sdonn register NODE *l, *r; 347*32938Sdonn 348*32938Sdonn l = getlr( p, 'L' ); 349*32938Sdonn r = getlr( p, 'R' ); 350*32938Sdonn m = (1 << tlen(l) * SZCHAR) - 1; 351*32938Sdonn r->tn.lval = ~r->tn.lval; 352*32938Sdonn if( (l->in.type == CHAR || l->in.type == SHORT) && 353*32938Sdonn (r->tn.lval & ~m) ) { 354*32938Sdonn putstr("cvt"); 355*32938Sdonn prtype(l); 356*32938Sdonn putstr("l\t"); 357*32938Sdonn adrput(l); 358*32938Sdonn putchar(','); 359*32938Sdonn adrput(resc); 360*32938Sdonn putstr("\n\t"); 361*32938Sdonn resc->tn.type = INT; 362*32938Sdonn l = resc; 363*32938Sdonn } 364*32938Sdonn else if( l->in.type == UCHAR || l->in.type == USHORT ) 365*32938Sdonn /* remove trash left over from complementing */ 366*32938Sdonn r->tn.lval &= m; 367*32938Sdonn putstr("bit"); 368*32938Sdonn prtype(l); 369*32938Sdonn printf("\t$%ld", r->tn.lval); 370*32938Sdonn putchar(','); 371*32938Sdonn adrput(l); 3729702Slinton return; 373*32938Sdonn } 3749702Slinton 3759702Slinton case 'U': /* 32 - n, for unsigned right shifts */ 3769702Slinton printf("$%d", 32 - p->in.right->tn.lval ); 3779702Slinton return; 3789702Slinton 3799702Slinton case 'T': /* rounded structure length for arguments */ 3809702Slinton { 3819702Slinton int size; 3829702Slinton 3839702Slinton size = p->stn.stsize; 3849702Slinton SETOFF( size, 4); 3859702Slinton printf("$%d", size); 3869702Slinton return; 3879702Slinton } 3889702Slinton 3899702Slinton case 'S': /* structure assignment */ 39032935Sdonn stasg(p); 39132935Sdonn break; 3929702Slinton 39332935Sdonn default: 39432935Sdonn cerror( "illegal zzzcode" ); 39532935Sdonn } 39632935Sdonn } 3979702Slinton 39832935Sdonn stasg(p) 39932935Sdonn register NODE *p; 40032935Sdonn { 40132935Sdonn register NODE *l, *r; 40232935Sdonn register size; 4039702Slinton 40432935Sdonn if( p->in.op == STASG ){ 40532935Sdonn l = p->in.left; 40632935Sdonn r = p->in.right; 4079702Slinton 40832935Sdonn } 40932935Sdonn else if( p->in.op == STARG ){ /* store an arg into a temporary */ 41032935Sdonn r = p->in.left; 41132935Sdonn } 41232935Sdonn else cerror( "STASG bad" ); 4139702Slinton 41432935Sdonn if( r->in.op == ICON ) r->in.op = NAME; 41532935Sdonn else if( r->in.op == REG ) r->in.op = OREG; 41632935Sdonn else if( r->in.op != OREG ) cerror( "STASG-r" ); 4179702Slinton 41832935Sdonn size = p->stn.stsize; 41932935Sdonn 42032935Sdonn if( size <= 0 || size > 65535 ) 42132935Sdonn cerror("structure size <0=0 or >65535"); 42232935Sdonn 42332935Sdonn switch(size) { 42432935Sdonn case 1: 42532935Sdonn putstr(" movb "); 42632935Sdonn break; 42732935Sdonn case 2: 42832935Sdonn putstr(" movw "); 42932935Sdonn break; 43032935Sdonn case 4: 43132935Sdonn putstr(" movl "); 43232935Sdonn break; 43332935Sdonn case 8: 43432935Sdonn putstr(" movq "); 43532935Sdonn break; 43632935Sdonn default: 43732935Sdonn printf(" movc3 $%d,", size); 43832935Sdonn break; 43932935Sdonn } 44032935Sdonn adrput(r); 44132935Sdonn if( p->in.op == STASG ){ 44232935Sdonn putchar(','); 44332935Sdonn adrput(l); 44432935Sdonn putchar('\n'); 44532935Sdonn } 44632935Sdonn else 44732935Sdonn putstr(",(sp)\n"); 44832935Sdonn 44932935Sdonn if( r->in.op == NAME ) r->in.op = ICON; 45032935Sdonn else if( r->in.op == OREG ) r->in.op = REG; 45132935Sdonn } 45232935Sdonn 45332935Sdonn NODE *makearg( ty ) int ty; { 45432935Sdonn register NODE *p, *q; 45532935Sdonn 45632935Sdonn /* build a -(sp) operand */ 45732935Sdonn p = talloc(); 45832935Sdonn p->in.op = REG; 45932935Sdonn /* the type needn't be right, just consistent */ 46032935Sdonn p->in.type = INCREF(ty); 46132935Sdonn p->tn.rval = SP; 46232935Sdonn p->tn.lval = 0; 46332935Sdonn q = talloc(); 46432935Sdonn q->in.op = ASG MINUS; 46532935Sdonn q->in.type = INCREF(ty); 46632935Sdonn q->in.left = p; 46732935Sdonn p = talloc(); 46832935Sdonn p->in.op = ICON; 46932935Sdonn p->in.type = INT; 47032935Sdonn p->tn.name = ""; 471*32938Sdonn p->tn.lval = szty(ty) * (SZINT/SZCHAR); 47232935Sdonn q->in.right = p; 47332935Sdonn p = talloc(); 47432935Sdonn p->in.op = UNARY MUL; 47532935Sdonn p->in.left = q; 47632935Sdonn return( p ); 47732935Sdonn } 47832935Sdonn 47932935Sdonn sconv( p, forarg ) register NODE *p; { 48032935Sdonn register NODE *l, *r; 48132935Sdonn int m, val; 48232935Sdonn 48332935Sdonn if (xdebug) eprint(p, 0, &val, &val); 48432935Sdonn r = getlr(p, 'R'); 48532935Sdonn if (p->in.op == ASSIGN) 48632935Sdonn l = getlr(p, 'L'); 48732935Sdonn else if (p->in.op == SCONV) { 48832935Sdonn #if defined(FORT) || defined(SPRECC) 48932935Sdonn m = r->in.type; 49032935Sdonn #else 49132935Sdonn m = r->in.type==FLOAT ? DOUBLE : r->in.type; 49232935Sdonn #endif 49332935Sdonn if (forarg) 49432935Sdonn l = makearg( m ); 49532935Sdonn else 49632935Sdonn l = resc; 49732935Sdonn l->in.type = m; 49832935Sdonn r = getlr(p, 'L'); 49932935Sdonn } 50032935Sdonn else { /* OPLTYPE */ 50132935Sdonn #if defined(FORT) || defined(SPRECC) 50232935Sdonn m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 50332935Sdonn #else 50432935Sdonn m = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 50532935Sdonn #endif 50632935Sdonn if (forarg) 50732935Sdonn l = makearg( m ); 50832935Sdonn else 50932935Sdonn l = resc; 51032935Sdonn l->in.type = m; 51132935Sdonn } 51232935Sdonn if (r->in.op == ICON) 51332935Sdonn if (r->in.name[0] == '\0') { 514*32938Sdonn if (r->tn.lval == 0 && !forarg) { 51532935Sdonn putstr("clr"); 51632935Sdonn prtype(l); 51732935Sdonn putchar('\t'); 51816418Sralph adrput(l); 51932935Sdonn goto cleanup; 52016418Sralph } 52132935Sdonn if (r->tn.lval < 0 && r->tn.lval >= -63) { 52232935Sdonn putstr("mneg"); 52332935Sdonn prtype(l); 52432935Sdonn r->tn.lval = -r->tn.lval; 52532935Sdonn goto ops; 52632935Sdonn } 52732935Sdonn if (r->tn.lval < 0) 52832935Sdonn r->in.type = r->tn.lval >= -128 ? CHAR 52932935Sdonn : (r->tn.lval >= -32768 ? SHORT 53032935Sdonn : INT); 53132935Sdonn else if (l->in.type == FLOAT || 53232935Sdonn l->in.type == DOUBLE) 53332935Sdonn r->in.type = r->tn.lval <= 63 ? INT 53432935Sdonn : (r->tn.lval <= 127 ? CHAR 53532935Sdonn : (r->tn.lval <= 32767 ? SHORT 53632935Sdonn : INT)); 53716418Sralph else 53832935Sdonn r->in.type = r->tn.lval <= 63 ? INT 53932935Sdonn : (r->tn.lval <= 127 ? CHAR 54032935Sdonn : (r->tn.lval <= 255 ? UCHAR 54132935Sdonn : (r->tn.lval <= 32767 ? SHORT 54232935Sdonn : (r->tn.lval <= 65535 ? USHORT 54332935Sdonn : INT)))); 544*32938Sdonn if (forarg && r->in.type == INT) { 545*32938Sdonn putstr("pushl\t"); 546*32938Sdonn adrput(r); 547*32938Sdonn goto cleanup; 548*32938Sdonn } 54932935Sdonn } 55032935Sdonn else { 551*32938Sdonn if (forarg && tlen(r) == SZINT/SZCHAR) { 552*32938Sdonn putstr("pushl\t"); 553*32938Sdonn adrput(r); 554*32938Sdonn goto cleanup; 555*32938Sdonn } 556*32938Sdonn putstr("moval\t"); 55732935Sdonn acon(r); 55832935Sdonn putchar(','); 55932935Sdonn adrput(l); 56032935Sdonn goto cleanup; 56132935Sdonn } 5629702Slinton 56332935Sdonn if (p->in.op == SCONV && 56432935Sdonn !(l->in.type == FLOAT || l->in.type == DOUBLE) && 56532935Sdonn !mixtypes(l, r)) { 56632935Sdonn /* 56732935Sdonn * Because registers must always contain objects 56832935Sdonn * of the same width as INTs, we may have to 56932935Sdonn * perform two conversions to get an INT. Can 57032935Sdonn * the conversions be collapsed into one? 57132935Sdonn */ 57232935Sdonn if (m = collapsible(l, r)) 57332935Sdonn r->in.type = m; 57432935Sdonn else { 57532935Sdonn /* 57632935Sdonn * Two steps are required. 57732935Sdonn */ 57832935Sdonn NODE *x = &resc[1]; 5799702Slinton 58032935Sdonn *x = *l; 58132935Sdonn if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 58232935Sdonn putstr("movz"); 58332935Sdonn else 58432935Sdonn putstr("cvt"); 58532935Sdonn prtype(r); 58632935Sdonn prtype(x); 58732935Sdonn putchar('\t'); 58832935Sdonn adrput(r); 58932935Sdonn putchar(','); 59032935Sdonn adrput(x); 59132935Sdonn putchar('\n'); 59232935Sdonn putchar('\t'); 59332935Sdonn r = x; 5949702Slinton } 59532935Sdonn l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 59632935Sdonn } 5979702Slinton 59832935Sdonn if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 59932935Sdonn mixtypes(l, r)) { 60032935Sdonn int label1, label2; 60132935Sdonn 60232935Sdonn label1 = getlab(); 60332935Sdonn label2 = getlab(); 60432935Sdonn 60532935Sdonn putstr("movl\t"); 60632935Sdonn adrput(r); 60732935Sdonn putchar(','); 60832935Sdonn adrput(l); 60932935Sdonn putstr("\n\tjbsc\t$31,"); 61032935Sdonn adrput(l); 61132935Sdonn printf(",L%d\n\tcvtl", label1); 61232935Sdonn prtype(l); 61332935Sdonn putchar('\t'); 61432935Sdonn adrput(l); 61532935Sdonn putchar(','); 61632935Sdonn adrput(l); 61732935Sdonn printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 61832935Sdonn prtype(l); 61932935Sdonn putchar('\t'); 62032935Sdonn adrput(l); 62132935Sdonn putchar(','); 62232935Sdonn adrput(l); 62332935Sdonn putstr("\n\tadd"); 62432935Sdonn prtype(l); 62532935Sdonn putstr("2\t$0"); 62632935Sdonn prtype(l); 62732935Sdonn putstr("2.147483648e9,"); 62832935Sdonn adrput(l); 62932935Sdonn printf("\nL%d:", label2); 63032935Sdonn 63132935Sdonn goto cleanup; 6329702Slinton } 63332935Sdonn 63432935Sdonn if (!mixtypes(l,r)) { 63532935Sdonn if (tlen(l) == tlen(r)) { 636*32938Sdonn if (forarg && tlen(l) == SZINT/SZCHAR) { 637*32938Sdonn putstr("pushl\t"); 638*32938Sdonn adrput(r); 639*32938Sdonn goto cleanup; 640*32938Sdonn } 64132935Sdonn putstr("mov"); 64232935Sdonn #ifdef FORT 64332935Sdonn if (Oflag) 64432935Sdonn prtype(l); 64532935Sdonn else { 64632935Sdonn if (l->in.type == DOUBLE) 64732935Sdonn putchar('q'); 64832935Sdonn else if(l->in.type == FLOAT) 64932935Sdonn putchar('l'); 65032935Sdonn else 65132935Sdonn prtype(l); 65232935Sdonn } 65332935Sdonn #else 65432935Sdonn prtype(l); 65532935Sdonn #endif FORT 65632935Sdonn goto ops; 65732935Sdonn } 65832935Sdonn else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 65932935Sdonn putstr("movz"); 66032935Sdonn else 66132935Sdonn putstr("cvt"); 66232935Sdonn } 66332935Sdonn else 66432935Sdonn putstr("cvt"); 66532935Sdonn prtype(r); 66632935Sdonn prtype(l); 66732935Sdonn ops: 66832935Sdonn putchar('\t'); 66932935Sdonn adrput(r); 67032935Sdonn putchar(','); 67132935Sdonn adrput(l); 67232935Sdonn 67332935Sdonn cleanup: 67432935Sdonn if (forarg) 67532935Sdonn tfree(l); 6769702Slinton } 6779702Slinton 67823536Sbloom /* 67923536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 68023536Sbloom * can be accomplished in one instruction, return the type of src 68123536Sbloom * that will do the job correctly; otherwise return 0. Note that 68223536Sbloom * a register must always end up having type INT or UNSIGNED. 68323536Sbloom */ 68423536Sbloom int 68523536Sbloom collapsible(dest, src) 68623536Sbloom NODE *dest, *src; 68723536Sbloom { 68823536Sbloom int st = src->in.type; 68923536Sbloom int dt = dest->in.type; 69023536Sbloom int newt = 0; 69123536Sbloom 69223536Sbloom /* 69323536Sbloom * Are there side effects of evaluating src? 69423536Sbloom * If the derived type will not be the same size as src, 69524418Smckusick * we may have to use two steps. 69623536Sbloom */ 69724418Smckusick if (tlen(src) > tlen(dest)) { 69824418Smckusick if (tshape(src, STARREG)) 69924418Smckusick return (0); 70024418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval)) 70124418Smckusick return (0); 70224418Smckusick } 70323536Sbloom 70423536Sbloom /* 70523536Sbloom * Can we get an object of dest's type by punning src? 70623536Sbloom * Praises be to great Cthulhu for little-endian machines... 70723536Sbloom */ 70823536Sbloom if (st == CHAR && dt == USHORT) 70923536Sbloom /* 71023536Sbloom * Special case -- we must sign-extend to 16 bits. 71123536Sbloom */ 71223536Sbloom return (0); 71323536Sbloom 71423536Sbloom if (tlen(src) < tlen(dest)) 71523536Sbloom newt = st; 71623536Sbloom else 71723536Sbloom newt = dt; 71823536Sbloom 71923536Sbloom return (newt); 72023536Sbloom } 72123536Sbloom 72217742Sralph rmove( rt, rs, t ) TWORD t; { 7239702Slinton printf( " %s %s,%s\n", 72417742Sralph #ifdef FORT 72517742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 72617742Sralph #endif 7279702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 7289702Slinton rnames[rs], rnames[rt] ); 7299702Slinton } 7309702Slinton 7319702Slinton struct respref 7329702Slinton respref[] = { 7339702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 7349702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 7359702Slinton INTEMP, INTEMP, 7369702Slinton FORARG, FORARG, 7379702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 7389702Slinton 0, 0 }; 7399702Slinton 7409702Slinton setregs(){ /* set up temporary registers */ 7419702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 7429702Slinton } 7439702Slinton 74432924Sdonn /*ARGSUSED*/ 7459702Slinton rewfld( p ) NODE *p; { 7469702Slinton return(1); 7479702Slinton } 7489702Slinton 74932924Sdonn /*ARGSUSED*/ 7509702Slinton callreg(p) NODE *p; { 7519702Slinton return( R0 ); 7529702Slinton } 7539702Slinton 7549702Slinton base( p ) register NODE *p; { 7559702Slinton register int o = p->in.op; 7569702Slinton 757*32938Sdonn if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */ 7589702Slinton if( o==REG ) return( p->tn.rval ); 7599702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 7609702Slinton return( p->in.left->tn.rval ); 7619702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 7629702Slinton return( p->tn.rval + 0200*1 ); 7639702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 7649702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 7659702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 7669702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 7679702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 768*32938Sdonn if( o==NAME ) return( 100 + 0200*1 ); 7699702Slinton return( -1 ); 7709702Slinton } 7719702Slinton 7729702Slinton offset( p, tyl ) register NODE *p; int tyl; { 7739702Slinton 77424418Smckusick if( tyl==1 && 77524418Smckusick p->in.op==REG && 77624418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) ) 77724418Smckusick return( p->tn.rval ); 77824418Smckusick if( p->in.op==LS && 77924418Smckusick p->in.left->in.op==REG && 78024418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 78124418Smckusick p->in.right->in.op==ICON && 78224418Smckusick p->in.right->in.name[0]=='\0' && 78324418Smckusick (1<<p->in.right->tn.lval)==tyl) 7849702Slinton return( p->in.left->tn.rval ); 78524418Smckusick if( tyl==2 && 78624418Smckusick p->in.op==PLUS && 78724418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 78824418Smckusick p->in.left->in.op==REG && 78924418Smckusick p->in.right->in.op==REG && 79024418Smckusick p->in.left->tn.rval==p->in.right->tn.rval ) 79124418Smckusick return( p->in.left->tn.rval ); 7929702Slinton return( -1 ); 7939702Slinton } 7949702Slinton 7959702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 7969702Slinton register NODE *t; 7979702Slinton NODE *f; 7989702Slinton 7999702Slinton p->in.op = OREG; 8009702Slinton f = p->in.left; /* have to free this subtree later */ 8019702Slinton 8029702Slinton /* init base */ 8039702Slinton switch (q->in.op) { 8049702Slinton case ICON: 8059702Slinton case REG: 8069702Slinton case OREG: 807*32938Sdonn case NAME: 8089702Slinton t = q; 8099702Slinton break; 8109702Slinton 8119702Slinton case MINUS: 8129702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 8139702Slinton case PLUS: 8149702Slinton t = q->in.right; 8159702Slinton break; 8169702Slinton 8179702Slinton case INCR: 8189702Slinton case ASG MINUS: 8199702Slinton t = q->in.left; 8209702Slinton break; 8219702Slinton 8229702Slinton case UNARY MUL: 8239702Slinton t = q->in.left->in.left; 8249702Slinton break; 8259702Slinton 8269702Slinton default: 8279702Slinton cerror("illegal makeor2"); 8289702Slinton } 8299702Slinton 8309702Slinton p->tn.lval = t->tn.lval; 8319702Slinton #ifndef FLEXNAMES 83232924Sdonn { 83332924Sdonn register int i; 83432924Sdonn for(i=0; i<NCHNAM; ++i) 83532924Sdonn p->in.name[i] = t->in.name[i]; 83632924Sdonn } 8379702Slinton #else 8389702Slinton p->in.name = t->in.name; 8399702Slinton #endif 8409702Slinton 8419702Slinton /* init offset */ 8429702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 8439702Slinton 8449702Slinton tfree(f); 8459702Slinton return; 8469702Slinton } 8479702Slinton 8489702Slinton canaddr( p ) NODE *p; { 8499702Slinton register int o = p->in.op; 8509702Slinton 8519702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 8529702Slinton return(0); 8539702Slinton } 8549702Slinton 85532935Sdonn flshape( p ) NODE *p; { 85632935Sdonn register int o = p->in.op; 85732935Sdonn 85832935Sdonn return( o == REG || o == NAME || o == ICON || 85932935Sdonn (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 8609702Slinton } 8619702Slinton 86232926Sdonn /* INTEMP shapes must not contain any temporary registers */ 8639702Slinton shtemp( p ) register NODE *p; { 86432926Sdonn int r; 86532926Sdonn 8669702Slinton if( p->in.op == STARG ) p = p->in.left; 86732926Sdonn 86832926Sdonn switch (p->in.op) { 86932926Sdonn case REG: 87032926Sdonn return( !istreg(p->tn.rval) ); 87132926Sdonn case OREG: 87232926Sdonn r = p->tn.rval; 87332926Sdonn if( R2TEST(r) ) { 87432926Sdonn if( istreg(R2UPK1(r)) ) 87532926Sdonn return(0); 87632926Sdonn r = R2UPK2(r); 87732926Sdonn } 87832926Sdonn return( !istreg(r) ); 87932926Sdonn case UNARY MUL: 88032926Sdonn p = p->in.left; 88132926Sdonn return( p->in.op != UNARY MUL && shtemp(p) ); 88232926Sdonn } 88332926Sdonn 88432926Sdonn if( optype( p->in.op ) != LTYPE ) return(0); 88532926Sdonn return(1); 8869702Slinton } 8879702Slinton 8889702Slinton shumul( p ) register NODE *p; { 88932935Sdonn register int o; 8909702Slinton extern int xdebug; 8919702Slinton 8929702Slinton if (xdebug) { 89332933Sdonn int val; 89432933Sdonn printf("shumul:\n"); 89532933Sdonn eprint(p, 0, &val, &val); 8969702Slinton } 8979702Slinton 8989702Slinton o = p->in.op; 8999702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 9009702Slinton 9019702Slinton if( ( o == INCR || o == ASG MINUS ) && 9029702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 9039702Slinton p->in.right->in.name[0] == '\0' ) 9049702Slinton { 90517659Sralph switch (p->in.type) 9069702Slinton { 9079702Slinton case CHAR|PTR: 9089702Slinton case UCHAR|PTR: 9099702Slinton o = 1; 9109702Slinton break; 9119702Slinton 9129702Slinton case SHORT|PTR: 9139702Slinton case USHORT|PTR: 9149702Slinton o = 2; 9159702Slinton break; 9169702Slinton 9179702Slinton case INT|PTR: 9189702Slinton case UNSIGNED|PTR: 9199702Slinton case LONG|PTR: 9209702Slinton case ULONG|PTR: 9219702Slinton case FLOAT|PTR: 9229702Slinton o = 4; 9239702Slinton break; 9249702Slinton 9259702Slinton case DOUBLE|PTR: 9269702Slinton o = 8; 9279702Slinton break; 9289702Slinton 9299702Slinton default: 93017742Sralph if ( ISPTR(p->in.type) && 93117742Sralph ISPTR(DECREF(p->in.type)) ) { 9329702Slinton o = 4; 9339702Slinton break; 9349702Slinton } 9359702Slinton else return(0); 9369702Slinton } 9379702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 9389702Slinton } 9399702Slinton 9409702Slinton return( 0 ); 9419702Slinton } 9429702Slinton 9439702Slinton adrcon( val ) CONSZ val; { 94424418Smckusick putchar( '$' ); 9459702Slinton printf( CONFMT, val ); 9469702Slinton } 9479702Slinton 9489702Slinton conput( p ) register NODE *p; { 9499702Slinton switch( p->in.op ){ 9509702Slinton 9519702Slinton case ICON: 9529702Slinton acon( p ); 9539702Slinton return; 9549702Slinton 9559702Slinton case REG: 95624418Smckusick putstr( rnames[p->tn.rval] ); 9579702Slinton return; 9589702Slinton 9599702Slinton default: 9609702Slinton cerror( "illegal conput" ); 9619702Slinton } 9629702Slinton } 9639702Slinton 96432923Sdonn /*ARGSUSED*/ 96532924Sdonn insput( p ) NODE *p; { 9669702Slinton cerror( "insput" ); 9679702Slinton } 9689702Slinton 96932928Sdonn upput( p, size ) NODE *p; int size; { 97032928Sdonn if( size == SZLONG && p->in.op == REG ) { 97132928Sdonn putstr( rnames[p->tn.rval + 1] ); 97232928Sdonn return; 97332928Sdonn } 9749702Slinton cerror( "upput" ); 9759702Slinton } 9769702Slinton 9779702Slinton adrput( p ) register NODE *p; { 9789702Slinton register int r; 9799702Slinton /* output an address, with offsets, from p */ 9809702Slinton 9819702Slinton if( p->in.op == FLD ){ 9829702Slinton p = p->in.left; 9839702Slinton } 9849702Slinton switch( p->in.op ){ 9859702Slinton 9869702Slinton case NAME: 9879702Slinton acon( p ); 9889702Slinton return; 9899702Slinton 9909702Slinton case ICON: 9919702Slinton /* addressable value of the constant */ 99224418Smckusick putchar( '$' ); 9939702Slinton acon( p ); 9949702Slinton return; 9959702Slinton 9969702Slinton case REG: 99724418Smckusick putstr( rnames[p->tn.rval] ); 9989702Slinton return; 9999702Slinton 10009702Slinton case OREG: 10019702Slinton r = p->tn.rval; 10029702Slinton if( R2TEST(r) ){ /* double indexing */ 10039702Slinton register int flags; 10049702Slinton 10059702Slinton flags = R2UPK3(r); 100624418Smckusick if( flags & 1 ) putchar('*'); 100724418Smckusick if( flags & 4 ) putchar('-'); 10089702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 10099702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 101024418Smckusick if( flags & 2 ) putchar('+'); 10119702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 10129702Slinton return; 10139702Slinton } 10149702Slinton if( r == AP ){ /* in the argument region */ 101532925Sdonn if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 10169702Slinton printf( CONFMT, p->tn.lval ); 101724418Smckusick putstr( "(ap)" ); 10189702Slinton return; 10199702Slinton } 10209702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 10219702Slinton printf( "(%s)", rnames[p->tn.rval] ); 10229702Slinton return; 10239702Slinton 10249702Slinton case UNARY MUL: 10259702Slinton /* STARNM or STARREG found */ 10269702Slinton if( tshape(p, STARNM) ) { 102724418Smckusick putchar( '*' ); 10289702Slinton adrput( p->in.left); 10299702Slinton } 10309702Slinton else { /* STARREG - really auto inc or dec */ 10319702Slinton register NODE *q; 10329702Slinton 103317659Sralph q = p->in.left; 103417742Sralph if( q->in.right->tn.lval != tlen(p) ) 103517742Sralph cerror("adrput: bad auto-increment/decrement"); 103617659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 103717659Sralph rnames[q->in.left->tn.rval], 103817659Sralph (q->in.op==INCR ? "+" : "") ); 10399702Slinton p->in.op = OREG; 104017659Sralph p->tn.rval = q->in.left->tn.rval; 104117659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 10429702Slinton #ifndef FLEXNAMES 10439702Slinton p->in.name[0] = '\0'; 10449702Slinton #else 10459702Slinton p->in.name = ""; 10469702Slinton #endif 10479702Slinton tfree(q); 10489702Slinton } 10499702Slinton return; 10509702Slinton 10519702Slinton default: 10529702Slinton cerror( "illegal address" ); 10539702Slinton return; 10549702Slinton 10559702Slinton } 10569702Slinton 10579702Slinton } 10589702Slinton 10599702Slinton acon( p ) register NODE *p; { /* print out a constant */ 10609702Slinton 106132935Sdonn if( p->in.name[0] == '\0' ) 10629702Slinton printf( CONFMT, p->tn.lval); 106332935Sdonn else { 10649702Slinton #ifndef FLEXNAMES 10659702Slinton printf( "%.8s", p->in.name ); 10669702Slinton #else 106724418Smckusick putstr( p->in.name ); 10689702Slinton #endif 106932935Sdonn if( p->tn.lval != 0 ) { 107032935Sdonn putchar( '+' ); 107132935Sdonn printf( CONFMT, p->tn.lval ); 107232935Sdonn } 10739702Slinton } 10749702Slinton } 10759702Slinton 10769702Slinton genscall( p, cookie ) register NODE *p; { 10779702Slinton /* structure valued call */ 10789702Slinton return( gencall( p, cookie ) ); 10799702Slinton } 10809702Slinton 10819702Slinton /* tbl */ 10829702Slinton int gc_numbytes; 10839702Slinton /* tbl */ 10849702Slinton 108532924Sdonn /*ARGSUSED*/ 10869702Slinton gencall( p, cookie ) register NODE *p; { 10879702Slinton /* generate the call given by p */ 108816418Sralph register NODE *p1; 108932935Sdonn register int temp, temp1; 109032935Sdonn register int m; 10919702Slinton 10929702Slinton if( p->in.right ) temp = argsize( p->in.right ); 10939702Slinton else temp = 0; 10949702Slinton 10959702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 10969702Slinton /* set aside room for structure return */ 10979702Slinton 10989702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 10999702Slinton else temp1 = temp; 11009702Slinton } 11019702Slinton 11029702Slinton if( temp > maxargs ) maxargs = temp; 11039702Slinton SETOFF(temp1,4); 11049702Slinton 11059702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 110616418Sralph genargs( p->in.right ); 11079702Slinton } 11089702Slinton 11099702Slinton p1 = p->in.left; 11109702Slinton if( p1->in.op != ICON ){ 11119702Slinton if( p1->in.op != REG ){ 11129702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 11139702Slinton if( p1->in.op != NAME ){ 11149702Slinton order( p1, INAREG ); 11159702Slinton } 11169702Slinton } 11179702Slinton } 11189702Slinton } 11199702Slinton 11209702Slinton /* tbl 11219702Slinton setup gc_numbytes so reference to ZC works */ 11229702Slinton 11239702Slinton gc_numbytes = temp&(0x3ff); 11249702Slinton /* tbl */ 11259702Slinton 11269702Slinton p->in.op = UNARY CALL; 11279702Slinton m = match( p, INTAREG|INTBREG ); 11289702Slinton 11299702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 11309702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 11319702Slinton if (temp >= 1024) 11329702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 11339702Slinton 11349702Slinton return(m != MDONE); 11359702Slinton } 11369702Slinton 11379702Slinton /* tbl */ 11389702Slinton char * 11399702Slinton ccbranches[] = { 114032935Sdonn "eql", 114132935Sdonn "neq", 114232935Sdonn "leq", 114332935Sdonn "lss", 114432935Sdonn "geq", 114532935Sdonn "gtr", 114632935Sdonn "lequ", 114732935Sdonn "lssu", 114832935Sdonn "gequ", 114932935Sdonn "gtru", 11509702Slinton }; 11519702Slinton /* tbl */ 11529702Slinton 115332924Sdonn /*ARGSUSED*/ 11549702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 11559702Slinton 115632935Sdonn if( o != 0 && ( o < EQ || o > UGT ) ) 115732935Sdonn cerror( "bad conditional branch: %s", opst[o] ); 115832935Sdonn printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); 11599702Slinton } 11609702Slinton 11619702Slinton nextcook( p, cookie ) NODE *p; { 11629702Slinton /* we have failed to match p with cookie; try another */ 11639702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 11649702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 11659702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 11669702Slinton return( FORREW ); 11679702Slinton } 11689702Slinton 116932924Sdonn /*ARGSUSED*/ 11709702Slinton lastchance( p, cook ) NODE *p; { 11719702Slinton /* forget it! */ 11729702Slinton return(0); 11739702Slinton } 11749702Slinton 11759702Slinton optim2( p ) register NODE *p; { 11769702Slinton /* do local tree transformations and optimizations */ 11779702Slinton 117832929Sdonn int o; 117932932Sdonn int i, mask; 118016181Sralph register NODE *l, *r; 11819702Slinton 118232929Sdonn switch( o = p->in.op ) { 11839702Slinton 11849702Slinton case AND: 118519933Smckusick /* commute L and R to eliminate complements and constants */ 118616181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 118716181Sralph l->in.op == COMPL ) { 11889702Slinton p->in.left = p->in.right; 118916181Sralph p->in.right = l; 11909702Slinton } 11919702Slinton case ASG AND: 11929702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 11939702Slinton r = p->in.right; 119432931Sdonn if( r->in.op==ICON && r->in.name[0]==0 ) { 119532931Sdonn /* check for degenerate operations */ 119632931Sdonn l = p->in.left; 119732932Sdonn mask = (1 << tlen(l) * SZCHAR) - 1; 119832932Sdonn if( ISUNSIGNED(r->in.type) ) { 1199*32938Sdonn i = (~r->tn.lval & mask); 1200*32938Sdonn if( i == 0 ) { 120132932Sdonn r->in.op = FREE; 120232932Sdonn ncopy(p, l); 120332932Sdonn l->in.op = FREE; 120432932Sdonn break; 120532932Sdonn } 1206*32938Sdonn else if( i == mask ) 120732932Sdonn goto zero; 120832932Sdonn else 120932932Sdonn r->tn.lval = i; 1210*32938Sdonn break; 121132932Sdonn } 121232932Sdonn else if( r->tn.lval == mask && 121332932Sdonn tlen(l) < SZINT/SZCHAR ) { 121432932Sdonn r->in.op = SCONV; 121532932Sdonn r->in.left = l; 121632932Sdonn r->in.right = 0; 121732932Sdonn r->in.type = ENUNSIGN(l->in.type); 121832932Sdonn r->in.su = l->in.su > 1 ? l->in.su : 1; 121932932Sdonn ncopy(p, r); 122032932Sdonn p->in.left = r; 122132932Sdonn p->in.type = INT; 122232931Sdonn break; 122332931Sdonn } 122432931Sdonn /* complement constant */ 12259702Slinton r->tn.lval = ~r->tn.lval; 12269702Slinton } 12279702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 12289702Slinton r->in.op = FREE; 12299702Slinton p->in.right = r->in.left; 12309702Slinton } 12319702Slinton else { /* insert complement node */ 123216181Sralph p->in.right = l = talloc(); 123316181Sralph l->in.op = COMPL; 123416181Sralph l->in.rall = NOPREF; 123516181Sralph l->in.type = r->in.type; 123616181Sralph l->in.left = r; 123716181Sralph l->in.right = NULL; 12389702Slinton } 12399702Slinton break; 12409702Slinton 124116181Sralph case SCONV: 124219933Smckusick l = p->in.left; 1243*32938Sdonn if( (l->in.type == UCHAR || l->in.type == USHORT) && 1244*32938Sdonn (p->in.type == DOUBLE || p->in.type == FLOAT) ) { 1245*32938Sdonn /* we can convert to INT without loss of significance */ 1246*32938Sdonn r = talloc(); 1247*32938Sdonn *r = *p; 1248*32938Sdonn r->in.type = INT; 1249*32938Sdonn p->in.left = r; 1250*32938Sdonn #if !defined(FORT) && !defined(SPRECC) 1251*32938Sdonn /* nothing to be 'gained' by a FLOAT conversion */ 1252*32938Sdonn p->in.type = DOUBLE; 1253*32938Sdonn #endif 1254*32938Sdonn return; 1255*32938Sdonn } 125617742Sralph #if defined(FORT) || defined(SPRECC) 125716573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 125819933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 125919933Smckusick return; 126016573Sralph #else 126119933Smckusick if( mixtypes(p, l) ) return; 126216573Sralph #endif 1263*32938Sdonn if( l->in.op == PCONV ) 126425751Sdonn return; 1265*32938Sdonn if( (l->in.op == CALL || l->in.op == UNARY CALL) && 1266*32938Sdonn l->in.type != INT && l->in.type != UNSIGNED ) 1267*32938Sdonn return; 126825751Sdonn 126919933Smckusick /* Only trust it to get it right if the size is the same */ 127019933Smckusick if( tlen(p) != tlen(l) ) 127119933Smckusick return; 127216181Sralph 127316181Sralph /* clobber conversion */ 127419933Smckusick if( l->in.op != FLD ) 127516181Sralph l->in.type = p->in.type; 127616181Sralph ncopy( p, l ); 127716181Sralph l->in.op = FREE; 127819933Smckusick 127916181Sralph break; 128016181Sralph 128124418Smckusick case ASSIGN: 128224418Smckusick /* 128324418Smckusick * Conversions are equivalent to assignments; 128424418Smckusick * when the two operations are combined, 128524418Smckusick * we can sometimes zap the conversion. 128624418Smckusick */ 128724418Smckusick r = p->in.right; 128824418Smckusick l = p->in.left; 128924418Smckusick if ( r->in.op == SCONV && 129024418Smckusick !mixtypes(l, r) && 129132922Sdonn l->in.op != FLD && 129224418Smckusick tlen(l) == tlen(r) ) { 129324418Smckusick p->in.right = r->in.left; 129424418Smckusick r->in.op = FREE; 129524418Smckusick } 1296*32938Sdonn else if( (r->in.type == UCHAR || r->in.type == USHORT) && 1297*32938Sdonn (p->in.type == DOUBLE || p->in.type == FLOAT) ) { 1298*32938Sdonn /* we can convert to INT without loss of significance */ 1299*32938Sdonn l = talloc(); 1300*32938Sdonn l->in.op = SCONV; 1301*32938Sdonn l->in.rall = NOPREF; 1302*32938Sdonn l->in.left = r; 1303*32938Sdonn l->in.right = NULL; 1304*32938Sdonn l->in.type = INT; 1305*32938Sdonn p->in.right = r; 1306*32938Sdonn return; 1307*32938Sdonn } 130824418Smckusick break; 130924418Smckusick 131032929Sdonn case ULE: 131132929Sdonn case ULT: 131232929Sdonn case UGE: 131332929Sdonn case UGT: 131432931Sdonn p->in.op -= (UGE-GE); 131532931Sdonn if( degenerate(p) ) 131632931Sdonn break; 131732931Sdonn p->in.op += (UGE-GE); 131832931Sdonn break; 131932931Sdonn 132032929Sdonn case EQ: 132132929Sdonn case NE: 132232929Sdonn case LE: 132332929Sdonn case LT: 132432929Sdonn case GE: 132532929Sdonn case GT: 1326*32938Sdonn if( p->in.left->in.op == SCONV && 1327*32938Sdonn p->in.right->in.op == SCONV ) { 1328*32938Sdonn l = p->in.left; 1329*32938Sdonn r = p->in.right; 1330*32938Sdonn if( l->in.type == DOUBLE && 1331*32938Sdonn l->in.left->in.type == FLOAT && 1332*32938Sdonn r->in.left->in.type == FLOAT ) { 1333*32938Sdonn /* nuke the conversions */ 1334*32938Sdonn p->in.left = l->in.left; 1335*32938Sdonn p->in.right = r->in.left; 1336*32938Sdonn l->in.op = FREE; 1337*32938Sdonn r->in.op = FREE; 1338*32938Sdonn } 1339*32938Sdonn /* more? */ 1340*32938Sdonn } 134132931Sdonn (void) degenerate(p); 134232931Sdonn break; 134332931Sdonn 134432931Sdonn case DIV: 134532931Sdonn if( p->in.right->in.op == ICON && 134632931Sdonn p->in.right->tn.name[0] == '\0' && 134732931Sdonn ISUNSIGNED(p->in.right->in.type) && 134832931Sdonn (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 134932931Sdonn /* easy to do here, harder to do in zzzcode() */ 135032931Sdonn p->in.op = UGE; 135132929Sdonn break; 135232931Sdonn } 135332931Sdonn case MOD: 135432931Sdonn case ASG DIV: 135532931Sdonn case ASG MOD: 135632931Sdonn /* 135732931Sdonn * optimize DIV and MOD 135832931Sdonn * 135932931Sdonn * basically we spot UCHAR and USHORT and try to do them 136032931Sdonn * as signed ints... apparently div+mul+sub is always 136132931Sdonn * faster than ediv for finding MOD on the VAX, when 136232931Sdonn * full unsigned MOD isn't needed. 136332931Sdonn * 136432931Sdonn * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 136532931Sdonn * are faster for unsigned dividend and a constant divisor 136632931Sdonn * in the right range (.5 to 1 of dividend's range for the 136732931Sdonn * first, .333+ to .5 for the second). full unsigned is 136832931Sdonn * already done cmp+sub in the appropriate case; the 136932931Sdonn * other cases are less common and require more ambition. 137032931Sdonn */ 137132931Sdonn if( degenerate(p) ) 137232929Sdonn break; 137332931Sdonn l = p->in.left; 137432931Sdonn r = p->in.right; 137532931Sdonn if( !ISUNSIGNED(r->in.type) || 137632931Sdonn tlen(l) >= SZINT/SZCHAR || 137732931Sdonn !(tlen(r) < SZINT/SZCHAR || 137832931Sdonn (r->in.op == ICON && r->tn.name[0] == '\0')) ) 137932929Sdonn break; 138032931Sdonn if( r->in.op == ICON ) 138132931Sdonn r->tn.type = INT; 138232931Sdonn else { 138332931Sdonn NODE *t = talloc(); 138432931Sdonn t->in.left = r; 138532931Sdonn r = t; 138632931Sdonn r->in.op = SCONV; 138732931Sdonn r->in.type = INT; 138832931Sdonn r->in.right = 0; 138932931Sdonn p->in.right = r; 139032931Sdonn } 139132931Sdonn if( o == DIV || o == MOD ) { 139232931Sdonn NODE *t = talloc(); 139332931Sdonn t->in.left = l; 139432931Sdonn l = t; 139532931Sdonn l->in.op = SCONV; 139632931Sdonn l->in.type = INT; 139732931Sdonn l->in.right = 0; 139832931Sdonn p->in.left = l; 139932931Sdonn } 140032931Sdonn /* handle asgops in table */ 140132931Sdonn break; 140232931Sdonn 140332931Sdonn case RS: 140432931Sdonn case ASG RS: 140532931Sdonn case LS: 140632931Sdonn case ASG LS: 140732931Sdonn /* pick up degenerate shifts */ 140832931Sdonn l = p->in.left; 140932931Sdonn r = p->in.right; 141032931Sdonn if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 141132929Sdonn break; 141232929Sdonn i = r->tn.lval; 141332931Sdonn if( i < 0 ) 141432931Sdonn /* front end 'fixes' this? */ 141532931Sdonn if( o == LS || o == ASG LS ) 141632931Sdonn o += (RS-LS); 141732931Sdonn else 141832931Sdonn o += (LS-RS); 141932931Sdonn if( (o == RS || o == ASG RS) && 142032931Sdonn !ISUNSIGNED(l->in.type) ) 142132931Sdonn /* can't optimize signed right shifts */ 142232929Sdonn break; 142332935Sdonn if( o == LS ) { 142432935Sdonn if( i < SZINT ) 142532935Sdonn break; 142632935Sdonn } 142732935Sdonn else { 142832935Sdonn if( i < tlen(l) * SZCHAR ) 142932935Sdonn break; 143032935Sdonn } 143132931Sdonn zero: 143232931Sdonn if( !asgop( o ) ) 143332931Sdonn if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 143432931Sdonn /* no side effects */ 143532932Sdonn tfree(l); 143632931Sdonn ncopy(p, r); 143732931Sdonn r->in.op = FREE; 143832931Sdonn p->tn.lval = 0; 143932931Sdonn } 144032931Sdonn else { 144132931Sdonn p->in.op = COMOP; 144232932Sdonn r->tn.lval = 0; 144332931Sdonn } 144432931Sdonn else { 144532931Sdonn p->in.op = ASSIGN; 144632931Sdonn r->tn.lval = 0; 144732929Sdonn } 144832931Sdonn break; 144932931Sdonn } 145032931Sdonn } 145132931Sdonn 145232931Sdonn degenerate(p) register NODE *p; { 145332931Sdonn int o; 145432931Sdonn int result, i; 145532931Sdonn int lower, upper; 145632931Sdonn register NODE *l, *r; 145732931Sdonn 145832931Sdonn /* 145932931Sdonn * try to keep degenerate comparisons with constants 146032931Sdonn * out of the table. 146132931Sdonn */ 146232931Sdonn r = p->in.right; 146332931Sdonn l = p->in.left; 146432931Sdonn if( r->in.op != ICON || 146532931Sdonn r->tn.name[0] != '\0' || 146632931Sdonn tlen(l) >= tlen(r) ) 146732931Sdonn return (0); 146832931Sdonn switch( l->in.type ) { 146932931Sdonn case CHAR: 147032931Sdonn lower = -(1 << SZCHAR - 1); 147132931Sdonn upper = (1 << SZCHAR - 1) - 1; 147232931Sdonn break; 147332931Sdonn case UCHAR: 147432931Sdonn lower = 0; 147532931Sdonn upper = (1 << SZCHAR) - 1; 147632931Sdonn break; 147732931Sdonn case SHORT: 147832931Sdonn lower = -(1 << SZSHORT - 1); 147932931Sdonn upper = (1 << SZSHORT - 1) - 1; 148032931Sdonn break; 148132931Sdonn case USHORT: 148232931Sdonn lower = 0; 148332931Sdonn upper = (1 << SZSHORT) - 1; 148432931Sdonn break; 148532931Sdonn default: 148632932Sdonn cerror("unsupported type in degenerate()"); 148732931Sdonn } 148832931Sdonn i = r->tn.lval; 148932931Sdonn switch( o = p->in.op ) { 149032931Sdonn case DIV: 149132931Sdonn case ASG DIV: 149232931Sdonn case MOD: 149332931Sdonn case ASG MOD: 149432931Sdonn /* DIV and MOD work like EQ */ 149532931Sdonn case EQ: 149632931Sdonn case NE: 149732931Sdonn if( lower == 0 && (unsigned) i > upper ) 149832931Sdonn result = o == NE; 149932931Sdonn else if( i < lower || i > upper ) 150032931Sdonn result = o == NE; 150132931Sdonn else 150232931Sdonn return (0); 150332931Sdonn break; 150432931Sdonn case LT: 150532931Sdonn case GE: 150632931Sdonn if( lower == 0 && (unsigned) i > upper ) 150732931Sdonn result = o == LT; 150832931Sdonn else if( i <= lower ) 150932931Sdonn result = o != LT; 151032931Sdonn else if( i > upper ) 151132931Sdonn result = o == LT; 151232931Sdonn else 151332931Sdonn return (0); 151432931Sdonn break; 151532931Sdonn case LE: 151632931Sdonn case GT: 151732931Sdonn if( lower == 0 && (unsigned) i >= upper ) 151832931Sdonn result = o == LE; 151932931Sdonn else if( i < lower ) 152032931Sdonn result = o != LE; 152132931Sdonn else if( i >= upper ) 152232931Sdonn result = o == LE; 152332931Sdonn else 152432931Sdonn return (0); 152532931Sdonn break; 152632931Sdonn default: 152732931Sdonn cerror("unknown op in degenerate()"); 152832931Sdonn } 152932931Sdonn 153032931Sdonn if( o == MOD || o == ASG MOD ) { 153132931Sdonn r->in.op = FREE; 153232931Sdonn ncopy(p, l); 153332931Sdonn l->in.op = FREE; 153432931Sdonn } 153532931Sdonn else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 153632931Sdonn /* no side effects */ 153732932Sdonn tfree(l); 153832931Sdonn ncopy(p, r); 153932931Sdonn r->in.op = FREE; 154032931Sdonn p->tn.lval = result; 154132931Sdonn } 154232931Sdonn else { 154332931Sdonn if( o == ASG DIV ) 154432931Sdonn p->in.op = ASSIGN; 154532929Sdonn else { 154632929Sdonn p->in.op = COMOP; 154732929Sdonn r->tn.type = INT; 154832929Sdonn } 154932931Sdonn r->tn.lval = result; 15509702Slinton } 155132931Sdonn if( logop(o) ) 155232931Sdonn p->in.type = INT; 155332931Sdonn 155432931Sdonn return (1); 15559702Slinton } 15569702Slinton 15579702Slinton /* added by jwf */ 15589702Slinton struct functbl { 15599702Slinton int fop; 15609702Slinton TWORD ftype; 15619702Slinton char *func; 15629702Slinton } opfunc[] = { 15639702Slinton DIV, TANY, "udiv", 15649702Slinton MOD, TANY, "urem", 156517715Sralph ASG DIV, TANY, "audiv", 156617715Sralph ASG MOD, TANY, "aurem", 15679702Slinton 0, 0, 0 }; 15689702Slinton 15699702Slinton hardops(p) register NODE *p; { 15709702Slinton /* change hard to do operators into function calls. */ 15719702Slinton register NODE *q; 15729702Slinton register struct functbl *f; 15739702Slinton register o; 157417742Sralph NODE *old,*temp; 15759702Slinton 15769702Slinton o = p->in.op; 157717742Sralph if( ! (optype(o)==BITYPE && 157817742Sralph (ISUNSIGNED(p->in.left->in.type) || 157917742Sralph ISUNSIGNED(p->in.right->in.type))) ) 158017742Sralph return; 15819702Slinton 15829702Slinton for( f=opfunc; f->fop; f++ ) { 15839702Slinton if( o==f->fop ) goto convert; 15849702Slinton } 15859702Slinton return; 15869702Slinton 15879702Slinton convert: 158832931Sdonn if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 158932928Sdonn /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 159032928Sdonn /* save a subroutine call -- use at most 5 instructions */ 159132928Sdonn return; 159232931Sdonn if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 159332931Sdonn /* optim2() will modify the op into an ordinary int op */ 159432931Sdonn return; 15959702Slinton if( asgop( o ) ) { 159617742Sralph old = NIL; 159717715Sralph switch( p->in.left->in.op ){ 159817742Sralph case FLD: 159917742Sralph q = p->in.left->in.left; 160017742Sralph /* 160117742Sralph * rewrite (lval.fld /= rval); as 160217742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 160317742Sralph * else the compiler will evaluate lval twice. 160417742Sralph */ 160517742Sralph if( q->in.op == UNARY MUL ){ 160617742Sralph /* first allocate a temp storage */ 160717742Sralph temp = talloc(); 160817742Sralph temp->in.op = OREG; 160917742Sralph temp->tn.rval = TMPREG; 161017742Sralph temp->tn.lval = BITOOR(freetemp(1)); 161117742Sralph temp->in.type = INCREF(p->in.type); 161217742Sralph #ifdef FLEXNAMES 161317742Sralph temp->in.name = ""; 161417742Sralph #else 161517742Sralph temp->in.name[0] = '\0'; 161617742Sralph #endif 161717742Sralph old = q->in.left; 161817742Sralph q->in.left = temp; 161917742Sralph } 162017742Sralph /* fall thru ... */ 162117742Sralph 162217715Sralph case REG: 162317715Sralph case NAME: 162417715Sralph case OREG: 162517715Sralph /* change ASG OP to a simple OP */ 162617715Sralph q = talloc(); 162717715Sralph q->in.op = NOASG p->in.op; 162817715Sralph q->in.rall = NOPREF; 162917715Sralph q->in.type = p->in.type; 163017715Sralph q->in.left = tcopy(p->in.left); 163117715Sralph q->in.right = p->in.right; 163217715Sralph p->in.op = ASSIGN; 163317715Sralph p->in.right = q; 163417715Sralph p = q; 163517715Sralph f -= 2; /* Note: this depends on the table order */ 163617742Sralph /* on the right side only - replace *temp with 163717742Sralph *(temp = &lval), build the assignment node */ 163817742Sralph if( old ){ 163917742Sralph temp = q->in.left->in.left; /* the "*" node */ 164017742Sralph q = talloc(); 164117742Sralph q->in.op = ASSIGN; 164217742Sralph q->in.left = temp->in.left; 164317742Sralph q->in.right = old; 164417742Sralph q->in.type = old->in.type; 164517742Sralph #ifdef FLEXNAMES 164617742Sralph q->in.name = ""; 164717742Sralph #else 164817742Sralph q->in.name[0] = '\0'; 164917742Sralph #endif 165017742Sralph temp->in.left = q; 165117742Sralph } 165217715Sralph break; 16539702Slinton 165417715Sralph case UNARY MUL: 165517715Sralph /* avoid doing side effects twice */ 165617715Sralph q = p->in.left; 165717715Sralph p->in.left = q->in.left; 165817715Sralph q->in.op = FREE; 165917715Sralph break; 166017715Sralph 166117715Sralph default: 166217715Sralph cerror( "hardops: can't compute & LHS" ); 166317715Sralph } 166417742Sralph } 166517715Sralph 16669702Slinton /* build comma op for args to function */ 16679702Slinton q = talloc(); 16689702Slinton q->in.op = CM; 16699702Slinton q->in.rall = NOPREF; 16709702Slinton q->in.type = INT; 16719702Slinton q->in.left = p->in.left; 16729702Slinton q->in.right = p->in.right; 16739702Slinton p->in.op = CALL; 16749702Slinton p->in.right = q; 16759702Slinton 16769702Slinton /* put function name in left node of call */ 16779702Slinton p->in.left = q = talloc(); 16789702Slinton q->in.op = ICON; 16799702Slinton q->in.rall = NOPREF; 16809702Slinton q->in.type = INCREF( FTN + p->in.type ); 16819702Slinton #ifndef FLEXNAMES 16829702Slinton strcpy( q->in.name, f->func ); 16839702Slinton #else 16849702Slinton q->in.name = f->func; 16859702Slinton #endif 16869702Slinton q->tn.lval = 0; 16879702Slinton q->tn.rval = 0; 16889702Slinton 16899702Slinton } 16909702Slinton 169117742Sralph zappost(p) NODE *p; { 169217742Sralph /* look for ++ and -- operators and remove them */ 169317742Sralph 169432935Sdonn register int o, ty; 169517742Sralph register NODE *q; 169617742Sralph o = p->in.op; 169717742Sralph ty = optype( o ); 169817742Sralph 169917742Sralph switch( o ){ 170017742Sralph 170117742Sralph case INCR: 170217742Sralph case DECR: 170317742Sralph q = p->in.left; 170417742Sralph p->in.right->in.op = FREE; /* zap constant */ 170517742Sralph ncopy( p, q ); 170617742Sralph q->in.op = FREE; 170717742Sralph return; 170817742Sralph 170917742Sralph } 171017742Sralph 171117742Sralph if( ty == BITYPE ) zappost( p->in.right ); 171217742Sralph if( ty != LTYPE ) zappost( p->in.left ); 171317742Sralph } 171417742Sralph 171517742Sralph fixpre(p) NODE *p; { 171617742Sralph 171732935Sdonn register int o, ty; 171817742Sralph o = p->in.op; 171917742Sralph ty = optype( o ); 172017742Sralph 172117742Sralph switch( o ){ 172217742Sralph 172317742Sralph case ASG PLUS: 172417742Sralph p->in.op = PLUS; 172517742Sralph break; 172617742Sralph case ASG MINUS: 172717742Sralph p->in.op = MINUS; 172817742Sralph break; 172917742Sralph } 173017742Sralph 173117742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 173217742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 173317742Sralph } 173417742Sralph 173532935Sdonn /*ARGSUSED*/ 173632935Sdonn NODE * addroreg(l) NODE *l; 173732935Sdonn /* OREG was built in clocal() 173832935Sdonn * for an auto or formal parameter 173932935Sdonn * now its address is being taken 174032935Sdonn * local code must unwind it 174132935Sdonn * back to PLUS/MINUS REG ICON 174232935Sdonn * according to local conventions 174332935Sdonn */ 174432935Sdonn { 174532935Sdonn cerror("address of OREG taken"); 174632935Sdonn /*NOTREACHED*/ 174732935Sdonn } 174832935Sdonn 174932935Sdonn 175032935Sdonn 175132935Sdonn # ifndef ONEPASS 175232935Sdonn main( argc, argv ) char *argv[]; { 175332935Sdonn return( mainp2( argc, argv ) ); 175432935Sdonn } 175532935Sdonn # endif 175632935Sdonn 175724418Smckusick strip(p) register NODE *p; { 175824418Smckusick NODE *q; 175924418Smckusick 176024418Smckusick /* strip nodes off the top when no side effects occur */ 176124418Smckusick for( ; ; ) { 176224418Smckusick switch( p->in.op ) { 176324418Smckusick case SCONV: /* remove lint tidbits */ 176424418Smckusick q = p->in.left; 176524418Smckusick ncopy( p, q ); 176624418Smckusick q->in.op = FREE; 176724418Smckusick break; 176824418Smckusick /* could probably add a few more here */ 176924418Smckusick default: 177024418Smckusick return; 177124418Smckusick } 177224418Smckusick } 177324418Smckusick } 177424418Smckusick 17759702Slinton myreader(p) register NODE *p; { 177624418Smckusick strip( p ); /* strip off operations with no side effects */ 177717742Sralph canon( p ); /* expands r-vals for fields */ 17789702Slinton walkf( p, hardops ); /* convert ops to function calls */ 17799702Slinton walkf( p, optim2 ); 17809702Slinton } 1781