1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.19 (Berkeley) 12/11/87"; 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 putstr(s) fputs((s), stdout) 13 14 # define BITMASK(n) ((1L<<n)-1) 15 16 /*ARGSUSED*/ 17 where(c){ 18 fprintf( stderr, "%s, line %d: ", filename, lineno ); 19 } 20 21 lineid( l, fn ) char *fn; { 22 /* identify line l and file fn */ 23 printf( "# line %d, file %s\n", l, fn ); 24 } 25 26 27 eobl2(){ 28 OFFSZ spoff; /* offset from stack pointer */ 29 #ifdef FORT 30 spoff = maxoff; 31 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 32 spoff /= SZCHAR; 33 SETOFF(spoff,4); 34 #ifndef FLEXNAMES 35 printf( " .set .F%d,%ld\n", ftnno, spoff ); 36 #else 37 /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 38 printf( " .set LF%d,%ld\n", ftnno, spoff ); 39 #endif 40 #else 41 extern int ftlab1, ftlab2; 42 43 spoff = maxoff; 44 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 45 spoff /= SZCHAR; 46 SETOFF(spoff,4); 47 printf( "L%d:\n", ftlab1); 48 if( spoff!=0 ) 49 if( spoff < 64 ) 50 printf( " subl2 $%ld,sp\n", spoff); 51 else 52 printf( " movab -%ld(sp),sp\n", spoff); 53 printf( " jbr L%d\n", ftlab2); 54 #endif 55 maxargs = -1; 56 } 57 58 struct hoptab { int opmask; char * opstring; } ioptab[] = { 59 60 ASG PLUS, "add", 61 ASG MINUS, "sub", 62 ASG MUL, "mul", 63 ASG DIV, "div", 64 ASG OR, "bis", 65 ASG ER, "xor", 66 ASG AND, "bic", 67 PLUS, "add", 68 MINUS, "sub", 69 MUL, "mul", 70 DIV, "div", 71 OR, "bis", 72 ER, "xor", 73 AND, "bic", 74 -1, "" }; 75 76 hopcode( f, o ){ 77 /* output the appropriate string from the above table */ 78 79 register struct hoptab *q; 80 81 for( q = ioptab; q->opmask>=0; ++q ){ 82 if( q->opmask == o ){ 83 putstr( q->opstring ); 84 /* tbl 85 if( f == 'F' ) putchar( 'e' ); 86 else if( f == 'D' ) putchar( 'd' ); 87 tbl */ 88 /* tbl */ 89 switch( f ) { 90 case 'L': 91 case 'W': 92 case 'B': 93 case 'D': 94 case 'F': 95 putchar(tolower(f)); 96 break; 97 98 } 99 /* tbl */ 100 return; 101 } 102 } 103 cerror( "no hoptab for %s", opst[o] ); 104 } 105 106 char * 107 rnames[] = { /* keyed to register number tokens */ 108 109 "r0", "r1", 110 "r2", "r3", "r4", "r5", 111 "r6", "r7", "r8", "r9", "r10", "r11", 112 "ap", "fp", "sp", "pc", 113 114 }; 115 116 int rstatus[] = { 117 SAREG|STAREG, SAREG|STAREG, 118 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 119 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 120 SAREG, SAREG, SAREG, SAREG, 121 122 }; 123 124 tlen(p) NODE *p; 125 { 126 switch(p->in.type) { 127 case CHAR: 128 case UCHAR: 129 return(1); 130 131 case SHORT: 132 case USHORT: 133 return(2); 134 135 case DOUBLE: 136 return(8); 137 138 default: 139 return(4); 140 } 141 } 142 143 mixtypes(p, q) NODE *p, *q; 144 { 145 register TWORD tp, tq; 146 147 tp = p->in.type; 148 tq = q->in.type; 149 150 return( (tp==FLOAT || tp==DOUBLE) != 151 (tq==FLOAT || tq==DOUBLE) ); 152 } 153 154 prtype(n) NODE *n; 155 { 156 switch (n->in.type) 157 { 158 case DOUBLE: 159 putchar('d'); 160 return; 161 162 case FLOAT: 163 putchar('f'); 164 return; 165 166 case LONG: 167 case ULONG: 168 case INT: 169 case UNSIGNED: 170 putchar('l'); 171 return; 172 173 case SHORT: 174 case USHORT: 175 putchar('w'); 176 return; 177 178 case CHAR: 179 case UCHAR: 180 putchar('b'); 181 return; 182 183 default: 184 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 185 else { 186 putchar('l'); 187 return; 188 } 189 } 190 } 191 192 zzzcode( p, c ) register NODE *p; { 193 register m; 194 int val; 195 switch( c ){ 196 197 case 'N': /* logical ops, turned into 0-1 */ 198 /* use register given by register 1 */ 199 cbgen( 0, m=getlab(), 'I' ); 200 deflab( p->bn.label ); 201 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 202 deflab( m ); 203 return; 204 205 case 'I': 206 case 'P': 207 cbgen( p->in.op, p->bn.label, c ); 208 return; 209 210 case 'A': 211 { 212 register NODE *l, *r; 213 214 if (xdebug) eprint(p, 0, &val, &val); 215 r = getlr(p, 'R'); 216 if (p->in.op == ASSIGN) 217 l = getlr(p, 'L'); 218 else if (p->in.op == SCONV) { 219 l = resc; 220 #if defined(FORT) || defined(SPRECC) 221 l->in.type = r->in.type; 222 #else 223 l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 224 #endif 225 r = getlr(p, 'L'); 226 } 227 else { /* OPLTYPE */ 228 l = resc; 229 #if defined(FORT) || defined(SPRECC) 230 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 231 #else 232 l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 233 #endif 234 } 235 if (r->in.op == ICON) 236 if (r->in.name[0] == '\0') { 237 if (r->tn.lval == 0) { 238 putstr("clr"); 239 prtype(l); 240 putchar('\t'); 241 adrput(l); 242 return; 243 } 244 if (r->tn.lval < 0 && r->tn.lval >= -63) { 245 putstr("mneg"); 246 prtype(l); 247 r->tn.lval = -r->tn.lval; 248 goto ops; 249 } 250 if (r->tn.lval < 0) 251 r->in.type = r->tn.lval >= -128 ? CHAR 252 : (r->tn.lval >= -32768 ? SHORT 253 : INT); 254 else if (l->in.type == FLOAT || 255 l->in.type == DOUBLE) 256 r->in.type = r->tn.lval <= 63 ? INT 257 : (r->tn.lval <= 127 ? CHAR 258 : (r->tn.lval <= 32767 ? SHORT 259 : INT)); 260 else 261 r->in.type = r->tn.lval <= 63 ? INT 262 : (r->tn.lval <= 127 ? CHAR 263 : (r->tn.lval <= 255 ? UCHAR 264 : (r->tn.lval <= 32767 ? SHORT 265 : (r->tn.lval <= 65535 ? USHORT 266 : INT)))); 267 } 268 else { 269 putstr("moval"); 270 putchar('\t'); 271 acon(r); 272 putchar(','); 273 adrput(l); 274 return; 275 } 276 277 if (p->in.op == SCONV && 278 !(l->in.type == FLOAT || l->in.type == DOUBLE) && 279 !mixtypes(l, r)) { 280 /* 281 * Because registers must always contain objects 282 * of the same width as INTs, we may have to 283 * perform two conversions to get an INT. Can 284 * the conversions be collapsed into one? 285 */ 286 if (m = collapsible(l, r)) 287 r->in.type = m; 288 else { 289 /* 290 * Two steps are required. 291 */ 292 NODE *x = &resc[1]; 293 294 *x = *l; 295 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 296 putstr("movz"); 297 else 298 putstr("cvt"); 299 prtype(r); 300 prtype(x); 301 putchar('\t'); 302 adrput(r); 303 putchar(','); 304 adrput(x); 305 putchar('\n'); 306 putchar('\t'); 307 r = x; 308 } 309 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 310 } 311 312 if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 313 mixtypes(l, r)) { 314 int label1, label2; 315 316 label1 = getlab(); 317 label2 = getlab(); 318 319 putstr("movl\t"); 320 adrput(r); 321 putchar(','); 322 adrput(l); 323 putstr("\n\tjbsc\t$31,"); 324 adrput(l); 325 printf(",L%d\n\tcvtl", label1); 326 prtype(l); 327 putchar('\t'); 328 adrput(l); 329 putchar(','); 330 adrput(l); 331 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 332 prtype(l); 333 putchar('\t'); 334 adrput(l); 335 putchar(','); 336 adrput(l); 337 putstr("\n\tadd"); 338 prtype(l); 339 putstr("2\t$0"); 340 prtype(l); 341 putstr("2.147483648e9,"); 342 adrput(l); 343 printf("\nL%d:", label2); 344 345 return; 346 } 347 348 if (!mixtypes(l,r)) { 349 if (tlen(l) == tlen(r)) { 350 putstr("mov"); 351 #ifdef FORT 352 if (Oflag) 353 prtype(l); 354 else { 355 if (l->in.type == DOUBLE) 356 putchar('q'); 357 else if(l->in.type == FLOAT) 358 putchar('l'); 359 else 360 prtype(l); 361 } 362 #else 363 prtype(l); 364 #endif FORT 365 goto ops; 366 } 367 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 368 putstr("movz"); 369 else 370 putstr("cvt"); 371 } 372 else 373 putstr("cvt"); 374 prtype(r); 375 prtype(l); 376 ops: 377 putchar('\t'); 378 adrput(r); 379 putchar(','); 380 adrput(l); 381 return; 382 } 383 384 case 'G': /* i *= f; asgops with int lhs and float rhs */ 385 { 386 register NODE *l, *r, *s; 387 int rt; 388 389 l = p->in.left; 390 r = p->in.right; 391 s = talloc(); 392 rt = r->in.type; 393 394 s->in.op = SCONV; 395 s->in.left = l; 396 s->in.type = rt; 397 zzzcode(s, 'A'); 398 putstr("\n\t"); 399 400 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 401 putstr("2\t"); 402 adrput(r); 403 putchar(','); 404 adrput(resc); 405 putstr("\n\t"); 406 407 s->in.op = ASSIGN; 408 s->in.left = l; 409 s->in.right = resc; 410 s->in.type = l->in.type; 411 zzzcode(s, 'A'); 412 413 s->in.op = FREE; 414 return; 415 } 416 417 case 'B': /* get oreg value in temp register for left shift */ 418 { 419 register NODE *r; 420 if (xdebug) eprint(p, 0, &val, &val); 421 r = p->in.right; 422 if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 423 putstr("movl"); 424 else { 425 putstr("cvt"); 426 prtype(r); 427 putchar('l'); 428 } 429 return; 430 } 431 432 case 'C': /* num words pushed on arg stack */ 433 { 434 extern int gc_numbytes; 435 extern int xdebug; 436 437 if (xdebug) printf("->%d<-",gc_numbytes); 438 439 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 440 return; 441 } 442 443 case 'D': /* INCR and DECR */ 444 zzzcode(p->in.left, 'A'); 445 putchar('\n'); 446 putchar('\t'); 447 448 case 'E': /* INCR and DECR, FOREFF */ 449 if (p->in.right->tn.lval == 1) 450 { 451 putstr( p->in.op == INCR ? "inc" : "dec" ); 452 prtype(p->in.left); 453 putchar('\t'); 454 adrput(p->in.left); 455 return; 456 } 457 putstr( p->in.op == INCR ? "add" : "sub" ); 458 prtype(p->in.left); 459 putchar('2'); 460 putchar('\t'); 461 adrput(p->in.right); 462 putchar(','); 463 adrput(p->in.left); 464 return; 465 466 case 'F': /* register type of right operand */ 467 { 468 register NODE *n; 469 extern int xdebug; 470 register int ty; 471 472 n = getlr( p, 'R' ); 473 ty = n->in.type; 474 475 if (xdebug) printf("->%d<-", ty); 476 477 if ( ty==DOUBLE) putchar('d'); 478 else if ( ty==FLOAT ) putchar('f'); 479 else putchar('l'); 480 return; 481 } 482 483 case 'L': /* type of left operand */ 484 case 'R': /* type of right operand */ 485 { 486 register NODE *n; 487 extern int xdebug; 488 489 n = getlr( p, c ); 490 if (xdebug) printf("->%d<-", n->in.type); 491 492 prtype(n); 493 return; 494 } 495 496 case 'Z': /* complement mask for bit instr */ 497 printf("$%ld", ~p->in.right->tn.lval); 498 return; 499 500 case 'U': /* 32 - n, for unsigned right shifts */ 501 printf("$%d", 32 - p->in.right->tn.lval ); 502 return; 503 504 case 'T': /* rounded structure length for arguments */ 505 { 506 int size; 507 508 size = p->stn.stsize; 509 SETOFF( size, 4); 510 printf("$%d", size); 511 return; 512 } 513 514 case 'S': /* structure assignment */ 515 { 516 register NODE *l, *r; 517 register size; 518 519 if( p->in.op == STASG ){ 520 l = p->in.left; 521 r = p->in.right; 522 523 } 524 else if( p->in.op == STARG ){ /* store an arg into a temporary */ 525 r = p->in.left; 526 } 527 else cerror( "STASG bad" ); 528 529 if( r->in.op == ICON ) r->in.op = NAME; 530 else if( r->in.op == REG ) r->in.op = OREG; 531 else if( r->in.op != OREG ) cerror( "STASG-r" ); 532 533 size = p->stn.stsize; 534 535 if( size <= 0 || size > 65535 ) 536 cerror("structure size <0=0 or >65535"); 537 538 switch(size) { 539 case 1: 540 putstr(" movb "); 541 break; 542 case 2: 543 putstr(" movw "); 544 break; 545 case 4: 546 putstr(" movl "); 547 break; 548 case 8: 549 putstr(" movq "); 550 break; 551 default: 552 printf(" movc3 $%d,", size); 553 break; 554 } 555 adrput(r); 556 if( p->in.op == STASG ){ 557 putchar(','); 558 adrput(l); 559 putchar('\n'); 560 } 561 else 562 putstr(",(sp)\n"); 563 564 if( r->in.op == NAME ) r->in.op = ICON; 565 else if( r->in.op == OREG ) r->in.op = REG; 566 567 } 568 break; 569 570 default: 571 cerror( "illegal zzzcode" ); 572 } 573 } 574 575 /* 576 * collapsible(dest, src) -- if a conversion with a register destination 577 * can be accomplished in one instruction, return the type of src 578 * that will do the job correctly; otherwise return 0. Note that 579 * a register must always end up having type INT or UNSIGNED. 580 */ 581 int 582 collapsible(dest, src) 583 NODE *dest, *src; 584 { 585 int st = src->in.type; 586 int dt = dest->in.type; 587 int newt = 0; 588 589 /* 590 * Are there side effects of evaluating src? 591 * If the derived type will not be the same size as src, 592 * we may have to use two steps. 593 */ 594 if (tlen(src) > tlen(dest)) { 595 if (tshape(src, STARREG)) 596 return (0); 597 if (src->in.op == OREG && R2TEST(src->tn.rval)) 598 return (0); 599 } 600 601 /* 602 * Can we get an object of dest's type by punning src? 603 * Praises be to great Cthulhu for little-endian machines... 604 */ 605 if (st == CHAR && dt == USHORT) 606 /* 607 * Special case -- we must sign-extend to 16 bits. 608 */ 609 return (0); 610 611 if (tlen(src) < tlen(dest)) 612 newt = st; 613 else 614 newt = dt; 615 616 return (newt); 617 } 618 619 rmove( rt, rs, t ) TWORD t; { 620 printf( " %s %s,%s\n", 621 #ifdef FORT 622 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 623 #endif 624 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 625 rnames[rs], rnames[rt] ); 626 } 627 628 struct respref 629 respref[] = { 630 INTAREG|INTBREG, INTAREG|INTBREG, 631 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 632 INTEMP, INTEMP, 633 FORARG, FORARG, 634 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 635 0, 0 }; 636 637 setregs(){ /* set up temporary registers */ 638 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 639 ; 640 } 641 642 /*ARGSUSED*/ 643 rewfld( p ) NODE *p; { 644 return(1); 645 } 646 647 /*ARGSUSED*/ 648 callreg(p) NODE *p; { 649 return( R0 ); 650 } 651 652 base( p ) register NODE *p; { 653 register int o = p->in.op; 654 655 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 656 if( o==REG ) return( p->tn.rval ); 657 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 658 return( p->in.left->tn.rval ); 659 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 660 return( p->tn.rval + 0200*1 ); 661 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 662 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 663 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 664 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 665 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 666 return( -1 ); 667 } 668 669 offset( p, tyl ) register NODE *p; int tyl; { 670 671 if( tyl==1 && 672 p->in.op==REG && 673 (p->in.type==INT || p->in.type==UNSIGNED) ) 674 return( p->tn.rval ); 675 if( p->in.op==LS && 676 p->in.left->in.op==REG && 677 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 678 p->in.right->in.op==ICON && 679 p->in.right->in.name[0]=='\0' && 680 (1<<p->in.right->tn.lval)==tyl) 681 return( p->in.left->tn.rval ); 682 if( tyl==2 && 683 p->in.op==PLUS && 684 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 685 p->in.left->in.op==REG && 686 p->in.right->in.op==REG && 687 p->in.left->tn.rval==p->in.right->tn.rval ) 688 return( p->in.left->tn.rval ); 689 return( -1 ); 690 } 691 692 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 693 register NODE *t; 694 NODE *f; 695 696 p->in.op = OREG; 697 f = p->in.left; /* have to free this subtree later */ 698 699 /* init base */ 700 switch (q->in.op) { 701 case ICON: 702 case REG: 703 case OREG: 704 t = q; 705 break; 706 707 case MINUS: 708 q->in.right->tn.lval = -q->in.right->tn.lval; 709 case PLUS: 710 t = q->in.right; 711 break; 712 713 case INCR: 714 case ASG MINUS: 715 t = q->in.left; 716 break; 717 718 case UNARY MUL: 719 t = q->in.left->in.left; 720 break; 721 722 default: 723 cerror("illegal makeor2"); 724 } 725 726 p->tn.lval = t->tn.lval; 727 #ifndef FLEXNAMES 728 { 729 register int i; 730 for(i=0; i<NCHNAM; ++i) 731 p->in.name[i] = t->in.name[i]; 732 } 733 #else 734 p->in.name = t->in.name; 735 #endif 736 737 /* init offset */ 738 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 739 740 tfree(f); 741 return; 742 } 743 744 canaddr( p ) NODE *p; { 745 register int o = p->in.op; 746 747 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 748 return(0); 749 } 750 751 flshape( p ) register NODE *p; { 752 return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 753 (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 754 } 755 756 shtemp( p ) register NODE *p; { 757 if( p->in.op == STARG ) p = p->in.left; 758 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 759 } 760 761 shumul( p ) register NODE *p; { 762 register o; 763 extern int xdebug; 764 765 if (xdebug) { 766 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 767 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 768 } 769 770 771 o = p->in.op; 772 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 773 774 if( ( o == INCR || o == ASG MINUS ) && 775 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 776 p->in.right->in.name[0] == '\0' ) 777 { 778 switch (p->in.type) 779 { 780 case CHAR|PTR: 781 case UCHAR|PTR: 782 o = 1; 783 break; 784 785 case SHORT|PTR: 786 case USHORT|PTR: 787 o = 2; 788 break; 789 790 case INT|PTR: 791 case UNSIGNED|PTR: 792 case LONG|PTR: 793 case ULONG|PTR: 794 case FLOAT|PTR: 795 o = 4; 796 break; 797 798 case DOUBLE|PTR: 799 o = 8; 800 break; 801 802 default: 803 if ( ISPTR(p->in.type) && 804 ISPTR(DECREF(p->in.type)) ) { 805 o = 4; 806 break; 807 } 808 else return(0); 809 } 810 return( p->in.right->tn.lval == o ? STARREG : 0); 811 } 812 813 return( 0 ); 814 } 815 816 adrcon( val ) CONSZ val; { 817 putchar( '$' ); 818 printf( CONFMT, val ); 819 } 820 821 conput( p ) register NODE *p; { 822 switch( p->in.op ){ 823 824 case ICON: 825 acon( p ); 826 return; 827 828 case REG: 829 putstr( rnames[p->tn.rval] ); 830 return; 831 832 default: 833 cerror( "illegal conput" ); 834 } 835 } 836 837 /*ARGSUSED*/ 838 insput( p ) NODE *p; { 839 cerror( "insput" ); 840 } 841 842 /*ARGSUSED*/ 843 upput( p, off ) NODE *p; int off; { 844 cerror( "upput" ); 845 } 846 847 adrput( p ) register NODE *p; { 848 register int r; 849 /* output an address, with offsets, from p */ 850 851 if( p->in.op == FLD ){ 852 p = p->in.left; 853 } 854 switch( p->in.op ){ 855 856 case NAME: 857 acon( p ); 858 return; 859 860 case ICON: 861 /* addressable value of the constant */ 862 putchar( '$' ); 863 acon( p ); 864 return; 865 866 case REG: 867 putstr( rnames[p->tn.rval] ); 868 return; 869 870 case OREG: 871 r = p->tn.rval; 872 if( R2TEST(r) ){ /* double indexing */ 873 register int flags; 874 875 flags = R2UPK3(r); 876 if( flags & 1 ) putchar('*'); 877 if( flags & 4 ) putchar('-'); 878 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 879 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 880 if( flags & 2 ) putchar('+'); 881 printf( "[%s]", rnames[R2UPK2(r)] ); 882 return; 883 } 884 if( r == AP ){ /* in the argument region */ 885 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 886 printf( CONFMT, p->tn.lval ); 887 putstr( "(ap)" ); 888 return; 889 } 890 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 891 printf( "(%s)", rnames[p->tn.rval] ); 892 return; 893 894 case UNARY MUL: 895 /* STARNM or STARREG found */ 896 if( tshape(p, STARNM) ) { 897 putchar( '*' ); 898 adrput( p->in.left); 899 } 900 else { /* STARREG - really auto inc or dec */ 901 register NODE *q; 902 903 /* tbl 904 p = p->in.left; 905 p->in.left->in.op = OREG; 906 if( p->in.op == INCR ) { 907 adrput( p->in.left ); 908 putchar( '+' ); 909 } 910 else { 911 putchar( '-' ); 912 adrput( p->in.left ); 913 } 914 tbl */ 915 q = p->in.left; 916 if( q->in.right->tn.lval != tlen(p) ) 917 cerror("adrput: bad auto-increment/decrement"); 918 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 919 rnames[q->in.left->tn.rval], 920 (q->in.op==INCR ? "+" : "") ); 921 p->in.op = OREG; 922 p->tn.rval = q->in.left->tn.rval; 923 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 924 #ifndef FLEXNAMES 925 p->in.name[0] = '\0'; 926 #else 927 p->in.name = ""; 928 #endif 929 tfree(q); 930 } 931 return; 932 933 default: 934 cerror( "illegal address" ); 935 return; 936 937 } 938 939 } 940 941 acon( p ) register NODE *p; { /* print out a constant */ 942 943 if( p->in.name[0] == '\0' ){ 944 printf( CONFMT, p->tn.lval); 945 } 946 else if( p->tn.lval == 0 ) { 947 #ifndef FLEXNAMES 948 printf( "%.8s", p->in.name ); 949 #else 950 putstr( p->in.name ); 951 #endif 952 } 953 else { 954 #ifndef FLEXNAMES 955 printf( "%.8s+", p->in.name ); 956 #else 957 printf( "%s+", p->in.name ); 958 #endif 959 printf( CONFMT, p->tn.lval ); 960 } 961 } 962 963 /* 964 aacon( p ) register NODE *p; { /* print out a constant */ 965 /* 966 967 if( p->in.name[0] == '\0' ){ 968 printf( CONFMT, p->tn.lval); 969 return( 0 ); 970 } 971 else if( p->tn.lval == 0 ) { 972 #ifndef FLEXNAMES 973 printf( "$%.8s", p->in.name ); 974 #else 975 printf( "$%s", p->in.name ); 976 #endif 977 return( 1 ); 978 } 979 else { 980 printf( "$(" ); 981 printf( CONFMT, p->tn.lval ); 982 printf( "+" ); 983 #ifndef FLEXNAMES 984 printf( "%.8s)", p->in.name ); 985 #else 986 printf( "%s)", p->in.name ); 987 #endif 988 return(1); 989 } 990 } 991 */ 992 993 genscall( p, cookie ) register NODE *p; { 994 /* structure valued call */ 995 return( gencall( p, cookie ) ); 996 } 997 998 /* tbl */ 999 int gc_numbytes; 1000 /* tbl */ 1001 1002 /*ARGSUSED*/ 1003 gencall( p, cookie ) register NODE *p; { 1004 /* generate the call given by p */ 1005 register NODE *p1; 1006 register temp, temp1; 1007 register m; 1008 1009 if( p->in.right ) temp = argsize( p->in.right ); 1010 else temp = 0; 1011 1012 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1013 /* set aside room for structure return */ 1014 1015 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1016 else temp1 = temp; 1017 } 1018 1019 if( temp > maxargs ) maxargs = temp; 1020 SETOFF(temp1,4); 1021 1022 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1023 genargs( p->in.right ); 1024 } 1025 1026 p1 = p->in.left; 1027 if( p1->in.op != ICON ){ 1028 if( p1->in.op != REG ){ 1029 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1030 if( p1->in.op != NAME ){ 1031 order( p1, INAREG ); 1032 } 1033 } 1034 } 1035 } 1036 1037 /* 1038 if( p1->in.op == REG && p->tn.rval == R5 ){ 1039 cerror( "call register overwrite" ); 1040 } 1041 */ 1042 /* tbl 1043 setup gc_numbytes so reference to ZC works */ 1044 1045 gc_numbytes = temp&(0x3ff); 1046 /* tbl */ 1047 1048 p->in.op = UNARY CALL; 1049 m = match( p, INTAREG|INTBREG ); 1050 1051 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1052 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1053 if (temp >= 1024) 1054 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1055 1056 /* tbl 1057 switch( temp ) { 1058 case 0: 1059 break; 1060 case 2: 1061 printf( " tst (sp)+\n" ); 1062 break; 1063 case 4: 1064 printf( " cmp (sp)+,(sp)+\n" ); 1065 break; 1066 default: 1067 printf( " add $%d,sp\n", temp); 1068 } 1069 tbl */ 1070 return(m != MDONE); 1071 } 1072 1073 /* tbl */ 1074 char * 1075 ccbranches[] = { 1076 " jeql L%d\n", 1077 " jneq L%d\n", 1078 " jleq L%d\n", 1079 " jlss L%d\n", 1080 " jgeq L%d\n", 1081 " jgtr L%d\n", 1082 " jlequ L%d\n", 1083 " jlssu L%d\n", 1084 " jgequ L%d\n", 1085 " jgtru L%d\n", 1086 }; 1087 /* tbl */ 1088 1089 /*ARGSUSED*/ 1090 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1091 1092 /* tbl */ 1093 if( o == 0 ) printf( " jbr L%d\n", lab ); 1094 /* tbl */ 1095 else { 1096 if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 1097 printf( ccbranches[o-EQ], lab ); 1098 } 1099 } 1100 1101 nextcook( p, cookie ) NODE *p; { 1102 /* we have failed to match p with cookie; try another */ 1103 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1104 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1105 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1106 return( FORREW ); 1107 } 1108 1109 /*ARGSUSED*/ 1110 lastchance( p, cook ) NODE *p; { 1111 /* forget it! */ 1112 return(0); 1113 } 1114 1115 optim2( p ) register NODE *p; { 1116 /* do local tree transformations and optimizations */ 1117 1118 register NODE *l, *r; 1119 1120 switch( p->in.op ) { 1121 1122 case AND: 1123 /* commute L and R to eliminate complements and constants */ 1124 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1125 l->in.op == COMPL ) { 1126 p->in.left = p->in.right; 1127 p->in.right = l; 1128 } 1129 case ASG AND: 1130 /* change meaning of AND to ~R&L - bic on pdp11 */ 1131 r = p->in.right; 1132 if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 1133 r->tn.lval = ~r->tn.lval; 1134 } 1135 else if( r->in.op==COMPL ) { /* ~~A => A */ 1136 r->in.op = FREE; 1137 p->in.right = r->in.left; 1138 } 1139 else { /* insert complement node */ 1140 p->in.right = l = talloc(); 1141 l->in.op = COMPL; 1142 l->in.rall = NOPREF; 1143 l->in.type = r->in.type; 1144 l->in.left = r; 1145 l->in.right = NULL; 1146 } 1147 break; 1148 1149 case SCONV: 1150 l = p->in.left; 1151 #if defined(FORT) || defined(SPRECC) 1152 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1153 l->in.type == FLOAT || l->in.type == DOUBLE ) 1154 return; 1155 #else 1156 if( mixtypes(p, l) ) return; 1157 #endif 1158 if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 1159 return; 1160 1161 /* Only trust it to get it right if the size is the same */ 1162 if( tlen(p) != tlen(l) ) 1163 return; 1164 1165 /* clobber conversion */ 1166 if( l->in.op != FLD ) 1167 l->in.type = p->in.type; 1168 ncopy( p, l ); 1169 l->in.op = FREE; 1170 1171 break; 1172 1173 case ASSIGN: 1174 /* 1175 * Conversions are equivalent to assignments; 1176 * when the two operations are combined, 1177 * we can sometimes zap the conversion. 1178 */ 1179 r = p->in.right; 1180 l = p->in.left; 1181 if ( r->in.op == SCONV && 1182 !mixtypes(l, r) && 1183 l->in.op != FLD && 1184 tlen(l) == tlen(r) ) { 1185 p->in.right = r->in.left; 1186 r->in.op = FREE; 1187 } 1188 break; 1189 1190 } 1191 } 1192 1193 /*ARGSUSED*/ 1194 NODE * addroreg(l) NODE *l; 1195 /* OREG was built in clocal() 1196 * for an auto or formal parameter 1197 * now its address is being taken 1198 * local code must unwind it 1199 * back to PLUS/MINUS REG ICON 1200 * according to local conventions 1201 */ 1202 { 1203 cerror("address of OREG taken"); 1204 /*NOTREACHED*/ 1205 } 1206 1207 1208 1209 # ifndef ONEPASS 1210 main( argc, argv ) char *argv[]; { 1211 return( mainp2( argc, argv ) ); 1212 } 1213 # endif 1214 1215 1216 /* added by jwf */ 1217 struct functbl { 1218 int fop; 1219 TWORD ftype; 1220 char *func; 1221 } opfunc[] = { 1222 DIV, TANY, "udiv", 1223 MOD, TANY, "urem", 1224 ASG DIV, TANY, "audiv", 1225 ASG MOD, TANY, "aurem", 1226 0, 0, 0 }; 1227 1228 hardops(p) register NODE *p; { 1229 /* change hard to do operators into function calls. */ 1230 register NODE *q; 1231 register struct functbl *f; 1232 register o; 1233 NODE *old,*temp; 1234 1235 o = p->in.op; 1236 if( ! (optype(o)==BITYPE && 1237 (ISUNSIGNED(p->in.left->in.type) || 1238 ISUNSIGNED(p->in.right->in.type))) ) 1239 return; 1240 1241 for( f=opfunc; f->fop; f++ ) { 1242 if( o==f->fop ) goto convert; 1243 } 1244 return; 1245 1246 convert: 1247 if( asgop( o ) ) { 1248 old = NIL; 1249 switch( p->in.left->in.op ){ 1250 case FLD: 1251 q = p->in.left->in.left; 1252 /* 1253 * rewrite (lval.fld /= rval); as 1254 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1255 * else the compiler will evaluate lval twice. 1256 */ 1257 if( q->in.op == UNARY MUL ){ 1258 /* first allocate a temp storage */ 1259 temp = talloc(); 1260 temp->in.op = OREG; 1261 temp->tn.rval = TMPREG; 1262 temp->tn.lval = BITOOR(freetemp(1)); 1263 temp->in.type = INCREF(p->in.type); 1264 #ifdef FLEXNAMES 1265 temp->in.name = ""; 1266 #else 1267 temp->in.name[0] = '\0'; 1268 #endif 1269 old = q->in.left; 1270 q->in.left = temp; 1271 } 1272 /* fall thru ... */ 1273 1274 case REG: 1275 case NAME: 1276 case OREG: 1277 /* change ASG OP to a simple OP */ 1278 q = talloc(); 1279 q->in.op = NOASG p->in.op; 1280 q->in.rall = NOPREF; 1281 q->in.type = p->in.type; 1282 q->in.left = tcopy(p->in.left); 1283 q->in.right = p->in.right; 1284 p->in.op = ASSIGN; 1285 p->in.right = q; 1286 p = q; 1287 f -= 2; /* Note: this depends on the table order */ 1288 /* on the right side only - replace *temp with 1289 *(temp = &lval), build the assignment node */ 1290 if( old ){ 1291 temp = q->in.left->in.left; /* the "*" node */ 1292 q = talloc(); 1293 q->in.op = ASSIGN; 1294 q->in.left = temp->in.left; 1295 q->in.right = old; 1296 q->in.type = old->in.type; 1297 #ifdef FLEXNAMES 1298 q->in.name = ""; 1299 #else 1300 q->in.name[0] = '\0'; 1301 #endif 1302 temp->in.left = q; 1303 } 1304 break; 1305 1306 case UNARY MUL: 1307 /* avoid doing side effects twice */ 1308 q = p->in.left; 1309 p->in.left = q->in.left; 1310 q->in.op = FREE; 1311 break; 1312 1313 default: 1314 cerror( "hardops: can't compute & LHS" ); 1315 } 1316 } 1317 1318 /* build comma op for args to function */ 1319 q = talloc(); 1320 q->in.op = CM; 1321 q->in.rall = NOPREF; 1322 q->in.type = INT; 1323 q->in.left = p->in.left; 1324 q->in.right = p->in.right; 1325 p->in.op = CALL; 1326 p->in.right = q; 1327 1328 /* put function name in left node of call */ 1329 p->in.left = q = talloc(); 1330 q->in.op = ICON; 1331 q->in.rall = NOPREF; 1332 q->in.type = INCREF( FTN + p->in.type ); 1333 #ifndef FLEXNAMES 1334 strcpy( q->in.name, f->func ); 1335 #else 1336 q->in.name = f->func; 1337 #endif 1338 q->tn.lval = 0; 1339 q->tn.rval = 0; 1340 1341 } 1342 1343 zappost(p) NODE *p; { 1344 /* look for ++ and -- operators and remove them */ 1345 1346 register o, ty; 1347 register NODE *q; 1348 o = p->in.op; 1349 ty = optype( o ); 1350 1351 switch( o ){ 1352 1353 case INCR: 1354 case DECR: 1355 q = p->in.left; 1356 p->in.right->in.op = FREE; /* zap constant */ 1357 ncopy( p, q ); 1358 q->in.op = FREE; 1359 return; 1360 1361 } 1362 1363 if( ty == BITYPE ) zappost( p->in.right ); 1364 if( ty != LTYPE ) zappost( p->in.left ); 1365 } 1366 1367 fixpre(p) NODE *p; { 1368 1369 register o, ty; 1370 o = p->in.op; 1371 ty = optype( o ); 1372 1373 switch( o ){ 1374 1375 case ASG PLUS: 1376 p->in.op = PLUS; 1377 break; 1378 case ASG MINUS: 1379 p->in.op = MINUS; 1380 break; 1381 } 1382 1383 if( ty == BITYPE ) fixpre( p->in.right ); 1384 if( ty != LTYPE ) fixpre( p->in.left ); 1385 } 1386 1387 strip(p) register NODE *p; { 1388 NODE *q; 1389 1390 /* strip nodes off the top when no side effects occur */ 1391 for( ; ; ) { 1392 switch( p->in.op ) { 1393 case SCONV: /* remove lint tidbits */ 1394 q = p->in.left; 1395 ncopy( p, q ); 1396 q->in.op = FREE; 1397 break; 1398 /* could probably add a few more here */ 1399 default: 1400 return; 1401 } 1402 } 1403 } 1404 1405 myreader(p) register NODE *p; { 1406 strip( p ); /* strip off operations with no side effects */ 1407 canon( p ); /* expands r-vals for fields */ 1408 walkf( p, hardops ); /* convert ops to function calls */ 1409 walkf( p, optim2 ); 1410 /* jwf toff = 0; /* stack offset swindle */ 1411 } 1412