summaryrefslogtreecommitdiff
path: root/src/cmd/5g/cgen64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/cgen64.c')
-rw-r--r--src/cmd/5g/cgen64.c82
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)