1: # include "pass2.h" 2: extern int fltused; 3: #define putstr(s) fputs((s),stdout) 4: 5: /* a lot of the machine dependent parts of the second pass */ 6: 7: # define BITMASK(n) ((1L<<n)-1) 8: where(c) { 9: fprintf(stderr, "%s, line %d: ", filename, lineno); 10: } 11: 12: lineid( l, fn ) char *fn; { 13: /* identify line l and file fn */ 14: printf( "/ line %d, file %s\n", l, fn ); 15: } 16: 17: eobl2(){ 18: OFFSZ spoff; /* offset from stack pointer */ 19: 20: spoff = maxoff; 21: if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 22: spoff /= SZCHAR; 23: SETOFF(spoff,2); 24: printf( " .F%d = %ld.\n", ftnno, spoff ); 25: if( fltused ) { 26: fltused = 0; 27: printf( " .globl fltused\n" ); 28: } 29: } 30: 31: struct hoptab { int opmask; char * opstring; } ioptab[]= { 32: 33: ASG PLUS, "add", 34: ASG MINUS, "sub", 35: ASG OR, "bis", 36: ASG AND, "bic", 37: ASG ER, "xor", 38: ASG MUL, "mul", 39: ASG DIV, "div", 40: ASG MOD, "div", 41: ASG LS, "asl", 42: ASG RS, "asr", 43: 44: -1, "" }; 45: 46: hopcode( f, o ){ 47: /* output the appropriate string from the above table */ 48: 49: register struct hoptab *q; 50: 51: for( q = ioptab; q->opmask>=0; ++q ){ 52: if( q->opmask == o ){ 53: printf( "%s", q->opstring ); 54: if( f == 'F' ) printf( "f" ); 55: return; 56: } 57: } 58: cerror( "no hoptab for %s", opst[o] ); 59: } 60: 61: char * 62: rnames[]= { /* keyed to register number tokens */ 63: 64: "r0", "r1", 65: "r2", "r3", "r4", 66: "r5", "sp", "pc", 67: 68: "fr0", "fr1", "fr2", "fr3", 69: "fr4", "fr5", /* not accumulators - used for temps */ 70: }; 71: 72: int rstatus[] = { 73: SAREG|STAREG, SAREG|STAREG, 74: SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, /* use as scratch if not reg var */ 75: SAREG, SAREG, SAREG, 76: 77: SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, SBREG|STBREG, 78: SBREG, SBREG, 79: }; 80: 81: tlen(p) NODE *p; 82: { 83: switch(p->in.type) { 84: case CHAR: 85: case UCHAR: 86: return(1); 87: 88: case LONG: 89: case ULONG: 90: case FLOAT: 91: return(4); 92: 93: case DOUBLE: 94: return(8); 95: 96: default: 97: return(2); 98: } 99: } 100: NODE *brnode; 101: int brcase; 102: 103: int toff = 0; /* number of stack locations used for args */ 104: 105: zzzcode( p, c ) NODE *p; { 106: register m; 107: switch( c ){ 108: 109: case 'B': /* output b if type is byte */ 110: if( p->in.type == CHAR || p->in.type == UCHAR ) printf( "b" ); 111: return; 112: 113: case 'N': /* logical ops, turned into 0-1 */ 114: /* use register given by register 1 */ 115: cbgen( 0, m=getlab(), 'I' ); 116: deflab( p->bn.label ); 117: printf( " clr %s\n", rnames[getlr( p, '1' )->tn.rval] ); 118: if( p->in.type == LONG || p->in.type == ULONG ) 119: printf( " clr %s\n", rnames[getlr(p, '1')->tn.rval + 1] ); 120: deflab( m ); 121: return; 122: 123: case 'I': 124: case 'F': 125: cbgen( p->in.op, p->bn.label, c ); 126: return; 127: 128: case 'A': 129: case 'C': 130: /* logical operators for longs 131: defer comparisons until branch occurs */ 132: 133: brnode = tcopy( p ); 134: brcase = c; 135: return; 136: 137: case 'H': /* fix up unsigned shifts */ 138: { register NODE *q; 139: register r, l; 140: TWORD t; 141: 142: if( p->in.op == ASG LS ) return; 143: if( p->in.op != ASG RS ) cerror( "ZH bad" ); 144: if( p->in.left->in.op != REG ) cerror( "SH left bad" ); 145: 146: r = p->in.left->tn.rval; 147: t = p->in.left->in.type; 148: l = (t==LONG || t == ULONG ); 149: 150: if( t != UNSIGNED && t != UCHAR && t != ULONG ) return; /* signed is ok */ 151: 152: /* there are three cases: right side is a constant, 153: and has the shift value; right side is 154: a temporary reg, and has the - shift value, 155: and right side is something else: A1 has the 156: - shift value then */ 157: 158: /* in the case where the value is known (rhs a constant), 159: the mask is just computed and put out... */ 160: 161: if( p->in.right->in.op == ICON ){ 162: int s; 163: s = p->in.right->tn.lval; 164: if( l ){ 165: if( s >= 16 ){ 166: printf( " clr r%d\n", r ); 167: s -= 16; 168: ++r; 169: } 170: } 171: if( s >= 16 ) printf( " clr r%d\n", r ); 172: else { 173: m = 0100000; 174: m >>= s; /* sign extends... */ 175: m <<= 1; 176: printf( " bic $%o,r%d\n", m, r ); 177: } 178: return; 179: } 180: 181: /* general case */ 182: 183: if( istnode( p->in.right ) ) q = p->in.right; 184: else q = getlr( p, '1' ); /* where -shift is stored */ 185: 186: /* first, we store the shifted value on the stack */ 187: printf( " mov r%d,-(sp)\n", r ); 188: if( l ) printf( " mov r%d,-(sp)\n", r+1 ); 189: 190: /* now, make a mask */ 191: 192: printf( " mov $100000,r%d\n", r ); 193: if( l ) printf( " clr r%d\n", r+1 ); 194: 195: /* shift (arithmetically ) */ 196: if( l ) expand( q, RNOP, " ashc AR" ); 197: else expand( q, RNOP, " ash AR" ); 198: printf( ",r%d\n", r ); 199: 200: if( l ) printf( " ashc $1,r%d\n", r ); 201: else printf( " asl r%d\n", r ); 202: 203: /* now, we have a mask: use it to clear sp, and reload */ 204: 205: if( l ){ 206: printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r+1, r+1 ); 207: } 208: printf( "\tbic\tr%d,(sp)\n\tmov\t(sp)+,r%d\n", r, r ); 209: /* whew! */ 210: return; 211: } 212: 213: case 'V': 214: /* sign extend or not -- register is one less than the 215: left descendent */ 216: 217: m = p->in.left->tn.rval - 1; 218: 219: if( ISUNSIGNED(p->in.type) ){ 220: printf( " clr r%d\n", m ); 221: } 222: else { 223: printf( " sxt r%d\n", m ); 224: } 225: return; 226: 227: /* stack management macros */ 228: case '-': 229: if( toff ++ ) printf( "-" ); 230: printf( "(sp)" ); 231: return; 232: 233: case '4': 234: if( toff == 0 ) ++toff; /* can't push doubles that way */ 235: printf( "-(sp)" ); 236: toff += 4; 237: return; 238: 239: case '~': 240: /* complimented CR */ 241: p->in.right->tn.lval = ~p->in.right->tn.lval; 242: conput( getlr( p, 'R' ) ); 243: p->in.right->tn.lval = ~p->in.right->tn.lval; 244: return; 245: 246: case 'M': 247: /* negated CR */ 248: p->in.right->tn.lval = -p->in.right->tn.lval; 249: conput( getlr( p, 'R' ) ); 250: p->in.right->tn.lval = -p->in.right->tn.lval; 251: return; 252: 253: case 'L': /* INIT for long constants */ 254: { 255: unsigned hi, lo; 256: lo = p->in.left->tn.lval & BITMASK(SZINT); 257: hi = ( p->in.left->tn.lval >> SZINT ) & BITMASK(SZINT); 258: printf( " %o; %o\n", hi, lo ); 259: return; 260: } 261: 262: case 'T': 263: /* Truncate longs for type conversions: 264: LONG|ULONG -> CHAR|UCHAR|INT|UNSIGNED 265: increment offset to second word */ 266: 267: m = p->in.type; 268: p = p->in.left; 269: switch( p->in.op ){ 270: case NAME: 271: case OREG: 272: p->tn.lval += SZINT/SZCHAR; 273: return; 274: case REG: 275: rfree( p->tn.rval, p->in.type ); 276: p->tn.rval += 1; 277: p->in.type = m; 278: rbusy( p->tn.rval, p->in.type ); 279: return; 280: default: 281: cerror( "Illegal ZT type conversion" ); 282: return; 283: 284: } 285: 286: case 'U': 287: /* same as AL for exp under U* */ 288: if( p->in.left->in.op == UNARY MUL ) { 289: adrput( getlr( p->in.left, 'L' ) ); 290: return; 291: } 292: cerror( "Illegal ZU" ); 293: /* NO RETURN */ 294: 295: case 'W': /* structure size */ 296: if( p->in.op == STASG ) 297: printf( "%d", p->stn.stsize); 298: else cerror( "Not a structure" ); 299: return; 300: 301: case 'S': /* structure assignment */ 302: { 303: register NODE *l, *r; 304: register size, count; 305: 306: if( p->in.op == STASG ){ 307: l = p->in.left; 308: r = p->in.right; 309: } 310: else if( p->in.op == STARG ){ /* store an arg onto the stack */ 311: r = p->in.left; 312: } 313: else cerror( "STASG bad" ); 314: 315: if( r->in.op == ICON ) r->in.op = NAME; 316: else if( r->in.op == REG ) r->in.op = OREG; 317: else if( r->in.op != OREG ) cerror( "STASG-r" ); 318: 319: size = p->stn.stsize; 320: count = size / 2; 321: 322: r->tn.lval += size; 323: if( p->in.op == STASG ) l->tn.lval += size; 324: 325: while( count-- ){ /* simple load/store loop */ 326: r->tn.lval -= 2; 327: expand( r, FOREFF, " mov AR," ); 328: if( p->in.op == STASG ){ 329: l->tn.lval -= 2; 330: expand( l, FOREFF, "AR\n" ); 331: } 332: else { 333: printf( "-(sp)\n" ); 334: } 335: 336: } 337: 338: if( r->in.op == NAME ) r->in.op = ICON; 339: else if( r->in.op == OREG ) r->in.op = REG; 340: 341: } 342: break; 343: 344: default: 345: cerror( "illegal zzzcode" ); 346: } 347: } 348: 349: rmove( rt, rs, t ) TWORD t; { 350: printf( " %s %s,%s\n", (t==FLOAT||t==DOUBLE)?"movf":"mov", rnames[rs], rnames[rt] ); 351: } 352: 353: struct respref 354: respref[] = { 355: INTAREG|INTBREG, INTAREG|INTBREG, 356: INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|SNAME|STARNM|SCON, 357: INTEMP, INTEMP, 358: FORARG, FORARG, 359: INTAREG, SOREG|SNAME, 360: 0, 0 }; 361: 362: setregs(){ /* set up temporary registers */ 363: register i; 364: 365: /* use any unused variable registers as scratch registers */ 366: fregs = maxtreg>=MINRVAR ? maxtreg + 1 : MINRVAR; 367: if( xdebug ){ 368: /* -x changes number of free regs to 2, -xx to 3, etc. */ 369: if( (xdebug+1) < fregs ) fregs = xdebug+1; 370: } 371: /* NOTE: for pdp11 fregs <= 4 for float regs */ 372: if( fregs > 4 ) fregs = 4; 373: for( i=MINRVAR; i<=MAXRVAR; i++ ) 374: rstatus[i] = i<fregs ? SAREG|STAREG : SAREG; 375: } 376: 377: szty(t) TWORD t; { /* size, in words, needed to hold thing of type t */ 378: /* really is the number of registers to hold type t */ 379: switch( t ) { 380: 381: case LONG: 382: case ULONG: 383: return( SZLONG/SZINT ); 384: 385: default: 386: return(1); 387: 388: } 389: } 390: 391: rewfld( p ) NODE *p; { 392: return(1); 393: } 394: 395: callreg(p) NODE *p; { 396: return( (p->in.type==DOUBLE||p->in.type==FLOAT) ? FR0 : R0 ); 397: } 398: 399: canaddr( p ) NODE *p; { 400: register int o = p->in.op; 401: 402: if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 403: return(0); 404: } 405: 406: flshape( p ) register NODE *p; { 407: register o = p->in.op; 408: if( o==NAME || o==REG || o==ICON || o==OREG ) return( 1 ); 409: return( o==UNARY MUL && shumul(p->in.left)==STARNM ); 410: } 411: 412: shtemp( p ) register NODE *p; { 413: if( p->in.op == UNARY MUL ) p = p->in.left; 414: if( p->in.op == REG || p->in.op == OREG ) return( !istreg( p->tn.rval ) ); 415: return( p->in.op == NAME || p->in.op == ICON ); 416: } 417: 418: spsz( t, v ) TWORD t; CONSZ v; { 419: 420: /* is v the size to increment something of type t */ 421: 422: if( !ISPTR(t) ) return( 0 ); 423: t = DECREF(t); 424: 425: if( ISPTR(t) ) return( v == 2 ); 426: 427: switch( t ){ 428: 429: case UCHAR: 430: case CHAR: 431: return( v == 1 ); 432: 433: case INT: 434: case UNSIGNED: 435: return( v == 2 ); 436: 437: case FLOAT: 438: return( v == 4 ); 439: 440: case DOUBLE: 441: return( v == 8 ); 442: } 443: 444: return( 0 ); 445: } 446: 447: shumul( p ) register NODE *p; { 448: register o; 449: 450: o = p->in.op; 451: if( o == NAME || o == OREG || o == ICON ) return( STARNM ); 452: 453: if( ( o == INCR || o == ASG MINUS ) && 454: ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 455: p->in.right->in.name[0] == '\0' && 456: spsz( p->in.left->in.type, p->in.right->tn.lval ) ) 457: return( STARREG ); 458: 459: return( 0 ); 460: } 461: 462: adrcon( val ) CONSZ val; { 463: printf( CONFMT, val ); 464: } 465: 466: conput( p ) register NODE *p; { 467: switch( p->in.op ){ 468: 469: case ICON: 470: acon( p ); 471: return; 472: 473: case REG: 474: putstr( rnames[p->tn.rval] ); 475: return; 476: 477: default: 478: cerror( "illegal conput" ); 479: } 480: } 481: 482: insput( p ) NODE *p; { 483: cerror( "insput" ); 484: } 485: 486: upput( p ) NODE *p; { 487: /* output the address of the second word in the 488: pair pointed to by p (for LONGs)*/ 489: CONSZ save; 490: 491: if( p->in.op == FLD ){ 492: p = p->in.left; 493: } 494: 495: save = p->tn.lval; 496: switch( p->in.op ){ 497: 498: case NAME: 499: p->tn.lval += SZINT/SZCHAR; 500: acon( p ); 501: break; 502: 503: case ICON: 504: /* addressable value of the constant */ 505: p->tn.lval &= BITMASK(SZINT); 506: putstr( "$" ); 507: acon( p ); 508: break; 509: 510: case REG: 511: putstr( rnames[p->tn.rval+1] ); 512: break; 513: 514: case OREG: 515: p->tn.lval += SZINT/SZCHAR; 516: if( p->tn.rval == R5 ){ /* in the argument region */ 517: if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 518: } 519: if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p ); 520: printf( "(%s)", rnames[p->tn.rval] ); 521: break; 522: 523: default: 524: cerror( "illegal upper address" ); 525: break; 526: 527: } 528: p->tn.lval = save; 529: 530: } 531: 532: adrput( p ) register NODE *p; { 533: /* output an address, with offsets, from p */ 534: 535: if( p->in.op == FLD ){ 536: p = p->in.left; 537: } 538: switch( p->in.op ){ 539: 540: case NAME: 541: acon( p ); 542: return; 543: 544: case ICON: 545: /* addressable value of the constant */ 546: if( szty( p->in.type ) == 2 ) { 547: /* print the high order value */ 548: CONSZ save; 549: save = p->tn.lval; 550: p->tn.lval = ( p->tn.lval >> SZINT ) & BITMASK(SZINT); 551: putstr( "$" ); 552: acon( p ); 553: p->tn.lval = save; 554: return; 555: } 556: printf( "$" ); 557: acon( p ); 558: return; 559: 560: case REG: 561: putstr( rnames[p->tn.rval] ); 562: return; 563: 564: case OREG: 565: if( p->tn.rval == R5 ){ /* in the argument region */ 566: if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 567: printf( CONFMT, p->tn.lval ); 568: putstr( ".(r5)" ); 569: return; 570: } 571: if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon( p ); 572: printf( "(%s)", rnames[p->tn.rval] ); 573: return; 574: 575: case UNARY MUL: 576: /* STARNM or STARREG found */ 577: if( tshape(p, STARNM) ) { 578: putstr( "*" ); 579: adrput( p->in.left); 580: } 581: else { /* STARREG - really auto inc or dec */ 582: /* turn into OREG so replacement node will 583: reflect the value of the expression */ 584: register i; 585: register NODE *q, *l; 586: 587: l = p->in.left; 588: q = l->in.left; 589: p->in.op = OREG; 590: p->in.rall = q->in.rall; 591: p->tn.lval = q->tn.lval; 592: p->tn.rval = q->tn.rval; 593: #ifndef FLEXNAMES 594: for(i=0; i<NCHNAM; ++i) 595: p->in.name[i] = q->in.name[i]; 596: #else 597: p->in.name = q->in.name; 598: #endif 599: if( l->in.op == INCR ) { 600: adrput( p ); 601: putstr( "+" ); 602: p->tn.lval -= l->in.right->tn.lval; 603: } 604: else { /* l->in.op == ASG MINUS */ 605: putstr( "-" ); 606: adrput( p ); 607: } 608: tfree( l ); 609: } 610: return; 611: 612: default: 613: cerror( "illegal address" ); 614: return; 615: 616: } 617: 618: } 619: 620: acon( p ) register NODE *p; { /* print out a constant */ 621: 622: if( p->in.name[0] == '\0' ){ /* constant only */ 623: printf( CONFMT, p->tn.lval); 624: printf( "." ); 625: } 626: else if( p->tn.lval == 0 ) { /* name only */ 627: #ifndef FLEXNAMES 628: printf( "%.8s", p->in.name ); 629: #else 630: putstr( p->in.name ); 631: #endif 632: } 633: else { /* name + offset */ 634: #ifndef FLEXNAMES 635: printf( "%.8s+", p->in.name ); 636: #else 637: putstr( p->in.name ); 638: #endif 639: printf( CONFMT, p->tn.lval ); 640: printf( "." ); 641: } 642: } 643: 644: genscall( p, cookie ) register NODE *p; { 645: /* structure valued call */ 646: return( gencall( p, cookie ) ); 647: } 648: 649: gencall( p, cookie ) register NODE *p; { 650: /* generate the call given by p */ 651: register temp; 652: register m; 653: 654: if( p->in.right ) temp = argsize( p->in.right ); 655: else temp = 0; 656: 657: if( p->in.right ){ /* generate args */ 658: genargs( p->in.right ); 659: } 660: 661: if( !shltype( p->in.left->in.op, p->in.left ) ) { 662: order( p->in.left, INAREG|SOREG ); 663: } 664: 665: p->in.op = UNARY CALL; 666: m = match( p, INTAREG|INTBREG ); 667: popargs( temp ); 668: return(m != MDONE); 669: } 670: 671: popargs( size ) register size; { 672: /* pop arguments from stack */ 673: 674: toff -= size/2; 675: if( toff == 0 && size >= 2 ) size -= 2; 676: switch( size ) { 677: case 0: 678: break; 679: case 2: 680: printf( " tst (sp)+\n" ); 681: break; 682: case 4: 683: printf( " cmp (sp)+,(sp)+\n" ); 684: break; 685: default: 686: printf( " add $%d.,sp\n", size); 687: } 688: } 689: 690: char * 691: ccbranches[] = { 692: " jeq L%d\n", 693: " jne L%d\n", 694: " jle L%d\n", 695: " jlt L%d\n", 696: " jge L%d\n", 697: " jgt L%d\n", 698: " jlos L%d\n", 699: " jlo L%d\n", 700: " jhis L%d\n", 701: " jhi L%d\n", 702: }; 703: 704: /* long branch table 705: 706: This table, when indexed by a logical operator, 707: selects a set of three logical conditions required 708: to generate long comparisons and branches. A zero 709: entry indicates that no branch is required. 710: E.G.: The <= operator would generate: 711: cmp AL,AR 712: jlt lable / 1st entry LT -> lable 713: jgt 1f / 2nd entry GT -> 1f 714: cmp UL,UR 715: jlos lable / 3rd entry ULE -> lable 716: 1: 717: */ 718: 719: int lbranches[][3] = { 720: /*EQ*/ 0, NE, EQ, 721: /*NE*/ NE, 0, NE, 722: /*LE*/ LT, GT, ULE, 723: /*LT*/ LT, GT, ULT, 724: /*GE*/ GT, LT, UGE, 725: /*GT*/ GT, LT, UGT, 726: /*ULE*/ ULT, UGT, ULE, 727: /*ULT*/ ULT, UGT, ULT, 728: /*UGE*/ UGT, ULT, UGE, 729: /*UGT*/ UGT, ULT, UGT, 730: }; 731: 732: /* logical relations when compared in reverse order (cmp R,L) */ 733: #ifndef ONEPASS 734: short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; 735: #else 736: extern short revrel[]; 737: #endif 738: 739: cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 740: register *plb; 741: int lab1f; 742: 743: if( o == 0 ) printf( " jbr L%d\n", lab ); 744: else if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 745: else { 746: switch( brcase ) { 747: 748: case 'A': 749: case 'C': 750: plb = lbranches[ o-EQ ]; 751: lab1f = getlab(); 752: expand( brnode, FORCC, brcase=='C' ? "\tcmp\tAL,AR\n" : "\ttst\tAR\n" ); 753: if( *plb != 0 ) 754: printf( ccbranches[*plb-EQ], lab); 755: if( *++plb != 0 ) 756: printf( ccbranches[*plb-EQ], lab1f); 757: expand( brnode, FORCC, brcase=='C' ? "\tcmp\tUL,UR\n" : "\ttst\tUR\n" ); 758: printf( ccbranches[*++plb-EQ], lab); 759: deflab( lab1f ); 760: reclaim( brnode, RNULL, 0 ); 761: break; 762: 763: default: 764: if( mode=='F' ) o = revrel[ o-EQ ]; 765: printf( ccbranches[o-EQ], lab ); 766: break; 767: } 768: 769: brcase = 0; 770: brnode = 0; 771: } 772: } 773: 774: nextcook( p, cookie ) NODE *p; { 775: /* we have failed to match p with cookie; try another */ 776: if( cookie == FORREW ) return( 0 ); /* hopeless! */ 777: if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 778: if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 779: return( FORREW ); 780: } 781: 782: lastchance( p, cook ) NODE *p; { 783: /* forget it! */ 784: return(0); 785: } 786: 787: struct functbl { 788: int fop; 789: TWORD ftype; 790: char *func; 791: } opfunc[] = { 792: MUL, LONG, "lmul", 793: DIV, LONG, "ldiv", 794: MOD, LONG, "lrem", 795: ASG MUL, LONG, "almul", 796: ASG DIV, LONG, "aldiv", 797: ASG MOD, LONG, "alrem", 798: MUL, ULONG, "lmul", 799: DIV, ULONG, "uldiv", 800: MOD, ULONG, "ulrem", 801: ASG MUL, ULONG, "almul", 802: ASG DIV, ULONG, "auldiv", 803: ASG MOD, ULONG, "aulrem", 804: 0, 0, 0 }; 805: 806: hardops(p) register NODE *p; { 807: /* change hard to do operators into function calls. 808: for pdp11 do long * / % */ 809: register NODE *q; 810: register struct functbl *f; 811: register o; 812: register TWORD t; 813: 814: o = p->in.op; 815: t = p->in.type; 816: if( t!=LONG && t!=ULONG ) return; 817: 818: for( f=opfunc; f->fop; f++ ) { 819: if( o==f->fop && t==f->ftype ) goto convert; 820: } 821: return; 822: 823: /* need address of left node for ASG OP */ 824: /* WARNING - this won't work for long in a REG */ 825: convert: 826: if( asgop( o ) ) { 827: switch( p->in.left->in.op ) { 828: 829: case UNARY MUL: /* convert to address */ 830: p->in.left->in.op = FREE; 831: p->in.left = p->in.left->in.left; 832: break; 833: 834: case NAME: /* convert to ICON pointer */ 835: p->in.left->in.op = ICON; 836: p->in.left->in.type = INCREF( p->in.left->in.type ); 837: break; 838: 839: case OREG: /* convert OREG to address */ 840: p->in.left->in.op = REG; 841: p->in.left->in.type = INCREF( p->in.left->in.type ); 842: if( p->in.left->tn.lval != 0 ) { 843: q = talloc(); 844: q->in.op = PLUS; 845: q->in.rall = NOPREF; 846: q->in.type = p->in.left->in.type; 847: q->in.left = p->in.left; 848: q->in.right = talloc(); 849: 850: q->in.right->in.op = ICON; 851: q->in.right->in.rall = NOPREF; 852: q->in.right->in.type = INT; 853: #ifdef FLEXNAMES 854: q->in.right->in.name = ""; 855: #else 856: q->in.right->in.name[0] = '\0'; 857: #endif 858: q->in.right->tn.lval = p->in.left->tn.lval; 859: q->in.right->tn.rval = 0; 860: 861: p->in.left->tn.lval = 0; 862: p->in.left = q; 863: } 864: break; 865: 866: default: 867: cerror( "Bad address for hard ops" ); 868: /* NO RETURN */ 869: 870: } 871: } 872: 873: /* build comma op for args to function */ 874: q = talloc(); 875: q->in.op = CM; 876: q->in.rall = NOPREF; 877: q->in.type = INT; 878: q->in.left = p->in.left; 879: q->in.right = p->in.right; 880: p->in.op = CALL; 881: p->in.right = q; 882: 883: /* put function name in left node of call */ 884: p->in.left = q = talloc(); 885: q->in.op = ICON; 886: q->in.rall = NOPREF; 887: q->in.type = INCREF( FTN + p->in.type ); 888: #ifndef FLEXNAMES 889: strcpy( q->in.name, f->func ); 890: #else 891: q->in.name = f->func; 892: #endif 893: q->tn.lval = 0; 894: q->tn.rval = 0; 895: 896: return; 897: 898: } 899: 900: optim2( p ) register NODE *p; { 901: /* do local tree transformations and optimizations */ 902: 903: register NODE *r; 904: 905: switch( p->in.op ) { 906: 907: case AND: 908: /* commute L and R to eliminate compliments and constants */ 909: if( p->in.left->in.op==ICON || p->in.left->in.op==COMPL ) { 910: r = p->in.left; 911: p->in.left = p->in.right; 912: p->in.right = r; 913: } 914: case ASG AND: 915: /* change meaning of AND to ~R&L - bic on pdp11 */ 916: r = p->in.right; 917: if( r->in.op==ICON ) { /* compliment constant */ 918: r->tn.lval = ~r->tn.lval; 919: } 920: else if( r->in.op==COMPL ) { /* ~~A => A */ 921: r->in.op = FREE; 922: p->in.right = r->in.left; 923: } 924: else { /* insert complement node */ 925: p->in.right = talloc(); 926: p->in.right->in.op = COMPL; 927: p->in.right->in.rall = NOPREF; 928: p->in.right->in.type = r->in.type; 929: p->in.right->in.left = r; 930: p->in.right->in.right = NULL; 931: } 932: break; 933: 934: } 935: } 936: 937: special( p, shape ) register NODE *p; { 938: /* special shape matching routine */ 939: 940: switch( shape ) { 941: 942: case SSCON: 943: if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= -128 && p->tn.lval <=127 ) return( 1 ); 944: break; 945: 946: case SCCON: 947: if( p->in.op == ICON && p->in.name[0]=='\0' && p->tn.lval>= 0 && p->tn.lval <=32767 ) return( 1 ); 948: break; 949: 950: default: 951: cerror( "bad special shape" ); 952: 953: } 954: 955: return( 0 ); 956: } 957: 958: NODE * addroreg(l) NODE *l; 959: /* OREG was built in clocal() 960: * for an auto or formal parameter 961: * now its address is being taken 962: * local code must unwind it 963: * back to PLUS/MINUS REG ICON 964: * according to local conventions 965: */ 966: { 967: cerror("address of OREG taken"); 968: /*NOTREACHED*/ 969: } 970: 971: # ifndef ONEPASS 972: main( argc, argv ) char *argv[]; { 973: return( mainp2( argc, argv ) ); 974: } 975: # endif 976: 977: myreader(p) register NODE *p; { 978: walkf( p, hardops ); /* convert ops to function calls */ 979: canon( p ); /* expands r-vals for fileds */ 980: walkf( p, optim2 ); 981: toff = 0; /* stack offset swindle */ 982: }