117742Sralph # ifndef lint 2*25751Sdonn static char *sccsid ="@(#)local2.c 1.13 (Berkeley) 01/08/86"; 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 169702Slinton where(c){ 179702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno ); 189702Slinton } 199702Slinton 209702Slinton lineid( l, fn ) char *fn; { 219702Slinton /* identify line l and file fn */ 229702Slinton printf( "# line %d, file %s\n", l, fn ); 239702Slinton } 249702Slinton 259702Slinton 269702Slinton eobl2(){ 279702Slinton OFFSZ spoff; /* offset from stack pointer */ 289702Slinton #ifdef FORT 299702Slinton spoff = maxoff; 309702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 319702Slinton spoff /= SZCHAR; 329702Slinton SETOFF(spoff,4); 339702Slinton #ifndef FLEXNAMES 349702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff ); 359702Slinton #else 369702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 379702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff ); 389702Slinton #endif 399702Slinton #else 409702Slinton extern int ftlab1, ftlab2; 419702Slinton 429702Slinton spoff = maxoff; 439702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 449702Slinton spoff /= SZCHAR; 459702Slinton SETOFF(spoff,4); 469702Slinton printf( "L%d:\n", ftlab1); 479702Slinton if( spoff!=0 ) 489702Slinton if( spoff < 64 ) 499702Slinton printf( " subl2 $%ld,sp\n", spoff); 509702Slinton else 519702Slinton printf( " movab -%ld(sp),sp\n", spoff); 529702Slinton printf( " jbr L%d\n", ftlab2); 539702Slinton #endif 549702Slinton maxargs = -1; 559702Slinton } 569702Slinton 579702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = { 589702Slinton 599702Slinton ASG PLUS, "add", 609702Slinton ASG MINUS, "sub", 619702Slinton ASG MUL, "mul", 629702Slinton ASG DIV, "div", 639702Slinton ASG OR, "bis", 649702Slinton ASG ER, "xor", 659702Slinton ASG AND, "bic", 669702Slinton PLUS, "add", 679702Slinton MINUS, "sub", 689702Slinton MUL, "mul", 699702Slinton DIV, "div", 709702Slinton OR, "bis", 719702Slinton ER, "xor", 729702Slinton AND, "bic", 739702Slinton -1, "" }; 749702Slinton 759702Slinton hopcode( f, o ){ 769702Slinton /* output the appropriate string from the above table */ 779702Slinton 789702Slinton register struct hoptab *q; 799702Slinton 809702Slinton for( q = ioptab; q->opmask>=0; ++q ){ 819702Slinton if( q->opmask == o ){ 8224418Smckusick putstr( q->opstring ); 839702Slinton /* tbl 8424418Smckusick if( f == 'F' ) putchar( 'e' ); 8524418Smckusick else if( f == 'D' ) putchar( 'd' ); 869702Slinton tbl */ 879702Slinton /* tbl */ 889702Slinton switch( f ) { 899702Slinton case 'L': 909702Slinton case 'W': 919702Slinton case 'B': 929702Slinton case 'D': 939702Slinton case 'F': 9424418Smckusick putchar(tolower(f)); 959702Slinton break; 969702Slinton 979702Slinton } 989702Slinton /* tbl */ 999702Slinton return; 1009702Slinton } 1019702Slinton } 1029702Slinton cerror( "no hoptab for %s", opst[o] ); 1039702Slinton } 1049702Slinton 1059702Slinton char * 1069702Slinton rnames[] = { /* keyed to register number tokens */ 1079702Slinton 1089702Slinton "r0", "r1", 1099702Slinton "r2", "r3", "r4", "r5", 1109702Slinton "r6", "r7", "r8", "r9", "r10", "r11", 1119702Slinton "ap", "fp", "sp", "pc", 1129702Slinton 1139702Slinton }; 1149702Slinton 1159702Slinton int rstatus[] = { 1169702Slinton SAREG|STAREG, SAREG|STAREG, 1179702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 1189702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 1199702Slinton SAREG, SAREG, SAREG, SAREG, 1209702Slinton 1219702Slinton }; 1229702Slinton 1239702Slinton tlen(p) NODE *p; 1249702Slinton { 1259702Slinton switch(p->in.type) { 1269702Slinton case CHAR: 1279702Slinton case UCHAR: 1289702Slinton return(1); 1299702Slinton 1309702Slinton case SHORT: 1319702Slinton case USHORT: 1329702Slinton return(2); 1339702Slinton 1349702Slinton case DOUBLE: 1359702Slinton return(8); 1369702Slinton 1379702Slinton default: 1389702Slinton return(4); 1399702Slinton } 1409702Slinton } 1419702Slinton 1429702Slinton mixtypes(p, q) NODE *p, *q; 1439702Slinton { 14416181Sralph register TWORD tp, tq; 1459702Slinton 1469702Slinton tp = p->in.type; 1479702Slinton tq = q->in.type; 1489702Slinton 1499702Slinton return( (tp==FLOAT || tp==DOUBLE) != 1509702Slinton (tq==FLOAT || tq==DOUBLE) ); 1519702Slinton } 1529702Slinton 1539702Slinton prtype(n) NODE *n; 1549702Slinton { 1559702Slinton switch (n->in.type) 1569702Slinton { 1579702Slinton case DOUBLE: 15824418Smckusick putchar('d'); 1599702Slinton return; 1609702Slinton 1619702Slinton case FLOAT: 16224418Smckusick putchar('f'); 1639702Slinton return; 1649702Slinton 1659702Slinton case LONG: 1669702Slinton case ULONG: 1679702Slinton case INT: 1689702Slinton case UNSIGNED: 16924418Smckusick putchar('l'); 1709702Slinton return; 1719702Slinton 1729702Slinton case SHORT: 1739702Slinton case USHORT: 17424418Smckusick putchar('w'); 1759702Slinton return; 1769702Slinton 1779702Slinton case CHAR: 1789702Slinton case UCHAR: 17924418Smckusick putchar('b'); 1809702Slinton return; 1819702Slinton 1829702Slinton default: 1839702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 1849702Slinton else { 18524418Smckusick putchar('l'); 1869702Slinton return; 1879702Slinton } 1889702Slinton } 1899702Slinton } 1909702Slinton 1919702Slinton zzzcode( p, c ) register NODE *p; { 1929702Slinton register m; 1939702Slinton CONSZ val; 1949702Slinton switch( c ){ 1959702Slinton 1969702Slinton case 'N': /* logical ops, turned into 0-1 */ 1979702Slinton /* use register given by register 1 */ 1989702Slinton cbgen( 0, m=getlab(), 'I' ); 1999702Slinton deflab( p->bn.label ); 2009702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 2019702Slinton deflab( m ); 2029702Slinton return; 2039702Slinton 2049702Slinton case 'I': 2059702Slinton case 'P': 2069702Slinton cbgen( p->in.op, p->bn.label, c ); 2079702Slinton return; 2089702Slinton 2099702Slinton case 'A': 2109702Slinton { 2119702Slinton register NODE *l, *r; 2129702Slinton 2139702Slinton if (xdebug) eprint(p, 0, &val, &val); 2149702Slinton r = getlr(p, 'R'); 21516181Sralph if (p->in.op == ASSIGN) 21616181Sralph l = getlr(p, 'L'); 21717208Sralph else if (p->in.op == SCONV) { 2189702Slinton l = resc; 21917742Sralph #if defined(FORT) || defined(SPRECC) 22016181Sralph l->in.type = r->in.type; 22116181Sralph #else 22216181Sralph l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 22316181Sralph #endif 22416181Sralph r = getlr(p, 'L'); 22516181Sralph } 22617208Sralph else { /* OPLTYPE */ 22716181Sralph l = resc; 22817742Sralph #if defined(FORT) || defined(SPRECC) 22916181Sralph l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 23016181Sralph #else 2319702Slinton l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 23216181Sralph #endif 2339702Slinton } 2349702Slinton if (r->in.op == ICON) 23517208Sralph if (r->in.name[0] == '\0') { 23617208Sralph if (r->tn.lval == 0) { 23724418Smckusick putstr("clr"); 2389702Slinton prtype(l); 23924418Smckusick putchar('\t'); 2409702Slinton adrput(l); 2419702Slinton return; 2429702Slinton } 24317208Sralph if (r->tn.lval < 0 && r->tn.lval >= -63) { 24424418Smckusick putstr("mneg"); 2459702Slinton prtype(l); 2469702Slinton r->tn.lval = -r->tn.lval; 2479702Slinton goto ops; 2489702Slinton } 24917208Sralph if (r->tn.lval < 0) 25017208Sralph r->in.type = r->tn.lval >= -128 ? CHAR 2519702Slinton : (r->tn.lval >= -32768 ? SHORT 25217208Sralph : INT); 25317208Sralph else if (l->in.type == FLOAT || 25417208Sralph l->in.type == DOUBLE) 25517208Sralph r->in.type = r->tn.lval <= 63 ? INT 25617208Sralph : (r->tn.lval <= 127 ? CHAR 25717208Sralph : (r->tn.lval <= 32767 ? SHORT 25817208Sralph : INT)); 25917208Sralph else 26017208Sralph r->in.type = r->tn.lval <= 63 ? INT 26117208Sralph : (r->tn.lval <= 127 ? CHAR 2629702Slinton : (r->tn.lval <= 255 ? UCHAR 2639702Slinton : (r->tn.lval <= 32767 ? SHORT 2649702Slinton : (r->tn.lval <= 65535 ? USHORT 26517208Sralph : INT)))); 2669702Slinton } 26717208Sralph else { 26824418Smckusick putstr("moval"); 26924418Smckusick putchar('\t'); 27016181Sralph acon(r); 27124418Smckusick putchar(','); 27216181Sralph adrput(l); 27316181Sralph return; 27416181Sralph } 2759702Slinton 27623536Sbloom if (p->in.op == SCONV && 27723536Sbloom !(l->in.type == FLOAT || l->in.type == DOUBLE) && 27823536Sbloom !mixtypes(l, r)) { 27923536Sbloom /* 28023536Sbloom * Because registers must always contain objects 28123536Sbloom * of the same width as INTs, we may have to 28223536Sbloom * perform two conversions to get an INT. Can 28323536Sbloom * the conversions be collapsed into one? 28423536Sbloom */ 28523536Sbloom if (m = collapsible(l, r)) 28623536Sbloom r->in.type = m; 28723536Sbloom else { 28823536Sbloom /* 28923536Sbloom * Two steps are required. 29023536Sbloom */ 29123536Sbloom NODE *x = &resc[1]; 29223536Sbloom 29323536Sbloom *x = *l; 29423536Sbloom if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 29524418Smckusick putstr("movz"); 2969702Slinton else 29724418Smckusick putstr("cvt"); 29823536Sbloom prtype(r); 29923536Sbloom prtype(x); 30024418Smckusick putchar('\t'); 30123536Sbloom adrput(r); 30224418Smckusick putchar(','); 30323536Sbloom adrput(x); 30424418Smckusick putchar('\n'); 30524418Smckusick putchar('\t'); 30623536Sbloom r = x; 3079702Slinton } 30823536Sbloom l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 3099702Slinton } 31023536Sbloom 311*25751Sdonn if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 312*25751Sdonn mixtypes(l, r)) { 313*25751Sdonn int label1, label2; 314*25751Sdonn 315*25751Sdonn label1 = getlab(); 316*25751Sdonn label2 = getlab(); 317*25751Sdonn 318*25751Sdonn putstr("movl\t"); 319*25751Sdonn adrput(r); 320*25751Sdonn putchar(','); 321*25751Sdonn adrput(l); 322*25751Sdonn putstr("\n\tbbsc\t$31,"); 323*25751Sdonn adrput(l); 324*25751Sdonn printf(",L%d\n\tcvtl", label1); 325*25751Sdonn prtype(l); 326*25751Sdonn putchar('\t'); 327*25751Sdonn adrput(l); 328*25751Sdonn putchar(','); 329*25751Sdonn adrput(l); 330*25751Sdonn printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 331*25751Sdonn prtype(l); 332*25751Sdonn putchar('\t'); 333*25751Sdonn adrput(l); 334*25751Sdonn putchar(','); 335*25751Sdonn adrput(l); 336*25751Sdonn putstr("\n\tadd"); 337*25751Sdonn prtype(l); 338*25751Sdonn putstr("2\t$0"); 339*25751Sdonn prtype(l); 340*25751Sdonn putstr("2.147483648e9,"); 341*25751Sdonn adrput(l); 342*25751Sdonn printf("\nL%d:", label2); 343*25751Sdonn 344*25751Sdonn return; 345*25751Sdonn } 346*25751Sdonn 34717208Sralph if (!mixtypes(l,r)) { 34817208Sralph if (tlen(l) == tlen(r)) { 34924418Smckusick putstr("mov"); 35017742Sralph #ifdef FORT 35117742Sralph if (Oflag) 35217742Sralph prtype(l); 35317742Sralph else { 35417742Sralph if (l->in.type == DOUBLE) 35524418Smckusick putchar('q'); 35617742Sralph else if(l->in.type == FLOAT) 35724418Smckusick putchar('l'); 35817742Sralph else 35917742Sralph prtype(l); 36017742Sralph } 36117742Sralph #else 3629702Slinton prtype(l); 36317742Sralph #endif FORT 3649702Slinton goto ops; 3659702Slinton } 3669702Slinton else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 36724418Smckusick putstr("movz"); 3689702Slinton else 36924418Smckusick putstr("cvt"); 3709702Slinton } 3719702Slinton else 37224418Smckusick putstr("cvt"); 3739702Slinton prtype(r); 3749702Slinton prtype(l); 3759702Slinton ops: 37624418Smckusick putchar('\t'); 3779702Slinton adrput(r); 37824418Smckusick putchar(','); 3799702Slinton adrput(l); 3809702Slinton return; 3819702Slinton } 3829702Slinton 383*25751Sdonn case 'G': /* i *= f; asgops with int lhs and float rhs */ 384*25751Sdonn { 385*25751Sdonn register NODE *l, *r, *s; 386*25751Sdonn int rt; 387*25751Sdonn 388*25751Sdonn l = p->in.left; 389*25751Sdonn r = p->in.right; 390*25751Sdonn s = talloc(); 391*25751Sdonn rt = r->in.type; 392*25751Sdonn 393*25751Sdonn s->in.op = SCONV; 394*25751Sdonn s->in.left = l; 395*25751Sdonn s->in.type = rt; 396*25751Sdonn zzzcode(s, 'A'); 397*25751Sdonn putstr("\n\t"); 398*25751Sdonn 399*25751Sdonn hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 400*25751Sdonn putstr("2\t"); 401*25751Sdonn adrput(r); 402*25751Sdonn putchar(','); 403*25751Sdonn adrput(resc); 404*25751Sdonn putstr("\n\t"); 405*25751Sdonn 406*25751Sdonn s->in.op = ASSIGN; 407*25751Sdonn s->in.left = l; 408*25751Sdonn s->in.right = resc; 409*25751Sdonn s->in.type = l->in.type; 410*25751Sdonn zzzcode(s, 'A'); 411*25751Sdonn 412*25751Sdonn s->in.op = FREE; 413*25751Sdonn return; 414*25751Sdonn } 415*25751Sdonn 4169702Slinton case 'B': /* get oreg value in temp register for left shift */ 4179702Slinton { 4189702Slinton register NODE *r; 4199702Slinton if (xdebug) eprint(p, 0, &val, &val); 4209702Slinton r = p->in.right; 4219702Slinton if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 42224418Smckusick putstr("movl"); 4239702Slinton else { 42424418Smckusick putstr("cvt"); 4259702Slinton prtype(r); 42624418Smckusick putchar('l'); 4279702Slinton } 4289702Slinton return; 4299702Slinton } 4309702Slinton 4319702Slinton case 'C': /* num words pushed on arg stack */ 4329702Slinton { 4339702Slinton extern int gc_numbytes; 4349702Slinton extern int xdebug; 4359702Slinton 4369702Slinton if (xdebug) printf("->%d<-",gc_numbytes); 4379702Slinton 4389702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 4399702Slinton return; 4409702Slinton } 4419702Slinton 4429702Slinton case 'D': /* INCR and DECR */ 4439702Slinton zzzcode(p->in.left, 'A'); 44424418Smckusick putchar('\n'); 44524418Smckusick putchar('\t'); 4469702Slinton 4479702Slinton case 'E': /* INCR and DECR, FOREFF */ 4489702Slinton if (p->in.right->tn.lval == 1) 4499702Slinton { 45024418Smckusick putstr( p->in.op == INCR ? "inc" : "dec" ); 4519702Slinton prtype(p->in.left); 45224418Smckusick putchar('\t'); 4539702Slinton adrput(p->in.left); 4549702Slinton return; 4559702Slinton } 45624418Smckusick putstr( p->in.op == INCR ? "add" : "sub" ); 4579702Slinton prtype(p->in.left); 45824418Smckusick putchar('2'); 45924418Smckusick putchar('\t'); 4609702Slinton adrput(p->in.right); 46124418Smckusick putchar(','); 4629702Slinton adrput(p->in.left); 4639702Slinton return; 4649702Slinton 4659702Slinton case 'F': /* register type of right operand */ 4669702Slinton { 4679702Slinton register NODE *n; 4689702Slinton extern int xdebug; 4699702Slinton register int ty; 4709702Slinton 4719702Slinton n = getlr( p, 'R' ); 4729702Slinton ty = n->in.type; 4739702Slinton 4749702Slinton if (xdebug) printf("->%d<-", ty); 4759702Slinton 47624418Smckusick if ( ty==DOUBLE) putchar('d'); 47724418Smckusick else if ( ty==FLOAT ) putchar('f'); 47824418Smckusick else putchar('l'); 4799702Slinton return; 4809702Slinton } 4819702Slinton 4829702Slinton case 'L': /* type of left operand */ 4839702Slinton case 'R': /* type of right operand */ 4849702Slinton { 4859702Slinton register NODE *n; 4869702Slinton extern int xdebug; 4879702Slinton 48816181Sralph n = getlr( p, c ); 4899702Slinton if (xdebug) printf("->%d<-", n->in.type); 4909702Slinton 4919702Slinton prtype(n); 4929702Slinton return; 4939702Slinton } 4949702Slinton 4959702Slinton case 'Z': /* complement mask for bit instr */ 4969702Slinton printf("$%ld", ~p->in.right->tn.lval); 4979702Slinton return; 4989702Slinton 4999702Slinton case 'U': /* 32 - n, for unsigned right shifts */ 5009702Slinton printf("$%d", 32 - p->in.right->tn.lval ); 5019702Slinton return; 5029702Slinton 5039702Slinton case 'T': /* rounded structure length for arguments */ 5049702Slinton { 5059702Slinton int size; 5069702Slinton 5079702Slinton size = p->stn.stsize; 5089702Slinton SETOFF( size, 4); 5099702Slinton printf("$%d", size); 5109702Slinton return; 5119702Slinton } 5129702Slinton 5139702Slinton case 'S': /* structure assignment */ 5149702Slinton { 5159702Slinton register NODE *l, *r; 5169702Slinton register size; 5179702Slinton 5189702Slinton if( p->in.op == STASG ){ 5199702Slinton l = p->in.left; 5209702Slinton r = p->in.right; 5219702Slinton 5229702Slinton } 5239702Slinton else if( p->in.op == STARG ){ /* store an arg into a temporary */ 5249702Slinton r = p->in.left; 5259702Slinton } 5269702Slinton else cerror( "STASG bad" ); 5279702Slinton 5289702Slinton if( r->in.op == ICON ) r->in.op = NAME; 5299702Slinton else if( r->in.op == REG ) r->in.op = OREG; 5309702Slinton else if( r->in.op != OREG ) cerror( "STASG-r" ); 5319702Slinton 5329702Slinton size = p->stn.stsize; 5339702Slinton 5349702Slinton if( size <= 0 || size > 65535 ) 5359702Slinton cerror("structure size <0=0 or >65535"); 5369702Slinton 5379702Slinton switch(size) { 5389702Slinton case 1: 53924418Smckusick putstr(" movb "); 5409702Slinton break; 5419702Slinton case 2: 54224418Smckusick putstr(" movw "); 5439702Slinton break; 5449702Slinton case 4: 54524418Smckusick putstr(" movl "); 5469702Slinton break; 5479702Slinton case 8: 54824418Smckusick putstr(" movq "); 5499702Slinton break; 5509702Slinton default: 5519702Slinton printf(" movc3 $%d,", size); 5529702Slinton break; 5539702Slinton } 5549702Slinton adrput(r); 55516418Sralph if( p->in.op == STASG ){ 55624418Smckusick putchar(','); 55716418Sralph adrput(l); 55824418Smckusick putchar('\n'); 55916418Sralph } 56016418Sralph else 56124418Smckusick putstr(",(sp)\n"); 5629702Slinton 5639702Slinton if( r->in.op == NAME ) r->in.op = ICON; 5649702Slinton else if( r->in.op == OREG ) r->in.op = REG; 5659702Slinton 5669702Slinton } 5679702Slinton break; 5689702Slinton 5699702Slinton default: 5709702Slinton cerror( "illegal zzzcode" ); 5719702Slinton } 5729702Slinton } 5739702Slinton 57423536Sbloom /* 57523536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 57623536Sbloom * can be accomplished in one instruction, return the type of src 57723536Sbloom * that will do the job correctly; otherwise return 0. Note that 57823536Sbloom * a register must always end up having type INT or UNSIGNED. 57923536Sbloom */ 58023536Sbloom int 58123536Sbloom collapsible(dest, src) 58223536Sbloom NODE *dest, *src; 58323536Sbloom { 58423536Sbloom int st = src->in.type; 58523536Sbloom int dt = dest->in.type; 58623536Sbloom int newt = 0; 58723536Sbloom 58823536Sbloom /* 58923536Sbloom * Are there side effects of evaluating src? 59023536Sbloom * If the derived type will not be the same size as src, 59124418Smckusick * we may have to use two steps. 59223536Sbloom */ 59324418Smckusick if (tlen(src) > tlen(dest)) { 59424418Smckusick if (tshape(src, STARREG)) 59524418Smckusick return (0); 59624418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval)) 59724418Smckusick return (0); 59824418Smckusick } 59923536Sbloom 60023536Sbloom /* 60123536Sbloom * Can we get an object of dest's type by punning src? 60223536Sbloom * Praises be to great Cthulhu for little-endian machines... 60323536Sbloom */ 60423536Sbloom if (st == CHAR && dt == USHORT) 60523536Sbloom /* 60623536Sbloom * Special case -- we must sign-extend to 16 bits. 60723536Sbloom */ 60823536Sbloom return (0); 60923536Sbloom 61023536Sbloom if (tlen(src) < tlen(dest)) 61123536Sbloom newt = st; 61223536Sbloom else 61323536Sbloom newt = dt; 61423536Sbloom 61523536Sbloom return (newt); 61623536Sbloom } 61723536Sbloom 61817742Sralph rmove( rt, rs, t ) TWORD t; { 6199702Slinton printf( " %s %s,%s\n", 62017742Sralph #ifdef FORT 62117742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 62217742Sralph #endif 6239702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 6249702Slinton rnames[rs], rnames[rt] ); 6259702Slinton } 6269702Slinton 6279702Slinton struct respref 6289702Slinton respref[] = { 6299702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 6309702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 6319702Slinton INTEMP, INTEMP, 6329702Slinton FORARG, FORARG, 6339702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 6349702Slinton 0, 0 }; 6359702Slinton 6369702Slinton setregs(){ /* set up temporary registers */ 6379702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 6389702Slinton ; 6399702Slinton } 6409702Slinton 6419702Slinton rewfld( p ) NODE *p; { 6429702Slinton return(1); 6439702Slinton } 6449702Slinton 6459702Slinton callreg(p) NODE *p; { 6469702Slinton return( R0 ); 6479702Slinton } 6489702Slinton 6499702Slinton base( p ) register NODE *p; { 6509702Slinton register int o = p->in.op; 6519702Slinton 6529702Slinton if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 6539702Slinton if( o==REG ) return( p->tn.rval ); 6549702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 6559702Slinton return( p->in.left->tn.rval ); 6569702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 6579702Slinton return( p->tn.rval + 0200*1 ); 6589702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 6599702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 6609702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 6619702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 6629702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 6639702Slinton return( -1 ); 6649702Slinton } 6659702Slinton 6669702Slinton offset( p, tyl ) register NODE *p; int tyl; { 6679702Slinton 66824418Smckusick if( tyl==1 && 66924418Smckusick p->in.op==REG && 67024418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) ) 67124418Smckusick return( p->tn.rval ); 67224418Smckusick if( p->in.op==LS && 67324418Smckusick p->in.left->in.op==REG && 67424418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 67524418Smckusick p->in.right->in.op==ICON && 67624418Smckusick p->in.right->in.name[0]=='\0' && 67724418Smckusick (1<<p->in.right->tn.lval)==tyl) 6789702Slinton return( p->in.left->tn.rval ); 67924418Smckusick if( tyl==2 && 68024418Smckusick p->in.op==PLUS && 68124418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 68224418Smckusick p->in.left->in.op==REG && 68324418Smckusick p->in.right->in.op==REG && 68424418Smckusick p->in.left->tn.rval==p->in.right->tn.rval ) 68524418Smckusick return( p->in.left->tn.rval ); 6869702Slinton return( -1 ); 6879702Slinton } 6889702Slinton 6899702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 6909702Slinton register NODE *t; 6919702Slinton register int i; 6929702Slinton NODE *f; 6939702Slinton 6949702Slinton p->in.op = OREG; 6959702Slinton f = p->in.left; /* have to free this subtree later */ 6969702Slinton 6979702Slinton /* init base */ 6989702Slinton switch (q->in.op) { 6999702Slinton case ICON: 7009702Slinton case REG: 7019702Slinton case OREG: 7029702Slinton t = q; 7039702Slinton break; 7049702Slinton 7059702Slinton case MINUS: 7069702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 7079702Slinton case PLUS: 7089702Slinton t = q->in.right; 7099702Slinton break; 7109702Slinton 7119702Slinton case INCR: 7129702Slinton case ASG MINUS: 7139702Slinton t = q->in.left; 7149702Slinton break; 7159702Slinton 7169702Slinton case UNARY MUL: 7179702Slinton t = q->in.left->in.left; 7189702Slinton break; 7199702Slinton 7209702Slinton default: 7219702Slinton cerror("illegal makeor2"); 7229702Slinton } 7239702Slinton 7249702Slinton p->tn.lval = t->tn.lval; 7259702Slinton #ifndef FLEXNAMES 7269702Slinton for(i=0; i<NCHNAM; ++i) 7279702Slinton p->in.name[i] = t->in.name[i]; 7289702Slinton #else 7299702Slinton p->in.name = t->in.name; 7309702Slinton #endif 7319702Slinton 7329702Slinton /* init offset */ 7339702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 7349702Slinton 7359702Slinton tfree(f); 7369702Slinton return; 7379702Slinton } 7389702Slinton 7399702Slinton canaddr( p ) NODE *p; { 7409702Slinton register int o = p->in.op; 7419702Slinton 7429702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 7439702Slinton return(0); 7449702Slinton } 7459702Slinton 7469702Slinton flshape( p ) register NODE *p; { 7479702Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 7489702Slinton (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 7499702Slinton } 7509702Slinton 7519702Slinton shtemp( p ) register NODE *p; { 7529702Slinton if( p->in.op == STARG ) p = p->in.left; 7539702Slinton return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 7549702Slinton } 7559702Slinton 7569702Slinton shumul( p ) register NODE *p; { 7579702Slinton register o; 7589702Slinton extern int xdebug; 7599702Slinton 7609702Slinton if (xdebug) { 7619702Slinton printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 7629702Slinton printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 7639702Slinton } 7649702Slinton 7659702Slinton 7669702Slinton o = p->in.op; 7679702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 7689702Slinton 7699702Slinton if( ( o == INCR || o == ASG MINUS ) && 7709702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 7719702Slinton p->in.right->in.name[0] == '\0' ) 7729702Slinton { 77317659Sralph switch (p->in.type) 7749702Slinton { 7759702Slinton case CHAR|PTR: 7769702Slinton case UCHAR|PTR: 7779702Slinton o = 1; 7789702Slinton break; 7799702Slinton 7809702Slinton case SHORT|PTR: 7819702Slinton case USHORT|PTR: 7829702Slinton o = 2; 7839702Slinton break; 7849702Slinton 7859702Slinton case INT|PTR: 7869702Slinton case UNSIGNED|PTR: 7879702Slinton case LONG|PTR: 7889702Slinton case ULONG|PTR: 7899702Slinton case FLOAT|PTR: 7909702Slinton o = 4; 7919702Slinton break; 7929702Slinton 7939702Slinton case DOUBLE|PTR: 7949702Slinton o = 8; 7959702Slinton break; 7969702Slinton 7979702Slinton default: 79817742Sralph if ( ISPTR(p->in.type) && 79917742Sralph ISPTR(DECREF(p->in.type)) ) { 8009702Slinton o = 4; 8019702Slinton break; 8029702Slinton } 8039702Slinton else return(0); 8049702Slinton } 8059702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 8069702Slinton } 8079702Slinton 8089702Slinton return( 0 ); 8099702Slinton } 8109702Slinton 8119702Slinton adrcon( val ) CONSZ val; { 81224418Smckusick putchar( '$' ); 8139702Slinton printf( CONFMT, val ); 8149702Slinton } 8159702Slinton 8169702Slinton conput( p ) register NODE *p; { 8179702Slinton switch( p->in.op ){ 8189702Slinton 8199702Slinton case ICON: 8209702Slinton acon( p ); 8219702Slinton return; 8229702Slinton 8239702Slinton case REG: 82424418Smckusick putstr( rnames[p->tn.rval] ); 8259702Slinton return; 8269702Slinton 8279702Slinton default: 8289702Slinton cerror( "illegal conput" ); 8299702Slinton } 8309702Slinton } 8319702Slinton 8329702Slinton insput( p ) register NODE *p; { 8339702Slinton cerror( "insput" ); 8349702Slinton } 8359702Slinton 8369702Slinton upput( p ) register NODE *p; { 8379702Slinton cerror( "upput" ); 8389702Slinton } 8399702Slinton 8409702Slinton adrput( p ) register NODE *p; { 8419702Slinton register int r; 8429702Slinton /* output an address, with offsets, from p */ 8439702Slinton 8449702Slinton if( p->in.op == FLD ){ 8459702Slinton p = p->in.left; 8469702Slinton } 8479702Slinton switch( p->in.op ){ 8489702Slinton 8499702Slinton case NAME: 8509702Slinton acon( p ); 8519702Slinton return; 8529702Slinton 8539702Slinton case ICON: 8549702Slinton /* addressable value of the constant */ 85524418Smckusick putchar( '$' ); 8569702Slinton acon( p ); 8579702Slinton return; 8589702Slinton 8599702Slinton case REG: 86024418Smckusick putstr( rnames[p->tn.rval] ); 8619702Slinton return; 8629702Slinton 8639702Slinton case OREG: 8649702Slinton r = p->tn.rval; 8659702Slinton if( R2TEST(r) ){ /* double indexing */ 8669702Slinton register int flags; 8679702Slinton 8689702Slinton flags = R2UPK3(r); 86924418Smckusick if( flags & 1 ) putchar('*'); 87024418Smckusick if( flags & 4 ) putchar('-'); 8719702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 8729702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 87324418Smckusick if( flags & 2 ) putchar('+'); 8749702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 8759702Slinton return; 8769702Slinton } 8779702Slinton if( r == AP ){ /* in the argument region */ 8789702Slinton if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" ); 8799702Slinton printf( CONFMT, p->tn.lval ); 88024418Smckusick putstr( "(ap)" ); 8819702Slinton return; 8829702Slinton } 8839702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 8849702Slinton printf( "(%s)", rnames[p->tn.rval] ); 8859702Slinton return; 8869702Slinton 8879702Slinton case UNARY MUL: 8889702Slinton /* STARNM or STARREG found */ 8899702Slinton if( tshape(p, STARNM) ) { 89024418Smckusick putchar( '*' ); 8919702Slinton adrput( p->in.left); 8929702Slinton } 8939702Slinton else { /* STARREG - really auto inc or dec */ 8949702Slinton register NODE *q; 8959702Slinton 8969702Slinton /* tbl 8979702Slinton p = p->in.left; 8989702Slinton p->in.left->in.op = OREG; 8999702Slinton if( p->in.op == INCR ) { 9009702Slinton adrput( p->in.left ); 90124418Smckusick putchar( '+' ); 9029702Slinton } 9039702Slinton else { 90424418Smckusick putchar( '-' ); 9059702Slinton adrput( p->in.left ); 9069702Slinton } 9079702Slinton tbl */ 90817659Sralph q = p->in.left; 90917742Sralph if( q->in.right->tn.lval != tlen(p) ) 91017742Sralph cerror("adrput: bad auto-increment/decrement"); 91117659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 91217659Sralph rnames[q->in.left->tn.rval], 91317659Sralph (q->in.op==INCR ? "+" : "") ); 9149702Slinton p->in.op = OREG; 91517659Sralph p->tn.rval = q->in.left->tn.rval; 91617659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 9179702Slinton #ifndef FLEXNAMES 9189702Slinton p->in.name[0] = '\0'; 9199702Slinton #else 9209702Slinton p->in.name = ""; 9219702Slinton #endif 9229702Slinton tfree(q); 9239702Slinton } 9249702Slinton return; 9259702Slinton 9269702Slinton default: 9279702Slinton cerror( "illegal address" ); 9289702Slinton return; 9299702Slinton 9309702Slinton } 9319702Slinton 9329702Slinton } 9339702Slinton 9349702Slinton acon( p ) register NODE *p; { /* print out a constant */ 9359702Slinton 9369702Slinton if( p->in.name[0] == '\0' ){ 9379702Slinton printf( CONFMT, p->tn.lval); 9389702Slinton } 9399702Slinton else if( p->tn.lval == 0 ) { 9409702Slinton #ifndef FLEXNAMES 9419702Slinton printf( "%.8s", p->in.name ); 9429702Slinton #else 94324418Smckusick putstr( p->in.name ); 9449702Slinton #endif 9459702Slinton } 9469702Slinton else { 9479702Slinton #ifndef FLEXNAMES 9489702Slinton printf( "%.8s+", p->in.name ); 9499702Slinton #else 9509702Slinton printf( "%s+", p->in.name ); 9519702Slinton #endif 9529702Slinton printf( CONFMT, p->tn.lval ); 9539702Slinton } 9549702Slinton } 9559702Slinton 9569702Slinton /* 9579702Slinton aacon( p ) register NODE *p; { /* print out a constant */ 9589702Slinton /* 9599702Slinton 9609702Slinton if( p->in.name[0] == '\0' ){ 9619702Slinton printf( CONFMT, p->tn.lval); 9629702Slinton return( 0 ); 9639702Slinton } 9649702Slinton else if( p->tn.lval == 0 ) { 9659702Slinton #ifndef FLEXNAMES 9669702Slinton printf( "$%.8s", p->in.name ); 9679702Slinton #else 9689702Slinton printf( "$%s", p->in.name ); 9699702Slinton #endif 9709702Slinton return( 1 ); 9719702Slinton } 9729702Slinton else { 9739702Slinton printf( "$(" ); 9749702Slinton printf( CONFMT, p->tn.lval ); 9759702Slinton printf( "+" ); 9769702Slinton #ifndef FLEXNAMES 9779702Slinton printf( "%.8s)", p->in.name ); 9789702Slinton #else 9799702Slinton printf( "%s)", p->in.name ); 9809702Slinton #endif 9819702Slinton return(1); 9829702Slinton } 9839702Slinton } 9849702Slinton */ 9859702Slinton 9869702Slinton genscall( p, cookie ) register NODE *p; { 9879702Slinton /* structure valued call */ 9889702Slinton return( gencall( p, cookie ) ); 9899702Slinton } 9909702Slinton 9919702Slinton /* tbl */ 9929702Slinton int gc_numbytes; 9939702Slinton /* tbl */ 9949702Slinton 9959702Slinton gencall( p, cookie ) register NODE *p; { 9969702Slinton /* generate the call given by p */ 99716418Sralph register NODE *p1; 9989702Slinton register temp, temp1; 9999702Slinton register m; 10009702Slinton 10019702Slinton if( p->in.right ) temp = argsize( p->in.right ); 10029702Slinton else temp = 0; 10039702Slinton 10049702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 10059702Slinton /* set aside room for structure return */ 10069702Slinton 10079702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 10089702Slinton else temp1 = temp; 10099702Slinton } 10109702Slinton 10119702Slinton if( temp > maxargs ) maxargs = temp; 10129702Slinton SETOFF(temp1,4); 10139702Slinton 10149702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 101516418Sralph genargs( p->in.right ); 10169702Slinton } 10179702Slinton 10189702Slinton p1 = p->in.left; 10199702Slinton if( p1->in.op != ICON ){ 10209702Slinton if( p1->in.op != REG ){ 10219702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 10229702Slinton if( p1->in.op != NAME ){ 10239702Slinton order( p1, INAREG ); 10249702Slinton } 10259702Slinton } 10269702Slinton } 10279702Slinton } 10289702Slinton 10299702Slinton /* 10309702Slinton if( p1->in.op == REG && p->tn.rval == R5 ){ 10319702Slinton cerror( "call register overwrite" ); 10329702Slinton } 10339702Slinton */ 10349702Slinton /* tbl 10359702Slinton setup gc_numbytes so reference to ZC works */ 10369702Slinton 10379702Slinton gc_numbytes = temp&(0x3ff); 10389702Slinton /* tbl */ 10399702Slinton 10409702Slinton p->in.op = UNARY CALL; 10419702Slinton m = match( p, INTAREG|INTBREG ); 10429702Slinton 10439702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 10449702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 10459702Slinton if (temp >= 1024) 10469702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 10479702Slinton 10489702Slinton /* tbl 10499702Slinton switch( temp ) { 10509702Slinton case 0: 10519702Slinton break; 10529702Slinton case 2: 10539702Slinton printf( " tst (sp)+\n" ); 10549702Slinton break; 10559702Slinton case 4: 10569702Slinton printf( " cmp (sp)+,(sp)+\n" ); 10579702Slinton break; 10589702Slinton default: 10599702Slinton printf( " add $%d,sp\n", temp); 10609702Slinton } 10619702Slinton tbl */ 10629702Slinton return(m != MDONE); 10639702Slinton } 10649702Slinton 10659702Slinton /* tbl */ 10669702Slinton char * 10679702Slinton ccbranches[] = { 10689702Slinton " jeql L%d\n", 10699702Slinton " jneq L%d\n", 10709702Slinton " jleq L%d\n", 10719702Slinton " jlss L%d\n", 10729702Slinton " jgeq L%d\n", 10739702Slinton " jgtr L%d\n", 10749702Slinton " jlequ L%d\n", 10759702Slinton " jlssu L%d\n", 10769702Slinton " jgequ L%d\n", 10779702Slinton " jgtru L%d\n", 10789702Slinton }; 10799702Slinton /* tbl */ 10809702Slinton 10819702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 10829702Slinton 10839702Slinton /* tbl */ 10849702Slinton if( o == 0 ) printf( " jbr L%d\n", lab ); 10859702Slinton /* tbl */ 10869702Slinton else { 10879702Slinton if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 10889702Slinton printf( ccbranches[o-EQ], lab ); 10899702Slinton } 10909702Slinton } 10919702Slinton 10929702Slinton nextcook( p, cookie ) NODE *p; { 10939702Slinton /* we have failed to match p with cookie; try another */ 10949702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 10959702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 10969702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 10979702Slinton return( FORREW ); 10989702Slinton } 10999702Slinton 11009702Slinton lastchance( p, cook ) NODE *p; { 11019702Slinton /* forget it! */ 11029702Slinton return(0); 11039702Slinton } 11049702Slinton 11059702Slinton optim2( p ) register NODE *p; { 11069702Slinton /* do local tree transformations and optimizations */ 11079702Slinton 110816181Sralph register NODE *l, *r; 110916181Sralph int m, ml; 11109702Slinton 11119702Slinton switch( p->in.op ) { 11129702Slinton 11139702Slinton case AND: 111419933Smckusick /* commute L and R to eliminate complements and constants */ 111516181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 111616181Sralph l->in.op == COMPL ) { 11179702Slinton p->in.left = p->in.right; 111816181Sralph p->in.right = l; 11199702Slinton } 11209702Slinton case ASG AND: 11219702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 11229702Slinton r = p->in.right; 112319933Smckusick if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 11249702Slinton r->tn.lval = ~r->tn.lval; 11259702Slinton } 11269702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 11279702Slinton r->in.op = FREE; 11289702Slinton p->in.right = r->in.left; 11299702Slinton } 11309702Slinton else { /* insert complement node */ 113116181Sralph p->in.right = l = talloc(); 113216181Sralph l->in.op = COMPL; 113316181Sralph l->in.rall = NOPREF; 113416181Sralph l->in.type = r->in.type; 113516181Sralph l->in.left = r; 113616181Sralph l->in.right = NULL; 11379702Slinton } 11389702Slinton break; 11399702Slinton 114016181Sralph case SCONV: 114119933Smckusick l = p->in.left; 114217742Sralph #if defined(FORT) || defined(SPRECC) 114316573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 114419933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 114519933Smckusick return; 114616573Sralph #else 114719933Smckusick if( mixtypes(p, l) ) return; 114816573Sralph #endif 1149*25751Sdonn if( l->in.op == PCONV ) 1150*25751Sdonn return; 1151*25751Sdonn 115219933Smckusick /* Only trust it to get it right if the size is the same */ 115319933Smckusick if( tlen(p) != tlen(l) ) 115419933Smckusick return; 115516181Sralph 115616181Sralph /* clobber conversion */ 115719933Smckusick if( l->in.op != FLD ) 115816181Sralph l->in.type = p->in.type; 115916181Sralph ncopy( p, l ); 116016181Sralph l->in.op = FREE; 116119933Smckusick 116216181Sralph break; 116316181Sralph 116424418Smckusick case ASSIGN: 116524418Smckusick /* 116624418Smckusick * Conversions are equivalent to assignments; 116724418Smckusick * when the two operations are combined, 116824418Smckusick * we can sometimes zap the conversion. 116924418Smckusick */ 117024418Smckusick r = p->in.right; 117124418Smckusick l = p->in.left; 117224418Smckusick if ( r->in.op == SCONV && 117324418Smckusick !mixtypes(l, r) && 117424418Smckusick tlen(l) == tlen(r) ) { 117524418Smckusick p->in.right = r->in.left; 117624418Smckusick r->in.op = FREE; 117724418Smckusick } 117824418Smckusick break; 117924418Smckusick 11809702Slinton } 11819702Slinton } 11829702Slinton 118317742Sralph NODE * addroreg(l) NODE *l; 11849702Slinton /* OREG was built in clocal() 11859702Slinton * for an auto or formal parameter 11869702Slinton * now its address is being taken 11879702Slinton * local code must unwind it 11889702Slinton * back to PLUS/MINUS REG ICON 11899702Slinton * according to local conventions 11909702Slinton */ 11919702Slinton { 11929702Slinton cerror("address of OREG taken"); 119317742Sralph /*NOTREACHED*/ 11949702Slinton } 11959702Slinton 11969702Slinton 11979702Slinton 11989702Slinton # ifndef ONEPASS 11999702Slinton main( argc, argv ) char *argv[]; { 12009702Slinton return( mainp2( argc, argv ) ); 12019702Slinton } 12029702Slinton # endif 12039702Slinton 12049702Slinton 12059702Slinton /* added by jwf */ 12069702Slinton struct functbl { 12079702Slinton int fop; 12089702Slinton TWORD ftype; 12099702Slinton char *func; 12109702Slinton } opfunc[] = { 12119702Slinton DIV, TANY, "udiv", 12129702Slinton MOD, TANY, "urem", 121317715Sralph ASG DIV, TANY, "audiv", 121417715Sralph ASG MOD, TANY, "aurem", 12159702Slinton 0, 0, 0 }; 12169702Slinton 12179702Slinton hardops(p) register NODE *p; { 12189702Slinton /* change hard to do operators into function calls. */ 12199702Slinton register NODE *q; 12209702Slinton register struct functbl *f; 12219702Slinton register o; 122217742Sralph NODE *old,*temp; 12239702Slinton 12249702Slinton o = p->in.op; 122517742Sralph if( ! (optype(o)==BITYPE && 122617742Sralph (ISUNSIGNED(p->in.left->in.type) || 122717742Sralph ISUNSIGNED(p->in.right->in.type))) ) 122817742Sralph return; 12299702Slinton 12309702Slinton for( f=opfunc; f->fop; f++ ) { 12319702Slinton if( o==f->fop ) goto convert; 12329702Slinton } 12339702Slinton return; 12349702Slinton 12359702Slinton convert: 12369702Slinton if( asgop( o ) ) { 123717742Sralph old = NIL; 123817715Sralph switch( p->in.left->in.op ){ 123917742Sralph case FLD: 124017742Sralph q = p->in.left->in.left; 124117742Sralph /* 124217742Sralph * rewrite (lval.fld /= rval); as 124317742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 124417742Sralph * else the compiler will evaluate lval twice. 124517742Sralph */ 124617742Sralph if( q->in.op == UNARY MUL ){ 124717742Sralph /* first allocate a temp storage */ 124817742Sralph temp = talloc(); 124917742Sralph temp->in.op = OREG; 125017742Sralph temp->tn.rval = TMPREG; 125117742Sralph temp->tn.lval = BITOOR(freetemp(1)); 125217742Sralph temp->in.type = INCREF(p->in.type); 125317742Sralph #ifdef FLEXNAMES 125417742Sralph temp->in.name = ""; 125517742Sralph #else 125617742Sralph temp->in.name[0] = '\0'; 125717742Sralph #endif 125817742Sralph old = q->in.left; 125917742Sralph q->in.left = temp; 126017742Sralph } 126117742Sralph /* fall thru ... */ 126217742Sralph 126317715Sralph case REG: 126417715Sralph case NAME: 126517715Sralph case OREG: 126617715Sralph /* change ASG OP to a simple OP */ 126717715Sralph q = talloc(); 126817715Sralph q->in.op = NOASG p->in.op; 126917715Sralph q->in.rall = NOPREF; 127017715Sralph q->in.type = p->in.type; 127117715Sralph q->in.left = tcopy(p->in.left); 127217715Sralph q->in.right = p->in.right; 127317715Sralph p->in.op = ASSIGN; 127417715Sralph p->in.right = q; 127517715Sralph p = q; 127617715Sralph f -= 2; /* Note: this depends on the table order */ 127717742Sralph /* on the right side only - replace *temp with 127817742Sralph *(temp = &lval), build the assignment node */ 127917742Sralph if( old ){ 128017742Sralph temp = q->in.left->in.left; /* the "*" node */ 128117742Sralph q = talloc(); 128217742Sralph q->in.op = ASSIGN; 128317742Sralph q->in.left = temp->in.left; 128417742Sralph q->in.right = old; 128517742Sralph q->in.type = old->in.type; 128617742Sralph #ifdef FLEXNAMES 128717742Sralph q->in.name = ""; 128817742Sralph #else 128917742Sralph q->in.name[0] = '\0'; 129017742Sralph #endif 129117742Sralph temp->in.left = q; 129217742Sralph } 129317715Sralph break; 12949702Slinton 129517715Sralph case UNARY MUL: 129617715Sralph /* avoid doing side effects twice */ 129717715Sralph q = p->in.left; 129817715Sralph p->in.left = q->in.left; 129917715Sralph q->in.op = FREE; 130017715Sralph break; 130117715Sralph 130217715Sralph default: 130317715Sralph cerror( "hardops: can't compute & LHS" ); 130417715Sralph } 130517742Sralph } 130617715Sralph 13079702Slinton /* build comma op for args to function */ 13089702Slinton q = talloc(); 13099702Slinton q->in.op = CM; 13109702Slinton q->in.rall = NOPREF; 13119702Slinton q->in.type = INT; 13129702Slinton q->in.left = p->in.left; 13139702Slinton q->in.right = p->in.right; 13149702Slinton p->in.op = CALL; 13159702Slinton p->in.right = q; 13169702Slinton 13179702Slinton /* put function name in left node of call */ 13189702Slinton p->in.left = q = talloc(); 13199702Slinton q->in.op = ICON; 13209702Slinton q->in.rall = NOPREF; 13219702Slinton q->in.type = INCREF( FTN + p->in.type ); 13229702Slinton #ifndef FLEXNAMES 13239702Slinton strcpy( q->in.name, f->func ); 13249702Slinton #else 13259702Slinton q->in.name = f->func; 13269702Slinton #endif 13279702Slinton q->tn.lval = 0; 13289702Slinton q->tn.rval = 0; 13299702Slinton 13309702Slinton } 13319702Slinton 133217742Sralph zappost(p) NODE *p; { 133317742Sralph /* look for ++ and -- operators and remove them */ 133417742Sralph 133517742Sralph register o, ty; 133617742Sralph register NODE *q; 133717742Sralph o = p->in.op; 133817742Sralph ty = optype( o ); 133917742Sralph 134017742Sralph switch( o ){ 134117742Sralph 134217742Sralph case INCR: 134317742Sralph case DECR: 134417742Sralph q = p->in.left; 134517742Sralph p->in.right->in.op = FREE; /* zap constant */ 134617742Sralph ncopy( p, q ); 134717742Sralph q->in.op = FREE; 134817742Sralph return; 134917742Sralph 135017742Sralph } 135117742Sralph 135217742Sralph if( ty == BITYPE ) zappost( p->in.right ); 135317742Sralph if( ty != LTYPE ) zappost( p->in.left ); 135417742Sralph } 135517742Sralph 135617742Sralph fixpre(p) NODE *p; { 135717742Sralph 135817742Sralph register o, ty; 135917742Sralph o = p->in.op; 136017742Sralph ty = optype( o ); 136117742Sralph 136217742Sralph switch( o ){ 136317742Sralph 136417742Sralph case ASG PLUS: 136517742Sralph p->in.op = PLUS; 136617742Sralph break; 136717742Sralph case ASG MINUS: 136817742Sralph p->in.op = MINUS; 136917742Sralph break; 137017742Sralph } 137117742Sralph 137217742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 137317742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 137417742Sralph } 137517742Sralph 137624418Smckusick strip(p) register NODE *p; { 137724418Smckusick NODE *q; 137824418Smckusick 137924418Smckusick /* strip nodes off the top when no side effects occur */ 138024418Smckusick for( ; ; ) { 138124418Smckusick switch( p->in.op ) { 138224418Smckusick case SCONV: /* remove lint tidbits */ 138324418Smckusick q = p->in.left; 138424418Smckusick ncopy( p, q ); 138524418Smckusick q->in.op = FREE; 138624418Smckusick break; 138724418Smckusick /* could probably add a few more here */ 138824418Smckusick default: 138924418Smckusick return; 139024418Smckusick } 139124418Smckusick } 139224418Smckusick } 139324418Smckusick 13949702Slinton myreader(p) register NODE *p; { 139524418Smckusick strip( p ); /* strip off operations with no side effects */ 139617742Sralph canon( p ); /* expands r-vals for fields */ 13979702Slinton walkf( p, hardops ); /* convert ops to function calls */ 13989702Slinton walkf( p, optim2 ); 13999702Slinton /* jwf toff = 0; /* stack offset swindle */ 14009702Slinton } 1401