Skip to content

Commit 4940f05

Browse files
committed
Implement __bswap[si]i2 intrinsics
These can be emitted by gcc, at least if requested specifically via __builtin_bswap{32,64}.
1 parent 0ccc1bf commit 4940f05

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ fn configure_check_cfg() {
161161
"__ashlsi3",
162162
"__ashrdi3",
163163
"__ashrsi3",
164+
"__bswapsi2",
165+
"__bswapdi2",
164166
"__clzsi2",
165167
"__divdi3",
166168
"__divsi3",

src/int/bswap.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
intrinsics! {
2+
#[maybe_use_optimized_c_shim]
3+
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
4+
/// Swaps bytes in 32-bit number
5+
pub extern "C" fn __bswapsi2(x: u32) -> u32 {
6+
(x & 0xff000000u32) >> 24 |
7+
(x & 0x00ff0000u32) >> 8 |
8+
(x & 0x0000ff00u32) << 8 |
9+
(x & 0x000000ffu32) << 24
10+
}
11+
12+
#[maybe_use_optimized_c_shim]
13+
#[cfg(target_pointer_width = "32")]
14+
/// Swaps bytes in 64-bit number
15+
pub extern "C" fn __bswapdi2(x: u64) -> u64 {
16+
__bswapsi2((x >> 32) as u32) as u64 |
17+
(__bswapsi2(x as u32) as u64) << 32
18+
}
19+
20+
#[maybe_use_optimized_c_shim]
21+
#[cfg(target_pointer_width = "64")]
22+
/// Swaps bytes in 64-bit number
23+
pub extern "C" fn __bswapdi2(x: u64) -> u64 {
24+
let x = (x & 0xff000000ff000000u64) >> 24 |
25+
(x & 0x00ff000000ff0000u64) >> 8 |
26+
(x & 0x0000ff000000ff00u64) << 8 |
27+
(x & 0x000000ff000000ffu64) << 24;
28+
x << 32 | x >> 32
29+
}
30+
}

src/int/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod specialized_div_rem;
44

55
pub mod addsub;
66
mod big;
7+
pub mod bswap;
78
pub mod leading_zeros;
89
pub mod mul;
910
pub mod sdiv;

testcrate/tests/misc.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,47 @@ fn leading_zeros() {
9292
})
9393
}
9494

95+
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
96+
#[test]
97+
fn bswap() {
98+
use compiler_builtins::int::bswap::{__bswapdi2, __bswapsi2};
99+
fuzz(N, |x: u32| {
100+
let x_std = x.swap_bytes();
101+
let x_intr = __bswapsi2(x);
102+
if x_std != x_intr {
103+
panic!("__bswapsi2({}): std: {}, builtins: {}", x, x_std, x_intr);
104+
}
105+
});
106+
fuzz(N, |x: u64| {
107+
let x_std = x.swap_bytes();
108+
let x_intr = __bswapdi2(x);
109+
if x_std != x_intr {
110+
panic!("__bswapdi2({}): std: {}, builtins: {}", x, x_std, x_intr);
111+
}
112+
});
113+
114+
let mut x1 = 0x12345678u32;
115+
let mut sw1 = __bswapsi2(x1);
116+
if sw1 != 0x78563412u32 {
117+
panic!("__bswapsi2({}): {}", x1, sw1);
118+
}
119+
x1 = 0x00000001u32;
120+
sw1 = __bswapsi2(x1);
121+
if sw1 != 0x01000000u32 {
122+
panic!("__bswapsi2({}): {}", x1, sw1);
123+
}
124+
let mut x2 = 0x123456789ABCDEF0u64;
125+
let mut sw2 = __bswapdi2(x2);
126+
if sw2 != 0xF0DEBC9A78563412u64 {
127+
panic!("__bswapdi2({}): {}", x2, sw2);
128+
}
129+
x2 = 0x0000000100000002u64;
130+
sw2 = __bswapdi2(x2);
131+
if sw2 != 0x0200000001000000u64 {
132+
panic!("__bswapdi2({}): {}", x2, sw2);
133+
}
134+
}
135+
95136
// This is approximate because of issues related to
96137
// https://github.com/rust-lang/rust/issues/73920.
97138
// TODO how do we resolve this indeterminacy?

0 commit comments

Comments
 (0)