Research V7 development
[unix-history] / usr / src / cmd / pcc / local2.c
CommitLineData
3c5d933b
SJ
1# include "mfile2"
2/* a lot of the machine dependent parts of the second pass */
3
4# define BITMASK(n) ((1L<<n)-1)
5
6lineid( l, fn ) char *fn; {
7 /* identify line l and file fn */
8 printf( "/ line %d, file %s\n", l, fn );
9 }
10
11eobl2(){
12 OFFSZ spoff; /* offset from stack pointer */
13
14 spoff = maxoff;
15 if( spoff >= AUTOINIT ) spoff -= AUTOINIT;
16 spoff /= SZCHAR;
17 SETOFF(spoff,2);
18 printf( " .F%d = %Ld.\n", ftnno, spoff );
19 if( fltused ) {
20 fltused = 0;
21 printf( " .globl fltused\n" );
22 }
23 }
24
25struct hoptab { int opmask; char * opstring; } ioptab[]= {
26
27 ASG PLUS, "add",
28 ASG MINUS, "sub",
29 ASG OR, "bis",
30 ASG AND, "bic",
31 ASG ER, "xor",
32 ASG MUL, "mul",
33 ASG DIV, "div",
34 ASG MOD, "div",
35 ASG LS, "asl",
36 ASG RS, "asr",
37
38 -1, "" };
39
40hopcode( f, o ){
41 /* output the appropriate string from the above table */
42
43 register struct hoptab *q;
44
45 for( q = ioptab; q->opmask>=0; ++q ){
46 if( q->opmask == o ){
47 printf( "%s", q->opstring );
48 if( f == 'F' ) printf( "f" );
49 return;
50 }
51 }
52 cerror( "no hoptab for %s", opst[o] );
53 }
54
55char *
56rnames[]= { /* keyed to register number tokens */
57
58 "r0", "r1",
59 "r2", "r3", "r4",
60 "r5", "sp", "pc",
61
62 "fr0", "fr1", "fr2", "fr3",
63 "fr4", "fr5", /* not accumulators - used for temps */
64 };
65
66int rstatus[] = {
67 SAREG|STAREG, SAREG|STAREG,
68 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, /* use as scratch if not reg var */
69 SAREG, SAREG, SAREG,
70
71 SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG,
72 SBREG, SBREG,
73 };
74
75NODE *brnode;
76int brcase;
77
78int toff = 0; /* number of stack locations used for args */
79
80zzzcode( p, c ) NODE *p; {
81 register m;
82 switch( c ){
83
84 case 'B': /* output b if type is byte */
85 if( p->type == CHAR || p->type == UCHAR ) printf( "b" );
86 return;
87
88 case 'N': /* logical ops, turned into 0-1 */
89 /* use register given by register 1 */
90 cbgen( 0, m=getlab(), 'I' );
91 deflab( p->label );
92 printf( " clr %s\n", rnames[getlr( p, '1' )->rval] );
93 if( p->type == LONG || p->type == ULONG )
94 printf( " clr %s\n", rnames[getlr( p, '1' )->rval + 1] );
95 deflab( m );
96 return;
97
98 case 'I':
99 case 'F':
100 cbgen( p->op, p->label, c );
101 return;
102
103 case 'A':
104 case 'C':
105 /* logical operators for longs
106 defer comparisons until branch occurs */
107
108 brnode = tcopy( p );
109 brcase = c;
110 return;
111
112 case 'H': /* fix up unsigned shifts */
113 { register NODE *q;
114 register r, l;
115 TWORD t;
116
117 if( p->op == ASG LS ) return;
118 if( p->op != ASG RS ) cerror( "ZH bad" );
119 if( p->left->op != REG ) cerror( "SH left bad" );
120
121 r = p->left->rval;
122 t = p->left->type;
123 l = (t==LONG || t == ULONG );
124
125 if( t != UNSIGNED && t != UCHAR && t != ULONG ) return; /* signed is ok */
126
127 /* there are three cases: right side is a constant,
128 and has the shift value; right side is
129 a temporary reg, and has the - shift value,
130 and right side is something else: A1 has the
131 - shift value then */
132
133 /* in the case where the value is known (rhs a constant),
134 the mask is just computed and put out... */
135
136 if( p->right->op == ICON ){
137 int s;
138 s = p->right->lval;
139 if( l ){
140 if( s >= 16 ){
141 printf( " clr r%d\n", r );
142 s -= 16;
143 ++r;
144 }
145 }
146 if( s >= 16 ) printf( " clr r%d\n", r );
147 else {
148 m = 0100000;
149 m >>= s; /* sign extends... */
150 m <<= 1;
151 printf( " bic $%o,r%d\n", m, r );
152 }
153 return;
154 }
155
156 /* general case */
157
158 if( istnode( p->right ) ) q = p->right;
159 else q = getlr( p, '1' ); /* where -shift is stored */
160
161 /* first, we store the shifted value on the stack */
162 printf( " mov r%d,-(sp)\n", r );
163 if( l ) printf( " mov r%d,-(sp)\n", r+1 );
164
165 /* now, make a mask */
166
167 printf( " mov $100000,r%d\n", r );
168 if( l ) printf( " clr r%d\n", r+1 );
169
170 /* shift (arithmetically ) */
171 if( l ) expand( q, RNOP, " ashc AR" );
172 else expand( q, RNOP, " ash AR" );
173 printf( ",r%d\n", r );
174
175 if( l ) printf( " ashc $1,r%d\n", r );
176 else printf( " asl r%d\n", r );
177
178 /* now, we have a mask: use it to clear sp, and reload */
179
180 if( l ){
181 printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r+1, r+1 );
182 }
183 printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r, r );
184 /* whew! */
185 return;
186 }
187
188 case 'V':
189 /* sign extend or not -- register is one less than the
190 left descendent */
191
192 m = p->left->rval - 1;
193
194 if( ISUNSIGNED(p->type) ){
195 printf( " clr r%d\n", m );
196 }
197 else {
198 printf( " sxt r%d\n", m );
199 }
200 return;
201
202 /* stack management macros */
203 case '-':
204 if( toff ++ ) printf( "-" );
205 printf( "(sp)" );
206 return;
207
208 case '4':
209 if( toff == 0 ) ++toff; /* can't push doubles that way */
210 printf( "-(sp)" );
211 toff += 4;
212 return;
213
214 case '~':
215 /* complimented CR */
216 p->right->lval = ~p->right->lval;
217 conput( getlr( p, 'R' ) );
218 p->right->lval = ~p->right->lval;
219 return;
220
221 case 'M':
222 /* negated CR */
223 p->right->lval = -p->right->lval;
224 conput( getlr( p, 'R' ) );
225 p->right->lval = -p->right->lval;
226 return;
227
228 case 'L': /* INIT for long constants */
229 {
230 unsigned hi, lo;
231 lo = p->left->lval & BITMASK(SZINT);
232 hi = ( p->left->lval >> SZINT ) & BITMASK(SZINT);
233 printf( " %o; %o\n", hi, lo );
234 return;
235 }
236
237 case 'T':
238 /* Truncate longs for type conversions:
239 LONG|ULONG -> CHAR|UCHAR|INT|UNSIGNED
240 increment offset to second word */
241
242 m = p->type;
243 p = p->left;
244 switch( p->op ){
245 case NAME:
246 case OREG:
247 p->lval += SZINT/SZCHAR;
248 return;
249 case REG:
250 rfree( p->rval, p->type );
251 p->rval += 1;
252 p->type = m;
253 rbusy( p->rval, p->type );
254 return;
255 default:
256 cerror( "Illegal ZT type conversion" );
257 return;
258
259 }
260
261 case 'U':
262 /* same as AL for exp under U* */
263 if( p->left->op == UNARY MUL ) {
264 adrput( getlr( p->left, 'L' ) );
265 return;
266 }
267 cerror( "Illegal ZU" );
268 /* NO RETURN */
269
270 case 'W': /* structure size */
271 if( p->op == STASG )
272 printf( "%d", p->stsize);
273 else cerror( "Not a structure" );
274 return;
275
276 case 'S': /* structure assignment */
277 {
278 register NODE *l, *r;
279 register size, count;
280
281 if( p->op == STASG ){
282 l = p->left;
283 r = p->right;
284 }
285 else if( p->op == STARG ){ /* store an arg onto the stack */
286 r = p->left;
287 }
288 else cerror( "STASG bad" );
289
290 if( r->op == ICON ) r->op = NAME;
291 else if( r->op == REG ) r->op = OREG;
292 else if( r->op != OREG ) cerror( "STASG-r" );
293
294 size = p->stsize;
295 count = size / 2;
296
297 r->lval += size;
298 if( p->op == STASG ) l->lval += size;
299
300 while( count-- ){ /* simple load/store loop */
301 r->lval -= 2;
302 expand( r, FOREFF, " mov AR," );
303 if( p->op == STASG ){
304 l->lval -= 2;
305 expand( l, FOREFF, "AR\n" );
306 }
307 else {
308 printf( "-(sp)\n" );
309 }
310
311 }
312
313 if( r->op == NAME ) r->op = ICON;
314 else if( r->op == OREG ) r->op = REG;
315
316 }
317 break;
318
319 default:
320 cerror( "illegal zzzcode" );
321 }
322 }
323
324rmove( rt, rs, t ) TWORD t; {
325 printf( " %s %s,%s\n", (t==FLOAT||t==DOUBLE)?"movf":"mov", rnames[rs], rnames[rt] );
326 }
327
328struct respref
329respref[] = {
330 INTAREG|INTBREG, INTAREG|INTBREG,
331 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|SNAME|STARNM|SCON,
332 INTEMP, INTEMP,
333 FORARG, FORARG,
334 INTAREG, SOREG|SNAME,
335 0, 0 };
336
337setregs(){ /* set up temporary registers */
338 register i;
339
340 /* use any unused variable registers as scratch registers */
341 fregs = maxtreg>=MINRVAR ? maxtreg + 1 : MINRVAR;
342 if( xdebug ){
343 /* -x changes number of free regs to 2, -xx to 3, etc. */
344 if( (xdebug+1) < fregs ) fregs = xdebug+1;
345 }
346 /* NOTE: for pdp11 fregs <= 4 for float regs */
347 if( fregs > 4 ) fregs = 4;
348 for( i=MINRVAR; i<=MAXRVAR; i++ )
349 rstatus[i] = i<fregs ? SAREG|STAREG : SAREG;
350 }
351
352szty(t) TWORD t; { /* size, in words, needed to hold thing of type t */
353 /* really is the number of registers to hold type t */
354 switch( t ) {
355
356 case LONG:
357 case ULONG:
358 return( SZLONG/SZINT );
359
360 default:
361 return(1);
362
363 }
364 }
365
366rewfld( p ) NODE *p; {
367 return(1);
368 }
369
370callreg(p) NODE *p; {
371 return( (p->type==DOUBLE||p->type==FLOAT) ? FR0 : R0 );
372 }
373
374shltype( o, p ) NODE *p; {
375 if( o == NAME|| o==REG || o == ICON || o == OREG ) return( 1 );
376 return( o==UNARY MUL && shumul(p->left) );
377 }
378
379flshape( p ) register NODE *p; {
380 register o = p->op;
381 if( o==NAME || o==REG || o==ICON || o==OREG ) return( 1 );
382 return( o==UNARY MUL && shumul(p->left)==STARNM );
383 }
384
385shtemp( p ) register NODE *p; {
386 if( p->op == UNARY MUL ) p = p->left;
387 if( p->op == REG || p->op == OREG ) return( !istreg( p->rval ) );
388 return( p->op == NAME || p->op == ICON );
389 }
390
391spsz( t, v ) TWORD t; CONSZ v; {
392
393 /* is v the size to increment something of type t */
394
395 if( !ISPTR(t) ) return( 0 );
396 t = DECREF(t);
397
398 if( ISPTR(t) ) return( v == 2 );
399
400 switch( t ){
401
402 case UCHAR:
403 case CHAR:
404 return( v == 1 );
405
406 case INT:
407 case UNSIGNED:
408 return( v == 2 );
409
410 case FLOAT:
411 return( v == 4 );
412
413 case DOUBLE:
414 return( v == 8 );
415 }
416
417 return( 0 );
418 }
419
420shumul( p ) register NODE *p; {
421 register o;
422
423 o = p->op;
424 if( o == NAME || o == OREG || o == ICON ) return( STARNM );
425
426 if( ( o == INCR || o == ASG MINUS ) &&
427 ( p->left->op == REG && p->right->op == ICON ) &&
428 p->right->name[0] == '\0' &&
429 spsz( p->left->type, p->right->lval ) )
430 return( STARREG );
431
432 return( 0 );
433 }
434
435adrcon( val ) CONSZ val; {
436 printf( CONFMT, val );
437 }
438
439conput( p ) register NODE *p; {
440 switch( p->op ){
441
442 case ICON:
443 acon( p );
444 return;
445
446 case REG:
447 printf( "%s", rnames[p->rval] );
448 return;
449
450 default:
451 cerror( "illegal conput" );
452 }
453 }
454
455insput( p ) NODE *p; {
456 cerror( "insput" );
457 }
458
459upput( p ) NODE *p; {
460 /* output the address of the second word in the
461 pair pointed to by p (for LONGs)*/
462 CONSZ save;
463
464 if( p->op == FLD ){
465 p = p->left;
466 }
467
468 save = p->lval;
469 switch( p->op ){
470
471 case NAME:
472 p->lval += SZINT/SZCHAR;
473 acon( p );
474 break;
475
476 case ICON:
477 /* addressable value of the constant */
478 p->lval &= BITMASK(SZINT);
479 printf( "$" );
480 acon( p );
481 break;
482
483 case REG:
484 printf( "%s", rnames[p->rval+1] );
485 break;
486
487 case OREG:
488 p->lval += SZINT/SZCHAR;
489 if( p->rval == R5 ){ /* in the argument region */
490 if( p->name[0] != '\0' ) werror( "bad arg temp" );
491 }
492 if( p->lval != 0 || p->name[0] != '\0' ) acon( p );
493 printf( "(%s)", rnames[p->rval] );
494 break;
495
496 default:
497 cerror( "illegal upper address" );
498 break;
499
500 }
501 p->lval = save;
502
503 }
504
505adrput( p ) register NODE *p; {
506 /* output an address, with offsets, from p */
507
508 if( p->op == FLD ){
509 p = p->left;
510 }
511 switch( p->op ){
512
513 case NAME:
514 acon( p );
515 return;
516
517 case ICON:
518 /* addressable value of the constant */
519 if( szty( p->type ) == 2 ) {
520 /* print the high order value */
521 CONSZ save;
522 save = p->lval;
523 p->lval = ( p->lval >> SZINT ) & BITMASK(SZINT);
524 printf( "$" );
525 acon( p );
526 p->lval = save;
527 return;
528 }
529 printf( "$" );
530 acon( p );
531 return;
532
533 case REG:
534 printf( "%s", rnames[p->rval] );
535 return;
536
537 case OREG:
538 if( p->rval == R5 ){ /* in the argument region */
539 if( p->name[0] != '\0' ) werror( "bad arg temp" );
540 printf( CONFMT, p->lval );
541 printf( ".(r5)" );
542 return;
543 }
544 if( p->lval != 0 || p->name[0] != '\0' ) acon( p );
545 printf( "(%s)", rnames[p->rval] );
546 return;
547
548 case UNARY MUL:
549 /* STARNM or STARREG found */
550 if( tshape(p, STARNM) ) {
551 printf( "*" );
552 adrput( p->left);
553 }
554 else { /* STARREG - really auto inc or dec */
555 /* turn into OREG so replacement node will
556 reflect the value of the expression */
557 register i;
558 register NODE *q, *l;
559
560 l = p->left;
561 q = l->left;
562 p->op = OREG;
563 p->rall = q->rall;
564 p->lval = q->lval;
565 p->rval = q->rval;
566 for( i=0; i<NCHNAM; i++ )
567 p->name[i] = q->name[i];
568 if( l->op == INCR ) {
569 adrput( p );
570 printf( "+" );
571 p->lval -= l->right->lval;
572 }
573 else { /* l->op == ASG MINUS */
574 printf( "-" );
575 adrput( p );
576 }
577 tfree( l );
578 }
579 return;
580
581 default:
582 cerror( "illegal address" );
583 return;
584
585 }
586
587 }
588
589acon( p ) register NODE *p; { /* print out a constant */
590
591 if( p->name[0] == '\0' ){ /* constant only */
592 printf( CONFMT, p->lval);
593 printf( "." );
594 }
595 else if( p->lval == 0 ) { /* name only */
596 printf( "%.8s", p->name );
597 }
598 else { /* name + offset */
599 printf( "%.8s+", p->name );
600 printf( CONFMT, p->lval );
601 printf( "." );
602 }
603 }
604
605genscall( p, cookie ) register NODE *p; {
606 /* structure valued call */
607 return( gencall( p, cookie ) );
608 }
609
610gencall( p, cookie ) register NODE *p; {
611 /* generate the call given by p */
612 register temp;
613 register m;
614
615 if( p->right ) temp = argsize( p->right );
616 else temp = 0;
617
618 if( p->right ){ /* generate args */
619 genargs( p->right );
620 }
621
622 if( !shltype( p->left->op, p->left ) ) {
623 order( p->left, INAREG|SOREG );
624 }
625
626 p->op = UNARY CALL;
627 m = match( p, INTAREG|INTBREG );
628 popargs( temp );
629 return(m != MDONE);
630 }
631
632popargs( size ) register size; {
633 /* pop arguments from stack */
634
635 toff -= size/2;
636 if( toff == 0 && size >= 2 ) size -= 2;
637 switch( size ) {
638 case 0:
639 break;
640 case 2:
641 printf( " tst (sp)+\n" );
642 break;
643 case 4:
644 printf( " cmp (sp)+,(sp)+\n" );
645 break;
646 default:
647 printf( " add $%d.,sp\n", size);
648 }
649 }
650
651char *
652ccbranches[] = {
653 " jeq L%d\n",
654 " jne L%d\n",
655 " jle L%d\n",
656 " jlt L%d\n",
657 " jge L%d\n",
658 " jgt L%d\n",
659 " jlos L%d\n",
660 " jlo L%d\n",
661 " jhis L%d\n",
662 " jhi L%d\n",
663 };
664
665/* long branch table
666
667 This table, when indexed by a logical operator,
668 selects a set of three logical conditions required
669 to generate long comparisons and branches. A zero
670 entry indicates that no branch is required.
671 E.G.: The <= operator would generate:
672 cmp AL,AR
673 jlt lable / 1st entry LT -> lable
674 jgt 1f / 2nd entry GT -> 1f
675 cmp UL,UR
676 jlos lable / 3rd entry ULE -> lable
677 1:
678 */
679
680int lbranches[][3] = {
681 /*EQ*/ 0, NE, EQ,
682 /*NE*/ NE, 0, NE,
683 /*LE*/ LT, GT, ULE,
684 /*LT*/ LT, GT, ULT,
685 /*GE*/ GT, LT, UGE,
686 /*GT*/ GT, LT, UGT,
687 /*ULE*/ ULT, UGT, ULE,
688 /*ULT*/ ULT, UGT, ULT,
689 /*UGE*/ UGT, ULT, UGE,
690 /*UGT*/ UGT, ULT, UGT,
691 };
692
693/* logical relations when compared in reverse order (cmp R,L) */
694extern short revrel[] ;
695
696cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
697 register *plb;
698 int lab1f;
699
700 if( o == 0 ) printf( " jbr L%d\n", lab );
701 else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] );
702 else {
703 switch( brcase ) {
704
705 case 'A':
706 case 'C':
707 plb = lbranches[ o-EQ ];
708 lab1f = getlab();
709 expand( brnode, FORCC, brcase=='C' ? "\tcmp\tAL,AR\n" : "\ttst\tAR\n" );
710 if( *plb != 0 )
711 printf( ccbranches[*plb-EQ], lab);
712 if( *++plb != 0 )
713 printf( ccbranches[*plb-EQ], lab1f);
714 expand( brnode, FORCC, brcase=='C' ? "\tcmp\tUL,UR\n" : "\ttst\tUR\n" );
715 printf( ccbranches[*++plb-EQ], lab);
716 deflab( lab1f );
717 reclaim( brnode, RNULL, 0 );
718 break;
719
720 default:
721 if( mode=='F' ) o = revrel[ o-EQ ];
722 printf( ccbranches[o-EQ], lab );
723 break;
724 }
725
726 brcase = 0;
727 brnode = 0;
728 }
729 }
730
731nextcook( p, cookie ) NODE *p; {
732 /* we have failed to match p with cookie; try another */
733 if( cookie == FORREW ) return( 0 ); /* hopeless! */
734 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
735 if( !(cookie&INTEMP) && asgop(p->op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
736 return( FORREW );
737 }
738
739lastchance( p, cook ) NODE *p; {
740 /* forget it! */
741 return(0);
742 }
743
744struct functbl {
745 int fop;
746 TWORD ftype;
747 char *func;
748 } opfunc[] = {
749 MUL, LONG, "lmul",
750 DIV, LONG, "ldiv",
751 MOD, LONG, "lrem",
752 ASG MUL, LONG, "almul",
753 ASG DIV, LONG, "aldiv",
754 ASG MOD, LONG, "alrem",
755 MUL, ULONG, "lmul",
756 DIV, ULONG, "uldiv",
757 MOD, ULONG, "ulrem",
758 ASG MUL, ULONG, "almul",
759 ASG DIV, ULONG, "auldiv",
760 ASG MOD, ULONG, "aulrem",
761 0, 0, 0 };
762
763hardops(p) register NODE *p; {
764 /* change hard to do operators into function calls.
765 for pdp11 do long * / % */
766 register NODE *q;
767 register struct functbl *f;
768 register o;
769 register TWORD t;
770
771 o = p->op;
772 t = p->type;
773 if( t!=LONG && t!=ULONG ) return;
774
775 for( f=opfunc; f->fop; f++ ) {
776 if( o==f->fop && t==f->ftype ) goto convert;
777 }
778 return;
779
780 /* need address of left node for ASG OP */
781 /* WARNING - this won't work for long in a REG */
782 convert:
783 if( asgop( o ) ) {
784 switch( p->left->op ) {
785
786 case UNARY MUL: /* convert to address */
787 p->left->op = FREE;
788 p->left = p->left->left;
789 break;
790
791 case NAME: /* convert to ICON pointer */
792 p->left->op = ICON;
793 p->left->type = INCREF( p->left->type );
794 break;
795
796 case OREG: /* convert OREG to address */
797 p->left->op = REG;
798 p->left->type = INCREF( p->left->type );
799 if( p->left->lval != 0 ) {
800 q = talloc();
801 q->op = PLUS;
802 q->rall = NOPREF;
803 q->type = p->left->type;
804 q->left = p->left;
805 q->right = talloc();
806
807 q->right->op = ICON;
808 q->right->rall = NOPREF;
809 q->right->type = INT;
810 q->right->name[0] = '\0';
811 q->right->lval = p->left->lval;
812 q->right->rval = 0;
813
814 p->left->lval = 0;
815 p->left = q;
816 }
817 break;
818
819 default:
820 cerror( "Bad address for hard ops" );
821 /* NO RETURN */
822
823 }
824 }
825
826 /* build comma op for args to function */
827 q = talloc();
828 q->op = CM;
829 q->rall = NOPREF;
830 q->type = INT;
831 q->left = p->left;
832 q->right = p->right;
833 p->op = CALL;
834 p->right = q;
835
836 /* put function name in left node of call */
837 p->left = q = talloc();
838 q->op = ICON;
839 q->rall = NOPREF;
840 q->type = INCREF( FTN + p->type );
841 strcpy( q->name, f->func );
842 q->lval = 0;
843 q->rval = 0;
844
845 return;
846
847 }
848
849optim2( p ) register NODE *p; {
850 /* do local tree transformations and optimizations */
851
852 register NODE *r;
853
854 switch( p->op ) {
855
856 case AND:
857 /* commute L and R to eliminate compliments and constants */
858 if( p->left->op==ICON || p->left->op==COMPL ) {
859 r = p->left;
860 p->left = p->right;
861 p->right = r;
862 }
863 case ASG AND:
864 /* change meaning of AND to ~R&L - bic on pdp11 */
865 r = p->right;
866 if( r->op==ICON ) { /* compliment constant */
867 r->lval = ~r->lval;
868 }
869 else if( r->op==COMPL ) { /* ~~A => A */
870 r->op = FREE;
871 p->right = r->left;
872 }
873 else { /* insert complement node */
874 p->right = talloc();
875 p->right->op = COMPL;
876 p->right->rall = NOPREF;
877 p->right->type = r->type;
878 p->right->left = r;
879 p->right->right = NULL;
880 }
881 break;
882
883 }
884 }
885
886myreader(p) register NODE *p; {
887 walkf( p, hardops ); /* convert ops to function calls */
888 canon( p ); /* expands r-vals for fileds */
889 walkf( p, optim2 );
890 toff = 0; /* stack offset swindle */
891 }
892
893special( p, shape ) register NODE *p; {
894 /* special shape matching routine */
895
896 switch( shape ) {
897
898 case SCCON:
899 if( p->op == ICON && p->name[0]=='\0' && p->lval>= -128 && p->lval <=127 ) return( 1 );
900 break;
901
902 case SICON:
903 if( p->op == ICON && p->name[0]=='\0' && p->lval>= 0 && p->lval <=32767 ) return( 1 );
904 break;
905
906 default:
907 cerror( "bad special shape" );
908
909 }
910
911 return( 0 );
912 }
913
914# ifndef ONEPASS
915main( argc, argv ) char *argv[]; {
916 return( mainp2( argc, argv ) );
917 }
918# endif