Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v102/c168/canon.lis
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1025 lines
30 KiB
Plaintext

1File: CANON.C Page 1
1 /*
2 Copyright 1982
3 Alcyon Corporation
4 8716 Production Ave.
5 San Diego, Ca. 92121
6 */
7
8 #include "cgen.h"
9 #include "cskel.h"
10
11 /*
12 * canon - expression canonicalization
13 * Top level tree canonicalization. This fixes any bit field
14 * accesses, then loops on commute and optim until no more
15 * optimizations are done.
16 */
17 char *canon(tp) /* returns pointer to tree*/
18 struct tnode *tp; /* pointer to tree to canonicalize*/
19 {
20 #ifndef NODEBUG
21 if ( oflag )
22 putexpr("pre-canon",tp);
23 #endif
24 tp = fixbfield(tp);
25 do {
26 sucomp(tp,0,1); /*need Sethy-Ullman's for commute*/
27 tp = commute(tp); /*commute the tree*/
28 } while( optim(&tp) ); /*keep trying for optimizations*/
29 #ifndef NODEBUG
30 if( oflag )
31 putexpr("canon",tp);
32 #endif
33 return(tp);
34 }
35
36 /* fixbfield - fix bit field operators*/
37 /* Fixes bit field assignment and normal usage*/
38 char *fixbfield(tp) /* returns pointer to fixed tree*/
39 struct tnode *tp; /* pointer to tree*/
40 {
41 register struct tnode *btp, *stp;
42 register int foff, fmask, op, flen;
43
44 if( leafop(op=tp->t_op) )
45 return(tp);
46 if( asgop(op) && tp->t_left->t_op == BFIELD ) {
47 tp->t_right = fixbfield(tp->t_right); /* [vlh] 4.0 */
48 btp = tp->t_left; /*pointer to BFIELD node*/
49 stp = btp->t_left; /*pointer to son of BFIELD node*/
50 foff = (btp->t_su>>8) & 0377;
51 flen = btp->t_su & 0377;
52 fmask = (1<<flen)-1;
53 if( tp->t_right->t_op == CINT && (op == ASSIGN || op == EQXOR) ) {
54 if( op == EQXOR ) {
55 tp->t_left = stp;
56 tp->t_right->t_value =<< foff;
57 return(tp);
58 }
59 if( !tp->t_right->t_value ) {
1File: CANON.C Page 2
60 tp->t_op = EQAND;
61 tp->t_left = stp;
62 tp->t_right->t_value = ~ (fmask << foff);
63 return(tp);
64 }
65 if( (tp->t_right->t_value & fmask) == fmask ) {
66 tp->t_op = EQOR;
67 tp->t_left = stp;
68 tp->t_right->t_value = fmask << foff;
69 return(tp);
70 }
71 }
72 if( fmask == -1 )
73 tp->t_left = stp;
74 else {
75 stp = tcopy(stp);
76 btp = fixbfield(btp);
77 op = tp->t_op;
78 tp = tp->t_right; /*pointer to expression*/
79 if( op != ASSIGN ) /*=op operator?*/
80 tp = tnalloc(op-(EQADD-ADD),INT,0,0,btp,tp);
81 tp = tnalloc(AND,INT,0,0,tp,cnalloc(INT,fmask));
82 tp = tnalloc(LSH,INT,0,0,tp,cnalloc(INT,foff));
83 btp = tnalloc(AND,INT,0,0,tcopy(stp),
84 cnalloc(INT,~(fmask<<foff)));
85 tp = tnalloc(OR,INT,0,0,btp,tp);
86 tp = tnalloc(ASSIGN,INT,0,0,stp,tp);
87 }
88 }
89 else if( op == BFIELD ) {
90 foff = (tp->t_su>>8) & 0377;
91 fmask = (1<<(tp->t_su&0377))-1;
92 tp = tnalloc(RSH,INT,0,0,tp->t_left,cnalloc(INT,foff));
93 tp = tnalloc(AND,INT,0,0,tp,cnalloc(INT,fmask));
94 }
95 else {
96 tp->t_left = fixbfield(tp->t_left);
97 if( binop(op) )
98 tp->t_right = fixbfield(tp->t_right);
99 }
100 return(tp);
101 }
102
103 /*
104 * optim - optimize expression tree
105 * This takes expression tree and performs the following
106 * translations: folds auto names to accesses off the local
107 * environment pointer, performs mostly "machine-independent"
108 * optimizations, such as multiply by zero and one, etc.,
109 * turns field accesses into and's and or's, etc.
110 * [vlh] 4.0 added checks for divide/modulos long zero...
111 * [vlh] 4.0 optimize multiply/divide 1L, add/sub 0L...
112 */
113 optim(tpp) /* returns pointer to new tree*/
114 struct tnode **tpp;
115 {
116 register struct tnode *ltp, *rtp, *tp;
117 register char *p;
118 register int i, cval, changes, op, lconst;
1File: CANON.C Page 3
119 long lcval; /* [vlh] 4.0 simple long constant handling */
120
121 tp = *tpp;
122 if( tp->t_type & ~TYPE ) {
123 tp->t_type =& TYPE;
124 tp->t_type =| POINTER;
125 }
126 if( leafop(op=tp->t_op) )
127 return(0);
128 lconst = changes = 0;
129 if( binop(op) )
130 changes =+ optim(&tp->t_right);
131 changes =+ optim(&tp->t_left);
132 for( ; notleafop(op=tp->t_op); changes++ ) {
133 #ifndef NODEBUG
134 if( oflag )
135 putexpr("optim",tp);
136 #endif
137 *tpp = tp;
138 ltp = tp->t_left;
139 if( binop(op) ) {
140 rtp = tp->t_right;
141 /* if( tp->t_type == CHAR ) [vlh] 4.0 */
142 /* tp->t_type = INT; [vlh] 4.0 */
143 if (!(p = constant(rtp)))
144 if (rtp->t_op == CLONG) {
145 lconst = 1;
146 lcval = rtp->t_lvalue;
147 }
148 }
149 else
150 if (!(p = constant(ltp)))
151 if (ltp->t_op == CLONG) {
152 lconst = 1;
153 lcval = ltp->t_lvalue;
154 }
155 if( p )
156 cval = p->t_value;
157 switch( op ) {
158
159 case ADD:
160 if( p ) {
161 if( !cval ) {
162 tp = ltp;
163 continue;
164 }
165 if( ltp->t_op == ADDR ) {
166 ltp->t_left->t_offset =+ cval;
167 tp = ltp;
168 continue;
169 }
170 }
171 else
172 if (lconst && !lcval) { /* [vlh] 4.0 plus long 0 */
173 tp = ltp;
174 continue;
175 }
176 break;
177
1File: CANON.C Page 4
178 case ASSIGN:
179 if( rtp->t_op == ADD && indexreg(rtp->t_left) &&
180 rtp->t_right->t_op == CINT ) {
181 ltp = rtp->t_left;
182 ltp->t_sc = REGOFF;
183 ltp->t_offset =+ rtp->t_right->t_value;
184 tp->t_right = ltp;
185 tp->t_op = EQADDR;
186 continue;
187 }
188 break;
189
190 case SUB:
191 if( p ) {
192 if( !cval ) {
193 tp = ltp;
194 continue;
195 }
196 tp->t_op = ADD;
197 p->t_value = -cval;
198 continue;
199 }
200 else
201 if (lconst && !lcval) { /* [vlh] 4.0 minus long 0... */
202 tp = ltp;
203 continue;
204 }
205 if( (p=constant(ltp)) && !p->t_value ) { /*0-X=-X*/
206 tp->t_op = UMINUS;
207 tp->t_left = ltp = rtp;
208 continue;
209 }
210 break;
211
212 case DIV:
213 case EQDIV:
214 if( p ) {
215 if( !cval ) { /*X/0->error*/
216 error("divide by zero");
217 tp = rtp;
218 continue;
219 }
220 if( cval == 1 ) {
221 tp = ltp;
222 continue;
223 }
224 if( cval == -1 ) {
225 tp->t_op = (tp->t_op == DIV ? UMINUS : EQNEG );
226 continue;
227 }
228 }
229 else
230 if (lconst) { /* [vlh] 4.0 simple long expr */
231 if (!lcval) {
232 error("divide by zero");
233 tp = rtp;
234 continue;
235 }
236 if (lcval == 1L) {
1File: CANON.C Page 5
237 tp = ltp;
238 continue;
239 }
240 }
241 if( (p=constant(ltp)) && !p->t_value ) {
242 tp = ltp;
243 continue;
244 }
245 if( multop(tpp) ) {
246 tp = *tpp;
247 continue;
248 }
249 break;
250
251 case EQMOD:
252 case MOD:
253 if( p ) {
254 if( !cval ) { /*X%0->error*/
255 error("modulus by zero");
256 tp = rtp;
257 continue;
258 }
259 if( cval == 1 ) { /*X%1->0*/
260 p->t_value = 0;
261 if (op == EQMOD) /*[vlh] 4.0*/
262 tp->t_op = ASSIGN;
263 else
264 tp = rtp;
265 continue;
266 }
267 }
268 else /* [vlh] 4.0 check for mod long 0 */
269 if (lconst) {
270 if(!lcval) {
271 error("modulus by zero");
272 tp = rtp;
273 continue;
274 }
275 if (lcval == 1L) {
276 rtp->t_lvalue = 0L;
277 if (op == EQMOD)
278 tp->t_op = ASSIGN;
279 else
280 tp = rtp;
281 continue;
282 }
283 }
284 if( (p=constant(ltp)) && !p->t_value ) {
285 tp = ltp;
286 continue;
287 }
288 if( multop(tpp) ) {
289 tp = *tpp;
290 continue;
291 }
292 break;
293
294 case MULT:
295 case EQMULT:
1File: CANON.C Page 6
296 if( p ) {
297 if( !cval ) {
298 if (op == EQMULT)
299 tp->t_op = ASSIGN;
300 else
301 tp = rtp;
302 continue;
303 }
304 if( cval == 1 ) {
305 tp = ltp;
306 continue;
307 }
308 if( cval == -1 ) {
309 tp->t_op = (tp->t_op == MULT ? UMINUS : EQNEG);
310 continue;
311 }
312 }
313 else
314 if (lconst) { /* [vlh] 4.0 simple long expr */
315 if (!lcval) {
316 if (op == EQMULT)
317 tp->t_op = ASSIGN;
318 else
319 tp = rtp;
320 continue;
321 }
322 if (lcval == 1L) {
323 tp = ltp;
324 continue;
325 }
326 }
327 if( multop(tpp) ) {
328 tp = *tpp;
329 continue;
330 }
331 break;
332
333 case EQUALS:
334 case NEQUALS:
335 if( p && (i=onebit(cval)) >= 0 && ltp->t_op == AND &&
336 (rtp=constant(ltp->t_right)) &&
337 i == onebit(rtp->t_value) ) {
338 tp->t_op = invrel[tp->t_op-EQUALS];
339 p->t_value = 0;
340 continue;
341 }
342 break;
343
344 case GREATEQ:
345 if( p && !cval && unsign(ltp->t_type) ) {
346 p->t_value = 1;
347 tp = p;
348 continue;
349 }
350 break;
351
352 case LESS:
353 if( p && !cval && unsign(ltp->t_type) ) {
354 tp = p;
1File: CANON.C Page 7
355 continue;
356 }
357 break;
358
359 case AND:
360 if( p ) {
361 if( !cval ) {
362 tp = rtp;
363 continue;
364 }
365 if( cval == -1 ) {
366 tp = ltp;
367 continue;
368 }
369 }
370 break;
371
372 case OR:
373 if( p ) {
374 if( !cval ) {
375 tp = ltp;
376 continue;
377 }
378 if( cval == -1 ) {
379 tp = rtp;
380 continue;
381 }
382 }
383 break;
384
385 case EQXOR:
386 case XOR:
387 if( p ) {
388 if( !cval ) {
389 tp = ltp;
390 continue;
391 }
392 if( cval == -1 ) {
393 tp->t_op = (tp->t_op == XOR ? COMPL : EQNOT);
394 continue;
395 }
396 }
397 break;
398
399 case LSH:
400 case EQLSH:
401 if( tp->t_type == LONG && rtp->t_op == INT2L &&
402 unsign(rtp->t_left) ) {
403 tp->t_right = rtp->t_left;
404 continue;
405 }
406 case RSH:
407 case EQRSH:
408 if( p ) {
409 if( !cval ) {
410 tp = ltp;
411 continue;
412 }
413 if( p != rtp ) {
1File: CANON.C Page 8
414 tp->t_right = p;
415 continue;
416 }
417 }
418 break;
419
420 case ADDR:
421 if( ltp->t_op == INDR ) {
422 tp = ltp->t_left;
423 continue;
424 }
425 if( ltp->t_op == SYMBOL && ltp->t_sc == REGOFF ) {
426 tp->t_op = ADD;
427 tp->t_right = cnalloc(INT,ltp->t_offset);
428 ltp->t_type = tp->t_type;
429 ltp->t_sc = REGISTER;
430 ltp->t_offset = 0;
431 continue;
432 }
433 break;
434
435 case INDR:
436 p = ltp->t_left;
437 switch( ltp->t_op ) {
438
439 case ADDR:
440 tp = p;
441 continue;
442
443 case CINT:
444 tp = snalloc(tp->t_type,CINDR,ltp->t_value,0,0);
445 continue;
446
447 case CLONG:
448 tp = snalloc(tp->t_type,CLINDR,ltp->t_lvalue.hiword,0,
449 ltp->t_lvalue.loword);
450 continue;
451
452 case CFLOAT: /* [vlh] 3.4 */
453 tp = snalloc(tp->t_type,CFINDR,ltp->t_lvalue.hiword,0,
454 ltp->t_lvalue.loword);
455 continue;
456
457 case SYMBOL:
458 if( indexreg(ltp) ) {
459 ltp->t_sc = REGOFF;
460 ltp->t_type = tp->t_type;
461 ltp->t_offset = 0;
462 tp = ltp;
463 continue;
464 }
465 break;
466
467 case ADD:
468 if( p->t_op == SYMBOL && p->t_sc == REGOFF &&
469 (rtp=constant(ltp->t_right)) &&
470 notpointer(p->t_type) ) {
471 p->t_offset =+ rtp->t_value;
472 tp = p;
1File: CANON.C Page 9
473 continue;
474 }
475 if( indexreg(p) ) {
476 if( rtp = constant(ltp->t_right) ) {
477 /*
478 * This combines an address register and a constant into a register
479 * offset. This relies on 68000 Addressing scheme somewhat.
480 */
481 p->t_sc = REGOFF;
482 p->t_type = tp->t_type;
483 p->t_offset =+ rtp->t_value;
484 tp = p;
485 continue;
486 }
487 if( !lflag && ltp->t_right->t_op == ADDR ) {
488 /*
489 * We can fold *(An+&expr) into *(&expr(An)), but note that &expr
490 * must be 16 bits for 68000, hence we can only do this if short
491 * addresses are enabled. Note that the storage classes are mapped:
492 * EXTERNAL->EXTOFF, STATIC->STATOFF, REGISTER->REGOFF
493 */
494 ltp = ltp->t_right->t_left;
495 ltp->t_sc =+ (EXTOFF-EXTERNAL);
496 ltp->t_type = tp->t_type;
497 tp = ltp;
498 continue;
499 }
500 }
501 break;
502 /*
503 * --X and X++ can be folded into -(An) and (An)+ 68000 instructions
504 */
505 case PREDEC:
506 case POSTINC:
507 if( indexreg(p) && ltp->t_type == p->t_type ) {
508 p->t_op = (ltp->t_op == PREDEC ? AUTODEC : AUTOINC);
509 p->t_type = tp->t_type;
510 tp = p;
511 continue;
512 }
513 }
514 break;
515
516 case NOT:
517 if( relop(ltp->t_op) ) { /*!(X>Y)->X<=Y*/
518 tp = ltp;
519 tp->t_op = invrel[tp->t_op-EQUALS];
520 continue;
521 }
522 break;
523
524 case UMINUS:
525 case COMPL:
526 if( tp->t_type == CHAR )
527 tp->t_type = INT;
528 if( tp->t_op == ltp->t_op ) {
529 tp = ltp->t_left;
530 continue;
531 }
1File: CANON.C Page 10
532 if( ltp->t_op == INT2L ) { /*~(INT2L X)->INT2L (~X)*/
533 ltp->t_op = tp->t_op;
534 tp->t_op = INT2L;
535 ltp->t_type = INT;
536 continue;
537 }
538 break;
539
540 case INT2L:
541 if( ltp->t_op == MULT ) { /*INT2L (X*Y)->X*Y*/
542 ltp->t_type = (ltp->t_type&(~TYPE))|LONG;
543 tp = ltp;
544 continue;
545 }
546 break;
547 }
548 if(!ccexpr(tpp))
549 break;
550 tp = *tpp;
551 }
552 *tpp = tp;
553 return(changes);
554 }
555
556 /*
557 * commute - commutes expression tree to canonical form
558 * This sorts commutable expression trees so that the most
559 * difficult expression is the left-most operand. Note that
560 * canon assumes that commute has placed constant operands in
561 * the right sub-tree. This also swaps relationals so that the
562 * most difficult expression is on the left.
563 */
564 char *commute(tp) /* returns commuted expression tree*/
565 struct tnode *tp;
566 {
567 struct tnode *clist[20], *plist[19];
568 register struct tnode **p, **q, *s;
569 struct tnode **plp, **clp;
570 register int op;
571
572 if( relop(op=tp->t_op) ) {
573 s = tp->t_left;
574 if( harder(tp->t_right,s) ) {
575 #ifndef NODEBUG
576 if(oflag)
577 putexpr("swaprel",tp);
578 #endif
579 tp->t_op = swaprel[op-EQUALS];
580 tp->t_left = tp->t_right;
581 tp->t_right = s;
582 }
583 }
584 if( commop(op) ) {
585 #ifndef NODEBUG
586 if(oflag)
587 putexpr("commute",tp);
588 #endif
589 clp = clist;
590 plp = plist;
1File: CANON.C Page 11
591 addtree(tp,&clp,&plp); /*collect comm. expressions*/
592 /*
593 * see if any sub-trees can also be commuted (with different operator)
594 */
595 clp--;
596 plp--;
597 for( p = clist; p <= clp; p++ )
598 *p = commute(*p);
599 /*
600 * this sorts the expressions in decreasing order of Sethy-Ullman
601 * values.
602 */
603 for( p = clist; p <= clp; p++ ) {
604 for( q = p; q <= clp; q++ ) {
605 if( harder(*q,*p) ) {
606 s = *q;
607 *q = *p;
608 *p = s;
609 }
610 }
611 }
612 /*
613 * Now, we start at the end of the list and collect any constants
614 * if possible.
615 */
616 for( q = clp, p = plp; p > plist; p-- ) {
617 s = *p;
618 s->t_right = *q;
619 s->t_left = *--q;
620 if( ccexpr(p) ) {
621 clp--;
622 plp--;
623 *q = *p; /*[vlh]*/
624 }
625 }
626 /*
627 * this takes the sorted sub-expression pointers and the pointers
628 * to the commutable operator nodes (plist) and structures the
629 * tree so that the left sub-expression is the most complex. The
630 * code generation scheme is very sensitive to this...
631 */
632 q = clist;
633 p = plist;
634 s = *q++;
635 while( p <= plp ) {
636 (*p)->t_left = s;
637 s = *p++;
638 s->t_right = *q++;
639 if(!longorptr(s->t_type)) {
640 if( longorptr(s->t_right->t_type) )
641 s->t_type = s->t_right->t_type;
642 else if( longorptr(s->t_left->t_type) )
643 s->t_type = s->t_left->t_type;
644 }
645 }
646 tp = s;
647 #ifndef NODEBUG
648 if(oflag)
649 putexpr("after commute",tp);
1File: CANON.C Page 12
650 #endif
651 }
652 else if( binop(op) ) {
653 tp->t_left = commute(tp->t_left);
654 tp->t_right = commute(tp->t_right);
655 }
656 else if( unaryop(op) )
657 tp->t_left = commute(tp->t_left);
658 return(tp);
659 }
660
661 /*
662 * harder - test one sub-expression for being "harder" than another
663 * This requires some special finagling for registers. The reason
664 * for this is that the code skeletons produce better code if the
665 * register is on the left. Also note that allowing an address
666 * register on the right can have disastrous effects for AND and OR.
667 * The basic point is: don't mess with this routine unless you're
668 * 100% sure you understand the ramifications...
669 */
670 harder(tp,ntp) /* returns 1 if tp > ntp, else 0*/
671 struct tnode *tp;
672 struct tnode *ntp;
673 {
674 if( ntp->t_su == SU_VHARD )
675 return(0);
676 if( tp->t_su == SU_VHARD )
677 return(1);
678 if( isreg(ntp) )
679 return(0);
680 if( isreg(tp) )
681 return(1);
682 if( constant(ntp) )
683 return(1);
684 if( constant(tp) )
685 return(0);
686 return( tp->t_su > ntp->t_su );
687 }
688
689 /*
690 * addtree - collect commutable sub-trees for commute
691 * This recurses down the sub-trees looking for groups of
692 * commutable operators. It collects the sub-trees and their
693 * parent nodes for commute.
694 */
695 addtree(tp,clist,plist) /* returns pointer to clist*/
696 struct tnode *tp; /* pointer to tree*/
697 struct tnode ***clist; /* commutable sub-trees*/
698 struct tnode ***plist; /* parent nodes of sub-trees*/
699 {
700 register struct tnode ***p, ***c;
701
702 c = clist;
703 p = plist;
704 if( tp->t_op == tp->t_left->t_op )
705 addtree(tp->t_left,c,p);
706 else
707 *(*c)++ = tp->t_left;
708 if( tp->t_op == tp->t_right->t_op )
1File: CANON.C Page 13
709 addtree(tp->t_right,c,p);
710 else
711 *(*c)++ = tp->t_right;
712 *(*p)++ = tp;
713 }
714
715 /* constant - test for tree being a constant node*/
716 char *constant(tp) /* returns 0 or ptr to const node*/
717 struct tnode *tp; /* pointer to tree*/
718 {
719 if( tp->t_op == CINT )
720 return(tp);
721 if((tp->t_op==INT2L || tp->t_op==LONG2I) && tp->t_left->t_op==CINT )
722 return(tp->t_left);
723 return(0);
724 }
725
726 /* indexreg - returns whether node is an address register*/
727 /* For 68000, must be an A register*/
728 indexreg(tp) /* returns whether node is A reg*/
729 struct tnode *tp; /* pointer to tree*/
730 {
731 if( tp->t_op == SYMBOL && tp->t_sc == REGISTER &&
732 !(isdreg(tp->t_reg)) )
733 return(1);
734 return(0);
735 }
736
737 /* ccexpr - compute constant expression*/
738 /* Evaluates constant expressions, including ?: and relationals*/
739 ccexpr(tpp) /* returns 1 if changes, 0 otherwise*/
740 struct tnode **tpp; /* pointer to tree*/
741 {
742 register struct tnode *ltp, *rtp, *tp;
743 register int op, i, j, anylong, anyfloat; /*[vlh] 3.4 anyfloat*/
744 register long rval, lval;
745
746 tp = *tpp;
747 op = tp->t_op;
748 if( leafop(op) )
749 return(0);
750 anylong = anyfloat = 0;
751 ltp = tp->t_left;
752 if( ltp->t_op == CLONG ) {
753 lval = ltp->t_lvalue;
754 anylong++;
755 }
756 else if ( ltp->t_op == CFLOAT) { /* [vlh] 3.4 */
757 lval = ltp->t_lvalue;
758 anyfloat++;
759 }
760 else if( ltp = constant(ltp) )
761 lval = ltp->t_value;
762 else
763 return(0);
764 if( binop(op) ) {
765 rtp = tp->t_right;
766 if( op == QMARK ) {
767 ltp = rtp->t_left;
1File: CANON.C Page 14
768 rtp = rtp->t_right;
769 if( ltp->t_op != CINT || rtp->t_op != CINT )
770 return(0);
771 ltp->t_value = (lval?ltp->t_value:rtp->t_value);
772 *tpp = ltp;
773 return(1);
774 }
775 if( rtp->t_op == CLONG ) {
776 anylong++;
777 rval = rtp->t_lvalue;
778 }
779 else if (rtp->t_op == CFLOAT) { /* [vlh] 3.4 */
780 anyfloat++;
781 rval = rtp->t_lvalue;
782 }
783 else if( rtp = constant(rtp) )
784 rval = rtp->t_value;
785 else
786 return(0);
787 }
788 i = lval;
789 j = rval;
790 switch( op ) {
791
792 case ADD:
793 lval =+ rval;
794 break;
795
796 case SUB:
797 lval =- rval;
798 break;
799
800 case MULT:
801 case DIV:
802 case MOD:
803 case LSH:
804 case RSH:
805 case XOR:
806 if( anylong || anyfloat ) /* [vlh] 3.4 float */
807 return(0);
808 switch( op ) {
809
810 case MULT:
811 lval = i * j;
812 break;
813
814 case DIV:
815 lval = i / j;
816 break;
817
818 case MOD:
819 lval = i % j;
820 break;
821
822 case RSH:
823 lval = i >> j;
824 break;
825
826 case LSH:
1File: CANON.C Page 15
827 lval = i << j;
828 break;
829
830 case XOR:
831 lval = i ^ j;
832 break;
833 }
834 break;
835
836 case GREAT:
837 lval = (lval>rval);
838 break;
839
840 case GREATEQ:
841 lval = (lval>=rval);
842 break;
843
844 case LESS:
845 lval = (lval<rval);
846 break;
847
848 case LESSEQ:
849 lval = (lval<=rval);
850 break;
851
852 case UMINUS:
853 lval = -lval;
854 break;
855
856 case COMPL:
857 lval = ~lval;
858 break;
859
860 case NOT:
861 lval = !lval;
862 break;
863
864 case OR:
865 lval =| rval;
866 break;
867
868 case AND:
869 lval =& rval;
870 break;
871
872 default:
873 return(0);
874
875 }
876 if( anylong )
877 ltp = lcnalloc(LONG,lval);
878 else if ( anyfloat )
879 ltp = fpcnalloc(FLOAT,lval);
880 else
881 ltp->t_value = lval;
882 *tpp = ltp;
883 return(1);
884 }
885
1File: CANON.C Page 16
886 /* power2 - do multiply and divide by powers of two*/
887 /* This changes multiplies and divides by constant powers of two*/
888 /* to shifts.*/
889 power2(tpp) /* returns 0 if not power of two*/
890 struct tnode **tpp; /* pointer to expression tree*/
891 {
892 register char *p;
893 register int i, j, op;
894 register struct tnode *tp;
895
896 tp = *tpp;
897 if( p = constant(tp->t_right) ) {
898 if( (i=onebit(p->t_value)) < 0 )
899 return(0);
900 switch( op = tp->t_op ) {
901
902 case MULT:
903 op = LSH;
904 break;
905
906 case EQMULT:
907 op = EQLSH;
908 break;
909
910 case DIV:
911 op = RSH;
912 break;
913
914 case EQDIV:
915 op = EQRSH;
916 break;
917
918 case MOD:
919 op = AND;
920 i = p->t_value - 1;
921 break;
922
923 case EQMOD:
924 op = EQAND;
925 i = p->t_value - 1;
926 break;
927
928 default:
929 return(0);
930 }
931 tp->t_op = op;
932 p->t_value = i;
933 return(1);
934 }
935 return(0);
936 }
937
938 /* chklong - check for tree being a long*/
939 chklong(tp) /* returns 1 if long, 0 otherwise*/
940 struct tnode *tp; /* pointer to expression tree*/
941 {
942 if( tp->t_op == INT2L && !(unsign(tp->t_left->t_type)) )
943 return(0);
944 if( tp->t_op == CLONG )
1File: CANON.C Page 17
945 return(1);
946 return( longorptr(tp->t_type) );
947 }
948
949 /* multop - handle multiplicative operators*/
950 /* This checks for powers of two optimizations, then for a hard*/
951 /* long operation.*/
952 multop(tpp) /* returns ptr to expression tree*/
953 struct tnode **tpp; /* pointer to expression tree*/
954 {
955 register struct tnode *ltp, *tp, *rtp, *p;
956 register int change;
957 register long l;
958
959 tp = *tpp;
960 if( change = power2(tpp) )
961 tp = *tpp;
962 if( chklong(rtp=tp->t_right) || chklong(ltp=tp->t_left) ) {
963 switch( tp->t_op ) {
964
965 case MULT:
966 tp->t_op = LMULT;
967 break;
968
969 case DIV:
970 case MOD:
971 if( chklong(rtp) ) { /*only hard if divisor is long*/
972 tp->t_op =+ (LMULT-MULT);
973 if( rtp->t_op == CLONG )
974 rtp->t_op = DCLONG;
975 }
976 break;
977
978 case EQDIV:
979 case EQMOD:
980 if( !chklong(rtp) )
981 break;
982 if( rtp->t_op == CLONG )
983 rtp->t_op = DCLONG;
984 case EQMULT:
985 tp->t_op =+ (LMULT-EQMULT);
986 *tpp = tnalloc(ASSIGN,tp->t_type,0,0,tcopy(ltp),tp);
987 change++;
988 break;
989 }
990 }
991 return(change);
992 }
993
994 /* onebit - returns whether constant is power of two (one bit on)*/
995 onebit(val) /* returns bit number or -1*/
996 int val; /* constant value to check*/
997 {
998 register int i;
999
1000 for( i = 15; val != 0; val =<< 1, i-- )
1001 if( val & 0100000 )
1002 break;
1003 if (val != 0100000)
1File: CANON.C Page 18
1004 return(-1);
1005 return(i);
1006 }