diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index 278b2ef69368d3cc36b50ccff92980e90b3882fc..5c2a8953b297e46ebfaa4cc468aa97a0b0396eac 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -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); } diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 362e649d03382bb22e1cc8ef68e00223cd8a8105..14ad872aa68f40e3c2f9ab1d34fb2c5eb5044964 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -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);