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