125828Ssam #ifndef lint 2*30360Ssam static char sccsid[] = "@(#)local2.c 1.8 (Berkeley) 01/09/87"; 325828Ssam #endif 425828Ssam 526076Ssam # include "pass2.h" 626076Ssam # include <ctype.h> 726162Ssam 826162Ssam # define putstr(s) fputs((s), stdout) 929672Ssam # define ISCHAR(p) (p->in.type == UCHAR || p->in.type == CHAR) 1026162Ssam 1125828Ssam # ifdef FORT 1225828Ssam int ftlab1, ftlab2; 1325828Ssam # endif 1425828Ssam /* a lot of the machine dependent parts of the second pass */ 1525828Ssam 1625828Ssam # define BITMASK(n) ((1L<<n)-1) 1725828Ssam 1825828Ssam # ifndef ONEPASS 1925828Ssam where(c){ 2025828Ssam fprintf( stderr, "%s, line %d: ", filename, lineno ); 2125828Ssam } 2225828Ssam # endif 2325828Ssam 2425828Ssam lineid( l, fn ) char *fn; { 2525828Ssam /* identify line l and file fn */ 2625828Ssam printf( "# line %d, file %s\n", l, fn ); 2725828Ssam } 2825828Ssam 2925828Ssam int ent_mask; 3025828Ssam 3125828Ssam eobl2(){ 3225828Ssam register OFFSZ spoff; /* offset from stack pointer */ 3325828Ssam #ifndef FORT 3425828Ssam extern int ftlab1, ftlab2; 3525828Ssam #endif 3625828Ssam 3725828Ssam spoff = maxoff; 3825828Ssam spoff /= SZCHAR; 3925828Ssam SETOFF(spoff,4); 4025828Ssam #ifdef FORT 4125828Ssam #ifndef FLEXNAMES 4225828Ssam printf( " .set .F%d,%d\n", ftnno, spoff ); 4325828Ssam #else 4425828Ssam /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 4525828Ssam printf( " .set LF%d,%d\n", ftnno, spoff ); 4625828Ssam #endif 4725828Ssam printf( " .set LWM%d,0x%x\n", ftnno, ent_mask&0x1ffc|0x1000); 4825828Ssam #else 4925828Ssam printf( " .set L%d,0x%x\n", ftnno, ent_mask&0x1ffc); 5025828Ssam printf( "L%d:\n", ftlab1); 5125828Ssam if( maxoff > AUTOINIT ) 5225828Ssam printf( " subl3 $%d,fp,sp\n", spoff); 5325828Ssam printf( " jbr L%d\n", ftlab2); 5425828Ssam #endif 5525828Ssam ent_mask = 0; 5625828Ssam maxargs = -1; 5725828Ssam } 5825828Ssam 5925828Ssam struct hoptab { int opmask; char * opstring; } ioptab[] = { 6025828Ssam 6125828Ssam PLUS, "add", 6225828Ssam MINUS, "sub", 6325828Ssam MUL, "mul", 6425828Ssam DIV, "div", 6525828Ssam MOD, "div", 6625828Ssam OR, "or", 6725828Ssam ER, "xor", 6825828Ssam AND, "and", 6925828Ssam -1, "" }; 7025828Ssam 7125828Ssam hopcode( f, o ){ 7225828Ssam /* output the appropriate string from the above table */ 7325828Ssam 7425828Ssam register struct hoptab *q; 7525828Ssam 7625828Ssam if(asgop(o)) 7725828Ssam o = NOASG o; 7825828Ssam for( q = ioptab; q->opmask>=0; ++q ){ 7925828Ssam if( q->opmask == o ){ 8025828Ssam if(f == 'E') 8125828Ssam printf( "e%s", q->opstring); 8225828Ssam else 8325828Ssam printf( "%s%c", q->opstring, tolower(f)); 8425828Ssam return; 8525828Ssam } 8625828Ssam } 8725828Ssam cerror( "no hoptab for %s", opst[o] ); 8825828Ssam } 8925828Ssam 9025828Ssam char * 9125828Ssam rnames[] = { /* keyed to register number tokens */ 9225828Ssam 9325828Ssam "r0", "r1", 9425828Ssam "r2", "r3", "r4", "r5", 9525828Ssam "r6", "r7", "r8", "r9", "r10", "r11", 9625828Ssam "r12", "fp", "sp", "pc", 9725828Ssam }; 9825828Ssam 9925828Ssam /* output register name and update entry mask */ 10025828Ssam char * 10125828Ssam rname(r) 10225828Ssam register int r; 10325828Ssam { 10425828Ssam 10525828Ssam ent_mask |= 1<<r; 10625828Ssam return(rnames[r]); 10725828Ssam } 10825828Ssam 10925828Ssam int rstatus[] = { 11025828Ssam SAREG|STAREG, SAREG|STAREG, 11125828Ssam SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 11225828Ssam SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 11325828Ssam SAREG, SAREG, SAREG, SAREG, 11425828Ssam }; 11525828Ssam 11625828Ssam tlen(p) NODE *p; 11725828Ssam { 11825828Ssam switch(p->in.type) { 11925828Ssam case CHAR: 12025828Ssam case UCHAR: 12125828Ssam return(1); 12225828Ssam 12325828Ssam case SHORT: 12425828Ssam case USHORT: 12525828Ssam return(2); 12625828Ssam 12725828Ssam case DOUBLE: 12825828Ssam return(8); 12925828Ssam 13025828Ssam default: 13125828Ssam return(4); 13225828Ssam } 13325828Ssam } 13425828Ssam 135*30360Ssam anyfloat(p, q) 136*30360Ssam NODE *p, *q; 137*30360Ssam { 138*30360Ssam register TWORD tp, tq; 139*30360Ssam 140*30360Ssam tp = p->in.type; 141*30360Ssam tq = q->in.type; 142*30360Ssam return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE); 143*30360Ssam } 144*30360Ssam 14525828Ssam prtype(n) NODE *n; 14625828Ssam { 14725828Ssam switch (n->in.type) 14825828Ssam { 14925828Ssam 15025828Ssam case DOUBLE: 15126162Ssam putchar('d'); 15225828Ssam return; 15325828Ssam 15425828Ssam case FLOAT: 15526162Ssam putchar('f'); 15625828Ssam return; 15725828Ssam 15825828Ssam case INT: 15925828Ssam case UNSIGNED: 16026162Ssam putchar('l'); 16125828Ssam return; 16225828Ssam 16325828Ssam case SHORT: 16425828Ssam case USHORT: 16526162Ssam putchar('w'); 16625828Ssam return; 16725828Ssam 16825828Ssam case CHAR: 16925828Ssam case UCHAR: 17026162Ssam putchar('b'); 17125828Ssam return; 17225828Ssam 17325828Ssam default: 17425828Ssam if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 17525828Ssam else { 17626162Ssam putchar('l'); 17725828Ssam return; 17825828Ssam } 17925828Ssam } 18025828Ssam } 18125828Ssam 18225828Ssam zzzcode( p, c ) register NODE *p; { 18325828Ssam register int m; 18425828Ssam int val; 18525828Ssam switch( c ){ 18625828Ssam 18725828Ssam case 'N': /* logical ops, turned into 0-1 */ 18825828Ssam /* use register given by register 1 */ 18925828Ssam cbgen( 0, m=getlab(), 'I' ); 19025828Ssam deflab( p->bn.label ); 19125828Ssam printf( " clrl %s\n", rname(getlr( p, '1' )->tn.rval) ); 19225828Ssam deflab( m ); 19325828Ssam return; 19425828Ssam 19525828Ssam case 'P': 19625828Ssam cbgen( p->in.op, p->bn.label, c ); 19725828Ssam return; 19825828Ssam 19925828Ssam case 'A': /* assignment and load (integer only) */ 20025828Ssam { 20125828Ssam register NODE *l, *r; 20225828Ssam 20325828Ssam if (xdebug) eprint(p, 0, &val, &val); 20425828Ssam r = getlr(p, 'R'); 20525828Ssam if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL) { 20625828Ssam l = resc; 20725828Ssam l->in.type = INT; 20825828Ssam } else 20925828Ssam l = getlr(p, 'L'); 21025828Ssam if(r->in.type==FLOAT || r->in.type==DOUBLE 21125828Ssam || l->in.type==FLOAT || l->in.type==DOUBLE) 21225828Ssam cerror("float in ZA"); 21325828Ssam if (r->in.op == ICON) 21425828Ssam if(r->in.name[0] == '\0') { 21525828Ssam if (r->tn.lval == 0) { 21626162Ssam putstr("clr"); 21725828Ssam prtype(l); 21826162Ssam putchar('\t'); 21925828Ssam adrput(l); 22025828Ssam return; 22125828Ssam } 22225828Ssam if (r->tn.lval < 0 && r->tn.lval >= -63) { 22326162Ssam putstr("mneg"); 22425828Ssam prtype(l); 22525828Ssam r->tn.lval = -r->tn.lval; 22625828Ssam goto ops; 22725828Ssam } 22825828Ssam #ifdef MOVAFASTER 22925828Ssam } else { 23026162Ssam putstr("movab\t"); 23125828Ssam acon(r); 23226162Ssam putchar(','); 23325828Ssam adrput(l); 23425828Ssam return; 23525828Ssam #endif MOVAFASTER 23625828Ssam } 23725828Ssam 23825828Ssam if (l->in.op == REG) { 23925828Ssam if( tlen(l) < tlen(r) ) { 24026162Ssam putstr(!ISUNSIGNED(l->in.type)? 24126162Ssam "cvt": "movz"); 24225828Ssam prtype(l); 24326162Ssam putchar('l'); 24425828Ssam goto ops; 24525828Ssam } else 24625828Ssam l->in.type = INT; 24725828Ssam } 24825828Ssam if (tlen(l) == tlen(r)) { 24926162Ssam putstr("mov"); 25025828Ssam prtype(l); 25125828Ssam goto ops; 25225828Ssam } else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 25326162Ssam putstr("movz"); 25425828Ssam else 25526162Ssam putstr("cvt"); 25625828Ssam prtype(r); 25725828Ssam prtype(l); 25825828Ssam ops: 25926162Ssam putchar('\t'); 26025828Ssam adrput(r); 26126162Ssam putchar(','); 26225828Ssam adrput(l); 26325828Ssam return; 26425828Ssam } 26525828Ssam 26625828Ssam case 'B': /* get oreg value in temp register for shift */ 26725828Ssam { 26825828Ssam register NODE *r; 26925828Ssam if (xdebug) eprint(p, 0, &val, &val); 27025828Ssam r = p->in.right; 27125828Ssam if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 27226162Ssam putstr("movl"); 27325828Ssam else { 27426162Ssam putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); 27525828Ssam prtype(r); 27626162Ssam putchar('l'); 27725828Ssam } 27825828Ssam return; 27925828Ssam } 28025828Ssam 28125828Ssam case 'C': /* num bytes pushed on arg stack */ 28225828Ssam { 28325828Ssam extern int gc_numbytes; 28425828Ssam extern int xdebug; 28525828Ssam 28625828Ssam if (xdebug) printf("->%d<-",gc_numbytes); 28725828Ssam 28825828Ssam printf("call%c $%d", 28925828Ssam (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s', 29025828Ssam gc_numbytes+4); 29125828Ssam /* dont change to double (here's the only place to catch it) */ 29225828Ssam if(p->in.type == FLOAT) 29325828Ssam rtyflg = 1; 29425828Ssam return; 29525828Ssam } 29625828Ssam 29725828Ssam case 'D': /* INCR and DECR */ 29825828Ssam zzzcode(p->in.left, 'A'); 29926162Ssam putstr("\n "); 30025828Ssam 30125828Ssam case 'E': /* INCR and DECR, FOREFF */ 30225828Ssam if (p->in.right->tn.lval == 1) 30325828Ssam { 30426162Ssam putstr(p->in.op == INCR ? "inc" : "dec"); 30525828Ssam prtype(p->in.left); 30626162Ssam putchar('\t'); 30725828Ssam adrput(p->in.left); 30825828Ssam return; 30925828Ssam } 31026162Ssam putstr(p->in.op == INCR ? "add" : "sub"); 31125828Ssam prtype(p->in.left); 31226162Ssam putstr("2 "); 31325828Ssam adrput(p->in.right); 31426162Ssam putchar(','); 31525828Ssam adrput(p->in.left); 31625828Ssam return; 31725828Ssam 31825828Ssam case 'F': /* masked constant for fields */ 31925947Ssam printf(ACONFMT, (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf); 32025828Ssam return; 32125828Ssam 32225828Ssam case 'H': /* opcode for shift */ 32325828Ssam if(p->in.op == LS || p->in.op == ASG LS) 32426162Ssam putstr("shll"); 32525828Ssam else if(ISUNSIGNED(p->in.left->in.type)) 32626162Ssam putstr("shrl"); 32725828Ssam else 32826162Ssam putstr("shar"); 32925828Ssam return; 33025828Ssam 33125828Ssam case 'L': /* type of left operand */ 33225828Ssam case 'R': /* type of right operand */ 33325828Ssam { 33425828Ssam register NODE *n; 33525828Ssam extern int xdebug; 33625828Ssam 33725828Ssam n = getlr ( p, c); 33825828Ssam if (xdebug) printf("->%d<-", n->in.type); 33925828Ssam 34025828Ssam prtype(n); 34125828Ssam return; 34225828Ssam } 34325828Ssam 344*30360Ssam case 'M': { /* initiate ediv for mod and unsigned div */ 34525828Ssam register char *r; 34625828Ssam m = getlr(p, '1')->tn.rval; 34725828Ssam r = rname(m); 34825828Ssam printf("\tclrl\t%s\n\tmovl\t", r); 34925828Ssam adrput(p->in.left); 35025828Ssam printf(",%s\n", rname(m+1)); 35125828Ssam if(!ISUNSIGNED(p->in.type)) { /* should be MOD */ 35225828Ssam m = getlab(); 35325828Ssam printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r); 35425828Ssam deflab(m); 35525828Ssam } 35625828Ssam return; 357*30360Ssam } 35825828Ssam 359*30360Ssam case 'T': { /* rounded structure length for arguments */ 360*30360Ssam int size = p->stn.stsize; 36125828Ssam SETOFF( size, 4); 36225828Ssam printf("movab -%d(sp),sp", size); 36325828Ssam return; 364*30360Ssam } 36525828Ssam 36625828Ssam case 'S': /* structure assignment */ 36725977Ssam stasg(p); 36825977Ssam break; 36925828Ssam 37029672Ssam case 'X': /* multiplication for short and char */ 37129672Ssam if (ISUNSIGNED(p->in.left->in.type)) 37229672Ssam printf("\tmovz"); 37329672Ssam else 37429672Ssam printf("\tcvt"); 37529672Ssam zzzcode(p, 'L'); 37629672Ssam printf("l\t"); 37729672Ssam adrput(p->in.left); 37829672Ssam printf(","); 37929672Ssam adrput(&resc[0]); 38029672Ssam printf("\n"); 38129672Ssam if (ISUNSIGNED(p->in.right->in.type)) 38229672Ssam printf("\tmovz"); 38329672Ssam else 38429672Ssam printf("\tcvt"); 38529672Ssam zzzcode(p, 'R'); 38629672Ssam printf("l\t"); 38729672Ssam adrput(p->in.right); 38829672Ssam printf(","); 38929672Ssam adrput(&resc[1]); 39029672Ssam printf("\n"); 39129672Ssam return; 39229672Ssam 393*30360Ssam case 'U': /* SCONV */ 394*30360Ssam case 'V': /* SCONV with FORCC */ 395*30360Ssam sconv(p, c == 'V'); 396*30360Ssam break; 397*30360Ssam 398*30360Ssam case 'Z': 399*30360Ssam p = p->in.right; 400*30360Ssam switch (p->in.type) { 401*30360Ssam case SHORT: { 402*30360Ssam short w = p->tn.lval; 403*30360Ssam p->tn.lval = w; 404*30360Ssam break; 405*30360Ssam } 406*30360Ssam case CHAR: { 407*30360Ssam char c = p->tn.lval; 408*30360Ssam p->tn.lval = c; 409*30360Ssam break; 410*30360Ssam } 411*30360Ssam } 412*30360Ssam printf("$%d", p->tn.lval); 413*30360Ssam break; 414*30360Ssam 41525977Ssam default: 41625977Ssam cerror( "illegal zzzcode" ); 41725977Ssam } 418*30360Ssam } 41925828Ssam 42025977Ssam #define MOVB(dst, src, off) { \ 42126162Ssam putstr("\tmovb\t"); upput(src, off); putchar(','); \ 42225977Ssam upput(dst, off); putchar('\n'); \ 42325977Ssam } 42425977Ssam #define MOVW(dst, src, off) { \ 42526162Ssam putstr("\tmovw\t"); upput(src, off); putchar(','); \ 42625977Ssam upput(dst, off); putchar('\n'); \ 42725977Ssam } 42825977Ssam #define MOVL(dst, src, off) { \ 42926162Ssam putstr("\tmovl\t"); upput(src, off); putchar(','); \ 43025977Ssam upput(dst, off); putchar('\n'); \ 43125977Ssam } 43225977Ssam /* 43325977Ssam * Generate code for a structure assignment. 43425977Ssam */ 43525977Ssam stasg(p) 43625977Ssam register NODE *p; 43725977Ssam { 43825977Ssam register NODE *l, *r; 43925977Ssam register int size; 44025828Ssam 44125977Ssam switch (p->in.op) { 44225977Ssam case STASG: /* regular assignment */ 44325977Ssam l = p->in.left; 44425977Ssam r = p->in.right; 44525977Ssam break; 44625977Ssam case STARG: /* place arg on the stack */ 44725977Ssam l = getlr(p, '3'); 44825977Ssam r = p->in.left; 44925977Ssam break; 45025977Ssam default: 45125977Ssam cerror("STASG bad"); 45225977Ssam /*NOTREACHED*/ 45325977Ssam } 45425977Ssam /* 45525977Ssam * Pun source for use in code generation. 45625977Ssam */ 45725977Ssam switch (r->in.op) { 45825977Ssam case ICON: 45925977Ssam r->in.op = NAME; 46025977Ssam break; 46125977Ssam case REG: 46225977Ssam r->in.op = OREG; 46325977Ssam break; 46425977Ssam default: 46525977Ssam cerror( "STASG-r" ); 46625977Ssam /*NOTREACHED*/ 46725977Ssam } 46825977Ssam size = p->stn.stsize; 46925977Ssam if (size <= 0 || size > 65535) 47025977Ssam cerror("structure size out of range"); 47125977Ssam /* 47225977Ssam * Generate optimized code based on structure size 47325977Ssam * and alignment properties.... 47425977Ssam */ 47525977Ssam switch (size) { 47625828Ssam 47725977Ssam case 1: 47826162Ssam putstr("\tmovb\t"); 47925977Ssam optimized: 48025977Ssam adrput(r); 48126162Ssam putchar(','); 48225977Ssam adrput(l); 48326162Ssam putchar('\n'); 48425977Ssam break; 48525828Ssam 48625977Ssam case 2: 48725977Ssam if (p->stn.stalign != 2) { 48825977Ssam MOVB(l, r, SZCHAR); 48926162Ssam putstr("\tmovb\t"); 49025977Ssam } else 49126162Ssam putstr("\tmovw\t"); 49225977Ssam goto optimized; 49325977Ssam 49425977Ssam case 4: 49525977Ssam if (p->stn.stalign != 4) { 49625977Ssam if (p->stn.stalign != 2) { 49725977Ssam MOVB(l, r, 3*SZCHAR); 49825977Ssam MOVB(l, r, 2*SZCHAR); 49925977Ssam MOVB(l, r, 1*SZCHAR); 50026162Ssam putstr("\tmovb\t"); 50125947Ssam } else { 50225977Ssam MOVW(l, r, SZSHORT); 50326162Ssam putstr("\tmovw\t"); 50425828Ssam } 50525977Ssam } else 50626162Ssam putstr("\tmovl\t"); 50725977Ssam goto optimized; 50825828Ssam 50925977Ssam case 6: 51025977Ssam if (p->stn.stalign != 2) 51125977Ssam goto movblk; 51225977Ssam MOVW(l, r, 2*SZSHORT); 51325977Ssam MOVW(l, r, 1*SZSHORT); 51426162Ssam putstr("\tmovw\t"); 51525977Ssam goto optimized; 51625977Ssam 51725977Ssam case 8: 51825977Ssam if (p->stn.stalign == 4) { 51925977Ssam MOVL(l, r, SZLONG); 52026162Ssam putstr("\tmovl\t"); 52125977Ssam goto optimized; 52225977Ssam } 52325977Ssam /* fall thru...*/ 52425977Ssam 52525977Ssam default: 52625977Ssam movblk: 52725977Ssam /* 52825977Ssam * Can we ever get a register conflict with R1 here? 52925977Ssam */ 53026162Ssam putstr("\tmovab\t"); 53125977Ssam adrput(l); 53226162Ssam putstr(",r1\n\tmovab\t"); 53325977Ssam adrput(r); 53425977Ssam printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size); 53525977Ssam rname(R2); 53625828Ssam break; 53725977Ssam } 53825977Ssam /* 53925977Ssam * Reverse above pun for reclaim. 54025977Ssam */ 54125977Ssam if (r->in.op == NAME) 54225977Ssam r->in.op = ICON; 54325977Ssam else if (r->in.op == OREG) 54425977Ssam r->in.op = REG; 54525977Ssam } 54625828Ssam 54725977Ssam /* 54825977Ssam * Output the address of the second item in the 54925977Ssam * pair pointed to by p. 55025977Ssam */ 55125977Ssam upput(p, size) 55225977Ssam register NODE *p; 55325977Ssam { 55425977Ssam CONSZ save; 55525977Ssam 55625977Ssam if (p->in.op == FLD) 55725977Ssam p = p->in.left; 55825977Ssam switch (p->in.op) { 55925977Ssam 56025977Ssam case NAME: 56125977Ssam case OREG: 56225977Ssam save = p->tn.lval; 56325977Ssam p->tn.lval += size/SZCHAR; 56425977Ssam adrput(p); 56525977Ssam p->tn.lval = save; 56625977Ssam break; 56725977Ssam 56825977Ssam case REG: 56925977Ssam if (size == SZLONG) { 57026162Ssam putstr(rname(p->tn.rval+1)); 57125977Ssam break; 57225977Ssam } 57325977Ssam /* fall thru... */ 57425977Ssam 57525828Ssam default: 57625977Ssam cerror("illegal upper address op %s size %d", 57725977Ssam opst[p->tn.op], size); 57825977Ssam /*NOTREACHED*/ 57925828Ssam } 58025977Ssam } 58125828Ssam 582*30360Ssam /* 583*30360Ssam * Generate code for storage conversions. 584*30360Ssam */ 585*30360Ssam sconv(p, forcc) 586*30360Ssam NODE *p; 587*30360Ssam { 588*30360Ssam register NODE *l, *r; 589*30360Ssam register wfrom, wto; 590*30360Ssam int oltype; 591*30360Ssam 592*30360Ssam l = getlr(p, '1'); 593*30360Ssam oltype = l->in.type, l->in.type = r->in.type; 594*30360Ssam r = getlr(p, 'L'); 595*30360Ssam wfrom = tlen(r), wto = tlen(l); 596*30360Ssam if (wfrom == wto) /* e.g. int -> unsigned */ 597*30360Ssam goto done; 598*30360Ssam /* 599*30360Ssam * Conversion in registers requires care 600*30360Ssam * as cvt and movz instruction don't work 601*30360Ssam * as expected (they end up as plain mov's). 602*30360Ssam */ 603*30360Ssam if (l->in.op == REG && r->in.op == REG) { 604*30360Ssam if (ISUNSIGNED(r->in.type)) { /* unsigned, mask */ 605*30360Ssam if (r->tn.lval != l->tn.lval) { 606*30360Ssam printf("\tandl3\t$%d,", (1<<(wto*SZCHAR))-1); 607*30360Ssam adrput(r); 608*30360Ssam putchar(','); 609*30360Ssam } else 610*30360Ssam printf("\tandl2\t$%d,", (1<<(wto*SZCHAR))-1); 611*30360Ssam adrput(l); 612*30360Ssam } else { /* effect sign-extend */ 613*30360Ssam int shift = (sizeof (int)-wto)*SZCHAR; 614*30360Ssam printf("\tshll\t$%d,", shift); 615*30360Ssam adrput(r); putchar(','); adrput(l); 616*30360Ssam printf("\n\tshar\t$%d,", shift); 617*30360Ssam adrput(l); putchar(','); adrput(l); 618*30360Ssam if (wfrom != sizeof (int)) { 619*30360Ssam /* 620*30360Ssam * Must mask if result is shorter than 621*30360Ssam * the width of a register (to account 622*30360Ssam * for register treatment). 623*30360Ssam */ 624*30360Ssam printf("\n\tandl2\t$%d,",(1<<(wfrom*SZCHAR))-1); 625*30360Ssam adrput(l); 626*30360Ssam } else 627*30360Ssam forcc = 0; 628*30360Ssam } 629*30360Ssam /* 630*30360Ssam * If condition codes are required and the last thing 631*30360Ssam * we did was mask the result, then we must generate a 632*30360Ssam * test of the appropriate type. 633*30360Ssam */ 634*30360Ssam if (forcc) { 635*30360Ssam printf("\n\tcmp"); 636*30360Ssam prtype(l); 637*30360Ssam putchar('\t'); 638*30360Ssam printf("$0,"); 639*30360Ssam adrput(l); 640*30360Ssam } 641*30360Ssam } else { 642*30360Ssam /* 643*30360Ssam * Conversion with at least one parameter in memory. 644*30360Ssam */ 645*30360Ssam if (wfrom < wto) { /* expanding datum */ 646*30360Ssam if (ISUNSIGNED(r->in.type)) { 647*30360Ssam printf("\tmovz"); 648*30360Ssam prtype(r); 649*30360Ssam /* 650*30360Ssam * If target is a register, generate 651*30360Ssam * movz?l so optimizer can compress 652*30360Ssam * argument pushes. 653*30360Ssam */ 654*30360Ssam if (l->in.op == REG) 655*30360Ssam putchar('l'); 656*30360Ssam else 657*30360Ssam prtype(l); 658*30360Ssam } else { 659*30360Ssam printf("\tcvt"); 660*30360Ssam prtype(r), prtype(l); 661*30360Ssam } 662*30360Ssam putchar('\t'); 663*30360Ssam adrput(r); 664*30360Ssam } else { /* shrinking dataum */ 665*30360Ssam int off = wfrom - wto; 666*30360Ssam if (l->in.op == REG) { 667*30360Ssam printf("\tmovz"); 668*30360Ssam prtype(l); 669*30360Ssam putchar('l'); 670*30360Ssam } else { 671*30360Ssam printf("\tcvt"); 672*30360Ssam prtype(l), prtype(r); 673*30360Ssam } 674*30360Ssam putchar('\t'); 675*30360Ssam switch (r->in.op) { 676*30360Ssam case NAME: case OREG: 677*30360Ssam r->tn.lval += off; 678*30360Ssam adrput(r); 679*30360Ssam r->tn.lval -= off; 680*30360Ssam break; 681*30360Ssam case REG: case ICON: case UNARY MUL: 682*30360Ssam adrput(r); 683*30360Ssam break; 684*30360Ssam default: 685*30360Ssam cerror("sconv: bad shrink op"); 686*30360Ssam /*NOTREACHED*/ 687*30360Ssam } 688*30360Ssam } 689*30360Ssam putchar(','); 690*30360Ssam adrput(l); 691*30360Ssam } 692*30360Ssam putchar('\n'); 693*30360Ssam done: 694*30360Ssam l->in.type = oltype; 695*30360Ssam } 696*30360Ssam 69725828Ssam rmove( rt, rs, t ) TWORD t;{ 69825828Ssam printf( " movl %s,%s\n", rname(rs), rname(rt) ); 69925828Ssam if(t==DOUBLE) 70025828Ssam printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) ); 70125828Ssam } 70225828Ssam 70325828Ssam struct respref 70425828Ssam respref[] = { 70525828Ssam INTAREG|INTBREG, INTAREG|INTBREG, 70625828Ssam INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 70725828Ssam INTEMP, INTEMP, 70825828Ssam FORARG, FORARG, 70925828Ssam INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 71025828Ssam 0, 0 }; 71125828Ssam 71225828Ssam setregs(){ /* set up temporary registers */ 71325828Ssam fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */ 71425828Ssam } 71525828Ssam 71626076Ssam #ifndef szty 71725828Ssam szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */ 71825828Ssam return(t==DOUBLE ? 2 : 1 ); 71925828Ssam } 72026076Ssam #endif 72125828Ssam 72225828Ssam rewfld( p ) NODE *p; { 72325828Ssam return(1); 72425828Ssam } 72525828Ssam 72625828Ssam callreg(p) NODE *p; { 72725828Ssam return( R0 ); 72825828Ssam } 72925828Ssam 73025828Ssam base( p ) register NODE *p; { 73125828Ssam register int o = p->in.op; 73225828Ssam 73325828Ssam if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 73425828Ssam if( o==REG ) return( p->tn.rval ); 73525828Ssam if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 73625828Ssam return( p->in.left->tn.rval ); 73725828Ssam if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 73825828Ssam return( p->tn.rval + 0200*1 ); 73925828Ssam return( -1 ); 74025828Ssam } 74125828Ssam 74225828Ssam offset( p, tyl ) register NODE *p; int tyl; { 74325828Ssam 74425828Ssam if(tyl > 8) return( -1 ); 74525828Ssam if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval ); 74625828Ssam if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 74725828Ssam (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0') 74825828Ssam && (1<<p->in.right->tn.lval)==tyl)) 74925828Ssam return( p->in.left->tn.rval ); 75025828Ssam return( -1 ); 75125828Ssam } 75225828Ssam 75325828Ssam makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 75425828Ssam register NODE *t; 75525828Ssam register int i; 75625828Ssam NODE *f; 75725828Ssam 75825828Ssam p->in.op = OREG; 75925828Ssam f = p->in.left; /* have to free this subtree later */ 76025828Ssam 76125828Ssam /* init base */ 76225828Ssam switch (q->in.op) { 76325828Ssam case ICON: 76425828Ssam case REG: 76525828Ssam case OREG: 76625828Ssam t = q; 76725828Ssam break; 76825828Ssam 76925828Ssam case MINUS: 77025828Ssam q->in.right->tn.lval = -q->in.right->tn.lval; 77125828Ssam case PLUS: 77225828Ssam t = q->in.right; 77325828Ssam break; 77425828Ssam 77525828Ssam case UNARY MUL: 77625828Ssam t = q->in.left->in.left; 77725828Ssam break; 77825828Ssam 77925828Ssam default: 78025828Ssam cerror("illegal makeor2"); 78125828Ssam } 78225828Ssam 78325828Ssam p->tn.lval = t->tn.lval; 78425828Ssam #ifndef FLEXNAMES 78525828Ssam for(i=0; i<NCHNAM; ++i) 78625828Ssam p->in.name[i] = t->in.name[i]; 78725828Ssam #else 78825828Ssam p->in.name = t->in.name; 78925828Ssam #endif 79025828Ssam 79125828Ssam /* init offset */ 79225828Ssam p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 79325828Ssam 79425828Ssam tfree(f); 79525828Ssam return; 79625828Ssam } 79725828Ssam 79825828Ssam canaddr( p ) NODE *p; { 79925828Ssam register int o = p->in.op; 80025828Ssam 80125828Ssam if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 80225828Ssam return(0); 80325828Ssam } 80425828Ssam 80526076Ssam #ifndef shltype 80625828Ssam shltype( o, p ) register NODE *p; { 80725828Ssam return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) ); 80825828Ssam } 80926076Ssam #endif 81025828Ssam 81125828Ssam flshape( p ) NODE *p; { 81225828Ssam register int o = p->in.op; 81325828Ssam 81425828Ssam if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 81525828Ssam return(0); 81625828Ssam } 81725828Ssam 81825828Ssam shtemp( p ) register NODE *p; { 81925828Ssam if( p->in.op == STARG ) p = p->in.left; 82025828Ssam return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 82125828Ssam } 82225828Ssam 82325828Ssam shumul( p ) register NODE *p; { 82425828Ssam register int o; 82525828Ssam extern int xdebug; 82625828Ssam 82725828Ssam if (xdebug) { 82825828Ssam printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 82925828Ssam printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 83025828Ssam } 83125828Ssam 83225828Ssam o = p->in.op; 83325828Ssam if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) 83425828Ssam && p->in.type != PTR+DOUBLE) 83525828Ssam return( STARNM ); 83625828Ssam 83725828Ssam return( 0 ); 83825828Ssam } 83925828Ssam 84025828Ssam special( p, shape ) register NODE *p; { 84125828Ssam if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1); 84225828Ssam else return(0); 84325828Ssam } 84425828Ssam 84525828Ssam adrcon( val ) CONSZ val; { 84625947Ssam printf(ACONFMT, val); 84725828Ssam } 84825828Ssam 84925828Ssam conput( p ) register NODE *p; { 85025828Ssam switch( p->in.op ){ 85125828Ssam 85225828Ssam case ICON: 85325828Ssam acon( p ); 85425828Ssam return; 85525828Ssam 85625828Ssam case REG: 85726162Ssam putstr(rname(p->tn.rval)); 85825828Ssam return; 85925828Ssam 86025828Ssam default: 86125828Ssam cerror( "illegal conput" ); 86225828Ssam } 86325828Ssam } 86425828Ssam 86525828Ssam insput( p ) NODE *p; { 86625828Ssam cerror( "insput" ); 86725828Ssam } 86825828Ssam 86925828Ssam adrput( p ) register NODE *p; { 87025828Ssam register int r; 87125828Ssam /* output an address, with offsets, from p */ 87225828Ssam 87325828Ssam if( p->in.op == FLD ){ 87425828Ssam p = p->in.left; 87525828Ssam } 87625828Ssam switch( p->in.op ){ 87725828Ssam 87825828Ssam case NAME: 87925828Ssam acon( p ); 88025828Ssam return; 88125828Ssam 88225828Ssam case ICON: 88325828Ssam /* addressable value of the constant */ 88426162Ssam putchar('$'); 88525828Ssam acon( p ); 88625828Ssam return; 88725828Ssam 88825828Ssam case REG: 88926162Ssam putstr(rname(p->tn.rval)); 89025828Ssam if(p->in.type == DOUBLE) /* for entry mask */ 89125828Ssam (void) rname(p->tn.rval+1); 89225828Ssam return; 89325828Ssam 89425828Ssam case OREG: 89525828Ssam r = p->tn.rval; 89625828Ssam if( R2TEST(r) ){ /* double indexing */ 89725828Ssam register int flags; 89825828Ssam 89925828Ssam flags = R2UPK3(r); 90026162Ssam if( flags & 1 ) putchar('*'); 90125828Ssam if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 90225828Ssam if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) ); 90325828Ssam printf( "[%s]", rname(R2UPK2(r)) ); 90425828Ssam return; 90525828Ssam } 90625828Ssam if( r == FP && p->tn.lval > 0 ){ /* in the argument region */ 90725828Ssam if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 90825828Ssam printf( CONFMT, p->tn.lval ); 90926162Ssam putstr( "(fp)" ); 91025828Ssam return; 91125828Ssam } 91225828Ssam if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 91325828Ssam printf( "(%s)", rname(p->tn.rval) ); 91425828Ssam return; 91525828Ssam 91625828Ssam case UNARY MUL: 91725828Ssam /* STARNM or STARREG found */ 91825828Ssam if( tshape(p, STARNM) ) { 91926162Ssam putchar( '*' ); 92025828Ssam adrput( p->in.left); 92125828Ssam } 92225828Ssam return; 92325828Ssam 92425828Ssam default: 92525828Ssam cerror( "illegal address" ); 92625828Ssam return; 92725828Ssam 92825828Ssam } 92925828Ssam 93025828Ssam } 93125828Ssam 93225828Ssam acon( p ) register NODE *p; { /* print out a constant */ 93325828Ssam 93425828Ssam if( p->in.name[0] == '\0' ){ 93525828Ssam printf( CONFMT, p->tn.lval); 93626162Ssam return; 93726162Ssam } else { 93825828Ssam #ifndef FLEXNAMES 93925828Ssam printf( "%.8s", p->in.name ); 94025828Ssam #else 94126162Ssam putstr(p->in.name); 94225828Ssam #endif 94326162Ssam if (p->tn.lval != 0) { 94426162Ssam putchar('+'); 94526162Ssam printf(CONFMT, p->tn.lval); 94625828Ssam } 94725828Ssam } 94826162Ssam } 94925828Ssam 95025828Ssam genscall( p, cookie ) register NODE *p; { 95125828Ssam /* structure valued call */ 95225828Ssam return( gencall( p, cookie ) ); 95325828Ssam } 95425828Ssam 95525828Ssam genfcall( p, cookie ) register NODE *p; { 95625828Ssam register NODE *p1; 95725828Ssam register int m; 95825828Ssam static char *funcops[6] = { 95925828Ssam "sin", "cos", "sqrt", "exp", "log", "atan" 96025828Ssam }; 96125828Ssam 96225828Ssam /* generate function opcodes */ 96325828Ssam if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT && 96425828Ssam (p1 = p->in.left)->in.op==ICON && 96525828Ssam p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) { 96625828Ssam #ifdef FLEXNAMES 96725828Ssam p1->in.name++; 96825828Ssam #else 96925828Ssam strcpy(p1->in.name, p1->in.name[1]); 97025828Ssam #endif 97125828Ssam for(m=0; m<6; m++) 97225828Ssam if(!strcmp(p1->in.name, funcops[m])) 97325828Ssam break; 97425828Ssam if(m >= 6) 97525828Ssam uerror("no opcode for fortarn function %s", p1->in.name); 97625828Ssam } else 97725828Ssam uerror("illegal type of fortarn function"); 97825828Ssam p1 = p->in.right; 97925828Ssam p->in.op = FORTCALL; 98025828Ssam if(!canaddr(p1)) 98125828Ssam order( p1, INAREG|INBREG|SOREG|STARREG|STARNM ); 98225828Ssam m = match( p, INTAREG|INTBREG ); 98325828Ssam return(m != MDONE); 98425828Ssam } 98525828Ssam 98625828Ssam /* tbl */ 98725828Ssam int gc_numbytes; 98825828Ssam /* tbl */ 98925828Ssam 99025828Ssam gencall( p, cookie ) register NODE *p; { 99125828Ssam /* generate the call given by p */ 99225828Ssam register NODE *p1, *ptemp; 99325828Ssam register int temp, temp1; 99425828Ssam register int m; 99525828Ssam 99625828Ssam if( p->in.right ) temp = argsize( p->in.right ); 99725828Ssam else temp = 0; 99825828Ssam 99925828Ssam if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 100025828Ssam /* set aside room for structure return */ 100125828Ssam 100225828Ssam if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 100325828Ssam else temp1 = temp; 100425828Ssam } 100525828Ssam 100625828Ssam if( temp > maxargs ) maxargs = temp; 100725828Ssam SETOFF(temp1,4); 100825828Ssam 100925828Ssam if( p->in.right ){ /* make temp node, put offset in, and generate args */ 101025828Ssam ptemp = talloc(); 101125828Ssam ptemp->in.op = OREG; 101225828Ssam ptemp->tn.lval = -1; 101325828Ssam ptemp->tn.rval = SP; 101425828Ssam #ifndef FLEXNAMES 101525828Ssam ptemp->in.name[0] = '\0'; 101625828Ssam #else 101725828Ssam ptemp->in.name = ""; 101825828Ssam #endif 101925828Ssam ptemp->in.rall = NOPREF; 102025828Ssam ptemp->in.su = 0; 102125828Ssam genargs( p->in.right, ptemp ); 102225828Ssam ptemp->in.op = FREE; 102325828Ssam } 102425828Ssam 102525828Ssam p1 = p->in.left; 102625828Ssam if( p1->in.op != ICON ){ 102725828Ssam if( p1->in.op != REG ){ 102825828Ssam if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 102925828Ssam if( p1->in.op != NAME ){ 103025828Ssam order( p1, INAREG ); 103125828Ssam } 103225828Ssam } 103325828Ssam } 103425828Ssam } 103525828Ssam 103625828Ssam /* tbl 103725828Ssam setup gc_numbytes so reference to ZC works */ 103825828Ssam 103925828Ssam gc_numbytes = temp&(0x3ff); 104025828Ssam 104125828Ssam p->in.op = UNARY CALL; 104225828Ssam m = match( p, INTAREG|INTBREG ); 104325828Ssam 104425828Ssam return(m != MDONE); 104525828Ssam } 104625828Ssam 104725828Ssam /* tbl */ 104825828Ssam char * 104925828Ssam ccbranches[] = { 105025828Ssam "eql", 105125828Ssam "neq", 105225828Ssam "leq", 105325828Ssam "lss", 105425828Ssam "geq", 105525828Ssam "gtr", 105625828Ssam "lequ", 105725828Ssam "lssu", 105825828Ssam "gequ", 105925828Ssam "gtru", 106025828Ssam }; 106125828Ssam /* tbl */ 106225828Ssam 106325828Ssam cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 106425828Ssam 106525828Ssam if(o != 0 && (o < EQ || o > UGT )) 106625828Ssam cerror( "bad conditional branch: %s", opst[o] ); 106725828Ssam printf( " j%s L%d\n", 106825828Ssam o == 0 ? "br" : ccbranches[o-EQ], lab ); 106925828Ssam } 107025828Ssam 107125828Ssam nextcook( p, cookie ) NODE *p; { 107225828Ssam /* we have failed to match p with cookie; try another */ 107325828Ssam if( cookie == FORREW ) return( 0 ); /* hopeless! */ 107425828Ssam if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 107525828Ssam if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 107625828Ssam return( FORREW ); 107725828Ssam } 107825828Ssam 107925828Ssam lastchance( p, cook ) NODE *p; { 108025828Ssam /* forget it! */ 108125828Ssam return(0); 108225828Ssam } 108325828Ssam 108425828Ssam optim2( p ) register NODE *p; { 108525828Ssam # ifdef ONEPASS 108625828Ssam /* do local tree transformations and optimizations */ 108725828Ssam # define RV(p) p->in.right->tn.lval 108826076Ssam # define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0) 1089*30360Ssam register int o, i; 1090*30360Ssam register NODE *l, *r; 109125828Ssam 1092*30360Ssam switch (o = p->in.op) { 1093*30360Ssam 1094*30360Ssam case DIV: case ASG DIV: 1095*30360Ssam case MOD: case ASG MOD: 1096*30360Ssam /* 1097*30360Ssam * Change unsigned mods and divs to 1098*30360Ssam * logicals (mul is done in mip & c2) 1099*30360Ssam */ 1100*30360Ssam if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) && 1101*30360Ssam (i = ispow2(RV(p))) >= 0) { 1102*30360Ssam if (o == DIV || o == ASG DIV) { 1103*30360Ssam p->in.op = RS; 1104*30360Ssam RV(p) = i; 1105*30360Ssam } else { 1106*30360Ssam p->in.op = AND; 1107*30360Ssam RV(p)--; 1108*30360Ssam } 1109*30360Ssam if (asgop(o)) 1110*30360Ssam p->in.op = ASG p->in.op; 111125828Ssam } 1112*30360Ssam return; 1113*30360Ssam 1114*30360Ssam case SCONV: 1115*30360Ssam l = p->in.left; 1116*30360Ssam /* clobber conversions w/o side effects */ 1117*30360Ssam if (!anyfloat(p, l) && l->in.op != PCONV && 1118*30360Ssam tlen(p) == tlen(l)) { 1119*30360Ssam if (l->in.op != FLD) 1120*30360Ssam l->in.type = p->in.type; 1121*30360Ssam ncopy(p, l); 1122*30360Ssam l->in.op = FREE; 1123*30360Ssam } 1124*30360Ssam return; 1125*30360Ssam 1126*30360Ssam case ASSIGN: 1127*30360Ssam /* 1128*30360Ssam * Try to zap storage conversions of non-float items. 1129*30360Ssam */ 1130*30360Ssam r = p->in.right; 1131*30360Ssam if (r->in.op == SCONV && !anyfloat(r->in.left, r)) { 1132*30360Ssam int wdest, wconv, wsrc; 1133*30360Ssam wdest = tlen(p->in.left); 1134*30360Ssam wconv = tlen(r); 1135*30360Ssam /* 1136*30360Ssam * If size doesn't change across assignment or 1137*30360Ssam * conversion expands src before shrinking again 1138*30360Ssam * due to the assignment, delete conversion so 1139*30360Ssam * code generator can create optimal code. 1140*30360Ssam */ 1141*30360Ssam if (wdest == wconv || 1142*30360Ssam (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) { 1143*30360Ssam p->in.right = r->in.left; 1144*30360Ssam r->in.op = FREE; 1145*30360Ssam } 1146*30360Ssam } 1147*30360Ssam return; 114825828Ssam } 114925828Ssam # endif 115025828Ssam } 115125828Ssam 115225828Ssam struct functbl { 115325828Ssam int fop; 115425828Ssam char *func; 115525828Ssam } opfunc[] = { 115625828Ssam DIV, "udiv", 115725828Ssam ASG DIV, "udiv", 115825828Ssam 0 115925828Ssam }; 116025828Ssam 116125828Ssam hardops(p) register NODE *p; { 116225828Ssam /* change hard to do operators into function calls. */ 116325828Ssam register NODE *q; 116425828Ssam register struct functbl *f; 116525828Ssam register int o; 116625828Ssam register TWORD t, t1, t2; 116725828Ssam 116825828Ssam o = p->in.op; 116925828Ssam 117025828Ssam for( f=opfunc; f->fop; f++ ) { 117125828Ssam if( o==f->fop ) goto convert; 117225828Ssam } 117325828Ssam return; 117425828Ssam 117525828Ssam convert: 117625828Ssam t = p->in.type; 117725828Ssam t1 = p->in.left->in.type; 117825828Ssam t2 = p->in.right->in.type; 117925828Ssam 118029672Ssam if (!((ISUNSIGNED(t1) && !(ISUNSIGNED(t2))) || 118129672Ssam ( t2 == UNSIGNED))) return; 118229672Ssam 118325828Ssam /* need to rewrite tree for ASG OP */ 118425828Ssam /* must change ASG OP to a simple OP */ 118525828Ssam if( asgop( o ) ) { 118625828Ssam q = talloc(); 118725828Ssam q->in.op = NOASG ( o ); 118825828Ssam q->in.rall = NOPREF; 118925828Ssam q->in.type = p->in.type; 119025828Ssam q->in.left = tcopy(p->in.left); 119125828Ssam q->in.right = p->in.right; 119225828Ssam p->in.op = ASSIGN; 119325828Ssam p->in.right = q; 119425828Ssam zappost(q->in.left); /* remove post-INCR(DECR) from new node */ 119525828Ssam fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */ 119625828Ssam p = q; 119725828Ssam 119825828Ssam } 119925828Ssam /* turn logicals to compare 0 */ 120025828Ssam else if( logop( o ) ) { 120125828Ssam ncopy(q = talloc(), p); 120225828Ssam p->in.left = q; 120325828Ssam p->in.right = q = talloc(); 120425828Ssam q->in.op = ICON; 120525828Ssam q->in.type = INT; 120625828Ssam #ifndef FLEXNAMES 120725828Ssam q->in.name[0] = '\0'; 120825828Ssam #else 120925828Ssam q->in.name = ""; 121025828Ssam #endif 121125828Ssam q->tn.lval = 0; 121225828Ssam q->tn.rval = 0; 121325828Ssam p = p->in.left; 121425828Ssam } 121525828Ssam 121625828Ssam /* build comma op for args to function */ 121725828Ssam t1 = p->in.left->in.type; 121825828Ssam t2 = 0; 121925828Ssam if ( optype(p->in.op) == BITYPE) { 122025828Ssam q = talloc(); 122125828Ssam q->in.op = CM; 122225828Ssam q->in.rall = NOPREF; 122325828Ssam q->in.type = INT; 122425828Ssam q->in.left = p->in.left; 122525828Ssam q->in.right = p->in.right; 122625828Ssam t2 = p->in.right->in.type; 122725828Ssam } else 122825828Ssam q = p->in.left; 122925828Ssam 123025828Ssam p->in.op = CALL; 123125828Ssam p->in.right = q; 123225828Ssam 123325828Ssam /* put function name in left node of call */ 123425828Ssam p->in.left = q = talloc(); 123525828Ssam q->in.op = ICON; 123625828Ssam q->in.rall = NOPREF; 123725828Ssam q->in.type = INCREF( FTN + p->in.type ); 123825828Ssam #ifndef FLEXNAMES 123925828Ssam strcpy( q->in.name, f->func ); 124025828Ssam #else 124125828Ssam q->in.name = f->func; 124225828Ssam #endif 124325828Ssam q->tn.lval = 0; 124425828Ssam q->tn.rval = 0; 124525828Ssam 124625828Ssam } 124725828Ssam 124825828Ssam zappost(p) NODE *p; { 124925828Ssam /* look for ++ and -- operators and remove them */ 125025828Ssam 125125828Ssam register int o, ty; 125225828Ssam register NODE *q; 125325828Ssam o = p->in.op; 125425828Ssam ty = optype( o ); 125525828Ssam 125625828Ssam switch( o ){ 125725828Ssam 125825828Ssam case INCR: 125925828Ssam case DECR: 126025828Ssam q = p->in.left; 126125828Ssam p->in.right->in.op = FREE; /* zap constant */ 126225828Ssam ncopy( p, q ); 126325828Ssam q->in.op = FREE; 126425828Ssam return; 126525828Ssam 126625828Ssam } 126725828Ssam 126825828Ssam if( ty == BITYPE ) zappost( p->in.right ); 126925828Ssam if( ty != LTYPE ) zappost( p->in.left ); 127025828Ssam } 127125828Ssam 127225828Ssam fixpre(p) NODE *p; { 127325828Ssam 127425828Ssam register int o, ty; 127525828Ssam o = p->in.op; 127625828Ssam ty = optype( o ); 127725828Ssam 127825828Ssam switch( o ){ 127925828Ssam 128025828Ssam case ASG PLUS: 128125828Ssam p->in.op = PLUS; 128225828Ssam break; 128325828Ssam case ASG MINUS: 128425828Ssam p->in.op = MINUS; 128525828Ssam break; 128625828Ssam } 128725828Ssam 128825828Ssam if( ty == BITYPE ) fixpre( p->in.right ); 128925828Ssam if( ty != LTYPE ) fixpre( p->in.left ); 129025828Ssam } 129125828Ssam 129225828Ssam NODE * addroreg(l) NODE *l; 129325828Ssam /* OREG was built in clocal() 129425828Ssam * for an auto or formal parameter 129525828Ssam * now its address is being taken 129625828Ssam * local code must unwind it 129725828Ssam * back to PLUS/MINUS REG ICON 129825828Ssam * according to local conventions 129925828Ssam */ 130025828Ssam { 130125828Ssam cerror("address of OREG taken"); 130225828Ssam } 130325828Ssam 130425828Ssam # ifndef ONEPASS 130525828Ssam main( argc, argv ) char *argv[]; { 130625828Ssam return( mainp2( argc, argv ) ); 130725828Ssam } 130825828Ssam # endif 130925828Ssam 1310*30360Ssam strip(p) register NODE *p; { 1311*30360Ssam NODE *q; 1312*30360Ssam 1313*30360Ssam /* strip nodes off the top when no side effects occur */ 1314*30360Ssam for( ; ; ) { 1315*30360Ssam switch( p->in.op ) { 1316*30360Ssam case SCONV: /* remove lint tidbits */ 1317*30360Ssam q = p->in.left; 1318*30360Ssam ncopy( p, q ); 1319*30360Ssam q->in.op = FREE; 1320*30360Ssam break; 1321*30360Ssam /* could probably add a few more here */ 1322*30360Ssam default: 1323*30360Ssam return; 1324*30360Ssam } 1325*30360Ssam } 1326*30360Ssam } 1327*30360Ssam 132825828Ssam myreader(p) register NODE *p; { 1329*30360Ssam strip( p ); /* strip off operations with no side effects */ 133025828Ssam walkf( p, hardops ); /* convert ops to function calls */ 133125828Ssam canon( p ); /* expands r-vals for fileds */ 133225828Ssam walkf( p, optim2 ); 133325828Ssam } 1334