runtime: fix uint64->float32 conversion for softfloat
The fix for #48807 in CL 354429 forgot that we also need to fix
the softfloat implementation.
Update #48807
Change-Id: I596fb4e14e78145d1ad43c130b2cc5122b73655c
Reviewed-on: https://go-review.googlesource.com/c/go/+/354613
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/compile/internal/test/ssa_test.go b/src/cmd/compile/internal/test/ssa_test.go
index 2f3e24c..af7d962 100644
--- a/src/cmd/compile/internal/test/ssa_test.go
+++ b/src/cmd/compile/internal/test/ssa_test.go
@@ -162,7 +162,7 @@
}
flags := []string{""}
- if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
+ if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" || runtime.GOARCH == "386" {
flags = append(flags, ",softfloat")
}
for _, flag := range flags {
diff --git a/src/runtime/softfloat64.go b/src/runtime/softfloat64.go
index 084aa13..42ef009 100644
--- a/src/runtime/softfloat64.go
+++ b/src/runtime/softfloat64.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Software IEEE754 64-bit floating point.
-// Only referred to (and thus linked in) by arm port
+// Only referred to (and thus linked in) by softfloat targets
// and by tests in this directory.
package runtime
@@ -414,6 +414,25 @@
}
return fpack64(fs, mant, int(mantbits64), 0)
}
+func fintto32(val int64) (f uint32) {
+ fs := uint64(val) & (1 << 63)
+ mant := uint64(val)
+ if fs != 0 {
+ mant = -mant
+ }
+ // Reduce mantissa size until it fits into a uint32.
+ // Keep track of the bits we throw away, and if any are
+ // nonzero or them into the lowest bit.
+ exp := int(mantbits32)
+ var trunc uint32
+ for mant >= 1<<32 {
+ trunc |= uint32(mant) & 1
+ mant >>= 1
+ exp++
+ }
+
+ return fpack32(uint32(fs>>32), uint32(mant), exp, trunc)
+}
// 64x64 -> 128 multiply.
// adapted from hacker's delight.
@@ -493,6 +512,7 @@
}
func fdiv32(x, y uint32) uint32 {
+ // TODO: are there double-rounding problems here? See issue 48807.
return f64to32(fdiv64(f32to64(x), f32to64(y)))
}
@@ -527,7 +547,7 @@
}
func fint32to32(x int32) uint32 {
- return f64to32(fintto64(int64(x)))
+ return fintto32(int64(x))
}
func fint32to64(x int32) uint64 {
@@ -535,7 +555,7 @@
}
func fint64to32(x int64) uint32 {
- return f64to32(fintto64(x))
+ return fintto32(x)
}
func fint64to64(x int64) uint64 {
@@ -595,5 +615,13 @@
}
func fuint64to32(x uint64) uint32 {
- return f64to32(fuint64to64(x))
+ if int64(x) >= 0 {
+ return fint64to32(int64(x))
+ }
+ // See ../cmd/compile/internal/ssagen/ssa.go:uint64Tofloat
+ y := x & 1
+ z := x >> 1
+ z = z | y
+ r := fint64to32(int64(z))
+ return fadd32(r, r)
}