diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-01 18:51:47 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-01 18:51:47 +0200 |
commit | 6c4d8f8b11bf04959c920c0720a60949db038a65 (patch) | |
tree | d02b5c0638d213821e58eabfdd774aea8d970a67 /sys/src/cmd/8c | |
parent | 82f9f3df72fc1383da60ad66422f03508085c8f0 (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.c | 17 |
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); |