📄 cgen64.c
字号:
{V_T1, Vins, AMOVL, O_t_hi, O_l_hi}, {V_T1, Vins, AMOVL, O_t_lo, O_l_lo}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {V_F1, Vins, AMOVL, O_t_lo, O_l_lo}, {V_F1, Vins, AMOVL, O_t_hi, O_l_hi}, {Vend},};static uchar (*asshrltab[])[VLEN] ={ asshrlgen, asshrlclo, asshrlc32, asshrlchi, asdshrlgen, asdshrlclo, asdshrlc32, asdshrlchi,};static uchar shrlargs[] = { ASHRL, 1 };static uchar sarlargs[] = { ASARL, 0 };/* ++ -- */static uchar incdec[][VLEN] ={ {Vinsx, Bop0, C01, O_l_lo}, {Vinsx, Bop1, C00, O_l_hi, Vend},};/* ++ -- *p */static uchar incdecpre[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsx, Bop0, C01, O_t_lo}, {Vinsx, Bop1, C00, O_t_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vins, AMOVL, O_t_hi, O_l_hi, Vend},};/* *p ++ -- */static uchar incdecpost[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsx, Bop0, C01, O_l_lo}, {Vinsx, Bop1, C00, O_l_hi, Vend},};/* binop rp, rp */static uchar binop00[][VLEN] ={ {Vinsx, Bop0, O_r_lo, O_l_lo}, {Vinsx, Bop1, O_r_hi, O_l_hi, Vend}, {Vend},};/* binop rp, addr */static uchar binoptmp[][VLEN] ={ {V_a0, Vins, AMOVL, O_r_lo, O_r0}, {Vinsx, Bop0, O_r0, O_l_lo}, {Vins, AMOVL, O_r_hi, O_r0}, {Vinsx, Bop1, O_r0, O_l_hi}, {V_f0, Vend},};/* binop t = *a op *b */static uchar binop11[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vinsx, Bop0, O_r_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsx, Bop1, O_r_hi, O_t_hi, Vend},};/* binop t = rp +- c */static uchar add0c[][VLEN] ={ {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo}, {V_r_lo_f, Vamv, Bop0, Bop1}, {Vinsx, Bop1, O_r_hi, O_l_hi}, {Vend},};/* binop t = rp & c */static uchar and0c[][VLEN] ={ {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo}, {V_r_lo_f, Vins, AMOVL, C00, O_l_lo}, {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi}, {V_r_hi_f, Vins, AMOVL, C00, O_l_hi}, {Vend},};/* binop t = rp | c */static uchar or0c[][VLEN] ={ {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo}, {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi}, {Vend},};/* binop t = c - rp */static uchar sub10[][VLEN] ={ {V_a0, Vins, AMOVL, O_l_lo, O_r0}, {Vinsx, Bop0, O_r_lo, O_r0}, {Vins, AMOVL, O_l_hi, O_r_lo}, {Vinsx, Bop1, O_r_hi, O_r_lo}, {Vspazz, V_f0, Vend},};/* binop t = c + *b */static uchar addca[][VLEN] ={ {Vins, AMOVL, O_r_lo, O_t_lo}, {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo}, {V_l_lo_f, Vamv, Bop0, Bop1}, {Vins, AMOVL, O_r_hi, O_t_hi}, {Vinsx, Bop1, O_l_hi, O_t_hi}, {Vend},};/* binop t = c & *b */static uchar andca[][VLEN] ={ {V_l_lo_t, Vins, AMOVL, O_r_lo, O_t_lo}, {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo}, {V_l_lo_f, Vzero, O_t_lo}, {V_l_hi_t, Vins, AMOVL, O_r_hi, O_t_hi}, {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi}, {V_l_hi_f, Vzero, O_t_hi}, {Vend},};/* binop t = c | *b */static uchar orca[][VLEN] ={ {Vins, AMOVL, O_r_lo, O_t_lo}, {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo}, {Vins, AMOVL, O_r_hi, O_t_hi}, {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi}, {Vend},};/* binop t = c - *b */static uchar subca[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsx, Bop0, O_r_lo, O_t_lo}, {Vinsx, Bop1, O_r_hi, O_t_hi}, {Vend},};/* binop t = *a +- c */static uchar addac[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo}, {V_r_lo_f, Vamv, Bop0, Bop1}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsx, Bop1, O_r_hi, O_t_hi}, {Vend},};/* binop t = *a | c */static uchar orac[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_t_hi}, {Vend},};/* binop t = *a & c */static uchar andac[][VLEN] ={ {V_r_lo_t, Vins, AMOVL, O_l_lo, O_t_lo}, {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo}, {V_r_lo_f, Vzero, O_t_lo}, {V_r_hi_t, Vins, AMOVL, O_l_hi, O_t_hi}, {V_r_hi_t, Vinsx, Bop0, O_r_hi, O_t_hi}, {V_r_hi_f, Vzero, O_t_hi}, {Vend},};static uchar ADDargs[] = { AADDL, AADCL };static uchar ANDargs[] = { AANDL, AANDL };static uchar ORargs[] = { AORL, AORL };static uchar SUBargs[] = { ASUBL, ASBBL };static uchar XORargs[] = { AXORL, AXORL };static uchar (*ADDtab[])[VLEN] ={ add0c, addca, addac,};static uchar (*ANDtab[])[VLEN] ={ and0c, andca, andac,};static uchar (*ORtab[])[VLEN] ={ or0c, orca, orac,};static uchar (*SUBtab[])[VLEN] ={ add0c, subca, addac,};/* mul of const32 */static uchar mulc32[][VLEN] ={ {V_a0, Vop, ONE, O_l_hi, C00}, {V_s0, Vins, AMOVL, O_r_lo, O_r0}, {Vins, AMULL, O_r0, O_Zop}, {Vgo, V_p0, V_s0}, {Vins, AMOVL, O_l_hi, O_r0}, {Vmul, O_r_lo, O_r0}, {Vins, AMOVL, O_r_lo, O_l_hi}, {Vins, AMULL, O_l_hi, O_Zop}, {Vins, AADDL, O_r0, O_l_hi}, {V_f0, V_p0, Vend},};/* mul of const64 */static uchar mulc64[][VLEN] ={ {V_a0, Vins, AMOVL, O_r_hi, O_r0}, {Vop, OOR, O_l_hi, O_r0}, {Vop, ONE, O_r0, C00}, {V_s0, Vins, AMOVL, O_r_lo, O_r0}, {Vins, AMULL, O_r0, O_Zop}, {Vgo, V_p0, V_s0}, {Vmul, O_r_lo, O_l_hi}, {Vins, AMOVL, O_l_lo, O_r0}, {Vmul, O_r_hi, O_r0}, {Vins, AADDL, O_l_hi, O_r0}, {Vins, AMOVL, O_r_lo, O_l_hi}, {Vins, AMULL, O_l_hi, O_Zop}, {Vins, AADDL, O_r0, O_l_hi}, {V_f0, V_p0, Vend},};/* mul general */static uchar mull[][VLEN] ={ {V_a0, Vins, AMOVL, O_r_hi, O_r0}, {Vop, OOR, O_l_hi, O_r0}, {Vop, ONE, O_r0, C00}, {V_s0, Vins, AMOVL, O_r_lo, O_r0}, {Vins, AMULL, O_r0, O_Zop}, {Vgo, V_p0, V_s0}, {Vins, AIMULL, O_r_lo, O_l_hi}, {Vins, AMOVL, O_l_lo, O_r0}, {Vins, AIMULL, O_r_hi, O_r0}, {Vins, AADDL, O_l_hi, O_r0}, {Vins, AMOVL, O_r_lo, O_l_hi}, {Vins, AMULL, O_l_hi, O_Zop}, {Vins, AADDL, O_r0, O_l_hi}, {V_f0, V_p0, Vend},};/* cast rp l to rp t */static uchar castrp[][VLEN] ={ {Vmv, O_l, O_t_lo}, {VT, Vins, AMOVL, O_t_lo, O_t_hi}, {VT, Vins, ASARL, C31, O_t_hi}, {VF, Vzero, O_t_hi}, {Vend},};/* cast rp l to addr t */static uchar castrpa[][VLEN] ={ {VT, V_a0, Vmv, O_l, O_r0}, {VT, Vins, AMOVL, O_r0, O_t_lo}, {VT, Vins, ASARL, C31, O_r0}, {VT, Vins, AMOVL, O_r0, O_t_hi}, {VT, V_f0}, {VF, Vmv, O_l, O_t_lo}, {VF, Vzero, O_t_hi}, {Vend},};static uchar netab0i[][VLEN] ={ {Vop, ONE, O_l_lo, O_r_lo}, {V_s0, Vop, ONE, O_l_hi, O_r_hi}, {V_s1, Vgo, V_s2, Vgo, V_s3}, {VF, V_p0, V_p1, VT, V_p2}, {Vgo, V_p3}, {VT, V_p0, V_p1, VF, V_p2}, {Vend},};static uchar netabii[][VLEN] ={ {V_a0, Vins, AMOVL, O_l_lo, O_r0}, {Vop, ONE, O_r0, O_r_lo}, {V_s0, Vins, AMOVL, O_l_hi, O_r0}, {Vop, ONE, O_r0, O_r_hi}, {V_s1, Vgo, V_s2, Vgo, V_s3}, {VF, V_p0, V_p1, VT, V_p2}, {Vgo, V_p3}, {VT, V_p0, V_p1, VF, V_p2}, {V_f0, Vend},};static uchar cmptab0i[][VLEN] ={ {Vopx, Bop0, O_l_hi, O_r_hi}, {V_s0, Vins0, AJNE}, {V_s1, Vopx, Bop1, O_l_lo, O_r_lo}, {V_s2, Vgo, V_s3, Vgo, V_s4}, {VT, V_p1, V_p3}, {VF, V_p0, V_p2}, {Vgo, V_p4}, {VT, V_p0, V_p2}, {VF, V_p1, V_p3}, {Vend},};static uchar cmptabii[][VLEN] ={ {V_a0, Vins, AMOVL, O_l_hi, O_r0}, {Vopx, Bop0, O_r0, O_r_hi}, {V_s0, Vins0, AJNE}, {V_s1, Vins, AMOVL, O_l_lo, O_r0}, {Vopx, Bop1, O_r0, O_r_lo}, {V_s2, Vgo, V_s3, Vgo, V_s4}, {VT, V_p1, V_p3}, {VF, V_p0, V_p2}, {Vgo, V_p4}, {VT, V_p0, V_p2}, {VF, V_p1, V_p3}, {V_f0, Vend},};static uchar (*NEtab[])[VLEN] ={ netab0i, netabii,};static uchar (*cmptab[])[VLEN] ={ cmptab0i, cmptabii,};static uchar GEargs[] = { OGT, OHS };static uchar GTargs[] = { OGT, OHI };static uchar HIargs[] = { OHI, OHI };static uchar HSargs[] = { OHI, OHS };/* Big Generator */static voidbiggen(Node *l, Node *r, Node *t, int true, uchar code[][VLEN], uchar *a){ int i, j, g, oc, op, lo, ro, to, xo, *xp; Type *lt; Prog *pr[VOPS]; Node *ot, *tl, *tr, tmps[2]; uchar *c, (*cp)[VLEN], args[VARGS]; if(a != nil) memmove(args, a, VARGS);//print("biggen %d %d %d\n", args[0], args[1], args[2]);//if(l) prtree(l, "l");//if(r) prtree(r, "r");//if(t) prtree(t, "t"); lo = ro = to = 0; cp = code; for (;;) { c = *cp++; g = 1; i = 0;//print("code %d %d %d %d %d\n", c[0], c[1], c[2], c[3], c[4]); for(;;) { switch(op = c[i]) { case Vgo: if(g) gbranch(OGOTO); i++; break; case Vamv: i += 3; if(i > VLEN) { diag(l, "bad Vop"); return; } if(g) args[c[i - 1]] = args[c[i - 2]]; break; case Vzero: i += 2; if(i > VLEN) { diag(l, "bad Vop"); return; } j = i - 1; goto op; case Vspazz: // nasty hack to save a reg in SUB//print("spazz\n"); if(g) {//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg); ot = r->right; r->right = r->left; tl = new(0, Z, Z); *tl = tmps[0]; r->left = tl; tmps[0] = *ot;//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg); } i++; break; case Vmv: case Vmul: case Vshll: i += 3; if(i > VLEN) { diag(l, "bad Vop"); return; } j = i - 2; goto op; case Vins0: i += 2; if(i > VLEN) { diag(l, "bad Vop"); return; } gins(c[i - 1], Z, Z); break; case Vop: case Vopx: case Vins: case Vinsl: case Vinsr: case Vinsla: case Vinsra: case Vinsx: i += 4; if(i > VLEN) { diag(l, "bad Vop"); return; } j = i - 2; goto op; op: if(!g) break; tl = Z; tr = Z; for(; j < i; j++) { switch(c[j]) { case C00: ot = nodconst(0); break; case C01: ot = nodconst(1); break; case C31: ot = nodconst(31); break; case C32: ot = nodconst(32); break; case O_l: case O_l_lo: ot = l; xp = &lo; xo = 0; goto op0; case O_l_hi: ot = l; xp = &lo; xo = SZ_LONG; goto op0; case O_r: case O_r_lo: ot = r; xp = &ro; xo = 0; goto op0; case O_r_hi: ot = r; xp = &ro; xo = SZ_LONG; goto op0; case O_t_lo: ot = t; xp = &to; xo = 0; goto op0; case O_t_hi: ot = t; xp = &to; xo = SZ_LONG; goto op0; case O_l_rp: ot = l; break; case O_r_rp: ot = r; break; case O_t_rp: ot = t; break; case O_r0: case O_r1: ot = &tmps[c[j] - O_r0]; break; case O_Zop: ot = Z; break; op0: switch(ot->op) { case OCONST: if(xo) ot = hi64(ot); else ot = lo64(ot); break; case OREGPAIR: if(xo) ot = ot->right; else ot = ot->left; break; case OREGISTER: break; default: if(xo != *xp) { ot->xoffset += xo - *xp; *xp = xo; } } break; default: diag(l, "bad V_lop"); return; } if(tl == nil) tl = ot; else tr = ot; } if(op == Vzero) { zeroregm(tl); break; } oc = c[i - 3]; if(op == Vinsx || op == Vopx) {//print("%d -> %d\n", oc, args[oc]); oc = args[oc]; } else { switch(oc) { case O_a0: case O_a1: oc = args[oc - O_a0]; break; } } switch(op) { case Vmul: mulgen(tr->type, tl, tr); break; case Vmv: gmove(tl, tr); break; case Vshll: shiftit(tr->type, tl, tr); break; case Vop: case Vopx: gopcode(oc, types[TULONG], tl, tr); break; case Vins: case Vinsx: gins(oc, tl, tr); break; case Vinsl: gins(oc, tl, tr->right); p->from.index = tr->left->reg; break; case Vinsr: gins(oc, tl, tr->left); p->from.index = tr->right->reg; break; case Vinsla: gins(oc, tl, tr + 1); p->from.index = tr->reg; break; case Vinsra: gins(oc, tl, tr); p->from.index = (tr + 1)->reg; break; } break; case VT: g = true; i++; break; case VF: g = !true; i++; break; case V_T0: case V_T1: g = args[op - V_T0]; i++; break; case V_F0: case V_F1: g = !args[op - V_F0]; i++; break; case V_C0: case V_C1: if(g) args[op - V_C0] = 0; i++; break; case V_S0: case V_S1: if(g) args[op - V_S0] = 1; i++; break; case V_l_lo_f: g = lo64v(l) == 0; i++; break; case V_l_hi_f: g = hi64v(l) == 0; i++; break; case V_l_lo_t: g = lo64v(l) != 0; i++; break; case V_l_hi_t: g = hi64v(l) != 0; i++; break; case V_l_lo_u: g = lo64v(l) >= 0; i++; break; case V_l_hi_u: g = hi64v(l) >= 0; i++; break; case V_r_lo_f: g = lo64v(r) == 0; i++; break; case V_r_hi_f: g = hi64v(r) == 0; i++; break; case V_r_lo_t: g = lo64v(r) != 0; i++; break; case V_r_hi_t: g = hi64v(r) != 0; i++; break; case V_r_lo_u: g = lo64v(r) >= 0; i++; break; case V_r_hi_u: g = hi64v(r) >= 0; i++; break; case Vend: goto out; case V_a0: case V_a1: if(g) { lt = l->type; l->type = types[TULONG]; regalloc(&tmps[op - V_a0], l, Z); l->type = lt; } i++; break; case V_f0: case V_f1: if(g) regfree(&tmps[op - V_f0]); i++; break; case V_p0: case V_p1: case V_p2: case V_p3: case V_p4: if(g) patch(pr[op - V_p0], pc); i++; break; case V_s0: case V_s1: case V_s2: case V_s3: case V_s4: if(g) pr[op - V_s0] = p; i++; break; default: diag(l, "bad biggen: %d", op); return; } if(i == VLEN || c[i] == 0) break; } }out: if(lo) l->xoffset -= lo; if(ro) r->xoffset -= ro; if(to) t->xoffset -= to;}intcgen64(Node *n, Node *nn){ Type *dt; uchar *args, (*cp)[VLEN], (**optab)[VLEN]; int li, ri, lri, dr, si, m, op, sh, cmp, true; Node *c, *d, *l, *r, *t, *s, nod1, nod2, nod3, nod4, nod5; if(debug['g']) { prtree(nn, "cgen64 lhs"); prtree(n, "cgen64"); print("AX = %d\n", reg[D_AX]); } cmp = 0; sh = 0; switch(n->op) { case ONEG: d = regpair(nn, n); sugen(n->left, d, 8); gins(ANOTL, Z, d->right); gins(ANEGL, Z, d->left); gins(ASBBL, nodconst(-1), d->right); break; case OCOM: if(!vaddr(n->left, 0) || !vaddr(nn, 0)) d = regpair(nn, n); else return 0; sugen(n->left, d, 8); gins(ANOTL, Z, d->left); gins(ANOTL, Z, d->right); break; case OADD: optab = ADDtab; args = ADDargs; goto twoop; case OAND: optab = ANDtab; args = ANDargs; goto twoop; case OOR: optab = ORtab; args = ORargs; goto twoop; case OSUB: optab = SUBtab; args = SUBargs; goto twoop; case OXOR: optab = ORtab; args = XORargs; goto twoop; case OASHL: sh = 1; args = nil; optab = shlltab; goto twoop; case OLSHR: sh = 1; args = shrlargs; optab = shrltab; goto twoop; case OASHR: sh = 1; args = sarlargs; optab = shrltab; goto twoop; case OEQ: cmp = 1; args = nil; optab = nil; goto twoop; case ONE: cmp = 1; args = nil; optab = nil; goto twoop; case OLE: cmp = 1; args = nil; optab = nil; goto twoop; case OLT: cmp = 1; args = nil; optab = nil; goto twoop; case OGE: cmp = 1; args = nil; optab = nil; goto twoop; case OGT: cmp = 1; args = nil; optab = nil; goto twoop; case OHI: cmp = 1; args = nil; optab = nil; goto twoop; case OHS: cmp = 1; args = nil; optab = nil; goto twoop; case OLO: cmp = 1; args = nil; optab = nil; goto twoop; case OLS: cmp = 1; args = nil; optab = nil; goto twoop;twoop: dr = nn != Z && nn->op == OREGPAIR; l = vfunc(n->left, nn); if(sh) r = n->right; else r = vfunc(n->right, nn); li = l->op == ONAME || l->op == OINDREG || l->op == OCONST; ri = r->op == ONAME || r->op == OINDREG || r->op == OCONST;#define IMM(l, r) ((l) | ((r) << 1)) lri = IMM(li, ri); /* find out what is so easy about some operands */ if(li) li = whatof(l, sh | cmp); if(ri) ri = whatof(r, cmp); if(sh) goto shift; if(cmp) goto cmp; /* evaluate hard subexps, stealing nn if possible. */ switch(lri) { case IMM(0, 0): bin00: if(l->complex > r->complex) { if(dr) t = nn; else t = regpair(Z, n); sugen(l, t, 8); l = t; t = regpair(Z, n); sugen(r, t, 8); r = t; } else { t = regpair(Z, n); sugen(r, t, 8); r = t; if(dr) t = nn; else t = regpair(Z, n); sugen(l, t, 8);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -