1: # ifndef lint 2: static char *sccsid ="@(#)local2.c 1.14 (Berkeley) 4/23/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 ) register NODE *p; { 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: }