diff options
Diffstat (limited to 'src/cmd/8g/cgen64.c')
-rw-r--r-- | src/cmd/8g/cgen64.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/src/cmd/8g/cgen64.c b/src/cmd/8g/cgen64.c index 8e568a0f9..dc50a409b 100644 --- a/src/cmd/8g/cgen64.c +++ b/src/cmd/8g/cgen64.c @@ -49,6 +49,7 @@ cgen64(Node *n, Node *res) case OADD: case OSUB: case OMUL: + case OLROT: case OLSH: case ORSH: case OAND: @@ -113,9 +114,9 @@ cgen64(Node *n, Node *res) // if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply. gins(AMOVL, &dx, &fx); gins(AORL, &ex, &fx); - p1 = gbranch(AJNE, T); + p1 = gbranch(AJNE, T, 0); gins(AMULL, &cx, N); // implicit &ax - p2 = gbranch(AJMP, T); + p2 = gbranch(AJMP, T, 0); patch(p1, pc); // full 64x64 -> 64, from 32x32 -> 64. @@ -131,6 +132,40 @@ cgen64(Node *n, Node *res) regfree(&ex); regfree(&fx); 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); + if(v >= 32) { + // reverse during load to do the first 32 bits of rotate + v -= 32; + gins(AMOVL, &lo1, &dx); + gins(AMOVL, &hi1, &ax); + } else { + gins(AMOVL, &lo1, &ax); + gins(AMOVL, &hi1, &dx); + } + if(v == 0) { + // done + } else { + gins(AMOVL, &dx, &cx); + p1 = gins(ASHLL, ncon(v), &dx); + p1->from.index = D_AX; // double-width shift + p1->from.scale = 0; + p1 = gins(ASHLL, ncon(v), &ax); + p1->from.index = D_CX; // double-width shift + p1->from.scale = 0; + } + break; case OLSH: if(r->op == OLITERAL) { @@ -178,7 +213,7 @@ cgen64(Node *n, Node *res) p1 = P; if(is64(r->type)) { gins(ACMPL, &hi2, ncon(0)); - p1 = gbranch(AJNE, T); + p1 = gbranch(AJNE, T, +1); gins(AMOVL, &lo2, &cx); } else { cx.type = types[TUINT32]; @@ -187,7 +222,7 @@ cgen64(Node *n, Node *res) // if shift count is >=64, zero value gins(ACMPL, &cx, ncon(64)); - p2 = gbranch(optoas(OLT, types[TUINT32]), T); + p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1); if(p1 != P) patch(p1, pc); gins(AXORL, &dx, &dx); @@ -196,11 +231,11 @@ cgen64(Node *n, Node *res) // if shift count is >= 32, zero low. gins(ACMPL, &cx, ncon(32)); - p1 = gbranch(optoas(OLT, types[TUINT32]), T); + p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1); gins(AMOVL, &ax, &dx); gins(ASHLL, &cx, &dx); // SHLL only uses bottom 5 bits of count gins(AXORL, &ax, &ax); - p2 = gbranch(AJMP, T); + p2 = gbranch(AJMP, T, 0); patch(p1, pc); // general shift @@ -267,7 +302,7 @@ cgen64(Node *n, Node *res) p1 = P; if(is64(r->type)) { gins(ACMPL, &hi2, ncon(0)); - p1 = gbranch(AJNE, T); + p1 = gbranch(AJNE, T, +1); gins(AMOVL, &lo2, &cx); } else { cx.type = types[TUINT32]; @@ -276,7 +311,7 @@ cgen64(Node *n, Node *res) // if shift count is >=64, zero or sign-extend value gins(ACMPL, &cx, ncon(64)); - p2 = gbranch(optoas(OLT, types[TUINT32]), T); + p2 = gbranch(optoas(OLT, types[TUINT32]), T, +1); if(p1 != P) patch(p1, pc); if(hi1.type->etype == TINT32) { @@ -290,7 +325,7 @@ cgen64(Node *n, Node *res) // if shift count is >= 32, sign-extend hi. gins(ACMPL, &cx, ncon(32)); - p1 = gbranch(optoas(OLT, types[TUINT32]), T); + p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1); gins(AMOVL, &dx, &ax); if(hi1.type->etype == TINT32) { gins(ASARL, &cx, &ax); // SARL only uses bottom 5 bits of count @@ -299,7 +334,7 @@ cgen64(Node *n, Node *res) gins(ASHRL, &cx, &ax); gins(AXORL, &dx, &dx); } - p2 = gbranch(AJMP, T); + p2 = gbranch(AJMP, T, 0); patch(p1, pc); // general shift @@ -427,7 +462,7 @@ out:; * 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, rr; Prog *br; @@ -457,14 +492,14 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // jeq to // L: - br = gbranch(AJNE, T); + br = gbranch(AJNE, T, -likely); break; case ONE: // cmp hi // jne to // cmp lo // jne to - patch(gbranch(AJNE, T), to); + patch(gbranch(AJNE, T, likely), to); break; case OGE: case OGT: @@ -474,8 +509,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // jge to (or jgt 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: @@ -485,8 +520,8 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) // cmp lo // jle 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; } @@ -502,7 +537,7 @@ cmp64(Node *nl, Node *nr, int op, Prog *to) } // 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) |