use super::*;
pub(crate) fn xor_gather(region: &[u8], dst: &mut [u8], offsets: &[u32]) {
let live = dst.len();
for (index, &start) in offsets.iter().enumerate() {
let start = start as usize;
let end = start
.checked_add(live)
.expect("xor_gather: offset + length overflows");
assert!(
end <= region.len(),
"xor_gather: offset {index} ({start}) + {live} exceeds region of {} bytes",
region.len(),
);
}
if offsets.is_empty() {
return;
}
if live <= XOR_INLINE_MAX {
for &start in offsets {
scalar::xor(dst, ®ion[start as usize..start as usize + live]);
}
return;
}
#[cfg(all(feature = "simd", target_arch = "x86_64"))]
match x86_proof() {
#[cfg(feature = "simd512")]
X86Proof::V4x(token) => {
x86::xor_gather_avx2(token.v3(), region, dst, offsets);
}
X86Proof::V3GfniCrypto(token) => {
x86::xor_gather_avx2(token.v3(), region, dst, offsets);
}
X86Proof::V3(token) => x86::xor_gather_avx2(token, region, dst, offsets),
X86Proof::V2(token) => {
for &start in offsets {
x86::xor_sse2(
token.v1(),
dst,
®ion[start as usize..start as usize + live],
);
}
}
X86Proof::Scalar => {
for &start in offsets {
scalar::xor(dst, ®ion[start as usize..start as usize + live]);
}
}
}
#[cfg(not(all(feature = "simd", target_arch = "x86_64")))]
{
for &start in offsets {
scalar::xor(dst, ®ion[start as usize..start as usize + live]);
}
}
}
const XOR_INLINE_MAX: usize = 31;
pub fn xor(dst: &mut [u8], src: &[u8]) {
assert_eq!(dst.len(), src.len(), "fgf::xor: length mismatch");
if dst.len() <= XOR_INLINE_MAX {
scalar::xor(dst, src);
return;
}
#[cfg(all(feature = "simd", target_arch = "x86_64"))]
match x86_proof() {
#[cfg(feature = "simd512")]
X86Proof::V4x(token) if dst.len() >= x86::bytes::XOR_AVX512_MIN => {
x86::bytes::xor_avx512(token.v4(), dst, src);
}
#[cfg(feature = "simd512")]
X86Proof::V4x(token) => x86::xor_avx2(token.v3(), dst, src),
X86Proof::V3GfniCrypto(token) => x86::xor_avx2(token.v3(), dst, src),
X86Proof::V3(token) => x86::xor_avx2(token, dst, src),
X86Proof::V2(token) => x86::xor_sse2(token.v1(), dst, src),
X86Proof::Scalar => scalar::xor(dst, src),
}
#[cfg(not(all(feature = "simd", target_arch = "x86_64")))]
scalar::xor(dst, src);
}
pub fn xor_broadcast(dst: &mut [u8], value_bytes: &[u8]) {
#[cfg(all(feature = "simd", target_arch = "x86_64"))]
match x86_proof() {
#[cfg(feature = "simd512")]
X86Proof::V4x(token) => {
x86::bytes::xor_broadcast_avx2(token.v3(), dst, value_bytes);
}
X86Proof::V3GfniCrypto(token) => {
x86::bytes::xor_broadcast_avx2(token.v3(), dst, value_bytes);
}
X86Proof::V3(token) => x86::bytes::xor_broadcast_avx2(token, dst, value_bytes),
X86Proof::V2(token) => x86::bytes::xor_broadcast_sse2(token.v1(), dst, value_bytes),
X86Proof::Scalar => scalar::xor_broadcast_bytes(dst, value_bytes),
}
#[cfg(not(all(feature = "simd", target_arch = "x86_64")))]
scalar::xor_broadcast_bytes(dst, value_bytes);
}