too many sccsid lines
[unix-history] / usr / src / old / pcc / ccom.tahoe / local2.c
CommitLineData
f2b49199
SL
1#ifndef lint
2static char sccsid[] = "@(#)local2.c 1.1 (Berkeley) %G%";
3#endif
4
5# include "mfile2"
6# include "ctype.h"
7# ifdef FORT
8int ftlab1, ftlab2;
9# endif
10/* a lot of the machine dependent parts of the second pass */
11
12# define BITMASK(n) ((1L<<n)-1)
13
14# ifndef ONEPASS
15where(c){
16 fprintf( stderr, "%s, line %d: ", filename, lineno );
17 }
18# endif
19
20lineid( l, fn ) char *fn; {
21 /* identify line l and file fn */
22 printf( "# line %d, file %s\n", l, fn );
23 }
24
25int ent_mask;
26
27eobl2(){
28 register OFFSZ spoff; /* offset from stack pointer */
29#ifndef FORT
30 extern int ftlab1, ftlab2;
31#endif
32
33 spoff = maxoff;
34 spoff /= SZCHAR;
35 SETOFF(spoff,4);
36#ifdef FORT
37#ifndef FLEXNAMES
38 printf( " .set .F%d,%d\n", ftnno, spoff );
39#else
40 /* SHOULD BE L%d ... ftnno but must change pc/f77 */
41 printf( " .set LF%d,%d\n", ftnno, spoff );
42#endif
43 printf( " .set LWM%d,0x%x\n", ftnno, ent_mask&0x1ffc|0x1000);
44#else
45 printf( " .set L%d,0x%x\n", ftnno, ent_mask&0x1ffc);
46 printf( "L%d:\n", ftlab1);
47 if( maxoff > AUTOINIT )
48 printf( " subl3 $%d,fp,sp\n", spoff);
49 printf( " jbr L%d\n", ftlab2);
50#endif
51 ent_mask = 0;
52 maxargs = -1;
53 }
54
55struct hoptab { int opmask; char * opstring; } ioptab[] = {
56
57 PLUS, "add",
58 MINUS, "sub",
59 MUL, "mul",
60 DIV, "div",
61 MOD, "div",
62 OR, "or",
63 ER, "xor",
64 AND, "and",
65 -1, "" };
66
67hopcode( f, o ){
68 /* output the appropriate string from the above table */
69
70 register struct hoptab *q;
71
72 if(asgop(o))
73 o = NOASG o;
74 for( q = ioptab; q->opmask>=0; ++q ){
75 if( q->opmask == o ){
76 if(f == 'E')
77 printf( "e%s", q->opstring);
78 else
79 printf( "%s%c", q->opstring, tolower(f));
80 return;
81 }
82 }
83 cerror( "no hoptab for %s", opst[o] );
84 }
85
86char *
87rnames[] = { /* keyed to register number tokens */
88
89 "r0", "r1",
90 "r2", "r3", "r4", "r5",
91 "r6", "r7", "r8", "r9", "r10", "r11",
92 "r12", "fp", "sp", "pc",
93 };
94
95/* output register name and update entry mask */
96char *
97rname(r)
98 register int r;
99{
100
101 ent_mask |= 1<<r;
102 return(rnames[r]);
103}
104
105int rstatus[] = {
106 SAREG|STAREG, SAREG|STAREG,
107 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
108 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
109 SAREG, SAREG, SAREG, SAREG,
110 };
111
112tlen(p) NODE *p;
113{
114 switch(p->in.type) {
115 case CHAR:
116 case UCHAR:
117 return(1);
118
119 case SHORT:
120 case USHORT:
121 return(2);
122
123 case DOUBLE:
124 return(8);
125
126 default:
127 return(4);
128 }
129}
130
131prtype(n) NODE *n;
132{
133 switch (n->in.type)
134 {
135
136 case DOUBLE:
137 printf("d");
138 return;
139
140 case FLOAT:
141 printf("f");
142 return;
143
144 case INT:
145 case UNSIGNED:
146 printf("l");
147 return;
148
149 case SHORT:
150 case USHORT:
151 printf("w");
152 return;
153
154 case CHAR:
155 case UCHAR:
156 printf("b");
157 return;
158
159 default:
160 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
161 else {
162 printf("l");
163 return;
164 }
165 }
166}
167
168zzzcode( p, c ) register NODE *p; {
169 register int m;
170 int val;
171 switch( c ){
172
173 case 'N': /* logical ops, turned into 0-1 */
174 /* use register given by register 1 */
175 cbgen( 0, m=getlab(), 'I' );
176 deflab( p->bn.label );
177 printf( " clrl %s\n", rname(getlr( p, '1' )->tn.rval) );
178 deflab( m );
179 return;
180
181 case 'P':
182 cbgen( p->in.op, p->bn.label, c );
183 return;
184
185 case 'A': /* assignment and load (integer only) */
186 {
187 register NODE *l, *r;
188
189 if (xdebug) eprint(p, 0, &val, &val);
190 r = getlr(p, 'R');
191 if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL) {
192 l = resc;
193 l->in.type = INT;
194 } else
195 l = getlr(p, 'L');
196 if(r->in.type==FLOAT || r->in.type==DOUBLE
197 || l->in.type==FLOAT || l->in.type==DOUBLE)
198 cerror("float in ZA");
199 if (r->in.op == ICON)
200 if(r->in.name[0] == '\0') {
201 if (r->tn.lval == 0) {
202 printf("clr");
203 prtype(l);
204 printf(" ");
205 adrput(l);
206 return;
207 }
208 if (r->tn.lval < 0 && r->tn.lval >= -63) {
209 printf("mneg");
210 prtype(l);
211 r->tn.lval = -r->tn.lval;
212 goto ops;
213 }
214#ifdef MOVAFASTER
215 } else {
216 printf("movab");
217 printf(" ");
218 acon(r);
219 printf(",");
220 adrput(l);
221 return;
222#endif MOVAFASTER
223 }
224
225 if (l->in.op == REG) {
226 if( tlen(l) < tlen(r) ) {
227 !ISUNSIGNED(l->in.type)?
228 printf("cvt"):
229 printf("movz");
230 prtype(l);
231 printf("l");
232 goto ops;
233 } else
234 l->in.type = INT;
235 }
236 if (tlen(l) == tlen(r)) {
237 printf("mov");
238 prtype(l);
239 goto ops;
240 } else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
241 printf("movz");
242 else
243 printf("cvt");
244 prtype(r);
245 prtype(l);
246 ops:
247 printf(" ");
248 adrput(r);
249 printf(",");
250 adrput(l);
251 return;
252 }
253
254 case 'B': /* get oreg value in temp register for shift */
255 {
256 register NODE *r;
257 if (xdebug) eprint(p, 0, &val, &val);
258 r = p->in.right;
259 if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
260 printf("movl");
261 else {
262 printf(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
263 prtype(r);
264 printf("l");
265 }
266 return;
267 }
268
269 case 'C': /* num bytes pushed on arg stack */
270 {
271 extern int gc_numbytes;
272 extern int xdebug;
273
274 if (xdebug) printf("->%d<-",gc_numbytes);
275
276 printf("call%c $%d",
277 (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s',
278 gc_numbytes+4);
279 /* dont change to double (here's the only place to catch it) */
280 if(p->in.type == FLOAT)
281 rtyflg = 1;
282 return;
283 }
284
285 case 'D': /* INCR and DECR */
286 zzzcode(p->in.left, 'A');
287 printf("\n ");
288
289 case 'E': /* INCR and DECR, FOREFF */
290 if (p->in.right->tn.lval == 1)
291 {
292 printf("%s", (p->in.op == INCR ? "inc" : "dec") );
293 prtype(p->in.left);
294 printf(" ");
295 adrput(p->in.left);
296 return;
297 }
298 printf("%s", (p->in.op == INCR ? "add" : "sub") );
299 prtype(p->in.left);
300 printf("2 ");
301 adrput(p->in.right);
302 printf(",");
303 adrput(p->in.left);
304 return;
305
306 case 'F': /* masked constant for fields */
307 printf("$%d", (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf);
308 return;
309
310 case 'H': /* opcode for shift */
311 if(p->in.op == LS || p->in.op == ASG LS)
312 printf("shll");
313 else if(ISUNSIGNED(p->in.left->in.type))
314 printf("shrl");
315 else
316 printf("shar");
317 return;
318
319 case 'L': /* type of left operand */
320 case 'R': /* type of right operand */
321 {
322 register NODE *n;
323 extern int xdebug;
324
325 n = getlr ( p, c);
326 if (xdebug) printf("->%d<-", n->in.type);
327
328 prtype(n);
329 return;
330 }
331
332 case 'M': /* initiate ediv for mod and unsigned div */
333 {
334 register char *r;
335 m = getlr(p, '1')->tn.rval;
336 r = rname(m);
337 printf("\tclrl\t%s\n\tmovl\t", r);
338 adrput(p->in.left);
339 printf(",%s\n", rname(m+1));
340 if(!ISUNSIGNED(p->in.type)) { /* should be MOD */
341 m = getlab();
342 printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
343 deflab(m);
344 }
345 }
346 return;
347
348 case 'U':
349 /* Truncate int for type conversions:
350 LONG|ULONG -> CHAR|UCHAR|SHORT|USHORT
351 SHORT|USHORT -> CHAR|UCHAR
352 increment offset to correct byte */
353 {
354 register NODE *p1;
355 int dif;
356
357 p1 = p->in.left;
358 switch( p1->in.op ){
359 case NAME:
360 case OREG:
361 dif = tlen(p1)-tlen(p);
362 p1->tn.lval += dif;
363 adrput(p1);
364 p1->tn.lval -= dif;
365 return;
366 default:
367 cerror( "Illegal ZU type conversion" );
368 return;
369 }
370 }
371
372 case 'T': /* rounded structure length for arguments */
373 {
374 int size;
375
376 size = p->stn.stsize;
377 SETOFF( size, 4);
378 printf("movab -%d(sp),sp", size);
379 return;
380 }
381
382 case 'S': /* structure assignment */
383 {
384 register NODE *l, *r;
385 register int size;
386
387 if( p->in.op == STASG ){
388 l = p->in.left;
389 r = p->in.right;
390
391 }
392 else if( p->in.op == STARG ){ /* store an arg into a temporary */
393 l = getlr( p, '3' );
394 r = p->in.left;
395 }
396 else cerror( "STASG bad" );
397
398 if( r->in.op == ICON ) r->in.op = NAME;
399 else if( r->in.op == REG ) r->in.op = OREG;
400 else if( r->in.op != OREG ) cerror( "STASG-r" );
401
402 size = p->stn.stsize;
403
404 if( size <= 0 || size > 65535 )
405 cerror("structure size <0=0 or >65535");
406
407 switch(size) {
408 case 1:
409 printf(" movb ");
410 break;
411 case 2:
412 printf(" movw ");
413 break;
414 case 4:
415 printf(" movl ");
416 break;
417 case 8:
418 printf(" movl ");
419 upput(r);
420 printf(",");
421 upput(l);
422 printf("\n movl ");
423 break;
424 default:
425 printf(" movab ");
426 adrput(l);
427 printf(",r1\n movab ");
428 adrput(r);
429 printf(",r0\n movl $%d,r2\n movblk\n", size);
430 rname(2);
431 goto endstasg;
432 }
433 adrput(r);
434 printf(",");
435 adrput(l);
436 printf("\n");
437 endstasg:
438 if( r->in.op == NAME ) r->in.op = ICON;
439 else if( r->in.op == OREG ) r->in.op = REG;
440
441 }
442 break;
443
444 default:
445 cerror( "illegal zzzcode" );
446 }
447 }
448
449rmove( rt, rs, t ) TWORD t;{
450 printf( " movl %s,%s\n", rname(rs), rname(rt) );
451 if(t==DOUBLE)
452 printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) );
453 }
454
455struct respref
456respref[] = {
457 INTAREG|INTBREG, INTAREG|INTBREG,
458 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
459 INTEMP, INTEMP,
460 FORARG, FORARG,
461 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
462 0, 0 };
463
464setregs(){ /* set up temporary registers */
465 fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */
466 }
467
468szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
469 return(t==DOUBLE ? 2 : 1 );
470 }
471
472rewfld( p ) NODE *p; {
473 return(1);
474 }
475
476callreg(p) NODE *p; {
477 return( R0 );
478 }
479
480base( p ) register NODE *p; {
481 register int o = p->in.op;
482
483 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
484 if( o==REG ) return( p->tn.rval );
485 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
486 return( p->in.left->tn.rval );
487 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
488 return( p->tn.rval + 0200*1 );
489 return( -1 );
490 }
491
492offset( p, tyl ) register NODE *p; int tyl; {
493
494 if(tyl > 8) return( -1 );
495 if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
496 if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
497 (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
498 && (1<<p->in.right->tn.lval)==tyl))
499 return( p->in.left->tn.rval );
500 return( -1 );
501 }
502
503makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
504 register NODE *t;
505 register int i;
506 NODE *f;
507
508 p->in.op = OREG;
509 f = p->in.left; /* have to free this subtree later */
510
511 /* init base */
512 switch (q->in.op) {
513 case ICON:
514 case REG:
515 case OREG:
516 t = q;
517 break;
518
519 case MINUS:
520 q->in.right->tn.lval = -q->in.right->tn.lval;
521 case PLUS:
522 t = q->in.right;
523 break;
524
525 case UNARY MUL:
526 t = q->in.left->in.left;
527 break;
528
529 default:
530 cerror("illegal makeor2");
531 }
532
533 p->tn.lval = t->tn.lval;
534#ifndef FLEXNAMES
535 for(i=0; i<NCHNAM; ++i)
536 p->in.name[i] = t->in.name[i];
537#else
538 p->in.name = t->in.name;
539#endif
540
541 /* init offset */
542 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
543
544 tfree(f);
545 return;
546 }
547
548canaddr( p ) NODE *p; {
549 register int o = p->in.op;
550
551 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
552 return(0);
553 }
554
555shltype( o, p ) register NODE *p; {
556 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
557 }
558
559flshape( p ) NODE *p; {
560 register int o = p->in.op;
561
562 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
563 return(0);
564 }
565
566shtemp( p ) register NODE *p; {
567 if( p->in.op == STARG ) p = p->in.left;
568 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
569 }
570
571shumul( p ) register NODE *p; {
572 register int o;
573 extern int xdebug;
574
575 if (xdebug) {
576 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
577 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
578 }
579
580 o = p->in.op;
581 if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
582 && p->in.type != PTR+DOUBLE)
583 return( STARNM );
584
585 return( 0 );
586 }
587
588special( p, shape ) register NODE *p; {
589 if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
590 else return(0);
591}
592
593adrcon( val ) CONSZ val; {
594 printf( "$" );
595 printf( CONFMT, val );
596 }
597
598conput( p ) register NODE *p; {
599 switch( p->in.op ){
600
601 case ICON:
602 acon( p );
603 return;
604
605 case REG:
606 printf( "%s", rname(p->tn.rval) );
607 return;
608
609 default:
610 cerror( "illegal conput" );
611 }
612 }
613
614insput( p ) NODE *p; {
615 cerror( "insput" );
616 }
617
618upput( p ) register NODE *p; {
619 /* output the address of the second long in the
620 pair pointed to by p (for DOUBLEs)*/
621 CONSZ save;
622
623 if( p->in.op == FLD ){
624 p = p->in.left;
625 }
626 switch( p->in.op ){
627
628 case NAME:
629 case OREG:
630 save = p->tn.lval;
631 p->tn.lval += SZLONG/SZCHAR;
632 adrput(p);
633 p->tn.lval = save;
634 return;
635
636 case REG:
637 printf( "%s", rname(p->tn.rval+1) );
638 return;
639
640 default:
641 cerror( "illegal upper address" );
642 }
643 }
644
645adrput( p ) register NODE *p; {
646 register int r;
647 /* output an address, with offsets, from p */
648
649 if( p->in.op == FLD ){
650 p = p->in.left;
651 }
652 switch( p->in.op ){
653
654 case NAME:
655 acon( p );
656 return;
657
658 case ICON:
659 /* addressable value of the constant */
660 printf( "$" );
661 acon( p );
662 return;
663
664 case REG:
665 printf( "%s", rname(p->tn.rval) );
666 if(p->in.type == DOUBLE) /* for entry mask */
667 (void) rname(p->tn.rval+1);
668 return;
669
670 case OREG:
671 r = p->tn.rval;
672 if( R2TEST(r) ){ /* double indexing */
673 register int flags;
674
675 flags = R2UPK3(r);
676 if( flags & 1 ) printf("*");
677 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
678 if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
679 printf( "[%s]", rname(R2UPK2(r)) );
680 return;
681 }
682 if( r == FP && p->tn.lval > 0 ){ /* in the argument region */
683 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
684 printf( CONFMT, p->tn.lval );
685 printf( "(fp)" );
686 return;
687 }
688 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
689 printf( "(%s)", rname(p->tn.rval) );
690 return;
691
692 case UNARY MUL:
693 /* STARNM or STARREG found */
694 if( tshape(p, STARNM) ) {
695 printf( "*" );
696 adrput( p->in.left);
697 }
698 return;
699
700 default:
701 cerror( "illegal address" );
702 return;
703
704 }
705
706 }
707
708acon( p ) register NODE *p; { /* print out a constant */
709
710 if( p->in.name[0] == '\0' ){
711 printf( CONFMT, p->tn.lval);
712 }
713 else if( p->tn.lval == 0 ) {
714#ifndef FLEXNAMES
715 printf( "%.8s", p->in.name );
716#else
717 printf( "%s", p->in.name );
718#endif
719 }
720 else {
721#ifndef FLEXNAMES
722 printf( "%.8s+", p->in.name );
723#else
724 printf( "%s+", p->in.name );
725#endif
726 printf( CONFMT, p->tn.lval );
727 }
728 }
729
730genscall( p, cookie ) register NODE *p; {
731 /* structure valued call */
732 return( gencall( p, cookie ) );
733 }
734
735genfcall( p, cookie ) register NODE *p; {
736 register NODE *p1;
737 register int m;
738 static char *funcops[6] = {
739 "sin", "cos", "sqrt", "exp", "log", "atan"
740 };
741
742 /* generate function opcodes */
743 if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
744 (p1 = p->in.left)->in.op==ICON &&
745 p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
746#ifdef FLEXNAMES
747 p1->in.name++;
748#else
749 strcpy(p1->in.name, p1->in.name[1]);
750#endif
751 for(m=0; m<6; m++)
752 if(!strcmp(p1->in.name, funcops[m]))
753 break;
754 if(m >= 6)
755 uerror("no opcode for fortarn function %s", p1->in.name);
756 } else
757 uerror("illegal type of fortarn function");
758 p1 = p->in.right;
759 p->in.op = FORTCALL;
760 if(!canaddr(p1))
761 order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
762 m = match( p, INTAREG|INTBREG );
763 return(m != MDONE);
764}
765
766/* tbl */
767int gc_numbytes;
768/* tbl */
769
770gencall( p, cookie ) register NODE *p; {
771 /* generate the call given by p */
772 register NODE *p1, *ptemp;
773 register int temp, temp1;
774 register int m;
775
776 if( p->in.right ) temp = argsize( p->in.right );
777 else temp = 0;
778
779 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
780 /* set aside room for structure return */
781
782 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
783 else temp1 = temp;
784 }
785
786 if( temp > maxargs ) maxargs = temp;
787 SETOFF(temp1,4);
788
789 if( p->in.right ){ /* make temp node, put offset in, and generate args */
790 ptemp = talloc();
791 ptemp->in.op = OREG;
792 ptemp->tn.lval = -1;
793 ptemp->tn.rval = SP;
794#ifndef FLEXNAMES
795 ptemp->in.name[0] = '\0';
796#else
797 ptemp->in.name = "";
798#endif
799 ptemp->in.rall = NOPREF;
800 ptemp->in.su = 0;
801 genargs( p->in.right, ptemp );
802 ptemp->in.op = FREE;
803 }
804
805 p1 = p->in.left;
806 if( p1->in.op != ICON ){
807 if( p1->in.op != REG ){
808 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
809 if( p1->in.op != NAME ){
810 order( p1, INAREG );
811 }
812 }
813 }
814 }
815
816/* tbl
817 setup gc_numbytes so reference to ZC works */
818
819 gc_numbytes = temp&(0x3ff);
820
821 p->in.op = UNARY CALL;
822 m = match( p, INTAREG|INTBREG );
823
824 return(m != MDONE);
825 }
826
827/* tbl */
828char *
829ccbranches[] = {
830 "eql",
831 "neq",
832 "leq",
833 "lss",
834 "geq",
835 "gtr",
836 "lequ",
837 "lssu",
838 "gequ",
839 "gtru",
840 };
841/* tbl */
842
843cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
844
845 if(o != 0 && (o < EQ || o > UGT ))
846 cerror( "bad conditional branch: %s", opst[o] );
847 printf( " j%s L%d\n",
848 o == 0 ? "br" : ccbranches[o-EQ], lab );
849 }
850
851nextcook( p, cookie ) NODE *p; {
852 /* we have failed to match p with cookie; try another */
853 if( cookie == FORREW ) return( 0 ); /* hopeless! */
854 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
855 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
856 return( FORREW );
857 }
858
859lastchance( p, cook ) NODE *p; {
860 /* forget it! */
861 return(0);
862 }
863
864optim2( p ) register NODE *p; {
865# ifdef ONEPASS
866 /* do local tree transformations and optimizations */
867# define RV(p) p->in.right->tn.lval
868 register int o = p->in.op;
869 register int i;
870
871 /* change unsigned mods and divs to logicals (mul is done in mip & c2) */
872 if(optype(o) == BITYPE && ISUNSIGNED(p->in.left->in.type)
873 && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
874 switch(o) {
875 case DIV:
876 case ASG DIV:
877 p->in.op = RS;
878 RV(p) = i;
879 break;
880 case MOD:
881 case ASG MOD:
882 p->in.op = AND;
883 RV(p)--;
884 break;
885 default:
886 return;
887 }
888 if(asgop(o))
889 p->in.op = ASG p->in.op;
890 }
891# endif
892}
893
894struct functbl {
895 int fop;
896 char *func;
897} opfunc[] = {
898 DIV, "udiv",
899 ASG DIV, "udiv",
900 0
901};
902
903hardops(p) register NODE *p; {
904 /* change hard to do operators into function calls. */
905 register NODE *q;
906 register struct functbl *f;
907 register int o;
908 register TWORD t, t1, t2;
909
910 o = p->in.op;
911
912 for( f=opfunc; f->fop; f++ ) {
913 if( o==f->fop ) goto convert;
914 }
915 return;
916
917 convert:
918 t = p->in.type;
919 t1 = p->in.left->in.type;
920 t2 = p->in.right->in.type;
921 if ( t1 != UNSIGNED && (t2 != UNSIGNED)) return;
922
923 /* need to rewrite tree for ASG OP */
924 /* must change ASG OP to a simple OP */
925 if( asgop( o ) ) {
926 q = talloc();
927 q->in.op = NOASG ( o );
928 q->in.rall = NOPREF;
929 q->in.type = p->in.type;
930 q->in.left = tcopy(p->in.left);
931 q->in.right = p->in.right;
932 p->in.op = ASSIGN;
933 p->in.right = q;
934 zappost(q->in.left); /* remove post-INCR(DECR) from new node */
935 fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */
936 p = q;
937
938 }
939 /* turn logicals to compare 0 */
940 else if( logop( o ) ) {
941 ncopy(q = talloc(), p);
942 p->in.left = q;
943 p->in.right = q = talloc();
944 q->in.op = ICON;
945 q->in.type = INT;
946#ifndef FLEXNAMES
947 q->in.name[0] = '\0';
948#else
949 q->in.name = "";
950#endif
951 q->tn.lval = 0;
952 q->tn.rval = 0;
953 p = p->in.left;
954 }
955
956 /* build comma op for args to function */
957 t1 = p->in.left->in.type;
958 t2 = 0;
959 if ( optype(p->in.op) == BITYPE) {
960 q = talloc();
961 q->in.op = CM;
962 q->in.rall = NOPREF;
963 q->in.type = INT;
964 q->in.left = p->in.left;
965 q->in.right = p->in.right;
966 t2 = p->in.right->in.type;
967 } else
968 q = p->in.left;
969
970 p->in.op = CALL;
971 p->in.right = q;
972
973 /* put function name in left node of call */
974 p->in.left = q = talloc();
975 q->in.op = ICON;
976 q->in.rall = NOPREF;
977 q->in.type = INCREF( FTN + p->in.type );
978#ifndef FLEXNAMES
979 strcpy( q->in.name, f->func );
980#else
981 q->in.name = f->func;
982#endif
983 q->tn.lval = 0;
984 q->tn.rval = 0;
985
986 }
987
988zappost(p) NODE *p; {
989 /* look for ++ and -- operators and remove them */
990
991 register int o, ty;
992 register NODE *q;
993 o = p->in.op;
994 ty = optype( o );
995
996 switch( o ){
997
998 case INCR:
999 case DECR:
1000 q = p->in.left;
1001 p->in.right->in.op = FREE; /* zap constant */
1002 ncopy( p, q );
1003 q->in.op = FREE;
1004 return;
1005
1006 }
1007
1008 if( ty == BITYPE ) zappost( p->in.right );
1009 if( ty != LTYPE ) zappost( p->in.left );
1010}
1011
1012fixpre(p) NODE *p; {
1013
1014 register int o, ty;
1015 o = p->in.op;
1016 ty = optype( o );
1017
1018 switch( o ){
1019
1020 case ASG PLUS:
1021 p->in.op = PLUS;
1022 break;
1023 case ASG MINUS:
1024 p->in.op = MINUS;
1025 break;
1026 }
1027
1028 if( ty == BITYPE ) fixpre( p->in.right );
1029 if( ty != LTYPE ) fixpre( p->in.left );
1030}
1031
1032NODE * addroreg(l) NODE *l;
1033 /* OREG was built in clocal()
1034 * for an auto or formal parameter
1035 * now its address is being taken
1036 * local code must unwind it
1037 * back to PLUS/MINUS REG ICON
1038 * according to local conventions
1039 */
1040{
1041 cerror("address of OREG taken");
1042}
1043
1044# ifndef ONEPASS
1045main( argc, argv ) char *argv[]; {
1046 return( mainp2( argc, argv ) );
1047 }
1048# endif
1049
1050myreader(p) register NODE *p; {
1051 walkf( p, hardops ); /* convert ops to function calls */
1052 canon( p ); /* expands r-vals for fileds */
1053 walkf( p, optim2 );
1054 }