restrict structure assignments to use movblk's; print address constants using ACONFMT
[unix-history] / usr / src / old / pcc / ccom.tahoe / local2.c
CommitLineData
f2b49199 1#ifndef lint
7412b41b 2static char sccsid[] = "@(#)local2.c 1.2 (Berkeley) %G%";
f2b49199
SL
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 */
7412b41b 307 printf(ACONFMT, (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf);
f2b49199
SL
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");
7412b41b
SL
406 /*
407 * Can't optimize with movw's or movl's here as
408 * we don't know the alignment properties of
409 * either source or destination (governed, potentially
410 * by alignment of enclosing structure/union).
411 * (PERHAPS WE COULD SIMULATE dclstruct?)
412 */
413 if (size != 1) {
414 printf("\tmovab\t");
415 adrput(l);
416 printf(",r1\n\tmovab\t");
417 adrput(r);
418 printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
419 rname(2);
420 } else {
421 printf("\tmovb\t");
422 adrput(r);
423 printf(",");
424 adrput(l);
425 printf("\n");
f2b49199 426 }
f2b49199
SL
427 if( r->in.op == NAME ) r->in.op = ICON;
428 else if( r->in.op == OREG ) r->in.op = REG;
429
430 }
431 break;
432
433 default:
434 cerror( "illegal zzzcode" );
435 }
436 }
437
438rmove( rt, rs, t ) TWORD t;{
439 printf( " movl %s,%s\n", rname(rs), rname(rt) );
440 if(t==DOUBLE)
441 printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) );
442 }
443
444struct respref
445respref[] = {
446 INTAREG|INTBREG, INTAREG|INTBREG,
447 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
448 INTEMP, INTEMP,
449 FORARG, FORARG,
450 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
451 0, 0 };
452
453setregs(){ /* set up temporary registers */
454 fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */
455 }
456
457szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
458 return(t==DOUBLE ? 2 : 1 );
459 }
460
461rewfld( p ) NODE *p; {
462 return(1);
463 }
464
465callreg(p) NODE *p; {
466 return( R0 );
467 }
468
469base( p ) register NODE *p; {
470 register int o = p->in.op;
471
472 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
473 if( o==REG ) return( p->tn.rval );
474 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
475 return( p->in.left->tn.rval );
476 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
477 return( p->tn.rval + 0200*1 );
478 return( -1 );
479 }
480
481offset( p, tyl ) register NODE *p; int tyl; {
482
483 if(tyl > 8) return( -1 );
484 if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
485 if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
486 (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
487 && (1<<p->in.right->tn.lval)==tyl))
488 return( p->in.left->tn.rval );
489 return( -1 );
490 }
491
492makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
493 register NODE *t;
494 register int i;
495 NODE *f;
496
497 p->in.op = OREG;
498 f = p->in.left; /* have to free this subtree later */
499
500 /* init base */
501 switch (q->in.op) {
502 case ICON:
503 case REG:
504 case OREG:
505 t = q;
506 break;
507
508 case MINUS:
509 q->in.right->tn.lval = -q->in.right->tn.lval;
510 case PLUS:
511 t = q->in.right;
512 break;
513
514 case UNARY MUL:
515 t = q->in.left->in.left;
516 break;
517
518 default:
519 cerror("illegal makeor2");
520 }
521
522 p->tn.lval = t->tn.lval;
523#ifndef FLEXNAMES
524 for(i=0; i<NCHNAM; ++i)
525 p->in.name[i] = t->in.name[i];
526#else
527 p->in.name = t->in.name;
528#endif
529
530 /* init offset */
531 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
532
533 tfree(f);
534 return;
535 }
536
537canaddr( p ) NODE *p; {
538 register int o = p->in.op;
539
540 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
541 return(0);
542 }
543
544shltype( o, p ) register NODE *p; {
545 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
546 }
547
548flshape( 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
555shtemp( p ) register NODE *p; {
556 if( p->in.op == STARG ) p = p->in.left;
557 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
558 }
559
560shumul( p ) register NODE *p; {
561 register int o;
562 extern int xdebug;
563
564 if (xdebug) {
565 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
566 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
567 }
568
569 o = p->in.op;
570 if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
571 && p->in.type != PTR+DOUBLE)
572 return( STARNM );
573
574 return( 0 );
575 }
576
577special( p, shape ) register NODE *p; {
578 if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
579 else return(0);
580}
581
582adrcon( val ) CONSZ val; {
7412b41b 583 printf(ACONFMT, val);
f2b49199
SL
584 }
585
586conput( p ) register NODE *p; {
587 switch( p->in.op ){
588
589 case ICON:
590 acon( p );
591 return;
592
593 case REG:
594 printf( "%s", rname(p->tn.rval) );
595 return;
596
597 default:
598 cerror( "illegal conput" );
599 }
600 }
601
602insput( p ) NODE *p; {
603 cerror( "insput" );
604 }
605
606upput( p ) register NODE *p; {
607 /* output the address of the second long in the
608 pair pointed to by p (for DOUBLEs)*/
609 CONSZ save;
610
611 if( p->in.op == FLD ){
612 p = p->in.left;
613 }
614 switch( p->in.op ){
615
616 case NAME:
617 case OREG:
618 save = p->tn.lval;
619 p->tn.lval += SZLONG/SZCHAR;
620 adrput(p);
621 p->tn.lval = save;
622 return;
623
624 case REG:
625 printf( "%s", rname(p->tn.rval+1) );
626 return;
627
628 default:
629 cerror( "illegal upper address" );
630 }
631 }
632
633adrput( p ) register NODE *p; {
634 register int r;
635 /* output an address, with offsets, from p */
636
637 if( p->in.op == FLD ){
638 p = p->in.left;
639 }
640 switch( p->in.op ){
641
642 case NAME:
643 acon( p );
644 return;
645
646 case ICON:
647 /* addressable value of the constant */
648 printf( "$" );
649 acon( p );
650 return;
651
652 case REG:
653 printf( "%s", rname(p->tn.rval) );
654 if(p->in.type == DOUBLE) /* for entry mask */
655 (void) rname(p->tn.rval+1);
656 return;
657
658 case OREG:
659 r = p->tn.rval;
660 if( R2TEST(r) ){ /* double indexing */
661 register int flags;
662
663 flags = R2UPK3(r);
664 if( flags & 1 ) printf("*");
665 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
666 if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
667 printf( "[%s]", rname(R2UPK2(r)) );
668 return;
669 }
670 if( r == FP && p->tn.lval > 0 ){ /* in the argument region */
671 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
672 printf( CONFMT, p->tn.lval );
673 printf( "(fp)" );
674 return;
675 }
676 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
677 printf( "(%s)", rname(p->tn.rval) );
678 return;
679
680 case UNARY MUL:
681 /* STARNM or STARREG found */
682 if( tshape(p, STARNM) ) {
683 printf( "*" );
684 adrput( p->in.left);
685 }
686 return;
687
688 default:
689 cerror( "illegal address" );
690 return;
691
692 }
693
694 }
695
696acon( p ) register NODE *p; { /* print out a constant */
697
698 if( p->in.name[0] == '\0' ){
699 printf( CONFMT, p->tn.lval);
700 }
701 else if( p->tn.lval == 0 ) {
702#ifndef FLEXNAMES
703 printf( "%.8s", p->in.name );
704#else
705 printf( "%s", p->in.name );
706#endif
707 }
708 else {
709#ifndef FLEXNAMES
710 printf( "%.8s+", p->in.name );
711#else
712 printf( "%s+", p->in.name );
713#endif
714 printf( CONFMT, p->tn.lval );
715 }
716 }
717
718genscall( p, cookie ) register NODE *p; {
719 /* structure valued call */
720 return( gencall( p, cookie ) );
721 }
722
723genfcall( p, cookie ) register NODE *p; {
724 register NODE *p1;
725 register int m;
726 static char *funcops[6] = {
727 "sin", "cos", "sqrt", "exp", "log", "atan"
728 };
729
730 /* generate function opcodes */
731 if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
732 (p1 = p->in.left)->in.op==ICON &&
733 p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
734#ifdef FLEXNAMES
735 p1->in.name++;
736#else
737 strcpy(p1->in.name, p1->in.name[1]);
738#endif
739 for(m=0; m<6; m++)
740 if(!strcmp(p1->in.name, funcops[m]))
741 break;
742 if(m >= 6)
743 uerror("no opcode for fortarn function %s", p1->in.name);
744 } else
745 uerror("illegal type of fortarn function");
746 p1 = p->in.right;
747 p->in.op = FORTCALL;
748 if(!canaddr(p1))
749 order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
750 m = match( p, INTAREG|INTBREG );
751 return(m != MDONE);
752}
753
754/* tbl */
755int gc_numbytes;
756/* tbl */
757
758gencall( p, cookie ) register NODE *p; {
759 /* generate the call given by p */
760 register NODE *p1, *ptemp;
761 register int temp, temp1;
762 register int m;
763
764 if( p->in.right ) temp = argsize( p->in.right );
765 else temp = 0;
766
767 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
768 /* set aside room for structure return */
769
770 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
771 else temp1 = temp;
772 }
773
774 if( temp > maxargs ) maxargs = temp;
775 SETOFF(temp1,4);
776
777 if( p->in.right ){ /* make temp node, put offset in, and generate args */
778 ptemp = talloc();
779 ptemp->in.op = OREG;
780 ptemp->tn.lval = -1;
781 ptemp->tn.rval = SP;
782#ifndef FLEXNAMES
783 ptemp->in.name[0] = '\0';
784#else
785 ptemp->in.name = "";
786#endif
787 ptemp->in.rall = NOPREF;
788 ptemp->in.su = 0;
789 genargs( p->in.right, ptemp );
790 ptemp->in.op = FREE;
791 }
792
793 p1 = p->in.left;
794 if( p1->in.op != ICON ){
795 if( p1->in.op != REG ){
796 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
797 if( p1->in.op != NAME ){
798 order( p1, INAREG );
799 }
800 }
801 }
802 }
803
804/* tbl
805 setup gc_numbytes so reference to ZC works */
806
807 gc_numbytes = temp&(0x3ff);
808
809 p->in.op = UNARY CALL;
810 m = match( p, INTAREG|INTBREG );
811
812 return(m != MDONE);
813 }
814
815/* tbl */
816char *
817ccbranches[] = {
818 "eql",
819 "neq",
820 "leq",
821 "lss",
822 "geq",
823 "gtr",
824 "lequ",
825 "lssu",
826 "gequ",
827 "gtru",
828 };
829/* tbl */
830
831cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
832
833 if(o != 0 && (o < EQ || o > UGT ))
834 cerror( "bad conditional branch: %s", opst[o] );
835 printf( " j%s L%d\n",
836 o == 0 ? "br" : ccbranches[o-EQ], lab );
837 }
838
839nextcook( p, cookie ) NODE *p; {
840 /* we have failed to match p with cookie; try another */
841 if( cookie == FORREW ) return( 0 ); /* hopeless! */
842 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
843 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
844 return( FORREW );
845 }
846
847lastchance( p, cook ) NODE *p; {
848 /* forget it! */
849 return(0);
850 }
851
852optim2( p ) register NODE *p; {
853# ifdef ONEPASS
854 /* do local tree transformations and optimizations */
855# define RV(p) p->in.right->tn.lval
856 register int o = p->in.op;
857 register int i;
858
859 /* change unsigned mods and divs to logicals (mul is done in mip & c2) */
860 if(optype(o) == BITYPE && ISUNSIGNED(p->in.left->in.type)
861 && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
862 switch(o) {
863 case DIV:
864 case ASG DIV:
865 p->in.op = RS;
866 RV(p) = i;
867 break;
868 case MOD:
869 case ASG MOD:
870 p->in.op = AND;
871 RV(p)--;
872 break;
873 default:
874 return;
875 }
876 if(asgop(o))
877 p->in.op = ASG p->in.op;
878 }
879# endif
880}
881
882struct functbl {
883 int fop;
884 char *func;
885} opfunc[] = {
886 DIV, "udiv",
887 ASG DIV, "udiv",
888 0
889};
890
891hardops(p) register NODE *p; {
892 /* change hard to do operators into function calls. */
893 register NODE *q;
894 register struct functbl *f;
895 register int o;
896 register TWORD t, t1, t2;
897
898 o = p->in.op;
899
900 for( f=opfunc; f->fop; f++ ) {
901 if( o==f->fop ) goto convert;
902 }
903 return;
904
905 convert:
906 t = p->in.type;
907 t1 = p->in.left->in.type;
908 t2 = p->in.right->in.type;
909 if ( t1 != UNSIGNED && (t2 != UNSIGNED)) return;
910
911 /* need to rewrite tree for ASG OP */
912 /* must change ASG OP to a simple OP */
913 if( asgop( o ) ) {
914 q = talloc();
915 q->in.op = NOASG ( o );
916 q->in.rall = NOPREF;
917 q->in.type = p->in.type;
918 q->in.left = tcopy(p->in.left);
919 q->in.right = p->in.right;
920 p->in.op = ASSIGN;
921 p->in.right = q;
922 zappost(q->in.left); /* remove post-INCR(DECR) from new node */
923 fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */
924 p = q;
925
926 }
927 /* turn logicals to compare 0 */
928 else if( logop( o ) ) {
929 ncopy(q = talloc(), p);
930 p->in.left = q;
931 p->in.right = q = talloc();
932 q->in.op = ICON;
933 q->in.type = INT;
934#ifndef FLEXNAMES
935 q->in.name[0] = '\0';
936#else
937 q->in.name = "";
938#endif
939 q->tn.lval = 0;
940 q->tn.rval = 0;
941 p = p->in.left;
942 }
943
944 /* build comma op for args to function */
945 t1 = p->in.left->in.type;
946 t2 = 0;
947 if ( optype(p->in.op) == BITYPE) {
948 q = talloc();
949 q->in.op = CM;
950 q->in.rall = NOPREF;
951 q->in.type = INT;
952 q->in.left = p->in.left;
953 q->in.right = p->in.right;
954 t2 = p->in.right->in.type;
955 } else
956 q = p->in.left;
957
958 p->in.op = CALL;
959 p->in.right = q;
960
961 /* put function name in left node of call */
962 p->in.left = q = talloc();
963 q->in.op = ICON;
964 q->in.rall = NOPREF;
965 q->in.type = INCREF( FTN + p->in.type );
966#ifndef FLEXNAMES
967 strcpy( q->in.name, f->func );
968#else
969 q->in.name = f->func;
970#endif
971 q->tn.lval = 0;
972 q->tn.rval = 0;
973
974 }
975
976zappost(p) NODE *p; {
977 /* look for ++ and -- operators and remove them */
978
979 register int o, ty;
980 register NODE *q;
981 o = p->in.op;
982 ty = optype( o );
983
984 switch( o ){
985
986 case INCR:
987 case DECR:
988 q = p->in.left;
989 p->in.right->in.op = FREE; /* zap constant */
990 ncopy( p, q );
991 q->in.op = FREE;
992 return;
993
994 }
995
996 if( ty == BITYPE ) zappost( p->in.right );
997 if( ty != LTYPE ) zappost( p->in.left );
998}
999
1000fixpre(p) NODE *p; {
1001
1002 register int o, ty;
1003 o = p->in.op;
1004 ty = optype( o );
1005
1006 switch( o ){
1007
1008 case ASG PLUS:
1009 p->in.op = PLUS;
1010 break;
1011 case ASG MINUS:
1012 p->in.op = MINUS;
1013 break;
1014 }
1015
1016 if( ty == BITYPE ) fixpre( p->in.right );
1017 if( ty != LTYPE ) fixpre( p->in.left );
1018}
1019
1020NODE * addroreg(l) NODE *l;
1021 /* OREG was built in clocal()
1022 * for an auto or formal parameter
1023 * now its address is being taken
1024 * local code must unwind it
1025 * back to PLUS/MINUS REG ICON
1026 * according to local conventions
1027 */
1028{
1029 cerror("address of OREG taken");
1030}
1031
1032# ifndef ONEPASS
1033main( argc, argv ) char *argv[]; {
1034 return( mainp2( argc, argv ) );
1035 }
1036# endif
1037
1038myreader(p) register NODE *p; {
1039 walkf( p, hardops ); /* convert ops to function calls */
1040 canon( p ); /* expands r-vals for fileds */
1041 walkf( p, optim2 );
1042 }