117742Sralph # ifndef lint 2*32925Sdonn static char *sccsid ="@(#)local2.c 1.19 (Berkeley) 12/11/87"; 317742Sralph # endif 417742Sralph 518556Sralph # include "pass2.h" 69702Slinton # include "ctype.h" 79702Slinton # ifdef FORT 89702Slinton int ftlab1, ftlab2; 99702Slinton # endif 109702Slinton /* a lot of the machine dependent parts of the second pass */ 119702Slinton 1224418Smckusick # define putstr(s) fputs((s), stdout) 1324418Smckusick 149702Slinton # define BITMASK(n) ((1L<<n)-1) 159702Slinton 1632924Sdonn /*ARGSUSED*/ 179702Slinton where(c){ 189702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno ); 199702Slinton } 209702Slinton 219702Slinton lineid( l, fn ) char *fn; { 229702Slinton /* identify line l and file fn */ 239702Slinton printf( "# line %d, file %s\n", l, fn ); 249702Slinton } 259702Slinton 269702Slinton 279702Slinton eobl2(){ 289702Slinton OFFSZ spoff; /* offset from stack pointer */ 299702Slinton #ifdef FORT 309702Slinton spoff = maxoff; 319702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 329702Slinton spoff /= SZCHAR; 339702Slinton SETOFF(spoff,4); 349702Slinton #ifndef FLEXNAMES 359702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff ); 369702Slinton #else 379702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 389702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff ); 399702Slinton #endif 409702Slinton #else 419702Slinton extern int ftlab1, ftlab2; 429702Slinton 439702Slinton spoff = maxoff; 449702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 459702Slinton spoff /= SZCHAR; 469702Slinton SETOFF(spoff,4); 479702Slinton printf( "L%d:\n", ftlab1); 489702Slinton if( spoff!=0 ) 499702Slinton if( spoff < 64 ) 509702Slinton printf( " subl2 $%ld,sp\n", spoff); 519702Slinton else 529702Slinton printf( " movab -%ld(sp),sp\n", spoff); 539702Slinton printf( " jbr L%d\n", ftlab2); 549702Slinton #endif 559702Slinton maxargs = -1; 569702Slinton } 579702Slinton 589702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = { 599702Slinton 609702Slinton ASG PLUS, "add", 619702Slinton ASG MINUS, "sub", 629702Slinton ASG MUL, "mul", 639702Slinton ASG DIV, "div", 649702Slinton ASG OR, "bis", 659702Slinton ASG ER, "xor", 669702Slinton ASG AND, "bic", 679702Slinton PLUS, "add", 689702Slinton MINUS, "sub", 699702Slinton MUL, "mul", 709702Slinton DIV, "div", 719702Slinton OR, "bis", 729702Slinton ER, "xor", 739702Slinton AND, "bic", 749702Slinton -1, "" }; 759702Slinton 769702Slinton hopcode( f, o ){ 779702Slinton /* output the appropriate string from the above table */ 789702Slinton 799702Slinton register struct hoptab *q; 809702Slinton 819702Slinton for( q = ioptab; q->opmask>=0; ++q ){ 829702Slinton if( q->opmask == o ){ 8324418Smckusick putstr( q->opstring ); 849702Slinton /* tbl 8524418Smckusick if( f == 'F' ) putchar( 'e' ); 8624418Smckusick else if( f == 'D' ) putchar( 'd' ); 879702Slinton tbl */ 889702Slinton /* tbl */ 899702Slinton switch( f ) { 909702Slinton case 'L': 919702Slinton case 'W': 929702Slinton case 'B': 939702Slinton case 'D': 949702Slinton case 'F': 9524418Smckusick putchar(tolower(f)); 969702Slinton break; 979702Slinton 989702Slinton } 999702Slinton /* tbl */ 1009702Slinton return; 1019702Slinton } 1029702Slinton } 1039702Slinton cerror( "no hoptab for %s", opst[o] ); 1049702Slinton } 1059702Slinton 1069702Slinton char * 1079702Slinton rnames[] = { /* keyed to register number tokens */ 1089702Slinton 1099702Slinton "r0", "r1", 1109702Slinton "r2", "r3", "r4", "r5", 1119702Slinton "r6", "r7", "r8", "r9", "r10", "r11", 1129702Slinton "ap", "fp", "sp", "pc", 1139702Slinton 1149702Slinton }; 1159702Slinton 1169702Slinton int rstatus[] = { 1179702Slinton SAREG|STAREG, SAREG|STAREG, 1189702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 1199702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 1209702Slinton SAREG, SAREG, SAREG, SAREG, 1219702Slinton 1229702Slinton }; 1239702Slinton 1249702Slinton tlen(p) NODE *p; 1259702Slinton { 1269702Slinton switch(p->in.type) { 1279702Slinton case CHAR: 1289702Slinton case UCHAR: 1299702Slinton return(1); 1309702Slinton 1319702Slinton case SHORT: 1329702Slinton case USHORT: 1339702Slinton return(2); 1349702Slinton 1359702Slinton case DOUBLE: 1369702Slinton return(8); 1379702Slinton 1389702Slinton default: 1399702Slinton return(4); 1409702Slinton } 1419702Slinton } 1429702Slinton 1439702Slinton mixtypes(p, q) NODE *p, *q; 1449702Slinton { 14516181Sralph register TWORD tp, tq; 1469702Slinton 1479702Slinton tp = p->in.type; 1489702Slinton tq = q->in.type; 1499702Slinton 1509702Slinton return( (tp==FLOAT || tp==DOUBLE) != 1519702Slinton (tq==FLOAT || tq==DOUBLE) ); 1529702Slinton } 1539702Slinton 1549702Slinton prtype(n) NODE *n; 1559702Slinton { 1569702Slinton switch (n->in.type) 1579702Slinton { 1589702Slinton case DOUBLE: 15924418Smckusick putchar('d'); 1609702Slinton return; 1619702Slinton 1629702Slinton case FLOAT: 16324418Smckusick putchar('f'); 1649702Slinton return; 1659702Slinton 1669702Slinton case LONG: 1679702Slinton case ULONG: 1689702Slinton case INT: 1699702Slinton case UNSIGNED: 17024418Smckusick putchar('l'); 1719702Slinton return; 1729702Slinton 1739702Slinton case SHORT: 1749702Slinton case USHORT: 17524418Smckusick putchar('w'); 1769702Slinton return; 1779702Slinton 1789702Slinton case CHAR: 1799702Slinton case UCHAR: 18024418Smckusick putchar('b'); 1819702Slinton return; 1829702Slinton 1839702Slinton default: 1849702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 1859702Slinton else { 18624418Smckusick putchar('l'); 1879702Slinton return; 1889702Slinton } 1899702Slinton } 1909702Slinton } 1919702Slinton 1929702Slinton zzzcode( p, c ) register NODE *p; { 1939702Slinton register m; 19432924Sdonn int val; 1959702Slinton switch( c ){ 1969702Slinton 1979702Slinton case 'N': /* logical ops, turned into 0-1 */ 1989702Slinton /* use register given by register 1 */ 1999702Slinton cbgen( 0, m=getlab(), 'I' ); 2009702Slinton deflab( p->bn.label ); 2019702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 2029702Slinton deflab( m ); 2039702Slinton return; 2049702Slinton 2059702Slinton case 'I': 2069702Slinton case 'P': 2079702Slinton cbgen( p->in.op, p->bn.label, c ); 2089702Slinton return; 2099702Slinton 2109702Slinton case 'A': 2119702Slinton { 2129702Slinton register NODE *l, *r; 2139702Slinton 2149702Slinton if (xdebug) eprint(p, 0, &val, &val); 2159702Slinton r = getlr(p, 'R'); 21616181Sralph if (p->in.op == ASSIGN) 21716181Sralph l = getlr(p, 'L'); 21817208Sralph else if (p->in.op == SCONV) { 2199702Slinton l = resc; 22017742Sralph #if defined(FORT) || defined(SPRECC) 22116181Sralph l->in.type = r->in.type; 22216181Sralph #else 22316181Sralph l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 22416181Sralph #endif 22516181Sralph r = getlr(p, 'L'); 22616181Sralph } 22717208Sralph else { /* OPLTYPE */ 22816181Sralph l = resc; 22917742Sralph #if defined(FORT) || defined(SPRECC) 23016181Sralph l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 23116181Sralph #else 2329702Slinton l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 23316181Sralph #endif 2349702Slinton } 2359702Slinton if (r->in.op == ICON) 23617208Sralph if (r->in.name[0] == '\0') { 23717208Sralph if (r->tn.lval == 0) { 23824418Smckusick putstr("clr"); 2399702Slinton prtype(l); 24024418Smckusick putchar('\t'); 2419702Slinton adrput(l); 2429702Slinton return; 2439702Slinton } 24417208Sralph if (r->tn.lval < 0 && r->tn.lval >= -63) { 24524418Smckusick putstr("mneg"); 2469702Slinton prtype(l); 2479702Slinton r->tn.lval = -r->tn.lval; 2489702Slinton goto ops; 2499702Slinton } 25017208Sralph if (r->tn.lval < 0) 25117208Sralph r->in.type = r->tn.lval >= -128 ? CHAR 2529702Slinton : (r->tn.lval >= -32768 ? SHORT 25317208Sralph : INT); 25417208Sralph else if (l->in.type == FLOAT || 25517208Sralph l->in.type == DOUBLE) 25617208Sralph r->in.type = r->tn.lval <= 63 ? INT 25717208Sralph : (r->tn.lval <= 127 ? CHAR 25817208Sralph : (r->tn.lval <= 32767 ? SHORT 25917208Sralph : INT)); 26017208Sralph else 26117208Sralph r->in.type = r->tn.lval <= 63 ? INT 26217208Sralph : (r->tn.lval <= 127 ? CHAR 2639702Slinton : (r->tn.lval <= 255 ? UCHAR 2649702Slinton : (r->tn.lval <= 32767 ? SHORT 2659702Slinton : (r->tn.lval <= 65535 ? USHORT 26617208Sralph : INT)))); 2679702Slinton } 26817208Sralph else { 26924418Smckusick putstr("moval"); 27024418Smckusick putchar('\t'); 27116181Sralph acon(r); 27224418Smckusick putchar(','); 27316181Sralph adrput(l); 27416181Sralph return; 27516181Sralph } 2769702Slinton 27723536Sbloom if (p->in.op == SCONV && 27823536Sbloom !(l->in.type == FLOAT || l->in.type == DOUBLE) && 27923536Sbloom !mixtypes(l, r)) { 28023536Sbloom /* 28123536Sbloom * Because registers must always contain objects 28223536Sbloom * of the same width as INTs, we may have to 28323536Sbloom * perform two conversions to get an INT. Can 28423536Sbloom * the conversions be collapsed into one? 28523536Sbloom */ 28623536Sbloom if (m = collapsible(l, r)) 28723536Sbloom r->in.type = m; 28823536Sbloom else { 28923536Sbloom /* 29023536Sbloom * Two steps are required. 29123536Sbloom */ 29223536Sbloom NODE *x = &resc[1]; 29323536Sbloom 29423536Sbloom *x = *l; 29523536Sbloom if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 29624418Smckusick putstr("movz"); 2979702Slinton else 29824418Smckusick putstr("cvt"); 29923536Sbloom prtype(r); 30023536Sbloom prtype(x); 30124418Smckusick putchar('\t'); 30223536Sbloom adrput(r); 30324418Smckusick putchar(','); 30423536Sbloom adrput(x); 30524418Smckusick putchar('\n'); 30624418Smckusick putchar('\t'); 30723536Sbloom r = x; 3089702Slinton } 30923536Sbloom l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 3109702Slinton } 31123536Sbloom 31225751Sdonn if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 31325751Sdonn mixtypes(l, r)) { 31425751Sdonn int label1, label2; 31525751Sdonn 31625751Sdonn label1 = getlab(); 31725751Sdonn label2 = getlab(); 31825751Sdonn 31925751Sdonn putstr("movl\t"); 32025751Sdonn adrput(r); 32125751Sdonn putchar(','); 32225751Sdonn adrput(l); 32327269Sdonn putstr("\n\tjbsc\t$31,"); 32425751Sdonn adrput(l); 32525751Sdonn printf(",L%d\n\tcvtl", label1); 32625751Sdonn prtype(l); 32725751Sdonn putchar('\t'); 32825751Sdonn adrput(l); 32925751Sdonn putchar(','); 33025751Sdonn adrput(l); 33125751Sdonn printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 33225751Sdonn prtype(l); 33325751Sdonn putchar('\t'); 33425751Sdonn adrput(l); 33525751Sdonn putchar(','); 33625751Sdonn adrput(l); 33725751Sdonn putstr("\n\tadd"); 33825751Sdonn prtype(l); 33925751Sdonn putstr("2\t$0"); 34025751Sdonn prtype(l); 34125751Sdonn putstr("2.147483648e9,"); 34225751Sdonn adrput(l); 34325751Sdonn printf("\nL%d:", label2); 34425751Sdonn 34525751Sdonn return; 34625751Sdonn } 34725751Sdonn 34817208Sralph if (!mixtypes(l,r)) { 34917208Sralph if (tlen(l) == tlen(r)) { 35024418Smckusick putstr("mov"); 35117742Sralph #ifdef FORT 35217742Sralph if (Oflag) 35317742Sralph prtype(l); 35417742Sralph else { 35517742Sralph if (l->in.type == DOUBLE) 35624418Smckusick putchar('q'); 35717742Sralph else if(l->in.type == FLOAT) 35824418Smckusick putchar('l'); 35917742Sralph else 36017742Sralph prtype(l); 36117742Sralph } 36217742Sralph #else 3639702Slinton prtype(l); 36417742Sralph #endif FORT 3659702Slinton goto ops; 3669702Slinton } 3679702Slinton else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 36824418Smckusick putstr("movz"); 3699702Slinton else 37024418Smckusick putstr("cvt"); 3719702Slinton } 3729702Slinton else 37324418Smckusick putstr("cvt"); 3749702Slinton prtype(r); 3759702Slinton prtype(l); 3769702Slinton ops: 37724418Smckusick putchar('\t'); 3789702Slinton adrput(r); 37924418Smckusick putchar(','); 3809702Slinton adrput(l); 3819702Slinton return; 3829702Slinton } 3839702Slinton 38425751Sdonn case 'G': /* i *= f; asgops with int lhs and float rhs */ 38525751Sdonn { 38625751Sdonn register NODE *l, *r, *s; 38725751Sdonn int rt; 38825751Sdonn 38925751Sdonn l = p->in.left; 39025751Sdonn r = p->in.right; 39125751Sdonn s = talloc(); 39225751Sdonn rt = r->in.type; 39325751Sdonn 39425751Sdonn s->in.op = SCONV; 39525751Sdonn s->in.left = l; 39625751Sdonn s->in.type = rt; 39725751Sdonn zzzcode(s, 'A'); 39825751Sdonn putstr("\n\t"); 39925751Sdonn 40025751Sdonn hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 40125751Sdonn putstr("2\t"); 40225751Sdonn adrput(r); 40325751Sdonn putchar(','); 40425751Sdonn adrput(resc); 40525751Sdonn putstr("\n\t"); 40625751Sdonn 40725751Sdonn s->in.op = ASSIGN; 40825751Sdonn s->in.left = l; 40925751Sdonn s->in.right = resc; 41025751Sdonn s->in.type = l->in.type; 41125751Sdonn zzzcode(s, 'A'); 41225751Sdonn 41325751Sdonn s->in.op = FREE; 41425751Sdonn return; 41525751Sdonn } 41625751Sdonn 4179702Slinton case 'B': /* get oreg value in temp register for left shift */ 4189702Slinton { 4199702Slinton register NODE *r; 4209702Slinton if (xdebug) eprint(p, 0, &val, &val); 4219702Slinton r = p->in.right; 4229702Slinton if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 42324418Smckusick putstr("movl"); 4249702Slinton else { 42524418Smckusick putstr("cvt"); 4269702Slinton prtype(r); 42724418Smckusick putchar('l'); 4289702Slinton } 4299702Slinton return; 4309702Slinton } 4319702Slinton 4329702Slinton case 'C': /* num words pushed on arg stack */ 4339702Slinton { 4349702Slinton extern int gc_numbytes; 4359702Slinton extern int xdebug; 4369702Slinton 4379702Slinton if (xdebug) printf("->%d<-",gc_numbytes); 4389702Slinton 4399702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 4409702Slinton return; 4419702Slinton } 4429702Slinton 4439702Slinton case 'D': /* INCR and DECR */ 4449702Slinton zzzcode(p->in.left, 'A'); 44524418Smckusick putchar('\n'); 44624418Smckusick putchar('\t'); 4479702Slinton 4489702Slinton case 'E': /* INCR and DECR, FOREFF */ 4499702Slinton if (p->in.right->tn.lval == 1) 4509702Slinton { 45124418Smckusick putstr( p->in.op == INCR ? "inc" : "dec" ); 4529702Slinton prtype(p->in.left); 45324418Smckusick putchar('\t'); 4549702Slinton adrput(p->in.left); 4559702Slinton return; 4569702Slinton } 45724418Smckusick putstr( p->in.op == INCR ? "add" : "sub" ); 4589702Slinton prtype(p->in.left); 45924418Smckusick putchar('2'); 46024418Smckusick putchar('\t'); 4619702Slinton adrput(p->in.right); 46224418Smckusick putchar(','); 4639702Slinton adrput(p->in.left); 4649702Slinton return; 4659702Slinton 4669702Slinton case 'F': /* register type of right operand */ 4679702Slinton { 4689702Slinton register NODE *n; 4699702Slinton extern int xdebug; 4709702Slinton register int ty; 4719702Slinton 4729702Slinton n = getlr( p, 'R' ); 4739702Slinton ty = n->in.type; 4749702Slinton 4759702Slinton if (xdebug) printf("->%d<-", ty); 4769702Slinton 47724418Smckusick if ( ty==DOUBLE) putchar('d'); 47824418Smckusick else if ( ty==FLOAT ) putchar('f'); 47924418Smckusick else putchar('l'); 4809702Slinton return; 4819702Slinton } 4829702Slinton 4839702Slinton case 'L': /* type of left operand */ 4849702Slinton case 'R': /* type of right operand */ 4859702Slinton { 4869702Slinton register NODE *n; 4879702Slinton extern int xdebug; 4889702Slinton 48916181Sralph n = getlr( p, c ); 4909702Slinton if (xdebug) printf("->%d<-", n->in.type); 4919702Slinton 4929702Slinton prtype(n); 4939702Slinton return; 4949702Slinton } 4959702Slinton 4969702Slinton case 'Z': /* complement mask for bit instr */ 4979702Slinton printf("$%ld", ~p->in.right->tn.lval); 4989702Slinton return; 4999702Slinton 5009702Slinton case 'U': /* 32 - n, for unsigned right shifts */ 5019702Slinton printf("$%d", 32 - p->in.right->tn.lval ); 5029702Slinton return; 5039702Slinton 5049702Slinton case 'T': /* rounded structure length for arguments */ 5059702Slinton { 5069702Slinton int size; 5079702Slinton 5089702Slinton size = p->stn.stsize; 5099702Slinton SETOFF( size, 4); 5109702Slinton printf("$%d", size); 5119702Slinton return; 5129702Slinton } 5139702Slinton 5149702Slinton case 'S': /* structure assignment */ 5159702Slinton { 5169702Slinton register NODE *l, *r; 5179702Slinton register size; 5189702Slinton 5199702Slinton if( p->in.op == STASG ){ 5209702Slinton l = p->in.left; 5219702Slinton r = p->in.right; 5229702Slinton 5239702Slinton } 5249702Slinton else if( p->in.op == STARG ){ /* store an arg into a temporary */ 5259702Slinton r = p->in.left; 5269702Slinton } 5279702Slinton else cerror( "STASG bad" ); 5289702Slinton 5299702Slinton if( r->in.op == ICON ) r->in.op = NAME; 5309702Slinton else if( r->in.op == REG ) r->in.op = OREG; 5319702Slinton else if( r->in.op != OREG ) cerror( "STASG-r" ); 5329702Slinton 5339702Slinton size = p->stn.stsize; 5349702Slinton 5359702Slinton if( size <= 0 || size > 65535 ) 5369702Slinton cerror("structure size <0=0 or >65535"); 5379702Slinton 5389702Slinton switch(size) { 5399702Slinton case 1: 54024418Smckusick putstr(" movb "); 5419702Slinton break; 5429702Slinton case 2: 54324418Smckusick putstr(" movw "); 5449702Slinton break; 5459702Slinton case 4: 54624418Smckusick putstr(" movl "); 5479702Slinton break; 5489702Slinton case 8: 54924418Smckusick putstr(" movq "); 5509702Slinton break; 5519702Slinton default: 5529702Slinton printf(" movc3 $%d,", size); 5539702Slinton break; 5549702Slinton } 5559702Slinton adrput(r); 55616418Sralph if( p->in.op == STASG ){ 55724418Smckusick putchar(','); 55816418Sralph adrput(l); 55924418Smckusick putchar('\n'); 56016418Sralph } 56116418Sralph else 56224418Smckusick putstr(",(sp)\n"); 5639702Slinton 5649702Slinton if( r->in.op == NAME ) r->in.op = ICON; 5659702Slinton else if( r->in.op == OREG ) r->in.op = REG; 5669702Slinton 5679702Slinton } 5689702Slinton break; 5699702Slinton 5709702Slinton default: 5719702Slinton cerror( "illegal zzzcode" ); 5729702Slinton } 5739702Slinton } 5749702Slinton 57523536Sbloom /* 57623536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 57723536Sbloom * can be accomplished in one instruction, return the type of src 57823536Sbloom * that will do the job correctly; otherwise return 0. Note that 57923536Sbloom * a register must always end up having type INT or UNSIGNED. 58023536Sbloom */ 58123536Sbloom int 58223536Sbloom collapsible(dest, src) 58323536Sbloom NODE *dest, *src; 58423536Sbloom { 58523536Sbloom int st = src->in.type; 58623536Sbloom int dt = dest->in.type; 58723536Sbloom int newt = 0; 58823536Sbloom 58923536Sbloom /* 59023536Sbloom * Are there side effects of evaluating src? 59123536Sbloom * If the derived type will not be the same size as src, 59224418Smckusick * we may have to use two steps. 59323536Sbloom */ 59424418Smckusick if (tlen(src) > tlen(dest)) { 59524418Smckusick if (tshape(src, STARREG)) 59624418Smckusick return (0); 59724418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval)) 59824418Smckusick return (0); 59924418Smckusick } 60023536Sbloom 60123536Sbloom /* 60223536Sbloom * Can we get an object of dest's type by punning src? 60323536Sbloom * Praises be to great Cthulhu for little-endian machines... 60423536Sbloom */ 60523536Sbloom if (st == CHAR && dt == USHORT) 60623536Sbloom /* 60723536Sbloom * Special case -- we must sign-extend to 16 bits. 60823536Sbloom */ 60923536Sbloom return (0); 61023536Sbloom 61123536Sbloom if (tlen(src) < tlen(dest)) 61223536Sbloom newt = st; 61323536Sbloom else 61423536Sbloom newt = dt; 61523536Sbloom 61623536Sbloom return (newt); 61723536Sbloom } 61823536Sbloom 61917742Sralph rmove( rt, rs, t ) TWORD t; { 6209702Slinton printf( " %s %s,%s\n", 62117742Sralph #ifdef FORT 62217742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 62317742Sralph #endif 6249702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 6259702Slinton rnames[rs], rnames[rt] ); 6269702Slinton } 6279702Slinton 6289702Slinton struct respref 6299702Slinton respref[] = { 6309702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 6319702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 6329702Slinton INTEMP, INTEMP, 6339702Slinton FORARG, FORARG, 6349702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 6359702Slinton 0, 0 }; 6369702Slinton 6379702Slinton setregs(){ /* set up temporary registers */ 6389702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 6399702Slinton ; 6409702Slinton } 6419702Slinton 64232924Sdonn /*ARGSUSED*/ 6439702Slinton rewfld( p ) NODE *p; { 6449702Slinton return(1); 6459702Slinton } 6469702Slinton 64732924Sdonn /*ARGSUSED*/ 6489702Slinton callreg(p) NODE *p; { 6499702Slinton return( R0 ); 6509702Slinton } 6519702Slinton 6529702Slinton base( p ) register NODE *p; { 6539702Slinton register int o = p->in.op; 6549702Slinton 6559702Slinton if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 6569702Slinton if( o==REG ) return( p->tn.rval ); 6579702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 6589702Slinton return( p->in.left->tn.rval ); 6599702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 6609702Slinton return( p->tn.rval + 0200*1 ); 6619702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 6629702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 6639702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 6649702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 6659702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 6669702Slinton return( -1 ); 6679702Slinton } 6689702Slinton 6699702Slinton offset( p, tyl ) register NODE *p; int tyl; { 6709702Slinton 67124418Smckusick if( tyl==1 && 67224418Smckusick p->in.op==REG && 67324418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) ) 67424418Smckusick return( p->tn.rval ); 67524418Smckusick if( p->in.op==LS && 67624418Smckusick p->in.left->in.op==REG && 67724418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 67824418Smckusick p->in.right->in.op==ICON && 67924418Smckusick p->in.right->in.name[0]=='\0' && 68024418Smckusick (1<<p->in.right->tn.lval)==tyl) 6819702Slinton return( p->in.left->tn.rval ); 68224418Smckusick if( tyl==2 && 68324418Smckusick p->in.op==PLUS && 68424418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 68524418Smckusick p->in.left->in.op==REG && 68624418Smckusick p->in.right->in.op==REG && 68724418Smckusick p->in.left->tn.rval==p->in.right->tn.rval ) 68824418Smckusick return( p->in.left->tn.rval ); 6899702Slinton return( -1 ); 6909702Slinton } 6919702Slinton 6929702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 6939702Slinton register NODE *t; 6949702Slinton NODE *f; 6959702Slinton 6969702Slinton p->in.op = OREG; 6979702Slinton f = p->in.left; /* have to free this subtree later */ 6989702Slinton 6999702Slinton /* init base */ 7009702Slinton switch (q->in.op) { 7019702Slinton case ICON: 7029702Slinton case REG: 7039702Slinton case OREG: 7049702Slinton t = q; 7059702Slinton break; 7069702Slinton 7079702Slinton case MINUS: 7089702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 7099702Slinton case PLUS: 7109702Slinton t = q->in.right; 7119702Slinton break; 7129702Slinton 7139702Slinton case INCR: 7149702Slinton case ASG MINUS: 7159702Slinton t = q->in.left; 7169702Slinton break; 7179702Slinton 7189702Slinton case UNARY MUL: 7199702Slinton t = q->in.left->in.left; 7209702Slinton break; 7219702Slinton 7229702Slinton default: 7239702Slinton cerror("illegal makeor2"); 7249702Slinton } 7259702Slinton 7269702Slinton p->tn.lval = t->tn.lval; 7279702Slinton #ifndef FLEXNAMES 72832924Sdonn { 72932924Sdonn register int i; 73032924Sdonn for(i=0; i<NCHNAM; ++i) 73132924Sdonn p->in.name[i] = t->in.name[i]; 73232924Sdonn } 7339702Slinton #else 7349702Slinton p->in.name = t->in.name; 7359702Slinton #endif 7369702Slinton 7379702Slinton /* init offset */ 7389702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 7399702Slinton 7409702Slinton tfree(f); 7419702Slinton return; 7429702Slinton } 7439702Slinton 7449702Slinton canaddr( p ) NODE *p; { 7459702Slinton register int o = p->in.op; 7469702Slinton 7479702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 7489702Slinton return(0); 7499702Slinton } 7509702Slinton 7519702Slinton flshape( p ) register NODE *p; { 7529702Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 7539702Slinton (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 7549702Slinton } 7559702Slinton 7569702Slinton shtemp( p ) register NODE *p; { 7579702Slinton if( p->in.op == STARG ) p = p->in.left; 7589702Slinton return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 7599702Slinton } 7609702Slinton 7619702Slinton shumul( p ) register NODE *p; { 7629702Slinton register o; 7639702Slinton extern int xdebug; 7649702Slinton 7659702Slinton if (xdebug) { 7669702Slinton printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 7679702Slinton printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 7689702Slinton } 7699702Slinton 7709702Slinton 7719702Slinton o = p->in.op; 7729702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 7739702Slinton 7749702Slinton if( ( o == INCR || o == ASG MINUS ) && 7759702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 7769702Slinton p->in.right->in.name[0] == '\0' ) 7779702Slinton { 77817659Sralph switch (p->in.type) 7799702Slinton { 7809702Slinton case CHAR|PTR: 7819702Slinton case UCHAR|PTR: 7829702Slinton o = 1; 7839702Slinton break; 7849702Slinton 7859702Slinton case SHORT|PTR: 7869702Slinton case USHORT|PTR: 7879702Slinton o = 2; 7889702Slinton break; 7899702Slinton 7909702Slinton case INT|PTR: 7919702Slinton case UNSIGNED|PTR: 7929702Slinton case LONG|PTR: 7939702Slinton case ULONG|PTR: 7949702Slinton case FLOAT|PTR: 7959702Slinton o = 4; 7969702Slinton break; 7979702Slinton 7989702Slinton case DOUBLE|PTR: 7999702Slinton o = 8; 8009702Slinton break; 8019702Slinton 8029702Slinton default: 80317742Sralph if ( ISPTR(p->in.type) && 80417742Sralph ISPTR(DECREF(p->in.type)) ) { 8059702Slinton o = 4; 8069702Slinton break; 8079702Slinton } 8089702Slinton else return(0); 8099702Slinton } 8109702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 8119702Slinton } 8129702Slinton 8139702Slinton return( 0 ); 8149702Slinton } 8159702Slinton 8169702Slinton adrcon( val ) CONSZ val; { 81724418Smckusick putchar( '$' ); 8189702Slinton printf( CONFMT, val ); 8199702Slinton } 8209702Slinton 8219702Slinton conput( p ) register NODE *p; { 8229702Slinton switch( p->in.op ){ 8239702Slinton 8249702Slinton case ICON: 8259702Slinton acon( p ); 8269702Slinton return; 8279702Slinton 8289702Slinton case REG: 82924418Smckusick putstr( rnames[p->tn.rval] ); 8309702Slinton return; 8319702Slinton 8329702Slinton default: 8339702Slinton cerror( "illegal conput" ); 8349702Slinton } 8359702Slinton } 8369702Slinton 83732923Sdonn /*ARGSUSED*/ 83832924Sdonn insput( p ) NODE *p; { 8399702Slinton cerror( "insput" ); 8409702Slinton } 8419702Slinton 84232923Sdonn /*ARGSUSED*/ 84332924Sdonn upput( p, off ) NODE *p; int off; { 8449702Slinton cerror( "upput" ); 8459702Slinton } 8469702Slinton 8479702Slinton adrput( p ) register NODE *p; { 8489702Slinton register int r; 8499702Slinton /* output an address, with offsets, from p */ 8509702Slinton 8519702Slinton if( p->in.op == FLD ){ 8529702Slinton p = p->in.left; 8539702Slinton } 8549702Slinton switch( p->in.op ){ 8559702Slinton 8569702Slinton case NAME: 8579702Slinton acon( p ); 8589702Slinton return; 8599702Slinton 8609702Slinton case ICON: 8619702Slinton /* addressable value of the constant */ 86224418Smckusick putchar( '$' ); 8639702Slinton acon( p ); 8649702Slinton return; 8659702Slinton 8669702Slinton case REG: 86724418Smckusick putstr( rnames[p->tn.rval] ); 8689702Slinton return; 8699702Slinton 8709702Slinton case OREG: 8719702Slinton r = p->tn.rval; 8729702Slinton if( R2TEST(r) ){ /* double indexing */ 8739702Slinton register int flags; 8749702Slinton 8759702Slinton flags = R2UPK3(r); 87624418Smckusick if( flags & 1 ) putchar('*'); 87724418Smckusick if( flags & 4 ) putchar('-'); 8789702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 8799702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 88024418Smckusick if( flags & 2 ) putchar('+'); 8819702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 8829702Slinton return; 8839702Slinton } 8849702Slinton if( r == AP ){ /* in the argument region */ 885*32925Sdonn if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 8869702Slinton printf( CONFMT, p->tn.lval ); 88724418Smckusick putstr( "(ap)" ); 8889702Slinton return; 8899702Slinton } 8909702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 8919702Slinton printf( "(%s)", rnames[p->tn.rval] ); 8929702Slinton return; 8939702Slinton 8949702Slinton case UNARY MUL: 8959702Slinton /* STARNM or STARREG found */ 8969702Slinton if( tshape(p, STARNM) ) { 89724418Smckusick putchar( '*' ); 8989702Slinton adrput( p->in.left); 8999702Slinton } 9009702Slinton else { /* STARREG - really auto inc or dec */ 9019702Slinton register NODE *q; 9029702Slinton 9039702Slinton /* tbl 9049702Slinton p = p->in.left; 9059702Slinton p->in.left->in.op = OREG; 9069702Slinton if( p->in.op == INCR ) { 9079702Slinton adrput( p->in.left ); 90824418Smckusick putchar( '+' ); 9099702Slinton } 9109702Slinton else { 91124418Smckusick putchar( '-' ); 9129702Slinton adrput( p->in.left ); 9139702Slinton } 9149702Slinton tbl */ 91517659Sralph q = p->in.left; 91617742Sralph if( q->in.right->tn.lval != tlen(p) ) 91717742Sralph cerror("adrput: bad auto-increment/decrement"); 91817659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 91917659Sralph rnames[q->in.left->tn.rval], 92017659Sralph (q->in.op==INCR ? "+" : "") ); 9219702Slinton p->in.op = OREG; 92217659Sralph p->tn.rval = q->in.left->tn.rval; 92317659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 9249702Slinton #ifndef FLEXNAMES 9259702Slinton p->in.name[0] = '\0'; 9269702Slinton #else 9279702Slinton p->in.name = ""; 9289702Slinton #endif 9299702Slinton tfree(q); 9309702Slinton } 9319702Slinton return; 9329702Slinton 9339702Slinton default: 9349702Slinton cerror( "illegal address" ); 9359702Slinton return; 9369702Slinton 9379702Slinton } 9389702Slinton 9399702Slinton } 9409702Slinton 9419702Slinton acon( p ) register NODE *p; { /* print out a constant */ 9429702Slinton 9439702Slinton if( p->in.name[0] == '\0' ){ 9449702Slinton printf( CONFMT, p->tn.lval); 9459702Slinton } 9469702Slinton else if( p->tn.lval == 0 ) { 9479702Slinton #ifndef FLEXNAMES 9489702Slinton printf( "%.8s", p->in.name ); 9499702Slinton #else 95024418Smckusick putstr( p->in.name ); 9519702Slinton #endif 9529702Slinton } 9539702Slinton else { 9549702Slinton #ifndef FLEXNAMES 9559702Slinton printf( "%.8s+", p->in.name ); 9569702Slinton #else 9579702Slinton printf( "%s+", p->in.name ); 9589702Slinton #endif 9599702Slinton printf( CONFMT, p->tn.lval ); 9609702Slinton } 9619702Slinton } 9629702Slinton 9639702Slinton /* 9649702Slinton aacon( p ) register NODE *p; { /* print out a constant */ 9659702Slinton /* 9669702Slinton 9679702Slinton if( p->in.name[0] == '\0' ){ 9689702Slinton printf( CONFMT, p->tn.lval); 9699702Slinton return( 0 ); 9709702Slinton } 9719702Slinton else if( p->tn.lval == 0 ) { 9729702Slinton #ifndef FLEXNAMES 9739702Slinton printf( "$%.8s", p->in.name ); 9749702Slinton #else 9759702Slinton printf( "$%s", p->in.name ); 9769702Slinton #endif 9779702Slinton return( 1 ); 9789702Slinton } 9799702Slinton else { 9809702Slinton printf( "$(" ); 9819702Slinton printf( CONFMT, p->tn.lval ); 9829702Slinton printf( "+" ); 9839702Slinton #ifndef FLEXNAMES 9849702Slinton printf( "%.8s)", p->in.name ); 9859702Slinton #else 9869702Slinton printf( "%s)", p->in.name ); 9879702Slinton #endif 9889702Slinton return(1); 9899702Slinton } 9909702Slinton } 9919702Slinton */ 9929702Slinton 9939702Slinton genscall( p, cookie ) register NODE *p; { 9949702Slinton /* structure valued call */ 9959702Slinton return( gencall( p, cookie ) ); 9969702Slinton } 9979702Slinton 9989702Slinton /* tbl */ 9999702Slinton int gc_numbytes; 10009702Slinton /* tbl */ 10019702Slinton 100232924Sdonn /*ARGSUSED*/ 10039702Slinton gencall( p, cookie ) register NODE *p; { 10049702Slinton /* generate the call given by p */ 100516418Sralph register NODE *p1; 10069702Slinton register temp, temp1; 10079702Slinton register m; 10089702Slinton 10099702Slinton if( p->in.right ) temp = argsize( p->in.right ); 10109702Slinton else temp = 0; 10119702Slinton 10129702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 10139702Slinton /* set aside room for structure return */ 10149702Slinton 10159702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 10169702Slinton else temp1 = temp; 10179702Slinton } 10189702Slinton 10199702Slinton if( temp > maxargs ) maxargs = temp; 10209702Slinton SETOFF(temp1,4); 10219702Slinton 10229702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 102316418Sralph genargs( p->in.right ); 10249702Slinton } 10259702Slinton 10269702Slinton p1 = p->in.left; 10279702Slinton if( p1->in.op != ICON ){ 10289702Slinton if( p1->in.op != REG ){ 10299702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 10309702Slinton if( p1->in.op != NAME ){ 10319702Slinton order( p1, INAREG ); 10329702Slinton } 10339702Slinton } 10349702Slinton } 10359702Slinton } 10369702Slinton 10379702Slinton /* 10389702Slinton if( p1->in.op == REG && p->tn.rval == R5 ){ 10399702Slinton cerror( "call register overwrite" ); 10409702Slinton } 10419702Slinton */ 10429702Slinton /* tbl 10439702Slinton setup gc_numbytes so reference to ZC works */ 10449702Slinton 10459702Slinton gc_numbytes = temp&(0x3ff); 10469702Slinton /* tbl */ 10479702Slinton 10489702Slinton p->in.op = UNARY CALL; 10499702Slinton m = match( p, INTAREG|INTBREG ); 10509702Slinton 10519702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 10529702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 10539702Slinton if (temp >= 1024) 10549702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 10559702Slinton 10569702Slinton /* tbl 10579702Slinton switch( temp ) { 10589702Slinton case 0: 10599702Slinton break; 10609702Slinton case 2: 10619702Slinton printf( " tst (sp)+\n" ); 10629702Slinton break; 10639702Slinton case 4: 10649702Slinton printf( " cmp (sp)+,(sp)+\n" ); 10659702Slinton break; 10669702Slinton default: 10679702Slinton printf( " add $%d,sp\n", temp); 10689702Slinton } 10699702Slinton tbl */ 10709702Slinton return(m != MDONE); 10719702Slinton } 10729702Slinton 10739702Slinton /* tbl */ 10749702Slinton char * 10759702Slinton ccbranches[] = { 10769702Slinton " jeql L%d\n", 10779702Slinton " jneq L%d\n", 10789702Slinton " jleq L%d\n", 10799702Slinton " jlss L%d\n", 10809702Slinton " jgeq L%d\n", 10819702Slinton " jgtr L%d\n", 10829702Slinton " jlequ L%d\n", 10839702Slinton " jlssu L%d\n", 10849702Slinton " jgequ L%d\n", 10859702Slinton " jgtru L%d\n", 10869702Slinton }; 10879702Slinton /* tbl */ 10889702Slinton 108932924Sdonn /*ARGSUSED*/ 10909702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 10919702Slinton 10929702Slinton /* tbl */ 10939702Slinton if( o == 0 ) printf( " jbr L%d\n", lab ); 10949702Slinton /* tbl */ 10959702Slinton else { 10969702Slinton if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 10979702Slinton printf( ccbranches[o-EQ], lab ); 10989702Slinton } 10999702Slinton } 11009702Slinton 11019702Slinton nextcook( p, cookie ) NODE *p; { 11029702Slinton /* we have failed to match p with cookie; try another */ 11039702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 11049702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 11059702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 11069702Slinton return( FORREW ); 11079702Slinton } 11089702Slinton 110932924Sdonn /*ARGSUSED*/ 11109702Slinton lastchance( p, cook ) NODE *p; { 11119702Slinton /* forget it! */ 11129702Slinton return(0); 11139702Slinton } 11149702Slinton 11159702Slinton optim2( p ) register NODE *p; { 11169702Slinton /* do local tree transformations and optimizations */ 11179702Slinton 111816181Sralph register NODE *l, *r; 11199702Slinton 11209702Slinton switch( p->in.op ) { 11219702Slinton 11229702Slinton case AND: 112319933Smckusick /* commute L and R to eliminate complements and constants */ 112416181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 112516181Sralph l->in.op == COMPL ) { 11269702Slinton p->in.left = p->in.right; 112716181Sralph p->in.right = l; 11289702Slinton } 11299702Slinton case ASG AND: 11309702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 11319702Slinton r = p->in.right; 113219933Smckusick if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 11339702Slinton r->tn.lval = ~r->tn.lval; 11349702Slinton } 11359702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 11369702Slinton r->in.op = FREE; 11379702Slinton p->in.right = r->in.left; 11389702Slinton } 11399702Slinton else { /* insert complement node */ 114016181Sralph p->in.right = l = talloc(); 114116181Sralph l->in.op = COMPL; 114216181Sralph l->in.rall = NOPREF; 114316181Sralph l->in.type = r->in.type; 114416181Sralph l->in.left = r; 114516181Sralph l->in.right = NULL; 11469702Slinton } 11479702Slinton break; 11489702Slinton 114916181Sralph case SCONV: 115019933Smckusick l = p->in.left; 115117742Sralph #if defined(FORT) || defined(SPRECC) 115216573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 115319933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 115419933Smckusick return; 115516573Sralph #else 115619933Smckusick if( mixtypes(p, l) ) return; 115716573Sralph #endif 115832924Sdonn if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 115925751Sdonn return; 116025751Sdonn 116119933Smckusick /* Only trust it to get it right if the size is the same */ 116219933Smckusick if( tlen(p) != tlen(l) ) 116319933Smckusick return; 116416181Sralph 116516181Sralph /* clobber conversion */ 116619933Smckusick if( l->in.op != FLD ) 116716181Sralph l->in.type = p->in.type; 116816181Sralph ncopy( p, l ); 116916181Sralph l->in.op = FREE; 117019933Smckusick 117116181Sralph break; 117216181Sralph 117324418Smckusick case ASSIGN: 117424418Smckusick /* 117524418Smckusick * Conversions are equivalent to assignments; 117624418Smckusick * when the two operations are combined, 117724418Smckusick * we can sometimes zap the conversion. 117824418Smckusick */ 117924418Smckusick r = p->in.right; 118024418Smckusick l = p->in.left; 118124418Smckusick if ( r->in.op == SCONV && 118224418Smckusick !mixtypes(l, r) && 118332922Sdonn l->in.op != FLD && 118424418Smckusick tlen(l) == tlen(r) ) { 118524418Smckusick p->in.right = r->in.left; 118624418Smckusick r->in.op = FREE; 118724418Smckusick } 118824418Smckusick break; 118924418Smckusick 11909702Slinton } 11919702Slinton } 11929702Slinton 119332924Sdonn /*ARGSUSED*/ 119417742Sralph NODE * addroreg(l) NODE *l; 11959702Slinton /* OREG was built in clocal() 11969702Slinton * for an auto or formal parameter 11979702Slinton * now its address is being taken 11989702Slinton * local code must unwind it 11999702Slinton * back to PLUS/MINUS REG ICON 12009702Slinton * according to local conventions 12019702Slinton */ 12029702Slinton { 12039702Slinton cerror("address of OREG taken"); 120417742Sralph /*NOTREACHED*/ 12059702Slinton } 12069702Slinton 12079702Slinton 12089702Slinton 12099702Slinton # ifndef ONEPASS 12109702Slinton main( argc, argv ) char *argv[]; { 12119702Slinton return( mainp2( argc, argv ) ); 12129702Slinton } 12139702Slinton # endif 12149702Slinton 12159702Slinton 12169702Slinton /* added by jwf */ 12179702Slinton struct functbl { 12189702Slinton int fop; 12199702Slinton TWORD ftype; 12209702Slinton char *func; 12219702Slinton } opfunc[] = { 12229702Slinton DIV, TANY, "udiv", 12239702Slinton MOD, TANY, "urem", 122417715Sralph ASG DIV, TANY, "audiv", 122517715Sralph ASG MOD, TANY, "aurem", 12269702Slinton 0, 0, 0 }; 12279702Slinton 12289702Slinton hardops(p) register NODE *p; { 12299702Slinton /* change hard to do operators into function calls. */ 12309702Slinton register NODE *q; 12319702Slinton register struct functbl *f; 12329702Slinton register o; 123317742Sralph NODE *old,*temp; 12349702Slinton 12359702Slinton o = p->in.op; 123617742Sralph if( ! (optype(o)==BITYPE && 123717742Sralph (ISUNSIGNED(p->in.left->in.type) || 123817742Sralph ISUNSIGNED(p->in.right->in.type))) ) 123917742Sralph return; 12409702Slinton 12419702Slinton for( f=opfunc; f->fop; f++ ) { 12429702Slinton if( o==f->fop ) goto convert; 12439702Slinton } 12449702Slinton return; 12459702Slinton 12469702Slinton convert: 12479702Slinton if( asgop( o ) ) { 124817742Sralph old = NIL; 124917715Sralph switch( p->in.left->in.op ){ 125017742Sralph case FLD: 125117742Sralph q = p->in.left->in.left; 125217742Sralph /* 125317742Sralph * rewrite (lval.fld /= rval); as 125417742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 125517742Sralph * else the compiler will evaluate lval twice. 125617742Sralph */ 125717742Sralph if( q->in.op == UNARY MUL ){ 125817742Sralph /* first allocate a temp storage */ 125917742Sralph temp = talloc(); 126017742Sralph temp->in.op = OREG; 126117742Sralph temp->tn.rval = TMPREG; 126217742Sralph temp->tn.lval = BITOOR(freetemp(1)); 126317742Sralph temp->in.type = INCREF(p->in.type); 126417742Sralph #ifdef FLEXNAMES 126517742Sralph temp->in.name = ""; 126617742Sralph #else 126717742Sralph temp->in.name[0] = '\0'; 126817742Sralph #endif 126917742Sralph old = q->in.left; 127017742Sralph q->in.left = temp; 127117742Sralph } 127217742Sralph /* fall thru ... */ 127317742Sralph 127417715Sralph case REG: 127517715Sralph case NAME: 127617715Sralph case OREG: 127717715Sralph /* change ASG OP to a simple OP */ 127817715Sralph q = talloc(); 127917715Sralph q->in.op = NOASG p->in.op; 128017715Sralph q->in.rall = NOPREF; 128117715Sralph q->in.type = p->in.type; 128217715Sralph q->in.left = tcopy(p->in.left); 128317715Sralph q->in.right = p->in.right; 128417715Sralph p->in.op = ASSIGN; 128517715Sralph p->in.right = q; 128617715Sralph p = q; 128717715Sralph f -= 2; /* Note: this depends on the table order */ 128817742Sralph /* on the right side only - replace *temp with 128917742Sralph *(temp = &lval), build the assignment node */ 129017742Sralph if( old ){ 129117742Sralph temp = q->in.left->in.left; /* the "*" node */ 129217742Sralph q = talloc(); 129317742Sralph q->in.op = ASSIGN; 129417742Sralph q->in.left = temp->in.left; 129517742Sralph q->in.right = old; 129617742Sralph q->in.type = old->in.type; 129717742Sralph #ifdef FLEXNAMES 129817742Sralph q->in.name = ""; 129917742Sralph #else 130017742Sralph q->in.name[0] = '\0'; 130117742Sralph #endif 130217742Sralph temp->in.left = q; 130317742Sralph } 130417715Sralph break; 13059702Slinton 130617715Sralph case UNARY MUL: 130717715Sralph /* avoid doing side effects twice */ 130817715Sralph q = p->in.left; 130917715Sralph p->in.left = q->in.left; 131017715Sralph q->in.op = FREE; 131117715Sralph break; 131217715Sralph 131317715Sralph default: 131417715Sralph cerror( "hardops: can't compute & LHS" ); 131517715Sralph } 131617742Sralph } 131717715Sralph 13189702Slinton /* build comma op for args to function */ 13199702Slinton q = talloc(); 13209702Slinton q->in.op = CM; 13219702Slinton q->in.rall = NOPREF; 13229702Slinton q->in.type = INT; 13239702Slinton q->in.left = p->in.left; 13249702Slinton q->in.right = p->in.right; 13259702Slinton p->in.op = CALL; 13269702Slinton p->in.right = q; 13279702Slinton 13289702Slinton /* put function name in left node of call */ 13299702Slinton p->in.left = q = talloc(); 13309702Slinton q->in.op = ICON; 13319702Slinton q->in.rall = NOPREF; 13329702Slinton q->in.type = INCREF( FTN + p->in.type ); 13339702Slinton #ifndef FLEXNAMES 13349702Slinton strcpy( q->in.name, f->func ); 13359702Slinton #else 13369702Slinton q->in.name = f->func; 13379702Slinton #endif 13389702Slinton q->tn.lval = 0; 13399702Slinton q->tn.rval = 0; 13409702Slinton 13419702Slinton } 13429702Slinton 134317742Sralph zappost(p) NODE *p; { 134417742Sralph /* look for ++ and -- operators and remove them */ 134517742Sralph 134617742Sralph register o, ty; 134717742Sralph register NODE *q; 134817742Sralph o = p->in.op; 134917742Sralph ty = optype( o ); 135017742Sralph 135117742Sralph switch( o ){ 135217742Sralph 135317742Sralph case INCR: 135417742Sralph case DECR: 135517742Sralph q = p->in.left; 135617742Sralph p->in.right->in.op = FREE; /* zap constant */ 135717742Sralph ncopy( p, q ); 135817742Sralph q->in.op = FREE; 135917742Sralph return; 136017742Sralph 136117742Sralph } 136217742Sralph 136317742Sralph if( ty == BITYPE ) zappost( p->in.right ); 136417742Sralph if( ty != LTYPE ) zappost( p->in.left ); 136517742Sralph } 136617742Sralph 136717742Sralph fixpre(p) NODE *p; { 136817742Sralph 136917742Sralph register o, ty; 137017742Sralph o = p->in.op; 137117742Sralph ty = optype( o ); 137217742Sralph 137317742Sralph switch( o ){ 137417742Sralph 137517742Sralph case ASG PLUS: 137617742Sralph p->in.op = PLUS; 137717742Sralph break; 137817742Sralph case ASG MINUS: 137917742Sralph p->in.op = MINUS; 138017742Sralph break; 138117742Sralph } 138217742Sralph 138317742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 138417742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 138517742Sralph } 138617742Sralph 138724418Smckusick strip(p) register NODE *p; { 138824418Smckusick NODE *q; 138924418Smckusick 139024418Smckusick /* strip nodes off the top when no side effects occur */ 139124418Smckusick for( ; ; ) { 139224418Smckusick switch( p->in.op ) { 139324418Smckusick case SCONV: /* remove lint tidbits */ 139424418Smckusick q = p->in.left; 139524418Smckusick ncopy( p, q ); 139624418Smckusick q->in.op = FREE; 139724418Smckusick break; 139824418Smckusick /* could probably add a few more here */ 139924418Smckusick default: 140024418Smckusick return; 140124418Smckusick } 140224418Smckusick } 140324418Smckusick } 140424418Smckusick 14059702Slinton myreader(p) register NODE *p; { 140624418Smckusick strip( p ); /* strip off operations with no side effects */ 140717742Sralph canon( p ); /* expands r-vals for fields */ 14089702Slinton walkf( p, hardops ); /* convert ops to function calls */ 14099702Slinton walkf( p, optim2 ); 14109702Slinton /* jwf toff = 0; /* stack offset swindle */ 14119702Slinton } 1412