#![expect(
clippy::inline_always,
reason = "the row operations must inline into the kernel compiled for the instruction set, or they run without it"
)]
#![expect(
unsafe_code,
reason = "NEON kernels, chosen only where the processor has NEON"
)]
use std::arch::aarch64::{
uint32x4_t, vandq_u32, vdupq_n_s32, vdupq_n_u32, vld1q_u8, vld1q_u32, vorrq_u32,
vreinterpretq_u8_u32, vreinterpretq_u32_u8, vshlq_u32, vst1q_u8, vst1q_u32,
};
use super::dispatch::{by_width, simd_kernels};
use super::kernel;
use super::row::Row;
#[derive(Clone, Copy)]
struct Pair(uint32x4_t, uint32x4_t);
impl Row for Pair {
const GROUPS: usize = 1;
#[inline(always)]
unsafe fn zero() -> Self {
unsafe { Self(vdupq_n_u32(0), vdupq_n_u32(0)) }
}
#[inline(always)]
unsafe fn splat(v: u32) -> Self {
unsafe {
let x = vdupq_n_u32(v);
Self(x, x)
}
}
#[inline(always)]
unsafe fn load_words(p: *const u32, _stride: usize) -> Self {
unsafe { Self(vld1q_u32(p), vld1q_u32(p.add(4))) }
}
#[inline(always)]
unsafe fn load_bytes(p: *const u8, _stride: usize) -> Self {
unsafe {
Self(
vreinterpretq_u32_u8(vld1q_u8(p)),
vreinterpretq_u32_u8(vld1q_u8(p.add(16))),
)
}
}
#[inline(always)]
unsafe fn store_words(self, p: *mut u32, _stride: usize) {
unsafe {
vst1q_u32(p, self.0);
vst1q_u32(p.add(4), self.1);
}
}
#[inline(always)]
unsafe fn store_bytes(self, p: *mut u8, _stride: usize) {
unsafe {
vst1q_u8(p, vreinterpretq_u8_u32(self.0));
vst1q_u8(p.add(16), vreinterpretq_u8_u32(self.1));
}
}
#[inline(always)]
unsafe fn or(self, o: Self) -> Self {
unsafe { Self(vorrq_u32(self.0, o.0), vorrq_u32(self.1, o.1)) }
}
#[inline(always)]
unsafe fn and(self, o: Self) -> Self {
unsafe { Self(vandq_u32(self.0, o.0), vandq_u32(self.1, o.1)) }
}
#[inline(always)]
unsafe fn shl(self, n: u32) -> Self {
unsafe {
let c = vdupq_n_s32(n.cast_signed());
Self(vshlq_u32(self.0, c), vshlq_u32(self.1, c))
}
}
#[inline(always)]
unsafe fn shr(self, n: u32) -> Self {
unsafe {
let c = vdupq_n_s32((n.cast_signed()).wrapping_neg());
Self(vshlq_u32(self.0, c), vshlq_u32(self.1, c))
}
}
}
simd_kernels!(Pair, "neon");