|
|
1.1 ! root 1: #include "cpass2.h" ! 2: #include "ctype.h" ! 3: #ifndef lint ! 4: static char sccsid[] = "@(#)local2.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 5: #endif ! 6: ! 7: /* ! 8: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 9: */ ! 10: ! 11: # ifdef FORT ! 12: int ftlab1, ftlab2; ! 13: # endif ! 14: /* a lot of the machine dependent parts of the second pass */ ! 15: #ifdef FORT ! 16: # define fltfun 0 ! 17: #else ! 18: extern int fltfun; ! 19: #endif ! 20: # define BITMASK(n) ((1L<<(n))-1) ! 21: ! 22: ! 23: int toff = 0; /* number of stack locations used for args */ ! 24: int maxtoff; ! 25: void stmove(); ! 26: void eval_field(); ! 27: void shiftreg(); ! 28: void incraddr(); ! 29: ! 30: /* everything you never wanted to know about condition codes */ ! 31: ! 32: char * ! 33: ccodes[] = { "eq", "ne", "le", "lt", "ge", "gt", "ls", "cs", "cc", "hi" }; ! 34: ! 35: char * ! 36: fccodes[] = { "eq", "neq", "le", "lt", "ge", "gt" }; ! 37: ! 38: char * ! 39: fnegccodes[] = { "neq", "eq", "nle", "nlt", "nge", "ngt" }; ! 40: ! 41: /* logical relations when compared in reverse order (cmp R,L) */ ! 42: ! 43: #ifdef FORT ! 44: short revrel[] = { EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; ! 45: #else ! 46: extern short revrel[]; ! 47: #endif ! 48: ! 49: /* negated logical relations -- integer comparisons only */ ! 50: ! 51: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; ! 52: ! 53: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ ! 54: ! 55: zzzcode( p, c, cookie ) NODE *p; ! 56: { ! 57: ! 58: register m,temp; ! 59: NODE *s; ! 60: ! 61: switch( c ){ ! 62: /* BCDEFGHIJKLMNOPRSTVWXabcdfglmrtv` '0-~ */ ! 63: ! 64: case 'C': ! 65: switch (p->in.left->in.op) { ! 66: ! 67: case ICON: print_str("\tjbsr\t"); ! 68: acon(p->in.left); ! 69: return; ! 70: ! 71: case REG: ! 72: if (indexreg(p->in.left)){ ! 73: /* already in an address register */ ! 74: print_str("\tjsr\t"); ! 75: adrput(p->in.left); ! 76: putchar('@'); ! 77: return; ! 78: } /* else fall through */ ! 79: ! 80: case NAME: ! 81: case OREG: print_str("\tmovl\t"); ! 82: adrput(p->in.left); ! 83: print_str(",a0\n\tjsr\ta0@"); ! 84: return; ! 85: ! 86: default: cerror("bad subroutine name"); ! 87: } ! 88: ! 89: case 'E': /* load doubles with overly complex addressing */ ! 90: { ! 91: /* ! 92: * accomplished by simplifying addressing, then ! 93: * falling through to case 'D'. ! 94: */ ! 95: expand(p, cookie, " lea AR,A2\n"); ! 96: /* ! 97: * we would like, at this point, just to paint over ! 98: * p with the place where we have the address calculated ! 99: * and be done with it. too bad we can't: reclaim ! 100: * needs to look at it. So we must RECUR here ! 101: */ ! 102: resc[1].tn.op = OREG; ! 103: resc[1].tn.lval = 0; ! 104: resc[1].tn.type = INCREF(DOUBLE); ! 105: zzzcode( &resc[1], 'D', cookie ); ! 106: return; ! 107: } ! 108: ! 109: ! 110: case 'D': /* load-store doubles with auto-incr/decr addressing */ ! 111: { ! 112: /* cases are: ASSIGN, or rewrite LEAF-node */ ! 113: # define FORW 0 ! 114: # define REVR 1 ! 115: static char * lrewrite[] = { "\tmovl\tA.,A1\n\tmovl\tU.,U1\n", ! 116: "\tmovl\tU.,U1\n\tmovl\tA.,A1\n"}; ! 117: static char * asreg[] = { "\tmovl\tAR,AL\n\tmovl\tUR,UL\n", ! 118: "\tmovl\tUR,UL\n\tmovl\tAR,AL\n"}; ! 119: char **rstring; ! 120: NODE * q; ! 121: if (p->in.op == ASSIGN){ ! 122: rstring = asreg; q = p->in.left; ! 123: } else { ! 124: rstring = lrewrite; q = p; ! 125: } ! 126: if (q->in.op == UNARY MUL && q->in.left->in.op == ASG MINUS) ! 127: expand( p, cookie, rstring[REVR] ); ! 128: else ! 129: expand( p, cookie, rstring[FORW] ); ! 130: # undef FORW ! 131: # undef REVR ! 132: } ! 133: return; ! 134: ! 135: case 'K': ! 136: /* ! 137: * 68881 floating point source operand ! 138: * This is essentially the same as AR, but ! 139: * in addition we check for the opportunity ! 140: * to use floating-point immediate mode. ! 141: * Only supported by the assembler in ! 142: * coprocessor instructions. ! 143: */ ! 144: switch(optype(p->in.op)) { ! 145: case LTYPE: ! 146: break; ! 147: case UTYPE: ! 148: if (p->in.op != UNARY MUL) ! 149: p = p->in.left; ! 150: break; ! 151: case BITYPE: ! 152: p = p->in.right; ! 153: break; ! 154: } ! 155: if (p->in.op == FCON) { ! 156: floatimmed(p); ! 157: } else { ! 158: adrput(p); ! 159: } ! 160: return; ! 161: ! 162: case 'L': ! 163: m = p->in.left->in.type; ! 164: goto suffix; ! 165: ! 166: case 'R': ! 167: m = p->in.right->in.type; ! 168: goto suffix; ! 169: ! 170: case 'B': ! 171: m = p->in.type; /* fall into suffix: */ ! 172: ! 173: suffix: ! 174: switch(m) { ! 175: case CHAR: ! 176: case UCHAR: ! 177: c = 'b'; ! 178: break; ! 179: case SHORT: ! 180: case USHORT: ! 181: c = 'w'; ! 182: break; ! 183: default: ! 184: c = 'l'; ! 185: break; ! 186: } ! 187: putchar(c); ! 188: return; ! 189: ! 190: case 'F': ! 191: /* ! 192: * print type characters for the source operand of ! 193: * a 68881 floating point instruction. ! 194: */ ! 195: switch(optype(p->in.op)) { ! 196: case LTYPE: ! 197: break; ! 198: case UTYPE: ! 199: if (p->in.op != UNARY MUL) ! 200: p = p->in.left; ! 201: break; ! 202: case BITYPE: ! 203: p = p->in.right; ! 204: break; ! 205: } ! 206: /* ! 207: * at this point, p is assumed to have matched ! 208: * the shape SFLOAT_SRCE (cf. special()) ! 209: */ ! 210: if (p->in.op == SCONV) ! 211: p = p->in.left; ! 212: goto float_suffix; ! 213: ! 214: case 'G': ! 215: /* ! 216: * print type character for the left subtree ! 217: */ ! 218: p = p->in.left; ! 219: if (p->in.op == SCONV) ! 220: p = p->in.left; ! 221: goto float_suffix; ! 222: ! 223: case '.': ! 224: float_suffix: ! 225: if (p->in.op == REG && iscreg(p->tn.rval)) { ! 226: /* ! 227: * source is coprocessor reg; data ! 228: * is in extended precision ! 229: */ ! 230: putchar('x'); ! 231: return; ! 232: } ! 233: /* ! 234: * print type character for the root node ! 235: */ ! 236: switch(BTYPE(p->in.type)) { ! 237: case CHAR: ! 238: c = 'b'; ! 239: break; ! 240: case SHORT: ! 241: c = 'w'; ! 242: break; ! 243: case FLOAT: ! 244: c = 's'; ! 245: break; ! 246: case DOUBLE: ! 247: c = 'd'; ! 248: break; ! 249: case UCHAR: ! 250: case USHORT: ! 251: /* ! 252: * the 68881 sign-extends integer operands ! 253: */ ! 254: cerror("compiler botched unsigned operand"); ! 255: /*NOTREACHED*/ ! 256: default: ! 257: c = 'l'; ! 258: break; ! 259: } ! 260: putchar(c); ! 261: return; ! 262: ! 263: case 'N': /* logical ops, turned into 0-1 */ ! 264: /* use register given by RESC1 */ ! 265: branch(m=getlab()); ! 266: /* FALL THROUGH */ ! 267: ! 268: make_boolean: ! 269: deflab( p->bn.label ); ! 270: temp = getlr( p, '1' )->tn.rval; ! 271: printf( " clrl %s\n", rnames[temp]); ! 272: markused(temp); ! 273: deflab( m ); ! 274: return; ! 275: ! 276: case 'H': ! 277: cbgen(p->in.op, p->in.left->in.type, p->bn.label, ! 278: p->bn.reversed, FCCODES); ! 279: return; ! 280: ! 281: case 'I': ! 282: cbgen(p->in.op, p->in.left->in.type, p->bn.label, ! 283: p->bn.reversed, CCODES); ! 284: return; ! 285: ! 286: /* stack management macros */ ! 287: case '-': ! 288: print_str( "sp@-" ); ! 289: case 'P': ! 290: toff += 4; ! 291: if (toff > maxtoff) maxtoff = toff; ! 292: return; ! 293: ! 294: case '0': ! 295: toff = 0; return; ! 296: ! 297: case '~': ! 298: /* complimented CR */ ! 299: p->in.right->tn.lval = ~p->in.right->tn.lval; ! 300: conput( getlr( p, 'R' ) ); ! 301: p->in.right->tn.lval = ~p->in.right->tn.lval; ! 302: return; ! 303: ! 304: case 'M': ! 305: /* negated CR */ ! 306: p->in.right->tn.lval = -p->in.right->tn.lval; ! 307: case 'O': ! 308: conput( getlr( p, 'R' ) ); ! 309: p->in.right->tn.lval = -p->in.right->tn.lval; ! 310: return; ! 311: ! 312: case 'T': ! 313: /* Truncate longs for type conversions: ! 314: INT|UNSIGNED -> CHAR|UCHAR|SHORT|USHORT ! 315: increment offset to second word */ ! 316: ! 317: m = p->in.type; ! 318: p = p->in.left; ! 319: switch( p->in.op ){ ! 320: case NAME: ! 321: case OREG: ! 322: if (p->in.type==SHORT || p->in.type==USHORT) ! 323: p->tn.lval += (m==CHAR || m==UCHAR) ? 1 : 0; ! 324: else p->tn.lval += (m==CHAR || m==UCHAR) ? 3 : 2; ! 325: return; ! 326: case REG: ! 327: return; ! 328: default: ! 329: cerror( "Illegal ZT type conversion" ); ! 330: return; ! 331: ! 332: } ! 333: ! 334: case 't': ! 335: /* ! 336: * Lengthen little (unsigned) things. Try to be smart ! 337: * about instruction sequences. ! 338: */ ! 339: s = p->in.left; ! 340: m = s->in.type; ! 341: if (ISUNSIGNED(m)){ ! 342: /* zero-extending into temp register */ ! 343: if ( istnode(s) && s->tn.rval == resc[0].tn.rval ){ ! 344: /* must use andl instructions */ ! 345: print_str_str( " andl #0x", (m==UCHAR)?"ff":"ffff"); ! 346: } else { ! 347: print_str_str_nl( " moveq #0,", rnames[ resc[0].tn.rval ] ); ! 348: printf( " mov%c ", (m==UCHAR)?'b':'w'); ! 349: adrput( s ); ! 350: } ! 351: putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] ); ! 352: } else { ! 353: /* sign-extending into temp register */ ! 354: if (!(istnode(s) && s->tn.rval == resc[0].tn.rval) ){ ! 355: /* not already in its register */ ! 356: printf( " mov%c ", (m==CHAR)?'b':'w'); ! 357: adrput( s ); ! 358: putchar(','); print_str_nl(rnames[ resc[0].tn.rval ] ); ! 359: } ! 360: /* sign-extend */ ! 361: if (m == CHAR) ! 362: print_str_str_nl( " extw ", rnames[resc[0].tn.rval]); ! 363: if (p->in.type != SHORT && p->in.type != USHORT) ! 364: print_str_str_nl( " extl ", rnames[resc[0].tn.rval]); ! 365: } ! 366: return; ! 367: ! 368: case 'W': /* structure size */ ! 369: if( p->in.op == STASG ) ! 370: print_d(p->stn.stsize); ! 371: else cerror( "Not a structure" ); ! 372: return; ! 373: ! 374: case 'S': /* structure assignment */ ! 375: stmove( p, cookie ); ! 376: return; ! 377: ! 378: case 'X':{ /* indexed effective address */ ! 379: NODE fake,*lp,*rp; ! 380: int flags; ! 381: lp = p->in.left; ! 382: rp = p->in.right; ! 383: R2PACKFLGS(flags, rp->in.type == SHORT, 0, 0); ! 384: fake.in.op = OREG; ! 385: fake.tn.rval = R2PACK(lp->in.left->tn.rval, rp->tn.rval, flags); ! 386: fake.tn.name = "\0"; ! 387: fake.tn.lval = lp->in.right->tn.lval; ! 388: oregput(&fake); ! 389: return; ! 390: } ! 391: ! 392: case 'a': ! 393: /* assign something to a bit field */ ! 394: case 'b': ! 395: /* extract a bit field */ ! 396: case 'c': ! 397: /* compare bit field with constant for CC only */ ! 398: eval_field( p, c, cookie); ! 399: return; ! 400: ! 401: case 'f': /* floating-point operation */ ! 402: /* since the floating-point format may be changed with a ! 403: * compile-time switch, we need to go think about this ! 404: */ ! 405: floatcode( p, cookie ); ! 406: fltused++; ! 407: return; ! 408: case 'g': /* floating-point conversion to normal register */ ! 409: /* anything that looks like a floating type conversion ! 410: * or a floating-register load or store comes here. ! 411: */ ! 412: floatconv( p, c, cookie ); ! 413: fltused++; ! 414: return; ! 415: ! 416: case 'm': /* multiplication by a constant */ ! 417: conmul( p, cookie ); ! 418: return; ! 419: ! 420: case 'd': /* division by a constant */ ! 421: condiv( p, cookie ); ! 422: return; ! 423: ! 424: case 'r': /* remainder by a constant */ ! 425: conrem( p, cookie ); ! 426: return; ! 427: ! 428: case ' ': /* leaf-type for effect only */ ! 429: /* ! 430: * usually this will generate NO code. ! 431: * the exception is INCR or ASG MINUS, as in ! 432: * *p++, *--p; ! 433: * these are recognized as side effects of addressing ! 434: * modes, so have not been dealt with by higher functions. ! 435: */ ! 436: if (p->in.op == UNARY MUL){ ! 437: if (p->in.left->in.op == INCR){ ! 438: printf(" addql #%d, %s\n", ! 439: tlen(p), rnames[p->in.left->in.left->tn.rval]); ! 440: } else if (p->in.left->in.op == ASG MINUS){ ! 441: printf(" subql #%d, %s\n", ! 442: tlen(p), rnames[p->in.left->in.left->tn.rval]); ! 443: } ! 444: } ! 445: return; ! 446: ! 447: case 'l': /* lea or addl instruction, as appropriate */ ! 448: if (p->in.left->tn.rval == resc[0].tn.rval){ ! 449: /* really a += */ ! 450: expand( p, cookie, " addZR AR,A1\n"); ! 451: } else { ! 452: /* really is a 3-address lea */ ! 453: expand( p, cookie, " lea AL@(0,AR:ZR),A1\n"); ! 454: } ! 455: return; ! 456: ! 457: case 'v': /* generate trapv for signed arithmetic */ ! 458: trapv(p->in.type); ! 459: return; ! 460: ! 461: case 'V': /* generate bound-testing code */ ! 462: bound_test(p, cookie); ! 463: return; ! 464: ! 465: default: ! 466: cerror( "illegal zzzcode" ); ! 467: } ! 468: } ! 469: ! 470: #define checkout if (resc[opno].tn.op != REG) cerror("struct-assign botch") ! 471: ! 472: NODE * ! 473: cpytmp( l, opno ) NODE *l; ! 474: { ! 475: NODE *new; ! 476: print_str( (l->in.op == REG)||(ISPTR(l->in.type))? " movl " : " lea "); ! 477: adrput( l ); ! 478: checkout; ! 479: new = &resc[opno]; ! 480: new->tn.type = ISPTR(l->in.type)?l->in.type:INCREF(l->in.type); ! 481: markused(new->tn.rval); ! 482: putchar(','); print_str_nl(rnames[new->tn.rval] ); ! 483: return new; ! 484: } ! 485: ! 486: ! 487: void ! 488: stmove( p , cookie ) register NODE *p; ! 489: { ! 490: register NODE *l, *r; ! 491: register size, i; ! 492: extern NODE resc[]; ! 493: int opno = 1; ! 494: int rcopy; ! 495: int xsize; ! 496: int labl; ! 497: int loopcode; ! 498: register char *cnt, *lhs, *rhs; ! 499: ! 500: char **moves; ! 501: # define MOVBSTRNG 0 ! 502: # define MOVWSTRNG 1 ! 503: # define MOVLSTRNG 2 ! 504: static char * asgstrings[] = { ! 505: " movb AR,AL\n", ! 506: " movw AR,AL\n", ! 507: " movl AR,AL\n", ! 508: }; ! 509: static char * argstrings[] = { ! 510: " movb AR,sp@-\n", ! 511: " movw AR,sp@-\n", ! 512: " movl AR,sp@-\n", ! 513: }; ! 514: ! 515: if( p->in.op == STASG ){ ! 516: l = p->in.left; ! 517: r = p->in.right; ! 518: moves = asgstrings; ! 519: } else if( p->in.op == STARG ){ /* store an arg onto the stack */ ! 520: /* ! 521: * "r" and "l" are obviously misnomers here. ! 522: * they should be "from" and, perhaps, "to". ! 523: */ ! 524: r = p->in.left; ! 525: checkout; ! 526: l = &resc[opno++]; ! 527: markused(l->tn.rval); ! 528: moves = argstrings; ! 529: } else ! 530: cerror( "STASG bad" ); ! 531: ! 532: if ( r->in.op == ICON ) ! 533: r->in.op = NAME; ! 534: /* ! 535: * avoid complicated memory operands ! 536: */ ! 537: if (l->in.op == OREG && R2TEST(l->tn.rval)) { ! 538: l = cpytmp( l, opno++ ); ! 539: } ! 540: if (r->in.op == OREG && R2TEST(r->tn.rval)) { ! 541: r = cpytmp( r, opno++ ); ! 542: } ! 543: size = p->stn.stsize; ! 544: xsize = size + (size&1); /* must be even */ ! 545: ! 546: /* ! 547: * now we make a totally arbitrary decision about ! 548: * when to loop, and when to emit straight-line code. ! 549: */ ! 550: ! 551: if (size <= 8){ ! 552: /* straight-line */ ! 553: NODE xxx; ! 554: ! 555: /* the MIT strategy -- gross, no? */ ! 556: if( l->in.op != REG && ISPTR(l->in.type)) ! 557: l = cpytmp( l, opno++ ); ! 558: if( r->in.op != REG && ISPTR(r->in.type)) ! 559: r = cpytmp( r, opno++ ); ! 560: xxx.in.op = STASG; ! 561: xxx.in.left = l; ! 562: xxx.in.right = r; ! 563: if( r->tn.op == REG ){ ! 564: r->tn.op = OREG; ! 565: r->tn.type = DECREF(r->tn.type); ! 566: } ! 567: if( l->in.op == REG ) l->in.op = OREG; ! 568: r->tn.lval += size; ! 569: l->tn.lval += size; ! 570: ! 571: switch (size&03){ ! 572: /* do special cases */ ! 573: case 1: ! 574: case 3: ! 575: r->tn.lval -= 1; ! 576: l->tn.lval -= 1; ! 577: expand( &xxx, cookie, moves[MOVBSTRNG] ); ! 578: if ((size&03) == 1) break; ! 579: /* case 3 falls through */ ! 580: case 2: ! 581: r->tn.lval -= 2; ! 582: l->tn.lval -= 2; ! 583: expand( &xxx, cookie, moves[MOVWSTRNG] ); ! 584: } ! 585: size -= size&03; ! 586: /* assert( size%4 == 0 ) */ ! 587: while( size ){ /* simple load/store loop */ ! 588: r->tn.lval -= 4; ! 589: l->tn.lval -= 4; ! 590: size -= 4; ! 591: expand( &xxx, cookie, moves[MOVLSTRNG] ); ! 592: } ! 593: } else { ! 594: /* loop code */ ! 595: loopcode = size >= 20; ! 596: if (loopcode) { ! 597: cnt = rnames[resc[0].tn.rval]; ! 598: printf(" mov%c #%d,%s\n", (size<(1<<16))?'w':'l', ! 599: size/4-1, cnt); ! 600: } ! 601: if ( !istnode(l)){ ! 602: if (l->tn.op==OREG && !R2TEST(l->tn.rval) ! 603: && istreg(l->tn.rval) && l->tn.lval==0) ! 604: l->tn.op=REG; ! 605: else ! 606: l = cpytmp( l, opno++ ); ! 607: } ! 608: if ( !istnode(r) ){ ! 609: r = cpytmp( r, opno++ ); ! 610: rcopy = 1; /* this is not our real rhs */ ! 611: } else ! 612: rcopy = 0; ! 613: lhs = rnames[l->tn.rval]; ! 614: rhs = rnames[r->tn.rval]; ! 615: if (p->in.op==STARG){ ! 616: /* ! 617: * structure argument: ! 618: * push space on stack (lea sp@(size),sp) ! 619: * copy sp to a temp register we can bomb ! 620: * go for it. ! 621: */ ! 622: if (xsize <(1<<16)) ! 623: printf( " lea sp@(-%d),sp\n", xsize); ! 624: else ! 625: printf( " subl #%d,sp\n", xsize); ! 626: printf(" movl sp,%s\n", lhs); ! 627: } ! 628: if (loopcode) { ! 629: print_label(labl= getlab()); ! 630: /* now emit the 2-instruction loop */ ! 631: printf(" movl %s@+,%s@+\n", rhs, lhs); ! 632: printf(" dbra %s,L%d\n", cnt, labl); ! 633: if (size>=(1<<16)){ ! 634: /* "long dbra" */ ! 635: printf(" clrw %s\n", cnt); ! 636: printf(" subql #1,%s\n", cnt); ! 637: printf(" jcc L%d\n", labl); ! 638: } ! 639: } else { ! 640: /* use autoincrement mode in an unrolled loop */ ! 641: int n; ! 642: for (n = 0; n < size/4; n++) ! 643: printf(" movl %s@+,%s@+\n", rhs, lhs); ! 644: } ! 645: switch (size&03) { ! 646: /* oops -- stuff leftover */ ! 647: case 3: ! 648: printf(" movw %s@+,%s@+\n", rhs, lhs); ! 649: /* fall thorugh */ ! 650: case 1: ! 651: printf(" movb %s@,%s@\n", rhs, lhs); ! 652: break; ! 653: case 2: ! 654: printf(" movw %s@,%s@\n", rhs, lhs); ! 655: break; ! 656: } ! 657: if (cookie&(INBREG|INTBREG) && !rcopy){ ! 658: /* oh damn, must repair damage */ ! 659: int temp; ! 660: temp = p->stn.stsize; ! 661: p->stn.stsize &= ~0x3; ! 662: if (size <(1<<16)) ! 663: expand( p, FOREFF, " lea AR@(-ZW),AR\n"); ! 664: else ! 665: expand( p, FOREFF, " subl #ZW,AR\n"); ! 666: p->stn.stsize = temp; ! 667: } ! 668: } ! 669: if (p->in.op==STARG){ ! 670: /* keep toff up-to-date */ ! 671: if (xsize<3){ ! 672: /* must pad */ ! 673: printf(" subqw #2,sp\n"); ! 674: xsize = 4; ! 675: } ! 676: toff += xsize; ! 677: if (toff>maxtoff) maxtoff= toff; ! 678: } else { ! 679: r = p->in.right; ! 680: if ( r->in.op == NAME ) ! 681: r->in.op = ICON; ! 682: else if (!(cookie&SANY) && r->tn.op==OREG && !ISPTR(r->tn.type)){ ! 683: /* we get to make up a (choke) address here */ ! 684: if (r->tn.lval == 0){ ! 685: r->in.op = REG; ! 686: r->tn.type = INCREF(r->tn.type); ! 687: } else ! 688: cerror("trapped in a multiple-structue-assigment"); ! 689: } ! 690: } ! 691: } ! 692: ! 693: #undef checkout ! 694: ! 695: /* ! 696: * alignfield(p, byteoff) ! 697: * Align an operand for a 68020 bit field operation. If byteoff ! 698: * is nonzero, subtract it (it was previously added to the offset ! 699: * part of p->in.left, possibly resulting in an odd offset). Then ! 700: * longword-align the offset, assuming that names and activation ! 701: * records are longword-aligned. ! 702: */ ! 703: static ! 704: alignfield(p, byteoff) ! 705: register NODE *p; /* assumed to be FLD op */ ! 706: int byteoff; ! 707: { ! 708: register NODE *lp; /* assumed to be operand address */ ! 709: int fieldoff, fieldsize, residue; ! 710: ! 711: lp = p->in.left; ! 712: switch( lp->in.op ){ ! 713: case NAME: ! 714: case ICON: ! 715: case OREG: ! 716: if (byteoff) { ! 717: /* undo it */ ! 718: lp->tn.lval -= byteoff; ! 719: } ! 720: residue = lp->tn.lval % (SZLONG/SZCHAR); ! 721: if (residue < 0) { ! 722: /* ! 723: * careful about AUTOs -- ! 724: * the offsets are negative ! 725: */ ! 726: residue += (SZLONG/SZCHAR); ! 727: } ! 728: fieldoff = UPKFOFF(p->tn.rval) + residue*SZCHAR; ! 729: fieldsize = UPKFSZ(p->tn.rval); ! 730: if (fieldoff + fieldsize <= SZLONG) { ! 731: /* ! 732: * take bytes away from the operand address, ! 733: * and put bits back in the field offset. ! 734: */ ! 735: lp->tn.lval -= residue; ! 736: p->tn.rval = PKFIELD(fieldsize, fieldoff); ! 737: } ! 738: break; ! 739: default: ! 740: cerror( "illegal address in alignfield" ); ! 741: break; ! 742: } ! 743: } ! 744: ! 745: expandfield(p) ! 746: register NODE *p; ! 747: { ! 748: printf( "{#%d:#%d}", UPKFOFF(p->tn.rval), UPKFSZ(p->tn.rval) ); ! 749: } ! 750: ! 751: void ! 752: eval_field( p, c, cookie ) ! 753: NODE *p; ! 754: char c; ! 755: { ! 756: register temp, m; ! 757: register NODE *l, *r; ! 758: int lobyte, hibyte; ! 759: char *regname; ! 760: NODE *fieldnode; ! 761: int conval; ! 762: ! 763: l = p->in.left; ! 764: r = p->in.right; ! 765: fieldnode = (c == 'b') ? p : p->in.left; ! 766: lobyte = (SZINT - fldshf - 1)/SZCHAR; /* byte containing low-order bit */ ! 767: hibyte = (SZINT -fldshf -fldsz)/SZCHAR;/* byte containing high-order bit */ ! 768: if (fieldnode->in.left->tn.op == REG){ ! 769: if ( ISPTR(fieldnode->in.left->tn.type)){ ! 770: fieldnode->in.left->tn.op = OREG; ! 771: } else { ! 772: /* always use longword accesses to registers */ ! 773: hibyte = 0; ! 774: temp = SZINT; ! 775: p->in.type = UNSIGNED; ! 776: goto longonly; ! 777: } ! 778: } ! 779: ! 780: if (lobyte==hibyte){ ! 781: /* ok to do byte accesses to memory */ ! 782: temp = SZCHAR; ! 783: p->in.type = UCHAR; ! 784: } else if ((hibyte&1) || (hibyte < (lobyte-1))){ ! 785: /* must do longword access */ ! 786: hibyte = 0; ! 787: temp = SZINT; ! 788: p->in.type = UNSIGNED; ! 789: } else { ! 790: /* word access */ ! 791: temp = SZSHORT; ! 792: p->in.type = USHORT; ! 793: } ! 794: ! 795: /* adjust shift value, paint over left type and address */ ! 796: fldshf = temp - (SZINT-fldshf -(hibyte*SZCHAR)); ! 797: if (hibyte){ ! 798: incraddr( fieldnode, hibyte); ! 799: } ! 800: ! 801: longonly: ! 802: ! 803: switch (c){ ! 804: case 'a': ! 805: /* assignment of a value to a bit field */ ! 806: /* the two cases are: constant r-h-s, and variable r-h-s */ ! 807: /* the constant case has several interesting sub-cases */ ! 808: if (r->tn.op == ICON){ ! 809: /* easy case */ ! 810: conval = r->tn.lval; ! 811: m = r->tn.lval; ! 812: if (fldsz == 1) { ! 813: /* very easy case */ ! 814: print_str_d( (m&1)?" bset #":" bclr #", fldshf); putchar(','); ! 815: adrput( l ); ! 816: } else { ! 817: /* ! 818: * wide field: ! 819: * depending on field size and alignment, we may ! 820: * have to do word or longword accesses ! 821: */ ! 822: if (m==0){ ! 823: /* clearing entire field */ ! 824: if (fldshf==0 && fldsz == temp){ ! 825: /* no masking involved -- whole unit */ ! 826: expand( p, cookie, " clrZB AL"); ! 827: } else { ! 828: expand( p, cookie, " andZB #N,AL"); ! 829: } ! 830: } else if ( m==-1 || m==BITMASK(fldsz)){ ! 831: /* setting entire field */ ! 832: if (fldshf==0 && fldsz == temp){ ! 833: /* no masking involved -- whole unit */ ! 834: if (fldsz == SZCHAR) { ! 835: expand( p, cookie, " st AL"); ! 836: } else { ! 837: expand( p, cookie, " movZB #CR,AL"); ! 838: } ! 839: } else { ! 840: expand( p, cookie, " orZB #M,AL" ); ! 841: } ! 842: } else { ! 843: /* -- inserting value -- */ ! 844: if (fldshf==0 && fldsz == temp){ ! 845: /* no masking involved -- whole unit */ ! 846: expand( p, cookie, " movZB #CR,AL"); ! 847: } else { ! 848: m &= BITMASK(fldsz); ! 849: r->tn.lval = m<<fldshf; ! 850: expand(p, cookie, " andZB #N,AL\n orZB #CR,AL"); ! 851: } ! 852: } ! 853: } ! 854: /* restore old ICON value in case we want to use it as ! 855: the result of the assignment */ ! 856: r->tn.lval = conval; ! 857: } else { ! 858: /* non-constant */ ! 859: /* there are only two cases here : ! 860: shifting and masking, or ! 861: not shifting or masking ! 862: */ ! 863: if (fldsz == temp && fldshf == 0){ ! 864: /* direct move */ ! 865: expand( p, cookie, " movZB AR,AL"); ! 866: } else if (use68020) { ! 867: /* the normal, ugly case, with 68020 instructions */ ! 868: alignfield(fieldnode, hibyte); ! 869: expand( p, cookie, " bfins AR,AL"); ! 870: expandfield(fieldnode); ! 871: } else { ! 872: /* the normal, ugly case, with 68010 instructions */ ! 873: /* clear field in destination */ ! 874: expand( p, cookie, " andZB #N,AL\n"); ! 875: /* move value to temp and adjust */ ! 876: temp = fldshf; ! 877: fldshf = 0; ! 878: if (r->tn.op == REG && istreg(r->tn.rval) && (cookie&FOREFF)){ ! 879: /* do it in place */ ! 880: regname = rnames[r->tn.rval]; ! 881: /* mask source to the right number of bits, and */ ! 882: expand( p, cookie, " andZB #M,AR\n"); ! 883: /* shift into place */ ! 884: shiftreg( temp, regname , -1, 0, 'l', UNSIGNED); ! 885: /* combine source into destination */ ! 886: expand( p, cookie, " orZB AR,AL"); ! 887: } else { ! 888: /* must copy over */ ! 889: rmove( resc[0].tn.rval, r->tn.rval, UNSIGNED ); ! 890: expand( p, cookie, " andZB #M,A1\n"); ! 891: regname = rnames[ resc[0].tn.rval ]; ! 892: shiftreg( temp, regname , -1, 0, 'l', UNSIGNED); ! 893: expand( p, cookie, " orZB A1,AL"); ! 894: } ! 895: } ! 896: } ! 897: p->in.type = UNSIGNED; ! 898: return; ! 899: ! 900: case 'b': ! 901: /* extracting field value -- either for CC or for value */ ! 902: if (cookie & FORCC){ ! 903: compare_with_zero: ! 904: /* only extracting value to compare it with zero */ ! 905: if (fldsz == 1){ ! 906: /* snap case -- so long as fields are unsigned! */ ! 907: print_str_d( " btst #", fldshf); putchar(','); ! 908: adrput( l ); ! 909: } else if (fldsz == temp && fldshf == 0){ ! 910: /* direct memory test */ ! 911: expand( p, cookie, " tstZB AL"); ! 912: } else { ! 913: /* ! 914: * move value into a register -- and with mask to set CC. ! 915: * We would have to worry about setting the N condition ! 916: * here, but our unsigned-ness prevents this from being ! 917: * a problem. ! 918: */ ! 919: if (l->tn.op == REG && istreg(l->tn.rval)){ ! 920: expand( p, cookie, " andl #M,AL"); ! 921: } else { ! 922: expand( p, cookie, ! 923: " movZB AL,A1\n andZB #M,A1"); ! 924: } ! 925: } ! 926: } else { ! 927: /* extracting value for value's sake */ ! 928: if (l->tn.op == REG && istreg(l->tn.rval)){ ! 929: regname = rnames[ l->tn.rval ]; ! 930: if (use68020 && fldshf != 0) { ! 931: alignfield(fieldnode, hibyte); ! 932: expand( p, cookie, " bfextu AL"); ! 933: expandfield(fieldnode); ! 934: putchar(','); print_str(regname); ! 935: } else { ! 936: shiftreg( -fldshf, regname , resc[0].tn.rval, 0, 'l', UNSIGNED); ! 937: fldshf = 0; ! 938: expand( p, cookie, " andl #M,AL"); ! 939: } ! 940: } else { ! 941: regname = rnames[ resc[0].tn.rval ]; ! 942: if (use68020 && fldshf != 0) { ! 943: alignfield(fieldnode, hibyte); ! 944: expand( p, cookie, " bfextu AL"); ! 945: expandfield(fieldnode); ! 946: putchar(','); print_str(regname); ! 947: } else { ! 948: if (temp != SZINT){ ! 949: print_str_str_nl(" moveq #0,", regname ); ! 950: } ! 951: expand( p, cookie, " movZB AL,A1"); ! 952: if (fldsz != temp || fldshf != 0){ ! 953: putchar('\n'); ! 954: shiftreg( -fldshf, regname, -1, 0, 'l', UNSIGNED); ! 955: fldshf = 0; ! 956: expand( p, cookie, " andZB #M,A1"); ! 957: } ! 958: } ! 959: } ! 960: } ! 961: ! 962: fieldnode->in.type = UNSIGNED; ! 963: return; ! 964: ! 965: case 'c': ! 966: /* comparison of field value with constant value for CC only */ ! 967: m = r->tn.lval; ! 968: if (m==0) goto compare_with_zero; ! 969: r->tn.lval = m << fldshf; ! 970: if (temp == fldsz && fldshf == 0 ){ ! 971: /* compare directly to memory */ ! 972: expand(p, cookie, " cmpZB #CR,AL"); ! 973: } else if (l->tn.op == REG && istreg(l->tn.rval) && cookie&FOREFF){ ! 974: /* munge in place */ ! 975: expand( p, cookie," andZB #M,AL\n cmpZB #CR,AL"); ! 976: } else { ! 977: /* move to register, mask, compare */ ! 978: expand( p, cookie, ! 979: " movZB AL,A1\n andZB #M,A1\n cmpZB #CR,A1"); ! 980: } ! 981: } ! 982: ! 983: } ! 984: ! 985: /* routine used by the field-evaluation code to emit shifting instructions. ! 986: "val" is the amount to shift, s is the name of the register to shift, ! 987: and "reg" is the register NUMBER of a helper, if one is available. ! 988: If val<0, we're doing right shifts ! 989: If needclr != 0, must clear lower word after swap. ! 990: */ ! 991: void ! 992: shiftreg( val, s , reg, needclr, typechar, type ) ! 993: char *s; ! 994: char typechar; ! 995: { ! 996: char *t; ! 997: char *shift = "lsll"; ! 998: int lshift; ! 999: if (val < 0 ){ ! 1000: shift = "lsrl"; ! 1001: val = -val; ! 1002: lshift = 0; ! 1003: } else{ ! 1004: lshift = 1; ! 1005: shift[0] = (ISUNSIGNED(type) || ISPTR(type))? 'l' : 'a'; ! 1006: } ! 1007: shift[3] = typechar; /* ugly hack */ ! 1008: if (val > 16 ){ ! 1009: if (reg >= 0){ ! 1010: printf(" movl #%d,%s\n", val, t=rnames[ reg ]); ! 1011: printf(" %s %s,%s\n", shift, t, s); ! 1012: trapv(type); ! 1013: return; ! 1014: } ! 1015: if (!(chk_ovfl && shift[0] == 'a')){ ! 1016: print_str_str_nl(" swap ", s); ! 1017: if (needclr&&lshift) ! 1018: print_str_str_nl(" clrw ", s); ! 1019: val -= 16; ! 1020: } ! 1021: } ! 1022: while (val > 0){ ! 1023: if (val> 8){ ! 1024: printf(" %s #8,%s\n", shift, s); ! 1025: val -= 8; ! 1026: } else { ! 1027: if (val==1 && lshift) ! 1028: printf(" add%c %s,%s\n", typechar, s,s); ! 1029: else ! 1030: printf(" %s #%d,%s\n", shift, val, s); ! 1031: val = 0; ! 1032: } ! 1033: trapv(type); ! 1034: } ! 1035: } ! 1036: ! 1037: void ! 1038: incraddr( p , v) ! 1039: register NODE *p; ! 1040: long v; ! 1041: { ! 1042: /* bump the address p by the value b. */ ! 1043: if( p->in.op == FLD ){ ! 1044: p = p->in.left; ! 1045: } ! 1046: switch( p->in.op ){ ! 1047: case NAME: ! 1048: case ICON: ! 1049: case OREG: ! 1050: p->tn.lval += v; ! 1051: break; ! 1052: default: ! 1053: cerror( "illegal incraddr address" ); ! 1054: break; ! 1055: ! 1056: } ! 1057: } ! 1058: ! 1059: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ ! 1060: ! 1061: insput( p ) register NODE *p; ! 1062: { ! 1063: #ifndef IEEECCODES ! 1064: printf(ccodes[p->in.op-EQ]); ! 1065: #else IEEECCODES ! 1066: if (ISFLOATING(p->in.left->in.type)) { ! 1067: printf(fccodes[p->in.op-EQ]); ! 1068: } else { ! 1069: printf(ccodes[p->in.op-EQ]); ! 1070: } ! 1071: #endif IEEECCODES ! 1072: } ! 1073: ! 1074: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ ! 1075: ! 1076: /* ! 1077: * Generate conditional branches from a relational operator. ! 1078: * The exact form of the branch depends on: ! 1079: * 1. whether or not the compared operands have floating point types ! 1080: * 2. whether or not the coprocessor condition code is used ! 1081: * 3. whether the operator has been negated. ! 1082: */ ! 1083: ! 1084: cbgen( o, type, label, reversed, mode ) ! 1085: int o; /* relational op {EQ, NE, LT, LE, ...} */ ! 1086: TWORD type; /* operand type - determines opcode */ ! 1087: int label; /* destination label */ ! 1088: int reversed; /* =1 if op is to be negated */ ! 1089: int mode; /* if FCCODES, use coprocessor condition codes */ ! 1090: { ! 1091: char *prefix; ! 1092: char *opname; ! 1093: ! 1094: #ifndef IEEECCODES ! 1095: if (reversed) { ! 1096: /* treat !(a < b) as (a >= b) */ ! 1097: o = negrel[o-EQ]; ! 1098: } ! 1099: if (mode == FCCODES) { ! 1100: prefix = "fj"; ! 1101: opname = fccodes[o-EQ]; ! 1102: } else { ! 1103: prefix = "j"; ! 1104: opname = ccodes[o-EQ]; ! 1105: } ! 1106: #else IEEECCODES ! 1107: if (ISFLOATING(type)) { ! 1108: prefix = (mode == FCCODES ? "fj" : "jf"); ! 1109: opname = (reversed ? fnegccodes[o-EQ] : fccodes[o-EQ]); ! 1110: } else { ! 1111: prefix = "j"; ! 1112: if (reversed) ! 1113: o = negrel[o-EQ]; ! 1114: opname = ccodes[o-EQ]; ! 1115: } ! 1116: #endif IEEECCODES ! 1117: printf(" %s%s L%d\n", prefix, opname, label); ! 1118: } ! 1119: ! 1120: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ ! 1121: ! 1122: #ifdef FORT ! 1123: branch(lab) ! 1124: int lab; ! 1125: { ! 1126: printf(" jra L%d\n", lab); ! 1127: } ! 1128: #endif FORT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.