#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 falseLines 1–500 of 2711. Load more
#include "gc.h" void zeroregm(Node *n) { gins(AMOVL, nodconst(0), n); } /* do we need to load the address of a vlong? */ int vaddr(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; } long hi64v(Node *n) { if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ return (long)(n->vconst) & ~0L; else return (long)((uvlong)n->vconst>>32) & ~0L; } long lo64v(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 void evacaxdx(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 int instpair(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 void zapreg(Node *n) { if(n->reg != D_NONE) { regfree(n); n->reg = D_NONE; } } static void freepair(Node *n) { regfree(n->left); regfree(n->right); } /* n is not OREGPAIR, nn is */ void loadpair(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 void storepair(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 void cast(Node *n, Type *t, Node *nn) { Node *r; r = new(OCAST, n, Z); r->type = t; sugen(r, nn, 8); } static void swapregs(Node *a, Node *b) { int t; t = a->reg; a->reg = b->reg; b->reg = t; } static void swappairs(Node *a, Node *b) { swapregs(a->left, b->left); swapregs(a->right, b->right); } static int saveme(Node *n) { int r; r = n->reg; return r >= D_AX && r <= D_DI; } static void saveit(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 void restoreit(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 int whatof(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 int reduxv(Node *n) { return lo64v(n) == 0 || hi64v(n) == 0; } int cond(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 int forcereg(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 int getreg(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