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