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