#![cfg(target_arch = "x86_64")]
use crate::arch::{HasAvx512, Simd, with_simd};
use crate::base::block::{Array128, Block, gen_shared_block512};
use std::arch::x86_64::*;
use std::ops::{BitAnd, BitXor};
use zerocopy::transmute;
#[derive(Clone, Copy)]
pub struct Avx1x512<S: Simd> {
val: __m512i,
simd: S,
}
impl<S: Simd> Block for Avx1x512<S>
where
S: HasAvx512,
{
gen_shared_block512!(S);
fn xor_down(self) -> Array128 {
with_simd! {
fn helper(
token: impl HasAvx512,
input: __m512i,
) -> Array128 {
let low_256 = _mm512_castsi512_si256(input);
let high_256 = _mm512_extracti64x4_epi64(input, 1);
let temp = _mm256_xor_si256(low_256, high_256);
let low_128 = _mm256_castsi256_si128(temp);
let high_128 = _mm256_extracti128_si256(temp, 1);
let out = _mm_xor_si128(low_128, high_128);
transmute!(out)
}
}
helper(self.simd, self.val)
}
fn aes_encrypt_round(state: Self, round_key: Self) -> Self {
with_simd! {
fn helper(
token: impl HasAvx512,
state: __m512i,
round_key: __m512i
) -> __m512i {
_mm512_aesenc_epi128(state, round_key)
}
}
Self {
val: helper(state.simd, state.val, round_key.val),
simd: state.simd,
}
}
}
impl<S: Simd> BitAnd for Avx1x512<S>
where
S: HasAvx512,
{
type Output = Avx1x512<S>;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx512,
first: __m512i,
second: __m512i,
) -> __m512i {
_mm512_and_si512(first, second)
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}
impl<S: Simd> BitXor for Avx1x512<S>
where
S: HasAvx512,
{
type Output = Avx1x512<S>;
#[inline(always)]
fn bitxor(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx512,
first: __m512i,
second: __m512i,
) -> __m512i {
_mm512_xor_si512(first, second)
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}