Commit dd5f3233 authored by Russ Cox's avatar Russ Cox

6g: save all 64 bits of AX/DX

8g: save AX/DX around div

R=ken
OCL=33094
CL=33096
parent 66bb399f
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#undef EXTERN #undef EXTERN
#define EXTERN #define EXTERN
#include "gg.h" #include "gg.h"
...@@ -531,17 +530,17 @@ savex(int dr, Node *x, Node *oldx, Node *res, Type *t) ...@@ -531,17 +530,17 @@ savex(int dr, Node *x, Node *oldx, Node *res, Type *t)
int r; int r;
r = reg[dr]; r = reg[dr];
nodreg(x, types[TINT64], dr); nodreg(x, types[TINT64], dr);
regalloc(x, t, x);
// save current ax and dx if they are live // save current ax and dx if they are live
// and not the destination // and not the destination
memset(oldx, 0, sizeof *oldx); memset(oldx, 0, sizeof *oldx);
if(r > 0 && !samereg(x, res)) { if(r > 0 && !samereg(x, res)) {
regalloc(oldx, t, N); regalloc(oldx, types[TINT64], N);
gmove(x, oldx); gmove(x, oldx);
} }
regalloc(x, t, x);
} }
static void static void
...@@ -550,6 +549,7 @@ restx(Node *x, Node *oldx) ...@@ -550,6 +549,7 @@ restx(Node *x, Node *oldx)
regfree(x); regfree(x);
if(oldx->op != 0) { if(oldx->op != 0) {
x->type = types[TINT64];
gmove(oldx, x); gmove(oldx, x);
regfree(oldx); regfree(oldx);
} }
......
...@@ -524,27 +524,28 @@ samereg(Node *a, Node *b) ...@@ -524,27 +524,28 @@ samereg(Node *a, Node *b)
void void
dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
{ {
int a; Node n1, t1, t2, nz;
Node n3, n4;
regalloc(&n3, t, res); tempalloc(&t1, nl->type);
a = optoas(op, t); tempalloc(&t2, nr->type);
cgen(nl, &t1);
cgen(nr, &t2);
if(nl->ullman >= UINF) { if(!samereg(ax, res) && !samereg(dx, res))
cgen(nl, &n3); regalloc(&n1, t, res);
gmove(&n3, ax); else
cgen(nr, &n3); regalloc(&n1, t, N);
} else { gmove(&t2, &n1);
cgen(nr, &n3); gmove(&t1, ax);
cgen(nl, ax);
}
if(!issigned[t->etype]) { if(!issigned[t->etype]) {
nodconst(&n4, t, 0); nodconst(&nz, t, 0);
gmove(&n4, dx); gmove(&nz, dx);
} else } else
gins(optoas(OEXTEND, t), N, N); gins(optoas(OEXTEND, t), N, N);
gins(a, &n3, N); gins(optoas(op, t), &n1, N);
regfree(&n3); regfree(&n1);
tempfree(&t2);
tempfree(&t1);
if(op == ODIV) if(op == ODIV)
gmove(ax, res); gmove(ax, res);
...@@ -552,6 +553,37 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) ...@@ -552,6 +553,37 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
gmove(dx, res); 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: * generate division according to op, one of:
* res = nl / nr * res = nl / nr
...@@ -560,7 +592,7 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) ...@@ -560,7 +592,7 @@ dodiv(int op, Type *t, Node *nl, Node *nr, Node *res, Node *ax, Node *dx)
void void
cgen_div(int op, Node *nl, Node *nr, Node *res) cgen_div(int op, Node *nl, Node *nr, Node *res)
{ {
Node ax, dx; Node ax, dx, oldax, olddx;
int rax, rdx; int rax, rdx;
Type *t; Type *t;
...@@ -574,15 +606,11 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) ...@@ -574,15 +606,11 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
if(t->width == 1) if(t->width == 1)
t = types[t->etype+2]; // int8 -> int16, uint8 -> uint16 t = types[t->etype+2]; // int8 -> int16, uint8 -> uint16
nodreg(&ax, types[TINT32], D_AX); savex(D_AX, &ax, &oldax, res, t);
nodreg(&dx, types[TINT32], D_DX); savex(D_DX, &dx, &olddx, res, t);
regalloc(&ax, t, &ax);
regalloc(&dx, t, &dx);
dodiv(op, t, nl, nr, res, &ax, &dx); dodiv(op, t, nl, nr, res, &ax, &dx);
restx(&dx, &olddx);
regfree(&ax); restx(&ax, &oldax);
regfree(&dx);
} }
/* /*
...@@ -601,9 +629,6 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) ...@@ -601,9 +629,6 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
if(nl->type->width > 4) if(nl->type->width > 4)
fatal("cgen_shift %T", nl->type->width); 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; w = nl->type->width * 8;
a = optoas(op, nl->type); a = optoas(op, nl->type);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment