|
|
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.