changes for pcc.h; fix isfloat to not get double -> float exceptions.
[unix-history] / usr / src / old / pcc / ccom.vax / local2.c
CommitLineData
262eaf56
RC
1# ifndef lint
2static char *sccsid ="@(#)local2.c 1.8 (Berkeley) %G%";
3# endif
4
439a068b
ML
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
14where(c){
15 fprintf( stderr, "%s, line %d: ", filename, lineno );
16 }
17
18lineid( l, fn ) char *fn; {
19 /* identify line l and file fn */
20 printf( "# line %d, file %s\n", l, fn );
21 }
22
23
24eobl2(){
25 OFFSZ spoff; /* offset from stack pointer */
26#ifdef FORT
27 spoff = maxoff;
28 if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
29 spoff /= SZCHAR;
30 SETOFF(spoff,4);
31#ifndef FLEXNAMES
32 printf( " .set .F%d,%ld\n", ftnno, spoff );
33#else
34 /* SHOULD BE L%d ... ftnno but must change pc/f77 */
35 printf( " .set LF%d,%ld\n", ftnno, spoff );
36#endif
37#else
38 extern int ftlab1, ftlab2;
39
40 spoff = maxoff;
41 if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
42 spoff /= SZCHAR;
43 SETOFF(spoff,4);
44 printf( "L%d:\n", ftlab1);
45 if( spoff!=0 )
46 if( spoff < 64 )
47 printf( " subl2 $%ld,sp\n", spoff);
48 else
49 printf( " movab -%ld(sp),sp\n", spoff);
50 printf( " jbr L%d\n", ftlab2);
51#endif
52 maxargs = -1;
53 }
54
55struct hoptab { int opmask; char * opstring; } ioptab[] = {
56
57 ASG PLUS, "add",
58 ASG MINUS, "sub",
59 ASG MUL, "mul",
60 ASG DIV, "div",
61 ASG OR, "bis",
62 ASG ER, "xor",
63 ASG AND, "bic",
64 PLUS, "add",
65 MINUS, "sub",
66 MUL, "mul",
67 DIV, "div",
68 OR, "bis",
69 ER, "xor",
70 AND, "bic",
71 -1, "" };
72
73hopcode( f, o ){
74 /* output the appropriate string from the above table */
75
76 register struct hoptab *q;
77
78 for( q = ioptab; q->opmask>=0; ++q ){
79 if( q->opmask == o ){
80 printf( "%s", q->opstring );
81/* tbl
82 if( f == 'F' ) printf( "e" );
83 else if( f == 'D' ) printf( "d" );
84 tbl */
85/* tbl */
86 switch( f ) {
87 case 'L':
88 case 'W':
89 case 'B':
90 case 'D':
91 case 'F':
92 printf("%c", tolower(f));
93 break;
94
95 }
96/* tbl */
97 return;
98 }
99 }
100 cerror( "no hoptab for %s", opst[o] );
101 }
102
103char *
104rnames[] = { /* keyed to register number tokens */
105
106 "r0", "r1",
107 "r2", "r3", "r4", "r5",
108 "r6", "r7", "r8", "r9", "r10", "r11",
109 "ap", "fp", "sp", "pc",
110
111 };
112
113int rstatus[] = {
114 SAREG|STAREG, SAREG|STAREG,
115 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
116 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
117 SAREG, SAREG, SAREG, SAREG,
118
119 };
120
121tlen(p) NODE *p;
122{
123 switch(p->in.type) {
124 case CHAR:
125 case UCHAR:
126 return(1);
127
128 case SHORT:
129 case USHORT:
130 return(2);
131
132 case DOUBLE:
133 return(8);
134
135 default:
136 return(4);
137 }
138}
139
140mixtypes(p, q) NODE *p, *q;
141{
472582a4 142 register TWORD tp, tq;
439a068b
ML
143
144 tp = p->in.type;
145 tq = q->in.type;
146
147 return( (tp==FLOAT || tp==DOUBLE) !=
148 (tq==FLOAT || tq==DOUBLE) );
149}
150
151prtype(n) NODE *n;
152{
153 switch (n->in.type)
154 {
155 case DOUBLE:
156 printf("d");
157 return;
158
159 case FLOAT:
160 printf("f");
161 return;
162
163 case LONG:
164 case ULONG:
165 case INT:
166 case UNSIGNED:
167 printf("l");
168 return;
169
170 case SHORT:
171 case USHORT:
172 printf("w");
173 return;
174
175 case CHAR:
176 case UCHAR:
177 printf("b");
178 return;
179
180 default:
181 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
182 else {
183 printf("l");
184 return;
185 }
186 }
187}
188
189zzzcode( p, c ) register NODE *p; {
190 register m;
191 CONSZ val;
192 switch( c ){
193
194 case 'N': /* logical ops, turned into 0-1 */
195 /* use register given by register 1 */
196 cbgen( 0, m=getlab(), 'I' );
197 deflab( p->bn.label );
198 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] );
199 deflab( m );
200 return;
201
202 case 'I':
203 case 'P':
204 cbgen( p->in.op, p->bn.label, c );
205 return;
206
207 case 'A':
208 {
209 register NODE *l, *r;
210
211 if (xdebug) eprint(p, 0, &val, &val);
212 r = getlr(p, 'R');
472582a4
RC
213 if (p->in.op == ASSIGN)
214 l = getlr(p, 'L');
3612cbf8 215 else if (p->in.op == SCONV) {
439a068b 216 l = resc;
262eaf56 217#if defined(FORT) || defined(SPRECC)
472582a4
RC
218 l->in.type = r->in.type;
219#else
220 l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type;
221#endif
222 r = getlr(p, 'L');
439a068b 223 }
3612cbf8 224 else { /* OPLTYPE */
472582a4 225 l = resc;
262eaf56 226#if defined(FORT) || defined(SPRECC)
472582a4
RC
227 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT);
228#else
229 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT);
230#endif
231 }
439a068b 232 if (r->in.op == ICON)
3612cbf8
RC
233 if (r->in.name[0] == '\0') {
234 if (r->tn.lval == 0) {
439a068b
ML
235 printf("clr");
236 prtype(l);
237 printf(" ");
238 adrput(l);
239 return;
240 }
3612cbf8 241 if (r->tn.lval < 0 && r->tn.lval >= -63) {
439a068b
ML
242 printf("mneg");
243 prtype(l);
244 r->tn.lval = -r->tn.lval;
245 goto ops;
246 }
3612cbf8
RC
247 if (r->tn.lval < 0)
248 r->in.type = r->tn.lval >= -128 ? CHAR
439a068b 249 : (r->tn.lval >= -32768 ? SHORT
3612cbf8
RC
250 : INT);
251 else if (l->in.type == FLOAT ||
252 l->in.type == DOUBLE)
253 r->in.type = r->tn.lval <= 63 ? INT
254 : (r->tn.lval <= 127 ? CHAR
255 : (r->tn.lval <= 32767 ? SHORT
256 : INT));
257 else
258 r->in.type = r->tn.lval <= 63 ? INT
259 : (r->tn.lval <= 127 ? CHAR
439a068b
ML
260 : (r->tn.lval <= 255 ? UCHAR
261 : (r->tn.lval <= 32767 ? SHORT
262 : (r->tn.lval <= 65535 ? USHORT
3612cbf8 263 : INT))));
439a068b 264 }
3612cbf8 265 else {
472582a4
RC
266 printf("moval");
267 printf(" ");
268 acon(r);
269 printf(",");
270 adrput(l);
271 return;
272 }
439a068b 273
3612cbf8
RC
274 if (l->in.op == REG && l->in.type != FLOAT && l->in.type != DOUBLE) {
275 if (tlen(l) < tlen(r) && !mixtypes(l,r)) {
472582a4
RC
276 if (ISUNSIGNED(l->in.type))
277 printf("movz");
439a068b 278 else
439a068b 279 printf("cvt");
472582a4
RC
280 prtype(l);
281 printf("l");
282 goto ops;
439a068b
ML
283 }
284 else
472582a4 285 l->in.type = INT;
439a068b 286 }
3612cbf8
RC
287 if (!mixtypes(l,r)) {
288 if (tlen(l) == tlen(r)) {
439a068b 289 printf("mov");
262eaf56
RC
290#ifdef FORT
291 if (Oflag)
292 prtype(l);
293 else {
294 if (l->in.type == DOUBLE)
295 printf("q");
296 else if(l->in.type == FLOAT)
297 printf("l");
298 else
299 prtype(l);
300 }
301#else
439a068b 302 prtype(l);
262eaf56 303#endif FORT
439a068b
ML
304 goto ops;
305 }
306 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type))
439a068b 307 printf("movz");
439a068b 308 else
439a068b 309 printf("cvt");
439a068b
ML
310 }
311 else
439a068b 312 printf("cvt");
439a068b
ML
313 prtype(r);
314 prtype(l);
315 ops:
316 printf(" ");
317 adrput(r);
318 printf(",");
319 adrput(l);
320 return;
321 }
322
323 case 'B': /* get oreg value in temp register for left shift */
324 {
325 register NODE *r;
326 if (xdebug) eprint(p, 0, &val, &val);
327 r = p->in.right;
328 if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
329 printf("movl");
330 else {
331 printf("cvt");
332 prtype(r);
333 printf("l");
334 }
335 return;
336 }
337
338 case 'C': /* num words pushed on arg stack */
339 {
340 extern int gc_numbytes;
341 extern int xdebug;
342
343 if (xdebug) printf("->%d<-",gc_numbytes);
344
345 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
346 return;
347 }
348
349 case 'D': /* INCR and DECR */
350 zzzcode(p->in.left, 'A');
351 printf("\n ");
352
353 case 'E': /* INCR and DECR, FOREFF */
354 if (p->in.right->tn.lval == 1)
355 {
356 printf("%s", (p->in.op == INCR ? "inc" : "dec") );
357 prtype(p->in.left);
358 printf(" ");
359 adrput(p->in.left);
360 return;
361 }
362 printf("%s", (p->in.op == INCR ? "add" : "sub") );
363 prtype(p->in.left);
364 printf("2 ");
365 adrput(p->in.right);
366 printf(",");
367 adrput(p->in.left);
368 return;
369
370 case 'F': /* register type of right operand */
371 {
372 register NODE *n;
373 extern int xdebug;
374 register int ty;
375
376 n = getlr( p, 'R' );
377 ty = n->in.type;
378
379 if (xdebug) printf("->%d<-", ty);
380
381 if ( ty==DOUBLE) printf("d");
382 else if ( ty==FLOAT ) printf("f");
383 else printf("l");
384 return;
385 }
386
387 case 'L': /* type of left operand */
388 case 'R': /* type of right operand */
389 {
390 register NODE *n;
391 extern int xdebug;
392
472582a4 393 n = getlr( p, c );
439a068b
ML
394 if (xdebug) printf("->%d<-", n->in.type);
395
396 prtype(n);
397 return;
398 }
399
400 case 'Z': /* complement mask for bit instr */
401 printf("$%ld", ~p->in.right->tn.lval);
402 return;
403
404 case 'U': /* 32 - n, for unsigned right shifts */
405 printf("$%d", 32 - p->in.right->tn.lval );
406 return;
407
408 case 'T': /* rounded structure length for arguments */
409 {
410 int size;
411
412 size = p->stn.stsize;
413 SETOFF( size, 4);
414 printf("$%d", size);
415 return;
416 }
417
418 case 'S': /* structure assignment */
419 {
420 register NODE *l, *r;
421 register size;
422
423 if( p->in.op == STASG ){
424 l = p->in.left;
425 r = p->in.right;
426
427 }
428 else if( p->in.op == STARG ){ /* store an arg into a temporary */
439a068b
ML
429 r = p->in.left;
430 }
431 else cerror( "STASG bad" );
432
433 if( r->in.op == ICON ) r->in.op = NAME;
434 else if( r->in.op == REG ) r->in.op = OREG;
435 else if( r->in.op != OREG ) cerror( "STASG-r" );
436
437 size = p->stn.stsize;
438
439 if( size <= 0 || size > 65535 )
440 cerror("structure size <0=0 or >65535");
441
442 switch(size) {
443 case 1:
444 printf(" movb ");
445 break;
446 case 2:
447 printf(" movw ");
448 break;
449 case 4:
450 printf(" movl ");
451 break;
452 case 8:
453 printf(" movq ");
454 break;
455 default:
456 printf(" movc3 $%d,", size);
457 break;
458 }
459 adrput(r);
3add848c
RC
460 if( p->in.op == STASG ){
461 printf(",");
462 adrput(l);
463 printf("\n");
464 }
465 else
466 printf(",(sp)\n");
439a068b
ML
467
468 if( r->in.op == NAME ) r->in.op = ICON;
469 else if( r->in.op == OREG ) r->in.op = REG;
470
471 }
472 break;
473
474 default:
475 cerror( "illegal zzzcode" );
476 }
477 }
478
262eaf56 479rmove( rt, rs, t ) TWORD t; {
439a068b 480 printf( " %s %s,%s\n",
262eaf56
RC
481#ifdef FORT
482 !Oflag ? (t==DOUBLE ? "movq" : "movl") :
483#endif
439a068b
ML
484 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")),
485 rnames[rs], rnames[rt] );
486 }
487
488struct respref
489respref[] = {
490 INTAREG|INTBREG, INTAREG|INTBREG,
491 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
492 INTEMP, INTEMP,
493 FORARG, FORARG,
494 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
495 0, 0 };
496
497setregs(){ /* set up temporary registers */
498 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */
499 ;
500 }
501
262eaf56
RC
502szty(t) TWORD t; { /* size, in registers, needed to hold thing of type t */
503#if defined(FORT) || defined(SPRECC)
472582a4
RC
504 return( (t==DOUBLE) ? 2 : 1 );
505#else
439a068b 506 return( (t==DOUBLE||t==FLOAT) ? 2 : 1 );
472582a4 507#endif
439a068b
ML
508 }
509
510rewfld( p ) NODE *p; {
511 return(1);
512 }
513
514callreg(p) NODE *p; {
515 return( R0 );
516 }
517
518base( p ) register NODE *p; {
519 register int o = p->in.op;
520
521 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
522 if( o==REG ) return( p->tn.rval );
523 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
524 return( p->in.left->tn.rval );
525 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
526 return( p->tn.rval + 0200*1 );
527 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 );
528 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 );
529 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG
530 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
531 return( p->in.left->in.left->tn.rval + 0200*(1+2) );
532 return( -1 );
533 }
534
535offset( p, tyl ) register NODE *p; int tyl; {
536
537 if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
538 if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
539 (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
540 && (1<<p->in.right->tn.lval)==tyl))
541 return( p->in.left->tn.rval );
542 return( -1 );
543 }
544
545makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
546 register NODE *t;
547 register int i;
548 NODE *f;
549
550 p->in.op = OREG;
551 f = p->in.left; /* have to free this subtree later */
552
553 /* init base */
554 switch (q->in.op) {
555 case ICON:
556 case REG:
557 case OREG:
558 t = q;
559 break;
560
561 case MINUS:
562 q->in.right->tn.lval = -q->in.right->tn.lval;
563 case PLUS:
564 t = q->in.right;
565 break;
566
567 case INCR:
568 case ASG MINUS:
569 t = q->in.left;
570 break;
571
572 case UNARY MUL:
573 t = q->in.left->in.left;
574 break;
575
576 default:
577 cerror("illegal makeor2");
578 }
579
580 p->tn.lval = t->tn.lval;
581#ifndef FLEXNAMES
582 for(i=0; i<NCHNAM; ++i)
583 p->in.name[i] = t->in.name[i];
584#else
585 p->in.name = t->in.name;
586#endif
587
588 /* init offset */
589 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
590
591 tfree(f);
592 return;
593 }
594
595canaddr( p ) NODE *p; {
596 register int o = p->in.op;
597
598 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
599 return(0);
600 }
601
602shltype( o, p ) register NODE *p; {
603 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
604 }
605
606flshape( p ) register NODE *p; {
607 return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON ||
608 (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) );
609 }
610
611shtemp( p ) register NODE *p; {
612 if( p->in.op == STARG ) p = p->in.left;
613 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
614 }
615
616shumul( p ) register NODE *p; {
617 register o;
618 extern int xdebug;
619
620 if (xdebug) {
621 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
622 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
623 }
624
625
626 o = p->in.op;
627 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM );
628
629 if( ( o == INCR || o == ASG MINUS ) &&
630 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) &&
631 p->in.right->in.name[0] == '\0' )
632 {
f83495a1 633 switch (p->in.type)
439a068b
ML
634 {
635 case CHAR|PTR:
636 case UCHAR|PTR:
637 o = 1;
638 break;
639
640 case SHORT|PTR:
641 case USHORT|PTR:
642 o = 2;
643 break;
644
645 case INT|PTR:
646 case UNSIGNED|PTR:
647 case LONG|PTR:
648 case ULONG|PTR:
649 case FLOAT|PTR:
650 o = 4;
651 break;
652
653 case DOUBLE|PTR:
654 o = 8;
655 break;
656
657 default:
262eaf56
RC
658 if ( ISPTR(p->in.type) &&
659 ISPTR(DECREF(p->in.type)) ) {
439a068b
ML
660 o = 4;
661 break;
662 }
663 else return(0);
664 }
665 return( p->in.right->tn.lval == o ? STARREG : 0);
666 }
667
668 return( 0 );
669 }
670
671adrcon( val ) CONSZ val; {
672 printf( "$" );
673 printf( CONFMT, val );
674 }
675
676conput( p ) register NODE *p; {
677 switch( p->in.op ){
678
679 case ICON:
680 acon( p );
681 return;
682
683 case REG:
684 printf( "%s", rnames[p->tn.rval] );
685 return;
686
687 default:
688 cerror( "illegal conput" );
689 }
690 }
691
692insput( p ) register NODE *p; {
693 cerror( "insput" );
694 }
695
696upput( p ) register NODE *p; {
697 cerror( "upput" );
698 }
699
700adrput( p ) register NODE *p; {
701 register int r;
702 /* output an address, with offsets, from p */
703
704 if( p->in.op == FLD ){
705 p = p->in.left;
706 }
707 switch( p->in.op ){
708
709 case NAME:
710 acon( p );
711 return;
712
713 case ICON:
714 /* addressable value of the constant */
715 printf( "$" );
716 acon( p );
717 return;
718
719 case REG:
720 printf( "%s", rnames[p->tn.rval] );
721 return;
722
723 case OREG:
724 r = p->tn.rval;
725 if( R2TEST(r) ){ /* double indexing */
726 register int flags;
727
728 flags = R2UPK3(r);
729 if( flags & 1 ) printf("*");
730 if( flags & 4 ) printf("-");
731 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
732 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] );
733 if( flags & 2 ) printf("+");
734 printf( "[%s]", rnames[R2UPK2(r)] );
735 return;
736 }
737 if( r == AP ){ /* in the argument region */
738 if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" );
739 printf( CONFMT, p->tn.lval );
740 printf( "(ap)" );
741 return;
742 }
743 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
744 printf( "(%s)", rnames[p->tn.rval] );
745 return;
746
747 case UNARY MUL:
748 /* STARNM or STARREG found */
749 if( tshape(p, STARNM) ) {
750 printf( "*" );
751 adrput( p->in.left);
752 }
753 else { /* STARREG - really auto inc or dec */
754 register NODE *q;
755
756/* tbl
757 p = p->in.left;
758 p->in.left->in.op = OREG;
759 if( p->in.op == INCR ) {
760 adrput( p->in.left );
761 printf( "+" );
762 }
763 else {
764 printf( "-" );
765 adrput( p->in.left );
766 }
767 tbl */
439a068b 768 q = p->in.left;
262eaf56
RC
769 if( q->in.right->tn.lval != tlen(p) )
770 cerror("adrput: bad auto-increment/decrement");
f83495a1
RC
771 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"),
772 rnames[q->in.left->tn.rval],
773 (q->in.op==INCR ? "+" : "") );
774 p->in.op = OREG;
775 p->tn.rval = q->in.left->tn.rval;
776 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0);
439a068b
ML
777#ifndef FLEXNAMES
778 p->in.name[0] = '\0';
779#else
780 p->in.name = "";
781#endif
782 tfree(q);
783 }
784 return;
785
786 default:
787 cerror( "illegal address" );
788 return;
789
790 }
791
792 }
793
794acon( p ) register NODE *p; { /* print out a constant */
795
796 if( p->in.name[0] == '\0' ){
797 printf( CONFMT, p->tn.lval);
798 }
799 else if( p->tn.lval == 0 ) {
800#ifndef FLEXNAMES
801 printf( "%.8s", p->in.name );
802#else
803 printf( "%s", p->in.name );
804#endif
805 }
806 else {
807#ifndef FLEXNAMES
808 printf( "%.8s+", p->in.name );
809#else
810 printf( "%s+", p->in.name );
811#endif
812 printf( CONFMT, p->tn.lval );
813 }
814 }
815
816/*
817aacon( p ) register NODE *p; { /* print out a constant */
818/*
819
820 if( p->in.name[0] == '\0' ){
821 printf( CONFMT, p->tn.lval);
822 return( 0 );
823 }
824 else if( p->tn.lval == 0 ) {
825#ifndef FLEXNAMES
826 printf( "$%.8s", p->in.name );
827#else
828 printf( "$%s", p->in.name );
829#endif
830 return( 1 );
831 }
832 else {
833 printf( "$(" );
834 printf( CONFMT, p->tn.lval );
835 printf( "+" );
836#ifndef FLEXNAMES
837 printf( "%.8s)", p->in.name );
838#else
839 printf( "%s)", p->in.name );
840#endif
841 return(1);
842 }
843 }
844 */
845
846genscall( p, cookie ) register NODE *p; {
847 /* structure valued call */
848 return( gencall( p, cookie ) );
849 }
850
851/* tbl */
852int gc_numbytes;
853/* tbl */
854
855gencall( p, cookie ) register NODE *p; {
856 /* generate the call given by p */
3add848c 857 register NODE *p1;
439a068b
ML
858 register temp, temp1;
859 register m;
860
861 if( p->in.right ) temp = argsize( p->in.right );
862 else temp = 0;
863
864 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
865 /* set aside room for structure return */
866
867 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
868 else temp1 = temp;
869 }
870
871 if( temp > maxargs ) maxargs = temp;
872 SETOFF(temp1,4);
873
874 if( p->in.right ){ /* make temp node, put offset in, and generate args */
3add848c 875 genargs( p->in.right );
439a068b
ML
876 }
877
878 p1 = p->in.left;
879 if( p1->in.op != ICON ){
880 if( p1->in.op != REG ){
881 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
882 if( p1->in.op != NAME ){
883 order( p1, INAREG );
884 }
885 }
886 }
887 }
888
889/*
890 if( p1->in.op == REG && p->tn.rval == R5 ){
891 cerror( "call register overwrite" );
892 }
893 */
894/* tbl
895 setup gc_numbytes so reference to ZC works */
896
897 gc_numbytes = temp&(0x3ff);
898/* tbl */
899
900 p->in.op = UNARY CALL;
901 m = match( p, INTAREG|INTBREG );
902
903 /* compensate for deficiency in 'ret' instruction ... wah,kre */
904 /* (plus in assignment to gc_numbytes above, for neatness only) */
905 if (temp >= 1024)
906 printf(" addl2 $%d,sp\n", (temp&(~0x3ff)));
907
908/* tbl
909 switch( temp ) {
910 case 0:
911 break;
912 case 2:
913 printf( " tst (sp)+\n" );
914 break;
915 case 4:
916 printf( " cmp (sp)+,(sp)+\n" );
917 break;
918 default:
919 printf( " add $%d,sp\n", temp);
920 }
921 tbl */
922 return(m != MDONE);
923 }
924
925/* tbl */
926char *
927ccbranches[] = {
928 " jeql L%d\n",
929 " jneq L%d\n",
930 " jleq L%d\n",
931 " jlss L%d\n",
932 " jgeq L%d\n",
933 " jgtr L%d\n",
934 " jlequ L%d\n",
935 " jlssu L%d\n",
936 " jgequ L%d\n",
937 " jgtru L%d\n",
938 };
939/* tbl */
940
941cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
942
943/* tbl */
944 if( o == 0 ) printf( " jbr L%d\n", lab );
945/* tbl */
946 else {
947 if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
948 printf( ccbranches[o-EQ], lab );
949 }
950 }
951
952nextcook( p, cookie ) NODE *p; {
953 /* we have failed to match p with cookie; try another */
954 if( cookie == FORREW ) return( 0 ); /* hopeless! */
955 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
956 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
957 return( FORREW );
958 }
959
960lastchance( p, cook ) NODE *p; {
961 /* forget it! */
962 return(0);
963 }
964
965optim2( p ) register NODE *p; {
966 /* do local tree transformations and optimizations */
967
472582a4
RC
968 register NODE *l, *r;
969 int m, ml;
439a068b
ML
970
971 switch( p->in.op ) {
972
973 case AND:
974 /* commute L and R to eliminate compliments and constants */
472582a4
RC
975 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 ||
976 l->in.op == COMPL ) {
439a068b 977 p->in.left = p->in.right;
472582a4 978 p->in.right = l;
439a068b
ML
979 }
980 case ASG AND:
981 /* change meaning of AND to ~R&L - bic on pdp11 */
982 r = p->in.right;
983 if( r->in.op==ICON && r->in.name[0]==0 ) { /* compliment constant */
984 r->tn.lval = ~r->tn.lval;
985 }
986 else if( r->in.op==COMPL ) { /* ~~A => A */
987 r->in.op = FREE;
988 p->in.right = r->in.left;
989 }
990 else { /* insert complement node */
472582a4
RC
991 p->in.right = l = talloc();
992 l->in.op = COMPL;
993 l->in.rall = NOPREF;
994 l->in.type = r->in.type;
995 l->in.left = r;
996 l->in.right = NULL;
439a068b
ML
997 }
998 break;
999
472582a4 1000 case SCONV:
262eaf56 1001#if defined(FORT) || defined(SPRECC)
7f12173b
RC
1002 if( p->in.type == FLOAT || p->in.type == DOUBLE ||
1003 (l = p->in.left)->in.type == FLOAT || l->in.type == DOUBLE )
1004 break;
1005#else
472582a4
RC
1006 m = (p->in.type == FLOAT || p->in.type == DOUBLE);
1007 ml = ((l = p->in.left)->in.type == FLOAT || l->in.type == DOUBLE);
1008 if( m != ml ) break;
7f12173b 1009#endif
472582a4
RC
1010 m = p->in.type;
1011 ml = l->in.type;
1012 /* meaningful ones are conversion of int to char, int to short,
1013 and short to char, and unsigned version of them */
1014 if( m==CHAR || m==UCHAR ){
1015 if( ml!=CHAR && ml!= UCHAR )
1016 break;
1017 }
1018 else if( m==SHORT || m==USHORT ){
1019 if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT )
1020 break;
1021 }
1022
1023 /* clobber conversion */
1024 if( tlen( p ) == tlen( l ) && l->in.op != FLD )
1025 l->in.type = p->in.type;
1026 ncopy( p, l );
1027 l->in.op = FREE;
1028 break;
1029
439a068b
ML
1030 }
1031 }
1032
262eaf56 1033NODE * addroreg(l) NODE *l;
439a068b
ML
1034 /* OREG was built in clocal()
1035 * for an auto or formal parameter
1036 * now its address is being taken
1037 * local code must unwind it
1038 * back to PLUS/MINUS REG ICON
1039 * according to local conventions
1040 */
1041{
1042 cerror("address of OREG taken");
262eaf56 1043 /*NOTREACHED*/
439a068b
ML
1044}
1045
1046
1047
1048# ifndef ONEPASS
1049main( argc, argv ) char *argv[]; {
1050 return( mainp2( argc, argv ) );
1051 }
1052# endif
1053
1054
1055/* added by jwf */
1056struct functbl {
1057 int fop;
1058 TWORD ftype;
1059 char *func;
1060 } opfunc[] = {
1061 DIV, TANY, "udiv",
1062 MOD, TANY, "urem",
28312bdc
RC
1063 ASG DIV, TANY, "audiv",
1064 ASG MOD, TANY, "aurem",
439a068b
ML
1065 0, 0, 0 };
1066
1067hardops(p) register NODE *p; {
1068 /* change hard to do operators into function calls. */
1069 register NODE *q;
1070 register struct functbl *f;
1071 register o;
262eaf56 1072 NODE *old,*temp;
439a068b
ML
1073
1074 o = p->in.op;
262eaf56
RC
1075 if( ! (optype(o)==BITYPE &&
1076 (ISUNSIGNED(p->in.left->in.type) ||
1077 ISUNSIGNED(p->in.right->in.type))) )
1078 return;
439a068b
ML
1079
1080 for( f=opfunc; f->fop; f++ ) {
1081 if( o==f->fop ) goto convert;
1082 }
1083 return;
1084
439a068b
ML
1085 convert:
1086 if( asgop( o ) ) {
262eaf56 1087 old = NIL;
28312bdc 1088 switch( p->in.left->in.op ){
262eaf56
RC
1089 case FLD:
1090 q = p->in.left->in.left;
1091 /*
1092 * rewrite (lval.fld /= rval); as
1093 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1094 * else the compiler will evaluate lval twice.
1095 */
1096 if( q->in.op == UNARY MUL ){
1097 /* first allocate a temp storage */
1098 temp = talloc();
1099 temp->in.op = OREG;
1100 temp->tn.rval = TMPREG;
1101 temp->tn.lval = BITOOR(freetemp(1));
1102 temp->in.type = INCREF(p->in.type);
1103#ifdef FLEXNAMES
1104 temp->in.name = "";
1105#else
1106 temp->in.name[0] = '\0';
1107#endif
1108 old = q->in.left;
1109 q->in.left = temp;
1110 }
1111 /* fall thru ... */
1112
28312bdc
RC
1113 case REG:
1114 case NAME:
1115 case OREG:
1116 /* change ASG OP to a simple OP */
1117 q = talloc();
1118 q->in.op = NOASG p->in.op;
1119 q->in.rall = NOPREF;
1120 q->in.type = p->in.type;
1121 q->in.left = tcopy(p->in.left);
1122 q->in.right = p->in.right;
1123 p->in.op = ASSIGN;
1124 p->in.right = q;
1125 p = q;
1126 f -= 2; /* Note: this depends on the table order */
262eaf56
RC
1127 /* on the right side only - replace *temp with
1128 *(temp = &lval), build the assignment node */
1129 if( old ){
1130 temp = q->in.left->in.left; /* the "*" node */
1131 q = talloc();
1132 q->in.op = ASSIGN;
1133 q->in.left = temp->in.left;
1134 q->in.right = old;
1135 q->in.type = old->in.type;
1136#ifdef FLEXNAMES
1137 q->in.name = "";
1138#else
1139 q->in.name[0] = '\0';
1140#endif
1141 temp->in.left = q;
1142 }
28312bdc
RC
1143 break;
1144
1145 case UNARY MUL:
1146 /* avoid doing side effects twice */
1147 q = p->in.left;
1148 p->in.left = q->in.left;
1149 q->in.op = FREE;
1150 break;
1151
1152 default:
1153 cerror( "hardops: can't compute & LHS" );
1154 }
262eaf56 1155 }
439a068b
ML
1156
1157 /* build comma op for args to function */
1158 q = talloc();
1159 q->in.op = CM;
1160 q->in.rall = NOPREF;
1161 q->in.type = INT;
1162 q->in.left = p->in.left;
1163 q->in.right = p->in.right;
1164 p->in.op = CALL;
1165 p->in.right = q;
1166
1167 /* put function name in left node of call */
1168 p->in.left = q = talloc();
1169 q->in.op = ICON;
1170 q->in.rall = NOPREF;
1171 q->in.type = INCREF( FTN + p->in.type );
1172#ifndef FLEXNAMES
1173 strcpy( q->in.name, f->func );
1174#else
1175 q->in.name = f->func;
1176#endif
1177 q->tn.lval = 0;
1178 q->tn.rval = 0;
1179
439a068b
ML
1180 }
1181
262eaf56
RC
1182zappost(p) NODE *p; {
1183 /* look for ++ and -- operators and remove them */
1184
1185 register o, ty;
1186 register NODE *q;
1187 o = p->in.op;
1188 ty = optype( o );
1189
1190 switch( o ){
1191
1192 case INCR:
1193 case DECR:
1194 q = p->in.left;
1195 p->in.right->in.op = FREE; /* zap constant */
1196 ncopy( p, q );
1197 q->in.op = FREE;
1198 return;
1199
1200 }
1201
1202 if( ty == BITYPE ) zappost( p->in.right );
1203 if( ty != LTYPE ) zappost( p->in.left );
1204}
1205
1206fixpre(p) NODE *p; {
1207
1208 register o, ty;
1209 o = p->in.op;
1210 ty = optype( o );
1211
1212 switch( o ){
1213
1214 case ASG PLUS:
1215 p->in.op = PLUS;
1216 break;
1217 case ASG MINUS:
1218 p->in.op = MINUS;
1219 break;
1220 }
1221
1222 if( ty == BITYPE ) fixpre( p->in.right );
1223 if( ty != LTYPE ) fixpre( p->in.left );
1224}
1225
439a068b 1226myreader(p) register NODE *p; {
262eaf56 1227 canon( p ); /* expands r-vals for fields */
439a068b 1228 walkf( p, hardops ); /* convert ops to function calls */
439a068b
ML
1229 walkf( p, optim2 );
1230 /* jwf toff = 0; /* stack offset swindle */
1231 }