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