📄 minimips.md
字号:
case RSH + I: case LSH + I: case RSH + U: case LSH + U: if (generic (p->kids[1]->op) != CNST) spill (INTTMP, IREG, p); break; case CALL + V: spill (INTTMP | INTRET, IREG, p); break; }}static voidemit2shift (Node p, char *shift_opcode){ int distance = p->kids[1]->syms[0]->u.c.v.i & 31; int src = getregnum (p->x.kids[0]); int dst = getregnum (p); if (distance == 0) print ("\tmove $%d, $%d\n", dst, src); else { if (distance & 1) { print ("\t%s $%d, $%d, 1\n", shift_opcode, dst, src); src = dst; } if (distance & 2) { print ("\t%s $%d, $%d, 2\n", shift_opcode, dst, src); src = dst; } if (distance & 4) { print ("\t%s $%d, $%d, 2\n", shift_opcode, dst, src); print ("\t%s $%d, $%d, 2\n", shift_opcode, dst, dst); src = dst; } if (distance & 8) { print ("\t%s $%d, $%d, 8\n", shift_opcode, dst, src); src = dst; } if (distance & 16) { print ("\t%s $%d, $%d, 8\n", shift_opcode, dst, src); print ("\t%s $%d, $%d, 8\n", shift_opcode, dst, dst); src = dst; } }}static voidemit2 (Node p){ int src, sz, ty; static int ty0; Symbol q; switch (specific (p->op)) { case ARG + F: case ARG + I: case ARG + P: case ARG + U: ty = optype (p->op); sz = opsize (p->op); if (p->x.argno == 0) ty0 = ty; q = argreg (p->x.argno, p->syms[2]->u.c.v.i, ty, sz, ty0); src = getregnum (p->x.kids[0]); if (q == NULL) print ("\tsw $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i); break; case ASGN + B: dalign = salign = p->syms[1]->u.c.v.i; blkcopy (getregnum (p->x.kids[0]), 0, getregnum (p->x.kids[1]), 0, p->syms[0]->u.c.v.i, tmpregs); break; case LSH + I: case LSH + U: emit2shift (p, "sll"); break; case RSH + I: emit2shift (p, "sra"); break; case RSH + U: emit2shift (p, "srl"); break; }}static Symbolargreg (int argno, int offset, int ty, int sz, int ty0){ assert ((offset & 3) == 0); if (offset > 12) return NULL; else return ireg[(offset / 4) + 4];}static voiddoarg (Node p){ static int argno; int align; if (argoffset == 0) argno = 0; p->x.argno = argno++; align = p->syms[1]->u.c.v.i < 4 ? 4 : p->syms[1]->u.c.v.i; p->syms[2] = intconst (mkactual (align, p->syms[0]->u.c.v.i));}static voidlocal (Symbol p){ if (askregvar (p, rmap (ttob (p->type))) == 0) mkauto (p);}static voidfunction (Symbol f, Symbol caller[], Symbol callee[], int ncalls){ int i, saved, sizeisave, varargs; Symbol r, argregs[4]; usedmask[0] = usedmask[1] = 0; freemask[0] = freemask[1] = ~(unsigned) 0; offset = maxoffset = maxargoffset = 0; for (i = 0; callee[i]; i++) ; varargs = variadic (f->type) || i > 0 && strcmp (callee[i - 1]->name, "va_alist") == 0; for (i = 0; callee[i]; i++) { Symbol p = callee[i]; Symbol q = caller[i]; assert (q); offset = roundup (offset, q->type->align); p->x.offset = q->x.offset = offset; p->x.name = q->x.name = stringd (offset); r = argreg (i, offset, optype (ttob (q->type)), q->type->size, optype (ttob (caller[0]->type))); if (i < 4) argregs[i] = r; offset = roundup (offset + q->type->size, 4); if (varargs) p->sclass = AUTO; else if (r && ncalls == 0 && !isstruct (q->type) && !p->addressed && !(isfloat (q->type) && r->x.regnode->set == IREG)) { p->sclass = q->sclass = REGISTER; askregvar (p, r); assert (p->x.regnode && p->x.regnode->vbl == p); q->x = p->x; q->type = p->type; } else if (askregvar (p, rmap (ttob (p->type))) && r != NULL && (isint (p->type) || p->type == q->type)) { assert (q->sclass != REGISTER); p->sclass = q->sclass = REGISTER; q->type = p->type; } } assert (!caller[i]); offset = 0; gencode (caller, callee); if (ncalls) usedmask[IREG] |= ((unsigned) 1) << 31; usedmask[IREG] &= 0xc0ff0000; maxargoffset = roundup (maxargoffset, 4); if (ncalls && maxargoffset < 16) maxargoffset = 16; sizeisave = 4 * bitcount (usedmask[IREG]); framesize = roundup (maxargoffset + sizeisave + maxoffset, 8); segment (CODE); print ("\t.align 2\n"); print ("\t.ent %s\n", f->x.name); print ("%s:\n", f->x.name); i = maxargoffset - framesize; print ("\t.frame $sp,%d,$31\n", framesize); if (framesize > 0) print ("\taddu $sp,$sp,%d\n", -framesize); if (usedmask[IREG]) print ("\t.mask 0x%x,%d\n", usedmask[IREG], i + sizeisave - 4); saved = maxargoffset; for (i = 16; i <= 31; i++) if (usedmask[IREG] & (1 << i)) { print ("\tsw $%d,%d($sp)\n", i, saved); saved += 4; } for (i = 0; i < 4 && callee[i]; i++) { r = argregs[i]; if (r && r->x.regnode != callee[i]->x.regnode) { Symbol out = callee[i]; Symbol in = caller[i]; int rn = r->x.regnode->number; assert (out && in && r && r->x.regnode); assert (out->sclass != REGISTER || out->x.regnode); if (out->sclass == REGISTER && (isint (out->type) || out->type == in->type)) { int outn = out->x.regnode->number; print ("\tmove $%d,$%d\n", outn, rn); } else { int off = in->x.offset + framesize; { int i, n = (in->type->size + 3) / 4; for (i = rn; i < rn + n && i <= 7; i++) print ("\tsw $%d,%d($sp)\n", i, off + (i - rn) * 4); } } } } if (varargs && callee[i - 1]) { i = callee[i - 1]->x.offset + callee[i - 1]->type->size; for (i = roundup (i, 4) / 4; i <= 3; i++) print ("\tsw $%d,%d($sp)\n", i + 4, framesize + 4 * i); } emitcode (); saved = maxargoffset; for (i = 16; i <= 31; i++) if (usedmask[IREG] & (1 << i)) { print ("\tlw $%d,%d($sp)\n", i, saved); saved += 4; } if (framesize > 0) print ("\taddu $sp,$sp,%d\n", framesize); print ("\tj $31\n"); print ("\t.end %s\n", f->x.name);}static voiddefconst (int suffix, int size, Value v){ if (suffix == F) { float f = v.d; print ("\t.word 0x%x\n", *(unsigned *) &f); } else if (suffix == P) print ("\t.word 0x%x\n", v.p); else if (size == 1) print ("\t.byte 0x%x\n", suffix == I ? v.i : v.u); else if (size == 2) print ("\t.half 0x%x\n", suffix == I ? v.i : v.u); else if (size == 4) print ("\t.word 0x%x\n", suffix == I ? v.i : v.u);}static voiddefaddress (Symbol p){ print ("\t.word %s\n", p->x.name);}static voiddefstring (int n, char *str){ char *s; for (s = str; s < str + n; s++) print ("\t.byte %d\n", (*s) & 0377);}static voidexport (Symbol p){ print ("\t.globl %s\n", p->x.name);}static voidimport (Symbol p){ if (!isfunc (p->type)) print ("\t.extern %s %d\n", p->name, p->type->size);}static voiddefsymbol (Symbol p){ if (p->scope >= LOCAL && p->sclass == STATIC) p->x.name = stringf ("L.%d", genlabel (1)); else if (p->generated) p->x.name = stringf ("L.%s", p->name); else assert (p->scope != CONSTANTS || isint (p->type) || isptr (p->type)), p->x.name = p->name;}static voidaddress (Symbol q, Symbol p, long n){ if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) q->x.name = stringf ("%s%s%D", p->x.name, n >= 0 ? "+" : "", n); else { assert (n <= INT_MAX && n >= INT_MIN); q->x.offset = p->x.offset + n; q->x.name = stringd (q->x.offset); }}static void global (Symbol p){ if (p->u.seg == BSS) { if (p->sclass == STATIC || Aflag >= 2) print ("\t.lcomm %s,%d\n", p->x.name, p->type->size); else print ("\t.comm %s,%d\n", p->x.name, p->type->size); } else { print ("\t.data\n"); print ("\t.align %c\n", ".01.2...3"[p->type->align]); print ("%s:\n", p->x.name); }}static voidsegment (int n){ cseg = n; switch (n) { case CODE: print ("\t.text\n"); break; case LIT: print ("\t.rdata\n"); break; }}static voidspace (int n){ if (cseg != BSS) print ("\t.space %d\n", n);}static voidblkloop (int dreg, int doff, int sreg, int soff, int size, int tmps[]){ int lab = genlabel (1); print ("\taddu $%d,$%d,%d\n", sreg, sreg, size & ~7); print ("\taddu $%d,$%d,%d\n", tmps[2], dreg, size & ~7); blkcopy (tmps[2], doff, sreg, soff, size & 7, tmps); print ("L.%d:\n", lab); print ("\taddu $%d,$%d,%d\n", sreg, sreg, -8); print ("\taddu $%d,$%d,%d\n", tmps[2], tmps[2], -8); blkcopy (tmps[2], doff, sreg, soff, 8, tmps); print ("\tbltu $%d,$%d,L.%d\n", dreg, tmps[2], lab);}static voidblkfetch (int size, int off, int reg, int tmp){ assert (size == 1 || size == 2 || size == 4); assert (tmp != reg); if (size == 1) print ("\tlb $%d,%d($%d)\n", tmp, off, reg); else if (size == 2) { print ("\tlb $%d,%d($%d)\n", tmp, off + 1, reg); print ("\tsll $%d,$%d,8\n", tmp, tmp); print ("\tlb $%d,%d($%d)\n", 30, off + 0, reg); print ("\tor $%d,$%d,$%d\n", tmp, tmp, 30); } else { if (salign >= size) print ("\tlw $%d,%d($%d)\n", tmp, off, reg); else { print ("\tlb $%d,%d($%d)\n", tmp, off + 3, reg); print ("\tsll $%d,$%d,8\n", tmp, tmp); print ("\tlb $%d,%d($%d)\n", 30, off + 2, reg); print ("\tor $%d,$%d,$%d\n", tmp, tmp, 30); print ("\tsll $%d,$%d,8\n", tmp, tmp); print ("\tlb $%d,%d($%d)\n", 30, off + 1, reg); print ("\tor $%d,$%d,$%d\n", tmp, tmp, 30); print ("\tsll $%d,$%d,8\n", tmp, tmp); print ("\tlb $%d,%d($%d)\n", 30, off + 0, reg); print ("\tor $%d,$%d,$%d\n", tmp, tmp, 30); } }}static voidblkstore (int size, int off, int reg, int tmp){ assert (size == 1 || size == 2 || size == 4); assert (tmp != reg); if (size == 1) print ("\tsb $%d,%d($%d)\n", tmp, off, reg); else if (size == 2) { print ("\tsb $%d,%d($%d)\n", tmp, off, reg); print ("\tsrl $%d,$%d,8\n", 30, tmp); print ("\tsb $%d,%d($%d)\n", 30, off + 1, reg); } else { if (dalign >= size) print ("sw $%d,%d($%d)\n", tmp, off, reg); else { print ("\tsb $%d,%d($%d)\n", tmp, off, reg); print ("\tsrl $%d,$%d,8\n", 30, tmp); print ("\tsb $%d,%d($%d)\n", 30, off + 1, reg); print ("\tsrl $%d,$%d,8\n", 30, 30); print ("\tsb $%d,%d($%d)\n", 30, off + 2, reg); print ("\tsrl $%d,$%d,8\n", 30, 30); print ("\tsb $%d,%d($%d)\n", 30, off + 3, reg); } }}static intbitcount (unsigned mask){ unsigned i, n = 0; for (i = 1; i; i <<= 1) if (mask & i) n++; return n;}static intmulops_calls (int op){ if (generic (op) == DIV || generic (op) == MOD || generic (op) == MUL) return 1; if (generic (op) == LSH || generic (op) == RSH) return 1; if ((generic (op) == ADD || generic (op) == SUB) && optype (op) == F) return 1; if (generic (op) == NEG && optype (op) == F) return 1; if (generic (op) == CVI && optype (op) == F) return 1; if (generic (op) == CVF && optype (op) == I) return 1; return 0;}Interface minimipsIR = { 1, 1, 0, /* char */ 4, 4, 0, /* short */ 4, 4, 0, /* int */ 4, 4, 0, /* long */ 4, 4, 0, /* long long */ 4, 4, 1, /* float */ 4, 4, 1, /* double */ 4, 4, 1, /* long double */ 4, 4, 0, /* T * */ 0, 1, 0, /* struct */ 0, /* little_endian */ mulops_calls, /* mulops_calls */ 0, /* wants_callb */ 0, /* wants_argb */ 1, /* left_to_right */ 0, /* wants_dag */ 0, /* unsigned_char */ address, blockbeg, blockend, defaddress, defconst, defstring, defsymbol, emit, export, function, gen, global, import, local, progbeg, progend, segment, space, 0, 0, 0, 0, 0, 0, 0, { 4, /* max_unaligned_load */ rmap, blkfetch, blkstore, blkloop, _label, _rule, _nts, _kids, _string, _templates, _isinstruction, _ntname, emit2, doarg, target, clobber, }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -