summaryrefslogtreecommitdiff
path: root/sys/src/cmd/8c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-06-01 18:51:47 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-06-01 18:51:47 +0200
commit6c4d8f8b11bf04959c920c0720a60949db038a65 (patch)
treed02b5c0638d213821e58eabfdd774aea8d970a67 /sys/src/cmd/8c
parent82f9f3df72fc1383da60ad66422f03508085c8f0 (diff)
8c: apply charles forsyth's 8c-cgen64-mul-savereg patch (from sources)
If 64-bit multiply has to save both AX and DX, it could load the wrong value into DX; also, biggen shouldn't allocate either AX or DX as temporaries when using the template for MUL.
Diffstat (limited to 'sys/src/cmd/8c')
-rw-r--r--sys/src/cmd/8c/cgen64.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/sys/src/cmd/8c/cgen64.c b/sys/src/cmd/8c/cgen64.c
index 6c4be5aa9..3077dad04 100644
--- a/sys/src/cmd/8c/cgen64.c
+++ b/sys/src/cmd/8c/cgen64.c
@@ -127,6 +127,7 @@ static void
zapreg(Node *n)
{
if(n->reg != D_NONE) {
+ //prtree(n, "zapreg");
regfree(n);
n->reg = D_NONE;
}
@@ -2224,6 +2225,7 @@ twoop:
t = nn;
else
t = regpair(Z, n);
+ //print("dr=%d ", dr); prtree(t, "t");
c = Z;
d = Z;
if(!nodreg(&nod1, t->left, D_AX)) {
@@ -2240,10 +2242,12 @@ twoop:
}else if(reg[D_DX] == 0)
fatal(Z, "vlong mul DX botch");
}
+ //prtree(t, "t1"); print("reg/ax = %d reg/dx = %d\n", reg[D_AX], reg[D_DX]);
if(m)
sugen(l, t, 8);
else
loadpair(l, t);
+ //prtree(t, "t2"); print("reg/ax = %d reg/dx = %d\n", reg[D_AX], reg[D_DX]);
if(t->left->reg != D_AX) {
c = &nod3;
regsalloc(c, t->left);
@@ -2251,11 +2255,16 @@ twoop:
gmove(t->left, &nod1);
zapreg(t->left);
}
+ //print("reg/ax = %d reg/dx = %d\n", reg[D_AX], reg[D_DX]);
if(t->right->reg != D_DX) {
d = &nod4;
regsalloc(d, t->right);
gmove(&nod2, d);
- gmove(t->right, &nod2);
+ if(t->right->reg == D_AX && c != nil){
+ /* need previous value of AX in DX */
+ gmove(c, &nod2);
+ }else
+ gmove(t->right, &nod2);
zapreg(t->right);
}
if(c != Z || d != Z) {
@@ -2265,6 +2274,8 @@ twoop:
}
else
s = t;
+ reg[D_AX]++; /* don't allow biggen to allocate AX or DX (smashed by MUL) as temp */
+ reg[D_DX]++;
if(r->op == OCONST) {
if(hi64v(r) == 0)
biggen(s, r, Z, 0, mulc32, nil);
@@ -2274,6 +2285,8 @@ twoop:
else
biggen(s, r, Z, 0, mull, nil);
instpair(t, Z);
+ reg[D_AX]--;
+ reg[D_DX]--;
if(c != Z) {
gmove(&nod1, t->left);
gmove(&nod3, &nod1);
@@ -2282,12 +2295,14 @@ twoop:
gmove(&nod2, t->right);
gmove(&nod4, &nod2);
}
+
if(r->op == OREGPAIR)
freepair(r);
if(!m)
storepair(t, l, 0);
if(l == &nod5)
regfree(l);
+
if(!dr) {
if(nn != Z)
storepair(t, nn, 1);