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

770 lines
24 KiB
Plaintext

1File: CODEGEN.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 /* scodegen - over-all code generation for expression*/
13 /* Picks off post-fix ++, --.*/
14 scodegen(tp,cookie,reg) /* returns register result is in*/
15 struct tnode *tp;
16 int cookie;
17 int reg;
18 {
19 struct tnode *clist[20];
20 struct tnode **clp;
21 register struct tnode **cp;
22 register int r;
23 register int ccflag;
24 register struct tnode *rtp;
25
26 if( tp->t_op == COMMA ) {
27 scodegen(tp->t_left,FOREFF,reg);
28 return(scodegen(tp->t_right,cookie,reg));
29 }
30 ccflag = 0;
31 clp = clist;
32 tp = addptree(tp,&clp);
33 if( clp > clist ) {
34 /*
35 * post ++, -- in tree. We need to compile the tree post operators
36 * then generate code to do the post operators, then do any fix up of
37 * condition codes since the Stupid 68000 architect was a nimnul.
38 */
39 if( cookie == FORCC ) {
40 /*
41 * here we make the observation that if we are comparing something with
42 * zero OR the top operator of the tree is not a comparison operator,
43 * we can compile the tree to a register, and then set the condition
44 * codes OK with a tst instruction at the end.
45 */
46 if( relop(tp->t_op) ) {
47 if( (rtp=constant(tp->t_right)) && !rtp->t_value ) {
48 ccflag = 1;
49 tp = tp->t_left;
50 cookie = FORREG;
51 }
52 else
53 ccflag = 2;
54 }
55 else {
56 ccflag = 1;
57 cookie = FORREG;
58 }
59 }
1File: CODEGEN.C Page 2
60 }
61 r = codegen(tp,cookie,reg);
62 if( clp > clist ) {
63 if( ccflag == 2 )
64 outccsave(r);
65 for( cp = clist; cp < clp; cp++ )
66 codegen(*cp,FOREFF,r+1);
67 if( ccflag == 1 )
68 outcmp0(r,tp);
69 else if( ccflag == 2 )
70 outccrestore(r);
71 }
72 return(r);
73 }
74
75 /* addptree - prune off postfix ++, -- from expression tree*/
76 /* This prunes off ++, -- and collects those expressions for*/
77 /* scodegen.*/
78 char *addptree(tp,clp) /* returns pointer to pruned tree*/
79 struct tnode *tp;
80 struct tnode ***clp;
81 {
82 register int op;
83
84 op = tp->t_op;
85 if( leafop(op) || op == QMARK ) /* [vlh] 4.0 QMARK... */
86 return(tp);
87 if( op == POSTINC || op == POSTDEC ) {
88 *(*clp)++ = tp;
89 return( tcopy(tp->t_left) );
90 }
91 if( binop(op) )
92 tp->t_right = addptree(tp->t_right,clp);
93 tp->t_left = addptree(tp->t_left,clp);
94 return(tp);
95 }
96
97 /* codegen - generate code for expression*/
98 /* This calls up rcodegen, which prunes off any special register*/
99 /* optimization code, then calls ucodegen (unrecursive) code*/
100 /* generation.*/
101 codegen(tp,cookie,reg) /* returns reg result is in*/
102 struct tnode *tp; /* tree pointer*/
103 int cookie; /* code generation goals*/
104 int reg; /* first available register*/
105 {
106 register int size, savestk, ssize, r, i, scookie;
107 register struct tnode *rtp;
108
109 #ifndef NODEBUG
110 if( cflag )
111 printf("codegen op=%d cookie=%d reg=%d\n",tp->t_op,cookie,reg);
112 #endif
113 switch( tp->t_op ) {
114
115 case CALL:
116 case NACALL:
117 ssize = 0;
118 savestk = stacksize;
1File: CODEGEN.C Page 3
119 if( tp->t_left->t_op != SYMBOL )
120 stacksize++;
121 if( tp->t_op == CALL ) {
122 rtp = tp->t_right;
123 while( rtp->t_op == COMMA ) {
124 ssize =+ dofarg(rtp->t_right);
125 rtp = rtp->t_left;
126 }
127 ssize =+ dofarg(rtp);
128 }
129 tp->t_op = FJSR; /*generate JSR (unary op)*/
130 codegen(tp,FORREG,reg);
131 popstack(ssize);
132 stacksize = savestk;
133 fixresult(tp,cookie,0);
134 return(0); /*result in R0*/
135
136 case COMMA:
137 codegen(tp->t_left,FOREFF,reg);
138 return(codegen(tp->t_right,cookie,reg));
139
140 case AND:
141 if( cookie == FORCC && (i=isonebit(tp->t_right)) >= 0 &&
142 (i=dobitadd(tp->t_left,i)) >= 0 ) {
143 if( convop(tp->t_right->t_op) )
144 tp->t_right = tp->t_right->t_left;
145 tp->t_right->t_value = i;
146 tp->t_op = BTST;
147 tp = canon(tp);
148 sucomp(tp,reg,1);
149 }
150 break;
151 }
152 if( rcodegen(&tp,cookie,reg) ) {
153 if( cookie == FORCC && tp->t_op == SYMBOL && tp->t_sc == REGISTER
154 && isdreg(tp->t_reg))
155 return(reg);
156 }
157 r = ucodegen(tp,cookie,reg);
158 return(r);
159 }
160
161 /* fixresult - fix result of code generation*/
162 fixresult(tp,cookie,reg) /* returns - none*/
163 struct tnode *tp;
164 int cookie; /* wanted this cookie*/
165 int reg;
166 {
167 #ifndef NODEBUG
168 if (cflag)
169 printf("fixresult cookie=%d reg=%d op=%d\n",cookie,reg,tp->t_op);
170 #endif
171 switch( cookie ) {
172
173 case FORCC:
174 outcmp0(reg,tp);
175 break;
176
177 case FORSP:
1File: CODEGEN.C Page 4
178 case FORSTACK:
179 stacksize++;
180 outrpush(reg,tp,cookie==FORSTACK);
181 break;
182
183 }
184 return(reg);
185 }
186
187 /* ucodegen - generate code for tree given cookie and starting register*/
188 /* Handles the matching of the expression tree node with the*/
189 /* corresponding code generation table. When a match is found,*/
190 /* expand is called to expand the code skeleton macro.*/
191 ucodegen(tp,cookie,reg) /* returns reg result is in*/
192 struct tnode *tp; /* pointer to expression tree*/
193 int cookie; /* (FORCC,FOREFF,FORREG,FORSTACK)*/
194 int reg; /* first available register*/
195 {
196 register int r;
197 register char *p;
198
199 #ifndef NODEBUG
200 if(cflag)
201 putexpr("ucodegen",tp);
202 #endif
203 switch( tp->t_op ) {
204
205 case STASSIGN: /*[vlh]*/
206 outstrcpy(codegen(tp->t_left,FORREG,areg(reg)),
207 codegen(tp->t_right,FORREG,areg(reg+1)), tp->t_type);
208 return(reg);
209 break;
210
211 case SYMBOL:
212 if( cookie == FOREFF )
213 return(reg);
214 break;
215
216 case LSH:
217 if( (isareg(reg)) && (p=constant(tp->t_right)) &&
218 !(unsign(tp->t_left->t_type)) &&
219 (p->t_value == 1 || p->t_value == 2) ) {
220 r = codegen(tp->t_left,FORREG,reg);
221 outmovr(r,reg,tp->t_left);
222 if( p->t_value == 2 )
223 outaddr(reg,reg,tp);
224 outaddr(reg,reg,tp);
225 fixresult(tp,cookie,reg);
226 return(reg);
227 }
228 break;
229
230 case EQMULT:
231 case EQDIV:
232 case LEQMULT:
233 case LEQDIV:
234 case EQMOD:
235 case LEQMOD:
236 case EQRSH:
1File: CODEGEN.C Page 5
237 case EQLSH:
238 case EQAND:
239 case EQOR:
240 case EQXOR:
241 if( indexreg(tp->t_left) ) {
242 reg = dreg(reg);
243 outmovr(r=tp->t_left->t_reg,reg,tp);
244 tp->t_left->t_reg = reg;
245 codegen(tp,cookie,reg+1);
246 outmovr(reg,r,tp);
247 return(reg);
248 }
249 break;
250
251 case ADD:
252 case EQADD:
253 if( (p=constant(tp->t_right)) && p->t_value < 0 &&
254 p->t_value >= -QUICKVAL ) {
255 p->t_value = - p->t_value;
256 tp->t_op =+ (SUB-ADD);
257 }
258 break;
259 }
260 sucomp(tp,reg,1);
261 if( (r=loadexpr(tp,cookie,reg)) >= 0 )
262 return(r);
263 if( (r=cqmark(tp,cookie,reg)) >= 0 )
264 return(r);
265 if( (r=hardrel(tp,cookie,reg)) >= 0 )
266 return(r);
267 if( cookie == FORCC && (p=match(tp,FOREFF,reg)) != 0 ) {
268 r = expand(tp,FOREFF,reg,p);
269 if( asgop(tp->t_op) && indexreg(tp->t_left) )
270 outcmp0(tp->t_left->t_reg,tp->t_left);
271 }
272 else if( p = match(tp,cookie,reg) )
273 r = expand(tp,cookie,reg,p);
274 else if( cookie != FORREG )
275 r = fixresult(tp,cookie,ucodegen(tp,FORREG,reg));
276 else
277 error("no code table for %d",tp->t_op);
278 return(r);
279 }
280
281 /* outstrcpy - output structure copy */
282 outstrcpy(lr,rr,size) /*[vlh]*/
283 int lr, rr; /* left register, right register */
284 int size; /* structure size to copy */
285 {
286 register int lab;
287 lab = nextlabel++;
288 printf("move #%d,r%d\n",(size/2)-1,dreg(lr));
289 outlab(lab);
290 printf("move (r%d)+,(r%d)+\ndbra r%d,L%d\n",rr,lr,dreg(lr),lab);
291 }
292
293 /* loadexpr - load an addressable expression into a register*/
294 /* This checks for any possible usage of the register indexed*/
295 /* addressing mode. Note that this relies on the good graces of the*/
1File: CODEGEN.C Page 6
296 /* load code skeletons not to muck up the compiler registers before*/
297 /* loading an addressable expression...*/
298 loadexpr(tp,cookie,reg) /* returns register loaded or -1*/
299 struct tnode *tp; /* pointer to expression tree*/
300 int reg; /* register to load*/
301 {
302 register struct tnode *rtp, *ltp, *xtp, *atp;
303 register int off, r, type, nr, ar, xr, xt;
304
305 if( tp->t_op == INDR || LOADABLE(tp) ) {
306 type = tp->t_type;
307 if( tp->t_op == INDR && (ltp=tp->t_left)->t_op == ADD ) {
308 rtp = ltp->t_right;
309 ltp = ltp->t_left;
310 off = 0;
311 if( rtp->t_op == CINT && ((off=rtp->t_value) < -128 ||
312 off > 127 || ltp->t_op != ADD ) ) {
313 tp = snalloc(type,AUTO,off,0,0);
314 if( indexreg(ltp) )
315 tp->t_reg = ltp->t_reg;
316 else {
317 r = codegen(ltp,FORREG,areg(reg));
318 if( isdreg(r) )
319 outmovr(r,areg(r),ltp);
320 tp->t_reg = areg(r);
321 }
322 }
323 else {
324 if( rtp->t_op == CINT ) {
325 rtp = ltp->t_right;
326 ltp = ltp->t_left;
327 }
328 if(indexreg(rtp) || (!(indexreg(ltp)) && (isreg(rtp)))) {
329 xtp = ltp;
330 ltp = rtp;
331 rtp = xtp;
332 }
333 xtp = atp = 0;
334 if( indexreg(ltp) ) {
335 ar = ltp->t_reg;
336 if( (isreg(rtp)) && rtp->t_type != CHAR ) {
337 xr = rtp->t_reg;
338 xt = rtp->t_type;
339 }
340 else
341 xtp = rtp;
342 }
343 else if( (isreg(ltp)) && ltp->t_type != CHAR &&
344 (lflag || rtp->t_op != ADDR) ) {
345 xr = ltp->t_reg;
346 xt = ltp->t_type;
347 atp = rtp;
348 }
349 else if( rtp->t_op == ADDR ) {
350 atp = ltp;
351 xtp = rtp;
352 }
353 else {
354 atp = rtp;
1File: CODEGEN.C Page 7
355 xtp = ltp;
356 }
357 nr = 0;
358 if( atp )
359 nr++;
360 if( xtp && (xtp->t_op != ADDR || lflag ) )
361 nr++;
362 if( dreg(nr+reg) <= HICREG ) {
363 r = reg;
364 if( atp ) {
365 ar = codegen(atp,FORREG,areg(r));
366 if( isdreg(ar) ) {
367 outmovr(ar,areg(ar),atp);
368 ar = areg(ar);
369 }
370 r++;
371 }
372 if( xtp && xtp->t_op == ADDR && !lflag ) {
373 tp = xtp->t_left;
374 tp->t_sc =+ (EXTOFF-EXTERNAL);
375 tp->t_offset =+ off;
376 tp->t_reg = ar;
377 }
378 else {
379 if( xtp ) {
380 xr = codegen(xtp,FORREG,areg(r));
381 xt = xtp->t_type;
382 }
383 tp = xnalloc(type,ar,off,xr,xt);
384 }
385 }
386 }
387 }
388 if( (isareg(reg)) && tp->t_type == CHAR )
389 reg = dreg(reg);
390 tp = tnalloc(LOAD,tp->t_type,SU_EASY,0,tp,null);
391 return( codegen(tp,cookie,reg) );
392 }
393 return(-1);
394
395 }
396
397 /* coffset - check offset for addressable node*/
398 char *coffset(tp) /* returns ptr to const off node*/
399 struct tnode *tp; /* pointer to node*/
400 {
401 register struct tnode *rtp;
402
403 if( tp->t_op == ADD ) {
404 rtp = tp->t_right;
405 if( rtp->t_op == CINT )
406 return(rtp);
407 if(!lflag) {
408 if( rtp->t_op == ADDR )
409 return(rtp->t_left);
410 rtp = tp->t_left;
411 if( rtp->t_op == ADDR ) {
412 tp->t_left = tp->t_right;
413 tp->t_right = rtp;
1File: CODEGEN.C Page 8
414 return(rtp->t_left);
415 }
416 }
417 }
418 return(0);
419 }
420
421 /* hardrel - do relationals returning a value*/
422 hardrel(tp,cookie,reg) /* returns reg or -1*/
423 struct tnode *tp; /* pointer to tree*/
424 int cookie; /* cookie for code generation*/
425 int reg; /* low register*/
426 {
427 char *p;
428 int op, lab1, lab2;
429
430 if( cookie != FORCC && (relop(op=tp->t_op) || op == LOR ||
431 op == LAND || op == NOT) ) {
432 lab1 = nextlabel++;
433 condbr(tp,TRUE,lab1,reg);
434 p = canon(cnalloc(INT,0));
435 codegen(p,cookie,reg);
436 lab2 = nextlabel++;
437 outgoto(lab2);
438 outlab(lab1);
439 p = canon(cnalloc(INT,1));
440 codegen(p,cookie,reg);
441 outlab(lab2);
442 return(reg);
443 }
444 return(-1);
445 }
446
447 /* cqmark - compile question mark operator*/
448 /* This does the compilation of the question mark operator.*/
449 cqmark(tp,cookie,reg) /* returns reg or -1*/
450 struct tnode *tp;
451 int cookie;
452 int reg;
453 {
454 register int lab1, lab2, savestk, r;
455
456 if( tp->t_op == QMARK && cookie != FORCC ) {
457 lab1 = nextlabel++;
458 condbr(tp->t_left,FALSE,lab1,reg);
459 savestk = stacksize;
460 r = scodegen(tp->t_right->t_left,cookie,reg); /* [mc] 4.0 */
461 outmovr(r,reg,tp);
462 stacksize = savestk;
463 outgoto(lab2=nextlabel++);
464 outlab(lab1);
465 r = scodegen(tp->t_right->t_right,cookie,reg); /* [mc] 4.0 */
466 outmovr(r,reg,tp);
467 outlab(lab2);
468 return(reg);
469 }
470 return(-1);
471 }
472
1File: CODEGEN.C Page 9
473 /* condbr - handle conditional branch code generation*/
474 /* This handles the conditional branch code generation, handling*/
475 /* the special cases for constants, ||, &&, ! and generating the*/
476 /* correct conditional branch instruction.*/
477 condbr(tp,dir,lab,reg)
478 struct tnode *tp;
479 int dir;
480 int lab;
481 int reg;
482 {
483 register struct tnode *ltp, *rtp;
484 register int lab1, optype, op, subdir;
485
486 ltp = tp->t_left;
487 if( binop(op=tp->t_op) )
488 rtp = tp->t_right;
489 subdir = dir; /*set up for LOR*/
490 switch( op ) {
491
492 case CINT:
493 if( !tp->t_value ) {
494 if( dir == FALSE )
495 outgoto(lab);
496 }
497 else if( dir != FALSE )
498 outgoto(lab);
499 break;
500
501 case NOT:
502 condbr(ltp,!dir,lab,reg);
503 break;
504
505 case LAND:
506 dir = !dir;
507 case LOR:
508 if( dir == FALSE ) {
509 lab1 = nextlabel++;
510 condbr(ltp,!subdir,lab1,reg);
511 condbr(rtp,subdir,lab,reg);
512 outlab(lab1);
513 }
514 else {
515 condbr(ltp,subdir,lab,reg);
516 condbr(rtp,subdir,lab,reg);
517 }
518 break;
519
520 case COMMA:
521 scodegen(tp->t_left,FOREFF,reg);
522 condbr(tp->t_right,dir,lab,reg);
523 break;
524
525 default:
526 if( op == NEQUALS && ltp->t_op == PREDEC &&
527 isdreg(ltp->t_left->t_reg) && ltp->t_left->t_type == INT &&
528 rtp->t_op == CINT && rtp->t_value == -1 ) {
529 outdbra(ltp->t_left->t_reg,lab);
530 break;
531 }
1File: CODEGEN.C Page 10
532 if( relop(op) && ltp->t_op == AUTOINC && rtp->t_op == AUTOINC &&
533 ltp->t_type == rtp->t_type )
534 outcmpm(tp);
535 else
536 scodegen(tp,FORCC,reg);
537 optype = 0;
538 if( relop(op) ) {
539 if( unorptr(ltp->t_type) || unorptr(rtp->t_type) )
540 optype =+ 1;
541 }
542 else
543 op = NEQUALS;
544 if(!dir)
545 op = invrel[op-EQUALS];
546 optype = brtab[op-EQUALS][optype];
547 printf("%s L%d\n",mnemonics[optype],lab);
548 break;
549 }
550 }
551
552 rcodegen(tpp,cookie,reg) /* returns changed flag*/
553 struct tnode **tpp; /* pointer to tree*/
554 int cookie; /* code generation cookie*/
555 int reg; /* register to use for code*/
556 {
557 register int change, op;
558 register struct tnode *tp;
559
560 tp = *tpp;
561 op = tp->t_op;
562 change = 0;
563 if( notleafop(op) && op != COMMA ) {
564 change =+ rcodegen(&tp->t_left,cookie,reg);
565 if( binop(op) )
566 change =+ rcodegen(&tp->t_right,cookie,reg);
567 change =+ rcgen(tpp,cookie,reg);
568 }
569 if( change )
570 *tpp = canon(*tpp);
571 return(change);
572 }
573
574 rcgen(tpp,cookie,reg) /* returns changed flag*/
575 struct tnode **tpp; /* pointer to tree*/
576 int cookie; /* code generation goals*/
577 int reg; /* register to use*/
578 {
579 register struct tnode *tp, *p, *ltp, *rtp;
580 register int op, change;
581
582 change = 0;
583 for( tp = *tpp ; binop(op=tp->t_op); *tpp=tp=canon(tp), change++ ) {
584 ltp = tp->t_left;
585 if( ltp->t_op != SYMBOL )
586 break;
587 rtp = tp->t_right;
588 switch( op ) {
589
590 case ASSIGN:
1File: CODEGEN.C Page 11
591 if( ltp->t_sc != REGISTER )
592 return(change);
593 switch( rtp->t_op ) {
594
595 case MULT:
596 case DIV:
597 case MOD:
598 case AND:
599 case OR:
600 case XOR:
601 case LSH:
602 case RSH:
603 if( isareg(ltp->t_reg) )
604 return(change);
605 case ADD:
606 case SUB:
607 p = rtp->t_right;
608 if(NOTADDRESSABLE(ltp) || !noref(rtp->t_right,ltp->t_reg))
609 return(change);
610 p = rtp->t_left;
611 if( p->t_op != SYMBOL || p->t_sc != REGISTER ||
612 p->t_reg != ltp->t_reg ) {
613 tp->t_right = p;
614 #ifndef NODEBUG
615 if( cflag > 1 )
616 putexpr("rcgen",tp);
617 #endif
618 codegen(tp,FOREFF,reg);
619 }
620 tp->t_right = rtp->t_right;
621 tp->t_op = rtp->t_op + (EQADD-ADD);
622 continue;
623 }
624 case EQLSH:
625 case EQRSH:
626 if( ltp->t_sc != REGISTER )
627 return(change);
628 case EQADD:
629 case EQSUB:
630 case EQAND:
631 case EQOR:
632 case EQXOR:
633 if( ltp->t_type == CHAR )
634 return(change);
635 #ifndef NODEBUG
636 if( cflag > 1 )
637 putexpr("rcgen",tp);
638 #endif
639 ucodegen(tp,FOREFF,reg);
640 tp = ltp;
641 continue;
642
643 case PREDEC:
644 case PREINC:
645 if( cookie == FORCC || ltp->t_type == CHAR )
646 return(change);
647 ucodegen(tp,FOREFF,reg);
648 tp = ltp;
649 continue;
1File: CODEGEN.C Page 12
650 }
651 break;
652 }
653 return(change);
654 }
655
656 noref(tp,reg) /* 4.0 change */
657 struct tnode *tp; /* returns 1 if no reference in tree to reg */
658 int reg;
659 {
660 if ( leafop(tp->t_op) ) {
661 if (tp->t_op == SYMBOL && tp->t_sc == REGISTER && tp->t_reg == reg)
662 return(0);
663 return(1);
664 }
665 if ( !noref(tp->t_left,reg) )
666 return(0);
667 if (binop(tp->t_op))
668 return( noref(tp->t_right,reg) );
669 return(1);
670 }
671
672 /* cdsize - compute size of data item*/
673 cdsize(tp) /* returns data size in bytes*/
674 struct tnode *tp;
675 {
676 register int type;
677
678 type = tp->t_type;
679 if( suptype(type) )
680 return(PTRSIZE);
681 switch( type ) {
682
683 case CHAR:
684 case INT:
685 case UNSIGNED:
686 return(INTSIZE);
687
688 case LONG:
689 case FLOAT: /* [vlh] 3.4 */
690 return(LONGSIZE);
691 }
692 error("cdsize: invalid type %d",type);
693 return(0);
694 }
695
696 dofarg(tp) /* returns number of bytes pushed*/
697 struct tnode *tp; /* pointer to expression tree*/
698 {
699 register int nb;
700
701 nb = 0;
702 if( tp->t_op == SYMBOL && tp->t_sc == STRUCT )
703 error("structure operation not implemented");
704 else if( stacksize ) {
705 codegen(tp,FORSTACK,0);
706 nb = cdsize(tp);
707 }
708 else
1File: CODEGEN.C Page 13
709 codegen(tp,FORSP,0);
710 return( nb );
711 }
712
713 /* dobitadd - do bit operation address checking and fixup*/
714 dobitadd(tp,bitno) /* returns -1 if can't or bitno*/
715 struct tnode *tp;
716 int bitno;
717 {
718 register int offset;
719
720 if( tp->t_type == CHAR )
721 offset = 0;
722 else
723 offset = cdsize(tp) - (bitno/BITSPBYTE) - 1;
724 if( tp->t_op == SYMBOL ) {
725 switch( tp->t_sc ) {
726
727 case REGISTER:
728 if( isdreg(tp->t_reg) )
729 return(bitno);
730 default:
731 return(-1);
732
733 case EXTERNAL:
734 case STATIC:
735 case REGOFF:
736 case STATOFF:
737 case EXTOFF:
738 tp->t_offset =+ offset;
739 return( bitno % BITSPBYTE );
740 }
741 }
742 else if( tp->t_op == INDR ) {
743 tp->t_left = tnalloc(ADD,tp->t_left->t_type,0,0,tp->t_left,
744 cnalloc(INT,offset));
745 return( bitno % BITSPBYTE );
746 }
747 return(-1);
748 }
749
750 isonebit(tp) /* returns -1 if not 1 bit, else bitno*/
751 struct tnode *tp; /* pointer to tree*/
752 {
753 if( tp = constant(tp) )
754 return( onebit(tp->t_value) );
755 return(-1);
756 }