Created
August 30, 2025 16:52
-
-
Save iximeow/511c13c3b5aa4897f63e7ebc23b385c1 to your computer and use it in GitHub Desktop.
bswap x86
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// welcome to another: ixi wrote a stupid one-off .rs | |
| /// | |
| /// `rustc -C opt-level=3 bswap_x86.rs` and have fun | |
| static mut LAST: u32 = 0; | |
| macro_rules! bench { | |
| ($testname:ident, $fn:ident) => { | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn $testname(num: u32) { | |
| for _ in 0..10_000_000usize { | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); $fn(num); | |
| } | |
| } | |
| } | |
| } | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn swap_builtin(num: u32) -> u32 { | |
| let l = num.reverse_bits(); | |
| unsafe { LAST = l }; | |
| l | |
| } | |
| bench!(test_swap_builtin, swap_builtin); | |
| static LUT: [u8; 256] = [ | |
| 0x00u8.reverse_bits(), 0x01u8.reverse_bits(), 0x02u8.reverse_bits(), 0x03u8.reverse_bits(), | |
| 0x04u8.reverse_bits(), 0x05u8.reverse_bits(), 0x06u8.reverse_bits(), 0x07u8.reverse_bits(), | |
| 0x08u8.reverse_bits(), 0x09u8.reverse_bits(), 0x0au8.reverse_bits(), 0x0bu8.reverse_bits(), | |
| 0x0cu8.reverse_bits(), 0x0du8.reverse_bits(), 0x0eu8.reverse_bits(), 0x0fu8.reverse_bits(), | |
| 0x10u8.reverse_bits(), 0x11u8.reverse_bits(), 0x12u8.reverse_bits(), 0x13u8.reverse_bits(), | |
| 0x14u8.reverse_bits(), 0x15u8.reverse_bits(), 0x16u8.reverse_bits(), 0x17u8.reverse_bits(), | |
| 0x18u8.reverse_bits(), 0x19u8.reverse_bits(), 0x1au8.reverse_bits(), 0x1bu8.reverse_bits(), | |
| 0x1cu8.reverse_bits(), 0x1du8.reverse_bits(), 0x1eu8.reverse_bits(), 0x1fu8.reverse_bits(), | |
| 0x20u8.reverse_bits(), 0x21u8.reverse_bits(), 0x22u8.reverse_bits(), 0x23u8.reverse_bits(), | |
| 0x24u8.reverse_bits(), 0x25u8.reverse_bits(), 0x26u8.reverse_bits(), 0x27u8.reverse_bits(), | |
| 0x28u8.reverse_bits(), 0x29u8.reverse_bits(), 0x2au8.reverse_bits(), 0x2bu8.reverse_bits(), | |
| 0x2cu8.reverse_bits(), 0x2du8.reverse_bits(), 0x2eu8.reverse_bits(), 0x2fu8.reverse_bits(), | |
| 0x30u8.reverse_bits(), 0x31u8.reverse_bits(), 0x32u8.reverse_bits(), 0x33u8.reverse_bits(), | |
| 0x34u8.reverse_bits(), 0x35u8.reverse_bits(), 0x36u8.reverse_bits(), 0x37u8.reverse_bits(), | |
| 0x38u8.reverse_bits(), 0x39u8.reverse_bits(), 0x3au8.reverse_bits(), 0x3bu8.reverse_bits(), | |
| 0x3cu8.reverse_bits(), 0x3du8.reverse_bits(), 0x3eu8.reverse_bits(), 0x3fu8.reverse_bits(), | |
| 0x40u8.reverse_bits(), 0x41u8.reverse_bits(), 0x42u8.reverse_bits(), 0x43u8.reverse_bits(), | |
| 0x44u8.reverse_bits(), 0x45u8.reverse_bits(), 0x46u8.reverse_bits(), 0x47u8.reverse_bits(), | |
| 0x48u8.reverse_bits(), 0x49u8.reverse_bits(), 0x4au8.reverse_bits(), 0x4bu8.reverse_bits(), | |
| 0x4cu8.reverse_bits(), 0x4du8.reverse_bits(), 0x4eu8.reverse_bits(), 0x4fu8.reverse_bits(), | |
| 0x50u8.reverse_bits(), 0x51u8.reverse_bits(), 0x52u8.reverse_bits(), 0x53u8.reverse_bits(), | |
| 0x54u8.reverse_bits(), 0x55u8.reverse_bits(), 0x56u8.reverse_bits(), 0x57u8.reverse_bits(), | |
| 0x58u8.reverse_bits(), 0x59u8.reverse_bits(), 0x5au8.reverse_bits(), 0x5bu8.reverse_bits(), | |
| 0x5cu8.reverse_bits(), 0x5du8.reverse_bits(), 0x5eu8.reverse_bits(), 0x5fu8.reverse_bits(), | |
| 0x60u8.reverse_bits(), 0x61u8.reverse_bits(), 0x62u8.reverse_bits(), 0x63u8.reverse_bits(), | |
| 0x64u8.reverse_bits(), 0x65u8.reverse_bits(), 0x66u8.reverse_bits(), 0x67u8.reverse_bits(), | |
| 0x68u8.reverse_bits(), 0x69u8.reverse_bits(), 0x6au8.reverse_bits(), 0x6bu8.reverse_bits(), | |
| 0x6cu8.reverse_bits(), 0x6du8.reverse_bits(), 0x6eu8.reverse_bits(), 0x6fu8.reverse_bits(), | |
| 0x70u8.reverse_bits(), 0x71u8.reverse_bits(), 0x72u8.reverse_bits(), 0x73u8.reverse_bits(), | |
| 0x74u8.reverse_bits(), 0x75u8.reverse_bits(), 0x76u8.reverse_bits(), 0x77u8.reverse_bits(), | |
| 0x78u8.reverse_bits(), 0x79u8.reverse_bits(), 0x7au8.reverse_bits(), 0x7bu8.reverse_bits(), | |
| 0x7cu8.reverse_bits(), 0x7du8.reverse_bits(), 0x7eu8.reverse_bits(), 0x7fu8.reverse_bits(), | |
| 0x80u8.reverse_bits(), 0x81u8.reverse_bits(), 0x82u8.reverse_bits(), 0x83u8.reverse_bits(), | |
| 0x84u8.reverse_bits(), 0x85u8.reverse_bits(), 0x86u8.reverse_bits(), 0x87u8.reverse_bits(), | |
| 0x88u8.reverse_bits(), 0x89u8.reverse_bits(), 0x8au8.reverse_bits(), 0x8bu8.reverse_bits(), | |
| 0x8cu8.reverse_bits(), 0x8du8.reverse_bits(), 0x8eu8.reverse_bits(), 0x8fu8.reverse_bits(), | |
| 0x90u8.reverse_bits(), 0x91u8.reverse_bits(), 0x92u8.reverse_bits(), 0x93u8.reverse_bits(), | |
| 0x94u8.reverse_bits(), 0x95u8.reverse_bits(), 0x96u8.reverse_bits(), 0x97u8.reverse_bits(), | |
| 0x98u8.reverse_bits(), 0x99u8.reverse_bits(), 0x9au8.reverse_bits(), 0x9bu8.reverse_bits(), | |
| 0x9cu8.reverse_bits(), 0x9du8.reverse_bits(), 0x9eu8.reverse_bits(), 0x9fu8.reverse_bits(), | |
| 0xa0u8.reverse_bits(), 0xa1u8.reverse_bits(), 0xa2u8.reverse_bits(), 0xa3u8.reverse_bits(), | |
| 0xa4u8.reverse_bits(), 0xa5u8.reverse_bits(), 0xa6u8.reverse_bits(), 0xa7u8.reverse_bits(), | |
| 0xa8u8.reverse_bits(), 0xa9u8.reverse_bits(), 0xaau8.reverse_bits(), 0xabu8.reverse_bits(), | |
| 0xacu8.reverse_bits(), 0xadu8.reverse_bits(), 0xaeu8.reverse_bits(), 0xafu8.reverse_bits(), | |
| 0xb0u8.reverse_bits(), 0xb1u8.reverse_bits(), 0xb2u8.reverse_bits(), 0xb3u8.reverse_bits(), | |
| 0xb4u8.reverse_bits(), 0xb5u8.reverse_bits(), 0xb6u8.reverse_bits(), 0xb7u8.reverse_bits(), | |
| 0xb8u8.reverse_bits(), 0xb9u8.reverse_bits(), 0xbau8.reverse_bits(), 0xbbu8.reverse_bits(), | |
| 0xbcu8.reverse_bits(), 0xbdu8.reverse_bits(), 0xbeu8.reverse_bits(), 0xbfu8.reverse_bits(), | |
| 0xc0u8.reverse_bits(), 0xc1u8.reverse_bits(), 0xc2u8.reverse_bits(), 0xc3u8.reverse_bits(), | |
| 0xc4u8.reverse_bits(), 0xc5u8.reverse_bits(), 0xc6u8.reverse_bits(), 0xc7u8.reverse_bits(), | |
| 0xc8u8.reverse_bits(), 0xc9u8.reverse_bits(), 0xcau8.reverse_bits(), 0xcbu8.reverse_bits(), | |
| 0xccu8.reverse_bits(), 0xcdu8.reverse_bits(), 0xceu8.reverse_bits(), 0xcfu8.reverse_bits(), | |
| 0xd0u8.reverse_bits(), 0xd1u8.reverse_bits(), 0xd2u8.reverse_bits(), 0xd3u8.reverse_bits(), | |
| 0xd4u8.reverse_bits(), 0xd5u8.reverse_bits(), 0xd6u8.reverse_bits(), 0xd7u8.reverse_bits(), | |
| 0xd8u8.reverse_bits(), 0xd9u8.reverse_bits(), 0xdau8.reverse_bits(), 0xdbu8.reverse_bits(), | |
| 0xdcu8.reverse_bits(), 0xddu8.reverse_bits(), 0xdeu8.reverse_bits(), 0xdfu8.reverse_bits(), | |
| 0xe0u8.reverse_bits(), 0xe1u8.reverse_bits(), 0xe2u8.reverse_bits(), 0xe3u8.reverse_bits(), | |
| 0xe4u8.reverse_bits(), 0xe5u8.reverse_bits(), 0xe6u8.reverse_bits(), 0xe7u8.reverse_bits(), | |
| 0xe8u8.reverse_bits(), 0xe9u8.reverse_bits(), 0xeau8.reverse_bits(), 0xebu8.reverse_bits(), | |
| 0xecu8.reverse_bits(), 0xedu8.reverse_bits(), 0xeeu8.reverse_bits(), 0xefu8.reverse_bits(), | |
| 0xf0u8.reverse_bits(), 0xf1u8.reverse_bits(), 0xf2u8.reverse_bits(), 0xf3u8.reverse_bits(), | |
| 0xf4u8.reverse_bits(), 0xf5u8.reverse_bits(), 0xf6u8.reverse_bits(), 0xf7u8.reverse_bits(), | |
| 0xf8u8.reverse_bits(), 0xf9u8.reverse_bits(), 0xfau8.reverse_bits(), 0xfbu8.reverse_bits(), | |
| 0xfcu8.reverse_bits(), 0xfdu8.reverse_bits(), 0xfeu8.reverse_bits(), 0xffu8.reverse_bits(), | |
| ]; | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn swap_lut(num: u32) -> u32 { | |
| let buf = num.to_le_bytes(); | |
| let b0 = LUT[buf[0] as usize]; | |
| let b1 = LUT[buf[1] as usize]; | |
| let b2 = LUT[buf[2] as usize]; | |
| let b3 = LUT[buf[3] as usize]; | |
| let l = u32::from_le_bytes([b0, b1, b2, b3]); | |
| unsafe { LAST = l }; | |
| l | |
| } | |
| bench!(test_swap_lut, swap_lut); | |
| macro_rules! bench_prearrayed { | |
| ($testname:ident, $fn:ident) => { | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn $testname(buf: &mut [u8; 4]) { | |
| for _ in 0..10_000_000usize { | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); $fn(buf); | |
| } | |
| } | |
| } | |
| } | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn swap_lut_prearrayed(buf: &mut [u8; 4]) { | |
| let b0 = LUT[buf[0] as usize]; | |
| let b1 = LUT[buf[1] as usize]; | |
| let b2 = LUT[buf[2] as usize]; | |
| let b3 = LUT[buf[3] as usize]; | |
| buf[0] = b3; | |
| buf[1] = b2; | |
| buf[2] = b1; | |
| buf[3] = b0; | |
| } | |
| bench_prearrayed!(test_swap_lut_prearrayed, swap_lut_prearrayed); | |
| #[unsafe(no_mangle)] | |
| #[inline(never)] | |
| fn swap_builtin_prearrayed(buf: &mut [u8; 4]) { | |
| let b = u32::from_le_bytes(*buf); | |
| *buf = b.reverse_bits().to_le_bytes() | |
| } | |
| bench_prearrayed!(test_swap_builtin_prearrayed, swap_builtin_prearrayed); | |
| pub fn main() { | |
| let mut args = std::env::args(); | |
| let me = args.next().expect("i have a name"); | |
| let dword = &args as *const _ as usize as u32; | |
| let mode = args.next(); | |
| match mode.as_ref().map(|m| m.as_str()) { | |
| Some("swap_builtin") => test_swap_builtin(dword), | |
| Some("swap_lut") => test_swap_lut(dword), | |
| Some("swap_builtin_prearrayed") => { | |
| let mut buf = dword.to_le_bytes(); | |
| test_swap_builtin_prearrayed(&mut buf); | |
| } | |
| Some("swap_lut_prearrayed") => { | |
| let mut buf = dword.to_le_bytes(); | |
| test_swap_lut_prearrayed(&mut buf); | |
| } | |
| Some(o) => { | |
| panic!("unknown mode: {}", o); | |
| } | |
| None => { | |
| panic!("usage: {} [swap_builtin|swap_lut]", me); | |
| } | |
| }; | |
| println!("your number is ready: {:08x}", unsafe { LAST }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment