diff --git a/crates/core_arch/src/x86/adx.rs b/crates/core_arch/src/x86/adx.rs index de9d816038..8d4c050838 100644 --- a/crates/core_arch/src/x86/adx.rs +++ b/crates/core_arch/src/x86/adx.rs @@ -5,6 +5,8 @@ use stdsimd_test::assert_instr; extern "unadjusted" { #[link_name = "llvm.x86.addcarry.32"] fn llvm_addcarry_u32(a: u8, b: u32, c: u32) -> (u8, u32); + #[link_name = "llvm.x86.addcarryx.u32"] + fn llvm_addcarryx_u32(a: u8, b: u32, c: u32, d: *mut u8) -> u8; #[link_name = "llvm.x86.subborrow.32"] fn llvm_subborrow_u32(a: u8, b: u32, c: u32) -> (u8, u32); } @@ -30,7 +32,8 @@ pub unsafe fn _addcarry_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 { #[stable(feature = "simd_x86_adx", since = "1.33.0")] #[cfg(not(stage0))] pub unsafe fn _addcarryx_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 { - _addcarry_u32(c_in, a, b, out) + let r = llvm_addcarryx_u32(c_in, a, b, out as *mut _ as *mut u8); + r } /// Add unsigned 32-bit integers a and b with unsigned 8-bit carry-in `c_in` @@ -44,3 +47,104 @@ pub unsafe fn _subborrow_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 { *out = b; a } + +#[cfg(test)] +mod tests { + use stdsimd_test::simd_test; + + use core_arch::x86::*; + + #[test] + fn test_addcarry_u32() { + unsafe { + let a = u32::max_value(); + let mut out = 0; + + let r = _addcarry_u32(0, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u32(0, a, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, a); + + let r = _addcarry_u32(1, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 1); + + let r = _addcarry_u32(1, a, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u32(0, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 7); + + let r = _addcarry_u32(1, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 8); + } + } + + #[simd_test(enable = "adx")] + unsafe fn test_addcarryx_u32() { + let a = u32::max_value(); + let mut out = 0; + + let r = _addcarry_u32(0, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u32(0, a, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, a); + + let r = _addcarry_u32(1, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 1); + + let r = _addcarry_u32(1, a, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u32(0, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 7); + + let r = _addcarry_u32(1, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 8); + } + + #[test] + fn test_subborrow_u32() { + unsafe { + let a = u32::max_value(); + let mut out = 0; + + let r = _subborrow_u32(0, 0, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a); + + let r = _subborrow_u32(0, 0, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 0); + + let r = _subborrow_u32(1, 0, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a - 1); + + let r = _subborrow_u32(1, 0, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a); + + let r = _subborrow_u32(0, 7, 3, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 4); + + let r = _subborrow_u32(1, 7, 3, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 3); + } + } +} diff --git a/crates/core_arch/src/x86_64/adx.rs b/crates/core_arch/src/x86_64/adx.rs index cc69ba4414..812fff0b86 100644 --- a/crates/core_arch/src/x86_64/adx.rs +++ b/crates/core_arch/src/x86_64/adx.rs @@ -5,6 +5,8 @@ use stdsimd_test::assert_instr; extern "unadjusted" { #[link_name = "llvm.x86.addcarry.64"] fn llvm_addcarry_u64(a: u8, b: u64, c: u64) -> (u8, u64); + #[link_name = "llvm.x86.addcarryx.u64"] + fn llvm_addcarryx_u64(a: u8, b: u64, c: u64, d: *mut u8) -> u8; #[link_name = "llvm.x86.subborrow.64"] fn llvm_subborrow_u64(a: u8, b: u64, c: u64) -> (u8, u64); } @@ -30,7 +32,7 @@ pub unsafe fn _addcarry_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 { #[stable(feature = "simd_x86_adx", since = "1.33.0")] #[cfg(not(stage0))] pub unsafe fn _addcarryx_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 { - _addcarry_u64(c_in, a, b, out) + llvm_addcarryx_u64(c_in, a, b, out as *mut _ as *mut u8) } /// Add unsigned 64-bit integers a and b with unsigned 8-bit carry-in `c_in` @@ -44,3 +46,104 @@ pub unsafe fn _subborrow_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 { *out = b; a } + +#[cfg(test)] +mod tests { + use stdsimd_test::simd_test; + + use core_arch::x86_64::*; + + #[test] + fn test_addcarry_u64() { + unsafe { + let a = u64::max_value(); + let mut out = 0; + + let r = _addcarry_u64(0, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u64(0, a, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, a); + + let r = _addcarry_u64(1, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 1); + + let r = _addcarry_u64(1, a, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u64(0, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 7); + + let r = _addcarry_u64(1, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 8); + } + } + + #[simd_test(enable = "adx")] + unsafe fn test_addcarryx_u64() { + let a = u64::max_value(); + let mut out = 0; + + let r = _addcarry_u64(0, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u64(0, a, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, a); + + let r = _addcarry_u64(1, a, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 1); + + let r = _addcarry_u64(1, a, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, 0); + + let r = _addcarry_u64(0, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 7); + + let r = _addcarry_u64(1, 3, 4, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 8); + } + + #[test] + fn test_subborrow_u64() { + unsafe { + let a = u64::max_value(); + let mut out = 0; + + let r = _subborrow_u64(0, 0, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a); + + let r = _subborrow_u64(0, 0, 0, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 0); + + let r = _subborrow_u64(1, 0, 1, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a - 1); + + let r = _subborrow_u64(1, 0, 0, &mut out); + assert_eq!(r, 1); + assert_eq!(out, a); + + let r = _subborrow_u64(0, 7, 3, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 4); + + let r = _subborrow_u64(1, 7, 3, &mut out); + assert_eq!(r, 0); + assert_eq!(out, 3); + } + } +}