the code generated for 64x64=64 was superficially plausible, but incorrect. the low-order words are unsigned regardless whether the 64-bit quantity is signed or unsigned, and the multiplication to form the high-order 32 bits of the 32x32=64 should therefore always be the unsigned version. Reference: /n/sources/patch/applied/qc-vlong-mul Date: Fri Jul 9 20:24:21 CES 2010 Signed-off-by: forsyth@terzarima.net --- /sys/src/cmd/qc/txt.c Fri Jul 9 20:22:45 2010 +++ /sys/src/cmd/qc/txt.c Fri Jul 9 20:22:41 2010 @@ -1493,15 +1493,12 @@ f2 = t; regalloc(&nod, ®node, Z); gins3(AMULLW, f1->right, f2->right, &nod); /* lo(f2.low*f1.low) */ - a1 = AMULHW; - if(o == OLMUL || o == OASLMUL) - a1 = AMULHWU; regalloc(&nod1, ®node, Z); - gins3(a1, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */ + gins3(AMULHWU, f1->right, f2->right, &nod1); /* hi(f2.low*f1.low) */ regalloc(&nod2, ®node, Z); gins3(AMULLW, f2->right, f1->left, &nod2); /* lo(f2.low*f1.high) */ gins(AADD, &nod2, &nod1); - gins3(AMULLW, f1->right, f2->left, &nod2); /* hi(f2.high*f1.low) */ + gins3(AMULLW, f1->right, f2->left, &nod2); /* lo(f2.high*f1.low) */ gins(AADD, &nod2, &nod1); regfree(&nod2); gmove(&nod, t->right);