From: Keith Randall Date: Thu, 7 Oct 2021 20:29:09 +0000 (-0700) Subject: runtime: fix uint64->float32 conversion for softfloat X-Git-Tag: go1.18beta1~969 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=16a3cefc93d9b896b2053320e387d0e449904aba;p=gostls13.git 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 Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/test/ssa_test.go b/src/cmd/compile/internal/test/ssa_test.go index 2f3e24c2d3..af7d9626f9 100644 --- a/src/cmd/compile/internal/test/ssa_test.go +++ b/src/cmd/compile/internal/test/ssa_test.go @@ -162,7 +162,7 @@ func TestCode(t *testing.T) { } 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 084aa132d9..42ef009297 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 @@ func fintto64(val int64) (f uint64) { } 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 fmul32(x, y uint32) uint32 { } 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 fge64(x, y uint64) bool { } func fint32to32(x int32) uint32 { - return f64to32(fintto64(int64(x))) + return fintto32(int64(x)) } func fint32to64(x int32) uint64 { @@ -535,7 +555,7 @@ func fint32to64(x int32) uint64 { } func fint64to32(x int64) uint32 { - return f64to32(fintto64(x)) + return fintto32(x) } func fint64to64(x int64) uint64 { @@ -595,5 +615,13 @@ func fuint64to64(x uint64) uint64 { } 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) }