-
Notifications
You must be signed in to change notification settings - Fork 379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cross v0.1.15 Breaks f32/f64 to_bits
on PowerPC
#313
Comments
Is this the same QEMU bug as in #314? |
@reitermarkus I doubt it's the same Qemu bug, but it appears to be another bug in Qemu. I'm attempting to diagnose which versions are currently affected now. Functionpub fn to_bits(f: f32) -> u32 {
f.to_bits()
} The x86 assembly is simple, just a move instruction, as we'd expect: example::to_bits:
mov eax, dword ptr [esp + 4]
ret The PowerPC assembly is as follows: example::to_bits:
stwu 1, -16(1)
stfs 1, 12(1)
lwz 3, 12(1)
addi 1, 1, 16
blr The PowerPC assembly for the type alias is identical: example::to_bits_alias:
stwu 1, -16(1)
stfs 1, 12(1)
lwz 3, 12(1)
addi 1, 1, 16
blr Run Instructions$ docker run \
-t -i \
-v ~/Desktop/sample/target:/target \
docker.io/rustembedded/cross:powerpc-unknown-linux-gnu-0.1.15 \
/bin/bash
# qemu-ppc --version
qemu-ppc version 4.1.0
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
# qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
8
2
$ docker run \
-t -i \
-v ~/Desktop/sample/target:/target \
docker.io/japaric/powerpc-unknown-linux-gnu:v0.1.14 \
/bin/bash
# qemu-ppc --version
qemu-ppc version 2.10.0
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
# qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
1
1 It seems like Qemu 4.10 is just spitting out garbage values. |
Versions:
I've tried other Qemu versions using: # Install dependencies
apt install curl python zlib1g-dev libglib2.0-dev libpixman-1-dev -y
# Download the Qemu from version
version=...
curl -L https://download.qemu.org/qemu-$version.tar.xz --output qemu-$version.tar.xz
tar xvf qemu-$version.tar.xz
# Build from source
cd qemu-$version
mkdir build && cd build
../configure --disable-kvm --target-list="ppc-linux-user"
make -j 5
# Test the Version
ppc-linux-user/qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample Results2.12.1 # ppc-linux-user/qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
1
1 3.0.1 # ppc-linux-user/qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
1
1 3.1.0 # ppc-linux-user/qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
8
2 3.1.1 # ppc-linux-user/qemu-ppc /target/powerpc-unknown-linux-gnu/debug/sample
8
2 |
@reitermarkus I'll file another upstream bug, in the meantime, since such rudimentary code is failing on PowerPC (just loads and stores), it might be prudent to use Qemu version 3.0.1 on PowerPC. |
Thanks. Can you submit a PR downgrading QEMU with a comment pointing to the upstream issue? |
@reitermarkus I believe it's a duplicate of this bug, since on further inspection, it affects both conversions to-and-from single-precision floats, but not double-precision floats. It seems to occur due to an internal conversion to a double, and was introduced in the same version I reported. I'll send the patch now. Codefn f32_to_bits(f: f32) -> u32 {
f.to_bits()
}
fn f32_to_bits_alias(f: f32) -> u32 {
let p = &f as *const f32;
let p = p as *const u32;
unsafe {
*p
}
}
fn f64_to_bits(f: f64) -> u64 {
f.to_bits()
}
fn f64_to_bits_alias(f: f64) -> u64 {
let p = &f as *const f64;
let p = p as *const u64;
unsafe {
*p
}
}
fn f32_from_bits(dw: u32) -> f32 {
f32::from_bits(dw)
}
fn f32_from_bits_alias(dw: u32) -> f32 {
let p = &dw as *const u32;
let p = p as *const f32;
unsafe {
*p
}
}
fn f64_from_bits(dw: u64) -> f64 {
f64::from_bits(dw)
}
fn f64_from_bits_alias(dw: u64) -> f64 {
let p = &dw as *const u64;
let p = p as *const f64;
unsafe {
*p
}
}
pub fn main() {
// Both have a single bit set, equivalent to 0x1.
let f: f32 = 1e-45;
let d: f64 = 5e-324;
println!("f32_to_bits={:?}", f32_to_bits(f));
println!("f32_to_bits_alias={:?}", f32_to_bits_alias(f));
println!("f64_to_bits={:?}", f64_to_bits(d));
println!("f64_to_bits_alias={:?}", f64_to_bits_alias(d));
let dw: u32 = 0x1;
let qw: u64 = 0x1;
println!("f32_from_bits={:?}", f32_from_bits(dw));
println!("f32_from_bits_alias={:?}", f32_from_bits_alias(dw));
println!("f64_from_bits={:?}", f64_from_bits(qw));
println!("f64_from_bits_alias={:?}", f64_from_bits_alias(qw));
} Resultsf32_to_bits=8
f32_to_bits_alias=2
f64_to_bits=1
f64_to_bits_alias=1
f32_from_bits=0.000000000000000000000000000000000000000000011
f32_from_bits_alias=0.000000000000000000000000000000000000000000003
f64_from_bits=0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
f64_from_bits_alias=0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005 |
The following code worked for cross v0.1.14, so any issues were introduced with the latest release.
Targets
Failing Code
Results
The value of
f.to_bits()
is4
, rather than1
, as expected, since1e-45
is the smallest denormal 32-bit floating point number. The direct type-pun through a pointer alias gets the correct value of1
. to_bits directly callsmem::transmute
, which should just pun the bytes to a new type.Explanation
The binary representation for the IEEE-754 single-precision floating point number 1e-45 is:
The first group is the sign bit, the second group is the exponent (including the hidden bit), and the third group is the significant digits (mantissa). The endianness of floats should be the same as integers on the architecture. Therefore,
f.to_bits()
should return1
, instead, for some unknown reason, it returns4
.Minimal Steps to Reproduce
cargo new --bin sample
).main.rs
.cross run --target powerpc-unknown-linux-gnu
).The text was updated successfully, but these errors were encountered: