diff options
Diffstat (limited to 'src/cmd/5g/cgen64.c')
-rw-r--r-- | src/cmd/5g/cgen64.c | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 1235d1ace..ef11e2adb 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -94,6 +94,7 @@ cgen64(Node *n, Node *res) case OAND: case OOR: case OXOR: + case OLROT: // binary operators. // common setup below. break; @@ -175,7 +176,7 @@ cgen64(Node *n, Node *res) p1->from.type = D_REG; p1->from.reg = bl.val.u.reg; p1->reg = ch.val.u.reg; - p1->to.type = D_REGREG; + p1->to.type = D_REGREG2; p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); @@ -185,7 +186,7 @@ cgen64(Node *n, Node *res) p1->from.type = D_REG; p1->from.reg = bh.val.u.reg; p1->reg = cl.val.u.reg; - p1->to.type = D_REGREG; + p1->to.type = D_REGREG2; p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); @@ -197,6 +198,47 @@ cgen64(Node *n, Node *res) break; + case OLROT: + // We only rotate by a constant c in [0,64). + // if c >= 32: + // lo, hi = hi, lo + // c -= 32 + // if c == 0: + // no-op + // else: + // t = hi + // shld hi:lo, c + // shld lo:t, c + v = mpgetfix(r->val.u.xval); + regalloc(&bl, lo1.type, N); + regalloc(&bh, hi1.type, N); + if(v >= 32) { + // reverse during load to do the first 32 bits of rotate + v -= 32; + gins(AMOVW, &hi1, &bl); + gins(AMOVW, &lo1, &bh); + } else { + gins(AMOVW, &hi1, &bh); + gins(AMOVW, &lo1, &bl); + } + if(v == 0) { + gins(AMOVW, &bh, &ah); + gins(AMOVW, &bl, &al); + } else { + // rotate by 1 <= v <= 31 + // MOVW bl<<v, al + // MOVW bh<<v, ah + // OR bl>>(32-v), ah + // OR bh>>(32-v), al + gshift(AMOVW, &bl, SHIFT_LL, v, &al); + gshift(AMOVW, &bh, SHIFT_LL, v, &ah); + gshift(AORR, &bl, SHIFT_LR, 32-v, &ah); + gshift(AORR, &bh, SHIFT_LR, 32-v, &al); + } + regfree(&bl); + regfree(&bh); + break; + case OLSH: regalloc(&bl, lo1.type, N); regalloc(&bh, hi1.type, N); @@ -243,7 +285,7 @@ cgen64(Node *n, Node *res) split64(r, &cl, &ch); gmove(&ch, &s); gins(ATST, &s, N); - p6 = gbranch(ABNE, T); + p6 = gbranch(ABNE, T, 0); gmove(&cl, &s); splitclean(); } else { @@ -257,7 +299,7 @@ cgen64(Node *n, Node *res) p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bh, &ah); p1->scond = C_SCOND_EQ; - p2 = gbranch(ABEQ, T); + p2 = gbranch(ABEQ, T, 0); // shift is < 32 nodconst(&n1, types[TUINT32], 32); @@ -281,14 +323,14 @@ cgen64(Node *n, Node *res) p1->scond = C_SCOND_LO; // BLO end - p3 = gbranch(ABLO, T); + p3 = gbranch(ABLO, T, 0); // shift == 32 p1 = gins(AEOR, &al, &al); p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bl, &ah); p1->scond = C_SCOND_EQ; - p4 = gbranch(ABEQ, T); + p4 = gbranch(ABEQ, T, 0); // shift is < 64 nodconst(&n1, types[TUINT32], 64); @@ -311,7 +353,7 @@ cgen64(Node *n, Node *res) p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah); p1->scond = C_SCOND_LO; - p5 = gbranch(ABLO, T); + p5 = gbranch(ABLO, T, 0); // shift >= 64 if (p6 != P) patch(p6, pc); @@ -406,7 +448,7 @@ olsh_break: else p1 = gins(AEOR, &ah, &ah); p1->scond = C_SCOND_NE; - p6 = gbranch(ABNE, T); + p6 = gbranch(ABNE, T, 0); gmove(&cl, &s); splitclean(); } else { @@ -420,7 +462,7 @@ olsh_break: p1->scond = C_SCOND_EQ; p1 = gins(AMOVW, &bh, &ah); p1->scond = C_SCOND_EQ; - p2 = gbranch(ABEQ, T); + p2 = gbranch(ABEQ, T, 0); // check if shift is < 32 nodconst(&n1, types[TUINT32], 32); @@ -449,7 +491,7 @@ olsh_break: p1->scond = C_SCOND_LO; // BLO end - p3 = gbranch(ABLO, T); + p3 = gbranch(ABLO, T, 0); // shift == 32 p1 = gins(AMOVW, &bh, &al); @@ -458,7 +500,7 @@ olsh_break: gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); else gins(AEOR, &ah, &ah); - p4 = gbranch(ABEQ, T); + p4 = gbranch(ABEQ, T, 0); // check if shift is < 64 nodconst(&n1, types[TUINT32], 64); @@ -484,7 +526,7 @@ olsh_break: } // BLO end - p5 = gbranch(ABLO, T); + p5 = gbranch(ABLO, T, 0); // s >= 64 if(p6 != P) @@ -633,7 +675,7 @@ orsh_break: * nl is memory; nr is constant or memory. */ void -cmp64(Node *nl, Node *nr, int op, Prog *to) +cmp64(Node *nl, Node *nr, int op, int likely, Prog *to) { Node lo1, hi1, lo2, hi2, r1, r2; Prog *br; @@ -663,14 +705,14 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // beq to // L: - br = gbranch(ABNE, T); + br = gbranch(ABNE, T, -likely); break; case ONE: // cmp hi // bne to // cmp lo // bne to - patch(gbranch(ABNE, T), to); + patch(gbranch(ABNE, T, likely), to); break; case OGE: case OGT: @@ -680,8 +722,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // bge to (or bgt to) // L: - patch(gbranch(optoas(OGT, t), T), to); - br = gbranch(optoas(OLT, t), T); + patch(gbranch(optoas(OGT, t), T, likely), to); + br = gbranch(optoas(OLT, t), T, -likely); break; case OLE: case OLT: @@ -691,8 +733,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // ble to (or jlt to) // L: - patch(gbranch(optoas(OLT, t), T), to); - br = gbranch(optoas(OGT, t), T); + patch(gbranch(optoas(OLT, t), T, likely), to); + br = gbranch(optoas(OGT, t), T, -likely); break; } @@ -707,7 +749,7 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) regfree(&r2); // jump again - patch(gbranch(optoas(op, t), T), to); + patch(gbranch(optoas(op, t), T, likely), to); // point first branch down here if appropriate if(br != P) |