#![cfg(target_arch = "x86_64")]
use crate::arch::{HasAvx2, Simd, with_simd};
use crate::base::block::{
Array128, Block, gen_shared_block256, gen_shared_block512,
};
use std::arch::x86_64::*;
use std::ops::{BitAnd, BitXor};
use zerocopy::transmute;
#[derive(Clone, Copy)]
pub struct Avx1x256<S: Simd> {
val: __m256i,
simd: S,
}
impl<S: Simd> Block for Avx1x256<S>
where
S: HasAvx2,
{
gen_shared_block256!(S);
fn xor_down(self) -> Array128 {
with_simd! {
fn helper(
token: impl HasAvx2,
input: __m256i,
) -> Array128 {
let low = _mm256_castsi256_si128(input);
let high = _mm256_extracti128_si256(input, 1);
let out = _mm_xor_si128(low, high);
transmute!(out)
}
}
helper(self.simd, self.val)
}
fn aes_encrypt_round(state: Self, round_key: Self) -> Self {
with_simd! {
fn helper(
token: impl HasAvx2,
state: __m256i,
round_key: __m256i
) -> __m256i {
_mm256_aesenc_epi128(state, round_key)
}
}
Self {
val: helper(state.simd, state.val, round_key.val),
simd: state.simd,
}
}
}
impl<S: Simd> BitAnd for Avx1x256<S>
where
S: HasAvx2,
{
type Output = Avx1x256<S>;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx2,
first: __m256i,
second: __m256i,
) -> __m256i {
_mm256_and_si256(first, second)
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}
impl<S: Simd> BitXor for Avx1x256<S>
where
S: HasAvx2,
{
type Output = Avx1x256<S>;
#[inline(always)]
fn bitxor(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx2,
first: __m256i,
second: __m256i,
) -> __m256i {
_mm256_xor_si256(first, second)
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}
#[derive(Clone, Copy)]
pub struct Avx2x256<S: Simd> {
val: [__m256i; 2],
simd: S,
}
impl<S: Simd> Block for Avx2x256<S>
where
S: HasAvx2,
{
gen_shared_block512!(S);
fn xor_down(self) -> Array128 {
with_simd! {
fn helper(
token: impl HasAvx2,
input: [__m256i; 2]
) -> Array128 {
let temp = _mm256_xor_si256(input[0], input[1]);
let low = _mm256_castsi256_si128(temp);
let high = _mm256_extracti128_si256(temp, 1);
let out = _mm_xor_si128(low, high);
transmute!(out)
}
}
helper(self.simd, self.val)
}
fn aes_encrypt_round(state: Self, round_key: Self) -> Self {
with_simd! {
fn helper(
token: impl HasAvx2,
state: [__m256i; 2],
round_key: [__m256i; 2],
) -> [__m256i; 2] {
[
_mm256_aesenc_epi128(state[0], round_key[0]),
_mm256_aesenc_epi128(state[1], round_key[1]),
]
}
}
Self {
val: helper(state.simd, state.val, round_key.val),
simd: state.simd,
}
}
}
impl<S: Simd> BitAnd for Avx2x256<S>
where
S: HasAvx2,
{
type Output = Avx2x256<S>;
#[inline(always)]
fn bitand(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx2,
first: [__m256i; 2],
second: [__m256i; 2],
) -> [__m256i; 2] {
[
_mm256_and_si256(first[0], second[0]),
_mm256_and_si256(first[1], second[1]),
]
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}
impl<S: Simd> BitXor for Avx2x256<S>
where
S: HasAvx2,
{
type Output = Avx2x256<S>;
#[inline(always)]
fn bitxor(self, rhs: Self) -> Self::Output {
with_simd! {
fn helper(
token: impl HasAvx2,
first: [__m256i; 2],
second: [__m256i; 2],
) -> [__m256i; 2] {
[
_mm256_xor_si256(first[0], second[0]),
_mm256_xor_si256(first[1], second[1]),
]
}
}
Self {
val: helper(self.simd, self.val, rhs.val),
simd: self.simd,
}
}
}