big: potential bug fix, cleanups

- implemented setWord, use it where setUint64 is wrong
- divLarge: use fast mulWW, divWW; implemented mulWW, divWW
- better assembly code for addMulVVW

R=rsc
CC=golang-dev
https://golang.org/cl/1258042
diff --git a/src/pkg/big/nat.go b/src/pkg/big/nat.go
index 668a626..b098937 100755
--- a/src/pkg/big/nat.go
+++ b/src/pkg/big/nat.go
@@ -69,16 +69,20 @@
 }
 
 
-func (z nat) setUint64(x uint64) nat {
+func (z nat) setWord(x Word) nat {
 	if x == 0 {
 		return z.make(0)
 	}
+	z = z.make(1)
+	z[0] = x
+	return z
+}
 
+
+func (z nat) setUint64(x uint64) nat {
 	// single-digit values
-	if x == uint64(Word(x)) {
-		z = z.make(1)
-		z[0] = Word(x)
-		return z
+	if w := Word(x); uint64(w) == x {
+		return z.setWord(w)
 	}
 
 	// compute number of words n required to represent x
@@ -194,7 +198,7 @@
 func (z nat) mulAddWW(x nat, y, r Word) nat {
 	m := len(x)
 	if m == 0 || y == 0 {
-		return z.setUint64(uint64(r)) // result is r
+		return z.setWord(r) // result is r
 	}
 	// m > 0
 
@@ -529,6 +533,8 @@
 	m := len(uIn) - n
 
 	// determine if z can be reused
+	// TODO(gri) should find a better solution - this if statement
+	//           is very costly (see e.g. time pidigits -s -n 10000)
 	if alias(z, uIn) || alias(z, v) {
 		z = nil // z is an alias for uIn or v - cannot reuse
 	}
@@ -549,15 +555,13 @@
 	// D2.
 	for j := m; j >= 0; j-- {
 		// D3.
-		var qhat Word
-		if u[j+n] == v[n-1] {
-			qhat = _B - 1
-		} else {
+		qhat := Word(_M)
+		if u[j+n] != v[n-1] {
 			var rhat Word
-			qhat, rhat = divWW_g(u[j+n], u[j+n-1], v[n-1])
+			qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
 
 			// x1 | x2 = q̂v_{n-2}
-			x1, x2 := mulWW_g(qhat, v[n-2])
+			x1, x2 := mulWW(qhat, v[n-2])
 			// test if q̂v_{n-2} > br̂ + u_{j+n-2}
 			for greaterThan(x1, x2, rhat, u[j+n-2]) {
 				qhat--
@@ -567,7 +571,7 @@
 				if rhat < prevRhat {
 					break
 				}
-				x1, x2 = mulWW_g(qhat, v[n-2])
+				x1, x2 = mulWW(qhat, v[n-2])
 			}
 		}