#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86 {
use crate::generic::SIMDExt;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
use simd_abstraction::arch::x86::*;
use simd_abstraction::traits::{SIMD128, SIMD256};
const SPLIT_M1: u32 = u32::from_le_bytes([0x00, 0xfc, 0xc0, 0x0f]);
const SPLIT_M2: u32 = u32::from_le_bytes([0xf0, 0x03, 0x3f, 0x00]);
const SPLIT_M3: u32 = u32::from_le_bytes([0x40, 0x00, 0x00, 0x04]);
const SPLIT_M4: u32 = u32::from_le_bytes([0x10, 0x00, 0x00, 0x01]);
const MERGE_M1: u16 = u16::from_le_bytes([0x40, 0x01]);
const MERGE_M2: u32 = u32::from_le_bytes([0x00, 0x10, 0x01, 0x00]);
unsafe impl SIMDExt for AVX2 {
#[inline(always)]
fn base64_split_bits(self, a: Self::V256) -> Self::V256 {
let a1 = self.v256_and(a, self.u32x8_splat(SPLIT_M1));
let a2 = self.v256_and(a, self.u32x8_splat(SPLIT_M2));
let a3 = unsafe { _mm256_mulhi_epu16(a1, self.u32x8_splat(SPLIT_M3)) };
let a4 = unsafe { _mm256_mullo_epi16(a2, self.u32x8_splat(SPLIT_M4)) };
self.v256_or(a3, a4)
}
#[inline(always)]
fn base64_merge_bits(self, a: Self::V256) -> Self::V256 {
let a1 = unsafe { _mm256_maddubs_epi16(a, self.u16x16_splat(MERGE_M1)) };
unsafe { _mm256_madd_epi16(a1, self.u32x8_splat(MERGE_M2)) }
}
}
unsafe impl SIMDExt for SSE41 {
#[inline(always)]
fn base64_split_bits(self, a: Self::V256) -> Self::V256 {
let a1 = self.v256_and(a, self.u32x8_splat(SPLIT_M1));
let a2 = self.v256_and(a, self.u32x8_splat(SPLIT_M2));
let a3 = unsafe {
let m3 = self.u32x4_splat(SPLIT_M3);
(_mm_mulhi_epu16(a1.0, m3), _mm_mulhi_epu16(a1.1, m3))
};
let a4 = unsafe {
let m4 = self.u32x4_splat(SPLIT_M4);
(_mm_mullo_epi16(a2.0, m4), _mm_mullo_epi16(a2.1, m4))
};
self.v256_or(a3, a4)
}
#[inline(always)]
fn base64_merge_bits(self, a: Self::V256) -> Self::V256 {
let a1 = unsafe {
let m1 = self.u16x8_splat(MERGE_M1);
(_mm_maddubs_epi16(a.0, m1), _mm_maddubs_epi16(a.1, m1))
};
unsafe {
let m2 = self.u32x4_splat(MERGE_M2);
(_mm_madd_epi16(a1.0, m2), _mm_madd_epi16(a1.1, m2))
}
}
}
}
#[cfg(target_arch = "wasm32")]
mod wasm {
use crate::generic::SIMDExt;
use simd_abstraction::arch::wasm::*;
unsafe impl SIMDExt for SIMD128 {}
}
#[cfg(all(
feature = "unstable",
any(target_arch = "arm", target_arch = "aarch64")
))]
mod arm {
use crate::generic::SIMDExt;
#[cfg(target_arch = "arm")]
use simd_abstraction::arch::arm::*;
#[cfg(target_arch = "aarch64")]
use simd_abstraction::arch::aarch64::*;
unsafe impl SIMDExt for NEON {} }