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