use crate::kernels::{delta, EDGE_ROW0};
#[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
#[inline(always)]
pub(crate) fn myers_step(eq: u64, vp: u64, vn: u64) -> (u64, u64) {
let (mut vp, mut vn) = (vp, vn);
unsafe {
std::arch::asm!(
"and {sum}, {eq}, {vp}",
"orr {u}, {eq}, {vp}",
"orr {xv}, {eq}, {vn}",
"lsl {vns}, {vn}, #1",
"add {sum}, {sum}, {vp}",
"orr {m}, {xv}, {vns}",
"orr {x}, {u}, {sum}",
"orn {t}, {eq}, {sum}",
"lsl {xs}, {x}, #1",
"and {mh}, {t}, {vp}",
"lsl {mhs}, {mh}, #1",
"bic {s}, {xs}, {vns}",
"bic {a}, {xs}, {m}",
"orr {vp}, {mhs}, {a}",
"bic {vn}, {xv}, {s}",
eq = in(reg) eq,
vp = inout(reg) vp,
vn = inout(reg) vn,
sum = out(reg) _,
u = out(reg) _,
xv = out(reg) _,
vns = out(reg) _,
m = out(reg) _,
x = out(reg) _,
t = out(reg) _,
xs = out(reg) _,
mh = out(reg) _,
mhs = out(reg) _,
s = out(reg) _,
a = out(reg) _,
options(pure, nomem, nostack, preserves_flags),
);
}
(vp, vn)
}
#[cfg_attr(
not(all(target_arch = "aarch64", target_vendor = "apple")),
allow(dead_code)
)]
#[inline(always)]
pub(crate) fn multiword<const W: usize, I: Iterator<Item = [u64; W]>>(
m: usize,
pm_iter: I,
mut edges: Option<&mut [u8]>,
) -> isize {
let mut vp = [!0u64; W];
let mut vn = [0u64; W];
for (j, pm_row) in pm_iter.enumerate() {
let e = edges.as_ref().map_or(EDGE_ROW0, |e| e[j]);
let mut carry = e & 1 != 0;
let (top_hp, top_hn) = {
let (mut below_ph, mut below_mh) = ((e as u64) << 62, (e as u64) << 61);
for k in 0..W {
let (eq, v_p, v_n) = (pm_row[k], vp[k], vn[k]);
let (sum, nc) = (eq & v_p).carrying_add(v_p, carry);
carry = nc;
let ph = v_n | !(sum | (v_p | eq));
let mh = v_p & (eq | !sum);
let xv = eq | v_n;
let ph_s = ph << 1 | below_ph >> 63;
vp[k] = (mh << 1 | below_mh >> 63) | !(xv | ph_s);
vn[k] = ph_s & xv;
(below_ph, below_mh) = (ph, mh);
}
(below_ph >> 63, below_mh >> 63)
};
if let Some(e) = edges.as_deref_mut() {
e[j] = carry as u8 | (top_hp as u8) << 1 | (top_hn as u8) << 2;
}
}
delta(vp, vn, m)
}