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