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. Reference: /n/sources/patch/applied/8c-cgen64-mul-savereg Date: Sat Jun 1 16:28:29 CES 2013 Signed-off-by: charles.forsyth@gmail.com --- /sys/src/cmd/8c/cgen64.c Sat Jun 1 16:27:07 2013 +++ /sys/src/cmd/8c/cgen64.c Sat Jun 1 16:27:02 2013 @@ -127,6 +127,7 @@ zapreg(Node *n) { if(n->reg != D_NONE) { + //prtree(n, "zapreg"); regfree(n); n->reg = D_NONE; } @@ -2224,6 +2225,7 @@ 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 @@ }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 @@ 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 @@ } 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 @@ 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 @@ 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);