|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <ctype.h> ! 5: #define Extern extern ! 6: #include "parl.h" ! 7: #include "globl.h" ! 8: ! 9: /* These are machine specific convs which generate no code */ ! 10: ulong ! 11: nopconv[Ntype] = ! 12: { ! 13: 0, /* TXXX */ ! 14: MINT|MUINT|MIND, /* TINT */ ! 15: MINT|MUINT|MIND, /* TUINT */ ! 16: MSINT|MSUINT, /* TSINT */ ! 17: MSINT|MSUINT, /* TSUINT */ ! 18: MCHAR, /* TCHAR */ ! 19: MFLOAT, /* TFLOAT */ ! 20: MINT|MUINT|MIND, /* TIND */ ! 21: 0, /* TCHANNEL */ ! 22: 0, /* TARRAY */ ! 23: MAGGREGATE, /* TAGGREGATE */ ! 24: MUNION, /* TUNION */ ! 25: 0, /* TFUNC */ ! 26: 0, /* TVOID */ ! 27: TADT, /* TADT */ ! 28: }; ! 29: ! 30: Inst* ! 31: ai(void) ! 32: { ! 33: Inst *i; ! 34: ! 35: i = malloc(sizeof(Inst)); ! 36: i->src1.type = A_NONE; ! 37: i->dst.type = A_NONE; ! 38: i->reg = Nreg; ! 39: i->next = 0; ! 40: i->lineno = iline; ! 41: return i; ! 42: } ! 43: ! 44: /* Emit an assembler instruction */ ! 45: Inst* ! 46: instruction(int op, Node *s1, Node *s2, Node *dst) ! 47: { ! 48: Inst *i; ! 49: ! 50: i = ai(); ! 51: i->op = op; ! 52: i->pc = pc++; ! 53: ! 54: if(s1) ! 55: mkaddr(s1, &i->src1, 1); ! 56: ! 57: if(s2 && s2 != dst) { ! 58: switch(s2->type) { ! 59: case OREGISTER: ! 60: break; ! 61: case OCONST: ! 62: if(s2->ival == 0) { ! 63: s2->reg = 0; ! 64: break; ! 65: } ! 66: /* Fall */ ! 67: default: ! 68: fatal("inst %s %N,%N,%N", itab[op], s1, s2, dst); ! 69: } ! 70: if(s2->t->type == TFLOAT) ! 71: i->reg = s2->reg - Freg; ! 72: else ! 73: i->reg = s2->reg; ! 74: } ! 75: ! 76: if(dst) { ! 77: mkaddr(dst, &i->dst, 1); ! 78: if(i->dst.type == A_REG) ! 79: if(i->reg == i->dst.reg) ! 80: i->reg = Nreg; ! 81: } ! 82: ilink(i); ! 83: return ipc; ! 84: } ! 85: ! 86: void ! 87: ilink(Inst *i) ! 88: { ! 89: if(opt('c')) ! 90: print("(%d)%i\n", i->lineno, i); ! 91: ! 92: if(proghead) ! 93: ipc->next = i; ! 94: else ! 95: proghead = i; ! 96: ! 97: ipc = i; ! 98: } ! 99: ! 100: /* Back patch a branch */ ! 101: void ! 102: label(Inst *i, ulong pc) ! 103: { ! 104: Adres *a; ! 105: ! 106: switch(i->op) { ! 107: case ABA: ! 108: case ABCC: ! 109: case ABCS: ! 110: case ABE: ! 111: case ABG: ! 112: case ABGE: ! 113: case ABGU: ! 114: case ABL: ! 115: case ABLE: ! 116: case ABLEU: ! 117: case ABN: ! 118: case ABNE: ! 119: case ABNEG: ! 120: case ABPOS: ! 121: case ABVC: ! 122: case ABVS: ! 123: case AJMPL: ! 124: case AJMP: ! 125: case AFBA: ! 126: case AFBE: ! 127: case AFBG: ! 128: case AFBGE: ! 129: case AFBL: ! 130: case AFBLE: ! 131: case AFBLG: ! 132: case AFBN: ! 133: case AFBNE: ! 134: case AFBO: ! 135: case AFBU: ! 136: case AFBUE: ! 137: case AFBUG: ! 138: case AFBUGE: ! 139: case AFBUL: ! 140: case AFBULE: ! 141: break; ! 142: ! 143: default: ! 144: fatal("label not branch"); ! 145: } ! 146: a = &i->dst; ! 147: a->type = A_BRANCH; ! 148: a->ival = pc; ! 149: } ! 150: ! 151: /* Select code for arithmetic operations */ ! 152: void ! 153: codmop(Node *o, Node *l, Node *r, Node *dst) ! 154: { ! 155: int op; ! 156: ! 157: op = AGOK; ! 158: switch(o->type) { ! 159: case OADD: ! 160: case OADDEQ: ! 161: switch(o->t->type) { ! 162: default: ! 163: op = AADD; ! 164: break; ! 165: case TFLOAT: ! 166: op = AFADDD; ! 167: break; ! 168: } ! 169: break; ! 170: ! 171: case OSUB: ! 172: case OSUBEQ: ! 173: switch(o->t->type) { ! 174: default: ! 175: op = ASUB; ! 176: break; ! 177: case TFLOAT: ! 178: op = AFSUBD; ! 179: break; ! 180: } ! 181: break; ! 182: ! 183: case OMUL: ! 184: case OMULEQ: ! 185: switch(o->t->type) { ! 186: default: ! 187: op = AMUL; ! 188: break; ! 189: case TFLOAT: ! 190: op = AFMULD; ! 191: break; ! 192: } ! 193: break; ! 194: ! 195: case ODIV: ! 196: case ODIVEQ: ! 197: switch(o->t->type) { ! 198: default: ! 199: op = ADIV; ! 200: break; ! 201: case TUINT: ! 202: case TSUINT: ! 203: op = ADIVL; ! 204: break; ! 205: case TFLOAT: ! 206: op = AFDIVD; ! 207: break; ! 208: } ! 209: break; ! 210: ! 211: case OMOD: ! 212: case OMODEQ: ! 213: switch(o->t->type) { ! 214: default: ! 215: op = AMOD; ! 216: break; ! 217: case TUINT: ! 218: case TSUINT: ! 219: op = AMODL; ! 220: break; ! 221: } ! 222: break; ! 223: ! 224: case OALSH: ! 225: case OLSH: ! 226: case OLSHEQ: ! 227: op = ASLL; ! 228: break; ! 229: ! 230: case ORSH: ! 231: case ORSHEQ: ! 232: op = ASRL; ! 233: break; ! 234: ! 235: case OXOR: ! 236: case OXOREQ: ! 237: op = AXOR; ! 238: break; ! 239: ! 240: case OLOR: ! 241: case OOREQ: ! 242: op = AOR; ! 243: break; ! 244: ! 245: case OLAND: ! 246: case OANDEQ: ! 247: op = AAND; ! 248: break; ! 249: ! 250: case OARSH: ! 251: op = ASRA; ! 252: break; ! 253: } ! 254: instruction(op, l, r, dst); ! 255: } ! 256: ! 257: int ! 258: mulcon(Node *n, Node *nn) ! 259: { ! 260: int o; ! 261: long v; ! 262: Multab *m; ! 263: Node *l, *r, nod1, nod2, mop; ! 264: char code[sizeof(m->code)+2], *p; ! 265: ! 266: if(n->t->type == TFLOAT) ! 267: return 0; ! 268: ! 269: mop.t = n->t; ! 270: l = n->left; ! 271: r = n->right; ! 272: if(l->type == OCONST) { ! 273: l = r; ! 274: r = n->left; ! 275: } ! 276: if(r->type != OCONST) ! 277: return 0; ! 278: ! 279: v = r->ival; ! 280: m = mulcon0(v); ! 281: if(!m) { ! 282: if(opt('M')) ! 283: print("%L multiply table: %lld\n", r->ival); ! 284: return 0; ! 285: } ! 286: if(opt('M')) ! 287: print("%L multiply: %ld\n", v); ! 288: ! 289: memmove(code, m->code, sizeof(m->code)); ! 290: code[sizeof(m->code)] = 0; ! 291: ! 292: p = code; ! 293: if(p[1] == 'i') ! 294: p += 2; ! 295: reg(&nod1, n->t, nn); ! 296: genexp(l, &nod1); ! 297: if(v < 0) { ! 298: mop.type = OSUB; ! 299: codmop(&mop, &nod1, con(0), &nod1); ! 300: } ! 301: reg(&nod2, n->t, ZeroN); ! 302: ! 303: for(;;) { ! 304: switch(*p) { ! 305: case '\0': ! 306: regfree(&nod2); ! 307: assign(&nod1, nn); ! 308: regfree(&nod1); ! 309: return 1; ! 310: case '+': ! 311: o = OADD; ! 312: goto addsub; ! 313: case '-': ! 314: o = OSUB; ! 315: addsub: /* number is r,n,l */ ! 316: v = p[1] - '0'; ! 317: r = &nod1; ! 318: if(v&4) ! 319: r = &nod2; ! 320: n = &nod1; ! 321: if(v&2) ! 322: n = &nod2; ! 323: l = &nod1; ! 324: if(v&1) ! 325: l = &nod2; ! 326: mop.type = o; ! 327: codmop(&mop, l, n, r); ! 328: break; ! 329: default: /* op is shiftcount, number is r,l */ ! 330: v = p[1] - '0'; ! 331: r = &nod1; ! 332: if(v&2) ! 333: r = &nod2; ! 334: l = &nod1; ! 335: if(v&1) ! 336: l = &nod2; ! 337: v = *p - 'a'; ! 338: if(v < 0 || v >= 32) { ! 339: diag(n, "mulcon unknown op: %c%c", p[0], p[1]); ! 340: break; ! 341: } ! 342: mop.type = OALSH; ! 343: codmop(&mop, con(v), l, r); ! 344: break; ! 345: } ! 346: p += 2; ! 347: } ! 348: return 0; ! 349: } ! 350: ! 351: int ! 352: vconst(Node *n) ! 353: { ! 354: int i; ! 355: ! 356: if(n == ZeroN || n->type != OCONST || n->t == ZeroT) ! 357: return -159; ! 358: ! 359: switch(n->t->type) { ! 360: case TFLOAT: ! 361: i = 100; ! 362: if(n->fval > i || n->fval < -i) ! 363: return -159; ! 364: i = n->fval; ! 365: if(i != n->fval) ! 366: return -159; ! 367: return i; ! 368: ! 369: case TCHAR: ! 370: case TSINT: ! 371: case TSUINT: ! 372: case TINT: ! 373: case TUINT: ! 374: case TIND: ! 375: i = n->ival; ! 376: if(i != n->ival) ! 377: return -159; ! 378: return i; ! 379: } ! 380: } ! 381: ! 382: /* Select code for conditional operators */ ! 383: void ! 384: codcond(int comp, Node *src1, Node *src2) ! 385: { ! 386: int a, t; ! 387: ! 388: if(src1->type == OCONST) ! 389: if(src1->ival == 0) ! 390: if(src1->t->type != TFLOAT) ! 391: src1 = regn(0); ! 392: ! 393: if(src2->type == OCONST) ! 394: if(src2->ival == 0) ! 395: if(src2->t->type != TFLOAT) ! 396: src2 = regn(0); ! 397: ! 398: t = src1->t->type; ! 399: switch(comp) { ! 400: default: ! 401: fatal("codcond: %N %s %N", src1, treeop[comp]+1, src2); ! 402: ! 403: case OEQ: ! 404: a = ABE; ! 405: if(t == TFLOAT) ! 406: a = AFBE; ! 407: break; ! 408: ! 409: case ONEQ: ! 410: a = ABNE; ! 411: if(t == TFLOAT) ! 412: a = AFBNE; ! 413: break; ! 414: ! 415: case OLT: ! 416: a = ABL; ! 417: if(t == TFLOAT) ! 418: a = AFBL; ! 419: break; ! 420: ! 421: case OGT: ! 422: a = ABG; ! 423: if(t == TFLOAT) ! 424: a = AFBG; ! 425: break; ! 426: ! 427: case OLEQ: ! 428: a = ABLE; ! 429: if(t == TFLOAT) ! 430: a = AFBLE; ! 431: break; ! 432: ! 433: case OGEQ: ! 434: a = ABGE; ! 435: if(t == TFLOAT) ! 436: a = AFBGE; ! 437: break; ! 438: ! 439: case OLO: ! 440: a = ABCS; ! 441: break; ! 442: ! 443: case OHI: ! 444: a = ABGU; ! 445: break; ! 446: ! 447: case OLOS: ! 448: a = ABLEU; ! 449: break; ! 450: ! 451: case OHIS: ! 452: a = ABCC; ! 453: break; ! 454: } ! 455: ! 456: if(t == TFLOAT) ! 457: instruction(AFCMPD,src1, ZeroN, src2); ! 458: else ! 459: instruction(ACMP, src1, ZeroN, src2); ! 460: ! 461: instruction(a, ZeroN, ZeroN, ZeroN); ! 462: } ! 463: ! 464: void ! 465: mkdata(Node *n, int off, int size, Inst *i) ! 466: { ! 467: Adres *a; ! 468: ! 469: if(n->type != ONAME) ! 470: fatal("mkdata %N\n", n); ! 471: ! 472: a = &i->src1; ! 473: ! 474: a->reg = Nreg; ! 475: a->ival = off; ! 476: a->sym = n->sym; ! 477: a->type = A_INDREG; ! 478: a->class = n->t->class; ! 479: a->etype = n->t->type; ! 480: ! 481: i->reg = size; ! 482: } ! 483: ! 484: void ! 485: mkaddr(Node *n, Adres *a, int ur0) ! 486: { ! 487: long o; ! 488: Tinfo *ti; ! 489: ! 490: a->sym = ZeroS; ! 491: a->reg = Nreg; ! 492: ! 493: switch(n->type) { ! 494: default: ! 495: fatal("mkaddr: %N\n", n); ! 496: ! 497: case ONAME: ! 498: ti = n->ti; ! 499: ! 500: a->type = A_INDREG; ! 501: a->etype = ti->t->type; ! 502: a->ival = ti->offset; ! 503: a->sym = n->sym; ! 504: if(ti->class == Argument) { ! 505: a->reg = RegSP; ! 506: a->class = A_NONE; ! 507: break; ! 508: } ! 509: a->class = ti->class; ! 510: break; ! 511: ! 512: case OCONST: ! 513: switch(n->t->type) { ! 514: default: ! 515: if(ur0 && n->ival == 0) { ! 516: a->type = A_REG; ! 517: a->reg = 0; ! 518: break; ! 519: } ! 520: a->type = A_CONST; ! 521: a->ival = n->ival; ! 522: break; ! 523: case TFLOAT: ! 524: a->type = A_FCONST; ! 525: a->fval = n->fval; ! 526: break; ! 527: } ! 528: break; ! 529: ! 530: case OADD: ! 531: if(n->left->type == OCONST) { ! 532: mkaddr(n->left, a, 0); ! 533: o = a->ival; ! 534: mkaddr(n->right, a, 1); ! 535: } ! 536: else { ! 537: mkaddr(n->right, a, 0); ! 538: o = a->ival; ! 539: mkaddr(n->left, a, 1); ! 540: } ! 541: a->ival += o; ! 542: break; ! 543: ! 544: case OINDREG: ! 545: a->type = A_INDREG; ! 546: a->reg = n->reg; ! 547: a->ival = n->ival; ! 548: break; ! 549: ! 550: case OREGISTER: ! 551: a->type = A_REG; ! 552: switch(n->t->type) { ! 553: default: ! 554: a->reg = n->reg; ! 555: break; ! 556: ! 557: case TFLOAT: ! 558: a->type = A_FREG; ! 559: if(n->reg == Retfreg) ! 560: a->reg = Retfregno; ! 561: else ! 562: a->reg = n->reg - Freg; ! 563: break; ! 564: } ! 565: break; ! 566: ! 567: case OIND: ! 568: mkaddr(n->left, a, 1); ! 569: if(a->type == A_REG || a->type == A_CONST) ! 570: a->type = A_INDREG; ! 571: break; ! 572: ! 573: case OADDR: ! 574: mkaddr(n->left, a, 1); ! 575: a->type = A_CONST; ! 576: a->ival += n->ival; ! 577: break; ! 578: } ! 579: } ! 580: ! 581: /* Generate function preamble and assign parameter offsets */ ! 582: void ! 583: preamble(Node *name) ! 584: { ! 585: Inst *i; ! 586: Node *n; ! 587: ! 588: i = ai(); ! 589: i->op = ATEXT; ! 590: i->pc = pc++; ! 591: i->lineno = name->srcline; ! 592: ! 593: n = an(0, ZeroN, ZeroN); ! 594: *n = *name; ! 595: n->type = ONAME; ! 596: mkaddr(n, &i->src1, 0); ! 597: mkaddr(con(0), &i->dst, 0); ! 598: ilink(i); ! 599: funentry = i; /* To back patch arg space */ ! 600: becomentry = i; ! 601: } ! 602: ! 603: /* Output accumulated string constants */ ! 604: void ! 605: strop(void) ! 606: { ! 607: String *s; ! 608: int c, l; ! 609: Inst *i; ! 610: char *p; ! 611: ! 612: for(s = strdat; s; s = s->next) { ! 613: i = ai(); ! 614: i->op = AGLOBL; ! 615: mkaddr(&s->n, &i->src1, 0); ! 616: mkaddr(con(s->len), &i->dst, 0); ! 617: ilink(i); ! 618: ! 619: c = 0; ! 620: p = s->string; ! 621: while(s->len) { ! 622: l = s->len; ! 623: if(l > 8) ! 624: l = 8; ! 625: ! 626: iline = s->n.srcline; ! 627: i = ai(); ! 628: i->op = ADATA; ! 629: i->dst.type = A_STRING; ! 630: memset(i->dst.str, 0, sizeof(i->dst.str)); ! 631: memmove(i->dst.str, p, l); ! 632: s->len -= l; ! 633: mkdata(&s->n, c, l, i); ! 634: p += l; ! 635: c += l; ! 636: ilink(i); ! 637: } ! 638: } ! 639: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.