]> Cypherpunks repositories - gostls13.git/commitdiff
6g: save all 64 bits of AX/DX
authorRuss Cox <rsc@golang.org>
Wed, 12 Aug 2009 20:18:27 +0000 (13:18 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 12 Aug 2009 20:18:27 +0000 (13:18 -0700)
8g: save AX/DX around div

R=ken
OCL=33094
CL=33096

src/cmd/6g/ggen.c
src/cmd/8g/ggen.c

index 278b2ef69368d3cc36b50ccff92980e90b3882fc..5c2a8953b297e46ebfaa4cc468aa97a0b0396eac 100644 (file)
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 #undef EXTERN
 #define        EXTERN
 #include "gg.h"
@@ -531,17 +530,17 @@ savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
        int r;
 
        r = reg[dr];
-
        nodreg(x, types[TINT64], dr);
-       regalloc(x, t, x);
 
        // save current ax and dx if they are live
        // and not the destination
        memset(oldx, 0, sizeof *oldx);
        if(r > 0 && !samereg(x, res)) {
-               regalloc(oldx, t, N);
+               regalloc(oldx, types[TINT64], N);
                gmove(x, oldx);
        }
+
+       regalloc(x, t, x);
 }
 
 static void
@@ -550,6 +549,7 @@ restx(Node *x, Node *oldx)
        regfree(x);
 
        if(oldx->op != 0) {
+               x->type = types[TINT64];
                gmove(oldx, x);
                regfree(oldx);
        }
index 362e649d03382bb22e1cc8ef68e00223cd8a8105..14ad872aa68f40e3c2f9ab1d34fb2c5eb5044964 100644 (file)
@@ -524,27 +524,28 @@ samereg(Node *a, Node *b)
 void
 dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
 {
-       int a;
-       Node n3, n4;
+       Node n1, t1, t2, nz;
 
-       regalloc(&n3, t, res);
-       a = optoas(op, t);
+       tempalloc(&t1, nl->type);
+       tempalloc(&t2, nr->type);
+       cgen(nl, &t1);
+       cgen(nr, &t2);
 
-       if(nl->ullman >= UINF) {
-               cgen(nl, &n3);
-               gmove(&n3, ax);
-               cgen(nr, &n3);
-       } else {
-               cgen(nr, &n3);
-               cgen(nl, ax);
-       }
+       if(!samereg(ax, res) && !samereg(dx, res))
+               regalloc(&n1, t, res);
+       else
+               regalloc(&n1, t, N);
+       gmove(&t2, &n1);
+       gmove(&t1, ax);
        if(!issigned[t->etype]) {
-               nodconst(&n4, t, 0);
-               gmove(&n4, dx);
+               nodconst(&nz, t, 0);
+               gmove(&nz, dx);
        } else
                gins(optoas(OEXTEND, t), N, N);
-       gins(a, &n3, N);
-       regfree(&n3);
+       gins(optoas(op, t), &n1, N);
+       regfree(&n1);
+       tempfree(&t2);
+       tempfree(&t1);
 
        if(op == ODIV)
                gmove(ax, res);
@@ -552,6 +553,37 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
                gmove(dx, res);
 }
 
+static void
+savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
+{
+       int r;
+
+       r = reg[dr];
+       nodreg(x, types[TINT32], dr);
+
+       // save current ax and dx if they are live
+       // and not the destination
+       memset(oldx, 0, sizeof *oldx);
+       if(r > 0 && !samereg(x, res)) {
+               tempalloc(oldx, types[TINT32]);
+               gmove(x, oldx);
+       }
+
+       regalloc(x, t, x);
+}
+
+static void
+restx(Node *x, Node *oldx)
+{
+       regfree(x);
+
+       if(oldx->op != 0) {
+               x->type = types[TINT32];
+               gmove(oldx, x);
+               tempfree(oldx);
+       }
+}
+
 /*
  * generate division according to op, one of:
  *     res = nl / nr
@@ -560,7 +592,7 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
 void
 cgen_div(int op, Node *nl, Node *nr, Node *res)
 {
-       Node ax, dx;
+       Node ax, dx, oldax, olddx;
        int rax, rdx;
        Type *t;
 
@@ -574,15 +606,11 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
        if(t->width == 1)
                t = types[t->etype+2];  // int8 -> int16, uint8 -> uint16
 
-       nodreg(&ax, types[TINT32], D_AX);
-       nodreg(&dx, types[TINT32], D_DX);
-       regalloc(&ax, t, &ax);
-       regalloc(&dx, t, &dx);
-
+       savex(D_AX, &ax, &oldax, res, t);
+       savex(D_DX, &dx, &olddx, res, t);
        dodiv(op, t, nl, nr, res, &ax, &dx);
-
-       regfree(&ax);
-       regfree(&dx);
+       restx(&dx, &olddx);
+       restx(&ax, &oldax);
 }
 
 /*
@@ -601,9 +629,6 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
        if(nl->type->width > 4)
                fatal("cgen_shift %T", nl->type->width);
 
-       if(nl->type->width == 1 && nl->type->etype != TUINT8)
-               fatal("cgen_shift %T", nl->type);
-
        w = nl->type->width * 8;
 
        a = optoas(op, nl->type);
@@ -655,7 +680,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
        }
        patch(p1, pc);
        gins(a, &n1, &n2);
-       
+
        if(oldcx.op != 0) {
                gmove(&oldcx, &cx);
                regfree(&oldcx);