117742Sralph # ifndef lint 2*32944Sdonn static char *sccsid ="@(#)local2.c 1.38 (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 ) { 23232938Sdonn /* 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 34432938Sdonn case 'Z': /* AND for CC with ICON -- lval is complemented */ 34532938Sdonn { 34632938Sdonn register NODE *l, *r; 34732938Sdonn 34832938Sdonn l = getlr( p, 'L' ); 34932938Sdonn r = getlr( p, 'R' ); 35032938Sdonn m = (1 << tlen(l) * SZCHAR) - 1; 35132938Sdonn r->tn.lval = ~r->tn.lval; 35232938Sdonn if( (l->in.type == CHAR || l->in.type == SHORT) && 35332938Sdonn (r->tn.lval & ~m) ) { 35432938Sdonn putstr("cvt"); 35532938Sdonn prtype(l); 35632938Sdonn putstr("l\t"); 35732938Sdonn adrput(l); 35832938Sdonn putchar(','); 35932938Sdonn adrput(resc); 36032938Sdonn putstr("\n\t"); 36132938Sdonn resc->tn.type = INT; 36232938Sdonn l = resc; 36332938Sdonn } 36432938Sdonn else if( l->in.type == UCHAR || l->in.type == USHORT ) 36532938Sdonn /* remove trash left over from complementing */ 36632938Sdonn r->tn.lval &= m; 36732938Sdonn putstr("bit"); 36832938Sdonn prtype(l); 36932938Sdonn printf("\t$%ld", r->tn.lval); 37032938Sdonn putchar(','); 37132938Sdonn adrput(l); 3729702Slinton return; 37332938Sdonn } 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 = ""; 47132941Sdonn /* size of floating argument is always 2 */ 47232941Sdonn p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR); 47332935Sdonn q->in.right = p; 47432935Sdonn p = talloc(); 47532935Sdonn p->in.op = UNARY MUL; 47632935Sdonn p->in.left = q; 47732935Sdonn return( p ); 47832935Sdonn } 47932935Sdonn 48032935Sdonn sconv( p, forarg ) register NODE *p; { 48132935Sdonn register NODE *l, *r; 48232935Sdonn int m, val; 48332935Sdonn 48432935Sdonn if (xdebug) eprint(p, 0, &val, &val); 48532935Sdonn r = getlr(p, 'R'); 48632935Sdonn if (p->in.op == ASSIGN) 48732935Sdonn l = getlr(p, 'L'); 48832935Sdonn else if (p->in.op == SCONV) { 48932935Sdonn m = r->in.type; 49032935Sdonn if (forarg) 49132935Sdonn l = makearg( m ); 49232935Sdonn else 49332935Sdonn l = resc; 49432935Sdonn l->in.type = m; 49532935Sdonn r = getlr(p, 'L'); 49632935Sdonn } 49732935Sdonn else { /* OPLTYPE */ 49832935Sdonn m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 49932935Sdonn if (forarg) 50032935Sdonn l = makearg( m ); 50132935Sdonn else 50232935Sdonn l = resc; 50332935Sdonn l->in.type = m; 50432935Sdonn } 50532935Sdonn if (r->in.op == ICON) 50632935Sdonn if (r->in.name[0] == '\0') { 50732942Sdonn if (r->tn.lval == 0 && 50832942Sdonn (r->in.type == DOUBLE || r->in.type == FLOAT || 50932942Sdonn !forarg)) { 51032942Sdonn if (r->in.type == FLOAT) 51132942Sdonn r->in.type = DOUBLE; 51232935Sdonn putstr("clr"); 51332935Sdonn prtype(l); 51432935Sdonn putchar('\t'); 51516418Sralph adrput(l); 51632935Sdonn goto cleanup; 51716418Sralph } 51832935Sdonn if (r->tn.lval < 0 && r->tn.lval >= -63) { 51932935Sdonn putstr("mneg"); 52032935Sdonn prtype(l); 52132935Sdonn r->tn.lval = -r->tn.lval; 52232935Sdonn goto ops; 52332935Sdonn } 52432935Sdonn if (r->tn.lval < 0) 52532935Sdonn r->in.type = r->tn.lval >= -128 ? CHAR 52632935Sdonn : (r->tn.lval >= -32768 ? SHORT 52732935Sdonn : INT); 52832935Sdonn else if (l->in.type == FLOAT || 52932935Sdonn l->in.type == DOUBLE) 53032935Sdonn r->in.type = r->tn.lval <= 63 ? INT 53132935Sdonn : (r->tn.lval <= 127 ? CHAR 53232935Sdonn : (r->tn.lval <= 32767 ? SHORT 53332935Sdonn : INT)); 53416418Sralph else 53532935Sdonn r->in.type = r->tn.lval <= 63 ? INT 53632935Sdonn : (r->tn.lval <= 127 ? CHAR 53732935Sdonn : (r->tn.lval <= 255 ? UCHAR 53832935Sdonn : (r->tn.lval <= 32767 ? SHORT 53932935Sdonn : (r->tn.lval <= 65535 ? USHORT 54032935Sdonn : INT)))); 54132938Sdonn if (forarg && r->in.type == INT) { 54232938Sdonn putstr("pushl\t"); 54332938Sdonn adrput(r); 54432938Sdonn goto cleanup; 54532938Sdonn } 54632935Sdonn } 54732935Sdonn else { 54832938Sdonn if (forarg && tlen(r) == SZINT/SZCHAR) { 54932938Sdonn putstr("pushl\t"); 55032938Sdonn adrput(r); 55132938Sdonn goto cleanup; 55232938Sdonn } 55332938Sdonn putstr("moval\t"); 55432935Sdonn acon(r); 55532935Sdonn putchar(','); 55632935Sdonn adrput(l); 55732935Sdonn goto cleanup; 55832935Sdonn } 5599702Slinton 56032935Sdonn if (p->in.op == SCONV && 56132935Sdonn !(l->in.type == FLOAT || l->in.type == DOUBLE) && 56232935Sdonn !mixtypes(l, r)) { 56332935Sdonn /* 56432935Sdonn * Because registers must always contain objects 56532935Sdonn * of the same width as INTs, we may have to 56632935Sdonn * perform two conversions to get an INT. Can 56732935Sdonn * the conversions be collapsed into one? 56832935Sdonn */ 56932935Sdonn if (m = collapsible(l, r)) 57032935Sdonn r->in.type = m; 57132935Sdonn else { 57232943Sdonn /* two steps are required */ 57332940Sdonn NODE *x; 5749702Slinton 57532940Sdonn if (forarg) { 57632940Sdonn x = resc; 57732940Sdonn x->in.type = l->in.type; 57832940Sdonn } 57932940Sdonn else { 58032940Sdonn x = &resc[1]; 58132940Sdonn *x = *l; 58232940Sdonn } 58332940Sdonn 58432935Sdonn if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 58532935Sdonn putstr("movz"); 58632935Sdonn else 58732935Sdonn putstr("cvt"); 58832935Sdonn prtype(r); 58932935Sdonn prtype(x); 59032935Sdonn putchar('\t'); 59132935Sdonn adrput(r); 59232935Sdonn putchar(','); 59332935Sdonn adrput(x); 59432935Sdonn putchar('\n'); 59532935Sdonn putchar('\t'); 59632935Sdonn r = x; 5979702Slinton } 59832935Sdonn l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 59932935Sdonn } 6009702Slinton 60132943Sdonn else if ((forarg || l == resc) && 60232943Sdonn tlen(l) < SZINT/SZCHAR && 60332943Sdonn mixtypes(l, r)) { 60432943Sdonn /* two steps needed here too */ 60532943Sdonn NODE *x; 60632943Sdonn 60732943Sdonn if (forarg) { 60832943Sdonn x = resc; 60932943Sdonn x->in.type = l->in.type; 61032943Sdonn } 61132943Sdonn else { 61232943Sdonn x = &resc[1]; 61332943Sdonn *x = *l; 61432943Sdonn } 61532943Sdonn putstr("cvt"); 61632943Sdonn prtype(r); 61732943Sdonn prtype(x); 61832943Sdonn putchar('\t'); 61932943Sdonn adrput(r); 62032943Sdonn putchar(','); 62132943Sdonn adrput(x); 62232943Sdonn putstr("\n\t"); 62332943Sdonn r = x; 62432943Sdonn l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 62532943Sdonn } 62632943Sdonn 62732943Sdonn else if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 62832935Sdonn mixtypes(l, r)) { 62932935Sdonn int label1, label2; 63032940Sdonn NODE *x = NULL; 63132935Sdonn 63232940Sdonn #if defined(FORT) || defined(SPRECC) 63332940Sdonn if (forarg) 63432940Sdonn #else 63532940Sdonn if (forarg || l == resc) 63632940Sdonn #endif 63732940Sdonn { 63832940Sdonn /* compute in register, convert to double when done */ 63932940Sdonn x = l; 64032940Sdonn l = resc; 64132940Sdonn l->in.type = x->in.type; 64232940Sdonn } 64332940Sdonn 64432935Sdonn label1 = getlab(); 64532935Sdonn label2 = getlab(); 64632935Sdonn 64732935Sdonn putstr("movl\t"); 64832935Sdonn adrput(r); 64932935Sdonn putchar(','); 65032935Sdonn adrput(l); 65132935Sdonn putstr("\n\tjbsc\t$31,"); 65232935Sdonn adrput(l); 65332935Sdonn printf(",L%d\n\tcvtl", label1); 65432935Sdonn prtype(l); 65532935Sdonn putchar('\t'); 65632935Sdonn adrput(l); 65732935Sdonn putchar(','); 65832935Sdonn adrput(l); 65932935Sdonn printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 66032935Sdonn prtype(l); 66132935Sdonn putchar('\t'); 66232935Sdonn adrput(l); 66332935Sdonn putchar(','); 66432935Sdonn adrput(l); 66532935Sdonn putstr("\n\tadd"); 66632935Sdonn prtype(l); 66732935Sdonn putstr("2\t$0"); 66832935Sdonn prtype(l); 66932935Sdonn putstr("2.147483648e9,"); 67032935Sdonn adrput(l); 67132935Sdonn printf("\nL%d:", label2); 67232935Sdonn 67332943Sdonn #if defined(FORT) || defined(SPRECC) 67432943Sdonn if (!forarg) 67532943Sdonn #else 67632940Sdonn if (!forarg && (l->in.type == DOUBLE || l != resc)) 67732943Sdonn #endif 67832940Sdonn goto cleanup; 67932943Sdonn if (x == NULL) 68032943Sdonn cerror("sconv botch"); 68132943Sdonn if (l == x) { 68232943Sdonn r = &resc[1]; 68332943Sdonn *r = *l; 68432940Sdonn } 68532943Sdonn else { 68632943Sdonn r = l; 68732943Sdonn l = x; 68832943Sdonn } 68932943Sdonn l->in.type = DOUBLE; 69032940Sdonn putstr("\n\t"); 6919702Slinton } 69232935Sdonn 69332943Sdonn else if( (l->in.type == FLOAT || l->in.type == DOUBLE) && 69432940Sdonn (r->in.type == UCHAR || r->in.type == USHORT) ) { 69532940Sdonn /* skip unnecessary unsigned to floating conversion */ 69632940Sdonn #if defined(FORT) || defined(SPRECC) 69732940Sdonn if (forarg) 69832940Sdonn #else 69932940Sdonn if (forarg || l == resc) 70032940Sdonn #endif 70132940Sdonn l->in.type = DOUBLE; 70232940Sdonn putstr("movz"); 70332940Sdonn prtype(r); 70432940Sdonn putstr("l\t"); 70532940Sdonn adrput(r); 70632940Sdonn putchar(','); 70732940Sdonn adrput(resc); 70832940Sdonn putstr("\n\t"); 70932940Sdonn if (l == resc) { 71032940Sdonn r = &resc[1]; 71132940Sdonn *r = *l; 71232940Sdonn } 71332940Sdonn else 71432940Sdonn r = resc; 71532940Sdonn r->in.type = INT; 71632940Sdonn } 71732940Sdonn 71832940Sdonn #if defined(FORT) || defined(SPRECC) 71932940Sdonn if (forarg && l->in.type == FLOAT) 72032940Sdonn #else 72132940Sdonn if ((forarg || l == resc) && l->in.type == FLOAT) 72232940Sdonn #endif 72332940Sdonn { 72432940Sdonn /* perform an implicit conversion to double */ 72532940Sdonn l->in.type = DOUBLE; 72632940Sdonn if (r->in.type != FLOAT && 72732940Sdonn r->in.type != CHAR && 72832940Sdonn r->in.type != SHORT) { 72932940Sdonn /* trim bits from the mantissa */ 73032940Sdonn putstr("cvt"); 73132940Sdonn prtype(r); 73232940Sdonn putstr("f\t"); 73332940Sdonn adrput(r); 73432940Sdonn putchar(','); 73532940Sdonn adrput(resc); 73632940Sdonn putstr("\n\t"); 73732940Sdonn if (l == resc) { 73832940Sdonn r = &resc[1]; 73932940Sdonn *r = *l; 74032940Sdonn } 74132940Sdonn else 74232940Sdonn r = resc; 74332940Sdonn r->in.type = FLOAT; 74432940Sdonn } 74532940Sdonn } 74632940Sdonn 74732935Sdonn if (!mixtypes(l,r)) { 74832935Sdonn if (tlen(l) == tlen(r)) { 74932938Sdonn if (forarg && tlen(l) == SZINT/SZCHAR) { 75032938Sdonn putstr("pushl\t"); 75132938Sdonn adrput(r); 75232938Sdonn goto cleanup; 75332938Sdonn } 75432935Sdonn putstr("mov"); 75532935Sdonn #ifdef FORT 75632935Sdonn if (Oflag) 75732935Sdonn prtype(l); 75832935Sdonn else { 75932935Sdonn if (l->in.type == DOUBLE) 76032935Sdonn putchar('q'); 76132935Sdonn else if(l->in.type == FLOAT) 76232935Sdonn putchar('l'); 76332935Sdonn else 76432935Sdonn prtype(l); 76532935Sdonn } 76632935Sdonn #else 76732935Sdonn prtype(l); 76832935Sdonn #endif FORT 76932935Sdonn goto ops; 77032935Sdonn } 77132935Sdonn else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 77232935Sdonn putstr("movz"); 77332935Sdonn else 77432935Sdonn putstr("cvt"); 77532935Sdonn } 77632935Sdonn else 77732935Sdonn putstr("cvt"); 77832935Sdonn prtype(r); 77932935Sdonn prtype(l); 78032935Sdonn ops: 78132935Sdonn putchar('\t'); 78232935Sdonn adrput(r); 78332935Sdonn putchar(','); 78432935Sdonn adrput(l); 78532935Sdonn 78632935Sdonn cleanup: 78732935Sdonn if (forarg) 78832935Sdonn tfree(l); 7899702Slinton } 7909702Slinton 79123536Sbloom /* 79223536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 79323536Sbloom * can be accomplished in one instruction, return the type of src 79423536Sbloom * that will do the job correctly; otherwise return 0. Note that 79523536Sbloom * a register must always end up having type INT or UNSIGNED. 79623536Sbloom */ 79723536Sbloom int 79823536Sbloom collapsible(dest, src) 79923536Sbloom NODE *dest, *src; 80023536Sbloom { 80123536Sbloom int st = src->in.type; 80223536Sbloom int dt = dest->in.type; 80323536Sbloom int newt = 0; 80423536Sbloom 80523536Sbloom /* 80623536Sbloom * Are there side effects of evaluating src? 80723536Sbloom * If the derived type will not be the same size as src, 80824418Smckusick * we may have to use two steps. 80923536Sbloom */ 81024418Smckusick if (tlen(src) > tlen(dest)) { 81124418Smckusick if (tshape(src, STARREG)) 81224418Smckusick return (0); 81324418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval)) 81424418Smckusick return (0); 81524418Smckusick } 81623536Sbloom 81723536Sbloom /* 81823536Sbloom * Can we get an object of dest's type by punning src? 81923536Sbloom * Praises be to great Cthulhu for little-endian machines... 82023536Sbloom */ 82123536Sbloom if (st == CHAR && dt == USHORT) 82223536Sbloom /* 82323536Sbloom * Special case -- we must sign-extend to 16 bits. 82423536Sbloom */ 82523536Sbloom return (0); 82623536Sbloom 82723536Sbloom if (tlen(src) < tlen(dest)) 82823536Sbloom newt = st; 82923536Sbloom else 83023536Sbloom newt = dt; 83123536Sbloom 83223536Sbloom return (newt); 83323536Sbloom } 83423536Sbloom 83517742Sralph rmove( rt, rs, t ) TWORD t; { 8369702Slinton printf( " %s %s,%s\n", 83717742Sralph #ifdef FORT 83817742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 83917742Sralph #endif 8409702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 8419702Slinton rnames[rs], rnames[rt] ); 8429702Slinton } 8439702Slinton 8449702Slinton struct respref 8459702Slinton respref[] = { 8469702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 8479702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 8489702Slinton INTEMP, INTEMP, 8499702Slinton FORARG, FORARG, 8509702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 8519702Slinton 0, 0 }; 8529702Slinton 8539702Slinton setregs(){ /* set up temporary registers */ 8549702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 8559702Slinton } 8569702Slinton 85732924Sdonn /*ARGSUSED*/ 8589702Slinton rewfld( p ) NODE *p; { 8599702Slinton return(1); 8609702Slinton } 8619702Slinton 86232924Sdonn /*ARGSUSED*/ 8639702Slinton callreg(p) NODE *p; { 8649702Slinton return( R0 ); 8659702Slinton } 8669702Slinton 8679702Slinton base( p ) register NODE *p; { 8689702Slinton register int o = p->in.op; 8699702Slinton 87032938Sdonn if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */ 8719702Slinton if( o==REG ) return( p->tn.rval ); 8729702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 8739702Slinton return( p->in.left->tn.rval ); 8749702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 8759702Slinton return( p->tn.rval + 0200*1 ); 8769702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 8779702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 8789702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 8799702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 8809702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 88132938Sdonn if( o==NAME ) return( 100 + 0200*1 ); 8829702Slinton return( -1 ); 8839702Slinton } 8849702Slinton 8859702Slinton offset( p, tyl ) register NODE *p; int tyl; { 8869702Slinton 88724418Smckusick if( tyl==1 && 88824418Smckusick p->in.op==REG && 88924418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) ) 89024418Smckusick return( p->tn.rval ); 89124418Smckusick if( p->in.op==LS && 89224418Smckusick p->in.left->in.op==REG && 89324418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 89424418Smckusick p->in.right->in.op==ICON && 89524418Smckusick p->in.right->in.name[0]=='\0' && 89624418Smckusick (1<<p->in.right->tn.lval)==tyl) 8979702Slinton return( p->in.left->tn.rval ); 89824418Smckusick if( tyl==2 && 89924418Smckusick p->in.op==PLUS && 90024418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 90124418Smckusick p->in.left->in.op==REG && 90224418Smckusick p->in.right->in.op==REG && 90324418Smckusick p->in.left->tn.rval==p->in.right->tn.rval ) 90424418Smckusick return( p->in.left->tn.rval ); 9059702Slinton return( -1 ); 9069702Slinton } 9079702Slinton 9089702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 9099702Slinton register NODE *t; 9109702Slinton NODE *f; 9119702Slinton 9129702Slinton p->in.op = OREG; 9139702Slinton f = p->in.left; /* have to free this subtree later */ 9149702Slinton 9159702Slinton /* init base */ 9169702Slinton switch (q->in.op) { 9179702Slinton case ICON: 9189702Slinton case REG: 9199702Slinton case OREG: 92032938Sdonn case NAME: 9219702Slinton t = q; 9229702Slinton break; 9239702Slinton 9249702Slinton case MINUS: 9259702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 9269702Slinton case PLUS: 9279702Slinton t = q->in.right; 9289702Slinton break; 9299702Slinton 9309702Slinton case INCR: 9319702Slinton case ASG MINUS: 9329702Slinton t = q->in.left; 9339702Slinton break; 9349702Slinton 9359702Slinton case UNARY MUL: 9369702Slinton t = q->in.left->in.left; 9379702Slinton break; 9389702Slinton 9399702Slinton default: 9409702Slinton cerror("illegal makeor2"); 9419702Slinton } 9429702Slinton 9439702Slinton p->tn.lval = t->tn.lval; 9449702Slinton #ifndef FLEXNAMES 94532924Sdonn { 94632924Sdonn register int i; 94732924Sdonn for(i=0; i<NCHNAM; ++i) 94832924Sdonn p->in.name[i] = t->in.name[i]; 94932924Sdonn } 9509702Slinton #else 9519702Slinton p->in.name = t->in.name; 9529702Slinton #endif 9539702Slinton 9549702Slinton /* init offset */ 9559702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 9569702Slinton 9579702Slinton tfree(f); 9589702Slinton return; 9599702Slinton } 9609702Slinton 9619702Slinton canaddr( p ) NODE *p; { 9629702Slinton register int o = p->in.op; 9639702Slinton 9649702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 9659702Slinton return(0); 9669702Slinton } 9679702Slinton 96832935Sdonn flshape( p ) NODE *p; { 96932935Sdonn register int o = p->in.op; 97032935Sdonn 97132935Sdonn return( o == REG || o == NAME || o == ICON || 97232935Sdonn (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 9739702Slinton } 9749702Slinton 97532926Sdonn /* INTEMP shapes must not contain any temporary registers */ 9769702Slinton shtemp( p ) register NODE *p; { 97732926Sdonn int r; 97832926Sdonn 9799702Slinton if( p->in.op == STARG ) p = p->in.left; 98032926Sdonn 98132926Sdonn switch (p->in.op) { 98232926Sdonn case REG: 98332926Sdonn return( !istreg(p->tn.rval) ); 98432926Sdonn case OREG: 98532926Sdonn r = p->tn.rval; 98632926Sdonn if( R2TEST(r) ) { 98732926Sdonn if( istreg(R2UPK1(r)) ) 98832926Sdonn return(0); 98932926Sdonn r = R2UPK2(r); 99032926Sdonn } 99132926Sdonn return( !istreg(r) ); 99232926Sdonn case UNARY MUL: 99332926Sdonn p = p->in.left; 99432926Sdonn return( p->in.op != UNARY MUL && shtemp(p) ); 99532926Sdonn } 99632926Sdonn 99732926Sdonn if( optype( p->in.op ) != LTYPE ) return(0); 99832926Sdonn return(1); 9999702Slinton } 10009702Slinton 10019702Slinton shumul( p ) register NODE *p; { 100232935Sdonn register int o; 10039702Slinton extern int xdebug; 10049702Slinton 10059702Slinton if (xdebug) { 100632933Sdonn int val; 100732933Sdonn printf("shumul:\n"); 100832933Sdonn eprint(p, 0, &val, &val); 10099702Slinton } 10109702Slinton 10119702Slinton o = p->in.op; 10129702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 10139702Slinton 10149702Slinton if( ( o == INCR || o == ASG MINUS ) && 10159702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 10169702Slinton p->in.right->in.name[0] == '\0' ) 10179702Slinton { 101817659Sralph switch (p->in.type) 10199702Slinton { 10209702Slinton case CHAR|PTR: 10219702Slinton case UCHAR|PTR: 10229702Slinton o = 1; 10239702Slinton break; 10249702Slinton 10259702Slinton case SHORT|PTR: 10269702Slinton case USHORT|PTR: 10279702Slinton o = 2; 10289702Slinton break; 10299702Slinton 10309702Slinton case INT|PTR: 10319702Slinton case UNSIGNED|PTR: 10329702Slinton case LONG|PTR: 10339702Slinton case ULONG|PTR: 10349702Slinton case FLOAT|PTR: 10359702Slinton o = 4; 10369702Slinton break; 10379702Slinton 10389702Slinton case DOUBLE|PTR: 10399702Slinton o = 8; 10409702Slinton break; 10419702Slinton 10429702Slinton default: 104317742Sralph if ( ISPTR(p->in.type) && 104417742Sralph ISPTR(DECREF(p->in.type)) ) { 10459702Slinton o = 4; 10469702Slinton break; 10479702Slinton } 10489702Slinton else return(0); 10499702Slinton } 10509702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 10519702Slinton } 10529702Slinton 10539702Slinton return( 0 ); 10549702Slinton } 10559702Slinton 10569702Slinton adrcon( val ) CONSZ val; { 105724418Smckusick putchar( '$' ); 10589702Slinton printf( CONFMT, val ); 10599702Slinton } 10609702Slinton 10619702Slinton conput( p ) register NODE *p; { 10629702Slinton switch( p->in.op ){ 10639702Slinton 10649702Slinton case ICON: 10659702Slinton acon( p ); 10669702Slinton return; 10679702Slinton 10689702Slinton case REG: 106924418Smckusick putstr( rnames[p->tn.rval] ); 10709702Slinton return; 10719702Slinton 10729702Slinton default: 10739702Slinton cerror( "illegal conput" ); 10749702Slinton } 10759702Slinton } 10769702Slinton 107732923Sdonn /*ARGSUSED*/ 107832924Sdonn insput( p ) NODE *p; { 10799702Slinton cerror( "insput" ); 10809702Slinton } 10819702Slinton 108232928Sdonn upput( p, size ) NODE *p; int size; { 108332928Sdonn if( size == SZLONG && p->in.op == REG ) { 108432928Sdonn putstr( rnames[p->tn.rval + 1] ); 108532928Sdonn return; 108632928Sdonn } 10879702Slinton cerror( "upput" ); 10889702Slinton } 10899702Slinton 10909702Slinton adrput( p ) register NODE *p; { 10919702Slinton register int r; 10929702Slinton /* output an address, with offsets, from p */ 10939702Slinton 10949702Slinton if( p->in.op == FLD ){ 10959702Slinton p = p->in.left; 10969702Slinton } 10979702Slinton switch( p->in.op ){ 10989702Slinton 10999702Slinton case NAME: 11009702Slinton acon( p ); 11019702Slinton return; 11029702Slinton 11039702Slinton case ICON: 11049702Slinton /* addressable value of the constant */ 110524418Smckusick putchar( '$' ); 11069702Slinton acon( p ); 11079702Slinton return; 11089702Slinton 11099702Slinton case REG: 111024418Smckusick putstr( rnames[p->tn.rval] ); 11119702Slinton return; 11129702Slinton 11139702Slinton case OREG: 11149702Slinton r = p->tn.rval; 11159702Slinton if( R2TEST(r) ){ /* double indexing */ 11169702Slinton register int flags; 11179702Slinton 11189702Slinton flags = R2UPK3(r); 111924418Smckusick if( flags & 1 ) putchar('*'); 112024418Smckusick if( flags & 4 ) putchar('-'); 11219702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 11229702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 112324418Smckusick if( flags & 2 ) putchar('+'); 11249702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 11259702Slinton return; 11269702Slinton } 11279702Slinton if( r == AP ){ /* in the argument region */ 112832925Sdonn if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 11299702Slinton printf( CONFMT, p->tn.lval ); 113024418Smckusick putstr( "(ap)" ); 11319702Slinton return; 11329702Slinton } 11339702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 11349702Slinton printf( "(%s)", rnames[p->tn.rval] ); 11359702Slinton return; 11369702Slinton 11379702Slinton case UNARY MUL: 11389702Slinton /* STARNM or STARREG found */ 11399702Slinton if( tshape(p, STARNM) ) { 114024418Smckusick putchar( '*' ); 11419702Slinton adrput( p->in.left); 11429702Slinton } 11439702Slinton else { /* STARREG - really auto inc or dec */ 11449702Slinton register NODE *q; 11459702Slinton 114617659Sralph q = p->in.left; 114717742Sralph if( q->in.right->tn.lval != tlen(p) ) 114817742Sralph cerror("adrput: bad auto-increment/decrement"); 114917659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 115017659Sralph rnames[q->in.left->tn.rval], 115117659Sralph (q->in.op==INCR ? "+" : "") ); 11529702Slinton p->in.op = OREG; 115317659Sralph p->tn.rval = q->in.left->tn.rval; 115417659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 11559702Slinton #ifndef FLEXNAMES 11569702Slinton p->in.name[0] = '\0'; 11579702Slinton #else 11589702Slinton p->in.name = ""; 11599702Slinton #endif 11609702Slinton tfree(q); 11619702Slinton } 11629702Slinton return; 11639702Slinton 11649702Slinton default: 11659702Slinton cerror( "illegal address" ); 11669702Slinton return; 11679702Slinton 11689702Slinton } 11699702Slinton 11709702Slinton } 11719702Slinton 11729702Slinton acon( p ) register NODE *p; { /* print out a constant */ 11739702Slinton 117432935Sdonn if( p->in.name[0] == '\0' ) 11759702Slinton printf( CONFMT, p->tn.lval); 117632935Sdonn else { 11779702Slinton #ifndef FLEXNAMES 11789702Slinton printf( "%.8s", p->in.name ); 11799702Slinton #else 118024418Smckusick putstr( p->in.name ); 11819702Slinton #endif 118232935Sdonn if( p->tn.lval != 0 ) { 118332935Sdonn putchar( '+' ); 118432935Sdonn printf( CONFMT, p->tn.lval ); 118532935Sdonn } 11869702Slinton } 11879702Slinton } 11889702Slinton 11899702Slinton genscall( p, cookie ) register NODE *p; { 11909702Slinton /* structure valued call */ 11919702Slinton return( gencall( p, cookie ) ); 11929702Slinton } 11939702Slinton 11949702Slinton /* tbl */ 11959702Slinton int gc_numbytes; 11969702Slinton /* tbl */ 11979702Slinton 119832924Sdonn /*ARGSUSED*/ 11999702Slinton gencall( p, cookie ) register NODE *p; { 12009702Slinton /* generate the call given by p */ 120116418Sralph register NODE *p1; 120232935Sdonn register int temp, temp1; 120332935Sdonn register int m; 12049702Slinton 12059702Slinton if( p->in.right ) temp = argsize( p->in.right ); 12069702Slinton else temp = 0; 12079702Slinton 12089702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 12099702Slinton /* set aside room for structure return */ 12109702Slinton 12119702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 12129702Slinton else temp1 = temp; 12139702Slinton } 12149702Slinton 12159702Slinton if( temp > maxargs ) maxargs = temp; 12169702Slinton SETOFF(temp1,4); 12179702Slinton 12189702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 121916418Sralph genargs( p->in.right ); 12209702Slinton } 12219702Slinton 12229702Slinton p1 = p->in.left; 12239702Slinton if( p1->in.op != ICON ){ 12249702Slinton if( p1->in.op != REG ){ 12259702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 12269702Slinton if( p1->in.op != NAME ){ 12279702Slinton order( p1, INAREG ); 12289702Slinton } 12299702Slinton } 12309702Slinton } 12319702Slinton } 12329702Slinton 12339702Slinton /* tbl 12349702Slinton setup gc_numbytes so reference to ZC works */ 12359702Slinton 12369702Slinton gc_numbytes = temp&(0x3ff); 12379702Slinton /* tbl */ 12389702Slinton 12399702Slinton p->in.op = UNARY CALL; 12409702Slinton m = match( p, INTAREG|INTBREG ); 12419702Slinton 12429702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 12439702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 12449702Slinton if (temp >= 1024) 12459702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 12469702Slinton 12479702Slinton return(m != MDONE); 12489702Slinton } 12499702Slinton 12509702Slinton /* tbl */ 12519702Slinton char * 12529702Slinton ccbranches[] = { 125332935Sdonn "eql", 125432935Sdonn "neq", 125532935Sdonn "leq", 125632935Sdonn "lss", 125732935Sdonn "geq", 125832935Sdonn "gtr", 125932935Sdonn "lequ", 126032935Sdonn "lssu", 126132935Sdonn "gequ", 126232935Sdonn "gtru", 12639702Slinton }; 12649702Slinton /* tbl */ 12659702Slinton 126632924Sdonn /*ARGSUSED*/ 12679702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 12689702Slinton 126932935Sdonn if( o != 0 && ( o < EQ || o > UGT ) ) 127032935Sdonn cerror( "bad conditional branch: %s", opst[o] ); 127132935Sdonn printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); 12729702Slinton } 12739702Slinton 12749702Slinton nextcook( p, cookie ) NODE *p; { 12759702Slinton /* we have failed to match p with cookie; try another */ 12769702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 12779702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 12789702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 12799702Slinton return( FORREW ); 12809702Slinton } 12819702Slinton 128232924Sdonn /*ARGSUSED*/ 12839702Slinton lastchance( p, cook ) NODE *p; { 12849702Slinton /* forget it! */ 12859702Slinton return(0); 12869702Slinton } 12879702Slinton 12889702Slinton optim2( p ) register NODE *p; { 12899702Slinton /* do local tree transformations and optimizations */ 12909702Slinton 129132929Sdonn int o; 129232932Sdonn int i, mask; 129316181Sralph register NODE *l, *r; 12949702Slinton 129532929Sdonn switch( o = p->in.op ) { 12969702Slinton 1297*32944Sdonn case ASG PLUS: 1298*32944Sdonn case ASG MINUS: 1299*32944Sdonn case ASG MUL: 1300*32944Sdonn case ASG OR: 1301*32944Sdonn /* simple ASG OPSIMP -- reduce range of constant rhs */ 1302*32944Sdonn l = p->in.left; 1303*32944Sdonn r = p->in.right; 1304*32944Sdonn if( tlen(l) < SZINT/SZCHAR && 1305*32944Sdonn r->in.op==ICON && r->in.name[0]==0 ){ 1306*32944Sdonn mask = (1 << tlen(l) * SZCHAR) - 1; 1307*32944Sdonn if( r->tn.lval & (mask & ~(mask >> 1)) ) 1308*32944Sdonn r->tn.lval |= ~mask; 1309*32944Sdonn else 1310*32944Sdonn r->tn.lval &= mask; 1311*32944Sdonn } 1312*32944Sdonn break; 1313*32944Sdonn 13149702Slinton case AND: 131519933Smckusick /* commute L and R to eliminate complements and constants */ 131616181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 131716181Sralph l->in.op == COMPL ) { 13189702Slinton p->in.left = p->in.right; 131916181Sralph p->in.right = l; 13209702Slinton } 1321*32944Sdonn /* fall through */ 1322*32944Sdonn 13239702Slinton case ASG AND: 1324*32944Sdonn /* change meaning of AND to ~R&L - bic on pdp11/vax */ 13259702Slinton r = p->in.right; 132632931Sdonn if( r->in.op==ICON && r->in.name[0]==0 ) { 132732931Sdonn /* check for degenerate operations */ 132832931Sdonn l = p->in.left; 132932932Sdonn mask = (1 << tlen(l) * SZCHAR) - 1; 1330*32944Sdonn if( o == ASG AND || ISUNSIGNED(r->in.type) ) { 1331*32944Sdonn i = ~r->tn.lval & mask; 133232938Sdonn if( i == 0 ) { 1333*32944Sdonn /* redundant mask */ 133432932Sdonn r->in.op = FREE; 133532932Sdonn ncopy(p, l); 133632932Sdonn l->in.op = FREE; 133732932Sdonn break; 133832932Sdonn } 133932938Sdonn else if( i == mask ) 1340*32944Sdonn /* all bits masked off */ 134132932Sdonn goto zero; 1342*32944Sdonn r->tn.lval = i; 1343*32944Sdonn if( tlen(l) < SZINT/SZCHAR ){ 1344*32944Sdonn /* sign extend */ 1345*32944Sdonn if( r->tn.lval & (mask & ~(mask >> 1)) ) 1346*32944Sdonn r->tn.lval |= ~mask; 1347*32944Sdonn else 1348*32944Sdonn r->tn.lval &= mask; 1349*32944Sdonn } 135032938Sdonn break; 135132932Sdonn } 135232932Sdonn else if( r->tn.lval == mask && 135332932Sdonn tlen(l) < SZINT/SZCHAR ) { 1354*32944Sdonn /* use movz instead of bic */ 135532932Sdonn r->in.op = SCONV; 135632932Sdonn r->in.left = l; 135732932Sdonn r->in.right = 0; 135832932Sdonn r->in.type = ENUNSIGN(l->in.type); 135932932Sdonn r->in.su = l->in.su > 1 ? l->in.su : 1; 136032932Sdonn ncopy(p, r); 136132932Sdonn p->in.left = r; 136232932Sdonn p->in.type = INT; 136332931Sdonn break; 136432931Sdonn } 136532931Sdonn /* complement constant */ 13669702Slinton r->tn.lval = ~r->tn.lval; 13679702Slinton } 13689702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 13699702Slinton r->in.op = FREE; 13709702Slinton p->in.right = r->in.left; 13719702Slinton } 13729702Slinton else { /* insert complement node */ 137316181Sralph p->in.right = l = talloc(); 137416181Sralph l->in.op = COMPL; 137516181Sralph l->in.rall = NOPREF; 137616181Sralph l->in.type = r->in.type; 137716181Sralph l->in.left = r; 137816181Sralph l->in.right = NULL; 13799702Slinton } 13809702Slinton break; 13819702Slinton 138216181Sralph case SCONV: 138319933Smckusick l = p->in.left; 138417742Sralph #if defined(FORT) || defined(SPRECC) 138516573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 138619933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 138719933Smckusick return; 138816573Sralph #else 138919933Smckusick if( mixtypes(p, l) ) return; 139016573Sralph #endif 139132938Sdonn if( l->in.op == PCONV ) 139225751Sdonn return; 139332938Sdonn if( (l->in.op == CALL || l->in.op == UNARY CALL) && 139432938Sdonn l->in.type != INT && l->in.type != UNSIGNED ) 139532938Sdonn return; 139625751Sdonn 139719933Smckusick /* Only trust it to get it right if the size is the same */ 139819933Smckusick if( tlen(p) != tlen(l) ) 139919933Smckusick return; 140016181Sralph 140116181Sralph /* clobber conversion */ 140219933Smckusick if( l->in.op != FLD ) 140316181Sralph l->in.type = p->in.type; 140416181Sralph ncopy( p, l ); 140516181Sralph l->in.op = FREE; 140619933Smckusick 140716181Sralph break; 140816181Sralph 140924418Smckusick case ASSIGN: 141024418Smckusick /* 141124418Smckusick * Conversions are equivalent to assignments; 141224418Smckusick * when the two operations are combined, 141324418Smckusick * we can sometimes zap the conversion. 141424418Smckusick */ 141524418Smckusick r = p->in.right; 141624418Smckusick l = p->in.left; 141724418Smckusick if ( r->in.op == SCONV && 141824418Smckusick !mixtypes(l, r) && 141932922Sdonn l->in.op != FLD && 142024418Smckusick tlen(l) == tlen(r) ) { 142124418Smckusick p->in.right = r->in.left; 142224418Smckusick r->in.op = FREE; 142324418Smckusick } 142424418Smckusick break; 142524418Smckusick 142632929Sdonn case ULE: 142732929Sdonn case ULT: 142832929Sdonn case UGE: 142932929Sdonn case UGT: 143032931Sdonn p->in.op -= (UGE-GE); 143132931Sdonn if( degenerate(p) ) 143232931Sdonn break; 143332931Sdonn p->in.op += (UGE-GE); 143432931Sdonn break; 143532931Sdonn 143632929Sdonn case EQ: 143732929Sdonn case NE: 143832929Sdonn case LE: 143932929Sdonn case LT: 144032929Sdonn case GE: 144132929Sdonn case GT: 144232938Sdonn if( p->in.left->in.op == SCONV && 144332938Sdonn p->in.right->in.op == SCONV ) { 144432938Sdonn l = p->in.left; 144532938Sdonn r = p->in.right; 144632938Sdonn if( l->in.type == DOUBLE && 144732938Sdonn l->in.left->in.type == FLOAT && 144832938Sdonn r->in.left->in.type == FLOAT ) { 144932938Sdonn /* nuke the conversions */ 145032938Sdonn p->in.left = l->in.left; 145132938Sdonn p->in.right = r->in.left; 145232938Sdonn l->in.op = FREE; 145332938Sdonn r->in.op = FREE; 145432938Sdonn } 145532938Sdonn /* more? */ 145632938Sdonn } 145732931Sdonn (void) degenerate(p); 145832931Sdonn break; 145932931Sdonn 146032931Sdonn case DIV: 146132931Sdonn if( p->in.right->in.op == ICON && 146232931Sdonn p->in.right->tn.name[0] == '\0' && 146332931Sdonn ISUNSIGNED(p->in.right->in.type) && 146432931Sdonn (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 146532931Sdonn /* easy to do here, harder to do in zzzcode() */ 146632931Sdonn p->in.op = UGE; 146732929Sdonn break; 146832931Sdonn } 146932931Sdonn case MOD: 147032931Sdonn case ASG DIV: 147132931Sdonn case ASG MOD: 147232931Sdonn /* 147332931Sdonn * optimize DIV and MOD 147432931Sdonn * 147532931Sdonn * basically we spot UCHAR and USHORT and try to do them 147632931Sdonn * as signed ints... apparently div+mul+sub is always 147732931Sdonn * faster than ediv for finding MOD on the VAX, when 147832931Sdonn * full unsigned MOD isn't needed. 147932931Sdonn * 148032931Sdonn * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 148132931Sdonn * are faster for unsigned dividend and a constant divisor 148232931Sdonn * in the right range (.5 to 1 of dividend's range for the 148332931Sdonn * first, .333+ to .5 for the second). full unsigned is 148432931Sdonn * already done cmp+sub in the appropriate case; the 148532931Sdonn * other cases are less common and require more ambition. 148632931Sdonn */ 148732931Sdonn if( degenerate(p) ) 148832929Sdonn break; 148932931Sdonn l = p->in.left; 149032931Sdonn r = p->in.right; 149132931Sdonn if( !ISUNSIGNED(r->in.type) || 149232931Sdonn tlen(l) >= SZINT/SZCHAR || 149332931Sdonn !(tlen(r) < SZINT/SZCHAR || 149432931Sdonn (r->in.op == ICON && r->tn.name[0] == '\0')) ) 149532929Sdonn break; 149632931Sdonn if( r->in.op == ICON ) 149732931Sdonn r->tn.type = INT; 149832931Sdonn else { 149932931Sdonn NODE *t = talloc(); 150032931Sdonn t->in.left = r; 150132931Sdonn r = t; 150232931Sdonn r->in.op = SCONV; 150332931Sdonn r->in.type = INT; 150432931Sdonn r->in.right = 0; 150532931Sdonn p->in.right = r; 150632931Sdonn } 150732931Sdonn if( o == DIV || o == MOD ) { 150832931Sdonn NODE *t = talloc(); 150932931Sdonn t->in.left = l; 151032931Sdonn l = t; 151132931Sdonn l->in.op = SCONV; 151232931Sdonn l->in.type = INT; 151332931Sdonn l->in.right = 0; 151432931Sdonn p->in.left = l; 151532931Sdonn } 151632931Sdonn /* handle asgops in table */ 151732931Sdonn break; 151832931Sdonn 151932931Sdonn case RS: 152032931Sdonn case ASG RS: 152132931Sdonn case LS: 152232931Sdonn case ASG LS: 152332931Sdonn /* pick up degenerate shifts */ 152432931Sdonn l = p->in.left; 152532931Sdonn r = p->in.right; 152632931Sdonn if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 152732929Sdonn break; 152832929Sdonn i = r->tn.lval; 152932931Sdonn if( i < 0 ) 153032931Sdonn /* front end 'fixes' this? */ 153132931Sdonn if( o == LS || o == ASG LS ) 153232931Sdonn o += (RS-LS); 153332931Sdonn else 153432931Sdonn o += (LS-RS); 153532931Sdonn if( (o == RS || o == ASG RS) && 153632931Sdonn !ISUNSIGNED(l->in.type) ) 153732931Sdonn /* can't optimize signed right shifts */ 153832929Sdonn break; 153932935Sdonn if( o == LS ) { 154032935Sdonn if( i < SZINT ) 154132935Sdonn break; 154232935Sdonn } 154332935Sdonn else { 154432935Sdonn if( i < tlen(l) * SZCHAR ) 154532935Sdonn break; 154632935Sdonn } 154732931Sdonn zero: 154832931Sdonn if( !asgop( o ) ) 154932931Sdonn if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 155032931Sdonn /* no side effects */ 155132932Sdonn tfree(l); 155232931Sdonn ncopy(p, r); 155332931Sdonn r->in.op = FREE; 155432931Sdonn p->tn.lval = 0; 155532931Sdonn } 155632931Sdonn else { 155732931Sdonn p->in.op = COMOP; 155832932Sdonn r->tn.lval = 0; 155932931Sdonn } 156032931Sdonn else { 156132931Sdonn p->in.op = ASSIGN; 156232931Sdonn r->tn.lval = 0; 156332929Sdonn } 156432931Sdonn break; 156532931Sdonn } 156632931Sdonn } 156732931Sdonn 156832931Sdonn degenerate(p) register NODE *p; { 156932931Sdonn int o; 157032931Sdonn int result, i; 157132931Sdonn int lower, upper; 157232931Sdonn register NODE *l, *r; 157332931Sdonn 157432931Sdonn /* 157532931Sdonn * try to keep degenerate comparisons with constants 157632931Sdonn * out of the table. 157732931Sdonn */ 157832931Sdonn r = p->in.right; 157932931Sdonn l = p->in.left; 158032931Sdonn if( r->in.op != ICON || 158132931Sdonn r->tn.name[0] != '\0' || 158232931Sdonn tlen(l) >= tlen(r) ) 158332931Sdonn return (0); 158432931Sdonn switch( l->in.type ) { 158532931Sdonn case CHAR: 158632931Sdonn lower = -(1 << SZCHAR - 1); 158732931Sdonn upper = (1 << SZCHAR - 1) - 1; 158832931Sdonn break; 158932931Sdonn case UCHAR: 159032931Sdonn lower = 0; 159132931Sdonn upper = (1 << SZCHAR) - 1; 159232931Sdonn break; 159332931Sdonn case SHORT: 159432931Sdonn lower = -(1 << SZSHORT - 1); 159532931Sdonn upper = (1 << SZSHORT - 1) - 1; 159632931Sdonn break; 159732931Sdonn case USHORT: 159832931Sdonn lower = 0; 159932931Sdonn upper = (1 << SZSHORT) - 1; 160032931Sdonn break; 160132931Sdonn default: 160232932Sdonn cerror("unsupported type in degenerate()"); 160332931Sdonn } 160432931Sdonn i = r->tn.lval; 160532931Sdonn switch( o = p->in.op ) { 160632931Sdonn case DIV: 160732931Sdonn case ASG DIV: 160832931Sdonn case MOD: 160932931Sdonn case ASG MOD: 161032931Sdonn /* DIV and MOD work like EQ */ 161132931Sdonn case EQ: 161232931Sdonn case NE: 161332931Sdonn if( lower == 0 && (unsigned) i > upper ) 161432931Sdonn result = o == NE; 161532931Sdonn else if( i < lower || i > upper ) 161632931Sdonn result = o == NE; 161732931Sdonn else 161832931Sdonn return (0); 161932931Sdonn break; 162032931Sdonn case LT: 162132931Sdonn case GE: 162232931Sdonn if( lower == 0 && (unsigned) i > upper ) 162332931Sdonn result = o == LT; 162432931Sdonn else if( i <= lower ) 162532931Sdonn result = o != LT; 162632931Sdonn else if( i > upper ) 162732931Sdonn result = o == LT; 162832931Sdonn else 162932931Sdonn return (0); 163032931Sdonn break; 163132931Sdonn case LE: 163232931Sdonn case GT: 163332931Sdonn if( lower == 0 && (unsigned) i >= upper ) 163432931Sdonn result = o == LE; 163532931Sdonn else if( i < lower ) 163632931Sdonn result = o != LE; 163732931Sdonn else if( i >= upper ) 163832931Sdonn result = o == LE; 163932931Sdonn else 164032931Sdonn return (0); 164132931Sdonn break; 164232931Sdonn default: 164332931Sdonn cerror("unknown op in degenerate()"); 164432931Sdonn } 164532931Sdonn 164632931Sdonn if( o == MOD || o == ASG MOD ) { 164732931Sdonn r->in.op = FREE; 164832931Sdonn ncopy(p, l); 164932931Sdonn l->in.op = FREE; 165032931Sdonn } 165132931Sdonn else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 165232931Sdonn /* no side effects */ 165332932Sdonn tfree(l); 165432931Sdonn ncopy(p, r); 165532931Sdonn r->in.op = FREE; 165632931Sdonn p->tn.lval = result; 165732931Sdonn } 165832931Sdonn else { 165932931Sdonn if( o == ASG DIV ) 166032931Sdonn p->in.op = ASSIGN; 166132929Sdonn else { 166232929Sdonn p->in.op = COMOP; 166332929Sdonn r->tn.type = INT; 166432929Sdonn } 166532931Sdonn r->tn.lval = result; 16669702Slinton } 166732931Sdonn if( logop(o) ) 166832931Sdonn p->in.type = INT; 166932931Sdonn 167032931Sdonn return (1); 16719702Slinton } 16729702Slinton 16739702Slinton /* added by jwf */ 16749702Slinton struct functbl { 16759702Slinton int fop; 16769702Slinton TWORD ftype; 16779702Slinton char *func; 16789702Slinton } opfunc[] = { 16799702Slinton DIV, TANY, "udiv", 16809702Slinton MOD, TANY, "urem", 168117715Sralph ASG DIV, TANY, "audiv", 168217715Sralph ASG MOD, TANY, "aurem", 16839702Slinton 0, 0, 0 }; 16849702Slinton 16859702Slinton hardops(p) register NODE *p; { 16869702Slinton /* change hard to do operators into function calls. */ 16879702Slinton register NODE *q; 16889702Slinton register struct functbl *f; 16899702Slinton register o; 169017742Sralph NODE *old,*temp; 16919702Slinton 16929702Slinton o = p->in.op; 169317742Sralph if( ! (optype(o)==BITYPE && 169417742Sralph (ISUNSIGNED(p->in.left->in.type) || 169517742Sralph ISUNSIGNED(p->in.right->in.type))) ) 169617742Sralph return; 16979702Slinton 16989702Slinton for( f=opfunc; f->fop; f++ ) { 16999702Slinton if( o==f->fop ) goto convert; 17009702Slinton } 17019702Slinton return; 17029702Slinton 17039702Slinton convert: 170432931Sdonn if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 170532928Sdonn /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 170632928Sdonn /* save a subroutine call -- use at most 5 instructions */ 170732928Sdonn return; 170832931Sdonn if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 170932931Sdonn /* optim2() will modify the op into an ordinary int op */ 171032931Sdonn return; 17119702Slinton if( asgop( o ) ) { 171217742Sralph old = NIL; 171317715Sralph switch( p->in.left->in.op ){ 171417742Sralph case FLD: 171517742Sralph q = p->in.left->in.left; 171617742Sralph /* 171717742Sralph * rewrite (lval.fld /= rval); as 171817742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 171917742Sralph * else the compiler will evaluate lval twice. 172017742Sralph */ 172117742Sralph if( q->in.op == UNARY MUL ){ 172217742Sralph /* first allocate a temp storage */ 172317742Sralph temp = talloc(); 172417742Sralph temp->in.op = OREG; 172517742Sralph temp->tn.rval = TMPREG; 172617742Sralph temp->tn.lval = BITOOR(freetemp(1)); 172717742Sralph temp->in.type = INCREF(p->in.type); 172817742Sralph #ifdef FLEXNAMES 172917742Sralph temp->in.name = ""; 173017742Sralph #else 173117742Sralph temp->in.name[0] = '\0'; 173217742Sralph #endif 173317742Sralph old = q->in.left; 173417742Sralph q->in.left = temp; 173517742Sralph } 173617742Sralph /* fall thru ... */ 173717742Sralph 173817715Sralph case REG: 173917715Sralph case NAME: 174017715Sralph case OREG: 174117715Sralph /* change ASG OP to a simple OP */ 174217715Sralph q = talloc(); 174317715Sralph q->in.op = NOASG p->in.op; 174417715Sralph q->in.rall = NOPREF; 174517715Sralph q->in.type = p->in.type; 174617715Sralph q->in.left = tcopy(p->in.left); 174717715Sralph q->in.right = p->in.right; 174817715Sralph p->in.op = ASSIGN; 174917715Sralph p->in.right = q; 175017715Sralph p = q; 175117715Sralph f -= 2; /* Note: this depends on the table order */ 175217742Sralph /* on the right side only - replace *temp with 175317742Sralph *(temp = &lval), build the assignment node */ 175417742Sralph if( old ){ 175517742Sralph temp = q->in.left->in.left; /* the "*" node */ 175617742Sralph q = talloc(); 175717742Sralph q->in.op = ASSIGN; 175817742Sralph q->in.left = temp->in.left; 175917742Sralph q->in.right = old; 176017742Sralph q->in.type = old->in.type; 176117742Sralph #ifdef FLEXNAMES 176217742Sralph q->in.name = ""; 176317742Sralph #else 176417742Sralph q->in.name[0] = '\0'; 176517742Sralph #endif 176617742Sralph temp->in.left = q; 176717742Sralph } 176817715Sralph break; 17699702Slinton 177017715Sralph case UNARY MUL: 177117715Sralph /* avoid doing side effects twice */ 177217715Sralph q = p->in.left; 177317715Sralph p->in.left = q->in.left; 177417715Sralph q->in.op = FREE; 177517715Sralph break; 177617715Sralph 177717715Sralph default: 177817715Sralph cerror( "hardops: can't compute & LHS" ); 177917715Sralph } 178017742Sralph } 178117715Sralph 17829702Slinton /* build comma op for args to function */ 17839702Slinton q = talloc(); 17849702Slinton q->in.op = CM; 17859702Slinton q->in.rall = NOPREF; 17869702Slinton q->in.type = INT; 17879702Slinton q->in.left = p->in.left; 17889702Slinton q->in.right = p->in.right; 17899702Slinton p->in.op = CALL; 17909702Slinton p->in.right = q; 17919702Slinton 17929702Slinton /* put function name in left node of call */ 17939702Slinton p->in.left = q = talloc(); 17949702Slinton q->in.op = ICON; 17959702Slinton q->in.rall = NOPREF; 17969702Slinton q->in.type = INCREF( FTN + p->in.type ); 17979702Slinton #ifndef FLEXNAMES 17989702Slinton strcpy( q->in.name, f->func ); 17999702Slinton #else 18009702Slinton q->in.name = f->func; 18019702Slinton #endif 18029702Slinton q->tn.lval = 0; 18039702Slinton q->tn.rval = 0; 18049702Slinton 18059702Slinton } 18069702Slinton 180717742Sralph zappost(p) NODE *p; { 180817742Sralph /* look for ++ and -- operators and remove them */ 180917742Sralph 181032935Sdonn register int o, ty; 181117742Sralph register NODE *q; 181217742Sralph o = p->in.op; 181317742Sralph ty = optype( o ); 181417742Sralph 181517742Sralph switch( o ){ 181617742Sralph 181717742Sralph case INCR: 181817742Sralph case DECR: 181917742Sralph q = p->in.left; 182017742Sralph p->in.right->in.op = FREE; /* zap constant */ 182117742Sralph ncopy( p, q ); 182217742Sralph q->in.op = FREE; 182317742Sralph return; 182417742Sralph 182517742Sralph } 182617742Sralph 182717742Sralph if( ty == BITYPE ) zappost( p->in.right ); 182817742Sralph if( ty != LTYPE ) zappost( p->in.left ); 182917742Sralph } 183017742Sralph 183117742Sralph fixpre(p) NODE *p; { 183217742Sralph 183332935Sdonn register int o, ty; 183417742Sralph o = p->in.op; 183517742Sralph ty = optype( o ); 183617742Sralph 183717742Sralph switch( o ){ 183817742Sralph 183917742Sralph case ASG PLUS: 184017742Sralph p->in.op = PLUS; 184117742Sralph break; 184217742Sralph case ASG MINUS: 184317742Sralph p->in.op = MINUS; 184417742Sralph break; 184517742Sralph } 184617742Sralph 184717742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 184817742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 184917742Sralph } 185017742Sralph 185132935Sdonn /*ARGSUSED*/ 185232935Sdonn NODE * addroreg(l) NODE *l; 185332935Sdonn /* OREG was built in clocal() 185432935Sdonn * for an auto or formal parameter 185532935Sdonn * now its address is being taken 185632935Sdonn * local code must unwind it 185732935Sdonn * back to PLUS/MINUS REG ICON 185832935Sdonn * according to local conventions 185932935Sdonn */ 186032935Sdonn { 186132935Sdonn cerror("address of OREG taken"); 186232935Sdonn /*NOTREACHED*/ 186332935Sdonn } 186432935Sdonn 186532935Sdonn 186632935Sdonn 186732935Sdonn # ifndef ONEPASS 186832935Sdonn main( argc, argv ) char *argv[]; { 186932935Sdonn return( mainp2( argc, argv ) ); 187032935Sdonn } 187132935Sdonn # endif 187232935Sdonn 187324418Smckusick strip(p) register NODE *p; { 187424418Smckusick NODE *q; 187524418Smckusick 187624418Smckusick /* strip nodes off the top when no side effects occur */ 187724418Smckusick for( ; ; ) { 187824418Smckusick switch( p->in.op ) { 187924418Smckusick case SCONV: /* remove lint tidbits */ 188024418Smckusick q = p->in.left; 188124418Smckusick ncopy( p, q ); 188224418Smckusick q->in.op = FREE; 188324418Smckusick break; 188424418Smckusick /* could probably add a few more here */ 188524418Smckusick default: 188624418Smckusick return; 188724418Smckusick } 188824418Smckusick } 188924418Smckusick } 189024418Smckusick 18919702Slinton myreader(p) register NODE *p; { 189224418Smckusick strip( p ); /* strip off operations with no side effects */ 189317742Sralph canon( p ); /* expands r-vals for fields */ 18949702Slinton walkf( p, hardops ); /* convert ops to function calls */ 18959702Slinton walkf( p, optim2 ); 18969702Slinton } 1897