|
|
1.1 ! root 1: #include "gencode.h" ! 2: #define fieldbotch(p) if(p->left->op == Fld) {rewritefld(p); longjmp(back, 1);} ! 3: jmp_buf back; ! 4: int acnt, Pflag, bbcnt; ! 5: NODE *svq; /* just for printing at FAIL */ ! 6: ! 7: gencode(p) ! 8: NODE *p; ! 9: { mnod *q; ! 10: ret s; ! 11: int svtemp, svregvar, i, svbb; ! 12: extern int bothdebug; ! 13: svtemp = tmpoff; ! 14: svregvar = regvar; ! 15: svbb = ++bbcnt; ! 16: svq = p; ! 17: if(setjmp(back)) { ! 18: pr("#\treg\t%d\n", ++acnt) /*,prtree(q), putchar('\n')*/; ! 19: if(acnt > 20) { ! 20: prtree(q); ! 21: outpr(); ! 22: tmpoff = svtemp; ! 23: bbcnt = svbb; ! 24: uerror("expression too complicated"); ! 25: return; ! 26: } ! 27: } ! 28: else ! 29: q = copytree(p); ! 30: buf = bufs[1]; ! 31: prptr = prbuf; ! 32: if(Pflag && q->op != Init) { ! 33: pr("#\tincl\tlocprof+%d\n", 4*(svbb+3)); ! 34: } ! 35: s = doit(q, 0, 0, REGMASK); ! 36: if(s.flag & FAIL) ! 37: uerror("codegen failed at top level"); ! 38: acnt = ntree = 0; ! 39: if(Pflag && q->op != Init) ! 40: printx("#%d ", svbb), prtree(q), printx("\n"); ! 41: outpr(); ! 42: tmpoff = svtemp; ! 43: regvar = svregvar; ! 44: } ! 45: ! 46: ret ! 47: doit(p, flag, dest, regmask) ! 48: mnod *p; ! 49: ret dest; ! 50: { ret s, t, x, y; ! 51: char *pp; ! 52: mnod snode, *q; ! 53: int i, j, svmask = regmask; ! 54: switch(p->op) { ! 55: default: ! 56: pr("#\tweird??? %d\n", p->op); ! 57: return(dest); ! 58: case Andeq: ! 59: fieldbotch(p) ! 60: if(dest.ans && p->left->op == Star) ! 61: longjmp(back, mediumstar(p)); ! 62: flag |= DESTISLEFT; ! 63: flag &= ~CC; ! 64: case And: ! 65: if((flag & CC)) { /* short b; reg int *c; if(b & *c++); */ ! 66: if(p->left->op == Conv && incrsize(p->left->left) < 4) ! 67: p->left = p->left->left; ! 68: if(p->right->op == Conv ! 69: && incrsize(p->right->left) < 4) ! 70: p->right = p->right->left; ! 71: } ! 72: t = doit(p->left, VALUE|USED, 0, regmask); ! 73: if(t.flag & FAIL) ! 74: return(t); ! 75: regmask &= ~t.regmask; ! 76: s = doit(p->right, VALUE|USED, 0, regmask); ! 77: if(s.flag & FAIL) ! 78: goto binfail; ! 79: if(flag & CC) { ! 80: if(incrsize(p->left) == incrsize(p->right)) ! 81: i = type(p->right); ! 82: else if(incrsize(p->left) < incrsize(p->right)) { ! 83: if(s.flag & INDEX) { ! 84: totemp(p, RIGHT); ! 85: longjmp(back, 1); ! 86: } ! 87: i = childtype(p); ! 88: } ! 89: else { ! 90: if(t.flag & INDEX) { ! 91: totemp(p, LEFT); ! 92: longjmp(back, 1); ! 93: } ! 94: i = type(p->right); ! 95: } ! 96: pr("#\tbit%c\t%s,%s\n", i, str(s), str(t)); ! 97: dest.ans = 0; ! 98: dest.flag = CC; ! 99: dest.regmask = 0; ! 100: return(dest); ! 101: } ! 102: regmask &= ~s.regmask; ! 103: /* p->right->op == Compl is a useful special case */ ! 104: if((flag & DESTISLEFT) && dest.ans == 0) ! 105: dest = x = t; ! 106: if(dest.ans == 0) ! 107: if(s.flag & SCRATCH) ! 108: dest = x = s; ! 109: else if(t.flag & SCRATCH) { ! 110: dest = t; ! 111: x = allocreg(p, regmask); ! 112: } ! 113: else ! 114: dest = x = allocreg(p, regmask); ! 115: else ! 116: x = allocreg(p, regmask); ! 117: if(p->right->op == Icon) { ! 118: x = tostack(); /* to get a buf */ ! 119: sprintx(str(x), "$%d", -p->right->lval - 1); ! 120: } ! 121: else ! 122: pr("#\tmcom%c\t%s,%s\n", childtype(p), str(s), str(x)); ! 123: if(strcmp(str(t), str(dest)) == 0) ! 124: pr("#\tbic%c2\t%s,%s\n", childtype(p), str(x), str(dest)); ! 125: else if(flag & DESTISLEFT) { ! 126: pr("#\tbic%c2\t%s,%s\n", childtype(p), str(x), str(t)); ! 127: if(strcmp(str(t), str(dest))) { ! 128: x = t; ! 129: goto movexdest; ! 130: } ! 131: } ! 132: else ! 133: pr("#\tbic%c3\t%s,%s,%s\n", childtype(p), str(x), ! 134: str(t), str(dest)); ! 135: if(flag & ASADDR) ! 136: goto toaddr; ! 137: dest.flag |= CC; ! 138: return(dest); ! 139: case Call: ! 140: call: ! 141: s.flag = funargs(p->right, regmask); ! 142: if(s.flag & FAIL) ! 143: return(s); ! 144: i = p->argsize/32; ! 145: if(i > 255) ! 146: uerror("%d arguments is too many", i); ! 147: called: ! 148: s = doit(p->left, VALUE|ASADDR|USED, 0, regmask); ! 149: pp = str(s); ! 150: aftercall: ! 151: if(svmask != REGMASK) { ! 152: debugpr("#FAIL aftercall "); ! 153: s.flag = FAIL; ! 154: return(s); ! 155: } ! 156: x = specialreg(p, regmask); ! 157: pr("#\tcalls\t$%d,%s\n", i, pp); ! 158: if(flag & ASADDR) { ! 159: strcat(str(x), ")"); ! 160: strshift(str(x), 1); ! 161: str(x)[0] = '('; ! 162: } ! 163: if(dest.ans == 0) ! 164: if(flag & DESTISLEFT) ! 165: dest = doit(p->left->op == Conv? ! 166: p->left->left: ! 167: p->left, 0/* ? */, 0, regmask & ~x.regmask); ! 168: else ! 169: return(x); ! 170: movexdest: /* type(p), not childtype, for a = a % b */ ! 171: if(strcmp(str(x), str(dest)) == 0) ! 172: return(x); ! 173: if((flag & TOSTACK) && incrsize(p) == 4) ! 174: pr("#\tpush%c\t%s\n", type(p), str(x)); ! 175: else if(x.flag & ICON0) ! 176: pr("#\tclr%c\t%s\n", type(p), str(dest)); ! 177: else if(isfloat(p) != isfloat(p->left) ! 178: && p->op != Call && p->op != Ucall) ! 179: pr("#\tcvt%c%c\t%s,%s\n", childtype(p), type(p), str(x), str(dest)); ! 180: else if((flag & TOSTACK) && (incrsize(p) != 8)) ! 181: pr("#\tcvt%cl\t%s,-(sp)\n", type(p), str(x)); ! 182: else { ! 183: pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest)); ! 184: dest = simpler(x, dest); ! 185: } ! 186: dest.flag |= CC; ! 187: return(dest); ! 188: case Cmp: ! 189: if(p->left->op == Conv && p->right->op == Conv ! 190: && childtype(p->left) == childtype(p->right) ! 191: && !isfloat(p->left->left)) { /* bogus? */ ! 192: p->left = p->left->left; ! 193: p->right = p->right->left; ! 194: } ! 195: else if(p->left->op == Conv && p->right->op == Icon ! 196: && p->right->lval >= 0 ! 197: && ((incrsize(p->left->left) == 1 ! 198: && p->right->lval < 128) ! 199: || (incrsize(p->left->left) == 2 ! 200: && p->right->lval < 32768))) ! 201: p->left = p->left->left; ! 202: /* the above rewriting depends on childype being of p->left */ ! 203: s = doit(p->left, VALUE|USED, 0, regmask); ! 204: if(s.flag & FAIL) ! 205: return(s); ! 206: regmask &= ~s.regmask; ! 207: t = doit(p->right, VALUE|USED, 0, regmask); ! 208: if(t.flag & FAIL) { ! 209: t = doit(p->right, VALUE|USED, 0, REGMASK); ! 210: if(!(t.flag & FAIL) && svmask != REGMASK) ! 211: return(t.flag = FAIL, t); ! 212: totemp(p, LEFT); ! 213: longjmp(back, 1); ! 214: } ! 215: pr("#\tcmp%c\t%s,%s\n", childtype(p), str(s), str(t)); ! 216: dest.ans = dest.regmask = 0; ! 217: dest.flag = CC; ! 218: return(dest); ! 219: case Comop: /* qnodes lurking underneath */ ! 220: if(p->left->op == Genlab && hasqnode(p->right)) { ! 221: if(dest.ans == 0) { ! 222: dest = allocreg(p, regmask); ! 223: } ! 224: t = doit(p->left, VALUE|(flag & CC), dest, regmask); ! 225: } ! 226: else ! 227: t = doit(p->left, 0, 0, regmask); ! 228: if(t.flag & FAIL) ! 229: return(t); ! 230: s = doit(p->right, VALUE|(flag & (USED|CC)), dest, regmask); ! 231: if(s.flag & FAIL) ! 232: return(s); ! 233: if(flag & ASADDR) { ! 234: dest.ans = 0; ! 235: i = (s.flag & (ISREG|CANINDIR|SCRATCH)); ! 236: j = s.regmask; ! 237: buf = str(s); ! 238: goto convbuf; ! 239: } ! 240: return(s); ! 241: case Compl: ! 242: s = doit(p->left, VALUE|USED, 0, regmask); ! 243: if(s.flag & FAIL) ! 244: return(s); ! 245: if(dest.ans == 0) ! 246: if(s.flag & SCRATCH) ! 247: dest = s; ! 248: else ! 249: dest = allocreg(p, regmask & ~s.regmask); ! 250: pr("#\tmcom%c\t%s,%s\n", childtype(p), str(s), str(dest)); ! 251: dest.flag |= CC; ! 252: return(dest); ! 253: case Conv: ! 254: if(p->left->op == Asg && p->left->left->op == Star) { ! 255: if(dest.ans == 0) { ! 256: dest = allocreg(p, regmask); ! 257: s = doit(p->left, VALUE|USED, dest, regmask); ! 258: } ! 259: else { ! 260: x = allocreg(p, regmask); ! 261: s = doit(p->left, VALUE|USED, x, regmask & ~x.regmask); ! 262: } ! 263: if(s.flag & FAIL) { ! 264: asgwrite(p->left); ! 265: longjmp(back, 1); ! 266: } ! 267: } ! 268: else ! 269: s = doit(p->left, VALUE|USED, 0, regmask); ! 270: if(childtype(p) == type(p) && dest.ans == 0) ! 271: return(s); ! 272: if(s.flag & FAIL) ! 273: return(s); ! 274: if(dest.ans == 0) ! 275: if(s.flag & SCRATCH) ! 276: dest = checksize(p, s, regmask); ! 277: else ! 278: dest = allocreg(p, regmask); ! 279: if(isunsigned(p->left) && incrsize(p) > incrsize(p->left)) { ! 280: if(type(p) != 'f' && type(p) != 'd') ! 281: pp = "movz"; ! 282: else { /* uns to float or double */ ! 283: rewriteconv(p); ! 284: longjmp(back, 1); ! 285: } ! 286: } ! 287: else ! 288: pp = "cvt"; ! 289: if(isfloat(p) != isfloat(p->left)) ! 290: goto cvtop; ! 291: if(incrsize(p) < incrsize(p->left)) { ! 292: if(isfloat(p)) ! 293: goto cvtop; ! 294: pr("#\tmov%c\t%s,%s\n", type(p), str(s), str(dest)); ! 295: dest = simpler(s, dest); ! 296: } ! 297: else if(incrsize(p) > incrsize(p->left)) ! 298: cvtop: ! 299: pr("#\t%s%c%c\t%s,%s\n", pp, childtype(p), type(p), str(s), str(dest)); ! 300: else { /* types were the same, but dest.ans != 0 */ ! 301: pr("#\tmov%c\t%s,%s\n", type(p), str(s), str(dest)); ! 302: dest = simpler(s, dest); ! 303: } ! 304: dest.flag |= CC; ! 305: return(dest); ! 306: case Decr: ! 307: i = -1; ! 308: pp = "sub"; ! 309: incrop: ! 310: if(p->type == Tfloat) ! 311: uerror("no float ++/--"); ! 312: fieldbotch(p) ! 313: /* if the dest uses regs, it may be from a qnode, so that reg ! 314: * shouldn't be used (i?*a->b++:x()) where b has offset > 0 ! 315: */ ! 316: s = doit(p->left, USED, 0, dest.ans? regmask & ~dest.regmask: regmask); ! 317: if(s.flag & FAIL) ! 318: return(s); ! 319: t = doit(p->right, 0, 0, 0); ! 320: if(flag & VALUE) { ! 321: if(dest.ans == 0) ! 322: dest = allocreg(p, regmask & ~s.regmask); ! 323: pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(dest)); ! 324: if(t.flag & ICON1) { ! 325: if(i == 1) ! 326: pp = "inc"; ! 327: else ! 328: pp = "dec"; ! 329: pr("#\t%s%c\t%s\n", pp, childtype(p), str(s)); ! 330: } ! 331: else ! 332: pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), ! 333: str(t), str(s)); ! 334: toaddr: ! 335: if(flag & ASADDR) { ! 336: if(dest.flag & ISREG) { ! 337: sprintx(buf, "(%s)", str(dest)); ! 338: done(dest, CANINDIR, dest.regmask); ! 339: } ! 340: if(dest.flag & CANINDIR) { ! 341: sprintx(buf, "*%s", str(dest)); ! 342: done(dest, 0, dest.regmask); ! 343: } ! 344: uerror("weird asaddr in incrop"); ! 345: } ! 346: dest.flag &= ~CC; ! 347: return(dest); ! 348: } ! 349: if(t.flag & ICON1) { ! 350: if(i == 1) ! 351: pp = "inc"; ! 352: else ! 353: pp = "dec"; ! 354: pr("#\t%s%c\t%s\n", pp, childtype(p), str(s)); ! 355: } ! 356: else ! 357: pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), str(t), str(s)); ! 358: if(dest.ans) { ! 359: x = s; ! 360: goto movexdest; ! 361: } ! 362: s.flag &= ~CC; ! 363: return(s); ! 364: case Diveq: ! 365: fieldbotch(p) ! 366: if(rewriteasgop(p)) ! 367: goto assign; ! 368: flag |= DESTISLEFT; ! 369: case Div: ! 370: /* trees wrong: uns/=int and int/=uns */ ! 371: if(!isunsigned(p->right) && !isunsigned(p->left)) { ! 372: pp = "div"; ! 373: goto binop; ! 374: } ! 375: pp = "udiv"; ! 376: unsdiv: ! 377: /* *p++ /= uns is hard */ ! 378: if(p->left->op == Star && fixuns(p)) ! 379: longjmp(back, 1); /* *A op= B => (T=A, *T op= B) */ ! 380: if(incrsize(p->right) != 4) { ! 381: snode.op = Conv; ! 382: snode.left = p->right; ! 383: snode.type = Tulong; ! 384: s = doit(&snode, VALUE|TOSTACK, tostack(), regmask); ! 385: } ! 386: else ! 387: s = doit(p->right, TOSTACK, tostack(), regmask); ! 388: if(s.flag & FAIL) ! 389: return(s); ! 390: regmask &= ~s.regmask; ! 391: if(incrsize(p->left) != 4) { ! 392: snode.op = Conv; ! 393: snode.left = p->left; ! 394: snode.type = Tulong; ! 395: t = doit(&snode, VALUE|TOSTACK, tostack(), regmask); ! 396: } ! 397: else ! 398: t = doit(p->left, VALUE|TOSTACK, tostack(), regmask); ! 399: if(t.flag & FAIL) { ! 400: if(dest.ans || svmask != REGMASK) { ! 401: t = doit(p->left, VALUE|TOSTACK, tostack(), svmask); ! 402: if(t.flag & FAIL) ! 403: return(t); ! 404: } ! 405: totemp(p, RIGHT); ! 406: longjmp(back, 1); ! 407: } ! 408: i = 2; ! 409: goto aftercall; ! 410: case Xoreq: ! 411: fieldbotch(p) ! 412: flag |= DESTISLEFT; ! 413: case Xor: ! 414: pp = "xor"; ! 415: binop: ! 416: if((flag & DESTISLEFT) && dest.ans && p->left->op == Star) ! 417: longjmp(back, mediumstar(p)); ! 418: t = doit(p->left, VALUE|USED, 0, regmask); ! 419: if(t.flag & FAIL) { ! 420: return(t); ! 421: } ! 422: regmask &= ~t.regmask; ! 423: s = doit(p->right, VALUE|USED, 0, regmask); ! 424: if(s.flag & FAIL) { ! 425: binfail: ! 426: if(dest.ans || svmask != REGMASK) { ! 427: s = doit(p->right, VALUE|USED, 0, svmask); ! 428: if(s.flag & FAIL) ! 429: return(s); ! 430: } ! 431: /* *foo op= expr requires care */ ! 432: if((flag & DESTISLEFT) && p->left->op == Star) ! 433: totemp(p->left, LEFT); ! 434: else ! 435: totemp(p, LEFT); ! 436: longjmp(back, 1); ! 437: } ! 438: if(type(p) != childtype(p)) { ! 439: x = allocreg(p, regmask); ! 440: pr("#\t%s%c3\t%s,%s,%s\n", pp, childtype(p), str(s), ! 441: str(t), str(x)); ! 442: if(dest.ans == 0) ! 443: if(flag & DESTISLEFT) ! 444: dest = t; ! 445: else ! 446: dest = x; ! 447: if(!isfloat(p) && !isfloat(p->left) ! 448: && incrsize(p) < incrsize(p->left)) { ! 449: pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest)); ! 450: dest = simpler(x, dest); ! 451: } ! 452: else ! 453: pr("#\tcvt%c%c\t%s,%s\n", childtype(p), type(p), ! 454: str(x), str(dest)); ! 455: dest.flag |= CC; ! 456: return(dest); ! 457: } ! 458: if(dest.ans == 0) ! 459: if((t.flag & SCRATCH) || (flag & DESTISLEFT)) { ! 460: twoop: ! 461: dest = t; ! 462: if(*pp == 'a' && (s.flag & ICON1)) ! 463: pr("#\tinc%c\t%s\n", childtype(p), str(t)); ! 464: else if(*pp == 's' && (s.flag & ICON1)) ! 465: pr("#\tdec%c\t%s\n", childtype(p), str(t)); ! 466: else ! 467: pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), ! 468: str(s), str(t)); ! 469: if(flag & ASADDR) ! 470: goto binopaddr; ! 471: if(flag & TOSTACK) ! 472: pr("#\tpush%c\t%s\n", type(p), str(t)); ! 473: dest.flag |= CC; ! 474: return(dest); ! 475: } ! 476: else if(s.flag & SCRATCH) ! 477: dest = s; ! 478: else ! 479: dest = allocreg(p, regmask); ! 480: if(dest.ans && (flag & DESTISLEFT)) { ! 481: pr("#\t%s%c2\t%s,%s\n", pp, childtype(p), str(s), str(t)); ! 482: x = t; ! 483: goto movexdest; ! 484: } ! 485: if(commutes(p->op) && strcmp(str(s), str(dest)) == 0) { ! 486: dest = s; ! 487: s = t; ! 488: t = dest; ! 489: goto twoop; ! 490: } ! 491: if(strcmp(str(t), str(dest)) == 0) ! 492: goto twoop; ! 493: ! 494: pr("#\t%s%c3\t%s,%s,%s\n", pp, childtype(p), str(s), str(t), str(dest)); ! 495: binopaddr: ! 496: if(flag & ASADDR) { ! 497: if(dest.flag & ISREG) { ! 498: strcat(str(dest), ")"); ! 499: strshift(str(dest), 1); ! 500: str(dest)[0] = '('; ! 501: return(dest); ! 502: } ! 503: if(dest.flag & CANINDIR) { ! 504: strshift(str(dest), 1); ! 505: str(dest)[0] = '*'; ! 506: dest.flag &= ~CANINDIR; ! 507: return(dest); ! 508: } ! 509: debugpr("#FAIL doubtful "); ! 510: dest.flag = FAIL; /* doubtful */ ! 511: return(dest); ! 512: } ! 513: dest.flag |= CC; ! 514: return(dest); ! 515: case Fld: ! 516: /* this is rvalues */ ! 517: s = doit(p->left, USED, 0, regmask); ! 518: if(s.flag & FAIL) ! 519: return(s); ! 520: if(dest.ans == 0) ! 521: dest = allocreg(p, regmask); ! 522: if((s.flag & INDEX) && p->left->op == Star ! 523: && incrsize(p->left) != 1) { ! 524: /* over-enthusiastic use of index mode */ ! 525: if(dest.flag & SCRATCH) ! 526: x = dest; ! 527: else ! 528: x = allocreg(p, regmask); ! 529: pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(x)); ! 530: s = x; ! 531: } ! 532: pr("#\text%sv\t$%d,$%d,%s,%s\n", isunsigned(p->left)? "z": "", ! 533: p->rval/64, p->rval%64, str(s), str(dest)); ! 534: dest.flag |= CC; ! 535: return(dest); ! 536: case Genbr: ! 537: if(p->left->op == Conv) ! 538: s = doit(p->left->left, CC|VALUE|USED, 0, regmask); ! 539: /*else if(p->left->op == And && pow2(p->left->right->lval) > 0) { ! 540: s = doit(p->left->left, CC|VALUE, 0, regmask); ! 541: pp = genjbc(p->lop); ! 542: pr("#\t%s\t$%d,%s,L%d\n", pp, pow2(p->left->right->lval), ! 543: str(s), p->label); ! 544: goto genbr0; ! 545: } not a win on 8550 */ ! 546: else ! 547: s = doit(p->left, CC|VALUE|USED, 0, regmask); ! 548: pp = genjmp(p->lop); ! 549: if(s.flag & CC) ! 550: if(p->left->op != Conv || p->left->type >= Tint) ! 551: pr("#\t%s\t", pp); ! 552: else ! 553: pr("#\ttst%c\t%s\n\t%s\t", childtype(p), ! 554: str(s), pp); ! 555: else if(p->left->op == Conv) ! 556: pr("#\ttst%c\t%s\n#\t%s\t", childtype(p->left), str(s), pp); ! 557: else ! 558: pr("#\ttst%c\t%s\n#\t%s\t", childtype(p), str(s), pp); ! 559: pr("L%d\n", p->label); ! 560: genbr0: ! 561: s.flag |= CC; /* ?? */ ! 562: if(Pflag) { ! 563: ++bbcnt; ! 564: pr("#\tincl\tlocprof+%d\n", 4*(bbcnt+3)); ! 565: } ! 566: return(s); ! 567: case Genlab: ! 568: s = doit(p->left, flag, dest, regmask); ! 569: pr("#L%d:\n", p->label); ! 570: if(Pflag) { ! 571: ++bbcnt; ! 572: pr("#\tincl\tlocprof+%d\n", 4*(bbcnt+3)); ! 573: } ! 574: return(s); ! 575: case Genubr: ! 576: s = doit(p->left, flag & CC, dest, regmask); ! 577: if((flag & CC) && !(s.flag & CC)) ! 578: pr("#\ttst%c\t%s\n", childtype(p), str(s)); ! 579: pr("#\tjbr\tL%d\n", p->label); ! 580: return(s); ! 581: case Icon: ! 582: if(p->name) ! 583: if(p->lval) ! 584: sprintx(buf, "%s+%d", p->name, p->lval); ! 585: else ! 586: sprintx(buf, "%s", p->name); ! 587: else ! 588: sprintx(buf, "%d", p->lval); ! 589: if(!(flag & ASADDR)) { ! 590: strshift(buf, 1);; ! 591: buf[0] = '$'; ! 592: } ! 593: i = 0; ! 594: if(p->name == 0) ! 595: if(p->lval == 0) ! 596: i = ICON0; ! 597: else if(p->lval == 1) ! 598: i = ICON1; ! 599: j = 0; ! 600: convbuf: /* the cookie is in buf */ ! 601: if(dest.ans == 0 && !(flag & TOSTACK)) { ! 602: if(p->op == Icon || !(flag & ASADDR)) { ! 603: done(s, i, j); ! 604: } ! 605: if(i & CANINDIR) { ! 606: strshift(buf, 1); ! 607: buf[0] = '*'; ! 608: done(s, i & ~CANINDIR, j); ! 609: } ! 610: if(i & ISREG) { ! 611: strcat(buf, ")"); ! 612: strshift(buf, 1); ! 613: buf[0] = '('; ! 614: done(s, i, j); ! 615: } ! 616: pp = buf; ! 617: buf += BUF; ! 618: s = allocreg(p, regmask); ! 619: pr("#\tmov%c\t%s,%s\n", type(p), pp, str(s)); ! 620: flag &= ~ASADDR; ! 621: goto inreg; ! 622: } ! 623: if(flag & TOSTACK) ! 624: if(incrsize(p) == 4) ! 625: pr("#\tpushl\t%s\n", buf); ! 626: else if(incrsize(p) == 8) ! 627: pr("#\tmovd\t%s,%s\n", buf, str(dest)); ! 628: else ! 629: pr("#\tcvt%cl\t%s,%s\n", type(p), buf, str(dest)); ! 630: else if(i & ICON0) ! 631: pr("#\tclr%c\t%s\n", type(p), str(dest)); ! 632: else { ! 633: pr("#\tmov%c\t%s,%s\n", type(p), buf, str(dest)); ! 634: if(!(dest.flag & INDEX) || !index(str(dest), '+') ! 635: && !index(str(dest), '-')) ! 636: ; ! 637: else if(!(i & INDEX) || !index(buf, '+') ! 638: && !index(buf, '-')) { ! 639: done(s, (i|CC), j); ! 640: } ! 641: else ! 642: dest.flag |= USED; ! 643: } ! 644: dest.flag |= CC; ! 645: return(dest); ! 646: case Incr: ! 647: i = 1; ! 648: pp = "add"; ! 649: goto incrop; ! 650: case Init: /* knows it is ICON */ ! 651: s = doit(p->left, ASADDR, 0, 0); ! 652: pr("#\t.long\t%s\n", str(s)); ! 653: return(dest); ! 654: case Lseq: ! 655: if(incrsize(p) != 4) ! 656: lsconv(p); ! 657: if(rewriteasgop(p)) ! 658: goto assign; ! 659: fieldbotch(p) ! 660: flag |= DESTISLEFT; ! 661: if(dest.ans && p->left->op == Star) ! 662: longjmp(back, mediumstar(p)); ! 663: case Ls: /* stupid vax */ ! 664: if(incrsize(p) != 4) ! 665: lsconv(p); ! 666: s = doit(p->left, VALUE|USED, 0, regmask); ! 667: if(s.flag & FAIL) ! 668: return(s); ! 669: regmask &= ~s.regmask; ! 670: t = doit(p->right, VALUE|USED, 0, regmask); ! 671: if(t.flag & FAIL) ! 672: goto binfail; ! 673: if((t.flag & INDEX) && p->right->op == Star ! 674: && incrsize(p->right) != 1) { ! 675: /* over-enthusiastic use of index mode */ ! 676: if(dest.flag & SCRATCH) ! 677: x = dest; ! 678: else ! 679: x = allocreg(p, regmask); ! 680: pr("#\tmov%c\t%s,%s\n", childtype(p), str(t), str(x)); ! 681: t = x; ! 682: } ! 683: if(dest.ans == 0) ! 684: if((s.flag & SCRATCH) || (flag & DESTISLEFT)) ! 685: dest = s; ! 686: else ! 687: dest = allocreg(p, regmask); ! 688: if(incrsize(p) != 4) { /* stupid vax */ ! 689: x = allocreg(p, regmask); ! 690: pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(x)); ! 691: pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(dest)); ! 692: if(flag & DESTISLEFT) ! 693: pr("#\tmovl\t%s,%s\n", str(x), str(s)); ! 694: dest.flag |= CC; ! 695: return(dest); ! 696: } ! 697: if(p->right->op == Icon && (i = p->right->lval) <= 4 ! 698: && (dest.flag & ISREG) && !(s.flag&AUTO)) { ! 699: if(strcmp(str(s), str(dest))) { ! 700: i--; ! 701: pr("#\taddl3\t%s,%s,%s\n", str(s), str(s), str(dest)); ! 702: } ! 703: while(i-- > 0) ! 704: pr("#\taddl2\t%s,%s\n", str(dest), str(dest)); ! 705: } ! 706: else if(flag & DESTISLEFT) ! 707: pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(s)); ! 708: else ! 709: pr("#\tashl\t%s,%s,%s\n", str(t), str(s), str(dest)); ! 710: if((flag & DESTISLEFT) && strcmp(str(dest), str(s))) ! 711: pr("#\tmovl\t%s,%s\n", str(s), str(dest)); ! 712: dest.flag |= CC; ! 713: return(dest); ! 714: case Minuseq: ! 715: fieldbotch(p) ! 716: if(rewriteasgop(p)) ! 717: goto assign; ! 718: flag |= DESTISLEFT; ! 719: case Minus: ! 720: pp = "sub"; ! 721: /* you won't believe this: type x[], *y where type is shorter than ! 722: * int, generates subx $_x,y which the assembler barfs on. ! 723: * instead, generate crummy code (stupid assembler) ! 724: */ ! 725: if(incrsize(p) < 4) { ! 726: if(p->left->op == Icon && p->left->name) { ! 727: p->left->type = Tint; ! 728: totemp(p, LEFT); ! 729: } ! 730: if(p->right->op == Icon && p->right->name) { ! 731: p->right->type = Tint; ! 732: totemp(p, RIGHT); ! 733: } ! 734: } ! 735: goto binop; ! 736: case Modeq: ! 737: fieldbotch(p) ! 738: if(rewriteasgop(p)) ! 739: goto assign; ! 740: if(dest.ans && p->left->op == Star) ! 741: longjmp(back, mediumstar(p)); ! 742: flag |= DESTISLEFT; ! 743: case Mod: ! 744: if(isunsigned(p->right) || isunsigned(p->left)) { ! 745: pp = "urem"; ! 746: goto unsdiv; ! 747: } ! 748: s = doit(p->left, VALUE|USED, 0, regmask); ! 749: if(s.flag & FAIL) ! 750: return(s); ! 751: regmask &= ~s.regmask; ! 752: t = doit(p->right, VALUE|USED, 0, regmask); ! 753: if(t.flag & FAIL) ! 754: goto binfail; ! 755: regmask &= ~t.regmask; ! 756: x = allocreg(p, regmask); ! 757: pr("#\tdiv%c3\t%s,%s,%s\n", childtype(p), str(t), str(s), str(x)); ! 758: pr("#\tmul%c2\t%s,%s\n", childtype(p), str(t), str(x)); ! 759: pr("#\tsub%c3\t%s,%s,%s\n", childtype(p), str(x), str(s), str(x)); ! 760: if(dest.ans) ! 761: goto movexdest; ! 762: if(flag & DESTISLEFT) { ! 763: dest = s; ! 764: goto movexdest; ! 765: } ! 766: x.flag |= CC; ! 767: return(x); ! 768: case Muleq: ! 769: fieldbotch(p) ! 770: if(rewriteasgop(p)) ! 771: goto assign; ! 772: flag |= DESTISLEFT; ! 773: case Mul: ! 774: pp = "mul"; ! 775: goto binop; ! 776: case Name: /* ASADDR? */ ! 777: if(p->lval && p->name) ! 778: sprintx(buf, "%s+%d", p->name, p->lval); ! 779: else if(p->name) ! 780: sprintx(buf, "%s", p->name); ! 781: else if(p->lval) ! 782: sprintf(buf, "%d", p->lval); ! 783: else ! 784: sprintx(buf, "0"); ! 785: j = 0; ! 786: i = CANINDIR; ! 787: goto convbuf; ! 788: case Oreq: ! 789: fieldbotch(p) ! 790: flag |= DESTISLEFT; ! 791: case Or: ! 792: pp = "bis"; ! 793: goto binop; ! 794: case Pluseq: ! 795: fieldbotch(p) ! 796: if(rewriteasgop(p)) ! 797: goto assign; ! 798: flag |= DESTISLEFT; ! 799: case Plus: ! 800: pp = "add"; ! 801: goto binop; ! 802: case Reg: ! 803: sprintx(buf, "%s", regnames[p->rval]); ! 804: j = 0; ! 805: i = ISREG; ! 806: if(p->lval == 1) ! 807: i |= SCRATCH; ! 808: goto convbuf; ! 809: case Rnode: case Snode: ! 810: x = specialreg(p, 3); ! 811: x.regmask = 0; ! 812: if(dest.ans) ! 813: goto movexdest; ! 814: return(x); ! 815: case Qnode: ! 816: return(specialreg(p, regmask)); ! 817: case Rseq: ! 818: fieldbotch(p) ! 819: if(incrsize(p) != 4) ! 820: lsconv(p); ! 821: if(rewriteasgop(p)) ! 822: goto assign; ! 823: flag |= DESTISLEFT; ! 824: case Rs: /* all right shifts are unsigned */ ! 825: if(incrsize(p->left) != 4) /* shifting funny objects */ ! 826: lsconv(p); ! 827: s = doit(p->left, VALUE|USED, 0, regmask); ! 828: if(s.flag & FAIL) ! 829: return(s); ! 830: if(p->left->op == Icon || ! 831: (s.flag & INDEX) && p->left->op == Star ! 832: && incrsize(p->left) != 1 || ! 833: (s.flag & AUTO) && incrsize(p->left) != 1) { ! 834: /* over-enthusiastic use of index mode */ ! 835: /* 12 >> i generates a byte immediate */ ! 836: if((s.flag & INDEX) && (flag & DESTISLEFT)) {/* *a++ >>= 1 */ ! 837: lsconv(p); /* not best */ ! 838: longjmp(back, 1); ! 839: } ! 840: if((flag & DESTISLEFT) && dest.ans == 0) { ! 841: dest = s; ! 842: regmask &= ~s.regmask; ! 843: } ! 844: if(dest.flag & SCRATCH) ! 845: x = dest; ! 846: else ! 847: x = allocreg(p, regmask); ! 848: pr("#\tmovl\t%s,%s\n", str(s), str(x)); ! 849: s = x; ! 850: } ! 851: regmask &= ~s.regmask; ! 852: if(dest.ans == 0) ! 853: if((flag & DESTISLEFT) || (s.flag & SCRATCH)) ! 854: dest = s; ! 855: else ! 856: dest = allocreg(p, regmask); ! 857: dest.flag |= CC; ! 858: regmask &= ~dest.regmask; ! 859: if(incrsize(p) != 4) ! 860: x = allocreg(p, regmask); ! 861: else if(flag & DESTISLEFT) ! 862: x = s; ! 863: else ! 864: x = dest; ! 865: if(p->right->op == Icon && (i = p->right->lval) >= 0) { ! 866: pr("#\textzv\t$%d,$%d,%s,%s\n", i, 32 - i, str(s), str(x)); ! 867: goto movexdest; ! 868: } ! 869: t = doit(p->right, VALUE|USED, 0, regmask); ! 870: if(t.flag & FAIL) ! 871: goto binfail; ! 872: y = allocreg(p, regmask & ~t.regmask); ! 873: pr("#\tsubl3\t%s,$32,%s\n", str(t), str(y)); ! 874: pr("#\textzv\t%s,%s,%s,%s\n", str(t), str(y), str(s), str(x)); ! 875: goto movexdest; ! 876: case Star: ! 877: switch(p->left->op) { ! 878: case Icon: /* as in foo((a, a)), where a is a struct */ ! 879: s = doit(p->left, VALUE, 0, regmask); ! 880: sprintx(buf, "%s", str(s)+1); ! 881: i = j = 0; ! 882: goto convbuf; ! 883: case Auto: ! 884: case Param: ! 885: case Name: ! 886: s = doit(p->left, VALUE, 0, regmask); ! 887: sprintx(buf, "*%s", str(s)); ! 888: j = i = 0; ! 889: goto convbuf; ! 890: case Reg: ! 891: s = doit(p->left, VALUE, 0, regmask); ! 892: inreg: ! 893: if(s.flag & ISREG) { ! 894: sprintx(buf, "(%s)", str(s)); ! 895: j = s.regmask; ! 896: i = CANINDIR; ! 897: goto convbuf; ! 898: } ! 899: else if(s.flag & CANINDIR) { ! 900: sprintx(buf, "*%s", str(s)); ! 901: j = s.regmask; ! 902: i = 0; ! 903: goto convbuf; ! 904: } ! 905: else { ! 906: debugpr("#FAIL STAR REG "); ! 907: s.flag = FAIL; ! 908: return(s); ! 909: } ! 910: } ! 911: q = p->left; ! 912: if(q->op == Incr && !(flag & INDEX) ! 913: && q->right->op == Icon && q->left->op == Reg ! 914: && incrsize(p) == (int) q->right->lval) { ! 915: s = doit(q->left, VALUE, 0, regmask); ! 916: sprintx(buf, "(%s)+", str(s)); ! 917: i = INDEX|AUTO; ! 918: j = s.regmask; ! 919: goto convbuf; ! 920: } ! 921: if(q->op == Plus && q->left->op == Ls ! 922: && !(flag & INDEX) ! 923: && q->left->right->op == Icon ! 924: && shiftsize(p) == (int) q->left->right->lval) { ! 925: s = doit(q->left->left, VALUE|USED, 0, regmask); ! 926: if(s.flag & FAIL) ! 927: return(s); ! 928: regmask &= ~s.regmask; ! 929: if(!(s.flag & ISREG)) { ! 930: x = allocreg(p, regmask); ! 931: pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x)); ! 932: regmask |= s.regmask; ! 933: regmask &= ~x.regmask; ! 934: s = x; ! 935: if(!(s.flag & ISREG)) { ! 936: debugpr("#FAIL a[b] "); ! 937: s.flag = FAIL; ! 938: return(s); ! 939: } ! 940: } ! 941: t = doit(q->right, ASADDR|USED|VALUE, 0, regmask); ! 942: if(t.flag & FAIL) { ! 943: totemp(q, LEFT); ! 944: longjmp(back, 1); ! 945: } ! 946: sprintx(buf, "%s[%s]", str(t), str(s)); ! 947: i = INDEX; ! 948: j = s.regmask | t.regmask; ! 949: goto convbuf; ! 950: } ! 951: if(q->op == Plus && q->right->op == Icon) { ! 952: s = doit(q->left, VALUE|USED, 0, regmask); ! 953: if(s.flag & FAIL) ! 954: return(s); ! 955: if(!(s.flag & ISREG)) { ! 956: x = allocreg(p, regmask); ! 957: pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x)); ! 958: s = x; ! 959: if(!(s.flag & ISREG)) { ! 960: debugpr("#FAIL a(b) "); ! 961: s.flag = FAIL; ! 962: return(s); ! 963: } ! 964: } ! 965: regmask &= ~s.regmask; ! 966: t = doit(q->right, ASADDR|USED, 0, regmask); ! 967: sprintx(buf, "%s(%s)", str(t), str(s)); ! 968: i = CANINDIR; ! 969: j = s.regmask; ! 970: goto convbuf; ! 971: } ! 972: if(q->op == Minus && q->right->op == Icon) { ! 973: s = doit(q->left, VALUE|USED, 0, regmask); ! 974: if(s.flag & FAIL) ! 975: return(s); ! 976: if(!(s.flag & ISREG)) { ! 977: x = allocreg(p, regmask); ! 978: pr("#\tmov%c\t%s,%s\n", childtype(q), str(s), str(x)); ! 979: s = x; ! 980: if(!(s.flag & ISREG)) { ! 981: debugpr("#FAIL %d(a) "); ! 982: s.flag = FAIL; ! 983: return(s); ! 984: } ! 985: } ! 986: regmask &= ~s.regmask; ! 987: sprintx(buf, "%d(%s)", -q->right->lval, str(s)); ! 988: i = CANINDIR; ! 989: j = s.regmask; ! 990: goto convbuf; ! 991: } ! 992: if(q->op == Minuseq && !(flag & (INDEX|USED)) ! 993: && q->right->op == Icon && q->left->op == Reg ! 994: && incrsize(p) == (int) q->right->lval) { ! 995: s = doit(q->left, VALUE, 0, regmask); ! 996: sprintx(buf, "-(%s)", str(s)); ! 997: i = INDEX|AUTO; ! 998: j = s.regmask; ! 999: goto convbuf; ! 1000: } ! 1001: if(q->op == Plus && q->left->op == Reg ! 1002: && !(flag & INDEX) && q->right->op == Reg ! 1003: && incrsize(p) == 1) { ! 1004: sprintx(buf, "(r%d)[r%d]", q->right->rval, ! 1005: q->left->rval); ! 1006: i = INDEX; ! 1007: j = 0; ! 1008: goto convbuf; ! 1009: } ! 1010: s = doit(p->left, VALUE|USED, 0, regmask); ! 1011: if(s.flag & FAIL) ! 1012: return(s); ! 1013: regmask &= ~s.regmask; ! 1014: if(s.flag & CANINDIR) { ! 1015: sprintx(buf, "*%s", str(s)); ! 1016: i = 0; ! 1017: j = s.regmask; ! 1018: goto convbuf; ! 1019: } ! 1020: if(!(s.flag & ISREG)) { ! 1021: x = allocreg(p, regmask); ! 1022: pr("#\tmov%c\t%s,%s\n", type(q), str(s), str(x)); ! 1023: regmask |= s.regmask; ! 1024: regmask &= ~x.regmask; ! 1025: s = x; ! 1026: } ! 1027: if(!(s.flag & ISREG)) { ! 1028: debugpr("#FAIL STAR "); ! 1029: s.flag = FAIL; ! 1030: return(s); ! 1031: } ! 1032: sprintx(buf, "(%s)", str(s)); ! 1033: i = 0; ! 1034: j = s.regmask; ! 1035: goto convbuf; ! 1036: case Stasg: ! 1037: if(p->stsize/8 == 4) { ! 1038: i = 'l'; ! 1039: stasg: ! 1040: s = doit(p->left, VALUE|ASADDR|USED|FSTASG, 0, regmask); ! 1041: if(s.flag & FAIL) ! 1042: return(s); ! 1043: regmask &= ~s.regmask; ! 1044: t = doit(p->right, VALUE|ASADDR|USED|FSTASG, 0, regmask); ! 1045: if(t.flag & FAIL) { ! 1046: t = doit(p->right, VALUE|ASADDR|USED|FSTASG, 0, REGMASK); ! 1047: if(!(t.flag & FAIL) && svmask != REGMASK) ! 1048: return(t.flag = FAIL, t); ! 1049: totemp(p, LEFT); ! 1050: longjmp(back, 1); ! 1051: } ! 1052: pr("#\tmov%c\t%s,%s\n", i, str(t), str(s)); ! 1053: if(!(flag & FSTASG)) ! 1054: s = addrsimp(s, t); ! 1055: return(s); ! 1056: } ! 1057: else if(p->stsize/8 == 8) { ! 1058: i = 'q'; ! 1059: goto stasg; ! 1060: } ! 1061: if(regmask != REGMASK) { ! 1062: debugpr("#FAIL stasg "); ! 1063: s.flag = FAIL; ! 1064: return(s); ! 1065: } ! 1066: s = doit(p->right, VALUE|USED|FSTASG, 0, regmask); ! 1067: if(s.flag & INDEX) { ! 1068: /* over-enthusiastic use of index mode */ ! 1069: x = allocreg(p, regmask); ! 1070: pr("#\tmovl\t%s,%s\n", str(s), str(x)); ! 1071: s = x; ! 1072: } ! 1073: regmask &= ~s.regmask; ! 1074: t = doit(p->left, VALUE|USED|FSTASG, 0, regmask); ! 1075: if(t.flag & FAIL) { ! 1076: totemp(p, RIGHT); ! 1077: longjmp(back, 1); ! 1078: } ! 1079: if(t.flag & INDEX) { ! 1080: /* over-enthusiastic use of index mode */ ! 1081: x = allocreg(p, regmask); ! 1082: pr("#\tmovl\t%s,%s\n", str(t), str(x)); ! 1083: t = x; ! 1084: } ! 1085: t = indirit(t); ! 1086: if(t.flag & FAIL) { ! 1087: if(p->left->op != Star) ! 1088: cerror("codegen failure in struct asg"); ! 1089: totemp(p->left, LEFT); ! 1090: longjmp(back, 1); ! 1091: } ! 1092: s = indirit(s); ! 1093: if(s.flag & FAIL) { ! 1094: if(p->right->op != Star) ! 1095: cerror("codgen fail in stasg"); ! 1096: totemp(p->right, LEFT); ! 1097: longjmp(back, 1); ! 1098: } ! 1099: pr("#\tmovc3\t$%d,%s,%s\n", p->stsize/8, str(s), str(t)); ! 1100: if(flag & USED) { ! 1101: t = specialreg(p, REGMASK); ! 1102: pr("#\tsubl3\t$%d,r3,r0\n", p->stsize/8); ! 1103: } ! 1104: else ! 1105: t.flag = 0; ! 1106: return(t); ! 1107: case Stcall: ! 1108: goto call; ! 1109: case Auto: ! 1110: sprintx(buf, "%d(%s)", p->lval, frameptr); ! 1111: j = 0; ! 1112: i = CANINDIR; ! 1113: goto convbuf; ! 1114: case Param: ! 1115: sprintx(buf, "%d(%s)", p->lval, argptr); ! 1116: j = 0; ! 1117: i = CANINDIR; ! 1118: goto convbuf; ! 1119: case Addr: ! 1120: s = doit(p->left, USED, 0, regmask); ! 1121: if(s.flag & FAIL) ! 1122: return(s); ! 1123: regmask &= ~s.regmask; ! 1124: if(dest.ans == 0) { ! 1125: dest = allocreg(p, regmask); ! 1126: } ! 1127: if(s.flag & ISREG) { ! 1128: x = alloctmp(p); ! 1129: pr("#\tmov%c\t%s,%s\n", childtype(p), str(s), str(x)); ! 1130: s = x; ! 1131: } ! 1132: if(flag & TOSTACK) ! 1133: pr("#\tpushal\t%s\n", str(s)); ! 1134: else ! 1135: pr("#\tmova%c\t%s,%s\n", type(p), str(s), str(dest)); ! 1136: if(flag & ASADDR) { ! 1137: if(dest.flag & ISREG) { ! 1138: strcat(str(dest), ")"); ! 1139: strshift(str(dest), 1); ! 1140: str(dest)[0] = '('; ! 1141: } ! 1142: else { ! 1143: strshift(str(dest), 1); ! 1144: str(dest)[0] = '*'; ! 1145: } ! 1146: } ! 1147: return(dest); ! 1148: case Ucall: ! 1149: i = 0; ! 1150: goto called; ! 1151: case Uminus: ! 1152: s = doit(p->left, VALUE|USED, 0, regmask); ! 1153: if(s.flag & FAIL) ! 1154: return(s); ! 1155: if(dest.ans == 0) ! 1156: if(s.flag & SCRATCH) ! 1157: dest = s; ! 1158: else ! 1159: dest = allocreg(p, regmask & ~s.regmask); ! 1160: pr("#\tmneg%c\t%s,%s\n", childtype(p), str(s), str(dest)); ! 1161: dest.flag |= CC; ! 1162: return(dest); ! 1163: case Ustcall: ! 1164: i = 0; ! 1165: goto called; ! 1166: case Asg: ! 1167: assign: ! 1168: if(p->left->op == Qnode && dest.ans) { ! 1169: s = doit(p->right, VALUE|(flag&USED? USED: 0), ! 1170: dest, regmask); ! 1171: return(s); ! 1172: } ! 1173: if(p->left->op == Rnode || p->left->op == Snode) { ! 1174: s = doit(p->right, VALUE|(flag&USED? USED: 0), ! 1175: dest, regmask); ! 1176: if(s.flag & FAIL) ! 1177: return(s); ! 1178: x = s; ! 1179: dest = doit(p->left, USED, 0, 0); ! 1180: goto movexdest; ! 1181: } ! 1182: if(p->left->op == Fld) { ! 1183: s = doit(p->left->left, INDEX, 0, regmask); ! 1184: regmask &= ~s.regmask; ! 1185: if(p->right->op == Asg) { ! 1186: x = allocreg(p->right, regmask); ! 1187: t = doit(p->right, VALUE|USED, x, regmask & ~x.regmask); ! 1188: } ! 1189: else ! 1190: t = doit(p->right, VALUE|USED, 0, regmask); ! 1191: if(t.flag & FAIL) { /* was fldstar */ ! 1192: totemp(p->left->left, LEFT); ! 1193: totemp(p, RIGHT); ! 1194: longjmp(back, 1); ! 1195: } ! 1196: i = '$'; ! 1197: pr("#\tinsv\t%s,%c%d,%c%d,%s\n", str(t), i, ! 1198: p->left->rval/64, i, ! 1199: p->left->rval % 64, str(s)); ! 1200: if(dest.ans) { ! 1201: pr("#\tmovl\t%s,%s\n", str(t), str(dest)); ! 1202: t.flag |= CC; ! 1203: } ! 1204: return(t); ! 1205: } ! 1206: if(dest.ans && p->left->op == Star) { ! 1207: if(dest.flag & SCRATCH) ! 1208: x = dest; ! 1209: else ! 1210: x = allocreg(p, regmask); ! 1211: s = doit(p->right, VALUE|USED, x, regmask); ! 1212: if(s.flag & FAIL) ! 1213: return(s); ! 1214: regmask &= ~s.regmask; ! 1215: t = doit(p->left, USED, 0, regmask); ! 1216: if(t.flag & FAIL) { ! 1217: /* did we fail because of a dest, or was it us? */ ! 1218: if(dest.ans || svmask != REGMASK) { ! 1219: t = doit(p->left, USED, 0, svmask); ! 1220: if(t.flag & FAIL) { ! 1221: return(t); ! 1222: } ! 1223: starasg(p); ! 1224: } ! 1225: else ! 1226: asgwrite(p); ! 1227: longjmp(back, 1); ! 1228: } ! 1229: pr("#\tmov%c\t%s,%s\n", type(p), str(x), str(t)); ! 1230: if(strcmp(str(x), str(dest)) == 0) { ! 1231: dest.flag |= CC; ! 1232: return(dest); ! 1233: } ! 1234: goto movexdest; ! 1235: } ! 1236: if(p->right->op == Fld && incrsize(p) != 4) { ! 1237: /* ext sets whole word */ ! 1238: asgwrite(p); ! 1239: p->left->type = isunsigned(p)? Tuint: Tint; ! 1240: longjmp(back, 1); ! 1241: } ! 1242: t = doit(p->left, USED, 0, regmask); ! 1243: regmask &= ~t.regmask; ! 1244: if(p->right->op == Genlab || p->right->op == Comop) ! 1245: extracheck(p); /* slightly worse code in usual case */ ! 1246: s = doit(p->right, VALUE, t, regmask); /* VALUE is't right: ! 1247: register char *a, *b; return((*a++ = *b++ | 40) != 3); */ ! 1248: if(s.flag & NOGOOD) { ! 1249: /* did we fail because of a dest, or was it us? */ ! 1250: if(s.flag & FAIL) { ! 1251: if(dest.ans || svmask != REGMASK) { ! 1252: s = doit(p->right, VALUE, t, svmask); ! 1253: if(s.flag & FAIL) { ! 1254: return(s); ! 1255: } ! 1256: } ! 1257: asgwrite(p); ! 1258: longjmp(back, 1); ! 1259: } ! 1260: else if((flag & USED) && !((flag & CC) && (s.flag & CC))) { ! 1261: /* presumably USED as in *p++=*q++ */ ! 1262: totemp(p, RIGHT); ! 1263: longjmp(back, 1); ! 1264: } ! 1265: } ! 1266: if(dest.ans) { ! 1267: x = s; ! 1268: goto movexdest; ! 1269: } ! 1270: else if(flag & ASADDR) { ! 1271: i = (s.flag & (ISREG|CANINDIR|SCRATCH)); ! 1272: j = s.regmask; ! 1273: buf = str(s); ! 1274: goto convbuf; ! 1275: } ! 1276: return(s); ! 1277: } ! 1278: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.