117742Sralph # ifndef lint
2*34251Sdonn static char *sccsid ="@(#)local2.c 1.39 (Berkeley) 05/11/88";
317742Sralph # endif
417742Sralph
518556Sralph # include "pass2.h"
632935Sdonn # include <ctype.h>
732935Sdonn
832935Sdonn # define putstr(s) fputs((s), stdout)
932935Sdonn
109702Slinton # ifdef FORT
119702Slinton int ftlab1, ftlab2;
129702Slinton # endif
139702Slinton /* a lot of the machine dependent parts of the second pass */
149702Slinton
159702Slinton # define BITMASK(n) ((1L<<n)-1)
169702Slinton
1732924Sdonn /*ARGSUSED*/
where(c)189702Slinton where(c){
199702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno );
209702Slinton }
219702Slinton
lineid(l,fn)229702Slinton lineid( l, fn ) char *fn; {
239702Slinton /* identify line l and file fn */
249702Slinton printf( "# line %d, file %s\n", l, fn );
259702Slinton }
269702Slinton
279702Slinton
eobl2()289702Slinton eobl2(){
2932935Sdonn register OFFSZ spoff; /* offset from stack pointer */
3032935Sdonn #ifndef FORT
3132935Sdonn extern int ftlab1, ftlab2;
3232935Sdonn #endif
3332935Sdonn
349702Slinton spoff = maxoff;
359702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
369702Slinton spoff /= SZCHAR;
379702Slinton SETOFF(spoff,4);
3832935Sdonn #ifdef FORT
399702Slinton #ifndef FLEXNAMES
409702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff );
419702Slinton #else
429702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */
439702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff );
449702Slinton #endif
459702Slinton #else
469702Slinton printf( "L%d:\n", ftlab1);
479702Slinton if( spoff!=0 )
489702Slinton if( spoff < 64 )
499702Slinton printf( " subl2 $%ld,sp\n", spoff);
509702Slinton else
519702Slinton printf( " movab -%ld(sp),sp\n", spoff);
529702Slinton printf( " jbr L%d\n", ftlab2);
539702Slinton #endif
549702Slinton maxargs = -1;
559702Slinton }
569702Slinton
579702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = {
589702Slinton
599702Slinton PLUS, "add",
609702Slinton MINUS, "sub",
619702Slinton MUL, "mul",
629702Slinton DIV, "div",
639702Slinton OR, "bis",
649702Slinton ER, "xor",
659702Slinton AND, "bic",
669702Slinton -1, "" };
679702Slinton
hopcode(f,o)689702Slinton hopcode( f, o ){
699702Slinton /* output the appropriate string from the above table */
709702Slinton
719702Slinton register struct hoptab *q;
729702Slinton
7332935Sdonn if(asgop(o))
7432935Sdonn o = NOASG o;
759702Slinton for( q = ioptab; q->opmask>=0; ++q ){
769702Slinton if( q->opmask == o ){
7732935Sdonn printf( "%s%c", q->opstring, tolower(f));
789702Slinton return;
799702Slinton }
809702Slinton }
819702Slinton cerror( "no hoptab for %s", opst[o] );
829702Slinton }
839702Slinton
849702Slinton char *
859702Slinton rnames[] = { /* keyed to register number tokens */
869702Slinton
879702Slinton "r0", "r1",
889702Slinton "r2", "r3", "r4", "r5",
899702Slinton "r6", "r7", "r8", "r9", "r10", "r11",
909702Slinton "ap", "fp", "sp", "pc",
919702Slinton };
929702Slinton
939702Slinton int rstatus[] = {
949702Slinton SAREG|STAREG, SAREG|STAREG,
959702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
969702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
979702Slinton SAREG, SAREG, SAREG, SAREG,
989702Slinton };
999702Slinton
tlen(p)1009702Slinton tlen(p) NODE *p;
1019702Slinton {
1029702Slinton switch(p->in.type) {
1039702Slinton case CHAR:
1049702Slinton case UCHAR:
1059702Slinton return(1);
1069702Slinton
1079702Slinton case SHORT:
1089702Slinton case USHORT:
10932937Sdonn return(SZSHORT/SZCHAR);
1109702Slinton
1119702Slinton case DOUBLE:
11232937Sdonn return(SZDOUBLE/SZCHAR);
1139702Slinton
1149702Slinton default:
11532937Sdonn return(SZINT/SZCHAR);
1169702Slinton }
1179702Slinton }
1189702Slinton
mixtypes(p,q)1199702Slinton mixtypes(p, q) NODE *p, *q;
1209702Slinton {
12116181Sralph register TWORD tp, tq;
1229702Slinton
1239702Slinton tp = p->in.type;
1249702Slinton tq = q->in.type;
1259702Slinton
1269702Slinton return( (tp==FLOAT || tp==DOUBLE) !=
1279702Slinton (tq==FLOAT || tq==DOUBLE) );
1289702Slinton }
1299702Slinton
prtype(n)1309702Slinton prtype(n) NODE *n;
1319702Slinton {
1329702Slinton switch (n->in.type)
1339702Slinton {
13432935Sdonn
1359702Slinton case DOUBLE:
13624418Smckusick putchar('d');
1379702Slinton return;
1389702Slinton
1399702Slinton case FLOAT:
14024418Smckusick putchar('f');
1419702Slinton return;
1429702Slinton
1439702Slinton case LONG:
1449702Slinton case ULONG:
1459702Slinton case INT:
1469702Slinton case UNSIGNED:
14724418Smckusick putchar('l');
1489702Slinton return;
1499702Slinton
1509702Slinton case SHORT:
1519702Slinton case USHORT:
15224418Smckusick putchar('w');
1539702Slinton return;
1549702Slinton
1559702Slinton case CHAR:
1569702Slinton case UCHAR:
15724418Smckusick putchar('b');
1589702Slinton return;
1599702Slinton
1609702Slinton default:
1619702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
1629702Slinton else {
16324418Smckusick putchar('l');
1649702Slinton return;
1659702Slinton }
1669702Slinton }
1679702Slinton }
1689702Slinton
zzzcode(p,c)1699702Slinton zzzcode( p, c ) register NODE *p; {
17032935Sdonn register int m;
17132924Sdonn int val;
1729702Slinton switch( c ){
1739702Slinton
1749702Slinton case 'N': /* logical ops, turned into 0-1 */
1759702Slinton /* use register given by register 1 */
1769702Slinton cbgen( 0, m=getlab(), 'I' );
1779702Slinton deflab( p->bn.label );
1789702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] );
1799702Slinton deflab( m );
1809702Slinton return;
1819702Slinton
1829702Slinton case 'P':
1839702Slinton cbgen( p->in.op, p->bn.label, c );
1849702Slinton return;
1859702Slinton
1869702Slinton case 'A':
18732935Sdonn case 'V':
18832935Sdonn sconv( p, c == 'V' );
1899702Slinton return;
1909702Slinton
19125751Sdonn case 'G': /* i *= f; asgops with int lhs and float rhs */
19225751Sdonn {
19325751Sdonn register NODE *l, *r, *s;
19425751Sdonn int rt;
19525751Sdonn
19625751Sdonn l = p->in.left;
19725751Sdonn r = p->in.right;
19825751Sdonn s = talloc();
19925751Sdonn rt = r->in.type;
20025751Sdonn
20125751Sdonn s->in.op = SCONV;
20225751Sdonn s->in.left = l;
20325751Sdonn s->in.type = rt;
20425751Sdonn zzzcode(s, 'A');
20525751Sdonn putstr("\n\t");
20625751Sdonn
20725751Sdonn hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
20825751Sdonn putstr("2\t");
20925751Sdonn adrput(r);
21025751Sdonn putchar(',');
21125751Sdonn adrput(resc);
21225751Sdonn putstr("\n\t");
21325751Sdonn
21425751Sdonn s->in.op = ASSIGN;
21525751Sdonn s->in.left = l;
21625751Sdonn s->in.right = resc;
21725751Sdonn s->in.type = l->in.type;
21825751Sdonn zzzcode(s, 'A');
21925751Sdonn
22025751Sdonn s->in.op = FREE;
22125751Sdonn return;
22225751Sdonn }
22325751Sdonn
22432928Sdonn case 'J': /* unsigned DIV/MOD with constant divisors */
22532928Sdonn {
22632928Sdonn register int ck = INAREG;
22732928Sdonn int label1, label2;
22832928Sdonn
22932928Sdonn /* case constant <= 1 is handled by optim() in pass 1 */
23032928Sdonn /* case constant < 0x80000000 is handled in table */
23132928Sdonn switch( p->in.op ) {
23232938Sdonn /* case DIV: handled in optim2() */
23332928Sdonn case MOD:
23432928Sdonn if( p->in.left->in.op == REG &&
23532928Sdonn p->in.left->tn.rval == resc->tn.rval )
23632928Sdonn goto asgmod;
23732928Sdonn label1 = getlab();
23832928Sdonn expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
23932928Sdonn printf("\tjlssu\tL%d\n", label1);
24032928Sdonn expand(p, ck, "\tsubl2\tAR,A1\n");
24132928Sdonn printf("L%d:", label1);
24232928Sdonn break;
24332928Sdonn case ASG DIV:
24432928Sdonn label1 = getlab();
24532928Sdonn label2 = getlab();
24632928Sdonn expand(p, ck, "cmpl\tAL,AR\n");
24732928Sdonn printf("\tjgequ\tL%d\n", label1);
24832928Sdonn expand(p, ck, "\tmovl\t$1,AL\n");
24932928Sdonn printf("\tjbr\tL%d\nL%d:\n", label2, label1);
25032928Sdonn expand(p, ck, "\tclrl\tAL\n");
25132928Sdonn printf("L%d:", label2);
25232928Sdonn break;
25332928Sdonn case ASG MOD:
25432928Sdonn asgmod:
25532928Sdonn label1 = getlab();
25632928Sdonn expand(p, ck, "cmpl\tAL,AR\n");
25732928Sdonn printf("\tjlssu\tL%d\n", label1);
25832928Sdonn expand(p, ck, "\tsubl2\tAR,AL\n");
25932928Sdonn printf("L%d:", label1);
26032928Sdonn break;
26132928Sdonn }
26232928Sdonn return;
26332928Sdonn }
26432928Sdonn
2659702Slinton case 'B': /* get oreg value in temp register for left shift */
2669702Slinton {
2679702Slinton register NODE *r;
2689702Slinton if (xdebug) eprint(p, 0, &val, &val);
2699702Slinton r = p->in.right;
27032937Sdonn if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT )
27124418Smckusick putstr("movl");
2729702Slinton else {
27332935Sdonn putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
2749702Slinton prtype(r);
27524418Smckusick putchar('l');
2769702Slinton }
2779702Slinton return;
2789702Slinton }
2799702Slinton
2809702Slinton case 'C': /* num words pushed on arg stack */
2819702Slinton {
2829702Slinton extern int gc_numbytes;
2839702Slinton extern int xdebug;
2849702Slinton
2859702Slinton if (xdebug) printf("->%d<-",gc_numbytes);
2869702Slinton
2879702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
2889702Slinton return;
2899702Slinton }
2909702Slinton
2919702Slinton case 'D': /* INCR and DECR */
2929702Slinton zzzcode(p->in.left, 'A');
29324418Smckusick putchar('\n');
29424418Smckusick putchar('\t');
2959702Slinton
2969702Slinton case 'E': /* INCR and DECR, FOREFF */
29732934Sdonn if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
2989702Slinton {
29932935Sdonn putstr(p->in.op == INCR ? "inc" : "dec");
3009702Slinton prtype(p->in.left);
30124418Smckusick putchar('\t');
3029702Slinton adrput(p->in.left);
3039702Slinton return;
3049702Slinton }
30532935Sdonn putstr(p->in.op == INCR ? "add" : "sub");
3069702Slinton prtype(p->in.left);
30724418Smckusick putchar('2');
30824418Smckusick putchar('\t');
3099702Slinton adrput(p->in.right);
31024418Smckusick putchar(',');
3119702Slinton adrput(p->in.left);
3129702Slinton return;
3139702Slinton
3149702Slinton case 'F': /* register type of right operand */
3159702Slinton {
3169702Slinton register NODE *n;
3179702Slinton extern int xdebug;
3189702Slinton register int ty;
3199702Slinton
3209702Slinton n = getlr( p, 'R' );
3219702Slinton ty = n->in.type;
3229702Slinton
3239702Slinton if (xdebug) printf("->%d<-", ty);
3249702Slinton
32524418Smckusick if ( ty==DOUBLE) putchar('d');
32624418Smckusick else if ( ty==FLOAT ) putchar('f');
32724418Smckusick else putchar('l');
3289702Slinton return;
3299702Slinton }
3309702Slinton
3319702Slinton case 'L': /* type of left operand */
3329702Slinton case 'R': /* type of right operand */
3339702Slinton {
3349702Slinton register NODE *n;
3359702Slinton extern int xdebug;
3369702Slinton
33716181Sralph n = getlr( p, c );
3389702Slinton if (xdebug) printf("->%d<-", n->in.type);
3399702Slinton
3409702Slinton prtype(n);
3419702Slinton return;
3429702Slinton }
3439702Slinton
34432938Sdonn case 'Z': /* AND for CC with ICON -- lval is complemented */
34532938Sdonn {
34632938Sdonn register NODE *l, *r;
34732938Sdonn
34832938Sdonn l = getlr( p, 'L' );
34932938Sdonn r = getlr( p, 'R' );
35032938Sdonn m = (1 << tlen(l) * SZCHAR) - 1;
35132938Sdonn r->tn.lval = ~r->tn.lval;
35232938Sdonn if( (l->in.type == CHAR || l->in.type == SHORT) &&
35332938Sdonn (r->tn.lval & ~m) ) {
35432938Sdonn putstr("cvt");
35532938Sdonn prtype(l);
35632938Sdonn putstr("l\t");
35732938Sdonn adrput(l);
35832938Sdonn putchar(',');
35932938Sdonn adrput(resc);
36032938Sdonn putstr("\n\t");
36132938Sdonn resc->tn.type = INT;
36232938Sdonn l = resc;
36332938Sdonn }
36432938Sdonn else if( l->in.type == UCHAR || l->in.type == USHORT )
36532938Sdonn /* remove trash left over from complementing */
36632938Sdonn r->tn.lval &= m;
36732938Sdonn putstr("bit");
36832938Sdonn prtype(l);
36932938Sdonn printf("\t$%ld", r->tn.lval);
37032938Sdonn putchar(',');
37132938Sdonn adrput(l);
3729702Slinton return;
37332938Sdonn }
3749702Slinton
3759702Slinton case 'U': /* 32 - n, for unsigned right shifts */
3769702Slinton printf("$%d", 32 - p->in.right->tn.lval );
3779702Slinton return;
3789702Slinton
3799702Slinton case 'T': /* rounded structure length for arguments */
3809702Slinton {
3819702Slinton int size;
3829702Slinton
3839702Slinton size = p->stn.stsize;
3849702Slinton SETOFF( size, 4);
3859702Slinton printf("$%d", size);
3869702Slinton return;
3879702Slinton }
3889702Slinton
3899702Slinton case 'S': /* structure assignment */
39032935Sdonn stasg(p);
39132935Sdonn break;
3929702Slinton
39332935Sdonn default:
39432935Sdonn cerror( "illegal zzzcode" );
39532935Sdonn }
39632935Sdonn }
3979702Slinton
stasg(p)39832935Sdonn stasg(p)
39932935Sdonn register NODE *p;
40032935Sdonn {
40132935Sdonn register NODE *l, *r;
40232935Sdonn register size;
4039702Slinton
40432935Sdonn if( p->in.op == STASG ){
40532935Sdonn l = p->in.left;
40632935Sdonn r = p->in.right;
4079702Slinton
40832935Sdonn }
40932935Sdonn else if( p->in.op == STARG ){ /* store an arg into a temporary */
41032935Sdonn r = p->in.left;
41132935Sdonn }
41232935Sdonn else cerror( "STASG bad" );
4139702Slinton
41432935Sdonn if( r->in.op == ICON ) r->in.op = NAME;
41532935Sdonn else if( r->in.op == REG ) r->in.op = OREG;
41632935Sdonn else if( r->in.op != OREG ) cerror( "STASG-r" );
4179702Slinton
41832935Sdonn size = p->stn.stsize;
41932935Sdonn
42032935Sdonn if( size <= 0 || size > 65535 )
42132935Sdonn cerror("structure size <0=0 or >65535");
42232935Sdonn
42332935Sdonn switch(size) {
42432935Sdonn case 1:
42532935Sdonn putstr(" movb ");
42632935Sdonn break;
42732935Sdonn case 2:
42832935Sdonn putstr(" movw ");
42932935Sdonn break;
43032935Sdonn case 4:
43132935Sdonn putstr(" movl ");
43232935Sdonn break;
43332935Sdonn case 8:
43432935Sdonn putstr(" movq ");
43532935Sdonn break;
43632935Sdonn default:
43732935Sdonn printf(" movc3 $%d,", size);
43832935Sdonn break;
43932935Sdonn }
44032935Sdonn adrput(r);
44132935Sdonn if( p->in.op == STASG ){
44232935Sdonn putchar(',');
44332935Sdonn adrput(l);
44432935Sdonn putchar('\n');
44532935Sdonn }
44632935Sdonn else
44732935Sdonn putstr(",(sp)\n");
44832935Sdonn
44932935Sdonn if( r->in.op == NAME ) r->in.op = ICON;
45032935Sdonn else if( r->in.op == OREG ) r->in.op = REG;
45132935Sdonn }
45232935Sdonn
makearg(ty)45332935Sdonn NODE *makearg( ty ) int ty; {
45432935Sdonn register NODE *p, *q;
45532935Sdonn
45632935Sdonn /* build a -(sp) operand */
45732935Sdonn p = talloc();
45832935Sdonn p->in.op = REG;
45932935Sdonn /* the type needn't be right, just consistent */
46032935Sdonn p->in.type = INCREF(ty);
46132935Sdonn p->tn.rval = SP;
46232935Sdonn p->tn.lval = 0;
46332935Sdonn q = talloc();
46432935Sdonn q->in.op = ASG MINUS;
46532935Sdonn q->in.type = INCREF(ty);
46632935Sdonn q->in.left = p;
46732935Sdonn p = talloc();
46832935Sdonn p->in.op = ICON;
46932935Sdonn p->in.type = INT;
47032935Sdonn p->tn.name = "";
47132941Sdonn /* size of floating argument is always 2 */
47232941Sdonn p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR);
47332935Sdonn q->in.right = p;
47432935Sdonn p = talloc();
47532935Sdonn p->in.op = UNARY MUL;
47632935Sdonn p->in.left = q;
47732935Sdonn return( p );
47832935Sdonn }
47932935Sdonn
sconv(p,forarg)48032935Sdonn sconv( p, forarg ) register NODE *p; {
48132935Sdonn register NODE *l, *r;
48232935Sdonn int m, val;
48332935Sdonn
48432935Sdonn if (xdebug) eprint(p, 0, &val, &val);
48532935Sdonn r = getlr(p, 'R');
48632935Sdonn if (p->in.op == ASSIGN)
48732935Sdonn l = getlr(p, 'L');
48832935Sdonn else if (p->in.op == SCONV) {
48932935Sdonn m = r->in.type;
49032935Sdonn if (forarg)
49132935Sdonn l = makearg( m );
49232935Sdonn else
49332935Sdonn l = resc;
49432935Sdonn l->in.type = m;
49532935Sdonn r = getlr(p, 'L');
49632935Sdonn }
49732935Sdonn else { /* OPLTYPE */
49832935Sdonn m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
49932935Sdonn if (forarg)
50032935Sdonn l = makearg( m );
50132935Sdonn else
50232935Sdonn l = resc;
50332935Sdonn l->in.type = m;
50432935Sdonn }
50532935Sdonn if (r->in.op == ICON)
50632935Sdonn if (r->in.name[0] == '\0') {
50732942Sdonn if (r->tn.lval == 0 &&
50832942Sdonn (r->in.type == DOUBLE || r->in.type == FLOAT ||
50932942Sdonn !forarg)) {
51032942Sdonn if (r->in.type == FLOAT)
51132942Sdonn r->in.type = DOUBLE;
51232935Sdonn putstr("clr");
51332935Sdonn prtype(l);
51432935Sdonn putchar('\t');
51516418Sralph adrput(l);
51632935Sdonn goto cleanup;
51716418Sralph }
51832935Sdonn if (r->tn.lval < 0 && r->tn.lval >= -63) {
51932935Sdonn putstr("mneg");
52032935Sdonn prtype(l);
52132935Sdonn r->tn.lval = -r->tn.lval;
52232935Sdonn goto ops;
52332935Sdonn }
52432935Sdonn if (r->tn.lval < 0)
52532935Sdonn r->in.type = r->tn.lval >= -128 ? CHAR
52632935Sdonn : (r->tn.lval >= -32768 ? SHORT
52732935Sdonn : INT);
52832935Sdonn else if (l->in.type == FLOAT ||
52932935Sdonn l->in.type == DOUBLE)
53032935Sdonn r->in.type = r->tn.lval <= 63 ? INT
53132935Sdonn : (r->tn.lval <= 127 ? CHAR
53232935Sdonn : (r->tn.lval <= 32767 ? SHORT
53332935Sdonn : INT));
53416418Sralph else
53532935Sdonn r->in.type = r->tn.lval <= 63 ? INT
53632935Sdonn : (r->tn.lval <= 127 ? CHAR
53732935Sdonn : (r->tn.lval <= 255 ? UCHAR
53832935Sdonn : (r->tn.lval <= 32767 ? SHORT
53932935Sdonn : (r->tn.lval <= 65535 ? USHORT
54032935Sdonn : INT))));
54132938Sdonn if (forarg && r->in.type == INT) {
54232938Sdonn putstr("pushl\t");
54332938Sdonn adrput(r);
54432938Sdonn goto cleanup;
54532938Sdonn }
54632935Sdonn }
54732935Sdonn else {
54832938Sdonn if (forarg && tlen(r) == SZINT/SZCHAR) {
54932938Sdonn putstr("pushl\t");
55032938Sdonn adrput(r);
55132938Sdonn goto cleanup;
55232938Sdonn }
55332938Sdonn putstr("moval\t");
55432935Sdonn acon(r);
55532935Sdonn putchar(',');
55632935Sdonn adrput(l);
55732935Sdonn goto cleanup;
55832935Sdonn }
5599702Slinton
56032935Sdonn if (p->in.op == SCONV &&
56132935Sdonn !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
56232935Sdonn !mixtypes(l, r)) {
56332935Sdonn /*
56432935Sdonn * Because registers must always contain objects
56532935Sdonn * of the same width as INTs, we may have to
56632935Sdonn * perform two conversions to get an INT. Can
56732935Sdonn * the conversions be collapsed into one?
56832935Sdonn */
56932935Sdonn if (m = collapsible(l, r))
57032935Sdonn r->in.type = m;
57132935Sdonn else {
57232943Sdonn /* two steps are required */
57332940Sdonn NODE *x;
5749702Slinton
57532940Sdonn if (forarg) {
57632940Sdonn x = resc;
57732940Sdonn x->in.type = l->in.type;
57832940Sdonn }
57932940Sdonn else {
58032940Sdonn x = &resc[1];
58132940Sdonn *x = *l;
58232940Sdonn }
58332940Sdonn
58432935Sdonn if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
58532935Sdonn putstr("movz");
58632935Sdonn else
58732935Sdonn putstr("cvt");
58832935Sdonn prtype(r);
58932935Sdonn prtype(x);
59032935Sdonn putchar('\t');
59132935Sdonn adrput(r);
59232935Sdonn putchar(',');
59332935Sdonn adrput(x);
59432935Sdonn putchar('\n');
59532935Sdonn putchar('\t');
59632935Sdonn r = x;
5979702Slinton }
59832935Sdonn l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
59932935Sdonn }
6009702Slinton
60132943Sdonn else if ((forarg || l == resc) &&
60232943Sdonn tlen(l) < SZINT/SZCHAR &&
60332943Sdonn mixtypes(l, r)) {
60432943Sdonn /* two steps needed here too */
60532943Sdonn NODE *x;
60632943Sdonn
60732943Sdonn if (forarg) {
60832943Sdonn x = resc;
60932943Sdonn x->in.type = l->in.type;
61032943Sdonn }
61132943Sdonn else {
61232943Sdonn x = &resc[1];
61332943Sdonn *x = *l;
61432943Sdonn }
61532943Sdonn putstr("cvt");
61632943Sdonn prtype(r);
61732943Sdonn prtype(x);
61832943Sdonn putchar('\t');
61932943Sdonn adrput(r);
62032943Sdonn putchar(',');
62132943Sdonn adrput(x);
62232943Sdonn putstr("\n\t");
62332943Sdonn r = x;
62432943Sdonn l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
62532943Sdonn }
62632943Sdonn
62732943Sdonn else if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
62832935Sdonn mixtypes(l, r)) {
629*34251Sdonn int label1;
63032940Sdonn NODE *x = NULL;
63132935Sdonn
63232940Sdonn #if defined(FORT) || defined(SPRECC)
63332940Sdonn if (forarg)
63432940Sdonn #else
63532940Sdonn if (forarg || l == resc)
63632940Sdonn #endif
63732940Sdonn {
63832940Sdonn /* compute in register, convert to double when done */
63932940Sdonn x = l;
64032940Sdonn l = resc;
64132940Sdonn l->in.type = x->in.type;
64232940Sdonn }
64332940Sdonn
64432935Sdonn label1 = getlab();
64532935Sdonn
646*34251Sdonn putstr("cvtl");
64732935Sdonn prtype(l);
64832935Sdonn putchar('\t');
649*34251Sdonn adrput(r);
65032935Sdonn putchar(',');
65132935Sdonn adrput(l);
652*34251Sdonn printf("\n\tjgeq\tL%d\n\tadd", label1);
65332935Sdonn prtype(l);
65432935Sdonn putstr("2\t$0");
65532935Sdonn prtype(l);
656*34251Sdonn putstr("4.294967296e9,");
65732935Sdonn adrput(l);
658*34251Sdonn printf("\nL%d:", label1);
65932935Sdonn
66032943Sdonn #if defined(FORT) || defined(SPRECC)
66132943Sdonn if (!forarg)
66232943Sdonn #else
66332940Sdonn if (!forarg && (l->in.type == DOUBLE || l != resc))
66432943Sdonn #endif
66532940Sdonn goto cleanup;
66632943Sdonn if (x == NULL)
66732943Sdonn cerror("sconv botch");
66832943Sdonn if (l == x) {
66932943Sdonn r = &resc[1];
67032943Sdonn *r = *l;
67132940Sdonn }
67232943Sdonn else {
67332943Sdonn r = l;
67432943Sdonn l = x;
67532943Sdonn }
67632943Sdonn l->in.type = DOUBLE;
67732940Sdonn putstr("\n\t");
6789702Slinton }
67932935Sdonn
68032943Sdonn else if( (l->in.type == FLOAT || l->in.type == DOUBLE) &&
68132940Sdonn (r->in.type == UCHAR || r->in.type == USHORT) ) {
68232940Sdonn /* skip unnecessary unsigned to floating conversion */
68332940Sdonn #if defined(FORT) || defined(SPRECC)
68432940Sdonn if (forarg)
68532940Sdonn #else
68632940Sdonn if (forarg || l == resc)
68732940Sdonn #endif
68832940Sdonn l->in.type = DOUBLE;
68932940Sdonn putstr("movz");
69032940Sdonn prtype(r);
69132940Sdonn putstr("l\t");
69232940Sdonn adrput(r);
69332940Sdonn putchar(',');
69432940Sdonn adrput(resc);
69532940Sdonn putstr("\n\t");
69632940Sdonn if (l == resc) {
69732940Sdonn r = &resc[1];
69832940Sdonn *r = *l;
69932940Sdonn }
70032940Sdonn else
70132940Sdonn r = resc;
70232940Sdonn r->in.type = INT;
70332940Sdonn }
70432940Sdonn
70532940Sdonn #if defined(FORT) || defined(SPRECC)
70632940Sdonn if (forarg && l->in.type == FLOAT)
70732940Sdonn #else
70832940Sdonn if ((forarg || l == resc) && l->in.type == FLOAT)
70932940Sdonn #endif
71032940Sdonn {
71132940Sdonn /* perform an implicit conversion to double */
71232940Sdonn l->in.type = DOUBLE;
71332940Sdonn if (r->in.type != FLOAT &&
71432940Sdonn r->in.type != CHAR &&
71532940Sdonn r->in.type != SHORT) {
71632940Sdonn /* trim bits from the mantissa */
71732940Sdonn putstr("cvt");
71832940Sdonn prtype(r);
71932940Sdonn putstr("f\t");
72032940Sdonn adrput(r);
72132940Sdonn putchar(',');
72232940Sdonn adrput(resc);
72332940Sdonn putstr("\n\t");
72432940Sdonn if (l == resc) {
72532940Sdonn r = &resc[1];
72632940Sdonn *r = *l;
72732940Sdonn }
72832940Sdonn else
72932940Sdonn r = resc;
73032940Sdonn r->in.type = FLOAT;
73132940Sdonn }
73232940Sdonn }
73332940Sdonn
73432935Sdonn if (!mixtypes(l,r)) {
73532935Sdonn if (tlen(l) == tlen(r)) {
73632938Sdonn if (forarg && tlen(l) == SZINT/SZCHAR) {
73732938Sdonn putstr("pushl\t");
73832938Sdonn adrput(r);
73932938Sdonn goto cleanup;
74032938Sdonn }
74132935Sdonn putstr("mov");
74232935Sdonn #ifdef FORT
74332935Sdonn if (Oflag)
74432935Sdonn prtype(l);
74532935Sdonn else {
74632935Sdonn if (l->in.type == DOUBLE)
74732935Sdonn putchar('q');
74832935Sdonn else if(l->in.type == FLOAT)
74932935Sdonn putchar('l');
75032935Sdonn else
75132935Sdonn prtype(l);
75232935Sdonn }
75332935Sdonn #else
75432935Sdonn prtype(l);
75532935Sdonn #endif FORT
75632935Sdonn goto ops;
75732935Sdonn }
75832935Sdonn else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
75932935Sdonn putstr("movz");
76032935Sdonn else
76132935Sdonn putstr("cvt");
76232935Sdonn }
76332935Sdonn else
76432935Sdonn putstr("cvt");
76532935Sdonn prtype(r);
76632935Sdonn prtype(l);
76732935Sdonn ops:
76832935Sdonn putchar('\t');
76932935Sdonn adrput(r);
77032935Sdonn putchar(',');
77132935Sdonn adrput(l);
77232935Sdonn
77332935Sdonn cleanup:
77432935Sdonn if (forarg)
77532935Sdonn tfree(l);
7769702Slinton }
7779702Slinton
77823536Sbloom /*
77923536Sbloom * collapsible(dest, src) -- if a conversion with a register destination
78023536Sbloom * can be accomplished in one instruction, return the type of src
78123536Sbloom * that will do the job correctly; otherwise return 0. Note that
78223536Sbloom * a register must always end up having type INT or UNSIGNED.
78323536Sbloom */
78423536Sbloom int
collapsible(dest,src)78523536Sbloom collapsible(dest, src)
78623536Sbloom NODE *dest, *src;
78723536Sbloom {
78823536Sbloom int st = src->in.type;
78923536Sbloom int dt = dest->in.type;
79023536Sbloom int newt = 0;
79123536Sbloom
79223536Sbloom /*
79323536Sbloom * Are there side effects of evaluating src?
79423536Sbloom * If the derived type will not be the same size as src,
79524418Smckusick * we may have to use two steps.
79623536Sbloom */
79724418Smckusick if (tlen(src) > tlen(dest)) {
79824418Smckusick if (tshape(src, STARREG))
79924418Smckusick return (0);
80024418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval))
80124418Smckusick return (0);
80224418Smckusick }
80323536Sbloom
80423536Sbloom /*
80523536Sbloom * Can we get an object of dest's type by punning src?
80623536Sbloom * Praises be to great Cthulhu for little-endian machines...
80723536Sbloom */
80823536Sbloom if (st == CHAR && dt == USHORT)
80923536Sbloom /*
81023536Sbloom * Special case -- we must sign-extend to 16 bits.
81123536Sbloom */
81223536Sbloom return (0);
81323536Sbloom
81423536Sbloom if (tlen(src) < tlen(dest))
81523536Sbloom newt = st;
81623536Sbloom else
81723536Sbloom newt = dt;
81823536Sbloom
81923536Sbloom return (newt);
82023536Sbloom }
82123536Sbloom
rmove(rt,rs,t)82217742Sralph rmove( rt, rs, t ) TWORD t; {
8239702Slinton printf( " %s %s,%s\n",
82417742Sralph #ifdef FORT
82517742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") :
82617742Sralph #endif
8279702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
8289702Slinton rnames[rs], rnames[rt] );
8299702Slinton }
8309702Slinton
8319702Slinton struct respref
8329702Slinton respref[] = {
8339702Slinton INTAREG|INTBREG, INTAREG|INTBREG,
8349702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
8359702Slinton INTEMP, INTEMP,
8369702Slinton FORARG, FORARG,
8379702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
8389702Slinton 0, 0 };
8399702Slinton
setregs()8409702Slinton setregs(){ /* set up temporary registers */
8419702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
8429702Slinton }
8439702Slinton
84432924Sdonn /*ARGSUSED*/
rewfld(p)8459702Slinton rewfld( p ) NODE *p; {
8469702Slinton return(1);
8479702Slinton }
8489702Slinton
84932924Sdonn /*ARGSUSED*/
callreg(p)8509702Slinton callreg(p) NODE *p; {
8519702Slinton return( R0 );
8529702Slinton }
8539702Slinton
base(p)8549702Slinton base( p ) register NODE *p; {
8559702Slinton register int o = p->in.op;
8569702Slinton
85732938Sdonn if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */
8589702Slinton if( o==REG ) return( p->tn.rval );
8599702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
8609702Slinton return( p->in.left->tn.rval );
8619702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
8629702Slinton return( p->tn.rval + 0200*1 );
8639702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
8649702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
8659702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
8669702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
8679702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) );
86832938Sdonn if( o==NAME ) return( 100 + 0200*1 );
8699702Slinton return( -1 );
8709702Slinton }
8719702Slinton
offset(p,tyl)8729702Slinton offset( p, tyl ) register NODE *p; int tyl; {
8739702Slinton
87424418Smckusick if( tyl==1 &&
87524418Smckusick p->in.op==REG &&
87624418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) )
87724418Smckusick return( p->tn.rval );
87824418Smckusick if( p->in.op==LS &&
87924418Smckusick p->in.left->in.op==REG &&
88024418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
88124418Smckusick p->in.right->in.op==ICON &&
88224418Smckusick p->in.right->in.name[0]=='\0' &&
88324418Smckusick (1<<p->in.right->tn.lval)==tyl)
8849702Slinton return( p->in.left->tn.rval );
88524418Smckusick if( tyl==2 &&
88624418Smckusick p->in.op==PLUS &&
88724418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
88824418Smckusick p->in.left->in.op==REG &&
88924418Smckusick p->in.right->in.op==REG &&
89024418Smckusick p->in.left->tn.rval==p->in.right->tn.rval )
89124418Smckusick return( p->in.left->tn.rval );
8929702Slinton return( -1 );
8939702Slinton }
8949702Slinton
makeor2(p,q,b,o)8959702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
8969702Slinton register NODE *t;
8979702Slinton NODE *f;
8989702Slinton
8999702Slinton p->in.op = OREG;
9009702Slinton f = p->in.left; /* have to free this subtree later */
9019702Slinton
9029702Slinton /* init base */
9039702Slinton switch (q->in.op) {
9049702Slinton case ICON:
9059702Slinton case REG:
9069702Slinton case OREG:
90732938Sdonn case NAME:
9089702Slinton t = q;
9099702Slinton break;
9109702Slinton
9119702Slinton case MINUS:
9129702Slinton q->in.right->tn.lval = -q->in.right->tn.lval;
9139702Slinton case PLUS:
9149702Slinton t = q->in.right;
9159702Slinton break;
9169702Slinton
9179702Slinton case INCR:
9189702Slinton case ASG MINUS:
9199702Slinton t = q->in.left;
9209702Slinton break;
9219702Slinton
9229702Slinton case UNARY MUL:
9239702Slinton t = q->in.left->in.left;
9249702Slinton break;
9259702Slinton
9269702Slinton default:
9279702Slinton cerror("illegal makeor2");
9289702Slinton }
9299702Slinton
9309702Slinton p->tn.lval = t->tn.lval;
9319702Slinton #ifndef FLEXNAMES
93232924Sdonn {
93332924Sdonn register int i;
93432924Sdonn for(i=0; i<NCHNAM; ++i)
93532924Sdonn p->in.name[i] = t->in.name[i];
93632924Sdonn }
9379702Slinton #else
9389702Slinton p->in.name = t->in.name;
9399702Slinton #endif
9409702Slinton
9419702Slinton /* init offset */
9429702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
9439702Slinton
9449702Slinton tfree(f);
9459702Slinton return;
9469702Slinton }
9479702Slinton
canaddr(p)9489702Slinton canaddr( p ) NODE *p; {
9499702Slinton register int o = p->in.op;
9509702Slinton
9519702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
9529702Slinton return(0);
9539702Slinton }
9549702Slinton
flshape(p)95532935Sdonn flshape( p ) NODE *p; {
95632935Sdonn register int o = p->in.op;
95732935Sdonn
95832935Sdonn return( o == REG || o == NAME || o == ICON ||
95932935Sdonn (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
9609702Slinton }
9619702Slinton
96232926Sdonn /* INTEMP shapes must not contain any temporary registers */
shtemp(p)9639702Slinton shtemp( p ) register NODE *p; {
96432926Sdonn int r;
96532926Sdonn
9669702Slinton if( p->in.op == STARG ) p = p->in.left;
96732926Sdonn
96832926Sdonn switch (p->in.op) {
96932926Sdonn case REG:
97032926Sdonn return( !istreg(p->tn.rval) );
97132926Sdonn case OREG:
97232926Sdonn r = p->tn.rval;
97332926Sdonn if( R2TEST(r) ) {
97432926Sdonn if( istreg(R2UPK1(r)) )
97532926Sdonn return(0);
97632926Sdonn r = R2UPK2(r);
97732926Sdonn }
97832926Sdonn return( !istreg(r) );
97932926Sdonn case UNARY MUL:
98032926Sdonn p = p->in.left;
98132926Sdonn return( p->in.op != UNARY MUL && shtemp(p) );
98232926Sdonn }
98332926Sdonn
98432926Sdonn if( optype( p->in.op ) != LTYPE ) return(0);
98532926Sdonn return(1);
9869702Slinton }
9879702Slinton
shumul(p)9889702Slinton shumul( p ) register NODE *p; {
98932935Sdonn register int o;
9909702Slinton extern int xdebug;
9919702Slinton
9929702Slinton if (xdebug) {
99332933Sdonn int val;
99432933Sdonn printf("shumul:\n");
99532933Sdonn eprint(p, 0, &val, &val);
9969702Slinton }
9979702Slinton
9989702Slinton o = p->in.op;
9999702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
10009702Slinton
10019702Slinton if( ( o == INCR || o == ASG MINUS ) &&
10029702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
10039702Slinton p->in.right->in.name[0] == '\0' )
10049702Slinton {
100517659Sralph switch (p->in.type)
10069702Slinton {
10079702Slinton case CHAR|PTR:
10089702Slinton case UCHAR|PTR:
10099702Slinton o = 1;
10109702Slinton break;
10119702Slinton
10129702Slinton case SHORT|PTR:
10139702Slinton case USHORT|PTR:
10149702Slinton o = 2;
10159702Slinton break;
10169702Slinton
10179702Slinton case INT|PTR:
10189702Slinton case UNSIGNED|PTR:
10199702Slinton case LONG|PTR:
10209702Slinton case ULONG|PTR:
10219702Slinton case FLOAT|PTR:
10229702Slinton o = 4;
10239702Slinton break;
10249702Slinton
10259702Slinton case DOUBLE|PTR:
10269702Slinton o = 8;
10279702Slinton break;
10289702Slinton
10299702Slinton default:
103017742Sralph if ( ISPTR(p->in.type) &&
103117742Sralph ISPTR(DECREF(p->in.type)) ) {
10329702Slinton o = 4;
10339702Slinton break;
10349702Slinton }
10359702Slinton else return(0);
10369702Slinton }
10379702Slinton return( p->in.right->tn.lval == o ? STARREG : 0);
10389702Slinton }
10399702Slinton
10409702Slinton return( 0 );
10419702Slinton }
10429702Slinton
adrcon(val)10439702Slinton adrcon( val ) CONSZ val; {
104424418Smckusick putchar( '$' );
10459702Slinton printf( CONFMT, val );
10469702Slinton }
10479702Slinton
conput(p)10489702Slinton conput( p ) register NODE *p; {
10499702Slinton switch( p->in.op ){
10509702Slinton
10519702Slinton case ICON:
10529702Slinton acon( p );
10539702Slinton return;
10549702Slinton
10559702Slinton case REG:
105624418Smckusick putstr( rnames[p->tn.rval] );
10579702Slinton return;
10589702Slinton
10599702Slinton default:
10609702Slinton cerror( "illegal conput" );
10619702Slinton }
10629702Slinton }
10639702Slinton
106432923Sdonn /*ARGSUSED*/
insput(p)106532924Sdonn insput( p ) NODE *p; {
10669702Slinton cerror( "insput" );
10679702Slinton }
10689702Slinton
upput(p,size)106932928Sdonn upput( p, size ) NODE *p; int size; {
107032928Sdonn if( size == SZLONG && p->in.op == REG ) {
107132928Sdonn putstr( rnames[p->tn.rval + 1] );
107232928Sdonn return;
107332928Sdonn }
10749702Slinton cerror( "upput" );
10759702Slinton }
10769702Slinton
adrput(p)10779702Slinton adrput( p ) register NODE *p; {
10789702Slinton register int r;
10799702Slinton /* output an address, with offsets, from p */
10809702Slinton
10819702Slinton if( p->in.op == FLD ){
10829702Slinton p = p->in.left;
10839702Slinton }
10849702Slinton switch( p->in.op ){
10859702Slinton
10869702Slinton case NAME:
10879702Slinton acon( p );
10889702Slinton return;
10899702Slinton
10909702Slinton case ICON:
10919702Slinton /* addressable value of the constant */
109224418Smckusick putchar( '$' );
10939702Slinton acon( p );
10949702Slinton return;
10959702Slinton
10969702Slinton case REG:
109724418Smckusick putstr( rnames[p->tn.rval] );
10989702Slinton return;
10999702Slinton
11009702Slinton case OREG:
11019702Slinton r = p->tn.rval;
11029702Slinton if( R2TEST(r) ){ /* double indexing */
11039702Slinton register int flags;
11049702Slinton
11059702Slinton flags = R2UPK3(r);
110624418Smckusick if( flags & 1 ) putchar('*');
110724418Smckusick if( flags & 4 ) putchar('-');
11089702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
11099702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
111024418Smckusick if( flags & 2 ) putchar('+');
11119702Slinton printf( "[%s]", rnames[R2UPK2(r)] );
11129702Slinton return;
11139702Slinton }
11149702Slinton if( r == AP ){ /* in the argument region */
111532925Sdonn if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
11169702Slinton printf( CONFMT, p->tn.lval );
111724418Smckusick putstr( "(ap)" );
11189702Slinton return;
11199702Slinton }
11209702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
11219702Slinton printf( "(%s)", rnames[p->tn.rval] );
11229702Slinton return;
11239702Slinton
11249702Slinton case UNARY MUL:
11259702Slinton /* STARNM or STARREG found */
11269702Slinton if( tshape(p, STARNM) ) {
112724418Smckusick putchar( '*' );
11289702Slinton adrput( p->in.left);
11299702Slinton }
11309702Slinton else { /* STARREG - really auto inc or dec */
11319702Slinton register NODE *q;
11329702Slinton
113317659Sralph q = p->in.left;
113417742Sralph if( q->in.right->tn.lval != tlen(p) )
113517742Sralph cerror("adrput: bad auto-increment/decrement");
113617659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
113717659Sralph rnames[q->in.left->tn.rval],
113817659Sralph (q->in.op==INCR ? "+" : "") );
11399702Slinton p->in.op = OREG;
114017659Sralph p->tn.rval = q->in.left->tn.rval;
114117659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
11429702Slinton #ifndef FLEXNAMES
11439702Slinton p->in.name[0] = '\0';
11449702Slinton #else
11459702Slinton p->in.name = "";
11469702Slinton #endif
11479702Slinton tfree(q);
11489702Slinton }
11499702Slinton return;
11509702Slinton
11519702Slinton default:
11529702Slinton cerror( "illegal address" );
11539702Slinton return;
11549702Slinton
11559702Slinton }
11569702Slinton
11579702Slinton }
11589702Slinton
acon(p)11599702Slinton acon( p ) register NODE *p; { /* print out a constant */
11609702Slinton
116132935Sdonn if( p->in.name[0] == '\0' )
11629702Slinton printf( CONFMT, p->tn.lval);
116332935Sdonn else {
11649702Slinton #ifndef FLEXNAMES
11659702Slinton printf( "%.8s", p->in.name );
11669702Slinton #else
116724418Smckusick putstr( p->in.name );
11689702Slinton #endif
116932935Sdonn if( p->tn.lval != 0 ) {
117032935Sdonn putchar( '+' );
117132935Sdonn printf( CONFMT, p->tn.lval );
117232935Sdonn }
11739702Slinton }
11749702Slinton }
11759702Slinton
genscall(p,cookie)11769702Slinton genscall( p, cookie ) register NODE *p; {
11779702Slinton /* structure valued call */
11789702Slinton return( gencall( p, cookie ) );
11799702Slinton }
11809702Slinton
11819702Slinton /* tbl */
11829702Slinton int gc_numbytes;
11839702Slinton /* tbl */
11849702Slinton
118532924Sdonn /*ARGSUSED*/
gencall(p,cookie)11869702Slinton gencall( p, cookie ) register NODE *p; {
11879702Slinton /* generate the call given by p */
118816418Sralph register NODE *p1;
118932935Sdonn register int temp, temp1;
119032935Sdonn register int m;
11919702Slinton
11929702Slinton if( p->in.right ) temp = argsize( p->in.right );
11939702Slinton else temp = 0;
11949702Slinton
11959702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
11969702Slinton /* set aside room for structure return */
11979702Slinton
11989702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
11999702Slinton else temp1 = temp;
12009702Slinton }
12019702Slinton
12029702Slinton if( temp > maxargs ) maxargs = temp;
12039702Slinton SETOFF(temp1,4);
12049702Slinton
12059702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */
120616418Sralph genargs( p->in.right );
12079702Slinton }
12089702Slinton
12099702Slinton p1 = p->in.left;
12109702Slinton if( p1->in.op != ICON ){
12119702Slinton if( p1->in.op != REG ){
12129702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
12139702Slinton if( p1->in.op != NAME ){
12149702Slinton order( p1, INAREG );
12159702Slinton }
12169702Slinton }
12179702Slinton }
12189702Slinton }
12199702Slinton
12209702Slinton /* tbl
12219702Slinton setup gc_numbytes so reference to ZC works */
12229702Slinton
12239702Slinton gc_numbytes = temp&(0x3ff);
12249702Slinton /* tbl */
12259702Slinton
12269702Slinton p->in.op = UNARY CALL;
12279702Slinton m = match( p, INTAREG|INTBREG );
12289702Slinton
12299702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */
12309702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */
12319702Slinton if (temp >= 1024)
12329702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff)));
12339702Slinton
12349702Slinton return(m != MDONE);
12359702Slinton }
12369702Slinton
12379702Slinton /* tbl */
12389702Slinton char *
12399702Slinton ccbranches[] = {
124032935Sdonn "eql",
124132935Sdonn "neq",
124232935Sdonn "leq",
124332935Sdonn "lss",
124432935Sdonn "geq",
124532935Sdonn "gtr",
124632935Sdonn "lequ",
124732935Sdonn "lssu",
124832935Sdonn "gequ",
124932935Sdonn "gtru",
12509702Slinton };
12519702Slinton /* tbl */
12529702Slinton
125332924Sdonn /*ARGSUSED*/
cbgen(o,lab,mode)12549702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
12559702Slinton
125632935Sdonn if( o != 0 && ( o < EQ || o > UGT ) )
125732935Sdonn cerror( "bad conditional branch: %s", opst[o] );
125832935Sdonn printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
12599702Slinton }
12609702Slinton
nextcook(p,cookie)12619702Slinton nextcook( p, cookie ) NODE *p; {
12629702Slinton /* we have failed to match p with cookie; try another */
12639702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */
12649702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
12659702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
12669702Slinton return( FORREW );
12679702Slinton }
12689702Slinton
126932924Sdonn /*ARGSUSED*/
lastchance(p,cook)12709702Slinton lastchance( p, cook ) NODE *p; {
12719702Slinton /* forget it! */
12729702Slinton return(0);
12739702Slinton }
12749702Slinton
optim2(p)12759702Slinton optim2( p ) register NODE *p; {
12769702Slinton /* do local tree transformations and optimizations */
12779702Slinton
127832929Sdonn int o;
127932932Sdonn int i, mask;
128016181Sralph register NODE *l, *r;
12819702Slinton
128232929Sdonn switch( o = p->in.op ) {
12839702Slinton
128432944Sdonn case ASG PLUS:
128532944Sdonn case ASG MINUS:
128632944Sdonn case ASG MUL:
128732944Sdonn case ASG OR:
128832944Sdonn /* simple ASG OPSIMP -- reduce range of constant rhs */
128932944Sdonn l = p->in.left;
129032944Sdonn r = p->in.right;
129132944Sdonn if( tlen(l) < SZINT/SZCHAR &&
129232944Sdonn r->in.op==ICON && r->in.name[0]==0 ){
129332944Sdonn mask = (1 << tlen(l) * SZCHAR) - 1;
129432944Sdonn if( r->tn.lval & (mask & ~(mask >> 1)) )
129532944Sdonn r->tn.lval |= ~mask;
129632944Sdonn else
129732944Sdonn r->tn.lval &= mask;
129832944Sdonn }
129932944Sdonn break;
130032944Sdonn
13019702Slinton case AND:
130219933Smckusick /* commute L and R to eliminate complements and constants */
130316181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
130416181Sralph l->in.op == COMPL ) {
13059702Slinton p->in.left = p->in.right;
130616181Sralph p->in.right = l;
13079702Slinton }
130832944Sdonn /* fall through */
130932944Sdonn
13109702Slinton case ASG AND:
131132944Sdonn /* change meaning of AND to ~R&L - bic on pdp11/vax */
13129702Slinton r = p->in.right;
131332931Sdonn if( r->in.op==ICON && r->in.name[0]==0 ) {
131432931Sdonn /* check for degenerate operations */
131532931Sdonn l = p->in.left;
131632932Sdonn mask = (1 << tlen(l) * SZCHAR) - 1;
131732944Sdonn if( o == ASG AND || ISUNSIGNED(r->in.type) ) {
131832944Sdonn i = ~r->tn.lval & mask;
131932938Sdonn if( i == 0 ) {
132032944Sdonn /* redundant mask */
132132932Sdonn r->in.op = FREE;
132232932Sdonn ncopy(p, l);
132332932Sdonn l->in.op = FREE;
132432932Sdonn break;
132532932Sdonn }
132632938Sdonn else if( i == mask )
132732944Sdonn /* all bits masked off */
132832932Sdonn goto zero;
132932944Sdonn r->tn.lval = i;
133032944Sdonn if( tlen(l) < SZINT/SZCHAR ){
133132944Sdonn /* sign extend */
133232944Sdonn if( r->tn.lval & (mask & ~(mask >> 1)) )
133332944Sdonn r->tn.lval |= ~mask;
133432944Sdonn else
133532944Sdonn r->tn.lval &= mask;
133632944Sdonn }
133732938Sdonn break;
133832932Sdonn }
133932932Sdonn else if( r->tn.lval == mask &&
134032932Sdonn tlen(l) < SZINT/SZCHAR ) {
134132944Sdonn /* use movz instead of bic */
134232932Sdonn r->in.op = SCONV;
134332932Sdonn r->in.left = l;
134432932Sdonn r->in.right = 0;
134532932Sdonn r->in.type = ENUNSIGN(l->in.type);
134632932Sdonn r->in.su = l->in.su > 1 ? l->in.su : 1;
134732932Sdonn ncopy(p, r);
134832932Sdonn p->in.left = r;
134932932Sdonn p->in.type = INT;
135032931Sdonn break;
135132931Sdonn }
135232931Sdonn /* complement constant */
13539702Slinton r->tn.lval = ~r->tn.lval;
13549702Slinton }
13559702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */
13569702Slinton r->in.op = FREE;
13579702Slinton p->in.right = r->in.left;
13589702Slinton }
13599702Slinton else { /* insert complement node */
136016181Sralph p->in.right = l = talloc();
136116181Sralph l->in.op = COMPL;
136216181Sralph l->in.rall = NOPREF;
136316181Sralph l->in.type = r->in.type;
136416181Sralph l->in.left = r;
136516181Sralph l->in.right = NULL;
13669702Slinton }
13679702Slinton break;
13689702Slinton
136916181Sralph case SCONV:
137019933Smckusick l = p->in.left;
137117742Sralph #if defined(FORT) || defined(SPRECC)
137216573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE ||
137319933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE )
137419933Smckusick return;
137516573Sralph #else
137619933Smckusick if( mixtypes(p, l) ) return;
137716573Sralph #endif
137832938Sdonn if( l->in.op == PCONV )
137925751Sdonn return;
138032938Sdonn if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
138132938Sdonn l->in.type != INT && l->in.type != UNSIGNED )
138232938Sdonn return;
138325751Sdonn
138419933Smckusick /* Only trust it to get it right if the size is the same */
138519933Smckusick if( tlen(p) != tlen(l) )
138619933Smckusick return;
138716181Sralph
138816181Sralph /* clobber conversion */
138919933Smckusick if( l->in.op != FLD )
139016181Sralph l->in.type = p->in.type;
139116181Sralph ncopy( p, l );
139216181Sralph l->in.op = FREE;
139319933Smckusick
139416181Sralph break;
139516181Sralph
139624418Smckusick case ASSIGN:
139724418Smckusick /*
139824418Smckusick * Conversions are equivalent to assignments;
139924418Smckusick * when the two operations are combined,
140024418Smckusick * we can sometimes zap the conversion.
140124418Smckusick */
140224418Smckusick r = p->in.right;
140324418Smckusick l = p->in.left;
140424418Smckusick if ( r->in.op == SCONV &&
140524418Smckusick !mixtypes(l, r) &&
140632922Sdonn l->in.op != FLD &&
140724418Smckusick tlen(l) == tlen(r) ) {
140824418Smckusick p->in.right = r->in.left;
140924418Smckusick r->in.op = FREE;
141024418Smckusick }
141124418Smckusick break;
141224418Smckusick
141332929Sdonn case ULE:
141432929Sdonn case ULT:
141532929Sdonn case UGE:
141632929Sdonn case UGT:
141732931Sdonn p->in.op -= (UGE-GE);
141832931Sdonn if( degenerate(p) )
141932931Sdonn break;
142032931Sdonn p->in.op += (UGE-GE);
142132931Sdonn break;
142232931Sdonn
142332929Sdonn case EQ:
142432929Sdonn case NE:
142532929Sdonn case LE:
142632929Sdonn case LT:
142732929Sdonn case GE:
142832929Sdonn case GT:
142932938Sdonn if( p->in.left->in.op == SCONV &&
143032938Sdonn p->in.right->in.op == SCONV ) {
143132938Sdonn l = p->in.left;
143232938Sdonn r = p->in.right;
143332938Sdonn if( l->in.type == DOUBLE &&
143432938Sdonn l->in.left->in.type == FLOAT &&
143532938Sdonn r->in.left->in.type == FLOAT ) {
143632938Sdonn /* nuke the conversions */
143732938Sdonn p->in.left = l->in.left;
143832938Sdonn p->in.right = r->in.left;
143932938Sdonn l->in.op = FREE;
144032938Sdonn r->in.op = FREE;
144132938Sdonn }
144232938Sdonn /* more? */
144332938Sdonn }
144432931Sdonn (void) degenerate(p);
144532931Sdonn break;
144632931Sdonn
144732931Sdonn case DIV:
144832931Sdonn if( p->in.right->in.op == ICON &&
144932931Sdonn p->in.right->tn.name[0] == '\0' &&
145032931Sdonn ISUNSIGNED(p->in.right->in.type) &&
145132931Sdonn (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
145232931Sdonn /* easy to do here, harder to do in zzzcode() */
145332931Sdonn p->in.op = UGE;
145432929Sdonn break;
145532931Sdonn }
145632931Sdonn case MOD:
145732931Sdonn case ASG DIV:
145832931Sdonn case ASG MOD:
145932931Sdonn /*
146032931Sdonn * optimize DIV and MOD
146132931Sdonn *
146232931Sdonn * basically we spot UCHAR and USHORT and try to do them
146332931Sdonn * as signed ints... apparently div+mul+sub is always
146432931Sdonn * faster than ediv for finding MOD on the VAX, when
146532931Sdonn * full unsigned MOD isn't needed.
146632931Sdonn *
146732931Sdonn * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
146832931Sdonn * are faster for unsigned dividend and a constant divisor
146932931Sdonn * in the right range (.5 to 1 of dividend's range for the
147032931Sdonn * first, .333+ to .5 for the second). full unsigned is
147132931Sdonn * already done cmp+sub in the appropriate case; the
147232931Sdonn * other cases are less common and require more ambition.
147332931Sdonn */
147432931Sdonn if( degenerate(p) )
147532929Sdonn break;
147632931Sdonn l = p->in.left;
147732931Sdonn r = p->in.right;
147832931Sdonn if( !ISUNSIGNED(r->in.type) ||
147932931Sdonn tlen(l) >= SZINT/SZCHAR ||
148032931Sdonn !(tlen(r) < SZINT/SZCHAR ||
148132931Sdonn (r->in.op == ICON && r->tn.name[0] == '\0')) )
148232929Sdonn break;
148332931Sdonn if( r->in.op == ICON )
148432931Sdonn r->tn.type = INT;
148532931Sdonn else {
148632931Sdonn NODE *t = talloc();
148732931Sdonn t->in.left = r;
148832931Sdonn r = t;
148932931Sdonn r->in.op = SCONV;
149032931Sdonn r->in.type = INT;
149132931Sdonn r->in.right = 0;
149232931Sdonn p->in.right = r;
149332931Sdonn }
149432931Sdonn if( o == DIV || o == MOD ) {
149532931Sdonn NODE *t = talloc();
149632931Sdonn t->in.left = l;
149732931Sdonn l = t;
149832931Sdonn l->in.op = SCONV;
149932931Sdonn l->in.type = INT;
150032931Sdonn l->in.right = 0;
150132931Sdonn p->in.left = l;
150232931Sdonn }
150332931Sdonn /* handle asgops in table */
150432931Sdonn break;
150532931Sdonn
150632931Sdonn case RS:
150732931Sdonn case ASG RS:
150832931Sdonn case LS:
150932931Sdonn case ASG LS:
151032931Sdonn /* pick up degenerate shifts */
151132931Sdonn l = p->in.left;
151232931Sdonn r = p->in.right;
151332931Sdonn if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
151432929Sdonn break;
151532929Sdonn i = r->tn.lval;
151632931Sdonn if( i < 0 )
151732931Sdonn /* front end 'fixes' this? */
151832931Sdonn if( o == LS || o == ASG LS )
151932931Sdonn o += (RS-LS);
152032931Sdonn else
152132931Sdonn o += (LS-RS);
152232931Sdonn if( (o == RS || o == ASG RS) &&
152332931Sdonn !ISUNSIGNED(l->in.type) )
152432931Sdonn /* can't optimize signed right shifts */
152532929Sdonn break;
152632935Sdonn if( o == LS ) {
152732935Sdonn if( i < SZINT )
152832935Sdonn break;
152932935Sdonn }
153032935Sdonn else {
153132935Sdonn if( i < tlen(l) * SZCHAR )
153232935Sdonn break;
153332935Sdonn }
153432931Sdonn zero:
153532931Sdonn if( !asgop( o ) )
153632931Sdonn if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
153732931Sdonn /* no side effects */
153832932Sdonn tfree(l);
153932931Sdonn ncopy(p, r);
154032931Sdonn r->in.op = FREE;
154132931Sdonn p->tn.lval = 0;
154232931Sdonn }
154332931Sdonn else {
154432931Sdonn p->in.op = COMOP;
154532932Sdonn r->tn.lval = 0;
154632931Sdonn }
154732931Sdonn else {
154832931Sdonn p->in.op = ASSIGN;
154932931Sdonn r->tn.lval = 0;
155032929Sdonn }
155132931Sdonn break;
155232931Sdonn }
155332931Sdonn }
155432931Sdonn
degenerate(p)155532931Sdonn degenerate(p) register NODE *p; {
155632931Sdonn int o;
155732931Sdonn int result, i;
155832931Sdonn int lower, upper;
155932931Sdonn register NODE *l, *r;
156032931Sdonn
156132931Sdonn /*
156232931Sdonn * try to keep degenerate comparisons with constants
156332931Sdonn * out of the table.
156432931Sdonn */
156532931Sdonn r = p->in.right;
156632931Sdonn l = p->in.left;
156732931Sdonn if( r->in.op != ICON ||
156832931Sdonn r->tn.name[0] != '\0' ||
156932931Sdonn tlen(l) >= tlen(r) )
157032931Sdonn return (0);
157132931Sdonn switch( l->in.type ) {
157232931Sdonn case CHAR:
157332931Sdonn lower = -(1 << SZCHAR - 1);
157432931Sdonn upper = (1 << SZCHAR - 1) - 1;
157532931Sdonn break;
157632931Sdonn case UCHAR:
157732931Sdonn lower = 0;
157832931Sdonn upper = (1 << SZCHAR) - 1;
157932931Sdonn break;
158032931Sdonn case SHORT:
158132931Sdonn lower = -(1 << SZSHORT - 1);
158232931Sdonn upper = (1 << SZSHORT - 1) - 1;
158332931Sdonn break;
158432931Sdonn case USHORT:
158532931Sdonn lower = 0;
158632931Sdonn upper = (1 << SZSHORT) - 1;
158732931Sdonn break;
158832931Sdonn default:
158932932Sdonn cerror("unsupported type in degenerate()");
159032931Sdonn }
159132931Sdonn i = r->tn.lval;
159232931Sdonn switch( o = p->in.op ) {
159332931Sdonn case DIV:
159432931Sdonn case ASG DIV:
159532931Sdonn case MOD:
159632931Sdonn case ASG MOD:
159732931Sdonn /* DIV and MOD work like EQ */
159832931Sdonn case EQ:
159932931Sdonn case NE:
160032931Sdonn if( lower == 0 && (unsigned) i > upper )
160132931Sdonn result = o == NE;
160232931Sdonn else if( i < lower || i > upper )
160332931Sdonn result = o == NE;
160432931Sdonn else
160532931Sdonn return (0);
160632931Sdonn break;
160732931Sdonn case LT:
160832931Sdonn case GE:
160932931Sdonn if( lower == 0 && (unsigned) i > upper )
161032931Sdonn result = o == LT;
161132931Sdonn else if( i <= lower )
161232931Sdonn result = o != LT;
161332931Sdonn else if( i > upper )
161432931Sdonn result = o == LT;
161532931Sdonn else
161632931Sdonn return (0);
161732931Sdonn break;
161832931Sdonn case LE:
161932931Sdonn case GT:
162032931Sdonn if( lower == 0 && (unsigned) i >= upper )
162132931Sdonn result = o == LE;
162232931Sdonn else if( i < lower )
162332931Sdonn result = o != LE;
162432931Sdonn else if( i >= upper )
162532931Sdonn result = o == LE;
162632931Sdonn else
162732931Sdonn return (0);
162832931Sdonn break;
162932931Sdonn default:
163032931Sdonn cerror("unknown op in degenerate()");
163132931Sdonn }
163232931Sdonn
163332931Sdonn if( o == MOD || o == ASG MOD ) {
163432931Sdonn r->in.op = FREE;
163532931Sdonn ncopy(p, l);
163632931Sdonn l->in.op = FREE;
163732931Sdonn }
163832931Sdonn else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
163932931Sdonn /* no side effects */
164032932Sdonn tfree(l);
164132931Sdonn ncopy(p, r);
164232931Sdonn r->in.op = FREE;
164332931Sdonn p->tn.lval = result;
164432931Sdonn }
164532931Sdonn else {
164632931Sdonn if( o == ASG DIV )
164732931Sdonn p->in.op = ASSIGN;
164832929Sdonn else {
164932929Sdonn p->in.op = COMOP;
165032929Sdonn r->tn.type = INT;
165132929Sdonn }
165232931Sdonn r->tn.lval = result;
16539702Slinton }
165432931Sdonn if( logop(o) )
165532931Sdonn p->in.type = INT;
165632931Sdonn
165732931Sdonn return (1);
16589702Slinton }
16599702Slinton
16609702Slinton /* added by jwf */
16619702Slinton struct functbl {
16629702Slinton int fop;
16639702Slinton TWORD ftype;
16649702Slinton char *func;
16659702Slinton } opfunc[] = {
16669702Slinton DIV, TANY, "udiv",
16679702Slinton MOD, TANY, "urem",
166817715Sralph ASG DIV, TANY, "audiv",
166917715Sralph ASG MOD, TANY, "aurem",
16709702Slinton 0, 0, 0 };
16719702Slinton
hardops(p)16729702Slinton hardops(p) register NODE *p; {
16739702Slinton /* change hard to do operators into function calls. */
16749702Slinton register NODE *q;
16759702Slinton register struct functbl *f;
16769702Slinton register o;
167717742Sralph NODE *old,*temp;
16789702Slinton
16799702Slinton o = p->in.op;
168017742Sralph if( ! (optype(o)==BITYPE &&
168117742Sralph (ISUNSIGNED(p->in.left->in.type) ||
168217742Sralph ISUNSIGNED(p->in.right->in.type))) )
168317742Sralph return;
16849702Slinton
16859702Slinton for( f=opfunc; f->fop; f++ ) {
16869702Slinton if( o==f->fop ) goto convert;
16879702Slinton }
16889702Slinton return;
16899702Slinton
16909702Slinton convert:
169132931Sdonn if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
169232928Sdonn /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
169332928Sdonn /* save a subroutine call -- use at most 5 instructions */
169432928Sdonn return;
169532931Sdonn if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
169632931Sdonn /* optim2() will modify the op into an ordinary int op */
169732931Sdonn return;
16989702Slinton if( asgop( o ) ) {
169917742Sralph old = NIL;
170017715Sralph switch( p->in.left->in.op ){
170117742Sralph case FLD:
170217742Sralph q = p->in.left->in.left;
170317742Sralph /*
170417742Sralph * rewrite (lval.fld /= rval); as
170517742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
170617742Sralph * else the compiler will evaluate lval twice.
170717742Sralph */
170817742Sralph if( q->in.op == UNARY MUL ){
170917742Sralph /* first allocate a temp storage */
171017742Sralph temp = talloc();
171117742Sralph temp->in.op = OREG;
171217742Sralph temp->tn.rval = TMPREG;
171317742Sralph temp->tn.lval = BITOOR(freetemp(1));
171417742Sralph temp->in.type = INCREF(p->in.type);
171517742Sralph #ifdef FLEXNAMES
171617742Sralph temp->in.name = "";
171717742Sralph #else
171817742Sralph temp->in.name[0] = '\0';
171917742Sralph #endif
172017742Sralph old = q->in.left;
172117742Sralph q->in.left = temp;
172217742Sralph }
172317742Sralph /* fall thru ... */
172417742Sralph
172517715Sralph case REG:
172617715Sralph case NAME:
172717715Sralph case OREG:
172817715Sralph /* change ASG OP to a simple OP */
172917715Sralph q = talloc();
173017715Sralph q->in.op = NOASG p->in.op;
173117715Sralph q->in.rall = NOPREF;
173217715Sralph q->in.type = p->in.type;
173317715Sralph q->in.left = tcopy(p->in.left);
173417715Sralph q->in.right = p->in.right;
173517715Sralph p->in.op = ASSIGN;
173617715Sralph p->in.right = q;
173717715Sralph p = q;
173817715Sralph f -= 2; /* Note: this depends on the table order */
173917742Sralph /* on the right side only - replace *temp with
174017742Sralph *(temp = &lval), build the assignment node */
174117742Sralph if( old ){
174217742Sralph temp = q->in.left->in.left; /* the "*" node */
174317742Sralph q = talloc();
174417742Sralph q->in.op = ASSIGN;
174517742Sralph q->in.left = temp->in.left;
174617742Sralph q->in.right = old;
174717742Sralph q->in.type = old->in.type;
174817742Sralph #ifdef FLEXNAMES
174917742Sralph q->in.name = "";
175017742Sralph #else
175117742Sralph q->in.name[0] = '\0';
175217742Sralph #endif
175317742Sralph temp->in.left = q;
175417742Sralph }
175517715Sralph break;
17569702Slinton
175717715Sralph case UNARY MUL:
175817715Sralph /* avoid doing side effects twice */
175917715Sralph q = p->in.left;
176017715Sralph p->in.left = q->in.left;
176117715Sralph q->in.op = FREE;
176217715Sralph break;
176317715Sralph
176417715Sralph default:
176517715Sralph cerror( "hardops: can't compute & LHS" );
176617715Sralph }
176717742Sralph }
176817715Sralph
17699702Slinton /* build comma op for args to function */
17709702Slinton q = talloc();
17719702Slinton q->in.op = CM;
17729702Slinton q->in.rall = NOPREF;
17739702Slinton q->in.type = INT;
17749702Slinton q->in.left = p->in.left;
17759702Slinton q->in.right = p->in.right;
17769702Slinton p->in.op = CALL;
17779702Slinton p->in.right = q;
17789702Slinton
17799702Slinton /* put function name in left node of call */
17809702Slinton p->in.left = q = talloc();
17819702Slinton q->in.op = ICON;
17829702Slinton q->in.rall = NOPREF;
17839702Slinton q->in.type = INCREF( FTN + p->in.type );
17849702Slinton #ifndef FLEXNAMES
17859702Slinton strcpy( q->in.name, f->func );
17869702Slinton #else
17879702Slinton q->in.name = f->func;
17889702Slinton #endif
17899702Slinton q->tn.lval = 0;
17909702Slinton q->tn.rval = 0;
17919702Slinton
17929702Slinton }
17939702Slinton
zappost(p)179417742Sralph zappost(p) NODE *p; {
179517742Sralph /* look for ++ and -- operators and remove them */
179617742Sralph
179732935Sdonn register int o, ty;
179817742Sralph register NODE *q;
179917742Sralph o = p->in.op;
180017742Sralph ty = optype( o );
180117742Sralph
180217742Sralph switch( o ){
180317742Sralph
180417742Sralph case INCR:
180517742Sralph case DECR:
180617742Sralph q = p->in.left;
180717742Sralph p->in.right->in.op = FREE; /* zap constant */
180817742Sralph ncopy( p, q );
180917742Sralph q->in.op = FREE;
181017742Sralph return;
181117742Sralph
181217742Sralph }
181317742Sralph
181417742Sralph if( ty == BITYPE ) zappost( p->in.right );
181517742Sralph if( ty != LTYPE ) zappost( p->in.left );
181617742Sralph }
181717742Sralph
fixpre(p)181817742Sralph fixpre(p) NODE *p; {
181917742Sralph
182032935Sdonn register int o, ty;
182117742Sralph o = p->in.op;
182217742Sralph ty = optype( o );
182317742Sralph
182417742Sralph switch( o ){
182517742Sralph
182617742Sralph case ASG PLUS:
182717742Sralph p->in.op = PLUS;
182817742Sralph break;
182917742Sralph case ASG MINUS:
183017742Sralph p->in.op = MINUS;
183117742Sralph break;
183217742Sralph }
183317742Sralph
183417742Sralph if( ty == BITYPE ) fixpre( p->in.right );
183517742Sralph if( ty != LTYPE ) fixpre( p->in.left );
183617742Sralph }
183717742Sralph
183832935Sdonn /*ARGSUSED*/
addroreg(l)183932935Sdonn NODE * addroreg(l) NODE *l;
184032935Sdonn /* OREG was built in clocal()
184132935Sdonn * for an auto or formal parameter
184232935Sdonn * now its address is being taken
184332935Sdonn * local code must unwind it
184432935Sdonn * back to PLUS/MINUS REG ICON
184532935Sdonn * according to local conventions
184632935Sdonn */
184732935Sdonn {
184832935Sdonn cerror("address of OREG taken");
184932935Sdonn /*NOTREACHED*/
185032935Sdonn }
185132935Sdonn
185232935Sdonn
185332935Sdonn
185432935Sdonn # ifndef ONEPASS
main(argc,argv)185532935Sdonn main( argc, argv ) char *argv[]; {
185632935Sdonn return( mainp2( argc, argv ) );
185732935Sdonn }
185832935Sdonn # endif
185932935Sdonn
strip(p)186024418Smckusick strip(p) register NODE *p; {
186124418Smckusick NODE *q;
186224418Smckusick
186324418Smckusick /* strip nodes off the top when no side effects occur */
186424418Smckusick for( ; ; ) {
186524418Smckusick switch( p->in.op ) {
186624418Smckusick case SCONV: /* remove lint tidbits */
186724418Smckusick q = p->in.left;
186824418Smckusick ncopy( p, q );
186924418Smckusick q->in.op = FREE;
187024418Smckusick break;
187124418Smckusick /* could probably add a few more here */
187224418Smckusick default:
187324418Smckusick return;
187424418Smckusick }
187524418Smckusick }
187624418Smckusick }
187724418Smckusick
myreader(p)18789702Slinton myreader(p) register NODE *p; {
187924418Smckusick strip( p ); /* strip off operations with no side effects */
188017742Sralph canon( p ); /* expands r-vals for fields */
18819702Slinton walkf( p, hardops ); /* convert ops to function calls */
18829702Slinton walkf( p, optim2 );
18839702Slinton }
1884