use vortex_buffer::BitBuffer;
use super::DepositBits;
use super::SelectBit;
use super::intersect_bit_buffer_by_rank_indices;
use super::intersect_bit_buffers;
use super::intersect_mask_driven;
use crate::Mask;
pub(super) struct Sve2Bdep;
impl DepositBits for Sve2Bdep {
#[inline]
fn deposit_bits(source: u64, mask: u64, _mask_count: usize) -> u64 {
unsafe { bdep_sve2(source, mask) }
}
}
impl SelectBit for Sve2Bdep {
#[inline]
fn select_bit_position(word: u64, rank: usize) -> usize {
debug_assert!(rank < word.count_ones() as usize);
unsafe { bdep_sve2(1u64 << rank, word) }.trailing_zeros() as usize
}
}
#[inline]
#[target_feature(enable = "sve2,sve2-bitperm")]
unsafe fn bdep_sve2(source: u64, mask: u64) -> u64 {
let result: u64;
unsafe {
std::arch::asm!(
"fmov d0, {source}",
"fmov d1, {mask}",
"bdep z0.d, z0.d, z1.d",
"fmov {result}, d0",
source = in(reg) source,
mask = in(reg) mask,
result = lateout(reg) result,
out("v0") _,
out("v1") _,
options(pure, nomem, nostack),
);
}
result
}
#[target_feature(enable = "sve2,sve2-bitperm")]
pub(super) unsafe fn intersect_bit_buffers_sve2(
self_buffer: &BitBuffer,
mask_buffer: &BitBuffer,
true_count: usize,
) -> Mask {
intersect_bit_buffers::<Sve2Bdep>(self_buffer, mask_buffer, true_count)
}
#[target_feature(enable = "sve2,sve2-bitperm")]
pub(super) unsafe fn intersect_bit_buffer_by_rank_indices_sve2(
self_buffer: &BitBuffer,
mask_indices: &[usize],
) -> Mask {
intersect_bit_buffer_by_rank_indices::<Sve2Bdep>(self_buffer, mask_indices)
}
#[target_feature(enable = "sve2,sve2-bitperm")]
pub(super) unsafe fn intersect_mask_driven_sve2<I>(
self_buffer: &BitBuffer,
mask_indices: I,
true_count: usize,
) -> Mask
where
I: Iterator<Item = usize>,
{
intersect_mask_driven::<Sve2Bdep, _>(self_buffer, mask_indices, true_count)
}