Implement __bswap[sdt]i2 intrinsics

These can be emitted by gcc, at least if requested specifically via __builtin_bswap{32,64,128}.
This commit is contained in:
Andrey Turkin 2024-06-22 00:01:52 +03:00 committed by Amanieu d'Antras
parent 34aa493499
commit 45465cc488
5 changed files with 63 additions and 0 deletions

View file

@ -154,6 +154,9 @@ rely on CI.
- [ ] arm/unordsf2vfp.S
- [x] ashldi3.c
- [x] ashrdi3.c
- [x] bswapdi2.c
- [x] bswapsi2.c
- [x] bswapti2.c
- [x] comparedf2.c
- [x] comparesf2.c
- [x] divdf3.c

View file

@ -161,6 +161,9 @@ fn configure_check_cfg() {
"__ashlsi3",
"__ashrdi3",
"__ashrsi3",
"__bswapsi2",
"__bswapdi2",
"__bswapti2",
"__clzsi2",
"__divdi3",
"__divsi3",

View file

@ -0,0 +1,22 @@
intrinsics! {
#[maybe_use_optimized_c_shim]
#[avr_skip]
/// Swaps bytes in 32-bit number
pub extern "C" fn __bswapsi2(x: u32) -> u32 {
x.swap_bytes()
}
#[maybe_use_optimized_c_shim]
#[avr_skip]
/// Swaps bytes in 64-bit number
pub extern "C" fn __bswapdi2(x: u64) -> u64 {
x.swap_bytes()
}
#[maybe_use_optimized_c_shim]
#[avr_skip]
/// Swaps bytes in 128-bit number
pub extern "C" fn __bswapti2(x: u128) -> u128 {
x.swap_bytes()
}
}

View file

@ -4,6 +4,7 @@ mod specialized_div_rem;
pub mod addsub;
mod big;
pub mod bswap;
pub mod leading_zeros;
pub mod mul;
pub mod sdiv;

View file

@ -92,6 +92,40 @@ fn leading_zeros() {
})
}
#[test]
#[cfg(not(target_arch = "avr"))]
fn bswap() {
use compiler_builtins::int::bswap::{__bswapdi2, __bswapsi2};
fuzz(N, |x: u32| {
assert_eq!(x.swap_bytes(), __bswapsi2(x));
});
fuzz(N, |x: u64| {
assert_eq!(x.swap_bytes(), __bswapdi2(x));
});
assert_eq!(__bswapsi2(0x12345678u32), 0x78563412u32);
assert_eq!(__bswapsi2(0x00000001u32), 0x01000000u32);
assert_eq!(__bswapdi2(0x123456789ABCDEF0u64), 0xF0DEBC9A78563412u64);
assert_eq!(__bswapdi2(0x0200000001000000u64), 0x0000000100000002u64);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
{
use compiler_builtins::int::bswap::__bswapti2;
fuzz(N, |x: u128| {
assert_eq!(x.swap_bytes(), __bswapti2(x));
});
assert_eq!(
__bswapti2(0x123456789ABCDEF013579BDF02468ACEu128),
0xCE8A4602DF9B5713F0DEBC9A78563412u128
);
assert_eq!(
__bswapti2(0x04000000030000000200000001000000u128),
0x00000001000000020000000300000004u128
);
}
}
// This is approximate because of issues related to
// https://github.com/rust-lang/rust/issues/73920.
// TODO how do we resolve this indeterminacy?