📄 cgen64.c
字号:
#include "gc.h"voidzeroregm(Node *n){ gins(AMOVL, nodconst(0), n);}/* do we need to load the address of a vlong? */intvaddr(Node *n, int a){ switch(n->op) { case ONAME: if(a) return 1; return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC); case OCONST: case OREGISTER: case OINDREG: return 1; } return 0;}longhi64v(Node *n){ if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ return (long)(n->vconst) & ~0L; else return (long)((uvlong)n->vconst>>32) & ~0L;}longlo64v(Node *n){ if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ return (long)((uvlong)n->vconst>>32) & ~0L; else return (long)(n->vconst) & ~0L;}Node *hi64(Node *n){ return nodconst(hi64v(n));}Node *lo64(Node *n){ return nodconst(lo64v(n));}static Node *anonreg(void){ Node *n; n = new(OREGISTER, Z, Z); n->reg = D_NONE; n->type = types[TLONG]; return n;}static Node *regpair(Node *n, Node *t){ Node *r; if(n != Z && n->op == OREGPAIR) return n; r = new(OREGPAIR, anonreg(), anonreg()); if(n != Z) r->type = n->type; else r->type = t->type; return r;}static voidevacaxdx(Node *r){ Node nod1, nod2; if(r->reg == D_AX || r->reg == D_DX) { reg[D_AX]++; reg[D_DX]++; /* * this is just an optim that should * check for spill */ r->type = types[TULONG]; regalloc(&nod1, r, Z); nodreg(&nod2, Z, r->reg); gins(AMOVL, &nod2, &nod1); regfree(r); r->reg = nod1.reg; reg[D_AX]--; reg[D_DX]--; }}/* lazy instantiation of register pair */static intinstpair(Node *n, Node *l){ int r; r = 0; if(n->left->reg == D_NONE) { if(l != Z) { n->left->reg = l->reg; r = 1; } else regalloc(n->left, n->left, Z); } if(n->right->reg == D_NONE) regalloc(n->right, n->right, Z); return r;}static voidzapreg(Node *n){ if(n->reg != D_NONE) { regfree(n); n->reg = D_NONE; }}static voidfreepair(Node *n){ regfree(n->left); regfree(n->right);}/* n is not OREGPAIR, nn is */voidloadpair(Node *n, Node *nn){ Node nod; instpair(nn, Z); if(n->op == OCONST) { gins(AMOVL, lo64(n), nn->left); n->xoffset += SZ_LONG; gins(AMOVL, hi64(n), nn->right); n->xoffset -= SZ_LONG; return; } if(!vaddr(n, 0)) { /* steal the right register for the laddr */ nod = regnode; nod.reg = nn->right->reg; lcgen(n, &nod); n = &nod; regind(n, n); n->xoffset = 0; } gins(AMOVL, n, nn->left); n->xoffset += SZ_LONG; gins(AMOVL, n, nn->right); n->xoffset -= SZ_LONG;}/* n is OREGPAIR, nn is not */static voidstorepair(Node *n, Node *nn, int f){ Node nod; if(!vaddr(nn, 0)) { reglcgen(&nod, nn, Z); nn = &nod; } gins(AMOVL, n->left, nn); nn->xoffset += SZ_LONG; gins(AMOVL, n->right, nn); nn->xoffset -= SZ_LONG; if(nn == &nod) regfree(&nod); if(f) freepair(n);}/* generate a cast t from n to tt */static voidcast(Node *n, Type *t, Node *nn){ Node *r; r = new(OCAST, n, Z); r->type = t; sugen(r, nn, 8);}static voidswapregs(Node *a, Node *b){ int t; t = a->reg; a->reg = b->reg; b->reg = t;}static voidswappairs(Node *a, Node *b){ swapregs(a->left, b->left); swapregs(a->right, b->right);}static intsaveme(Node *n){ int r; r = n->reg; return r >= D_AX && r <= D_DI;}static voidsaveit(Node *n, Node *t, Node *r){ Node nod; if(saveme(n)) { t->reg = n->reg; gins(AMOVL, t, r); r->xoffset += SZ_LONG; if(n->reg == D_AX) { regalloc(&nod, n, Z); regfree(n); n->reg = nod.reg; } }}static voidrestoreit(Node *n, Node *t, Node *r){ if(saveme(n)) { t->reg = n->reg; gins(AMOVL, r, t); r->xoffset += SZ_LONG; }}enum{/* 4 only, see WW */ WNONE = 0, WCONST, WADDR, WHARD,};static intwhatof(Node *n, int a){ if(n->op == OCONST) return WCONST; return !vaddr(n, a) ? WHARD : WADDR;}/* can upgrade an extern to addr for AND */static intreduxv(Node *n){ return lo64v(n) == 0 || hi64v(n) == 0;}intcond(int op){ switch(op) { case OANDAND: case OOROR: case ONOT: return 1; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OHI: case OHS: case OLO: case OLS: return 1; } return 0;}/* * for a func operand call it and then return * the safe node */static Node *vfunc(Node *n, Node *nn){ Node *t; if(n->op != OFUNC) return n; t = new(0, Z, Z); if(nn == Z || nn == nodret) nn = n; regsalloc(t, nn); sugen(n, t, 8); return t;}static intforcereg(Node *d, int r, int o, Node *t){ int a; if(d->reg != D_NONE) diag(Z, "force alloc"); d->reg = r; a = 0; if(reg[r]) { reg[o]++; regalloc(t, d, Z); a = 1; gins(AMOVL, d, t); reg[o]--; } reg[r]++; return a;}/* try to steal a reg */static intgetreg(Node **np, Node *t, int r){ Node *n, *p; n = *np; if(n->reg == r) { p = new(0, Z, Z); regalloc(p, n, Z); gins(AMOVL, n, p); *t = *n; *np = p; return 1; } return 0;}static Node *snarfreg(Node *n, Node *t, int r, Node *d, Node *c){ if(n == Z || n->op != OREGPAIR || (!getreg(&n->left, t, r) && !getreg(&n->right, t, r))) { if(nodreg(t, Z, r)) { regalloc(c, d, Z); gins(AMOVL, t, c); reg[r]++; return c; } reg[r]++; } return Z;}enum{ Vstart = OEND, Vgo, Vamv, Vmv, Vzero, Vop, Vopx, Vins, Vins0, Vinsl, Vinsr, Vinsla, Vinsra, Vinsx, Vmul, Vshll, VT, VF, V_l_lo_f, V_l_hi_f, V_l_lo_t, V_l_hi_t, V_l_lo_u, V_l_hi_u, V_r_lo_f, V_r_hi_f, V_r_lo_t, V_r_hi_t, V_r_lo_u, V_r_hi_u, Vspazz, Vend, V_T0, V_T1, V_F0, V_F1, V_a0, V_a1, V_f0, V_f1, V_p0, V_p1, V_p2, V_p3, V_p4, V_s0, V_s1, V_s2, V_s3, V_s4, C00, C01, C31, C32, O_l_lo, O_l_hi, O_r_lo, O_r_hi, O_t_lo, O_t_hi, O_l, O_r, O_l_rp, O_r_rp, O_t_rp, O_r0, O_r1, O_Zop, O_a0, O_a1, V_C0, V_C1, V_S0, V_S1, VOPS = 5, VLEN = 5, VARGS = 2, S00 = 0, Sc0, Sc1, Sc2, Sac3, Sac4, S10, SAgen = 0, SAclo, SAc32, SAchi, SAdgen, SAdclo, SAdc32, SAdchi, B0c = 0, Bca, Bac, T0i = 0, Tii, Bop0 = 0, Bop1,};/* * _testv: * CMPL lo,$0 * JNE true * CMPL hi,$0 * JNE true * GOTO false * false: * GOTO code * true: * GOTO patchme * code: */static uchar testi[][VLEN] ={ {Vop, ONE, O_l_lo, C00}, {V_s0, Vop, ONE, O_l_hi, C00}, {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},};/* shift left general case */static uchar shll00[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vinsl, ASHLL, O_r, O_l_rp}, {Vins, ASHLL, O_r, O_l_lo, Vgo}, {V_p0, V_s0}, {Vins, ASHLL, O_r, O_l_lo}, {Vins, AMOVL, O_l_lo, O_l_hi}, {Vzero, O_l_lo, V_p0, Vend},};/* shift left rp, const < 32 */static uchar shllc0[][VLEN] ={ {Vinsl, ASHLL, O_r, O_l_rp}, {Vshll, O_r, O_l_lo, Vend},};/* shift left rp, const == 32 */static uchar shllc1[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_l_hi}, {Vzero, O_l_lo, Vend},};/* shift left rp, const > 32 */static uchar shllc2[][VLEN] ={ {Vshll, O_r, O_l_lo}, {Vins, AMOVL, O_l_lo, O_l_hi}, {Vzero, O_l_lo, Vend},};/* shift left addr, const == 32 */static uchar shllac3[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_hi}, {Vzero, O_t_lo, Vend},};/* shift left addr, const > 32 */static uchar shllac4[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_hi}, {Vshll, O_r, O_t_hi}, {Vzero, O_t_lo, Vend},};/* shift left of constant */static uchar shll10[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsl, ASHLL, O_r, O_t_rp}, {Vins, ASHLL, O_r, O_t_lo, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_lo, O_t_hi}, {V_l_lo_t, Vins, ASHLL, O_r, O_t_hi}, {Vzero, O_t_lo, V_p0, Vend},};static uchar (*shlltab[])[VLEN] ={ shll00, shllc0, shllc1, shllc2, shllac3, shllac4, shll10,};/* shift right general case */static uchar shrl00[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vinsr, ASHRL, O_r, O_l_rp}, {Vins, O_a0, O_r, O_l_hi, Vgo}, {V_p0, V_s0}, {Vins, O_a0, O_r, O_l_hi}, {Vins, AMOVL, O_l_hi, O_l_lo}, {V_T1, Vzero, O_l_hi}, {V_F1, Vins, ASARL, C31, O_l_hi}, {V_p0, Vend},};/* shift right rp, const < 32 */static uchar shrlc0[][VLEN] ={ {Vinsr, ASHRL, O_r, O_l_rp}, {Vins, O_a0, O_r, O_l_hi, Vend},};/* shift right rp, const == 32 */static uchar shrlc1[][VLEN] ={ {Vins, AMOVL, O_l_hi, O_l_lo}, {V_T1, Vzero, O_l_hi}, {V_F1, Vins, ASARL, C31, O_l_hi}, {Vend},};/* shift right rp, const > 32 */static uchar shrlc2[][VLEN] ={ {Vins, O_a0, O_r, O_l_hi}, {Vins, AMOVL, O_l_hi, O_l_lo}, {V_T1, Vzero, O_l_hi}, {V_F1, Vins, ASARL, C31, O_l_hi}, {Vend},};/* shift right addr, const == 32 */static uchar shrlac3[][VLEN] ={ {Vins, AMOVL, O_l_hi, O_t_lo}, {V_T1, Vzero, O_t_hi}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {Vend},};/* shift right addr, const > 32 */static uchar shrlac4[][VLEN] ={ {Vins, AMOVL, O_l_hi, O_t_lo}, {Vins, O_a0, O_r, O_t_lo}, {V_T1, Vzero, O_t_hi}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {Vend},};/* shift right of constant */static uchar shrl10[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsr, ASHRL, O_r, O_t_rp}, {Vins, O_a0, O_r, O_t_hi, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_hi, O_t_lo}, {V_l_hi_t, Vins, O_a0, O_r, O_t_lo}, {V_l_hi_u, V_S1}, {V_T1, Vzero, O_t_hi, V_p0}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {Vend},};static uchar (*shrltab[])[VLEN] ={ shrl00, shrlc0, shrlc1, shrlc2, shrlac3, shrlac4, shrl10,};/* shift asop left general case */static uchar asshllgen[][VLEN] ={ {V_a0, V_a1}, {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_r0}, {Vins, AMOVL, O_l_hi, O_r1}, {Vinsla, ASHLL, O_r, O_r0}, {Vins, ASHLL, O_r, O_r0}, {Vins, AMOVL, O_r1, O_l_hi}, {Vins, AMOVL, O_r0, O_l_lo, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_lo, O_r0}, {Vzero, O_l_lo}, {Vins, ASHLL, O_r, O_r0}, {Vins, AMOVL, O_r0, O_l_hi, V_p0}, {V_f0, V_f1, Vend},};/* shift asop left, const < 32 */static uchar asshllclo[][VLEN] ={ {V_a0, V_a1}, {Vins, AMOVL, O_l_lo, O_r0}, {Vins, AMOVL, O_l_hi, O_r1}, {Vinsla, ASHLL, O_r, O_r0}, {Vshll, O_r, O_r0}, {Vins, AMOVL, O_r1, O_l_hi}, {Vins, AMOVL, O_r0, O_l_lo}, {V_f0, V_f1, Vend},};/* shift asop left, const == 32 */static uchar asshllc32[][VLEN] ={ {V_a0}, {Vins, AMOVL, O_l_lo, O_r0}, {Vzero, O_l_lo}, {Vins, AMOVL, O_r0, O_l_hi}, {V_f0, Vend},};/* shift asop left, const > 32 */static uchar asshllchi[][VLEN] ={ {V_a0}, {Vins, AMOVL, O_l_lo, O_r0}, {Vzero, O_l_lo}, {Vshll, O_r, O_r0}, {Vins, AMOVL, O_r0, O_l_hi}, {V_f0, Vend},};/* shift asop dest left general case */static uchar asdshllgen[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsl, ASHLL, O_r, O_t_rp}, {Vins, ASHLL, O_r, O_t_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vins, AMOVL, O_t_lo, O_l_lo, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_lo, O_t_hi}, {Vzero, O_l_lo}, {Vins, ASHLL, O_r, O_t_hi}, {Vzero, O_t_lo}, {Vins, AMOVL, O_t_hi, O_l_hi, V_p0}, {Vend},};/* shift asop dest left, const < 32 */static uchar asdshllclo[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsl, ASHLL, O_r, O_t_rp}, {Vshll, O_r, O_t_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vend},};/* shift asop dest left, const == 32 */static uchar asdshllc32[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_hi}, {Vzero, O_t_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vend},};/* shift asop dest, const > 32 */static uchar asdshllchi[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_hi}, {Vzero, O_t_lo}, {Vshll, O_r, O_t_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vend},};static uchar (*asshlltab[])[VLEN] ={ asshllgen, asshllclo, asshllc32, asshllchi, asdshllgen, asdshllclo, asdshllc32, asdshllchi,};/* shift asop right general case */static uchar asshrlgen[][VLEN] ={ {V_a0, V_a1}, {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_r0}, {Vins, AMOVL, O_l_hi, O_r1}, {Vinsra, ASHRL, O_r, O_r0}, {Vinsx, Bop0, O_r, O_r1}, {Vins, AMOVL, O_r0, O_l_lo}, {Vins, AMOVL, O_r1, O_l_hi, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_hi, O_r0}, {Vinsx, Bop0, O_r, O_r0}, {V_T1, Vzero, O_l_hi}, {Vins, AMOVL, O_r0, O_l_lo}, {V_F1, Vins, ASARL, C31, O_r0}, {V_F1, Vins, AMOVL, O_r0, O_l_hi}, {V_p0, V_f0, V_f1, Vend},};/* shift asop right, const < 32 */static uchar asshrlclo[][VLEN] ={ {V_a0, V_a1}, {Vins, AMOVL, O_l_lo, O_r0}, {Vins, AMOVL, O_l_hi, O_r1}, {Vinsra, ASHRL, O_r, O_r0}, {Vinsx, Bop0, O_r, O_r1}, {Vins, AMOVL, O_r0, O_l_lo}, {Vins, AMOVL, O_r1, O_l_hi}, {V_f0, V_f1, Vend},};/* shift asop right, const == 32 */static uchar asshrlc32[][VLEN] ={ {V_a0}, {Vins, AMOVL, O_l_hi, O_r0}, {V_T1, Vzero, O_l_hi}, {Vins, AMOVL, O_r0, O_l_lo}, {V_F1, Vins, ASARL, C31, O_r0}, {V_F1, Vins, AMOVL, O_r0, O_l_hi}, {V_f0, Vend},};/* shift asop right, const > 32 */static uchar asshrlchi[][VLEN] ={ {V_a0}, {Vins, AMOVL, O_l_hi, O_r0}, {V_T1, Vzero, O_l_hi}, {Vinsx, Bop0, O_r, O_r0}, {Vins, AMOVL, O_r0, O_l_lo}, {V_F1, Vins, ASARL, C31, O_r0}, {V_F1, Vins, AMOVL, O_r0, O_l_hi}, {V_f0, Vend},};/* shift asop dest right general case */static uchar asdshrlgen[][VLEN] ={ {Vop, OGE, O_r, C32}, {V_s0, Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsr, ASHRL, O_r, O_t_rp}, {Vinsx, Bop0, O_r, O_t_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vins, AMOVL, O_t_hi, O_l_hi, Vgo}, {V_p0, V_s0}, {Vins, AMOVL, O_l_hi, O_t_lo}, {V_T1, Vzero, O_t_hi}, {Vinsx, Bop0, O_r, O_t_lo}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {Vins, AMOVL, O_t_hi, O_l_hi, V_p0}, {Vend},};/* shift asop dest right, const < 32 */static uchar asdshrlclo[][VLEN] ={ {Vins, AMOVL, O_l_lo, O_t_lo}, {Vins, AMOVL, O_l_hi, O_t_hi}, {Vinsr, ASHRL, O_r, O_t_rp}, {Vinsx, Bop0, O_r, O_t_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vend},};/* shift asop dest right, const == 32 */static uchar asdshrlc32[][VLEN] ={ {Vins, AMOVL, O_l_hi, O_t_lo}, {V_T1, Vzero, O_t_hi}, {V_F1, Vins, AMOVL, O_t_lo, O_t_hi}, {V_F1, Vins, ASARL, C31, O_t_hi}, {Vins, AMOVL, O_t_lo, O_l_lo}, {Vins, AMOVL, O_t_hi, O_l_hi}, {Vend},};/* shift asop dest, const > 32 */static uchar asdshrlchi[][VLEN] ={ {Vins, AMOVL, O_l_hi, O_t_lo}, {V_T1, Vzero, O_t_hi}, {Vinsx, Bop0, O_r, O_t_lo},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -