utah rcsid 1.28 87/08/24 01:55:20: (1) Changed code for ZZ so that we can
[unix-history] / usr / src / old / pcc / ccom.vax / local2.c
CommitLineData
262eaf56 1# ifndef lint
6eafb37d 2static char *sccsid ="@(#)local2.c 1.32 (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 = "";
6eafb37d 471 p->tn.lval = szty(ty) * (SZINT/SZCHAR);
74789784
DS
472 q->in.right = p;
473 p = talloc();
474 p->in.op = UNARY MUL;
475 p->in.left = q;
476 return( p );
477 }
478
479sconv( p, forarg ) register NODE *p; {
480 register NODE *l, *r;
481 int m, val;
482
483 if (xdebug) eprint(p, 0, &val, &val);
484 r = getlr(p, 'R');
485 if (p->in.op == ASSIGN)
486 l = getlr(p, 'L');
487 else if (p->in.op == SCONV) {
488#if defined(FORT) || defined(SPRECC)
489 m = r->in.type;
490#else
491 m = r->in.type==FLOAT ? DOUBLE : r->in.type;
492#endif
493 if (forarg)
494 l = makearg( m );
495 else
496 l = resc;
497 l->in.type = m;
498 r = getlr(p, 'L');
499 }
500 else { /* OPLTYPE */
501#if defined(FORT) || defined(SPRECC)
502 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
503#else
504 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
505#endif
506 if (forarg)
507 l = makearg( m );
508 else
509 l = resc;
510 l->in.type = m;
511 }
512 if (r->in.op == ICON)
513 if (r->in.name[0] == '\0') {
6eafb37d 514 if (r->tn.lval == 0 && !forarg) {
74789784
DS
515 putstr("clr");
516 prtype(l);
517 putchar('\t');
3add848c 518 adrput(l);
74789784
DS
519 goto cleanup;
520 }
521 if (r->tn.lval < 0 && r->tn.lval >= -63) {
522 putstr("mneg");
523 prtype(l);
524 r->tn.lval = -r->tn.lval;
525 goto ops;
3add848c 526 }
74789784
DS
527 if (r->tn.lval < 0)
528 r->in.type = r->tn.lval >= -128 ? CHAR
529 : (r->tn.lval >= -32768 ? SHORT
530 : INT);
531 else if (l->in.type == FLOAT ||
532 l->in.type == DOUBLE)
533 r->in.type = r->tn.lval <= 63 ? INT
534 : (r->tn.lval <= 127 ? CHAR
535 : (r->tn.lval <= 32767 ? SHORT
536 : INT));
3add848c 537 else
74789784
DS
538 r->in.type = r->tn.lval <= 63 ? INT
539 : (r->tn.lval <= 127 ? CHAR
540 : (r->tn.lval <= 255 ? UCHAR
541 : (r->tn.lval <= 32767 ? SHORT
542 : (r->tn.lval <= 65535 ? USHORT
543 : INT))));
6eafb37d
DS
544 if (forarg && r->in.type == INT) {
545 putstr("pushl\t");
546 adrput(r);
547 goto cleanup;
548 }
74789784
DS
549 }
550 else {
6eafb37d
DS
551 if (forarg && tlen(r) == SZINT/SZCHAR) {
552 putstr("pushl\t");
553 adrput(r);
554 goto cleanup;
555 }
556 putstr("moval\t");
74789784
DS
557 acon(r);
558 putchar(',');
559 adrput(l);
560 goto cleanup;
561 }
439a068b 562
74789784
DS
563 if (p->in.op == SCONV &&
564 !(l->in.type == FLOAT || l->in.type == DOUBLE) &&
565 !mixtypes(l, r)) {
566 /*
567 * Because registers must always contain objects
568 * of the same width as INTs, we may have to
569 * perform two conversions to get an INT. Can
570 * the conversions be collapsed into one?
571 */
572 if (m = collapsible(l, r))
573 r->in.type = m;
574 else {
575 /*
576 * Two steps are required.
577 */
578 NODE *x = &resc[1];
439a068b 579
74789784
DS
580 *x = *l;
581 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type))
582 putstr("movz");
583 else
584 putstr("cvt");
585 prtype(r);
586 prtype(x);
587 putchar('\t');
588 adrput(r);
589 putchar(',');
590 adrput(x);
591 putchar('\n');
592 putchar('\t');
593 r = x;
439a068b 594 }
74789784
DS
595 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT);
596 }
439a068b 597
74789784
DS
598 if ((r->in.type == UNSIGNED || r->in.type == ULONG) &&
599 mixtypes(l, r)) {
600 int label1, label2;
601
602 label1 = getlab();
603 label2 = getlab();
604
605 putstr("movl\t");
606 adrput(r);
607 putchar(',');
608 adrput(l);
609 putstr("\n\tjbsc\t$31,");
610 adrput(l);
611 printf(",L%d\n\tcvtl", label1);
612 prtype(l);
613 putchar('\t');
614 adrput(l);
615 putchar(',');
616 adrput(l);
617 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1);
618 prtype(l);
619 putchar('\t');
620 adrput(l);
621 putchar(',');
622 adrput(l);
623 putstr("\n\tadd");
624 prtype(l);
625 putstr("2\t$0");
626 prtype(l);
627 putstr("2.147483648e9,");
628 adrput(l);
629 printf("\nL%d:", label2);
630
631 goto cleanup;
439a068b 632 }
74789784
DS
633
634 if (!mixtypes(l,r)) {
635 if (tlen(l) == tlen(r)) {
6eafb37d
DS
636 if (forarg && tlen(l) == SZINT/SZCHAR) {
637 putstr("pushl\t");
638 adrput(r);
639 goto cleanup;
640 }
74789784
DS
641 putstr("mov");
642#ifdef FORT
643 if (Oflag)
644 prtype(l);
645 else {
646 if (l->in.type == DOUBLE)
647 putchar('q');
648 else if(l->in.type == FLOAT)
649 putchar('l');
650 else
651 prtype(l);
652 }
653#else
654 prtype(l);
655#endif FORT
656 goto ops;
657 }
658 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
659 putstr("movz");
660 else
661 putstr("cvt");
662 }
663 else
664 putstr("cvt");
665 prtype(r);
666 prtype(l);
667ops:
668 putchar('\t');
669 adrput(r);
670 putchar(',');
671 adrput(l);
672
673cleanup:
674 if (forarg)
675 tfree(l);
439a068b
ML
676 }
677
83d9f822
JB
678/*
679 * collapsible(dest, src) -- if a conversion with a register destination
680 * can be accomplished in one instruction, return the type of src
681 * that will do the job correctly; otherwise return 0. Note that
682 * a register must always end up having type INT or UNSIGNED.
683 */
684int
685collapsible(dest, src)
686NODE *dest, *src;
687{
688 int st = src->in.type;
689 int dt = dest->in.type;
690 int newt = 0;
691
692 /*
693 * Are there side effects of evaluating src?
694 * If the derived type will not be the same size as src,
88bb0c9f 695 * we may have to use two steps.
83d9f822 696 */
88bb0c9f
KM
697 if (tlen(src) > tlen(dest)) {
698 if (tshape(src, STARREG))
699 return (0);
700 if (src->in.op == OREG && R2TEST(src->tn.rval))
701 return (0);
702 }
83d9f822
JB
703
704 /*
705 * Can we get an object of dest's type by punning src?
706 * Praises be to great Cthulhu for little-endian machines...
707 */
708 if (st == CHAR && dt == USHORT)
709 /*
710 * Special case -- we must sign-extend to 16 bits.
711 */
712 return (0);
713
714 if (tlen(src) < tlen(dest))
715 newt = st;
716 else
717 newt = dt;
718
719 return (newt);
720 }
721
262eaf56 722rmove( rt, rs, t ) TWORD t; {
439a068b 723 printf( " %s %s,%s\n",
262eaf56
RC
724#ifdef FORT
725 !Oflag ? (t==DOUBLE ? "movq" : "movl") :
726#endif
439a068b
ML
727 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
728 rnames[rs], rnames[rt] );
729 }
730
731struct respref
732respref[] = {
733 INTAREG|INTBREG, INTAREG|INTBREG,
734 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
735 INTEMP, INTEMP,
736 FORARG, FORARG,
737 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
738 0, 0 };
739
740setregs(){ /* set up temporary registers */
741 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
439a068b
ML
742 }
743
6dc2c6c8 744/*ARGSUSED*/
439a068b
ML
745rewfld( p ) NODE *p; {
746 return(1);
747 }
748
6dc2c6c8 749/*ARGSUSED*/
439a068b
ML
750callreg(p) NODE *p; {
751 return( R0 );
752 }
753
754base( p ) register NODE *p; {
755 register int o = p->in.op;
756
6eafb37d 757 if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */
439a068b
ML
758 if( o==REG ) return( p->tn.rval );
759 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
760 return( p->in.left->tn.rval );
761 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
762 return( p->tn.rval + 0200*1 );
763 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
764 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
765 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
766 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
767 return( p->in.left->in.left->tn.rval + 0200*(1+2) );
6eafb37d 768 if( o==NAME ) return( 100 + 0200*1 );
439a068b
ML
769 return( -1 );
770 }
771
772offset( p, tyl ) register NODE *p; int tyl; {
773
88bb0c9f
KM
774 if( tyl==1 &&
775 p->in.op==REG &&
776 (p->in.type==INT || p->in.type==UNSIGNED) )
777 return( p->tn.rval );
778 if( p->in.op==LS &&
779 p->in.left->in.op==REG &&
780 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
781 p->in.right->in.op==ICON &&
782 p->in.right->in.name[0]=='\0' &&
783 (1<<p->in.right->tn.lval)==tyl)
784 return( p->in.left->tn.rval );
785 if( tyl==2 &&
786 p->in.op==PLUS &&
787 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
788 p->in.left->in.op==REG &&
789 p->in.right->in.op==REG &&
790 p->in.left->tn.rval==p->in.right->tn.rval )
439a068b
ML
791 return( p->in.left->tn.rval );
792 return( -1 );
793 }
794
795makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
796 register NODE *t;
439a068b
ML
797 NODE *f;
798
799 p->in.op = OREG;
800 f = p->in.left; /* have to free this subtree later */
801
802 /* init base */
803 switch (q->in.op) {
804 case ICON:
805 case REG:
806 case OREG:
6eafb37d 807 case NAME:
439a068b
ML
808 t = q;
809 break;
810
811 case MINUS:
812 q->in.right->tn.lval = -q->in.right->tn.lval;
813 case PLUS:
814 t = q->in.right;
815 break;
816
817 case INCR:
818 case ASG MINUS:
819 t = q->in.left;
820 break;
821
822 case UNARY MUL:
823 t = q->in.left->in.left;
824 break;
825
826 default:
827 cerror("illegal makeor2");
828 }
829
830 p->tn.lval = t->tn.lval;
831#ifndef FLEXNAMES
6dc2c6c8
DS
832 {
833 register int i;
834 for(i=0; i<NCHNAM; ++i)
835 p->in.name[i] = t->in.name[i];
836 }
439a068b
ML
837#else
838 p->in.name = t->in.name;
839#endif
840
841 /* init offset */
842 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
843
844 tfree(f);
845 return;
846 }
847
848canaddr( p ) NODE *p; {
849 register int o = p->in.op;
850
851 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
852 return(0);
853 }
854
74789784
DS
855flshape( p ) NODE *p; {
856 register int o = p->in.op;
857
858 return( o == REG || o == NAME || o == ICON ||
859 (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
439a068b
ML
860 }
861
10902f65 862/* INTEMP shapes must not contain any temporary registers */
439a068b 863shtemp( p ) register NODE *p; {
10902f65
DS
864 int r;
865
439a068b 866 if( p->in.op == STARG ) p = p->in.left;
10902f65
DS
867
868 switch (p->in.op) {
869 case REG:
870 return( !istreg(p->tn.rval) );
871 case OREG:
872 r = p->tn.rval;
873 if( R2TEST(r) ) {
874 if( istreg(R2UPK1(r)) )
875 return(0);
876 r = R2UPK2(r);
877 }
878 return( !istreg(r) );
10902f65
DS
879 case UNARY MUL:
880 p = p->in.left;
881 return( p->in.op != UNARY MUL && shtemp(p) );
10902f65
DS
882 }
883
884 if( optype( p->in.op ) != LTYPE ) return(0);
885 return(1);
439a068b
ML
886 }
887
888shumul( p ) register NODE *p; {
74789784 889 register int o;
439a068b
ML
890 extern int xdebug;
891
892 if (xdebug) {
f221fccf
DS
893 int val;
894 printf("shumul:\n");
895 eprint(p, 0, &val, &val);
439a068b
ML
896 }
897
439a068b
ML
898 o = p->in.op;
899 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
900
901 if( ( o == INCR || o == ASG MINUS ) &&
902 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
903 p->in.right->in.name[0] == '\0' )
904 {
f83495a1 905 switch (p->in.type)
439a068b
ML
906 {
907 case CHAR|PTR:
908 case UCHAR|PTR:
909 o = 1;
910 break;
911
912 case SHORT|PTR:
913 case USHORT|PTR:
914 o = 2;
915 break;
916
917 case INT|PTR:
918 case UNSIGNED|PTR:
919 case LONG|PTR:
920 case ULONG|PTR:
921 case FLOAT|PTR:
922 o = 4;
923 break;
924
925 case DOUBLE|PTR:
926 o = 8;
927 break;
928
929 default:
262eaf56
RC
930 if ( ISPTR(p->in.type) &&
931 ISPTR(DECREF(p->in.type)) ) {
439a068b
ML
932 o = 4;
933 break;
934 }
935 else return(0);
936 }
937 return( p->in.right->tn.lval == o ? STARREG : 0);
938 }
939
940 return( 0 );
941 }
942
943adrcon( val ) CONSZ val; {
88bb0c9f 944 putchar( '$' );
439a068b
ML
945 printf( CONFMT, val );
946 }
947
948conput( p ) register NODE *p; {
949 switch( p->in.op ){
950
951 case ICON:
952 acon( p );
953 return;
954
955 case REG:
88bb0c9f 956 putstr( rnames[p->tn.rval] );
439a068b
ML
957 return;
958
959 default:
960 cerror( "illegal conput" );
961 }
962 }
963
4ab1e9a8 964/*ARGSUSED*/
6dc2c6c8 965insput( p ) NODE *p; {
439a068b
ML
966 cerror( "insput" );
967 }
968
70f59a26
DS
969upput( p, size ) NODE *p; int size; {
970 if( size == SZLONG && p->in.op == REG ) {
971 putstr( rnames[p->tn.rval + 1] );
972 return;
973 }
439a068b
ML
974 cerror( "upput" );
975 }
976
977adrput( p ) register NODE *p; {
978 register int r;
979 /* output an address, with offsets, from p */
980
981 if( p->in.op == FLD ){
982 p = p->in.left;
983 }
984 switch( p->in.op ){
985
986 case NAME:
987 acon( p );
988 return;
989
990 case ICON:
991 /* addressable value of the constant */
88bb0c9f 992 putchar( '$' );
439a068b
ML
993 acon( p );
994 return;
995
996 case REG:
88bb0c9f 997 putstr( rnames[p->tn.rval] );
439a068b
ML
998 return;
999
1000 case OREG:
1001 r = p->tn.rval;
1002 if( R2TEST(r) ){ /* double indexing */
1003 register int flags;
1004
1005 flags = R2UPK3(r);
88bb0c9f
KM
1006 if( flags & 1 ) putchar('*');
1007 if( flags & 4 ) putchar('-');
439a068b
ML
1008 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1009 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
88bb0c9f 1010 if( flags & 2 ) putchar('+');
439a068b
ML
1011 printf( "[%s]", rnames[R2UPK2(r)] );
1012 return;
1013 }
1014 if( r == AP ){ /* in the argument region */
237a345d 1015 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
439a068b 1016 printf( CONFMT, p->tn.lval );
88bb0c9f 1017 putstr( "(ap)" );
439a068b
ML
1018 return;
1019 }
1020 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1021 printf( "(%s)", rnames[p->tn.rval] );
1022 return;
1023
1024 case UNARY MUL:
1025 /* STARNM or STARREG found */
1026 if( tshape(p, STARNM) ) {
88bb0c9f 1027 putchar( '*' );
439a068b
ML
1028 adrput( p->in.left);
1029 }
1030 else { /* STARREG - really auto inc or dec */
1031 register NODE *q;
1032
439a068b 1033 q = p->in.left;
262eaf56
RC
1034 if( q->in.right->tn.lval != tlen(p) )
1035 cerror("adrput: bad auto-increment/decrement");
f83495a1
RC
1036 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
1037 rnames[q->in.left->tn.rval],
1038 (q->in.op==INCR ? "+" : "") );
1039 p->in.op = OREG;
1040 p->tn.rval = q->in.left->tn.rval;
1041 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
439a068b
ML
1042#ifndef FLEXNAMES
1043 p->in.name[0] = '\0';
1044#else
1045 p->in.name = "";
1046#endif
1047 tfree(q);
1048 }
1049 return;
1050
1051 default:
1052 cerror( "illegal address" );
1053 return;
1054
1055 }
1056
1057 }
1058
1059acon( p ) register NODE *p; { /* print out a constant */
1060
74789784 1061 if( p->in.name[0] == '\0' )
439a068b 1062 printf( CONFMT, p->tn.lval);
74789784 1063 else {
439a068b
ML
1064#ifndef FLEXNAMES
1065 printf( "%.8s", p->in.name );
1066#else
88bb0c9f 1067 putstr( p->in.name );
439a068b 1068#endif
74789784
DS
1069 if( p->tn.lval != 0 ) {
1070 putchar( '+' );
1071 printf( CONFMT, p->tn.lval );
1072 }
439a068b
ML
1073 }
1074 }
439a068b
ML
1075
1076genscall( p, cookie ) register NODE *p; {
1077 /* structure valued call */
1078 return( gencall( p, cookie ) );
1079 }
1080
1081/* tbl */
1082int gc_numbytes;
1083/* tbl */
1084
6dc2c6c8 1085/*ARGSUSED*/
439a068b
ML
1086gencall( p, cookie ) register NODE *p; {
1087 /* generate the call given by p */
3add848c 1088 register NODE *p1;
74789784
DS
1089 register int temp, temp1;
1090 register int m;
439a068b
ML
1091
1092 if( p->in.right ) temp = argsize( p->in.right );
1093 else temp = 0;
1094
1095 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1096 /* set aside room for structure return */
1097
1098 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1099 else temp1 = temp;
1100 }
1101
1102 if( temp > maxargs ) maxargs = temp;
1103 SETOFF(temp1,4);
1104
1105 if( p->in.right ){ /* make temp node, put offset in, and generate args */
3add848c 1106 genargs( p->in.right );
439a068b
ML
1107 }
1108
1109 p1 = p->in.left;
1110 if( p1->in.op != ICON ){
1111 if( p1->in.op != REG ){
1112 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1113 if( p1->in.op != NAME ){
1114 order( p1, INAREG );
1115 }
1116 }
1117 }
1118 }
1119
439a068b
ML
1120/* tbl
1121 setup gc_numbytes so reference to ZC works */
1122
1123 gc_numbytes = temp&(0x3ff);
1124/* tbl */
1125
1126 p->in.op = UNARY CALL;
1127 m = match( p, INTAREG|INTBREG );
1128
1129 /* compensate for deficiency in 'ret' instruction ... wah,kre */
1130 /* (plus in assignment to gc_numbytes above, for neatness only) */
1131 if (temp >= 1024)
1132 printf(" addl2 $%d,sp\n", (temp&(~0x3ff)));
1133
439a068b
ML
1134 return(m != MDONE);
1135 }
1136
1137/* tbl */
1138char *
1139ccbranches[] = {
74789784
DS
1140 "eql",
1141 "neq",
1142 "leq",
1143 "lss",
1144 "geq",
1145 "gtr",
1146 "lequ",
1147 "lssu",
1148 "gequ",
1149 "gtru",
439a068b
ML
1150 };
1151/* tbl */
1152
6dc2c6c8 1153/*ARGSUSED*/
439a068b
ML
1154cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1155
74789784
DS
1156 if( o != 0 && ( o < EQ || o > UGT ) )
1157 cerror( "bad conditional branch: %s", opst[o] );
1158 printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab );
439a068b
ML
1159 }
1160
1161nextcook( p, cookie ) NODE *p; {
1162 /* we have failed to match p with cookie; try another */
1163 if( cookie == FORREW ) return( 0 ); /* hopeless! */
1164 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1165 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1166 return( FORREW );
1167 }
1168
6dc2c6c8 1169/*ARGSUSED*/
439a068b
ML
1170lastchance( p, cook ) NODE *p; {
1171 /* forget it! */
1172 return(0);
1173 }
1174
1175optim2( p ) register NODE *p; {
1176 /* do local tree transformations and optimizations */
1177
71cac6bf 1178 int o;
bcc20d15 1179 int i, mask;
472582a4 1180 register NODE *l, *r;
439a068b 1181
71cac6bf 1182 switch( o = p->in.op ) {
439a068b
ML
1183
1184 case AND:
85696ba1 1185 /* commute L and R to eliminate complements and constants */
472582a4
RC
1186 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
1187 l->in.op == COMPL ) {
439a068b 1188 p->in.left = p->in.right;
472582a4 1189 p->in.right = l;
439a068b
ML
1190 }
1191 case ASG AND:
1192 /* change meaning of AND to ~R&L - bic on pdp11 */
1193 r = p->in.right;
89ccccb8
DS
1194 if( r->in.op==ICON && r->in.name[0]==0 ) {
1195 /* check for degenerate operations */
1196 l = p->in.left;
bcc20d15
DS
1197 mask = (1 << tlen(l) * SZCHAR) - 1;
1198 if( ISUNSIGNED(r->in.type) ) {
6eafb37d
DS
1199 i = (~r->tn.lval & mask);
1200 if( i == 0 ) {
bcc20d15
DS
1201 r->in.op = FREE;
1202 ncopy(p, l);
1203 l->in.op = FREE;
1204 break;
1205 }
6eafb37d 1206 else if( i == mask )
bcc20d15
DS
1207 goto zero;
1208 else
1209 r->tn.lval = i;
6eafb37d 1210 break;
bcc20d15
DS
1211 }
1212 else if( r->tn.lval == mask &&
1213 tlen(l) < SZINT/SZCHAR ) {
1214 r->in.op = SCONV;
1215 r->in.left = l;
1216 r->in.right = 0;
1217 r->in.type = ENUNSIGN(l->in.type);
1218 r->in.su = l->in.su > 1 ? l->in.su : 1;
1219 ncopy(p, r);
1220 p->in.left = r;
1221 p->in.type = INT;
89ccccb8
DS
1222 break;
1223 }
1224 /* complement constant */
439a068b
ML
1225 r->tn.lval = ~r->tn.lval;
1226 }
1227 else if( r->in.op==COMPL ) { /* ~~A => A */
1228 r->in.op = FREE;
1229 p->in.right = r->in.left;
1230 }
1231 else { /* insert complement node */
472582a4
RC
1232 p->in.right = l = talloc();
1233 l->in.op = COMPL;
1234 l->in.rall = NOPREF;
1235 l->in.type = r->in.type;
1236 l->in.left = r;
1237 l->in.right = NULL;
439a068b
ML
1238 }
1239 break;
1240
472582a4 1241 case SCONV:
85696ba1 1242 l = p->in.left;
6eafb37d
DS
1243 if( (l->in.type == UCHAR || l->in.type == USHORT) &&
1244 (p->in.type == DOUBLE || p->in.type == FLOAT) ) {
1245 /* we can convert to INT without loss of significance */
1246 r = talloc();
1247 *r = *p;
1248 r->in.type = INT;
1249 p->in.left = r;
1250#if !defined(FORT) && !defined(SPRECC)
1251 /* nothing to be 'gained' by a FLOAT conversion */
1252 p->in.type = DOUBLE;
1253#endif
1254 return;
1255 }
262eaf56 1256#if defined(FORT) || defined(SPRECC)
7f12173b 1257 if( p->in.type == FLOAT || p->in.type == DOUBLE ||
85696ba1
KM
1258 l->in.type == FLOAT || l->in.type == DOUBLE )
1259 return;
7f12173b 1260#else
85696ba1 1261 if( mixtypes(p, l) ) return;
7f12173b 1262#endif
6eafb37d
DS
1263 if( l->in.op == PCONV )
1264 return;
1265 if( (l->in.op == CALL || l->in.op == UNARY CALL) &&
1266 l->in.type != INT && l->in.type != UNSIGNED )
4bcc0eaf
DS
1267 return;
1268
85696ba1
KM
1269 /* Only trust it to get it right if the size is the same */
1270 if( tlen(p) != tlen(l) )
1271 return;
472582a4
RC
1272
1273 /* clobber conversion */
85696ba1 1274 if( l->in.op != FLD )
472582a4
RC
1275 l->in.type = p->in.type;
1276 ncopy( p, l );
1277 l->in.op = FREE;
85696ba1 1278
472582a4
RC
1279 break;
1280
88bb0c9f
KM
1281 case ASSIGN:
1282 /*
1283 * Conversions are equivalent to assignments;
1284 * when the two operations are combined,
1285 * we can sometimes zap the conversion.
1286 */
1287 r = p->in.right;
1288 l = p->in.left;
1289 if ( r->in.op == SCONV &&
1290 !mixtypes(l, r) &&
ef3be726 1291 l->in.op != FLD &&
88bb0c9f
KM
1292 tlen(l) == tlen(r) ) {
1293 p->in.right = r->in.left;
1294 r->in.op = FREE;
1295 }
6eafb37d
DS
1296 else if( (r->in.type == UCHAR || r->in.type == USHORT) &&
1297 (p->in.type == DOUBLE || p->in.type == FLOAT) ) {
1298 /* we can convert to INT without loss of significance */
1299 l = talloc();
1300 l->in.op = SCONV;
1301 l->in.rall = NOPREF;
1302 l->in.left = r;
1303 l->in.right = NULL;
1304 l->in.type = INT;
1305 p->in.right = r;
1306 return;
1307 }
88bb0c9f
KM
1308 break;
1309
71cac6bf
DS
1310 case ULE:
1311 case ULT:
1312 case UGE:
1313 case UGT:
89ccccb8
DS
1314 p->in.op -= (UGE-GE);
1315 if( degenerate(p) )
1316 break;
1317 p->in.op += (UGE-GE);
1318 break;
1319
71cac6bf
DS
1320 case EQ:
1321 case NE:
1322 case LE:
1323 case LT:
1324 case GE:
1325 case GT:
6eafb37d
DS
1326 if( p->in.left->in.op == SCONV &&
1327 p->in.right->in.op == SCONV ) {
1328 l = p->in.left;
1329 r = p->in.right;
1330 if( l->in.type == DOUBLE &&
1331 l->in.left->in.type == FLOAT &&
1332 r->in.left->in.type == FLOAT ) {
1333 /* nuke the conversions */
1334 p->in.left = l->in.left;
1335 p->in.right = r->in.left;
1336 l->in.op = FREE;
1337 r->in.op = FREE;
1338 }
1339 /* more? */
1340 }
89ccccb8
DS
1341 (void) degenerate(p);
1342 break;
1343
1344 case DIV:
1345 if( p->in.right->in.op == ICON &&
1346 p->in.right->tn.name[0] == '\0' &&
1347 ISUNSIGNED(p->in.right->in.type) &&
1348 (unsigned) p->in.right->tn.lval >= 0x80000000 ) {
1349 /* easy to do here, harder to do in zzzcode() */
1350 p->in.op = UGE;
71cac6bf 1351 break;
89ccccb8
DS
1352 }
1353 case MOD:
1354 case ASG DIV:
1355 case ASG MOD:
1356 /*
1357 * optimize DIV and MOD
1358 *
1359 * basically we spot UCHAR and USHORT and try to do them
1360 * as signed ints... apparently div+mul+sub is always
1361 * faster than ediv for finding MOD on the VAX, when
1362 * full unsigned MOD isn't needed.
1363 *
1364 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub
1365 * are faster for unsigned dividend and a constant divisor
1366 * in the right range (.5 to 1 of dividend's range for the
1367 * first, .333+ to .5 for the second). full unsigned is
1368 * already done cmp+sub in the appropriate case; the
1369 * other cases are less common and require more ambition.
1370 */
1371 if( degenerate(p) )
71cac6bf 1372 break;
89ccccb8
DS
1373 l = p->in.left;
1374 r = p->in.right;
1375 if( !ISUNSIGNED(r->in.type) ||
1376 tlen(l) >= SZINT/SZCHAR ||
1377 !(tlen(r) < SZINT/SZCHAR ||
1378 (r->in.op == ICON && r->tn.name[0] == '\0')) )
71cac6bf 1379 break;
89ccccb8
DS
1380 if( r->in.op == ICON )
1381 r->tn.type = INT;
1382 else {
1383 NODE *t = talloc();
1384 t->in.left = r;
1385 r = t;
1386 r->in.op = SCONV;
1387 r->in.type = INT;
1388 r->in.right = 0;
1389 p->in.right = r;
71cac6bf 1390 }
89ccccb8
DS
1391 if( o == DIV || o == MOD ) {
1392 NODE *t = talloc();
1393 t->in.left = l;
1394 l = t;
1395 l->in.op = SCONV;
1396 l->in.type = INT;
1397 l->in.right = 0;
1398 p->in.left = l;
1399 }
1400 /* handle asgops in table */
1401 break;
1402
1403 case RS:
1404 case ASG RS:
1405 case LS:
1406 case ASG LS:
1407 /* pick up degenerate shifts */
1408 l = p->in.left;
1409 r = p->in.right;
1410 if( !(r->in.op == ICON && r->tn.name[0] == '\0') )
71cac6bf 1411 break;
89ccccb8
DS
1412 i = r->tn.lval;
1413 if( i < 0 )
1414 /* front end 'fixes' this? */
1415 if( o == LS || o == ASG LS )
1416 o += (RS-LS);
1417 else
1418 o += (LS-RS);
1419 if( (o == RS || o == ASG RS) &&
1420 !ISUNSIGNED(l->in.type) )
1421 /* can't optimize signed right shifts */
71cac6bf 1422 break;
74789784
DS
1423 if( o == LS ) {
1424 if( i < SZINT )
1425 break;
1426 }
1427 else {
1428 if( i < tlen(l) * SZCHAR )
1429 break;
1430 }
89ccccb8
DS
1431 zero:
1432 if( !asgop( o ) )
1433 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1434 /* no side effects */
bcc20d15 1435 tfree(l);
89ccccb8
DS
1436 ncopy(p, r);
1437 r->in.op = FREE;
1438 p->tn.lval = 0;
1439 }
1440 else {
1441 p->in.op = COMOP;
bcc20d15 1442 r->tn.lval = 0;
89ccccb8
DS
1443 }
1444 else {
1445 p->in.op = ASSIGN;
1446 r->tn.lval = 0;
71cac6bf 1447 }
89ccccb8
DS
1448 break;
1449 }
1450 }
1451
1452degenerate(p) register NODE *p; {
1453 int o;
1454 int result, i;
1455 int lower, upper;
1456 register NODE *l, *r;
1457
1458 /*
1459 * try to keep degenerate comparisons with constants
1460 * out of the table.
1461 */
1462 r = p->in.right;
1463 l = p->in.left;
1464 if( r->in.op != ICON ||
1465 r->tn.name[0] != '\0' ||
1466 tlen(l) >= tlen(r) )
1467 return (0);
1468 switch( l->in.type ) {
1469 case CHAR:
1470 lower = -(1 << SZCHAR - 1);
1471 upper = (1 << SZCHAR - 1) - 1;
1472 break;
1473 case UCHAR:
1474 lower = 0;
1475 upper = (1 << SZCHAR) - 1;
1476 break;
1477 case SHORT:
1478 lower = -(1 << SZSHORT - 1);
1479 upper = (1 << SZSHORT - 1) - 1;
1480 break;
1481 case USHORT:
1482 lower = 0;
1483 upper = (1 << SZSHORT) - 1;
1484 break;
1485 default:
bcc20d15 1486 cerror("unsupported type in degenerate()");
89ccccb8
DS
1487 }
1488 i = r->tn.lval;
1489 switch( o = p->in.op ) {
1490 case DIV:
1491 case ASG DIV:
1492 case MOD:
1493 case ASG MOD:
1494 /* DIV and MOD work like EQ */
1495 case EQ:
1496 case NE:
1497 if( lower == 0 && (unsigned) i > upper )
1498 result = o == NE;
1499 else if( i < lower || i > upper )
1500 result = o == NE;
1501 else
1502 return (0);
1503 break;
1504 case LT:
1505 case GE:
1506 if( lower == 0 && (unsigned) i > upper )
1507 result = o == LT;
1508 else if( i <= lower )
1509 result = o != LT;
1510 else if( i > upper )
1511 result = o == LT;
1512 else
1513 return (0);
1514 break;
1515 case LE:
1516 case GT:
1517 if( lower == 0 && (unsigned) i >= upper )
1518 result = o == LE;
1519 else if( i < lower )
1520 result = o != LE;
1521 else if( i >= upper )
1522 result = o == LE;
1523 else
1524 return (0);
1525 break;
1526 default:
1527 cerror("unknown op in degenerate()");
1528 }
1529
1530 if( o == MOD || o == ASG MOD ) {
1531 r->in.op = FREE;
1532 ncopy(p, l);
1533 l->in.op = FREE;
1534 }
1535 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) {
1536 /* no side effects */
bcc20d15 1537 tfree(l);
89ccccb8
DS
1538 ncopy(p, r);
1539 r->in.op = FREE;
1540 p->tn.lval = result;
1541 }
1542 else {
1543 if( o == ASG DIV )
1544 p->in.op = ASSIGN;
71cac6bf
DS
1545 else {
1546 p->in.op = COMOP;
71cac6bf 1547 r->tn.type = INT;
71cac6bf 1548 }
89ccccb8 1549 r->tn.lval = result;
439a068b 1550 }
89ccccb8
DS
1551 if( logop(o) )
1552 p->in.type = INT;
1553
1554 return (1);
439a068b
ML
1555 }
1556
439a068b
ML
1557/* added by jwf */
1558struct functbl {
1559 int fop;
1560 TWORD ftype;
1561 char *func;
1562 } opfunc[] = {
1563 DIV, TANY, "udiv",
1564 MOD, TANY, "urem",
28312bdc
RC
1565 ASG DIV, TANY, "audiv",
1566 ASG MOD, TANY, "aurem",
439a068b
ML
1567 0, 0, 0 };
1568
1569hardops(p) register NODE *p; {
1570 /* change hard to do operators into function calls. */
1571 register NODE *q;
1572 register struct functbl *f;
1573 register o;
262eaf56 1574 NODE *old,*temp;
439a068b
ML
1575
1576 o = p->in.op;
262eaf56
RC
1577 if( ! (optype(o)==BITYPE &&
1578 (ISUNSIGNED(p->in.left->in.type) ||
1579 ISUNSIGNED(p->in.right->in.type))) )
1580 return;
439a068b
ML
1581
1582 for( f=opfunc; f->fop; f++ ) {
1583 if( o==f->fop ) goto convert;
1584 }
1585 return;
1586
439a068b 1587 convert:
89ccccb8 1588 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' )
70f59a26
DS
1589 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */
1590 /* save a subroutine call -- use at most 5 instructions */
70f59a26 1591 return;
89ccccb8
DS
1592 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR )
1593 /* optim2() will modify the op into an ordinary int op */
1594 return;
439a068b 1595 if( asgop( o ) ) {
262eaf56 1596 old = NIL;
28312bdc 1597 switch( p->in.left->in.op ){
262eaf56
RC
1598 case FLD:
1599 q = p->in.left->in.left;
1600 /*
1601 * rewrite (lval.fld /= rval); as
1602 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1603 * else the compiler will evaluate lval twice.
1604 */
1605 if( q->in.op == UNARY MUL ){
1606 /* first allocate a temp storage */
1607 temp = talloc();
1608 temp->in.op = OREG;
1609 temp->tn.rval = TMPREG;
1610 temp->tn.lval = BITOOR(freetemp(1));
1611 temp->in.type = INCREF(p->in.type);
1612#ifdef FLEXNAMES
1613 temp->in.name = "";
1614#else
1615 temp->in.name[0] = '\0';
1616#endif
1617 old = q->in.left;
1618 q->in.left = temp;
1619 }
1620 /* fall thru ... */
1621
28312bdc
RC
1622 case REG:
1623 case NAME:
1624 case OREG:
1625 /* change ASG OP to a simple OP */
1626 q = talloc();
1627 q->in.op = NOASG p->in.op;
1628 q->in.rall = NOPREF;
1629 q->in.type = p->in.type;
1630 q->in.left = tcopy(p->in.left);
1631 q->in.right = p->in.right;
1632 p->in.op = ASSIGN;
1633 p->in.right = q;
1634 p = q;
1635 f -= 2; /* Note: this depends on the table order */
262eaf56
RC
1636 /* on the right side only - replace *temp with
1637 *(temp = &lval), build the assignment node */
1638 if( old ){
1639 temp = q->in.left->in.left; /* the "*" node */
1640 q = talloc();
1641 q->in.op = ASSIGN;
1642 q->in.left = temp->in.left;
1643 q->in.right = old;
1644 q->in.type = old->in.type;
1645#ifdef FLEXNAMES
1646 q->in.name = "";
1647#else
1648 q->in.name[0] = '\0';
1649#endif
1650 temp->in.left = q;
1651 }
28312bdc
RC
1652 break;
1653
1654 case UNARY MUL:
1655 /* avoid doing side effects twice */
1656 q = p->in.left;
1657 p->in.left = q->in.left;
1658 q->in.op = FREE;
1659 break;
1660
1661 default:
1662 cerror( "hardops: can't compute & LHS" );
1663 }
262eaf56 1664 }
439a068b
ML
1665
1666 /* build comma op for args to function */
1667 q = talloc();
1668 q->in.op = CM;
1669 q->in.rall = NOPREF;
1670 q->in.type = INT;
1671 q->in.left = p->in.left;
1672 q->in.right = p->in.right;
1673 p->in.op = CALL;
1674 p->in.right = q;
1675
1676 /* put function name in left node of call */
1677 p->in.left = q = talloc();
1678 q->in.op = ICON;
1679 q->in.rall = NOPREF;
1680 q->in.type = INCREF( FTN + p->in.type );
1681#ifndef FLEXNAMES
1682 strcpy( q->in.name, f->func );
1683#else
1684 q->in.name = f->func;
1685#endif
1686 q->tn.lval = 0;
1687 q->tn.rval = 0;
1688
439a068b
ML
1689 }
1690
262eaf56
RC
1691zappost(p) NODE *p; {
1692 /* look for ++ and -- operators and remove them */
1693
74789784 1694 register int o, ty;
262eaf56
RC
1695 register NODE *q;
1696 o = p->in.op;
1697 ty = optype( o );
1698
1699 switch( o ){
1700
1701 case INCR:
1702 case DECR:
1703 q = p->in.left;
1704 p->in.right->in.op = FREE; /* zap constant */
1705 ncopy( p, q );
1706 q->in.op = FREE;
1707 return;
1708
1709 }
1710
1711 if( ty == BITYPE ) zappost( p->in.right );
1712 if( ty != LTYPE ) zappost( p->in.left );
1713}
1714
1715fixpre(p) NODE *p; {
1716
74789784 1717 register int o, ty;
262eaf56
RC
1718 o = p->in.op;
1719 ty = optype( o );
1720
1721 switch( o ){
1722
1723 case ASG PLUS:
1724 p->in.op = PLUS;
1725 break;
1726 case ASG MINUS:
1727 p->in.op = MINUS;
1728 break;
1729 }
1730
1731 if( ty == BITYPE ) fixpre( p->in.right );
1732 if( ty != LTYPE ) fixpre( p->in.left );
1733}
1734
74789784
DS
1735/*ARGSUSED*/
1736NODE * addroreg(l) NODE *l;
1737 /* OREG was built in clocal()
1738 * for an auto or formal parameter
1739 * now its address is being taken
1740 * local code must unwind it
1741 * back to PLUS/MINUS REG ICON
1742 * according to local conventions
1743 */
1744{
1745 cerror("address of OREG taken");
1746 /*NOTREACHED*/
1747}
1748
1749
1750
1751# ifndef ONEPASS
1752main( argc, argv ) char *argv[]; {
1753 return( mainp2( argc, argv ) );
1754 }
1755# endif
1756
88bb0c9f
KM
1757strip(p) register NODE *p; {
1758 NODE *q;
1759
1760 /* strip nodes off the top when no side effects occur */
1761 for( ; ; ) {
1762 switch( p->in.op ) {
1763 case SCONV: /* remove lint tidbits */
1764 q = p->in.left;
1765 ncopy( p, q );
1766 q->in.op = FREE;
1767 break;
1768 /* could probably add a few more here */
1769 default:
1770 return;
1771 }
1772 }
1773 }
1774
439a068b 1775myreader(p) register NODE *p; {
88bb0c9f 1776 strip( p ); /* strip off operations with no side effects */
262eaf56 1777 canon( p ); /* expands r-vals for fields */
439a068b 1778 walkf( p, hardops ); /* convert ops to function calls */
439a068b 1779 walkf( p, optim2 );
439a068b 1780 }