|
|
1.1 ! root 1: /* C compiler: SPARC code generator */ ! 2: ! 3: #include "c.h" ! 4: ! 5: #ifdef sparc ! 6: #include <stab.h> ! 7: #include "stabbsd.c" ! 8: #endif ! 9: ! 10: dclproto(static void address,(Symbol, Symbol, int)); ! 11: dclproto(static void blkfetch,(int, int, int, int)); ! 12: dclproto(static void blkloop,(int, int, int, int, int, int[])); ! 13: dclproto(static void blkstore,(int, int, int, int)); ! 14: dclproto(static void defaddress,(Symbol)); ! 15: dclproto(static void defconst,(int, Value)); ! 16: dclproto(static void defstring,(int, char *)); ! 17: dclproto(static void defsymbol,(Symbol)); ! 18: dclproto(static void doarg,(Node)); ! 19: dclproto(static void emitspecial,(Node)); ! 20: dclproto(static void function,(Symbol, Symbol [], Symbol [], int)); ! 21: dclproto(static void global,(Symbol)); ! 22: dclproto(static void import,(Symbol)); ! 23: dclproto(static void local,(Symbol)); ! 24: dclproto(static Symbol nextreg,(Symbol)); ! 25: dclproto(static void progbeg,(int, char **)); ! 26: dclproto(static void segment,(int)); ! 27: dclproto(static void space,(int)); ! 28: ! 29: dclproto(static void initgen,(void)); ! 30: dclproto(static void final,(Node)); ! 31: ! 32: #ifdef GEN4 ! 33: dclproto(static unsigned emit2,(Node,Node[],short[])); ! 34: dclproto(static void target,(Node)); ! 35: #endif ! 36: ! 37: Interface sparcInterface = { ! 38: "sparc", ! 39: 1, 1, 0, /* char */ ! 40: 2, 2, 0, /* short */ ! 41: 4, 4, 0, /* int */ ! 42: 4, 4, 1, /* float */ ! 43: 8, 8, 1, /* double */ ! 44: 4, 4, 0, /* T * */ ! 45: 0, 1, 0, /* struct */ ! 46: 1, /* left_to_right */ ! 47: 0, /* little_endian */ ! 48: 1, /* jump_on_return */ ! 49: 1, /* mulops_are_calls */ ! 50: 0, /* compl_band */ ! 51: 1, /* no_argb */ ! 52: NODAG, /* no_dag */ ! 53: address, ! 54: blockbeg, ! 55: blockend, ! 56: defaddress, ! 57: defconst, ! 58: defstring, ! 59: defsymbol, ! 60: 0, ! 61: export, ! 62: function, ! 63: gen, ! 64: global, ! 65: import, ! 66: local, ! 67: progbeg, ! 68: progend, ! 69: segment, ! 70: space, ! 71: #ifdef sparc ! 72: stabblock, 0, 0, stabinit, stabline, stabsym, stabtype, ! 73: #else ! 74: 0, 0, 0, 0, 0, 0, 0, ! 75: #endif ! 76: {".global %s\n", 0, 1, {".seg \"text\"", ".seg \"bss\"", ".seg \"data\"", ".seg \"text\""}, ! 77: doarg, docall, blkfetch, blkloop, blkstore, ! 78: final, 0, emitspecial, ! 79: #ifdef GEN4 ! 80: sparc_kids, sparc_ntname, sparc_nts, sparc_rule, sparc_state, sparc_string, sparc_cost, ! 81: rules, emit2, target ! 82: #endif ! 83: } ! 84: }; ! 85: ! 86: static Symbol curfunc; ! 87: static int nlocals; ! 88: static Symbol d0, f0, g0, i0, freg[32], ireg[6], oreg[6]; ! 89: dclproto(static void rename,(int)); ! 90: ! 91: /* address - initialize q for addressing expression p+n */ ! 92: static void address(q, p, n) Symbol q, p; int n; { ! 93: q->x.offset = p->x.offset + n; ! 94: if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) ! 95: q->x.name = stringf("%s%s%d", p->x.name, n >= 0 ? "+" : "", n); ! 96: else ! 97: q->x.name = stringd(q->x.offset); ! 98: } ! 99: ! 100: /* blkfetch - emit code to load k bytes from reg+off into tmp */ ! 101: static void blkfetch(k, off, reg, tmp) { ! 102: assert(k == 1 || k == 2 || k == 4); ! 103: assert(salign >= k); ! 104: print("ld%s [%%r%d+%d],%%r%d\n", &"ub\0uh\0..\0\0"[3*(k-1)], reg, off, tmp); ! 105: } ! 106: ! 107: /* blkloop - emit loop to copy size bytes from sreg+soff to dreg+doff using tmp regs */ ! 108: static void blkloop(dreg, doff, sreg, soff, size, tmp) int tmp[]; { ! 109: if ((size&~7) > 4096) { ! 110: print("set %d,%%%s\n", size&~7, tmp[2]); ! 111: print("add %%r%d,%%r%d,%%r%d\n", sreg, tmp[2], sreg); ! 112: print("add %%r%d,%%r%d,%%r%d\n", dreg, tmp[2], tmp[2]); ! 113: } else { ! 114: print("add %%r%d,%d,%%r%d\n", sreg, size&~7, sreg); ! 115: print("add %%r%d,%d,%%r%d\n", dreg, size&~7, tmp[2]); ! 116: } ! 117: blkcopy(tmp[2], doff, sreg, soff, size&7, tmp); ! 118: print("1: dec 8,%%r%d\n", tmp[2]); ! 119: blkcopy(tmp[2], doff, sreg, soff - 8, 8, tmp); ! 120: print("cmp %%r%d,%%r%d; bgt 1b; dec 8,%%r%d\n", tmp[2], dreg, sreg); ! 121: } ! 122: ! 123: /* blkstore - emit code to store k bytes from tmp to reg+off */ ! 124: static void blkstore(k, off, reg, tmp) { ! 125: assert(k == 1 || k == 2 || k == 4); ! 126: assert(dalign >= k); ! 127: print("st%s %%r%d,[%%r%d+%d]\n", &"b\0h\0.\0\0"[2*(k-1)], tmp, reg, off); ! 128: } ! 129: ! 130: ! 131: static void defaddress(p) Symbol p; { ! 132: if (p->scope == LABELS) ! 133: print(".align 4; "); /* for switch tables */ ! 134: print(".word %s\n", p->x.name); ! 135: } ! 136: ! 137: /* defconst - define a constant */ ! 138: static void defconst(ty, v) Value v; { ! 139: struct real r; ! 140: ! 141: switch (ty) { ! 142: case C: print(".byte %d\n", v.uc); break; ! 143: case S: print(".half %d\n", v.ss); break; ! 144: case I: print(".word %d\n", v.i ); break; ! 145: case U: print(".word 0x%x\n", v.u ); break; ! 146: case P: print(".word 0x%x\n", v.p ); break; ! 147: case F: ! 148: r = decode(F, v.f); ! 149: if (v.f) ! 150: r.exp = (r.exp + 127)&0xff; ! 151: print(".word 0x%x\n", (r.sign<<31) | (r.exp<<23) | (r.msb>>9)); ! 152: break; ! 153: case D: ! 154: r = decode(D, v.d); ! 155: if (v.d) ! 156: r.exp = (r.exp + 1023)&0x7ff; ! 157: print(".word 0x%x,0x%x\n", ! 158: (r.sign<<31) | (r.exp<<20) | (r.msb>>12), ! 159: ( r.msb<<20) | (r.lsb>>12)); ! 160: break; ! 161: default: ! 162: assert(0); ! 163: } ! 164: } ! 165: ! 166: static void defstring(n, s) char *s; { ! 167: genascii(".ascii", ".byte", n, s); ! 168: } ! 169: ! 170: /* defsymbol - compute and store p's back-end name */ ! 171: static void defsymbol(p) Symbol p; { ! 172: if (p->scope >= LOCAL && p->sclass == STATIC) ! 173: p->x.name = stringf("%d", genlabel(1)); ! 174: else ! 175: p->x.name = p->name; ! 176: if (p->scope >= LABELS) ! 177: p->x.name = stringf(p->generated ? "L%s" : "_%s", p->x.name); ! 178: } ! 179: ! 180: /* doarg - assign offset for next ARG node */ ! 181: static void doarg(p) Node p; { ! 182: static int reg; ! 183: ! 184: if (argoffset == 0) ! 185: reg = 0; ! 186: assert(p); ! 187: assert(p->syms[0]); ! 188: assert(p->syms[1]); ! 189: p->syms[2] = intconst(mkactual((p->syms[1]->u.c.v.i == 8 ? 4 : p->syms[1]->u.c.v.i), p->syms[0]->u.c.v.i, 4)/4); ! 190: p->syms[1] = intconst(reg/4); ! 191: assert(p->op != ARG+B); ! 192: reg += roundup(p->syms[0]->u.c.v.i, 4); ! 193: } ! 194: ! 195: #ifdef GEN4 ! 196: char **opcodes; ! 197: #endif ! 198: ! 199: /* emitspecial - emit hard double-precision operators */ ! 200: static void emitspecial(p) Node p; { ! 201: if (genx == 4 ? (p->op == ASGN+B) : !strcmp(opcodes[p->op], "# asgnb")) { ! 202: static int tmp[] = { 1, 2, 3 }; ! 203: dalign = salign = p->syms[1]->u.c.v.i; ! 204: blkcopy(getregnode(p->kids[0]->syms[RX])->regnum, 0, ! 205: getregnode(p->kids[1]->syms[RX])->regnum, 0, p->syms[0]->u.c.v.i, tmp); ! 206: } else if (genx == 4 ? (p->op == ARG+D) : !strcmp(opcodes[p->op], "# argd")) { ! 207: int dstoff = p->syms[2]->u.c.v.i; ! 208: int dstreg = p->syms[1]->u.c.v.i; ! 209: int src = getregnode(p->kids[0]->syms[RX])->regnum; ! 210: print("st %%f%d,[%%sp+4*%d+68]\n", src, dstoff); ! 211: print("st %%f%d,[%%sp+4*%d+68]\n", src+1, dstoff+1); ! 212: if (dstreg <= 5) ! 213: print("ld [%%sp+4*%d+68],%%o%d\n", dstoff, dstreg); ! 214: if (dstreg <= 4) ! 215: print("ld [%%sp+4*%d+68],%%o%d\n", dstoff+1, dstreg+1); ! 216: } else if (genx == 4 ? (p->op == LOAD+D) : !strcmp(opcodes[p->op], "# movd")) { ! 217: int dst = getregnode(p->syms[RX])->regnum; ! 218: int src = getregnode(p->kids[0]->syms[RX])->regnum; ! 219: print("fmovs %%f%d,%%f%d; fmovs %%f%d,%%f%d\n", src, dst, src+1, dst+1); ! 220: } else if (genx == 4 ? (p->op == NEG+D) : !strcmp(opcodes[p->op], "# negd")) { ! 221: int dst = getregnode(p->syms[RX])->regnum; ! 222: int src = getregnode(p->kids[0]->syms[RX])->regnum; ! 223: print("fnegs %%f%d,%%f%d; fmovs %%f%d,%%f%d\n", src, dst, src+1, dst+1); ! 224: } ! 225: } ! 226: ! 227: /* function - generate code for a function */ ! 228: static void function(f, caller, callee, n) Symbol f, callee[], caller[]; { ! 229: int fpused = 0, framesize, i, reg = 0, varargs; ! 230: Symbol p, q; ! 231: ! 232: initfunc(n + glevel + pflag, 4*(16 + 1), 6*4); ! 233: for (i = 0; callee[i]; i++) ! 234: ; ! 235: varargs = variadic(f->type) || i > 0 && strcmp(callee[i-1]->name, "__builtin_va_alist") == 0; ! 236: for (i = 0; p = callee[i]; i++) { ! 237: q = caller[i]; ! 238: assert(q); ! 239: if (isfloat(p->type) || isstruct(p->type) || reg >= 6) { ! 240: p->x.offset = offset; ! 241: p->x.name = q->x.name = stringd(p->x.offset); ! 242: p->sclass = q->sclass = AUTO; ! 243: fpused++; ! 244: } else if (p->addressed || varargs || glevel && glevel != 3) { ! 245: p->x.offset = offset; ! 246: p->x.name = stringd(p->x.offset); ! 247: p->sclass = AUTO; ! 248: q->sclass = REGISTER; ! 249: if (!getregvar(q, ireg[reg])) ! 250: assert(0); ! 251: fpused++; ! 252: } else { ! 253: p->sclass = q->sclass = REGISTER; ! 254: if (!getregvar(p, ireg[reg])) ! 255: assert(0); ! 256: q->x.name = p->x.name; ! 257: } ! 258: reg += isstruct(p->type) ? 1 : roundup(q->type->size, 4)/4; ! 259: offset += roundup(q->type->size, 4); ! 260: } ! 261: assert(caller[i] == 0); ! 262: curfunc = f; ! 263: nlocals = offset = 0; ! 264: gencode(caller, callee); ! 265: freeregvars(); ! 266: if (isstruct(freturn(f->type))) ! 267: fpused++; ! 268: if (maxoffset > 0 || (usedmask[IREG]&0x00ffff00) || (usedmask[FREG]&~3) || varargs) ! 269: ncalls++; ! 270: framesize = roundup(4*(16 + 1) + argbuildsize + maxoffset, 8); ! 271: savebase[IREG] = framesize; ! 272: print(".align 4\n.proc 4\n%s:", f->x.name); ! 273: savemask[IREG] = 0xffff0000; ! 274: if (ncalls == 0) { ! 275: Symbol p; ! 276: rename(-16); ! 277: for (p = regvars; p; p = p->x.nextregvar) ! 278: p->x.name = p->x.regvar->x.name; ! 279: print(fpused ? "mov %%fp,%%g7; mov %%sp,%%fp\n" : "\n"); ! 280: savemask[IREG] = 0; ! 281: } else if (framesize <= 4095) ! 282: print("save %%sp,%d,%%sp\n", -framesize); ! 283: else ! 284: print("set %d,%%g1; save %%sp,%%g1,%%sp\n", -framesize); ! 285: if (varargs) ! 286: for (; reg < 6; reg++) ! 287: print("st %%i%d,[%%fp+%d]\n", reg, 4*reg + 68); ! 288: else ! 289: for (offset = 4*(16 + 1), reg = i = 0; p = caller[i]; i++) { ! 290: if (isdouble(p->type) && reg <= 4) { ! 291: print("st %%%s,[%%fp+%d]\n", ireg[reg++]->x.name, offset); ! 292: print("st %%%s,[%%fp+%d]\n", ireg[reg++]->x.name, offset + 4); ! 293: } else if (isfloat(p->type) && reg <= 5) ! 294: print("st %%%s,[%%fp+%d]\n", ireg[reg++]->x.name, offset); ! 295: else ! 296: reg++; ! 297: offset += roundup(p->type->size, 4); ! 298: } ! 299: if (pflag) { ! 300: int lab = genlabel(1); ! 301: print("set L%d,%%o0; call mcount; nop\n", lab); ! 302: print(".seg \"data\"\n.align 4; L%d:.word 0\n.seg \"text\"\n", lab); ! 303: } ! 304: emitcode(); ! 305: if (ncalls == 0) { ! 306: rename(16); ! 307: if (fpused) ! 308: print("retl; mov %%g7,%%fp\n"); ! 309: else ! 310: print("retl; nop\n"); ! 311: } else ! 312: print("ret; restore\n"); ! 313: } ! 314: ! 315: /* global - global id */ ! 316: static void global(p) Symbol p; { ! 317: if (p->type->align > 1) ! 318: print(".align %d; ", p->type->align); ! 319: assert(p->u.seg); ! 320: if (p->u.seg == BSS && (p->sclass == STATIC || Aflag >= 2)) ! 321: print(".reserve %s,", p->x.name); ! 322: else if (p->u.seg == BSS) ! 323: print(".common %s,", p->x.name); ! 324: else ! 325: print("%s:", p->x.name); ! 326: } ! 327: ! 328: static void import(p) Symbol p; { ! 329: p->x.name = stringf("_%s", p->name); ! 330: } ! 331: ! 332: /* local - local */ ! 333: static void local(p) Symbol p; { ! 334: if (nlocals++ == 0 && isstruct(freturn(curfunc->type))) { ! 335: p->x.name = stringd(4*16); ! 336: return; ! 337: } ! 338: if (!p->addressed && isscalar(p->type) && !isfloat(p->type)) ! 339: p->sclass = REGISTER; ! 340: if (glevel && glevel != 3) ! 341: p->sclass = AUTO; ! 342: if (getregvar(p, rmap[ttob(p->type)]) == 0) ! 343: p->x.name = stringd(mkauto(p, p->type->align)); ! 344: } ! 345: ! 346: static Symbol nextreg(p) Symbol p; { ! 347: return freg[getregnode(p)->regnum+1]; ! 348: } ! 349: ! 350: /* progbeg - beginning of program */ ! 351: static void progbeg(argc, argv) char *argv[]; { ! 352: int i; ! 353: ! 354: nregsets = 2; ! 355: eemask[IREG] = 0xffff0000; eemask[FREG] = 0; ! 356: tmask[IREG] = 0x3fffff00; tmask[FREG] = -1; ! 357: vmask[IREG] = 0x3ff00000; vmask[FREG] = 0; ! 358: parseflags(argc, argv); ! 359: initgen(); ! 360: d0 = mkregs( "0", 0, 0, 2, 3, FREG, D, 0); ! 361: f0 = mkregs( "0", 0, 0, 1, 1, FREG, F, 0); ! 362: g0 = mkregs( "r0", 0, 0, 1, 1, IREG, I, 0); ! 363: i0 = mkregs("r24", 24, 24, 1, 0, IREG, I, 0); /* zero mask; use only for RETI. */ ! 364: for (i = 0; i < 6; i++) { ! 365: oreg[i] = mkregs("r%d", i + 8, i + 8, 1, 1, IREG, I, 0); ! 366: ireg[i] = mkregs("r%d", i + 24, i + 24, 1, 1, IREG, I, 0); ! 367: } ! 368: for (i = 0; i < 32; i++) ! 369: freg[i] = mkregs("%d", i, i, 1, 1, FREG, F, 0); ! 370: rmap[I] = mkregs("r%d", 8, 13, 1, 1, IREG, I, rmap[I]); ! 371: rmap[I] = mkregs("r%d", 16, 23, 1, 1, IREG, I, rmap[I]); ! 372: rmap[I] = mkregs("r%d", 24, 29, 1, 1, IREG, I, rmap[I]); ! 373: rmap[F] = mkregs("%d", 0, 31, 1, 1, FREG, F, rmap[F]); ! 374: rmap[D] = mkregs("%d", 0, 31, 2, 3, FREG, D, rmap[D]); ! 375: rmap[C] = rmap[S] = rmap[P] = rmap[U] = rmap[I]; ! 376: } ! 377: ! 378: static void rename(inc) { ! 379: Symbol p; ! 380: ! 381: for (p = regs; p; p = p->x.regnode->next) ! 382: if (p == i0 || p->x.regnode->regset == IREG && p->x.regnode->mask&0x3f000000) ! 383: p->x.name = stringf("r%d", p->x.regnode->regnum += inc); ! 384: } ! 385: ! 386: static void segment(n) { ! 387: setseg(n); ! 388: } ! 389: ! 390: static void space(n) { ! 391: spacen((n), ".skip"); ! 392: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.