117742Sralph # ifndef lint 2*32926Sdonn static char *sccsid ="@(#)local2.c 1.20 (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 756*32926Sdonn /* INTEMP shapes must not contain any temporary registers */ 7579702Slinton shtemp( p ) register NODE *p; { 758*32926Sdonn int r; 759*32926Sdonn 7609702Slinton if( p->in.op == STARG ) p = p->in.left; 761*32926Sdonn 762*32926Sdonn switch (p->in.op) { 763*32926Sdonn case REG: 764*32926Sdonn return( !istreg(p->tn.rval) ); 765*32926Sdonn case OREG: 766*32926Sdonn r = p->tn.rval; 767*32926Sdonn if( R2TEST(r) ) { 768*32926Sdonn if( istreg(R2UPK1(r)) ) 769*32926Sdonn return(0); 770*32926Sdonn r = R2UPK2(r); 771*32926Sdonn } 772*32926Sdonn return( !istreg(r) ); 773*32926Sdonn /* 774*32926Sdonn case UNARY MUL: 775*32926Sdonn p = p->in.left; 776*32926Sdonn return( p->in.op != UNARY MUL && shtemp(p) ); 777*32926Sdonn */ 778*32926Sdonn } 779*32926Sdonn 780*32926Sdonn if( optype( p->in.op ) != LTYPE ) return(0); 781*32926Sdonn return(1); 7829702Slinton } 7839702Slinton 7849702Slinton shumul( p ) register NODE *p; { 7859702Slinton register o; 7869702Slinton extern int xdebug; 7879702Slinton 7889702Slinton if (xdebug) { 7899702Slinton printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 7909702Slinton printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 7919702Slinton } 7929702Slinton 7939702Slinton 7949702Slinton o = p->in.op; 7959702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 7969702Slinton 7979702Slinton if( ( o == INCR || o == ASG MINUS ) && 7989702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 7999702Slinton p->in.right->in.name[0] == '\0' ) 8009702Slinton { 80117659Sralph switch (p->in.type) 8029702Slinton { 8039702Slinton case CHAR|PTR: 8049702Slinton case UCHAR|PTR: 8059702Slinton o = 1; 8069702Slinton break; 8079702Slinton 8089702Slinton case SHORT|PTR: 8099702Slinton case USHORT|PTR: 8109702Slinton o = 2; 8119702Slinton break; 8129702Slinton 8139702Slinton case INT|PTR: 8149702Slinton case UNSIGNED|PTR: 8159702Slinton case LONG|PTR: 8169702Slinton case ULONG|PTR: 8179702Slinton case FLOAT|PTR: 8189702Slinton o = 4; 8199702Slinton break; 8209702Slinton 8219702Slinton case DOUBLE|PTR: 8229702Slinton o = 8; 8239702Slinton break; 8249702Slinton 8259702Slinton default: 82617742Sralph if ( ISPTR(p->in.type) && 82717742Sralph ISPTR(DECREF(p->in.type)) ) { 8289702Slinton o = 4; 8299702Slinton break; 8309702Slinton } 8319702Slinton else return(0); 8329702Slinton } 8339702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 8349702Slinton } 8359702Slinton 8369702Slinton return( 0 ); 8379702Slinton } 8389702Slinton 8399702Slinton adrcon( val ) CONSZ val; { 84024418Smckusick putchar( '$' ); 8419702Slinton printf( CONFMT, val ); 8429702Slinton } 8439702Slinton 8449702Slinton conput( p ) register NODE *p; { 8459702Slinton switch( p->in.op ){ 8469702Slinton 8479702Slinton case ICON: 8489702Slinton acon( p ); 8499702Slinton return; 8509702Slinton 8519702Slinton case REG: 85224418Smckusick putstr( rnames[p->tn.rval] ); 8539702Slinton return; 8549702Slinton 8559702Slinton default: 8569702Slinton cerror( "illegal conput" ); 8579702Slinton } 8589702Slinton } 8599702Slinton 86032923Sdonn /*ARGSUSED*/ 86132924Sdonn insput( p ) NODE *p; { 8629702Slinton cerror( "insput" ); 8639702Slinton } 8649702Slinton 86532923Sdonn /*ARGSUSED*/ 86632924Sdonn upput( p, off ) NODE *p; int off; { 8679702Slinton cerror( "upput" ); 8689702Slinton } 8699702Slinton 8709702Slinton adrput( p ) register NODE *p; { 8719702Slinton register int r; 8729702Slinton /* output an address, with offsets, from p */ 8739702Slinton 8749702Slinton if( p->in.op == FLD ){ 8759702Slinton p = p->in.left; 8769702Slinton } 8779702Slinton switch( p->in.op ){ 8789702Slinton 8799702Slinton case NAME: 8809702Slinton acon( p ); 8819702Slinton return; 8829702Slinton 8839702Slinton case ICON: 8849702Slinton /* addressable value of the constant */ 88524418Smckusick putchar( '$' ); 8869702Slinton acon( p ); 8879702Slinton return; 8889702Slinton 8899702Slinton case REG: 89024418Smckusick putstr( rnames[p->tn.rval] ); 8919702Slinton return; 8929702Slinton 8939702Slinton case OREG: 8949702Slinton r = p->tn.rval; 8959702Slinton if( R2TEST(r) ){ /* double indexing */ 8969702Slinton register int flags; 8979702Slinton 8989702Slinton flags = R2UPK3(r); 89924418Smckusick if( flags & 1 ) putchar('*'); 90024418Smckusick if( flags & 4 ) putchar('-'); 9019702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 9029702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 90324418Smckusick if( flags & 2 ) putchar('+'); 9049702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 9059702Slinton return; 9069702Slinton } 9079702Slinton if( r == AP ){ /* in the argument region */ 90832925Sdonn if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 9099702Slinton printf( CONFMT, p->tn.lval ); 91024418Smckusick putstr( "(ap)" ); 9119702Slinton return; 9129702Slinton } 9139702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 9149702Slinton printf( "(%s)", rnames[p->tn.rval] ); 9159702Slinton return; 9169702Slinton 9179702Slinton case UNARY MUL: 9189702Slinton /* STARNM or STARREG found */ 9199702Slinton if( tshape(p, STARNM) ) { 92024418Smckusick putchar( '*' ); 9219702Slinton adrput( p->in.left); 9229702Slinton } 9239702Slinton else { /* STARREG - really auto inc or dec */ 9249702Slinton register NODE *q; 9259702Slinton 9269702Slinton /* tbl 9279702Slinton p = p->in.left; 9289702Slinton p->in.left->in.op = OREG; 9299702Slinton if( p->in.op == INCR ) { 9309702Slinton adrput( p->in.left ); 93124418Smckusick putchar( '+' ); 9329702Slinton } 9339702Slinton else { 93424418Smckusick putchar( '-' ); 9359702Slinton adrput( p->in.left ); 9369702Slinton } 9379702Slinton tbl */ 93817659Sralph q = p->in.left; 93917742Sralph if( q->in.right->tn.lval != tlen(p) ) 94017742Sralph cerror("adrput: bad auto-increment/decrement"); 94117659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 94217659Sralph rnames[q->in.left->tn.rval], 94317659Sralph (q->in.op==INCR ? "+" : "") ); 9449702Slinton p->in.op = OREG; 94517659Sralph p->tn.rval = q->in.left->tn.rval; 94617659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 9479702Slinton #ifndef FLEXNAMES 9489702Slinton p->in.name[0] = '\0'; 9499702Slinton #else 9509702Slinton p->in.name = ""; 9519702Slinton #endif 9529702Slinton tfree(q); 9539702Slinton } 9549702Slinton return; 9559702Slinton 9569702Slinton default: 9579702Slinton cerror( "illegal address" ); 9589702Slinton return; 9599702Slinton 9609702Slinton } 9619702Slinton 9629702Slinton } 9639702Slinton 9649702Slinton acon( p ) register NODE *p; { /* print out a constant */ 9659702Slinton 9669702Slinton if( p->in.name[0] == '\0' ){ 9679702Slinton printf( CONFMT, p->tn.lval); 9689702Slinton } 9699702Slinton else if( p->tn.lval == 0 ) { 9709702Slinton #ifndef FLEXNAMES 9719702Slinton printf( "%.8s", p->in.name ); 9729702Slinton #else 97324418Smckusick putstr( p->in.name ); 9749702Slinton #endif 9759702Slinton } 9769702Slinton else { 9779702Slinton #ifndef FLEXNAMES 9789702Slinton printf( "%.8s+", p->in.name ); 9799702Slinton #else 9809702Slinton printf( "%s+", p->in.name ); 9819702Slinton #endif 9829702Slinton printf( CONFMT, p->tn.lval ); 9839702Slinton } 9849702Slinton } 9859702Slinton 9869702Slinton /* 9879702Slinton aacon( p ) register NODE *p; { /* print out a constant */ 9889702Slinton /* 9899702Slinton 9909702Slinton if( p->in.name[0] == '\0' ){ 9919702Slinton printf( CONFMT, p->tn.lval); 9929702Slinton return( 0 ); 9939702Slinton } 9949702Slinton else if( p->tn.lval == 0 ) { 9959702Slinton #ifndef FLEXNAMES 9969702Slinton printf( "$%.8s", p->in.name ); 9979702Slinton #else 9989702Slinton printf( "$%s", p->in.name ); 9999702Slinton #endif 10009702Slinton return( 1 ); 10019702Slinton } 10029702Slinton else { 10039702Slinton printf( "$(" ); 10049702Slinton printf( CONFMT, p->tn.lval ); 10059702Slinton printf( "+" ); 10069702Slinton #ifndef FLEXNAMES 10079702Slinton printf( "%.8s)", p->in.name ); 10089702Slinton #else 10099702Slinton printf( "%s)", p->in.name ); 10109702Slinton #endif 10119702Slinton return(1); 10129702Slinton } 10139702Slinton } 10149702Slinton */ 10159702Slinton 10169702Slinton genscall( p, cookie ) register NODE *p; { 10179702Slinton /* structure valued call */ 10189702Slinton return( gencall( p, cookie ) ); 10199702Slinton } 10209702Slinton 10219702Slinton /* tbl */ 10229702Slinton int gc_numbytes; 10239702Slinton /* tbl */ 10249702Slinton 102532924Sdonn /*ARGSUSED*/ 10269702Slinton gencall( p, cookie ) register NODE *p; { 10279702Slinton /* generate the call given by p */ 102816418Sralph register NODE *p1; 10299702Slinton register temp, temp1; 10309702Slinton register m; 10319702Slinton 10329702Slinton if( p->in.right ) temp = argsize( p->in.right ); 10339702Slinton else temp = 0; 10349702Slinton 10359702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 10369702Slinton /* set aside room for structure return */ 10379702Slinton 10389702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 10399702Slinton else temp1 = temp; 10409702Slinton } 10419702Slinton 10429702Slinton if( temp > maxargs ) maxargs = temp; 10439702Slinton SETOFF(temp1,4); 10449702Slinton 10459702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 104616418Sralph genargs( p->in.right ); 10479702Slinton } 10489702Slinton 10499702Slinton p1 = p->in.left; 10509702Slinton if( p1->in.op != ICON ){ 10519702Slinton if( p1->in.op != REG ){ 10529702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 10539702Slinton if( p1->in.op != NAME ){ 10549702Slinton order( p1, INAREG ); 10559702Slinton } 10569702Slinton } 10579702Slinton } 10589702Slinton } 10599702Slinton 10609702Slinton /* 10619702Slinton if( p1->in.op == REG && p->tn.rval == R5 ){ 10629702Slinton cerror( "call register overwrite" ); 10639702Slinton } 10649702Slinton */ 10659702Slinton /* tbl 10669702Slinton setup gc_numbytes so reference to ZC works */ 10679702Slinton 10689702Slinton gc_numbytes = temp&(0x3ff); 10699702Slinton /* tbl */ 10709702Slinton 10719702Slinton p->in.op = UNARY CALL; 10729702Slinton m = match( p, INTAREG|INTBREG ); 10739702Slinton 10749702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 10759702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 10769702Slinton if (temp >= 1024) 10779702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 10789702Slinton 10799702Slinton /* tbl 10809702Slinton switch( temp ) { 10819702Slinton case 0: 10829702Slinton break; 10839702Slinton case 2: 10849702Slinton printf( " tst (sp)+\n" ); 10859702Slinton break; 10869702Slinton case 4: 10879702Slinton printf( " cmp (sp)+,(sp)+\n" ); 10889702Slinton break; 10899702Slinton default: 10909702Slinton printf( " add $%d,sp\n", temp); 10919702Slinton } 10929702Slinton tbl */ 10939702Slinton return(m != MDONE); 10949702Slinton } 10959702Slinton 10969702Slinton /* tbl */ 10979702Slinton char * 10989702Slinton ccbranches[] = { 10999702Slinton " jeql L%d\n", 11009702Slinton " jneq L%d\n", 11019702Slinton " jleq L%d\n", 11029702Slinton " jlss L%d\n", 11039702Slinton " jgeq L%d\n", 11049702Slinton " jgtr L%d\n", 11059702Slinton " jlequ L%d\n", 11069702Slinton " jlssu L%d\n", 11079702Slinton " jgequ L%d\n", 11089702Slinton " jgtru L%d\n", 11099702Slinton }; 11109702Slinton /* tbl */ 11119702Slinton 111232924Sdonn /*ARGSUSED*/ 11139702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 11149702Slinton 11159702Slinton /* tbl */ 11169702Slinton if( o == 0 ) printf( " jbr L%d\n", lab ); 11179702Slinton /* tbl */ 11189702Slinton else { 11199702Slinton if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 11209702Slinton printf( ccbranches[o-EQ], lab ); 11219702Slinton } 11229702Slinton } 11239702Slinton 11249702Slinton nextcook( p, cookie ) NODE *p; { 11259702Slinton /* we have failed to match p with cookie; try another */ 11269702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 11279702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 11289702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 11299702Slinton return( FORREW ); 11309702Slinton } 11319702Slinton 113232924Sdonn /*ARGSUSED*/ 11339702Slinton lastchance( p, cook ) NODE *p; { 11349702Slinton /* forget it! */ 11359702Slinton return(0); 11369702Slinton } 11379702Slinton 11389702Slinton optim2( p ) register NODE *p; { 11399702Slinton /* do local tree transformations and optimizations */ 11409702Slinton 114116181Sralph register NODE *l, *r; 11429702Slinton 11439702Slinton switch( p->in.op ) { 11449702Slinton 11459702Slinton case AND: 114619933Smckusick /* commute L and R to eliminate complements and constants */ 114716181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 114816181Sralph l->in.op == COMPL ) { 11499702Slinton p->in.left = p->in.right; 115016181Sralph p->in.right = l; 11519702Slinton } 11529702Slinton case ASG AND: 11539702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 11549702Slinton r = p->in.right; 115519933Smckusick if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 11569702Slinton r->tn.lval = ~r->tn.lval; 11579702Slinton } 11589702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 11599702Slinton r->in.op = FREE; 11609702Slinton p->in.right = r->in.left; 11619702Slinton } 11629702Slinton else { /* insert complement node */ 116316181Sralph p->in.right = l = talloc(); 116416181Sralph l->in.op = COMPL; 116516181Sralph l->in.rall = NOPREF; 116616181Sralph l->in.type = r->in.type; 116716181Sralph l->in.left = r; 116816181Sralph l->in.right = NULL; 11699702Slinton } 11709702Slinton break; 11719702Slinton 117216181Sralph case SCONV: 117319933Smckusick l = p->in.left; 117417742Sralph #if defined(FORT) || defined(SPRECC) 117516573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 117619933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 117719933Smckusick return; 117816573Sralph #else 117919933Smckusick if( mixtypes(p, l) ) return; 118016573Sralph #endif 118132924Sdonn if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 118225751Sdonn return; 118325751Sdonn 118419933Smckusick /* Only trust it to get it right if the size is the same */ 118519933Smckusick if( tlen(p) != tlen(l) ) 118619933Smckusick return; 118716181Sralph 118816181Sralph /* clobber conversion */ 118919933Smckusick if( l->in.op != FLD ) 119016181Sralph l->in.type = p->in.type; 119116181Sralph ncopy( p, l ); 119216181Sralph l->in.op = FREE; 119319933Smckusick 119416181Sralph break; 119516181Sralph 119624418Smckusick case ASSIGN: 119724418Smckusick /* 119824418Smckusick * Conversions are equivalent to assignments; 119924418Smckusick * when the two operations are combined, 120024418Smckusick * we can sometimes zap the conversion. 120124418Smckusick */ 120224418Smckusick r = p->in.right; 120324418Smckusick l = p->in.left; 120424418Smckusick if ( r->in.op == SCONV && 120524418Smckusick !mixtypes(l, r) && 120632922Sdonn l->in.op != FLD && 120724418Smckusick tlen(l) == tlen(r) ) { 120824418Smckusick p->in.right = r->in.left; 120924418Smckusick r->in.op = FREE; 121024418Smckusick } 121124418Smckusick break; 121224418Smckusick 12139702Slinton } 12149702Slinton } 12159702Slinton 121632924Sdonn /*ARGSUSED*/ 121717742Sralph NODE * addroreg(l) NODE *l; 12189702Slinton /* OREG was built in clocal() 12199702Slinton * for an auto or formal parameter 12209702Slinton * now its address is being taken 12219702Slinton * local code must unwind it 12229702Slinton * back to PLUS/MINUS REG ICON 12239702Slinton * according to local conventions 12249702Slinton */ 12259702Slinton { 12269702Slinton cerror("address of OREG taken"); 122717742Sralph /*NOTREACHED*/ 12289702Slinton } 12299702Slinton 12309702Slinton 12319702Slinton 12329702Slinton # ifndef ONEPASS 12339702Slinton main( argc, argv ) char *argv[]; { 12349702Slinton return( mainp2( argc, argv ) ); 12359702Slinton } 12369702Slinton # endif 12379702Slinton 12389702Slinton 12399702Slinton /* added by jwf */ 12409702Slinton struct functbl { 12419702Slinton int fop; 12429702Slinton TWORD ftype; 12439702Slinton char *func; 12449702Slinton } opfunc[] = { 12459702Slinton DIV, TANY, "udiv", 12469702Slinton MOD, TANY, "urem", 124717715Sralph ASG DIV, TANY, "audiv", 124817715Sralph ASG MOD, TANY, "aurem", 12499702Slinton 0, 0, 0 }; 12509702Slinton 12519702Slinton hardops(p) register NODE *p; { 12529702Slinton /* change hard to do operators into function calls. */ 12539702Slinton register NODE *q; 12549702Slinton register struct functbl *f; 12559702Slinton register o; 125617742Sralph NODE *old,*temp; 12579702Slinton 12589702Slinton o = p->in.op; 125917742Sralph if( ! (optype(o)==BITYPE && 126017742Sralph (ISUNSIGNED(p->in.left->in.type) || 126117742Sralph ISUNSIGNED(p->in.right->in.type))) ) 126217742Sralph return; 12639702Slinton 12649702Slinton for( f=opfunc; f->fop; f++ ) { 12659702Slinton if( o==f->fop ) goto convert; 12669702Slinton } 12679702Slinton return; 12689702Slinton 12699702Slinton convert: 12709702Slinton if( asgop( o ) ) { 127117742Sralph old = NIL; 127217715Sralph switch( p->in.left->in.op ){ 127317742Sralph case FLD: 127417742Sralph q = p->in.left->in.left; 127517742Sralph /* 127617742Sralph * rewrite (lval.fld /= rval); as 127717742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 127817742Sralph * else the compiler will evaluate lval twice. 127917742Sralph */ 128017742Sralph if( q->in.op == UNARY MUL ){ 128117742Sralph /* first allocate a temp storage */ 128217742Sralph temp = talloc(); 128317742Sralph temp->in.op = OREG; 128417742Sralph temp->tn.rval = TMPREG; 128517742Sralph temp->tn.lval = BITOOR(freetemp(1)); 128617742Sralph temp->in.type = INCREF(p->in.type); 128717742Sralph #ifdef FLEXNAMES 128817742Sralph temp->in.name = ""; 128917742Sralph #else 129017742Sralph temp->in.name[0] = '\0'; 129117742Sralph #endif 129217742Sralph old = q->in.left; 129317742Sralph q->in.left = temp; 129417742Sralph } 129517742Sralph /* fall thru ... */ 129617742Sralph 129717715Sralph case REG: 129817715Sralph case NAME: 129917715Sralph case OREG: 130017715Sralph /* change ASG OP to a simple OP */ 130117715Sralph q = talloc(); 130217715Sralph q->in.op = NOASG p->in.op; 130317715Sralph q->in.rall = NOPREF; 130417715Sralph q->in.type = p->in.type; 130517715Sralph q->in.left = tcopy(p->in.left); 130617715Sralph q->in.right = p->in.right; 130717715Sralph p->in.op = ASSIGN; 130817715Sralph p->in.right = q; 130917715Sralph p = q; 131017715Sralph f -= 2; /* Note: this depends on the table order */ 131117742Sralph /* on the right side only - replace *temp with 131217742Sralph *(temp = &lval), build the assignment node */ 131317742Sralph if( old ){ 131417742Sralph temp = q->in.left->in.left; /* the "*" node */ 131517742Sralph q = talloc(); 131617742Sralph q->in.op = ASSIGN; 131717742Sralph q->in.left = temp->in.left; 131817742Sralph q->in.right = old; 131917742Sralph q->in.type = old->in.type; 132017742Sralph #ifdef FLEXNAMES 132117742Sralph q->in.name = ""; 132217742Sralph #else 132317742Sralph q->in.name[0] = '\0'; 132417742Sralph #endif 132517742Sralph temp->in.left = q; 132617742Sralph } 132717715Sralph break; 13289702Slinton 132917715Sralph case UNARY MUL: 133017715Sralph /* avoid doing side effects twice */ 133117715Sralph q = p->in.left; 133217715Sralph p->in.left = q->in.left; 133317715Sralph q->in.op = FREE; 133417715Sralph break; 133517715Sralph 133617715Sralph default: 133717715Sralph cerror( "hardops: can't compute & LHS" ); 133817715Sralph } 133917742Sralph } 134017715Sralph 13419702Slinton /* build comma op for args to function */ 13429702Slinton q = talloc(); 13439702Slinton q->in.op = CM; 13449702Slinton q->in.rall = NOPREF; 13459702Slinton q->in.type = INT; 13469702Slinton q->in.left = p->in.left; 13479702Slinton q->in.right = p->in.right; 13489702Slinton p->in.op = CALL; 13499702Slinton p->in.right = q; 13509702Slinton 13519702Slinton /* put function name in left node of call */ 13529702Slinton p->in.left = q = talloc(); 13539702Slinton q->in.op = ICON; 13549702Slinton q->in.rall = NOPREF; 13559702Slinton q->in.type = INCREF( FTN + p->in.type ); 13569702Slinton #ifndef FLEXNAMES 13579702Slinton strcpy( q->in.name, f->func ); 13589702Slinton #else 13599702Slinton q->in.name = f->func; 13609702Slinton #endif 13619702Slinton q->tn.lval = 0; 13629702Slinton q->tn.rval = 0; 13639702Slinton 13649702Slinton } 13659702Slinton 136617742Sralph zappost(p) NODE *p; { 136717742Sralph /* look for ++ and -- operators and remove them */ 136817742Sralph 136917742Sralph register o, ty; 137017742Sralph register NODE *q; 137117742Sralph o = p->in.op; 137217742Sralph ty = optype( o ); 137317742Sralph 137417742Sralph switch( o ){ 137517742Sralph 137617742Sralph case INCR: 137717742Sralph case DECR: 137817742Sralph q = p->in.left; 137917742Sralph p->in.right->in.op = FREE; /* zap constant */ 138017742Sralph ncopy( p, q ); 138117742Sralph q->in.op = FREE; 138217742Sralph return; 138317742Sralph 138417742Sralph } 138517742Sralph 138617742Sralph if( ty == BITYPE ) zappost( p->in.right ); 138717742Sralph if( ty != LTYPE ) zappost( p->in.left ); 138817742Sralph } 138917742Sralph 139017742Sralph fixpre(p) NODE *p; { 139117742Sralph 139217742Sralph register o, ty; 139317742Sralph o = p->in.op; 139417742Sralph ty = optype( o ); 139517742Sralph 139617742Sralph switch( o ){ 139717742Sralph 139817742Sralph case ASG PLUS: 139917742Sralph p->in.op = PLUS; 140017742Sralph break; 140117742Sralph case ASG MINUS: 140217742Sralph p->in.op = MINUS; 140317742Sralph break; 140417742Sralph } 140517742Sralph 140617742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 140717742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 140817742Sralph } 140917742Sralph 141024418Smckusick strip(p) register NODE *p; { 141124418Smckusick NODE *q; 141224418Smckusick 141324418Smckusick /* strip nodes off the top when no side effects occur */ 141424418Smckusick for( ; ; ) { 141524418Smckusick switch( p->in.op ) { 141624418Smckusick case SCONV: /* remove lint tidbits */ 141724418Smckusick q = p->in.left; 141824418Smckusick ncopy( p, q ); 141924418Smckusick q->in.op = FREE; 142024418Smckusick break; 142124418Smckusick /* could probably add a few more here */ 142224418Smckusick default: 142324418Smckusick return; 142424418Smckusick } 142524418Smckusick } 142624418Smckusick } 142724418Smckusick 14289702Slinton myreader(p) register NODE *p; { 142924418Smckusick strip( p ); /* strip off operations with no side effects */ 143017742Sralph canon( p ); /* expands r-vals for fields */ 14319702Slinton walkf( p, hardops ); /* convert ops to function calls */ 14329702Slinton walkf( p, optim2 ); 14339702Slinton /* jwf toff = 0; /* stack offset swindle */ 14349702Slinton } 1435