use core::arch::aarch64::*;
use crate::low::aarch64::cpu;
pub(crate) fn sha1_compress_blocks(state: &mut [u32; 5], blocks: &[u8]) {
debug_assert!(blocks.len().is_multiple_of(64));
unsafe { sha1(state, blocks) }
}
macro_rules! rounds4 {
($op:ident, $k:ident, $abcd:ident, $e:ident, $e_next:ident, $w0:ident, $w1:ident, $w2:ident, $w3:ident) => {
rounds4!($op, $k, $abcd, $e, $e_next, $w0);
let $w0 = vsha1su1q_u32(vsha1su0q_u32($w0, $w1, $w2), $w3);
};
($op:ident, $k:ident, $abcd:ident, $e:ident, $e_next:ident, $w0:ident) => {
let wk = vaddq_u32($w0, $k);
let $e_next = vsha1h_u32(vgetq_lane_u32::<0>($abcd));
$abcd = $op($abcd, $e, wk);
};
}
#[target_feature(enable = "neon,sha2")]
fn sha1(state: &mut [u32; 5], blocks: &[u8]) {
let k0 = vdupq_n_u32(0x5a827999);
let k1 = vdupq_n_u32(0x6ed9eba1);
let k2 = vdupq_n_u32(0x8f1bbcdc);
let k3 = vdupq_n_u32(0xca62c1d6);
let mut abcd = unsafe { vld1q_u32(state[0..4].as_ptr()) };
let mut e = state[4];
let (chunks, _) = blocks.as_chunks::<64>();
for block in chunks {
let abcd_prev = abcd;
let e_prev = e;
unsafe { cpu::prefetch_ro(block.as_ptr().add(64)) };
let (msg0, msg1, msg2, msg3) = unsafe {
(
vld1q_u32(block[0..].as_ptr().cast()),
vld1q_u32(block[16..].as_ptr().cast()),
vld1q_u32(block[32..].as_ptr().cast()),
vld1q_u32(block[48..].as_ptr().cast()),
)
};
let msg0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg0)));
let msg1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg1)));
let msg2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg2)));
let msg3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(msg3)));
let e0 = e;
rounds4!(vsha1cq_u32, k0, abcd, e0, e1, msg0, msg1, msg2, msg3);
rounds4!(vsha1cq_u32, k0, abcd, e1, e0, msg1, msg2, msg3, msg0);
rounds4!(vsha1cq_u32, k0, abcd, e0, e1, msg2, msg3, msg0, msg1);
rounds4!(vsha1cq_u32, k0, abcd, e1, e0, msg3, msg0, msg1, msg2);
rounds4!(vsha1cq_u32, k0, abcd, e0, e1, msg0, msg1, msg2, msg3);
rounds4!(vsha1pq_u32, k1, abcd, e1, e0, msg1, msg2, msg3, msg0);
rounds4!(vsha1pq_u32, k1, abcd, e0, e1, msg2, msg3, msg0, msg1);
rounds4!(vsha1pq_u32, k1, abcd, e1, e0, msg3, msg0, msg1, msg2);
rounds4!(vsha1pq_u32, k1, abcd, e0, e1, msg0, msg1, msg2, msg3);
rounds4!(vsha1pq_u32, k1, abcd, e1, e0, msg1, msg2, msg3, msg0);
rounds4!(vsha1mq_u32, k2, abcd, e0, e1, msg2, msg3, msg0, msg1);
rounds4!(vsha1mq_u32, k2, abcd, e1, e0, msg3, msg0, msg1, msg2);
rounds4!(vsha1mq_u32, k2, abcd, e0, e1, msg0, msg1, msg2, msg3);
rounds4!(vsha1mq_u32, k2, abcd, e1, e0, msg1, msg2, msg3, msg0);
rounds4!(vsha1mq_u32, k2, abcd, e0, e1, msg2, msg3, msg0, msg1);
rounds4!(vsha1pq_u32, k3, abcd, e1, e0, msg3, msg0, msg1, msg2);
rounds4!(vsha1pq_u32, k3, abcd, e0, e1, msg0);
rounds4!(vsha1pq_u32, k3, abcd, e1, e0, msg1);
rounds4!(vsha1pq_u32, k3, abcd, e0, e1, msg2);
rounds4!(vsha1pq_u32, k3, abcd, e1, e0, msg3);
abcd = vaddq_u32(abcd, abcd_prev);
e = e0.wrapping_add(e_prev);
}
unsafe { vst1q_u32(state[0..4].as_mut_ptr(), abcd) };
state[4] = e;
}