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 }