Go prebuilts for linux-x86, version 1.4.1

See README.ANDROID for instructions on rebuilding the prebuilts.

Change-Id: I86db7f4fb3269585078da4d38947ca9126ac813b
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
new file mode 100644
index 0000000..6afd75c
--- /dev/null
+++ b/src/cmd/gc/mparith3.c
@@ -0,0 +1,346 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include	<u.h>
+#include	<libc.h>
+#include	"go.h"
+
+/*
+ * returns the leading non-zero
+ * word of the number
+ */
+int
+sigfig(Mpflt *a)
+{
+	int i;
+
+	for(i=Mpprec-1; i>=0; i--)
+		if(a->val.a[i] != 0)
+			break;
+//print("sigfig %d %d\n", i-z+1, z);
+	return i+1;
+}
+
+/*
+ * sets the exponent.
+ * a too large exponent is an error.
+ * a too small exponent rounds the number to zero.
+ */
+void
+mpsetexp(Mpflt *a, int exp) {
+	if((short)exp != exp) {
+		if(exp > 0) {
+			yyerror("float constant is too large");
+			a->exp = 0x7fff;
+		}
+		else {
+			mpmovecflt(a, 0);
+		}
+	}
+	else {
+		a->exp = exp;
+	}
+}
+
+/*
+ * shifts the leading non-zero
+ * word of the number to Mpnorm
+ */
+void
+mpnorm(Mpflt *a)
+{
+	int s, os;
+	long x;
+
+	os = sigfig(a);
+	if(os == 0) {
+		// zero
+		a->exp = 0;
+		a->val.neg = 0;
+		return;
+	}
+
+	// this will normalize to the nearest word
+	x = a->val.a[os-1];
+	s = (Mpnorm-os) * Mpscale;
+
+	// further normalize to the nearest bit
+	for(;;) {
+		x <<= 1;
+		if(x & Mpbase)
+			break;
+		s++;
+		if(x == 0) {
+			// this error comes from trying to
+			// convert an Inf or something
+			// where the initial x=0x80000000
+			s = (Mpnorm-os) * Mpscale;
+			break;
+		}
+	}
+
+	mpshiftfix(&a->val, s);
+	mpsetexp(a, a->exp-s);
+}
+
+/// implements float arihmetic
+
+void
+mpaddfltflt(Mpflt *a, Mpflt *b)
+{
+	int sa, sb, s;
+	Mpflt c;
+
+	if(Mpdebug)
+		print("\n%F + %F", a, b);
+
+	sa = sigfig(a);
+	if(sa == 0) {
+		mpmovefltflt(a, b);
+		goto out;
+	}
+
+	sb = sigfig(b);
+	if(sb == 0)
+		goto out;
+
+	s = a->exp - b->exp;
+	if(s > 0) {
+		// a is larger, shift b right
+		mpmovefltflt(&c, b);
+		mpshiftfix(&c.val, -s);
+		mpaddfixfix(&a->val, &c.val, 0);
+		goto out;
+	}
+	if(s < 0) {
+		// b is larger, shift a right
+		mpshiftfix(&a->val, s);
+		mpsetexp(a, a->exp-s);
+		mpaddfixfix(&a->val, &b->val, 0);
+		goto out;
+	}
+	mpaddfixfix(&a->val, &b->val, 0);
+
+out:
+	mpnorm(a);
+	if(Mpdebug)
+		print(" = %F\n\n", a);
+}
+
+void
+mpmulfltflt(Mpflt *a, Mpflt *b)
+{
+	int sa, sb;
+
+	if(Mpdebug)
+		print("%F\n * %F\n", a, b);
+
+	sa = sigfig(a);
+	if(sa == 0) {
+		// zero
+		a->exp = 0;
+		a->val.neg = 0;
+		return;
+	}
+
+	sb = sigfig(b);
+	if(sb == 0) {
+		// zero
+		mpmovefltflt(a, b);
+		return;
+	}
+
+	mpmulfract(&a->val, &b->val);
+	mpsetexp(a, (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1);
+
+	mpnorm(a);
+	if(Mpdebug)
+		print(" = %F\n\n", a);
+}
+
+void
+mpdivfltflt(Mpflt *a, Mpflt *b)
+{
+	int sa, sb;
+	Mpflt c;
+
+	if(Mpdebug)
+		print("%F\n / %F\n", a, b);
+
+	sb = sigfig(b);
+	if(sb == 0) {
+		// zero and ovfl
+		a->exp = 0;
+		a->val.neg = 0;
+		a->val.ovf = 1;
+		yyerror("constant division by zero");
+		return;
+	}
+
+	sa = sigfig(a);
+	if(sa == 0) {
+		// zero
+		a->exp = 0;
+		a->val.neg = 0;
+		return;
+	}
+
+	// adjust b to top
+	mpmovefltflt(&c, b);
+	mpshiftfix(&c.val, Mpscale);
+
+	// divide
+	mpdivfract(&a->val, &c.val);
+	mpsetexp(a, (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1);
+
+	mpnorm(a);
+	if(Mpdebug)
+		print(" = %F\n\n", a);
+}
+
+static double
+mpgetfltN(Mpflt *a, int prec, int bias)
+{
+	int s, i, e, minexp;
+	uvlong v;
+	double f;
+
+	if(a->val.ovf && nsavederrors+nerrors == 0)
+		yyerror("mpgetflt ovf");
+
+	s = sigfig(a);
+	if(s == 0)
+		return 0;
+
+	if(s != Mpnorm) {
+		yyerror("mpgetflt norm");
+		mpnorm(a);
+	}
+
+	while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
+		mpshiftfix(&a->val, 1);
+		mpsetexp(a, a->exp-1);	// can set 'a' to zero
+		s = sigfig(a);
+		if(s == 0)
+			return 0;
+	}
+
+	// pick up the mantissa, a rounding bit, and a tie-breaking bit in a uvlong
+	s = prec+2;
+	v = 0;
+	for(i=Mpnorm-1; s>=Mpscale; i--) {
+		v = (v<<Mpscale) | a->val.a[i];
+		s -= Mpscale;
+	}
+	if(s > 0) {
+		v = (v<<s) | (a->val.a[i]>>(Mpscale-s));
+		if((a->val.a[i]&((1<<(Mpscale-s))-1)) != 0)
+			v |= 1;
+		i--;
+	}
+	for(; i >= 0; i--) {
+		if(a->val.a[i] != 0)
+			v |= 1;
+	}
+
+	// gradual underflow
+	e = Mpnorm*Mpscale + a->exp - prec;
+	minexp = bias+1-prec+1;
+	if(e < minexp) {
+		s = minexp - e;
+		if(s > prec+1)
+			s = prec+1;
+		if((v & ((1ULL<<s)-1)) != 0)
+			v |= 1ULL<<s;
+		v >>= s;
+		e = minexp;
+	}
+	
+	// round to even
+	v |= (v&4)>>2;
+	v += v&1;
+	v >>= 2;
+
+	f = (double)(v);
+	f = ldexp(f, e);
+
+	if(a->val.neg)
+		f = -f;
+
+	return f;
+}
+
+double
+mpgetflt(Mpflt *a)
+{
+	return mpgetfltN(a, 53, -1023);
+}
+
+double
+mpgetflt32(Mpflt *a)
+{
+	return mpgetfltN(a, 24, -127);
+}
+
+void
+mpmovecflt(Mpflt *a, double c)
+{
+	int i;
+	double f;
+	long l;
+
+	if(Mpdebug)
+		print("\nconst %g", c);
+	mpmovecfix(&a->val, 0);
+	a->exp = 0;
+	if(c == 0)
+		goto out;
+	if(c < 0) {
+		a->val.neg = 1;
+		c = -c;
+	}
+
+	f = frexp(c, &i);
+	a->exp = i;
+
+	for(i=0; i<10; i++) {
+		f = f*Mpbase;
+		l = floor(f);
+		f = f - l;
+		a->exp -= Mpscale;
+		a->val.a[0] = l;
+		if(f == 0)
+			break;
+		mpshiftfix(&a->val, Mpscale);
+	}
+
+out:
+	mpnorm(a);
+	if(Mpdebug)
+		print(" = %F\n", a);
+}
+
+void
+mpnegflt(Mpflt *a)
+{
+	a->val.neg ^= 1;
+}
+
+int
+mptestflt(Mpflt *a)
+{
+	int s;
+
+	if(Mpdebug)
+		print("\n%F?", a);
+	s = sigfig(a);
+	if(s != 0) {
+		s = +1;
+		if(a->val.neg)
+			s = -1;
+	}
+	if(Mpdebug)
+		print(" = %d\n", s);
+	return s;
+}