#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
use crate::avx2::*;
#[target_feature(enable = "avx2")]
unsafe fn encode_block(block: &mut <Avx2 as super::Encoder>::Block, charset: crate::CharacterSet) {
let input = array_as_m256i(*block);
let result = _mm256_subs_epu8(input, _mm256_set1_epi8(51));
let less = _mm256_cmpgt_epi8(_mm256_set1_epi8(26), input);
let result = _mm256_or_si256(result, _mm256_and_si256(less, _mm256_set1_epi8(13)));
let shift_lut = match charset {
crate::CharacterSet::Standard => dup_mm_setr_epi8([
b'a' as i8 - 26,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'+' as i8 - 62,
b'/' as i8 - 63,
b'A' as _,
0,
0,
]),
crate::CharacterSet::UrlSafe => dup_mm_setr_epi8([
b'a' as i8 - 26,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'0' as i8 - 52,
b'-' as i8 - 62,
b'_' as i8 - 63,
b'A' as _,
0,
0,
]),
};
let shift = _mm256_shuffle_epi8(shift_lut, result);
*block = m256i_as_array(_mm256_add_epi8(shift, input));
}
#[target_feature(enable = "avx2")]
unsafe fn unpack_block(
input: &<Avx2 as super::Unpacker>::Input,
output: &mut <Avx2 as super::Unpacker>::Output,
) {
let input = _mm256_set_m128i(
core::ptr::read_unaligned(input.as_ptr().offset(8) as _),
core::ptr::read_unaligned(input.as_ptr() as _),
);
#[rustfmt::skip]
let shuf = _mm256_set_epi8(
14, 15, 13, 14,
11, 12, 10, 11,
8, 9, 7, 8,
5, 6, 4, 5,
10, 11, 9, 10,
7, 8, 6, 7,
4, 5, 3, 4,
1, 2, 0, 1,
);
let input = _mm256_shuffle_epi8(input, shuf);
let t0 = _mm256_and_si256(input, _mm256_set1_epi32(0x0fc0fc00));
let t1 = _mm256_mulhi_epu16(t0, _mm256_set1_epi32(0x04000040));
let t2 = _mm256_and_si256(input, _mm256_set1_epi32(0x003f03f0));
let t3 = _mm256_mullo_epi16(t2, _mm256_set1_epi32(0x01000010));
*output = m256i_as_array(_mm256_or_si256(t1, t3));
}
#[derive(Copy, Clone)]
pub(super) struct Avx2 {
_private: (),
}
impl Avx2 {
#[target_feature(enable = "avx2,bmi1,sse4.2,popcnt")]
pub(super) unsafe fn new() -> Avx2 {
Avx2 { _private: () }
}
}
impl super::Encoder for Avx2 {
type Block = [u8; 32];
fn encode_block(self, block: &mut Self::Block, charset: crate::CharacterSet) {
unsafe { encode_block(block, charset) }
}
}
impl super::Unpacker for Avx2 {
type Input = [u8; 24];
type Output = [u8; 32];
fn unpack_block(self, input: &Self::Input, output: &mut Self::Output) {
unsafe { unpack_block(input, output) }
}
}