date and time created 90/06/17 16:06:28 by bostic
[unix-history] / usr / src / old / pcc / ccom.vax / local2.c
CommitLineData
262eaf56 1# ifndef lint
5270d49e 2static char *sccsid ="@(#)local2.c 1.39 (Berkeley) %G%";
262eaf56
RC
3# endif
4
0ec67d08 5# include "pass2.h"
74789784
DS
6# include <ctype.h>
7
8# define putstr(s) fputs((s), stdout)
9
439a068b
ML
10# ifdef FORT
11int ftlab1, ftlab2;
12# endif
13/* a lot of the machine dependent parts of the second pass */
14
15# define BITMASK(n) ((1L<<n)-1)
16
6dc2c6c8 17/*ARGSUSED*/
439a068b
ML
18where(c){
19 fprintf( stderr, "%s, line %d: ", filename, lineno );
20 }
21
22lineid( l, fn ) char *fn; {
23 /* identify line l and file fn */
24 printf( "# line %d, file %s\n", l, fn );
25 }
26
27
28eobl2(){
74789784
DS
29 register OFFSZ spoff; /* offset from stack pointer */
30#ifndef FORT
31 extern int ftlab1, ftlab2;
32#endif
33
439a068b
ML
34 spoff = maxoff;
35 if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
36 spoff /= SZCHAR;
37 SETOFF(spoff,4);
74789784 38#ifdef FORT
439a068b
ML
39#ifndef FLEXNAMES
40 printf( " .set .F%d,%ld\n", ftnno, spoff );
41#else
42 /* SHOULD BE L%d ... ftnno but must change pc/f77 */
43 printf( " .set LF%d,%ld\n", ftnno, spoff );
44#endif
45#else
439a068b
ML
46 printf( "L%d:\n", ftlab1);
47 if( spoff!=0 )
48 if( spoff < 64 )
49 printf( " subl2 $%ld,sp\n", spoff);
50 else
51 printf( " movab -%ld(sp),sp\n", spoff);
52 printf( " jbr L%d\n", ftlab2);
53#endif
54 maxargs = -1;
55 }
56
57struct hoptab { int opmask; char * opstring; } ioptab[] = {
58
439a068b
ML
59 PLUS, "add",
60 MINUS, "sub",
61 MUL, "mul",
62 DIV, "div",
63 OR, "bis",
64 ER, "xor",
65 AND, "bic",
66 -1, "" };
67
68hopcode( f, o ){
69 /* output the appropriate string from the above table */
70
71 register struct hoptab *q;
72
74789784
DS
73 if(asgop(o))
74 o = NOASG o;
439a068b
ML
75 for( q = ioptab; q->opmask>=0; ++q ){
76 if( q->opmask == o ){
74789784 77 printf( "%s%c", q->opstring, tolower(f));
439a068b
ML
78 return;
79 }
80 }
81 cerror( "no hoptab for %s", opst[o] );
82 }
83
84char *
85rnames[] = { /* keyed to register number tokens */
86
87 "r0", "r1",
88 "r2", "r3", "r4", "r5",
89 "r6", "r7", "r8", "r9", "r10", "r11",
90 "ap", "fp", "sp", "pc",
439a068b
ML
91 };
92
93int rstatus[] = {
94 SAREG|STAREG, SAREG|STAREG,
95 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
96 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
97 SAREG, SAREG, SAREG, SAREG,
439a068b
ML
98 };
99
100tlen(p) NODE *p;
101{
102 switch(p->in.type) {
103 case CHAR:
104 case UCHAR:
105 return(1);
106
107 case SHORT:
108 case USHORT:
3f494137 109 return(SZSHORT/SZCHAR);
439a068b
ML
110
111 case DOUBLE:
3f494137 112 return(SZDOUBLE/SZCHAR);
439a068b
ML
113
114 default:
3f494137 115 return(SZINT/SZCHAR);
439a068b
ML
116 }
117}
118
119mixtypes(p, q) NODE *p, *q;
120{
472582a4 121 register TWORD tp, tq;
439a068b
ML
122
123 tp = p->in.type;
124 tq = q->in.type;
125
126 return( (tp==FLOAT || tp==DOUBLE) !=
127 (tq==FLOAT || tq==DOUBLE) );
128}
129
130prtype(n) NODE *n;
131{
132 switch (n->in.type)
133 {
74789784 134
439a068b 135 case DOUBLE:
88bb0c9f 136 putchar('d');
439a068b
ML
137 return;
138
139 case FLOAT:
88bb0c9f 140 putchar('f');
439a068b
ML
141 return;
142
143 case LONG:
144 case ULONG:
145 case INT:
146 case UNSIGNED:
88bb0c9f 147 putchar('l');
439a068b
ML
148 return;
149
150 case SHORT:
151 case USHORT:
88bb0c9f 152 putchar('w');
439a068b
ML
153 return;
154
155 case CHAR:
156 case UCHAR:
88bb0c9f 157 putchar('b');
439a068b
ML
158 return;
159
160 default:
161 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
162 else {
88bb0c9f 163 putchar('l');
439a068b
ML
164 return;
165 }
166 }
167}
168
169zzzcode( p, c ) register NODE *p; {
74789784 170 register int m;
6dc2c6c8 171 int val;
439a068b
ML
172 switch( c ){
173
174 case 'N': /* logical ops, turned into 0-1 */
175 /* use register given by register 1 */
176 cbgen( 0, m=getlab(), 'I' );
177 deflab( p->bn.label );
178 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] );
179 deflab( m );
180 return;
181
439a068b
ML
182 case 'P':
183 cbgen( p->in.op, p->bn.label, c );
184 return;
185
186 case 'A':
74789784
DS
187 case 'V':
188 sconv( p, c == 'V' );
439a068b 189 return;
439a068b 190
4bcc0eaf
DS
191 case 'G': /* i *= f; asgops with int lhs and float rhs */
192 {
193 register NODE *l, *r, *s;
194 int rt;
195
196 l = p->in.left;
197 r = p->in.right;
198 s = talloc();
199 rt = r->in.type;
200
201 s->in.op = SCONV;
202 s->in.left = l;
203 s->in.type = rt;
204 zzzcode(s, 'A');
205 putstr("\n\t");
206
207 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
208 putstr("2\t");
209 adrput(r);
210 putchar(',');
211 adrput(resc);
212 putstr("\n\t");
213
214 s->in.op = ASSIGN;
215 s->in.left = l;
216 s->in.right = resc;
217 s->in.type = l->in.type;
218 zzzcode(s, 'A');
219
220 s->in.op = FREE;
221 return;
222 }
223
70f59a26
DS
224 case 'J': /* unsigned DIV/MOD with constant divisors */
225 {
226 register int ck = INAREG;
227 int label1, label2;
228
229 /* case constant <= 1 is handled by optim() in pass 1 */
230 /* case constant < 0x80000000 is handled in table */
231 switch( p->in.op ) {
6eafb37d 232 /* case DIV: handled in optim2() */
70f59a26
DS
233 case MOD:
234 if( p->in.left->in.op == REG &&
235 p->in.left->tn.rval == resc->tn.rval )
236 goto asgmod;
237 label1 = getlab();
238 expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n");
239 printf("\tjlssu\tL%d\n", label1);
240 expand(p, ck, "\tsubl2\tAR,A1\n");
241 printf("L%d:", label1);
242 break;
243 case ASG DIV:
244 label1 = getlab();
245 label2 = getlab();
246 expand(p, ck, "cmpl\tAL,AR\n");
247 printf("\tjgequ\tL%d\n", label1);
248 expand(p, ck, "\tmovl\t$1,AL\n");
249 printf("\tjbr\tL%d\nL%d:\n", label2, label1);
250 expand(p, ck, "\tclrl\tAL\n");
251 printf("L%d:", label2);
252 break;
253 case ASG MOD:
254 asgmod:
255 label1 = getlab();
256 expand(p, ck, "cmpl\tAL,AR\n");
257 printf("\tjlssu\tL%d\n", label1);
258 expand(p, ck, "\tsubl2\tAR,AL\n");
259 printf("L%d:", label1);
260 break;
261 }
262 return;
263 }
264
439a068b
ML
265 case 'B': /* get oreg value in temp register for left shift */
266 {
267 register NODE *r;
268 if (xdebug) eprint(p, 0, &val, &val);
269 r = p->in.right;
3f494137 270 if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT )
88bb0c9f 271 putstr("movl");
439a068b 272 else {
74789784 273 putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
439a068b 274 prtype(r);
88bb0c9f 275 putchar('l');
439a068b
ML
276 }
277 return;
278 }
279
280 case 'C': /* num words pushed on arg stack */
281 {
282 extern int gc_numbytes;
283 extern int xdebug;
284
285 if (xdebug) printf("->%d<-",gc_numbytes);
286
287 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
288 return;
289 }
290
291 case 'D': /* INCR and DECR */
292 zzzcode(p->in.left, 'A');
88bb0c9f
KM
293 putchar('\n');
294 putchar('\t');
439a068b
ML
295
296 case 'E': /* INCR and DECR, FOREFF */
ffc0e7a6 297 if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1)
439a068b 298 {
74789784 299 putstr(p->in.op == INCR ? "inc" : "dec");
439a068b 300 prtype(p->in.left);
88bb0c9f 301 putchar('\t');
439a068b
ML
302 adrput(p->in.left);
303 return;
304 }
74789784 305 putstr(p->in.op == INCR ? "add" : "sub");
439a068b 306 prtype(p->in.left);
88bb0c9f
KM
307 putchar('2');
308 putchar('\t');
439a068b 309 adrput(p->in.right);
88bb0c9f 310 putchar(',');
439a068b
ML
311 adrput(p->in.left);
312 return;
313
314 case 'F': /* register type of right operand */
315 {
316 register NODE *n;
317 extern int xdebug;
318 register int ty;
319
320 n = getlr( p, 'R' );
321 ty = n->in.type;
322
323 if (xdebug) printf("->%d<-", ty);
324
88bb0c9f
KM
325 if ( ty==DOUBLE) putchar('d');
326 else if ( ty==FLOAT ) putchar('f');
327 else putchar('l');
439a068b
ML
328 return;
329 }
330
331 case 'L': /* type of left operand */
332 case 'R': /* type of right operand */
333 {
334 register NODE *n;
335 extern int xdebug;
336
472582a4 337 n = getlr( p, c );
439a068b
ML
338 if (xdebug) printf("->%d<-", n->in.type);
339
340 prtype(n);
341 return;
342 }
343
6eafb37d
DS
344 case 'Z': /* AND for CC with ICON -- lval is complemented */
345 {
346 register NODE *l, *r;
347
348 l = getlr( p, 'L' );
349 r = getlr( p, 'R' );
350 m = (1 << tlen(l) * SZCHAR) - 1;
351 r->tn.lval = ~r->tn.lval;
352 if( (l->in.type == CHAR || l->in.type == SHORT) &&
353 (r->tn.lval & ~m) ) {
354 putstr("cvt");
355 prtype(l);
356 putstr("l\t");
357 adrput(l);
358 putchar(',');
359 adrput(resc);
360 putstr("\n\t");
361 resc->tn.type = INT;
362 l = resc;
363 }
364 else if( l->in.type == UCHAR || l->in.type == USHORT )
365 /* remove trash left over from complementing */
366 r->tn.lval &= m;
367 putstr("bit");
368 prtype(l);
369 printf("\t$%ld", r->tn.lval);
370 putchar(',');
371 adrput(l);
439a068b 372 return;
6eafb37d 373 }
439a068b
ML
374
375 case 'U': /* 32 - n, for unsigned right shifts */
376 printf("$%d", 32 - p->in.right->tn.lval );
377 return;
378
379 case 'T': /* rounded structure length for arguments */
380 {
381 int size;
382
383 size = p->stn.stsize;
384 SETOFF( size, 4);
385 printf("$%d", size);
386 return;
387 }
388
389 case 'S': /* structure assignment */
74789784
DS
390 stasg(p);
391 break;
439a068b 392
74789784
DS
393 default:
394 cerror( "illegal zzzcode" );
395 }
396 }
439a068b 397
74789784
DS
398stasg(p)
399 register NODE *p;
400{
401 register NODE *l, *r;
402 register size;
439a068b 403
74789784
DS
404 if( p->in.op == STASG ){
405 l = p->in.left;
406 r = p->in.right;
439a068b 407
74789784
DS
408 }
409 else if( p->in.op == STARG ){ /* store an arg into a temporary */
410 r = p->in.left;
411 }
412 else cerror( "STASG bad" );
439a068b 413
74789784
DS
414 if( r->in.op == ICON ) r->in.op = NAME;
415 else if( r->in.op == REG ) r->in.op = OREG;
416 else if( r->in.op != OREG ) cerror( "STASG-r" );
439a068b 417
74789784
DS
418 size = p->stn.stsize;
419
420 if( size <= 0 || size > 65535 )
421 cerror("structure size <0=0 or >65535");
422
423 switch(size) {
424 case 1:
425 putstr(" movb ");
426 break;
427 case 2:
428 putstr(" movw ");
429 break;
430 case 4:
431 putstr(" movl ");
432 break;
433 case 8:
434 putstr(" movq ");
435 break;
436 default:
437 printf(" movc3 $%d,", size);
438 break;
439 }
440 adrput(r);
441 if( p->in.op == STASG ){
442 putchar(',');
443 adrput(l);
444 putchar('\n');
445 }
446 else
447 putstr(",(sp)\n");
448
449 if( r->in.op == NAME ) r->in.op = ICON;
450 else if( r->in.op == OREG ) r->in.op = REG;
451 }
452
453NODE *makearg( ty ) int ty; {
454 register NODE *p, *q;
455
456 /* build a -(sp) operand */
457 p = talloc();
458 p->in.op = REG;
459 /* the type needn't be right, just consistent */
460 p->in.type = INCREF(ty);
461 p->tn.rval = SP;
462 p->tn.lval = 0;
463 q = talloc();
464 q->in.op = ASG MINUS;
465 q->in.type = INCREF(ty);
466 q->in.left = p;
467 p = talloc();
468 p->in.op = ICON;
469 p->in.type = INT;
470 p->tn.name = "";
8af0c924
DS
471 /* size of floating argument is always 2 */
472 p->tn.lval = (1 + (ty == FLOAT || ty == DOUBLE)) * (SZINT/SZCHAR);
74789784
DS
473 q->in.right = p;
474 p = talloc();
475 p->in.op = UNARY MUL;
476 p->in.left = q;
477 return( p );
478 }
479
480sconv( p, forarg ) register NODE *p; {
481 register NODE *l, *r;
482 int m, val;
483
484 if (xdebug) eprint(p, 0, &val, &val);
485 r = getlr(p, 'R');
486 if (p->in.op == ASSIGN)
487 l = getlr(p, 'L');
488 else if (p->in.op == SCONV) {
74789784 489 m = r->in.type;
74789784
DS
490 if (forarg)
491 l = makearg( m );
492 else
493 l = resc;
494 l->in.type = m;
495 r = getlr(p, 'L');
496 }
497 else { /* OPLTYPE */
74789784 498 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
74789784
DS
499 if (forarg)
500 l = makearg( m );
501 else
502 l = resc;
503 l->in.type = m;
504 }
505 if (r->in.op == ICON)
506 if (r->in.name[0] == '\0') {
77163d79
DS
507 if (r->tn.lval == 0 &&
508 (r->in.type == DOUBLE || r->in.type == FLOAT ||
509 !forarg)) {
510 if (r->in.type == FLOAT)
511 r->in.type = DOUBLE;
74789784
DS
512 putstr("clr");
513 prtype(l);
514 putchar('\t');
3add848c 515 adrput(l);
74789784
DS
516 goto cleanup;
517 }
518 if (r->tn.lval < 0 && r->tn.lval >= -63) {
519 putstr("mneg");
520 prtype(l);
521 r->tn.lval = -r->tn.lval;
522 goto ops;
3add848c 523 }
74789784
DS
524 if (r->tn.lval < 0)
525 r->in.type = r->tn.lval >= -128 ? CHAR
526 : (r->tn.lval >= -32768 ? SHORT
527 : INT);
528 else if (l->in.type == FLOAT ||
529 l->in.type == DOUBLE)
530 r->in.type = r->tn.lval <= 63 ? INT
531 : (r->tn.lval <= 127 ? CHAR
532 : (r->tn.lval <= 32767 ? SHORT
533 : INT));
3add848c 534 else
74789784
DS
535 r->in.type = r->tn.lval <= 63 ? INT
536 : (r->tn.lval <= 127 ? CHAR
537 : (r->tn.lval <= 255 ? UCHAR
538 : (r->tn.lval <= 32767 ? SHORT
539 : (r->tn.lval <= 65535 ? USHORT
540 : INT))));
6eafb37d
DS
541 if (forarg && r->in.type == INT) {
542 putstr("pushl\t");
543 adrput(r);
544 goto cleanup;
545 }
74789784
DS
546 }
547 else {
6eafb37d
DS
548 if (forarg && tlen(r) == SZINT/SZCHAR) {
549 putstr("pushl\t");
550 adrput(r);
551 goto cleanup;
552 }
553 putstr("moval\t");
74789784
DS
554 acon(r);
555 putchar(',');
556 adrput(l);
557 goto cleanup;
558 }
439a068b 559
74789784
DS
560 if (p->in.op == SCONV &&
561 !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
562 !mixtypes(l, r)) {
563 /*
564 * Because registers must always contain objects
565 * of the same width as INTs, we may have to
566 * perform two conversions to get an INT. Can
567 * the conversions be collapsed into one?
568 */
569 if (m = collapsible(l, r))
570 r->in.type = m;
571 else {
d2f82175 572 /* two steps are required */
10ff05ec
DS
573 NODE *x;
574
575 if (forarg) {
576 x = resc;
577 x->in.type = l->in.type;
578 }
579 else {
580 x = &resc[1];
581 *x = *l;
582 }
439a068b 583
74789784
DS
584 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
585 putstr("movz");
586 else
587 putstr("cvt");
588 prtype(r);
589 prtype(x);
590 putchar('\t');
591 adrput(r);
592 putchar(',');
593 adrput(x);
594 putchar('\n');
595 putchar('\t');
596 r = x;
439a068b 597 }
74789784
DS
598 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
599 }
439a068b 600
d2f82175
DS
601 else if ((forarg || l == resc) &&
602 tlen(l) < SZINT/SZCHAR &&
603 mixtypes(l, r)) {
604 /* two steps needed here too */
605 NODE *x;
606
607 if (forarg) {
608 x = resc;
609 x->in.type = l->in.type;
610 }
611 else {
612 x = &resc[1];
613 *x = *l;
614 }
615 putstr("cvt");
616 prtype(r);
617 prtype(x);
618 putchar('\t');
619 adrput(r);
620 putchar(',');
621 adrput(x);
622 putstr("\n\t");
623 r = x;
624 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
625 }
626
627 else if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
74789784 628 mixtypes(l, r)) {
5270d49e 629 int label1;
10ff05ec
DS
630 NODE *x = NULL;
631
632#if defined(FORT) || defined(SPRECC)
633 if (forarg)
634#else
635 if (forarg || l == resc)
636#endif
637 {
638 /* compute in register, convert to double when done */
639 x = l;
640 l = resc;
641 l->in.type = x->in.type;
642 }
74789784
DS
643
644 label1 = getlab();
74789784 645
5270d49e 646 putstr("cvtl");
74789784
DS
647 prtype(l);
648 putchar('\t');
5270d49e 649 adrput(r);
74789784
DS
650 putchar(',');
651 adrput(l);
5270d49e 652 printf("\n\tjgeq\tL%d\n\tadd", label1);
74789784
DS
653 prtype(l);
654 putstr("2\t$0");
655 prtype(l);
5270d49e 656 putstr("4.294967296e9,");
74789784 657 adrput(l);
5270d49e 658 printf("\nL%d:", label1);
74789784 659
d2f82175
DS
660#if defined(FORT) || defined(SPRECC)
661 if (!forarg)
662#else
10ff05ec 663 if (!forarg && (l->in.type == DOUBLE || l != resc))
d2f82175 664#endif
10ff05ec 665 goto cleanup;
d2f82175
DS
666 if (x == NULL)
667 cerror("sconv botch");
668 if (l == x) {
669 r = &resc[1];
670 *r = *l;
671 }
672 else {
673 r = l;
674 l = x;
10ff05ec 675 }
d2f82175 676 l->in.type = DOUBLE;
10ff05ec
DS
677 putstr("\n\t");
678 }
679
d2f82175 680 else if( (l->in.type == FLOAT || l->in.type == DOUBLE) &&
10ff05ec
DS
681 (r->in.type == UCHAR || r->in.type == USHORT) ) {
682 /* skip unnecessary unsigned to floating conversion */
683#if defined(FORT) || defined(SPRECC)
684 if (forarg)
685#else
686 if (forarg || l == resc)
687#endif
688 l->in.type = DOUBLE;
689 putstr("movz");
690 prtype(r);
691 putstr("l\t");
692 adrput(r);
693 putchar(',');
694 adrput(resc);
695 putstr("\n\t");
696 if (l == resc) {
697 r = &resc[1];
698 *r = *l;
699 }
700 else
701 r = resc;
702 r->in.type = INT;
703 }
704
705#if defined(FORT) || defined(SPRECC)
706 if (forarg && l->in.type == FLOAT)
707#else
708 if ((forarg || l == resc) && l->in.type == FLOAT)
709#endif
710 {
711 /* perform an implicit conversion to double */
712 l->in.type = DOUBLE;
713 if (r->in.type != FLOAT &&
714 r->in.type != CHAR &&
715 r->in.type != SHORT) {
716 /* trim bits from the mantissa */
717 putstr("cvt");
718 prtype(r);
719 putstr("f\t");
720 adrput(r);
721 putchar(',');
722 adrput(resc);
723 putstr("\n\t");
724 if (l == resc) {
725 r = &resc[1];
726 *r = *l;
727 }
728 else
729 r = resc;
730 r->in.type = FLOAT;
731 }
439a068b 732 }
74789784
DS
733
734 if (!mixtypes(l,r)) {
735 if (tlen(l) == tlen(r)) {
6eafb37d
DS
736 if (forarg && tlen(l) == SZINT/SZCHAR) {
737 putstr("pushl\t");
738 adrput(r);
739 goto cleanup;
740 }
74789784
DS
741 putstr("mov");
742#ifdef FORT
743 if (Oflag)
744 prtype(l);
745 else {
746 if (l->in.type == DOUBLE)
747 putchar('q');
748 else if(l->in.type == FLOAT)
749 putchar('l');
750 else
751 prtype(l);
752 }
753#else
754 prtype(l);
755#endif FORT
756 goto ops;
757 }
758 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
759 putstr("movz");
760 else
761 putstr("cvt");
762 }
763 else
764 putstr("cvt");
765 prtype(r);
766 prtype(l);
767ops:
768 putchar('\t');
769 adrput(r);
770 putchar(',');
771 adrput(l);
772
773cleanup:
774 if (forarg)
775 tfree(l);
439a068b
ML
776 }
777
83d9f822
JB
778/*
779 * collapsible(dest, src) -- if a conversion with a register destination
780 * can be accomplished in one instruction, return the type of src
781 * that will do the job correctly; otherwise return 0. Note that
782 * a register must always end up having type INT or UNSIGNED.
783 */
784int
785collapsible(dest, src)
786NODE *dest, *src;
787{
788 int st = src->in.type;
789 int dt = dest->in.type;
790 int newt = 0;
791
792 /*
793 * Are there side effects of evaluating src?
794 * If the derived type will not be the same size as src,
88bb0c9f 795 * we may have to use two steps.
83d9f822 796 */
88bb0c9f
KM
797 if (tlen(src) > tlen(dest)) {
798 if (tshape(src, STARREG))
799 return (0);
800 if (src->in.op == OREG && R2TEST(src->tn.rval))
801 return (0);
802 }
83d9f822
JB
803
804 /*
805 * Can we get an object of dest's type by punning src?
806 * Praises be to great Cthulhu for little-endian machines...
807 */
808 if (st == CHAR && dt == USHORT)
809 /*
810 * Special case -- we must sign-extend to 16 bits.
811 */
812 return (0);
813
814 if (tlen(src) < tlen(dest))
815 newt = st;
816 else
817 newt = dt;
818
819 return (newt);
820 }
821
262eaf56 822rmove( rt, rs, t ) TWORD t; {
439a068b 823 printf( " %s %s,%s\n",
262eaf56
RC
824#ifdef FORT
825 !Oflag ? (t==DOUBLE ? "movq" : "movl") :
826#endif
439a068b
ML
827 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
828 rnames[rs], rnames[rt] );
829 }
830
831struct respref
832respref[] = {
833 INTAREG|INTBREG, INTAREG|INTBREG,
834 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
835 INTEMP, INTEMP,
836 FORARG, FORARG,
837 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
838 0, 0 };
839
840setregs(){ /* set up temporary registers */
841 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
439a068b
ML
842 }
843
6dc2c6c8 844/*ARGSUSED*/
439a068b
ML
845rewfld( p ) NODE *p; {
846 return(1);
847 }
848
6dc2c6c8 849/*ARGSUSED*/
439a068b
ML
850callreg(p) NODE *p; {
851 return( R0 );
852 }
853
854base( p ) register NODE *p; {
855 register int o = p->in.op;
856
6eafb37d 857 if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */
439a068b
ML
858 if( o==REG ) return( p->tn.rval );
859 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
860 return( p->in.left->tn.rval );
861 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
862 return( p->tn.rval + 0200*1 );
863 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
864 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
865 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
866 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
867 return( p->in.left->in.left->tn.rval + 0200*(1+2) );
6eafb37d 868 if( o==NAME ) return( 100 + 0200*1 );
439a068b
ML
869 return( -1 );
870 }
871
872offset( p, tyl ) register NODE *p; int tyl; {
873
88bb0c9f
KM
874 if( tyl==1 &&
875 p->in.op==REG &&
876 (p->in.type==INT || p->in.type==UNSIGNED) )
877 return( p->tn.rval );
878 if( p->in.op==LS &&
879 p->in.left->in.op==REG &&
880 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
881 p->in.right->in.op==ICON &&
882 p->in.right->in.name[0]=='\0' &&
883 (1<<p->in.right->tn.lval)==tyl)
884 return( p->in.left->tn.rval );
885 if( tyl==2 &&
886 p->in.op==PLUS &&
887 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
888 p->in.left->in.op==REG &&
889 p->in.right->in.op==REG &&
890 p->in.left->tn.rval==p->in.right->tn.rval )
439a068b
ML
891 return( p->in.left->tn.rval );
892 return( -1 );
893 }
894
895makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
896 register NODE *t;
439a068b
ML
897 NODE *f;
898
899 p->in.op = OREG;
900 f = p->in.left; /* have to free this subtree later */
901
902 /* init base */
903 switch (q->in.op) {
904 case ICON:
905 case REG:
906 case OREG:
6eafb37d 907 case NAME:
439a068b
ML
908 t = q;
909 break;
910
911 case MINUS:
912 q->in.right->tn.lval = -q->in.right->tn.lval;
913 case PLUS:
914 t = q->in.right;
915 break;
916
917 case INCR:
918 case ASG MINUS:
919 t = q->in.left;
920 break;
921
922 case UNARY MUL:
923 t = q->in.left->in.left;
924 break;
925
926 default:
927 cerror("illegal makeor2");
928 }
929
930 p->tn.lval = t->tn.lval;
931#ifndef FLEXNAMES
6dc2c6c8
DS
932 {
933 register int i;
934 for(i=0; i<NCHNAM; ++i)
935 p->in.name[i] = t->in.name[i];
936 }
439a068b
ML
937#else
938 p->in.name = t->in.name;
939#endif
940
941 /* init offset */
942 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
943
944 tfree(f);
945 return;
946 }
947
948canaddr( p ) NODE *p; {
949 register int o = p->in.op;
950
951 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
952 return(0);
953 }
954
74789784
DS
955flshape( p ) NODE *p; {
956 register int o = p->in.op;
957
958 return( o == REG || o == NAME || o == ICON ||
959 (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
439a068b
ML
960 }
961
10902f65 962/* INTEMP shapes must not contain any temporary registers */
439a068b 963shtemp( p ) register NODE *p; {
10902f65
DS
964 int r;
965
439a068b 966 if( p->in.op == STARG ) p = p->in.left;
10902f65
DS
967
968 switch (p->in.op) {
969 case REG:
970 return( !istreg(p->tn.rval) );
971 case OREG:
972 r = p->tn.rval;
973 if( R2TEST(r) ) {
974 if( istreg(R2UPK1(r)) )
975 return(0);
976 r = R2UPK2(r);
977 }
978 return( !istreg(r) );
10902f65
DS
979 case UNARY MUL:
980 p = p->in.left;
981 return( p->in.op != UNARY MUL && shtemp(p) );
10902f65
DS
982 }
983
984 if( optype( p->in.op ) != LTYPE ) return(0);
985 return(1);
439a068b
ML
986 }
987
988shumul( p ) register NODE *p; {
74789784 989 register int o;
439a068b
ML
990 extern int xdebug;
991
992 if (xdebug) {
f221fccf
DS
993 int val;
994 printf("shumul:\n");
995 eprint(p, 0, &val, &val);
439a068b
ML
996 }
997
439a068b
ML
998 o = p->in.op;
999 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
1000
1001 if( ( o == INCR || o == ASG MINUS ) &&
1002 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
1003 p->in.right->in.name[0] == '\0' )
1004 {
f83495a1 1005 switch (p->in.type)
439a068b
ML
1006 {
1007 case CHAR|PTR:
1008 case UCHAR|PTR:
1009 o = 1;
1010 break;
1011
1012 case SHORT|PTR:
1013 case USHORT|PTR:
1014 o = 2;
1015 break;
1016
1017 case INT|PTR:
1018 case UNSIGNED|PTR:
1019 case LONG|PTR:
1020 case ULONG|PTR:
1021 case FLOAT|PTR:
1022 o = 4;
1023 break;
1024
1025 case DOUBLE|PTR:
1026 o = 8;
1027 break;
1028
1029 default:
262eaf56
RC
1030 if ( ISPTR(p->in.type) &&
1031 ISPTR(DECREF(p->in.type)) ) {
439a068b
ML
1032 o = 4;
1033 break;
1034 }
1035 else return(0);
1036 }
1037 return( p->in.right->tn.lval == o ? STARREG : 0);
1038 }
1039
1040 return( 0 );
1041 }
1042
1043adrcon( val ) CONSZ val; {
88bb0c9f 1044 putchar( '$' );
439a068b
ML
1045 printf( CONFMT, val );
1046 }
1047
1048conput( p ) register NODE *p; {
1049 switch( p->in.op ){
1050
1051 case ICON:
1052 acon( p );
1053 return;
1054
1055 case REG:
88bb0c9f 1056 putstr( rnames[p->tn.rval] );
439a068b
ML
1057 return;
1058
1059 default:
1060 cerror( "illegal conput" );
1061 }
1062 }
1063
4ab1e9a8 1064/*ARGSUSED*/
6dc2c6c8 1065insput( p ) NODE *p; {
439a068b
ML
1066 cerror( "insput" );
1067 }
1068
70f59a26
DS
1069upput( p, size ) NODE *p; int size; {
1070 if( size == SZLONG && p->in.op == REG ) {
1071 putstr( rnames[p->tn.rval + 1] );
1072 return;
1073 }
439a068b
ML
1074 cerror( "upput" );
1075 }
1076
1077adrput( p ) register NODE *p; {
1078 register int r;
1079 /* output an address, with offsets, from p */
1080
1081 if( p->in.op == FLD ){
1082 p = p->in.left;
1083 }
1084 switch( p->in.op ){
1085
1086 case NAME:
1087 acon( p );
1088 return;
1089
1090 case ICON:
1091 /* addressable value of the constant */
88bb0c9f 1092 putchar( '$' );
439a068b
ML
1093 acon( p );
1094 return;
1095
1096 case REG:
88bb0c9f 1097 putstr( rnames[p->tn.rval] );
439a068b
ML
1098 return;
1099
1100 case OREG:
1101 r = p->tn.rval;
1102 if( R2TEST(r) ){ /* double indexing */
1103 register int flags;
1104
1105 flags = R2UPK3(r);
88bb0c9f
KM
1106 if( flags & 1 ) putchar('*');
1107 if( flags & 4 ) putchar('-');
439a068b
ML
1108 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1109 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
88bb0c9f 1110 if( flags & 2 ) putchar('+');
439a068b
ML
1111 printf( "[%s]", rnames[R2UPK2(r)] );
1112 return;
1113 }
1114 if( r == AP ){ /* in the argument region */
237a345d 1115 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
439a068b 1116 printf( CONFMT, p->tn.lval );
88bb0c9f 1117 putstr( "(ap)" );
439a068b
ML
1118 return;
1119 }
1120 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1121 printf( "(%s)", rnames[p->tn.rval] );
1122 return;
1123
1124 case UNARY MUL:
1125 /* STARNM or STARREG found */
1126 if( tshape(p, STARNM) ) {
88bb0c9f 1127 putchar( '*' );
439a068b
ML
1128 adrput( p->in.left);
1129 }
1130 else { /* STARREG - really auto inc or dec */
1131 register NODE *q;
1132
439a068b 1133 q = p->in.left;
262eaf56
RC
1134 if( q->in.right->tn.lval != tlen(p) )
1135 cerror("adrput: bad auto-increment/decrement");
f83495a1
RC
1136 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
1137 rnames[q->in.left->tn.rval],
1138 (q->in.op==INCR ? "+" : "") );
1139 p->in.op = OREG;
1140 p->tn.rval = q->in.left->tn.rval;
1141 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
439a068b
ML
1142#ifndef FLEXNAMES
1143 p->in.name[0] = '\0';
1144#else
1145 p->in.name = "";
1146#endif
1147 tfree(q);
1148 }
1149 return;
1150
1151 default:
1152 cerror( "illegal address" );
1153 return;
1154
1155 }
1156
1157 }
1158
1159acon( p ) register NODE *p; { /* print out a constant */
1160
74789784 1161 if( p->in.name[0] == '\0' )
439a068b 1162 printf( CONFMT, p->tn.lval);
74789784 1163 else {
439a068b
ML
1164#ifndef FLEXNAMES
1165 printf( "%.8s", p->in.name );
1166#else
88bb0c9f 1167 putstr( p->in.name );
439a068b 1168#endif
74789784
DS
1169 if( p->tn.lval != 0 ) {
1170 putchar( '+' );
1171 printf( CONFMT, p->tn.lval );
1172 }
439a068b
ML
1173 }
1174 }
439a068b
ML
1175
1176genscall( p, cookie ) register NODE *p; {
1177 /* structure valued call */
1178 return( gencall( p, cookie ) );
1179 }
1180
1181/* tbl */
1182int gc_numbytes;
1183/* tbl */
1184
6dc2c6c8 1185/*ARGSUSED*/
439a068b
ML
1186gencall( p, cookie ) register NODE *p; {
1187 /* generate the call given by p */
3add848c 1188 register NODE *p1;
74789784
DS
1189 register int temp, temp1;
1190 register int m;
439a068b
ML
1191
1192 if( p->in.right ) temp = argsize( p->in.right );
1193 else temp = 0;
1194
1195 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1196 /* set aside room for structure return */
1197
1198 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1199 else temp1 = temp;
1200 }
1201
1202 if( temp > maxargs ) maxargs = temp;
1203 SETOFF(temp1,4);
1204
1205 if( p->in.right ){ /* make temp node, put offset in, and generate args */
3add848c 1206 genargs( p->in.right );
439a068b
ML
1207 }
1208
1209 p1 = p->in.left;
1210 if( p1->in.op != ICON ){
1211 if( p1->in.op != REG ){
1212 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1213 if( p1->in.op != NAME ){
1214 order( p1, INAREG );
1215 }
1216 }
1217 }
1218 }
1219
439a068b
ML
1220/* tbl
1221 setup gc_numbytes so reference to ZC works */
1222
1223 gc_numbytes = temp&(0x3ff);
1224/* tbl */
1225
1226 p->in.op = UNARY CALL;
1227 m = match( p, INTAREG|INTBREG );
1228
1229 /* compensate for deficiency in 'ret' instruction ... wah,kre */
1230 /* (plus in assignment to gc_numbytes above, for neatness only) */
1231 if (temp >= 1024)
1232 printf(" addl2 $%d,sp\n", (temp&(~0x3ff)));
1233
439a068b
ML
1234 return(m != MDONE);
1235 }
1236
1237/* tbl */
1238char *
1239ccbranches[] = {
74789784
DS
1240 "eql",
1241 "neq",
1242 "leq",
1243 "lss",
1244 "geq",
1245 "gtr",
1246 "lequ",
1247 "lssu",
1248 "gequ",
1249 "gtru",
439a068b
ML
1250 };
1251/* tbl */
1252
6dc2c6c8 1253/*ARGSUSED*/
439a068b
ML
1254cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1255
74789784
DS
1256 if( o != 0 && ( o < EQ || o > UGT ) )
1257 cerror( "bad conditional branch: %s", opst[o] );
1258 printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
439a068b
ML
1259 }
1260
1261nextcook( p, cookie ) NODE *p; {
1262 /* we have failed to match p with cookie; try another */
1263 if( cookie == FORREW ) return( 0 ); /* hopeless! */
1264 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1265 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1266 return( FORREW );
1267 }
1268
6dc2c6c8 1269/*ARGSUSED*/
439a068b
ML
1270lastchance( p, cook ) NODE *p; {
1271 /* forget it! */
1272 return(0);
1273 }
1274
1275optim2( p ) register NODE *p; {
1276 /* do local tree transformations and optimizations */
1277
71cac6bf 1278 int o;
bcc20d15 1279 int i, mask;
472582a4 1280 register NODE *l, *r;
439a068b 1281
71cac6bf 1282 switch( o = p->in.op ) {
439a068b 1283
4f1e05c6
DS
1284 case ASG PLUS:
1285 case ASG MINUS:
1286 case ASG MUL:
1287 case ASG OR:
1288 /* simple ASG OPSIMP -- reduce range of constant rhs */
1289 l = p->in.left;
1290 r = p->in.right;
1291 if( tlen(l) < SZINT/SZCHAR &&
1292 r->in.op==ICON && r->in.name[0]==0 ){
1293 mask = (1 << tlen(l) * SZCHAR) - 1;
1294 if( r->tn.lval & (mask & ~(mask >> 1)) )
1295 r->tn.lval |= ~mask;
1296 else
1297 r->tn.lval &= mask;
1298 }
1299 break;
1300
439a068b 1301 case AND:
85696ba1 1302 /* commute L and R to eliminate complements and constants */
472582a4
RC
1303 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1304 l->in.op == COMPL ) {
439a068b 1305 p->in.left = p->in.right;
472582a4 1306 p->in.right = l;
439a068b 1307 }
4f1e05c6
DS
1308 /* fall through */
1309
439a068b 1310 case ASG AND:
4f1e05c6 1311 /* change meaning of AND to ~R&L - bic on pdp11/vax */
439a068b 1312 r = p->in.right;
89ccccb8
DS
1313 if( r->in.op==ICON && r->in.name[0]==0 ) {
1314 /* check for degenerate operations */
1315 l = p->in.left;
bcc20d15 1316 mask = (1 << tlen(l) * SZCHAR) - 1;
4f1e05c6
DS
1317 if( o == ASG AND || ISUNSIGNED(r->in.type) ) {
1318 i = ~r->tn.lval & mask;
6eafb37d 1319 if( i == 0 ) {
4f1e05c6 1320 /* redundant mask */
bcc20d15
DS
1321 r->in.op = FREE;
1322 ncopy(p, l);
1323 l->in.op = FREE;
1324 break;
1325 }
6eafb37d 1326 else if( i == mask )
4f1e05c6 1327 /* all bits masked off */
bcc20d15 1328 goto zero;
4f1e05c6
DS
1329 r->tn.lval = i;
1330 if( tlen(l) < SZINT/SZCHAR ){
1331 /* sign extend */
1332 if( r->tn.lval & (mask & ~(mask >> 1)) )
1333 r->tn.lval |= ~mask;
1334 else
1335 r->tn.lval &= mask;
1336 }
6eafb37d 1337 break;
bcc20d15
DS
1338 }
1339 else if( r->tn.lval == mask &&
1340 tlen(l) < SZINT/SZCHAR ) {
4f1e05c6 1341 /* use movz instead of bic */
bcc20d15
DS
1342 r->in.op = SCONV;
1343 r->in.left = l;
1344 r->in.right = 0;
1345 r->in.type = ENUNSIGN(l->in.type);
1346 r->in.su = l->in.su > 1 ? l->in.su : 1;
1347 ncopy(p, r);
1348 p->in.left = r;
1349 p->in.type = INT;
89ccccb8
DS
1350 break;
1351 }
1352 /* complement constant */
439a068b
ML
1353 r->tn.lval = ~r->tn.lval;
1354 }
1355 else if( r->in.op==COMPL ) { /* ~~A => A */
1356 r->in.op = FREE;
1357 p->in.right = r->in.left;
1358 }
1359 else { /* insert complement node */
472582a4
RC
1360 p->in.right = l = talloc();
1361 l->in.op = COMPL;
1362 l->in.rall = NOPREF;
1363 l->in.type = r->in.type;
1364 l->in.left = r;
1365 l->in.right = NULL;
439a068b
ML
1366 }
1367 break;
1368
472582a4 1369 case SCONV:
85696ba1 1370 l = p->in.left;
262eaf56 1371#if defined(FORT) || defined(SPRECC)
7f12173b 1372 if( p->in.type == FLOAT || p->in.type == DOUBLE ||
85696ba1
KM
1373 l->in.type == FLOAT || l->in.type == DOUBLE )
1374 return;
7f12173b 1375#else
85696ba1 1376 if( mixtypes(p, l) ) return;
7f12173b 1377#endif
6eafb37d
DS
1378 if( l->in.op == PCONV )
1379 return;
1380 if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
1381 l->in.type != INT && l->in.type != UNSIGNED )
4bcc0eaf
DS
1382 return;
1383
85696ba1
KM
1384 /* Only trust it to get it right if the size is the same */
1385 if( tlen(p) != tlen(l) )
1386 return;
472582a4
RC
1387
1388 /* clobber conversion */
85696ba1 1389 if( l->in.op != FLD )
472582a4
RC
1390 l->in.type = p->in.type;
1391 ncopy( p, l );
1392 l->in.op = FREE;
85696ba1 1393
472582a4
RC
1394 break;
1395
88bb0c9f
KM
1396 case ASSIGN:
1397 /*
1398 * Conversions are equivalent to assignments;
1399 * when the two operations are combined,
1400 * we can sometimes zap the conversion.
1401 */
1402 r = p->in.right;
1403 l = p->in.left;
1404 if ( r->in.op == SCONV &&
1405 !mixtypes(l, r) &&
ef3be726 1406 l->in.op != FLD &&
88bb0c9f
KM
1407 tlen(l) == tlen(r) ) {
1408 p->in.right = r->in.left;
1409 r->in.op = FREE;
1410 }
1411 break;
1412
71cac6bf
DS
1413 case ULE:
1414 case ULT:
1415 case UGE:
1416 case UGT:
89ccccb8
DS
1417 p->in.op -= (UGE-GE);
1418 if( degenerate(p) )
1419 break;
1420 p->in.op += (UGE-GE);
1421 break;
1422
71cac6bf
DS
1423 case EQ:
1424 case NE:
1425 case LE:
1426 case LT:
1427 case GE:
1428 case GT:
6eafb37d
DS
1429 if( p->in.left->in.op == SCONV &&
1430 p->in.right->in.op == SCONV ) {
1431 l = p->in.left;
1432 r = p->in.right;
1433 if( l->in.type == DOUBLE &&
1434 l->in.left->in.type == FLOAT &&
1435 r->in.left->in.type == FLOAT ) {
1436 /* nuke the conversions */
1437 p->in.left = l->in.left;
1438 p->in.right = r->in.left;
1439 l->in.op = FREE;
1440 r->in.op = FREE;
1441 }
1442 /* more? */
1443 }
89ccccb8
DS
1444 (void) degenerate(p);
1445 break;
1446
1447 case DIV:
1448 if( p->in.right->in.op == ICON &&
1449 p->in.right->tn.name[0] == '\0' &&
1450 ISUNSIGNED(p->in.right->in.type) &&
1451 (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
1452 /* easy to do here, harder to do in zzzcode() */
1453 p->in.op = UGE;
71cac6bf 1454 break;
89ccccb8
DS
1455 }
1456 case MOD:
1457 case ASG DIV:
1458 case ASG MOD:
1459 /*
1460 * optimize DIV and MOD
1461 *
1462 * basically we spot UCHAR and USHORT and try to do them
1463 * as signed ints... apparently div+mul+sub is always
1464 * faster than ediv for finding MOD on the VAX, when
1465 * full unsigned MOD isn't needed.
1466 *
1467 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
1468 * are faster for unsigned dividend and a constant divisor
1469 * in the right range (.5 to 1 of dividend's range for the
1470 * first, .333+ to .5 for the second). full unsigned is
1471 * already done cmp+sub in the appropriate case; the
1472 * other cases are less common and require more ambition.
1473 */
1474 if( degenerate(p) )
71cac6bf 1475 break;
89ccccb8
DS
1476 l = p->in.left;
1477 r = p->in.right;
1478 if( !ISUNSIGNED(r->in.type) ||
1479 tlen(l) >= SZINT/SZCHAR ||
1480 !(tlen(r) < SZINT/SZCHAR ||
1481 (r->in.op == ICON && r->tn.name[0] == '\0')) )
71cac6bf 1482 break;
89ccccb8
DS
1483 if( r->in.op == ICON )
1484 r->tn.type = INT;
1485 else {
1486 NODE *t = talloc();
1487 t->in.left = r;
1488 r = t;
1489 r->in.op = SCONV;
1490 r->in.type = INT;
1491 r->in.right = 0;
1492 p->in.right = r;
71cac6bf 1493 }
89ccccb8
DS
1494 if( o == DIV || o == MOD ) {
1495 NODE *t = talloc();
1496 t->in.left = l;
1497 l = t;
1498 l->in.op = SCONV;
1499 l->in.type = INT;
1500 l->in.right = 0;
1501 p->in.left = l;
1502 }
1503 /* handle asgops in table */
1504 break;
1505
1506 case RS:
1507 case ASG RS:
1508 case LS:
1509 case ASG LS:
1510 /* pick up degenerate shifts */
1511 l = p->in.left;
1512 r = p->in.right;
1513 if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
71cac6bf 1514 break;
89ccccb8
DS
1515 i = r->tn.lval;
1516 if( i < 0 )
1517 /* front end 'fixes' this? */
1518 if( o == LS || o == ASG LS )
1519 o += (RS-LS);
1520 else
1521 o += (LS-RS);
1522 if( (o == RS || o == ASG RS) &&
1523 !ISUNSIGNED(l->in.type) )
1524 /* can't optimize signed right shifts */
71cac6bf 1525 break;
74789784
DS
1526 if( o == LS ) {
1527 if( i < SZINT )
1528 break;
1529 }
1530 else {
1531 if( i < tlen(l) * SZCHAR )
1532 break;
1533 }
89ccccb8
DS
1534 zero:
1535 if( !asgop( o ) )
1536 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1537 /* no side effects */
bcc20d15 1538 tfree(l);
89ccccb8
DS
1539 ncopy(p, r);
1540 r->in.op = FREE;
1541 p->tn.lval = 0;
1542 }
1543 else {
1544 p->in.op = COMOP;
bcc20d15 1545 r->tn.lval = 0;
89ccccb8
DS
1546 }
1547 else {
1548 p->in.op = ASSIGN;
1549 r->tn.lval = 0;
71cac6bf 1550 }
89ccccb8
DS
1551 break;
1552 }
1553 }
1554
1555degenerate(p) register NODE *p; {
1556 int o;
1557 int result, i;
1558 int lower, upper;
1559 register NODE *l, *r;
1560
1561 /*
1562 * try to keep degenerate comparisons with constants
1563 * out of the table.
1564 */
1565 r = p->in.right;
1566 l = p->in.left;
1567 if( r->in.op != ICON ||
1568 r->tn.name[0] != '\0' ||
1569 tlen(l) >= tlen(r) )
1570 return (0);
1571 switch( l->in.type ) {
1572 case CHAR:
1573 lower = -(1 << SZCHAR - 1);
1574 upper = (1 << SZCHAR - 1) - 1;
1575 break;
1576 case UCHAR:
1577 lower = 0;
1578 upper = (1 << SZCHAR) - 1;
1579 break;
1580 case SHORT:
1581 lower = -(1 << SZSHORT - 1);
1582 upper = (1 << SZSHORT - 1) - 1;
1583 break;
1584 case USHORT:
1585 lower = 0;
1586 upper = (1 << SZSHORT) - 1;
1587 break;
1588 default:
bcc20d15 1589 cerror("unsupported type in degenerate()");
89ccccb8
DS
1590 }
1591 i = r->tn.lval;
1592 switch( o = p->in.op ) {
1593 case DIV:
1594 case ASG DIV:
1595 case MOD:
1596 case ASG MOD:
1597 /* DIV and MOD work like EQ */
1598 case EQ:
1599 case NE:
1600 if( lower == 0 && (unsigned) i > upper )
1601 result = o == NE;
1602 else if( i < lower || i > upper )
1603 result = o == NE;
1604 else
1605 return (0);
1606 break;
1607 case LT:
1608 case GE:
1609 if( lower == 0 && (unsigned) i > upper )
1610 result = o == LT;
1611 else if( i <= lower )
1612 result = o != LT;
1613 else if( i > upper )
1614 result = o == LT;
1615 else
1616 return (0);
1617 break;
1618 case LE:
1619 case GT:
1620 if( lower == 0 && (unsigned) i >= upper )
1621 result = o == LE;
1622 else if( i < lower )
1623 result = o != LE;
1624 else if( i >= upper )
1625 result = o == LE;
1626 else
1627 return (0);
1628 break;
1629 default:
1630 cerror("unknown op in degenerate()");
1631 }
1632
1633 if( o == MOD || o == ASG MOD ) {
1634 r->in.op = FREE;
1635 ncopy(p, l);
1636 l->in.op = FREE;
1637 }
1638 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1639 /* no side effects */
bcc20d15 1640 tfree(l);
89ccccb8
DS
1641 ncopy(p, r);
1642 r->in.op = FREE;
1643 p->tn.lval = result;
1644 }
1645 else {
1646 if( o == ASG DIV )
1647 p->in.op = ASSIGN;
71cac6bf
DS
1648 else {
1649 p->in.op = COMOP;
71cac6bf 1650 r->tn.type = INT;
71cac6bf 1651 }
89ccccb8 1652 r->tn.lval = result;
439a068b 1653 }
89ccccb8
DS
1654 if( logop(o) )
1655 p->in.type = INT;
1656
1657 return (1);
439a068b
ML
1658 }
1659
439a068b
ML
1660/* added by jwf */
1661struct functbl {
1662 int fop;
1663 TWORD ftype;
1664 char *func;
1665 } opfunc[] = {
1666 DIV, TANY, "udiv",
1667 MOD, TANY, "urem",
28312bdc
RC
1668 ASG DIV, TANY, "audiv",
1669 ASG MOD, TANY, "aurem",
439a068b
ML
1670 0, 0, 0 };
1671
1672hardops(p) register NODE *p; {
1673 /* change hard to do operators into function calls. */
1674 register NODE *q;
1675 register struct functbl *f;
1676 register o;
262eaf56 1677 NODE *old,*temp;
439a068b
ML
1678
1679 o = p->in.op;
262eaf56
RC
1680 if( ! (optype(o)==BITYPE &&
1681 (ISUNSIGNED(p->in.left->in.type) ||
1682 ISUNSIGNED(p->in.right->in.type))) )
1683 return;
439a068b
ML
1684
1685 for( f=opfunc; f->fop; f++ ) {
1686 if( o==f->fop ) goto convert;
1687 }
1688 return;
1689
439a068b 1690 convert:
89ccccb8 1691 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
70f59a26
DS
1692 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
1693 /* save a subroutine call -- use at most 5 instructions */
70f59a26 1694 return;
89ccccb8
DS
1695 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
1696 /* optim2() will modify the op into an ordinary int op */
1697 return;
439a068b 1698 if( asgop( o ) ) {
262eaf56 1699 old = NIL;
28312bdc 1700 switch( p->in.left->in.op ){
262eaf56
RC
1701 case FLD:
1702 q = p->in.left->in.left;
1703 /*
1704 * rewrite (lval.fld /= rval); as
1705 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1706 * else the compiler will evaluate lval twice.
1707 */
1708 if( q->in.op == UNARY MUL ){
1709 /* first allocate a temp storage */
1710 temp = talloc();
1711 temp->in.op = OREG;
1712 temp->tn.rval = TMPREG;
1713 temp->tn.lval = BITOOR(freetemp(1));
1714 temp->in.type = INCREF(p->in.type);
1715#ifdef FLEXNAMES
1716 temp->in.name = "";
1717#else
1718 temp->in.name[0] = '\0';
1719#endif
1720 old = q->in.left;
1721 q->in.left = temp;
1722 }
1723 /* fall thru ... */
1724
28312bdc
RC
1725 case REG:
1726 case NAME:
1727 case OREG:
1728 /* change ASG OP to a simple OP */
1729 q = talloc();
1730 q->in.op = NOASG p->in.op;
1731 q->in.rall = NOPREF;
1732 q->in.type = p->in.type;
1733 q->in.left = tcopy(p->in.left);
1734 q->in.right = p->in.right;
1735 p->in.op = ASSIGN;
1736 p->in.right = q;
1737 p = q;
1738 f -= 2; /* Note: this depends on the table order */
262eaf56
RC
1739 /* on the right side only - replace *temp with
1740 *(temp = &lval), build the assignment node */
1741 if( old ){
1742 temp = q->in.left->in.left; /* the "*" node */
1743 q = talloc();
1744 q->in.op = ASSIGN;
1745 q->in.left = temp->in.left;
1746 q->in.right = old;
1747 q->in.type = old->in.type;
1748#ifdef FLEXNAMES
1749 q->in.name = "";
1750#else
1751 q->in.name[0] = '\0';
1752#endif
1753 temp->in.left = q;
1754 }
28312bdc
RC
1755 break;
1756
1757 case UNARY MUL:
1758 /* avoid doing side effects twice */
1759 q = p->in.left;
1760 p->in.left = q->in.left;
1761 q->in.op = FREE;
1762 break;
1763
1764 default:
1765 cerror( "hardops: can't compute & LHS" );
1766 }
262eaf56 1767 }
439a068b
ML
1768
1769 /* build comma op for args to function */
1770 q = talloc();
1771 q->in.op = CM;
1772 q->in.rall = NOPREF;
1773 q->in.type = INT;
1774 q->in.left = p->in.left;
1775 q->in.right = p->in.right;
1776 p->in.op = CALL;
1777 p->in.right = q;
1778
1779 /* put function name in left node of call */
1780 p->in.left = q = talloc();
1781 q->in.op = ICON;
1782 q->in.rall = NOPREF;
1783 q->in.type = INCREF( FTN + p->in.type );
1784#ifndef FLEXNAMES
1785 strcpy( q->in.name, f->func );
1786#else
1787 q->in.name = f->func;
1788#endif
1789 q->tn.lval = 0;
1790 q->tn.rval = 0;
1791
439a068b
ML
1792 }
1793
262eaf56
RC
1794zappost(p) NODE *p; {
1795 /* look for ++ and -- operators and remove them */
1796
74789784 1797 register int o, ty;
262eaf56
RC
1798 register NODE *q;
1799 o = p->in.op;
1800 ty = optype( o );
1801
1802 switch( o ){
1803
1804 case INCR:
1805 case DECR:
1806 q = p->in.left;
1807 p->in.right->in.op = FREE; /* zap constant */
1808 ncopy( p, q );
1809 q->in.op = FREE;
1810 return;
1811
1812 }
1813
1814 if( ty == BITYPE ) zappost( p->in.right );
1815 if( ty != LTYPE ) zappost( p->in.left );
1816}
1817
1818fixpre(p) NODE *p; {
1819
74789784 1820 register int o, ty;
262eaf56
RC
1821 o = p->in.op;
1822 ty = optype( o );
1823
1824 switch( o ){
1825
1826 case ASG PLUS:
1827 p->in.op = PLUS;
1828 break;
1829 case ASG MINUS:
1830 p->in.op = MINUS;
1831 break;
1832 }
1833
1834 if( ty == BITYPE ) fixpre( p->in.right );
1835 if( ty != LTYPE ) fixpre( p->in.left );
1836}
1837
74789784
DS
1838/*ARGSUSED*/
1839NODE * addroreg(l) NODE *l;
1840 /* OREG was built in clocal()
1841 * for an auto or formal parameter
1842 * now its address is being taken
1843 * local code must unwind it
1844 * back to PLUS/MINUS REG ICON
1845 * according to local conventions
1846 */
1847{
1848 cerror("address of OREG taken");
1849 /*NOTREACHED*/
1850}
1851
1852
1853
1854# ifndef ONEPASS
1855main( argc, argv ) char *argv[]; {
1856 return( mainp2( argc, argv ) );
1857 }
1858# endif
1859
88bb0c9f
KM
1860strip(p) register NODE *p; {
1861 NODE *q;
1862
1863 /* strip nodes off the top when no side effects occur */
1864 for( ; ; ) {
1865 switch( p->in.op ) {
1866 case SCONV: /* remove lint tidbits */
1867 q = p->in.left;
1868 ncopy( p, q );
1869 q->in.op = FREE;
1870 break;
1871 /* could probably add a few more here */
1872 default:
1873 return;
1874 }
1875 }
1876 }
1877
439a068b 1878myreader(p) register NODE *p; {
88bb0c9f 1879 strip( p ); /* strip off operations with no side effects */
262eaf56 1880 canon( p ); /* expands r-vals for fields */
439a068b 1881 walkf( p, hardops ); /* convert ops to function calls */
439a068b 1882 walkf( p, optim2 );
439a068b 1883 }