use super::super::ssse3::{mul_elementwise_assign_ssse3, mul_elementwise_ssse3};
use crate::field::gf8b::Elem;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_gfni(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
a: &[u8],
b: &[u8],
) {
assert_eq!(
dst.len(),
a.len(),
"mul_elementwise_gfni: dst and a differ in length"
);
assert_eq!(
dst.len(),
b.len(),
"mul_elementwise_gfni: dst and b differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<32>();
let (a_lanes, a_rest) = a.as_chunks::<32>();
let (b_lanes, b_rest) = b.as_chunks::<32>();
for ((dlane, alane), blane) in dst_lanes.iter_mut().zip(a_lanes).zip(b_lanes) {
let x = _mm256_loadu_si256(alane);
let y = _mm256_loadu_si256(blane);
_mm256_storeu_si256(dlane, _mm256_gf2p8mul_epi8(x, y));
}
let (dst16, dst_tail) = dst_rest.as_chunks_mut::<16>();
let (a16, a_tail) = a_rest.as_chunks::<16>();
let (b16, b_tail) = b_rest.as_chunks::<16>();
for ((d16, a16s), b16s) in dst16.iter_mut().zip(a16).zip(b16) {
let x = _mm_loadu_si128(a16s);
let y = _mm_loadu_si128(b16s);
_mm_storeu_si128(d16, _mm_gf2p8mul_epi8(x, y));
}
for ((d, &x), &y) in dst_tail.iter_mut().zip(a_tail).zip(b_tail) {
*d = Elem(x).mul(Elem(y)).0;
}
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_assign_gfni(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
src: &[u8],
) {
assert_eq!(
dst.len(),
src.len(),
"mul_elementwise_assign_gfni: dst and src differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<32>();
let (src_lanes, src_rest) = src.as_chunks::<32>();
for (dlane, slane) in dst_lanes.iter_mut().zip(src_lanes) {
let x = _mm256_loadu_si256(&*dlane);
let y = _mm256_loadu_si256(slane);
_mm256_storeu_si256(dlane, _mm256_gf2p8mul_epi8(x, y));
}
let (dst16, dst_tail) = dst_rest.as_chunks_mut::<16>();
let (src16, src_tail) = src_rest.as_chunks::<16>();
for (d16, s16) in dst16.iter_mut().zip(src16) {
let x = _mm_loadu_si128(&*d16);
let y = _mm_loadu_si128(s16);
_mm_storeu_si128(d16, _mm_gf2p8mul_epi8(x, y));
}
for (d, s) in dst_tail.iter_mut().zip(src_tail) {
*d = Elem(*d).mul(Elem(*s)).0;
}
}
pub(in crate::kernel::x86::gf8) const ISO_11D_TO_11B: u64 = 0xffaa_cc88_f0a0_c080;
#[inline]
#[archmage::rite(v3_gfni_crypto)]
fn multiply_vectors_8d(x: __m256i, y: __m256i) -> __m256i {
use core::arch::x86_64::*;
let phi = _mm256_set1_epi64x(ISO_11D_TO_11B.cast_signed());
let px = _mm256_gf2p8affine_epi64_epi8::<0>(x, phi);
let py = _mm256_gf2p8affine_epi64_epi8::<0>(y, phi);
let p = _mm256_gf2p8mul_epi8(px, py);
_mm256_gf2p8affine_epi64_epi8::<0>(p, phi)
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_gfni_8d(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
a: &[u8],
b: &[u8],
) {
assert_eq!(
dst.len(),
a.len(),
"mul_elementwise_gfni_8d: dst and a differ in length"
);
assert_eq!(
dst.len(),
b.len(),
"mul_elementwise_gfni_8d: dst and b differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<32>();
let (a_lanes, a_rest) = a.as_chunks::<32>();
let (b_lanes, b_rest) = b.as_chunks::<32>();
for ((dlane, alane), blane) in dst_lanes.iter_mut().zip(a_lanes).zip(b_lanes) {
let x = _mm256_loadu_si256(alane);
let y = _mm256_loadu_si256(blane);
_mm256_storeu_si256(dlane, multiply_vectors_8d(x, y));
}
mul_elementwise_ssse3::<0x1d>(_token.v3().v2(), dst_rest, a_rest, b_rest);
}
#[allow(clippy::used_underscore_binding)]
#[archmage::arcane(import_intrinsics)]
pub fn mul_elementwise_assign_gfni_8d(
_token: archmage::X64V3GfniCryptoToken,
dst: &mut [u8],
src: &[u8],
) {
assert_eq!(
dst.len(),
src.len(),
"mul_elementwise_assign_gfni_8d: dst and src differ in length"
);
let (dst_lanes, dst_rest) = dst.as_chunks_mut::<32>();
let (src_lanes, src_rest) = src.as_chunks::<32>();
for (dlane, slane) in dst_lanes.iter_mut().zip(src_lanes) {
let x = _mm256_loadu_si256(&*dlane);
let y = _mm256_loadu_si256(slane);
_mm256_storeu_si256(dlane, multiply_vectors_8d(x, y));
}
mul_elementwise_assign_ssse3::<0x1d>(_token.v3().v2(), dst_rest, src_rest);
}