|
|
1.1 ! root 1: /* C compiler: MIPS code generator */ ! 2: ! 3: #include "c.h" ! 4: ! 5: static Symbol f0, ireg[32], d4, d6, f12, f14; ! 6: ! 7: static int flabel; ! 8: int gnum = 8; ! 9: char *nrflag = ""; ! 10: int framesize; ! 11: ! 12: dclproto(static void addr,(Symbol, Symbol, int)); ! 13: dclproto(static void funcsave,(int, int, int, int, unsigned, unsigned, int)); ! 14: dclproto(static void storearg,(Symbol, Symbol, Symbol)); ! 15: dclproto(static unsigned a_def,(Symbol)); ! 16: dclproto(static void a_defaddress,(Symbol)); ! 17: dclproto(static unsigned a_emit,(unsigned, int, int, int, int)); ! 18: dclproto(static void a_end,(Symbol)); ! 19: dclproto(static void a_entry,(Symbol, int, int)); ! 20: dclproto(static int a_offset,(int)); ! 21: dclproto(static void a_symbol,(int, Symbol)); ! 22: dclproto(static void a_word,(unsigned, int)); ! 23: ! 24: dclproto(static void address,(Symbol, Symbol, int)); ! 25: dclproto(static void blkfetch,(int, int, int, int)); ! 26: dclproto(static void blkloop,(int, int, int, int, int, int[])); ! 27: dclproto(static void blkstore,(int, int, int, int)); ! 28: dclproto(static void defaddress,(Symbol)); ! 29: dclproto(static void defconst,(int, Value)); ! 30: dclproto(static void defstring,(int, char *)); ! 31: dclproto(static void defsymbol,(Symbol)); ! 32: dclproto(static void doarg,(Node)); ! 33: dclproto(static void emitspecial,(Node)); ! 34: dclproto(static void function,(Symbol, Symbol [], Symbol [], int)); ! 35: dclproto(static void global,(Symbol)); ! 36: dclproto(static void import,(Symbol)); ! 37: dclproto(static void local,(Symbol)); ! 38: dclproto(static void progbeg,(int, char **)); ! 39: dclproto(static void segment,(int)); ! 40: dclproto(static void space,(int)); ! 41: ! 42: dclproto(static void stabinit,(char *, int, char *[])); ! 43: dclproto(static void stabline,(Coordinate *)); ! 44: dclproto(static void stabsym,(Symbol)); ! 45: ! 46: dclproto(static void initgen,(void)); ! 47: dclproto(static void final,(Node)); ! 48: ! 49: #ifdef GEN4 ! 50: dclproto(static unsigned emit2,(Node,Node[],short[])); ! 51: dclproto(static void target,(Node)); ! 52: #endif ! 53: ! 54: struct emit put = { ! 55: setseg, ! 56: spacen, ! 57: genascii, ! 58: a_emit, ! 59: addr, ! 60: a_def, ! 61: a_defaddress, ! 62: a_end, ! 63: a_entry, ! 64: a_offset, ! 65: a_symbol, ! 66: a_word ! 67: }; ! 68: ! 69: Interface mipsInterface = { ! 70: "mips", ! 71: 1, 1, 0, /* char */ ! 72: 2, 2, 0, /* short */ ! 73: 4, 4, 0, /* int */ ! 74: 4, 4, 1, /* float */ ! 75: 8, 8, 1, /* double */ ! 76: 4, 4, 0, /* T * */ ! 77: 0, 1, 0, /* struct */ ! 78: 1, /* left_to_right */ ! 79: 0, /* little_endian */ ! 80: 1, /* jump_on_return */ ! 81: 0, /* mulops_are_calls */ ! 82: 0, /* compl_band */ ! 83: 0, /* no_argb */ ! 84: NODAG, /* no_dag */ ! 85: address, ! 86: blockbeg, ! 87: blockend, ! 88: defaddress, ! 89: defconst, ! 90: defstring, ! 91: defsymbol, ! 92: 0, ! 93: export, ! 94: function, ! 95: gen, ! 96: global, ! 97: import, ! 98: local, ! 99: progbeg, ! 100: progend, ! 101: segment, ! 102: space, ! 103: 0, ! 104: 0, ! 105: 0, ! 106: stabinit, ! 107: stabline, ! 108: stabsym, ! 109: 0, ! 110: {".globl %s\n", 0, 4, {".text", 0, 0, ".rdata", ".rdata" }, ! 111: doarg, docall, blkfetch, blkloop, blkstore, ! 112: final, 0, emitspecial, ! 113: #ifdef GEN4 ! 114: mips_kids, mips_ntname, mips_nts, mips_rule, mips_state, mips_string, mips_cost, ! 115: rules, emit2, target ! 116: #endif ! 117: } ! 118: }, mipselInterface = { ! 119: "mipsel", ! 120: 1, 1, 0, /* char */ ! 121: 2, 2, 0, /* short */ ! 122: 4, 4, 0, /* int */ ! 123: 4, 4, 1, /* float */ ! 124: 8, 8, 1, /* double */ ! 125: 4, 4, 0, /* T * */ ! 126: 0, 1, 0, /* struct */ ! 127: 1, /* left_to_right */ ! 128: 1, /* little_endian */ ! 129: 1, /* jump_on_return */ ! 130: 0, /* mulops_are_calls */ ! 131: 0, /* compl_band */ ! 132: 0, /* no_argb */ ! 133: NODAG, /* no_dag */ ! 134: address, ! 135: blockbeg, ! 136: blockend, ! 137: defaddress, ! 138: defconst, ! 139: defstring, ! 140: defsymbol, ! 141: 0, ! 142: export, ! 143: function, ! 144: gen, ! 145: global, ! 146: import, ! 147: local, ! 148: progbeg, ! 149: progend, ! 150: segment, ! 151: space, ! 152: 0, ! 153: 0, ! 154: 0, ! 155: stabinit, ! 156: stabline, ! 157: stabsym, ! 158: 0, ! 159: {".globl %s\n", 0, 4, {".text", 0, 0, ".rdata", ".rdata" }, ! 160: doarg, docall, blkfetch, blkloop, blkstore, ! 161: final, 0, emitspecial, ! 162: #ifdef GEN4 ! 163: mips_kids, mips_ntname, mips_nts, mips_rule, mips_state, mips_string, mips_cost, ! 164: rules, emit2, target ! 165: #endif ! 166: } ! 167: }; ! 168: ! 169: #define nop 0,0,0,0,0 ! 170: ! 171: static unsigned a_def(s1) Symbol s1; { ! 172: print("%s:\n", s1->x.name); ! 173: return 0; ! 174: } ! 175: ! 176: static void a_defaddress(p) Symbol p; { ! 177: if (p->scope == LABELS) ! 178: print(".align 2; "); /* for switch tables */ ! 179: print(".word %s\n", (p)->x.name); ! 180: } ! 181: ! 182: static unsigned a_emit(op, rs, rt, rd, immed) unsigned op; { ! 183: int off = immed; ! 184: ! 185: switch (op) { ! 186: case 0: ! 187: if (immed) ! 188: print("sll $%s,$%s,%d\n", ireg[rd]->x.name, ireg[rt]->x.name, immed>>6); ! 189: else ! 190: print("%s", nrflag); ! 191: break; ! 192: case o_bgt: print("bgtz $%d,L.%d\n", rs, rd); break; ! 193: case o_or: print("or $%d,$%d,$%d\n", rd, rs, rt); break; ! 194: case o_sltu: print("sltu $%d,$%d,$%d\n", rd, rs, rt); break; ! 195: case o_addu: ! 196: if (rs == 0) ! 197: print("move $%d,$%d\n", rd, rt); ! 198: else if (rt == 0) ! 199: print("move $%d,$%d\n", rd, rs); ! 200: else ! 201: print("addu $%d,$%d,$%d\n", rd, rs, rt); ! 202: break; ! 203: case o_addui: print("addu $%s,$%s,%d\n", ireg[rt]->x.name, ireg[rs]->x.name, immed); break; ! 204: case o_srli: print("srl $%s,$%s,%d\n", ireg[rd]->x.name, ireg[rt]->x.name, immed>>6); break; ! 205: case o_lbu: print("lbu $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 206: case o_lhu: print("lhu $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 207: case o_lw: print("lw $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 208: case o_lwl: print("lwl $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 209: case o_lwr: print("lwr $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 210: case o_sb: print("sb $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 211: case o_sh: print("sh $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 212: case o_sw: print("sw $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 213: case o_swl: print("swl $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 214: case o_swr: print("swr $%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 215: case o_l_s: print("l.s $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 216: case o_l_d: print("l.d $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 217: case o_s_s: print("s.s $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 218: case o_s_d: print("s.d $f%d,%d($%s)\n", rt, off, ireg[rs]->x.name); break; ! 219: case o_mtc1_s: print("mtc1 $%d,$f%d\n", rt, rd); break; ! 220: case o_mfc1_s: print("mfc1 $%d,$f%d\n", rt, rd); break; ! 221: case o_mtc1_d: print("mtc1.d $%d,$f%d\n", rt, rd); break; ! 222: case o_mfc1_d: print("mfc1.d $%d,$f%d\n", rt, rd); break; ! 223: case o_mov_s: print("mov.s $f%d,$f%d\n", immed>>6, rd); break; ! 224: case o_mov_d: print("mov.d $f%d,$f%d\n", immed>>6, rd); break; ! 225: default: assert(0); ! 226: } ! 227: return rt; ! 228: } ! 229: ! 230: static void a_end(s1) Symbol s1; { ! 231: print("j $31\n%s.end %s\n", nrflag, s1->x.name); ! 232: } ! 233: ! 234: static void a_entry(s1, flabel, framesize) Symbol s1; { ! 235: segment(CODE); ! 236: print(".align 2; .ent %s\n", s1->x.name); ! 237: put.def(s1); ! 238: print("$fp%d=%d\n.frame $sp,%d,$31\n", flabel, framesize, framesize); ! 239: } ! 240: ! 241: static int a_offset(i) { ! 242: return i; ! 243: } ! 244: ! 245: static void a_symbol(seg, p) Symbol p; { ! 246: if (seg == DATA) ! 247: print(".%s; ", p->type->size > gnum || isarray(p->type) ? "data" : "sdata"); ! 248: if (seg == BSS && (p->sclass == STATIC || Aflag >= 2)) ! 249: print(".lcomm %s,", p->x.name); ! 250: else if (seg == BSS) ! 251: print(".comm %s,", p->x.name); ! 252: else { ! 253: if (p->type->align > 1) ! 254: print(".align %c; ", "..1.2...3"[p->type->align]); ! 255: print("%s:", p->x.name); ! 256: } ! 257: } ! 258: ! 259: static void a_word(w, sz) unsigned w; { ! 260: static char *fmt[] = { 0, ".byte %d\n", ".half %d\n", 0, ".word 0x%x\n" }; ! 261: ! 262: assert(sz >= 1 && sz < sizeof fmt/sizeof fmt[0] && fmt[sz]); ! 263: print(fmt[sz], w); ! 264: } ! 265: ! 266: /* addr - initialize q for addressing expression p+n */ ! 267: static void addr(q, p, n) Symbol q, p; { ! 268: q->x.offset = p->x.offset + n; ! 269: if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) ! 270: q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n); ! 271: else ! 272: q->x.name = stringf("$fp%d%s%d", flabel, ! 273: q->x.offset >= 0 ? "+" : "", q->x.offset); ! 274: } ! 275: ! 276: static void address(p, q, n) Symbol p, q; { ! 277: put.addr(p, q, n); ! 278: } ! 279: ! 280: /* argreg - which register, if any, holds arg at given offset and of given type? */ ! 281: Symbol argreg(offset, ty, ty0, varargs) { ! 282: assert((offset&3) == 0); ! 283: if (offset > 12) ! 284: return 0; ! 285: else if (!varargs && offset == 0 && (ty == F || ty == D)) ! 286: return f12; ! 287: else if (!varargs && offset == 4 && ty0 == F && ty == F) ! 288: return f14; ! 289: else if (!varargs && offset == 8 && ty0 == D && (ty == F || ty == D)) ! 290: return f14; ! 291: else if (varargs && offset == 0 && ty == D) ! 292: return d4; ! 293: else if (offset == 8 && ty == D) ! 294: return d6; ! 295: else ! 296: return ireg[(offset/4) + 4]; ! 297: } ! 298: ! 299: #define BIG (!IR->little_endian) ! 300: ! 301: /* blkfetch - emit code to load k bytes from reg+off into tmp */ ! 302: static void blkfetch(k, off, reg, tmp) { ! 303: static unsigned ops[] = {0, o_lbu, o_lhu, 0, o_lw}; ! 304: ! 305: assert(k == 1 || k == 2 || k == 4); ! 306: if (salign >= k) { ! 307: put.emit(ops[k], reg, tmp, 0, put.offset(off)); ! 308: put.emit(nop); ! 309: } else if (k == 2) { ! 310: put.emit(o_lbu, reg, tmp, 0, put.offset(off+!BIG)); ! 311: if (!bflag) ! 312: print(".set noat\n"); ! 313: put.emit(o_lbu, reg, 1, 0, put.offset(off+ BIG)); ! 314: put.emit(o_slli, 0, tmp, tmp, 8<<6); ! 315: put.emit(o_or, 1, tmp, tmp, 0); ! 316: if (!bflag) ! 317: print(".set at\n"); ! 318: } else { ! 319: put.emit(o_lwl, reg, tmp, 0, put.offset(off+(BIG?0:3))); ! 320: put.emit(o_lwr, reg, tmp, 0, put.offset(off+(BIG?3:0))); ! 321: put.emit(nop); ! 322: } ! 323: } ! 324: ! 325: /* blkloop - emit loop to copy size bytes from sreg+soff to dreg+doff using tmp regs */ ! 326: static void blkloop(dreg, doff, sreg, soff, size, tmp) int tmp[]; { ! 327: struct symbol lab; ! 328: unsigned pc1; ! 329: ! 330: BZERO(&lab, struct symbol); ! 331: lab.u.l.label = genlabel(1); ! 332: lab.name = stringd(lab.u.l.label); ! 333: lab.scope = LABELS; ! 334: lab.generated = 1; ! 335: defsymbol(&lab); ! 336: put.emit(o_addui, sreg, sreg, 0, size&~7); ! 337: put.emit(o_addui, dreg, tmp[2], 0, size&~7); ! 338: blkcopy(tmp[2], doff, sreg, soff, size&7, tmp); ! 339: put.def(&lab); ! 340: pc1 = symeaddr(&lab); ! 341: put.emit(o_addui, sreg, sreg, 0, put.offset(-8)); ! 342: put.emit(o_addui, tmp[2], tmp[2], 0, put.offset(-8)); ! 343: blkcopy(tmp[2], doff, sreg, soff, 8, tmp); ! 344: if (!bflag) ! 345: print(".set noat\n"); ! 346: put.emit(o_sltu, dreg, tmp[2], 1, 0); ! 347: if (bflag) { ! 348: symeaddr(&lab) = 0; ! 349: put.def(&lab); ! 350: } ! 351: put.emit(o_bgt, 1, 0, bflag ? 0 : lab.u.l.label, ! 352: put.offset((int)(pc1 - (symeaddr(&lab) + 4))>>2)); ! 353: put.emit(nop); ! 354: if (!bflag) ! 355: print(".set at\n"); ! 356: } ! 357: ! 358: /* blkstore - emit code to store k bytes from tmp to reg+off */ ! 359: static void blkstore(k, off, reg, tmp) { ! 360: static unsigned ops[] = {0, o_sb, o_sh, 0, o_sw}; ! 361: ! 362: assert(k == 1 || k == 2 || k == 4); ! 363: if (dalign >= k) ! 364: put.emit(ops[k], reg, tmp, 0, put.offset(off)); ! 365: else if (k == 2) { ! 366: if (!bflag) ! 367: print(".set noat\n"); ! 368: put.emit(o_srli, 0, tmp, 1, 8<<6); ! 369: put.emit(o_sb, reg, 1, 0, put.offset(off+!BIG)); ! 370: if (!bflag) ! 371: print(".set at\n"); ! 372: put.emit(o_sb, reg, tmp, 0, put.offset(off+ BIG)); ! 373: } else { ! 374: put.emit(o_swl, reg, tmp, 0, put.offset(off+(BIG?0:3))); ! 375: put.emit(o_swr, reg, tmp, 0, put.offset(off+(BIG?3:0))); ! 376: } ! 377: } ! 378: ! 379: static void defaddress(p) Symbol p; { ! 380: put.defaddr(p); ! 381: } ! 382: ! 383: /* defconst - define a constant */ ! 384: static void defconst(ty, v) Value v; { ! 385: struct real r; ! 386: ! 387: switch (ty) { ! 388: case C: put.word(v.uc, 1); break; ! 389: case S: put.word(v.ss, 2); break; ! 390: case I: put.word(v.i, 4); break; ! 391: case U: put.word(v.u, 4); break; ! 392: case P: put.word((unsigned int)v.p, 4); break; ! 393: case F: ! 394: r = decode(F, v.f); ! 395: if (v.f) ! 396: r.exp = (r.exp + 127)&0xff; ! 397: put.word((r.sign<<31) | (r.exp<<23) | (r.msb>>9), 4); ! 398: break; ! 399: case D: ! 400: r = decode(D, v.d); ! 401: if (v.d) ! 402: r.exp = (r.exp + 1023)&0x7ff; ! 403: if (IR->little_endian) { ! 404: put.word(( r.msb<<20) | (r.lsb>>12), 4); ! 405: put.word((r.sign<<31) | (r.exp<<20) | (r.msb>>12), 4); ! 406: } else { ! 407: put.word((r.sign<<31) | (r.exp<<20) | (r.msb>>12), 4); ! 408: put.word(( r.msb<<20) | (r.lsb>>12), 4); ! 409: } ! 410: break; ! 411: default: ! 412: assert(0); ! 413: } ! 414: } ! 415: ! 416: static void defstring(n, s) char *s; { ! 417: put.string(".ascii", ".byte", n, s); ! 418: } ! 419: ! 420: /* defsymbol - compute and store p's back-end name */ ! 421: static void defsymbol(p) Symbol p; { ! 422: if (p->scope >= LOCAL && p->sclass == STATIC) ! 423: p->x.name = stringf("L.%d", genlabel(1)); ! 424: else if (p->generated) ! 425: p->x.name = stringf("L.%s", p->name); ! 426: else ! 427: p->x.name = p->name; ! 428: } ! 429: ! 430: dclproto(static Node iscall,(Node)); ! 431: ! 432: static Node iscall(q) Node q; { ! 433: if (generic(q->op) == CALL) ! 434: return q; ! 435: else if (IR->no_dag && generic(q->op) == ASGN && generic(q->kids[1]->op) == CALL) ! 436: return q->kids[1]; ! 437: else ! 438: return 0; ! 439: } ! 440: ! 441: /* doarg - assign offset for next ARG node */ ! 442: static void doarg(p) Node p; { ! 443: Symbol tmp; ! 444: ! 445: if (argoffset == 0) { ! 446: Node call, q = p->link; ! 447: while ((call = iscall(q)) == 0) ! 448: q = q->link; ! 449: assert(generic(call->op) == CALL && call->syms[0]); ! 450: if (variadic(call->syms[0]->type)) ! 451: for (q = p; !iscall(q); q = q->link) ! 452: if (generic(q->op) == ARG) ! 453: q->x.isvararg = 1; ! 454: if (optype(call->op) == B) ! 455: argoffset = 4; ! 456: } ! 457: tmp = p->syms[0]; ! 458: p->syms[0] = intconst(mkactual(p->syms[1]->u.c.v.i, p->syms[0]->u.c.v.i, 4)); ! 459: p->syms[2] = p->syms[1]; ! 460: p->syms[1] = tmp; /* xc=S0 */ ! 461: } ! 462: ! 463: #ifdef GEN4 ! 464: char **opcodes; /* dreg to get what's below to compile */ ! 465: #endif ! 466: ! 467: static void emitspecial(p) Node p; { ! 468: ! 469: if (genx == 4 ? (p->op == ARGB) : !strcmp(opcodes[p->op], "# argb")) ! 470: emitargb(p); ! 471: else if (genx == 4 ? (p->op == ASGNB) : !strcmp(opcodes[p->op], "# asgnb")) ! 472: emitasgnb(p); ! 473: } ! 474: ! 475: void emitargb(p) Node p; { ! 476: static int tmp[] = { 2, 3, 8 }; ! 477: ! 478: int dst, n = p->syms[0]->u.c.v.i + p->syms[1]->u.c.v.i; ! 479: dalign = 4; ! 480: salign = p->syms[2]->u.c.v.i; ! 481: blkcopy(29, p->syms[0]->u.c.v.i, ! 482: getregnode(p->kids[0]->syms[RX])->regnum, 0, p->syms[1]->u.c.v.i, tmp); ! 483: for (dst = p->syms[0]->u.c.v.i; dst <= 12 && dst < n; dst += 4) ! 484: put.emit(o_lw, r_sp, dst/4+4, 0, put.offset(dst)); ! 485: if (p->syms[0]->u.c.v.i <= 12) ! 486: put.emit(nop); ! 487: } ! 488: ! 489: void emitasgnb(p) Node p; { ! 490: static int tmp[] = { 2, 3, 8 }; ! 491: ! 492: dalign = salign = p->syms[1]->u.c.v.i; ! 493: blkcopy(getregnode(p->kids[0]->syms[RX])->regnum, 0, ! 494: getregnode(p->kids[1]->syms[RX])->regnum, 0, p->syms[0]->u.c.v.i, tmp); ! 495: } ! 496: ! 497: /* function - generate code for a function */ ! 498: static void function(f, caller, callee, n) Symbol f, callee[], caller[]; { ! 499: int i, lbase, varargs; ! 500: Symbol p, q, r, argireg[4]; ! 501: int ty0 = caller[0] ? ttob(caller[0]->type) : I; ! 502: ! 503: initfunc(n, 0, 0); ! 504: for (i = 0; callee[i]; i++) ! 505: ; ! 506: varargs = variadic(f->type) || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; ! 507: flabel++; ! 508: if (isstruct(freturn(f->type))) { ! 509: offset = 4; ! 510: ty0 = I; ! 511: } ! 512: for (i = 0; p = callee[i]; i++) { ! 513: q = caller[i]; ! 514: assert(q); ! 515: offset = roundup(offset, q->type->align); ! 516: p->x.offset = q->x.offset = offset; ! 517: p->x.name = q->x.name = stringf("$fp%d+%d", flabel, offset); ! 518: r = argreg(offset, ttob(q->type), ty0, varargs); ! 519: if (i < 4) ! 520: argireg[i] = r; ! 521: offset = roundup(offset + q->type->size, 4); ! 522: if (varargs) ! 523: p->sclass = AUTO; ! 524: else if ( ! 525: r && ! 526: ncalls == 0 && ! 527: !isstruct(q->type) && ! 528: !p->addressed && ! 529: (!isfloat(q->type) || r->x.regnode->regset == FREG) ! 530: ) { ! 531: p->x.regvar = q->x.regvar = r; ! 532: p->x.name = q->x.name = r->x.name; ! 533: p->sclass = q->sclass = REGISTER; ! 534: if (!isfloat(p->type)) ! 535: q->type = p->type; ! 536: } else if ( ! 537: getregvar(p, rmap[ttob(p->type)]) && ! 538: r && ! 539: (isint(p->type) || p->type == q->type) ! 540: ) { ! 541: assert(p->x.regvar != r); ! 542: q->sclass = REGISTER; ! 543: q->type = p->type; ! 544: } ! 545: } ! 546: assert(caller[i] == 0); ! 547: offset = 0; ! 548: gencode(caller, callee); ! 549: mvregvars(); ! 550: if (ncalls) ! 551: usedmask[IREG] |= 1<<31; ! 552: usedmask[IREG] &= eemask[IREG]; ! 553: usedmask[FREG] &= eemask[FREG]; ! 554: if (argbuildsize && argbuildsize < 16) ! 555: argbuildsize = 16; ! 556: savemask[FREG] = usedmask[FREG]; savemask[IREG] = usedmask[IREG]; ! 557: savebase[FREG] = argbuildsize; savebase[IREG] = savebase[FREG] + 4*bitcount(usedmask[FREG]); ! 558: lbase = savebase[IREG] + 4*bitcount(usedmask[IREG]); ! 559: framesize = roundup(lbase + maxoffset, 8); ! 560: put.entry(f, flabel, framesize); ! 561: for (i = 0; p = callee[i]; i++) { ! 562: if (p->sclass == REGISTER) { ! 563: assert(p->x.regvar && p->x.regvar->x.regnode); ! 564: symeaddr(p) = p->x.regvar->x.regnode->regnum; ! 565: } ! 566: } ! 567: if (framesize > 0) ! 568: put.emit(o_addui, r_sp, r_sp, 0, put.offset(-framesize)); ! 569: if (usedmask[FREG]) { ! 570: if (!bflag) ! 571: print(".fmask 0x%x,%d\n", usedmask[FREG], savebase[IREG] - framesize - 8); ! 572: funcsave(o_s_d, 20, 30, 2, usedmask[FREG], 3, savebase[FREG]); ! 573: } ! 574: if (usedmask[IREG]) { ! 575: if (!bflag) ! 576: print(".mask 0x%x,%d\n", usedmask[IREG], lbase - framesize - 4); ! 577: funcsave(o_sw, 16, 31, 1, usedmask[IREG], 1, savebase[IREG]); ! 578: } ! 579: if (isstruct(freturn(f->type))) ! 580: put.emit(o_sw, r_sp, 4, 0, put.offset(framesize - 4)); ! 581: for (i = 0; i < 4 && callee[i]; i++) ! 582: if ((r = argireg[i]) && (varargs || r != callee[i]->x.regvar)) ! 583: storearg(callee[i], caller[i], r); ! 584: if (varargs && r) ! 585: for (i = r->x.regnode->regnum + (r == d4 || r == d6); i <= 6; i++) ! 586: put.emit(o_sw, r_sp, i + 1, 0, put.offset(framesize + 4*(i - 3))); ! 587: emitcode(); ! 588: if (usedmask[FREG]) { ! 589: funcsave(o_l_d, 20, 30, 2, usedmask[FREG], 3, savebase[FREG]); ! 590: put.emit(nop); ! 591: } ! 592: if (usedmask[IREG]) { ! 593: funcsave(o_lw, 16, 31, 1, usedmask[IREG], 1, savebase[IREG]); ! 594: put.emit(nop); ! 595: } ! 596: if (framesize > 0) ! 597: put.emit(o_addui, r_sp, r_sp, 0, put.offset(framesize)); ! 598: put.end(f); ! 599: } ! 600: ! 601: /* funcsave - generate register save/restore sequences */ ! 602: static void funcsave(op, lo, hi, inc, used, mask, base) unsigned used, mask; { ! 603: for (; lo <= hi; lo += inc) ! 604: if ((used>>lo)&mask) { ! 605: put.emit(op, r_sp, lo, 0, put.offset(base)); ! 606: base += 4*inc; ! 607: } ! 608: } ! 609: ! 610: static void global(p) Symbol p; { ! 611: assert(p->u.seg); ! 612: put.symbol(p->u.seg, p); ! 613: } ! 614: ! 615: /* import - import a symbol */ ! 616: static void import(p) Symbol p; { ! 617: if (!isfunc(p->type) && !bflag) ! 618: print(".extern %s %d\n", p->name, ! 619: isarray(p->type) ? 0 : p->type->size); ! 620: } ! 621: ! 622: /* local - local */ ! 623: static void local(p) Symbol p; { ! 624: if (getregvar(p, rmap[ttob(p->type)]) == 0) { ! 625: int offset = mkauto(p, p->type->align); ! 626: p->x.name = stringf("$fp%d%d", flabel, offset); ! 627: } ! 628: } ! 629: ! 630: /* progbeg - beginning of program */ ! 631: static void progbeg(argc, argv) char *argv[]; { ! 632: int i; ! 633: ! 634: nregsets = 2; ! 635: eemask[IREG] = 0xc0ff0000; eemask[FREG] = 0xfff00000; ! 636: tmask[IREG] = 0x0300ffff; tmask[FREG] = 0x000f0fff; ! 637: vmask[IREG] = 0x40ff0000; vmask[FREG] = 0xfff00000; ! 638: parseflags(argc, argv); ! 639: for (i = 0; i < argc; i++) ! 640: if (strncmp(argv[i], "-G", 2) == 0) ! 641: gnum = atoi(argv[i] + 2); ! 642: #if BINARY ! 643: else if (strcmp(argv[i], "-binary") == 0) { ! 644: dclproto(extern unsigned (*emitter),(Node, int)); ! 645: dclproto(extern unsigned emitbin,(Node, int)); ! 646: extern struct emit bput; ! 647: bflag = 1; ! 648: put = bput; ! 649: emitter = emitbin; ! 650: } ! 651: #endif ! 652: else if (strcmp(argv[i], "-noreorder") == 0) { ! 653: nrflag = "nop\n"; ! 654: #ifdef GEN4 ! 655: addnops(); ! 656: #endif ! 657: } ! 658: initgen(); ! 659: for (i = 0; i < 32; i++) ! 660: ireg[i] = mkregs("%d", i, i, 1, 1, IREG, I, 0); ! 661: ireg[29]->x.name = "sp"; ! 662: d4 = mkregs("%d", 4, 4, 1, 3, IREG, V, 0); ! 663: d6 = mkregs("%d", 6, 6, 1, 3, IREG, V, 0); ! 664: f0 = mkregs("%d", 0, 0, 1, 3, FREG, D, 0); ! 665: f12 = mkregs("%d", 12, 12, 1, 3, FREG, D, 0); ! 666: f14 = mkregs("%d", 14, 14, 1, 3, FREG, D, 0); ! 667: rmap[I] = mkregs("%d", 2, 2, 1, 1, IREG, I, rmap[I]); ! 668: rmap[I] = mkregs("%d", 8, 25, 1, 1, IREG, I, rmap[I]); ! 669: rmap[I] = mkregs("%d", 30, 30, 1, 1, IREG, I, rmap[I]); ! 670: rmap[D] = mkregs("%d", 4, 10, 2, 3, FREG, D, rmap[D]); ! 671: rmap[D] = mkregs("%d", 16, 30, 2, 3, FREG, D, rmap[D]); ! 672: rmap[F] = rmap[D]; rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I]; ! 673: rmap[F] = rmap[D]; rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I]; ! 674: if (!bflag) ! 675: print(".set %sreorder\n", *nrflag ? "no" : ""); ! 676: } ! 677: ! 678: static void segment(n) { ! 679: put.seg(n); ! 680: } ! 681: ! 682: static void space(n) { ! 683: put.spacen(n, ".space"); ! 684: } ! 685: ! 686: /* storearg - emit a store for an argument in register r. p is callee, q caller */ ! 687: static void storearg(p, q, r) Symbol p, q, r; { ! 688: int pn, rn; ! 689: ! 690: assert(r && r->x.regnode); ! 691: rn = r->x.regnode->regnum; ! 692: if (p->sclass == REGISTER && (isint(p->type) || p->type == q->type)) { ! 693: assert(p && p->x.regvar && p->x.regvar->x.regnode); ! 694: pn = p->x.regvar->x.regnode->regnum; ! 695: if (!isfloat(q->type)) ! 696: put.emit(o_move, rn, 0, pn, 0); ! 697: else if (r->x.regnode->regset == FREG) { ! 698: put.emit(ttob(q->type) == D ? o_mov_d : o_mov_s, 0, 0, rn, pn<<6); ! 699: put.emit(nop); ! 700: } else ! 701: put.emit(ttob(q->type) == D ? o_mtc1_d : o_mtc1_s, 0, rn, pn, 0); ! 702: } else { ! 703: if (!isfloat(q->type)) { ! 704: int n = (q->type->size - 1)/4; ! 705: if (n > '7' - *r->x.name) ! 706: n = '7' - *r->x.name; ! 707: for ( ; n >= 0; n--) ! 708: put.emit(o_sw, r_sp, rn+n, 0, put.offset(q->x.offset + framesize + n*4)); ! 709: put.emit(nop); ! 710: } else if (r->x.regnode->regset == FREG) { ! 711: put.emit(ttob(q->type) == D ? o_s_d : o_s_s, r_sp, rn, 0, ! 712: put.offset(q->x.offset + framesize)); ! 713: put.emit(nop); ! 714: } else { ! 715: put.emit(o_sw, r_sp, rn, 0, put.offset(q->x.offset + framesize)); ! 716: if (ttob(q->type) == D) ! 717: put.emit(o_sw, r_sp, rn + 1, 0, put.offset(q->x.offset + framesize + 4)); ! 718: put.emit(nop); ! 719: } ! 720: } ! 721: } ! 722: ! 723: static char *currentfile; ! 724: ! 725: /* stabinit - initialize stab output */ ! 726: static void stabinit(file, argc, argv) char *file, *argv[]; { ! 727: if (file) { ! 728: print(".file 2,\"%s\"\n", file); ! 729: currentfile = file; ! 730: } ! 731: } ! 732: ! 733: /* stabline - emit stab entry for source coordinate *cp */ ! 734: static void stabline(cp) Coordinate *cp; { ! 735: if (cp->file && cp->file != currentfile) { ! 736: print(".file 2,\"%s\"\n", cp->file); ! 737: currentfile = cp->file; ! 738: } ! 739: print(".loc 2,%d\n", cp->y); ! 740: } ! 741: ! 742: /* stabsym - output a stab entry for symbol p */ ! 743: static void stabsym(p) Symbol p; { ! 744: if (p == cfunc && IR->stabline) ! 745: (*IR->stabline)(&p->src); ! 746: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.