1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.17 (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 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 /*ARGSUSED*/ 833 insput( p ) register NODE *p; { 834 cerror( "insput" ); 835 } 836 837 /*ARGSUSED*/ 838 upput( p, off ) register NODE *p; int off; { 839 cerror( "upput" ); 840 } 841 842 adrput( p ) register NODE *p; { 843 register int r; 844 /* output an address, with offsets, from p */ 845 846 if( p->in.op == FLD ){ 847 p = p->in.left; 848 } 849 switch( p->in.op ){ 850 851 case NAME: 852 acon( p ); 853 return; 854 855 case ICON: 856 /* addressable value of the constant */ 857 putchar( '$' ); 858 acon( p ); 859 return; 860 861 case REG: 862 putstr( rnames[p->tn.rval] ); 863 return; 864 865 case OREG: 866 r = p->tn.rval; 867 if( R2TEST(r) ){ /* double indexing */ 868 register int flags; 869 870 flags = R2UPK3(r); 871 if( flags & 1 ) putchar('*'); 872 if( flags & 4 ) putchar('-'); 873 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 874 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 875 if( flags & 2 ) putchar('+'); 876 printf( "[%s]", rnames[R2UPK2(r)] ); 877 return; 878 } 879 if( r == AP ){ /* in the argument region */ 880 if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" ); 881 printf( CONFMT, p->tn.lval ); 882 putstr( "(ap)" ); 883 return; 884 } 885 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 886 printf( "(%s)", rnames[p->tn.rval] ); 887 return; 888 889 case UNARY MUL: 890 /* STARNM or STARREG found */ 891 if( tshape(p, STARNM) ) { 892 putchar( '*' ); 893 adrput( p->in.left); 894 } 895 else { /* STARREG - really auto inc or dec */ 896 register NODE *q; 897 898 /* tbl 899 p = p->in.left; 900 p->in.left->in.op = OREG; 901 if( p->in.op == INCR ) { 902 adrput( p->in.left ); 903 putchar( '+' ); 904 } 905 else { 906 putchar( '-' ); 907 adrput( p->in.left ); 908 } 909 tbl */ 910 q = p->in.left; 911 if( q->in.right->tn.lval != tlen(p) ) 912 cerror("adrput: bad auto-increment/decrement"); 913 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 914 rnames[q->in.left->tn.rval], 915 (q->in.op==INCR ? "+" : "") ); 916 p->in.op = OREG; 917 p->tn.rval = q->in.left->tn.rval; 918 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 919 #ifndef FLEXNAMES 920 p->in.name[0] = '\0'; 921 #else 922 p->in.name = ""; 923 #endif 924 tfree(q); 925 } 926 return; 927 928 default: 929 cerror( "illegal address" ); 930 return; 931 932 } 933 934 } 935 936 acon( p ) register NODE *p; { /* print out a constant */ 937 938 if( p->in.name[0] == '\0' ){ 939 printf( CONFMT, p->tn.lval); 940 } 941 else if( p->tn.lval == 0 ) { 942 #ifndef FLEXNAMES 943 printf( "%.8s", p->in.name ); 944 #else 945 putstr( p->in.name ); 946 #endif 947 } 948 else { 949 #ifndef FLEXNAMES 950 printf( "%.8s+", p->in.name ); 951 #else 952 printf( "%s+", p->in.name ); 953 #endif 954 printf( CONFMT, p->tn.lval ); 955 } 956 } 957 958 /* 959 aacon( p ) register NODE *p; { /* print out a constant */ 960 /* 961 962 if( p->in.name[0] == '\0' ){ 963 printf( CONFMT, p->tn.lval); 964 return( 0 ); 965 } 966 else if( p->tn.lval == 0 ) { 967 #ifndef FLEXNAMES 968 printf( "$%.8s", p->in.name ); 969 #else 970 printf( "$%s", p->in.name ); 971 #endif 972 return( 1 ); 973 } 974 else { 975 printf( "$(" ); 976 printf( CONFMT, p->tn.lval ); 977 printf( "+" ); 978 #ifndef FLEXNAMES 979 printf( "%.8s)", p->in.name ); 980 #else 981 printf( "%s)", p->in.name ); 982 #endif 983 return(1); 984 } 985 } 986 */ 987 988 genscall( p, cookie ) register NODE *p; { 989 /* structure valued call */ 990 return( gencall( p, cookie ) ); 991 } 992 993 /* tbl */ 994 int gc_numbytes; 995 /* tbl */ 996 997 gencall( p, cookie ) register NODE *p; { 998 /* generate the call given by p */ 999 register NODE *p1; 1000 register temp, temp1; 1001 register m; 1002 1003 if( p->in.right ) temp = argsize( p->in.right ); 1004 else temp = 0; 1005 1006 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1007 /* set aside room for structure return */ 1008 1009 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1010 else temp1 = temp; 1011 } 1012 1013 if( temp > maxargs ) maxargs = temp; 1014 SETOFF(temp1,4); 1015 1016 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1017 genargs( p->in.right ); 1018 } 1019 1020 p1 = p->in.left; 1021 if( p1->in.op != ICON ){ 1022 if( p1->in.op != REG ){ 1023 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1024 if( p1->in.op != NAME ){ 1025 order( p1, INAREG ); 1026 } 1027 } 1028 } 1029 } 1030 1031 /* 1032 if( p1->in.op == REG && p->tn.rval == R5 ){ 1033 cerror( "call register overwrite" ); 1034 } 1035 */ 1036 /* tbl 1037 setup gc_numbytes so reference to ZC works */ 1038 1039 gc_numbytes = temp&(0x3ff); 1040 /* tbl */ 1041 1042 p->in.op = UNARY CALL; 1043 m = match( p, INTAREG|INTBREG ); 1044 1045 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1046 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1047 if (temp >= 1024) 1048 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1049 1050 /* tbl 1051 switch( temp ) { 1052 case 0: 1053 break; 1054 case 2: 1055 printf( " tst (sp)+\n" ); 1056 break; 1057 case 4: 1058 printf( " cmp (sp)+,(sp)+\n" ); 1059 break; 1060 default: 1061 printf( " add $%d,sp\n", temp); 1062 } 1063 tbl */ 1064 return(m != MDONE); 1065 } 1066 1067 /* tbl */ 1068 char * 1069 ccbranches[] = { 1070 " jeql L%d\n", 1071 " jneq L%d\n", 1072 " jleq L%d\n", 1073 " jlss L%d\n", 1074 " jgeq L%d\n", 1075 " jgtr L%d\n", 1076 " jlequ L%d\n", 1077 " jlssu L%d\n", 1078 " jgequ L%d\n", 1079 " jgtru L%d\n", 1080 }; 1081 /* tbl */ 1082 1083 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1084 1085 /* tbl */ 1086 if( o == 0 ) printf( " jbr L%d\n", lab ); 1087 /* tbl */ 1088 else { 1089 if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 1090 printf( ccbranches[o-EQ], lab ); 1091 } 1092 } 1093 1094 nextcook( p, cookie ) NODE *p; { 1095 /* we have failed to match p with cookie; try another */ 1096 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1097 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1098 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1099 return( FORREW ); 1100 } 1101 1102 lastchance( p, cook ) NODE *p; { 1103 /* forget it! */ 1104 return(0); 1105 } 1106 1107 optim2( p ) register NODE *p; { 1108 /* do local tree transformations and optimizations */ 1109 1110 register NODE *l, *r; 1111 int m, ml; 1112 1113 switch( p->in.op ) { 1114 1115 case AND: 1116 /* commute L and R to eliminate complements and constants */ 1117 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1118 l->in.op == COMPL ) { 1119 p->in.left = p->in.right; 1120 p->in.right = l; 1121 } 1122 case ASG AND: 1123 /* change meaning of AND to ~R&L - bic on pdp11 */ 1124 r = p->in.right; 1125 if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 1126 r->tn.lval = ~r->tn.lval; 1127 } 1128 else if( r->in.op==COMPL ) { /* ~~A => A */ 1129 r->in.op = FREE; 1130 p->in.right = r->in.left; 1131 } 1132 else { /* insert complement node */ 1133 p->in.right = l = talloc(); 1134 l->in.op = COMPL; 1135 l->in.rall = NOPREF; 1136 l->in.type = r->in.type; 1137 l->in.left = r; 1138 l->in.right = NULL; 1139 } 1140 break; 1141 1142 case SCONV: 1143 l = p->in.left; 1144 #if defined(FORT) || defined(SPRECC) 1145 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1146 l->in.type == FLOAT || l->in.type == DOUBLE ) 1147 return; 1148 #else 1149 if( mixtypes(p, l) ) return; 1150 #endif 1151 if( l->in.op == PCONV ) 1152 return; 1153 1154 /* Only trust it to get it right if the size is the same */ 1155 if( tlen(p) != tlen(l) ) 1156 return; 1157 1158 /* clobber conversion */ 1159 if( l->in.op != FLD ) 1160 l->in.type = p->in.type; 1161 ncopy( p, l ); 1162 l->in.op = FREE; 1163 1164 break; 1165 1166 case ASSIGN: 1167 /* 1168 * Conversions are equivalent to assignments; 1169 * when the two operations are combined, 1170 * we can sometimes zap the conversion. 1171 */ 1172 r = p->in.right; 1173 l = p->in.left; 1174 if ( r->in.op == SCONV && 1175 !mixtypes(l, r) && 1176 l->in.op != FLD && 1177 tlen(l) == tlen(r) ) { 1178 p->in.right = r->in.left; 1179 r->in.op = FREE; 1180 } 1181 break; 1182 1183 } 1184 } 1185 1186 NODE * addroreg(l) NODE *l; 1187 /* OREG was built in clocal() 1188 * for an auto or formal parameter 1189 * now its address is being taken 1190 * local code must unwind it 1191 * back to PLUS/MINUS REG ICON 1192 * according to local conventions 1193 */ 1194 { 1195 cerror("address of OREG taken"); 1196 /*NOTREACHED*/ 1197 } 1198 1199 1200 1201 # ifndef ONEPASS 1202 main( argc, argv ) char *argv[]; { 1203 return( mainp2( argc, argv ) ); 1204 } 1205 # endif 1206 1207 1208 /* added by jwf */ 1209 struct functbl { 1210 int fop; 1211 TWORD ftype; 1212 char *func; 1213 } opfunc[] = { 1214 DIV, TANY, "udiv", 1215 MOD, TANY, "urem", 1216 ASG DIV, TANY, "audiv", 1217 ASG MOD, TANY, "aurem", 1218 0, 0, 0 }; 1219 1220 hardops(p) register NODE *p; { 1221 /* change hard to do operators into function calls. */ 1222 register NODE *q; 1223 register struct functbl *f; 1224 register o; 1225 NODE *old,*temp; 1226 1227 o = p->in.op; 1228 if( ! (optype(o)==BITYPE && 1229 (ISUNSIGNED(p->in.left->in.type) || 1230 ISUNSIGNED(p->in.right->in.type))) ) 1231 return; 1232 1233 for( f=opfunc; f->fop; f++ ) { 1234 if( o==f->fop ) goto convert; 1235 } 1236 return; 1237 1238 convert: 1239 if( asgop( o ) ) { 1240 old = NIL; 1241 switch( p->in.left->in.op ){ 1242 case FLD: 1243 q = p->in.left->in.left; 1244 /* 1245 * rewrite (lval.fld /= rval); as 1246 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1247 * else the compiler will evaluate lval twice. 1248 */ 1249 if( q->in.op == UNARY MUL ){ 1250 /* first allocate a temp storage */ 1251 temp = talloc(); 1252 temp->in.op = OREG; 1253 temp->tn.rval = TMPREG; 1254 temp->tn.lval = BITOOR(freetemp(1)); 1255 temp->in.type = INCREF(p->in.type); 1256 #ifdef FLEXNAMES 1257 temp->in.name = ""; 1258 #else 1259 temp->in.name[0] = '\0'; 1260 #endif 1261 old = q->in.left; 1262 q->in.left = temp; 1263 } 1264 /* fall thru ... */ 1265 1266 case REG: 1267 case NAME: 1268 case OREG: 1269 /* change ASG OP to a simple OP */ 1270 q = talloc(); 1271 q->in.op = NOASG p->in.op; 1272 q->in.rall = NOPREF; 1273 q->in.type = p->in.type; 1274 q->in.left = tcopy(p->in.left); 1275 q->in.right = p->in.right; 1276 p->in.op = ASSIGN; 1277 p->in.right = q; 1278 p = q; 1279 f -= 2; /* Note: this depends on the table order */ 1280 /* on the right side only - replace *temp with 1281 *(temp = &lval), build the assignment node */ 1282 if( old ){ 1283 temp = q->in.left->in.left; /* the "*" node */ 1284 q = talloc(); 1285 q->in.op = ASSIGN; 1286 q->in.left = temp->in.left; 1287 q->in.right = old; 1288 q->in.type = old->in.type; 1289 #ifdef FLEXNAMES 1290 q->in.name = ""; 1291 #else 1292 q->in.name[0] = '\0'; 1293 #endif 1294 temp->in.left = q; 1295 } 1296 break; 1297 1298 case UNARY MUL: 1299 /* avoid doing side effects twice */ 1300 q = p->in.left; 1301 p->in.left = q->in.left; 1302 q->in.op = FREE; 1303 break; 1304 1305 default: 1306 cerror( "hardops: can't compute & LHS" ); 1307 } 1308 } 1309 1310 /* build comma op for args to function */ 1311 q = talloc(); 1312 q->in.op = CM; 1313 q->in.rall = NOPREF; 1314 q->in.type = INT; 1315 q->in.left = p->in.left; 1316 q->in.right = p->in.right; 1317 p->in.op = CALL; 1318 p->in.right = q; 1319 1320 /* put function name in left node of call */ 1321 p->in.left = q = talloc(); 1322 q->in.op = ICON; 1323 q->in.rall = NOPREF; 1324 q->in.type = INCREF( FTN + p->in.type ); 1325 #ifndef FLEXNAMES 1326 strcpy( q->in.name, f->func ); 1327 #else 1328 q->in.name = f->func; 1329 #endif 1330 q->tn.lval = 0; 1331 q->tn.rval = 0; 1332 1333 } 1334 1335 zappost(p) NODE *p; { 1336 /* look for ++ and -- operators and remove them */ 1337 1338 register o, ty; 1339 register NODE *q; 1340 o = p->in.op; 1341 ty = optype( o ); 1342 1343 switch( o ){ 1344 1345 case INCR: 1346 case DECR: 1347 q = p->in.left; 1348 p->in.right->in.op = FREE; /* zap constant */ 1349 ncopy( p, q ); 1350 q->in.op = FREE; 1351 return; 1352 1353 } 1354 1355 if( ty == BITYPE ) zappost( p->in.right ); 1356 if( ty != LTYPE ) zappost( p->in.left ); 1357 } 1358 1359 fixpre(p) NODE *p; { 1360 1361 register o, ty; 1362 o = p->in.op; 1363 ty = optype( o ); 1364 1365 switch( o ){ 1366 1367 case ASG PLUS: 1368 p->in.op = PLUS; 1369 break; 1370 case ASG MINUS: 1371 p->in.op = MINUS; 1372 break; 1373 } 1374 1375 if( ty == BITYPE ) fixpre( p->in.right ); 1376 if( ty != LTYPE ) fixpre( p->in.left ); 1377 } 1378 1379 strip(p) register NODE *p; { 1380 NODE *q; 1381 1382 /* strip nodes off the top when no side effects occur */ 1383 for( ; ; ) { 1384 switch( p->in.op ) { 1385 case SCONV: /* remove lint tidbits */ 1386 q = p->in.left; 1387 ncopy( p, q ); 1388 q->in.op = FREE; 1389 break; 1390 /* could probably add a few more here */ 1391 default: 1392 return; 1393 } 1394 } 1395 } 1396 1397 myreader(p) register NODE *p; { 1398 strip( p ); /* strip off operations with no side effects */ 1399 canon( p ); /* expands r-vals for fields */ 1400 walkf( p, hardops ); /* convert ops to function calls */ 1401 walkf( p, optim2 ); 1402 /* jwf toff = 0; /* stack offset swindle */ 1403 } 1404