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