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