use core::arch::asm;
pub mod slot {
pub const X: usize = 0;
pub const Y: usize = 4;
pub const Z: usize = 8;
pub const T: usize = 12;
pub const YPX: usize = 32;
pub const YMX: usize = 36;
pub const NZ: usize = 40;
pub const T2D: usize = 44;
}
pub struct Ws(pub [u64; 64]);
pub struct Ws2(pub [u64; 128]);
macro_rules! block2 {
($ws:expr, $($text:expr),+ $(,)?) => {{
let ws: &mut Ws2 = $ws;
unsafe {
asm!(
$($text),+,
in("rdi") ws.0.as_mut_ptr(),
out("rax") _,
out("rcx") _,
out("rdx") _,
out("rsi") _,
out("r8") _,
out("r9") _,
out("r10") _,
out("r11") _,
out("r12") _,
out("r13") _,
out("r14") _,
out("r15") _,
options(nostack),
);
}
}};
}
#[inline(never)]
pub fn madd_ext2(ws: &mut Ws2) {
block2!(
ws,
fe_add!(384, 32, 0),
fe_add!(896, 544, 512),
fe_sub!(416, 32, 0),
fe_sub!(928, 544, 512),
fe_mul!(384, 384, 256),
fe_mul!(896, 896, 768),
fe_mul!(416, 416, 288),
fe_mul!(928, 928, 800),
fe_mul!(448, 96, 352),
fe_mul!(960, 608, 864),
fe_add!(480, 64, 64),
fe_add!(992, 576, 576),
fe_sub!(128, 384, 416),
fe_sub!(640, 896, 928),
fe_add!(160, 384, 416),
fe_add!(672, 896, 928),
fe_add!(192, 480, 448),
fe_add!(704, 992, 960),
fe_sub!(224, 480, 448),
fe_sub!(736, 992, 960),
fe_mul!(0, 128, 224),
fe_mul!(512, 640, 736),
fe_mul!(32, 160, 192),
fe_mul!(544, 672, 704),
fe_mul!(64, 192, 224),
fe_mul!(576, 704, 736),
fe_mul!(96, 128, 160),
fe_mul!(608, 640, 672),
);
}
macro_rules! block {
($ws:expr, $($text:expr),+ $(,)?) => {{
let ws: &mut Ws = $ws;
unsafe {
asm!(
$($text),+,
in("rdi") ws.0.as_mut_ptr(),
out("rax") _,
out("rcx") _,
out("rdx") _,
out("rsi") _,
out("r8") _,
out("r9") _,
out("r10") _,
out("r11") _,
out("r12") _,
out("r13") _,
out("r14") _,
out("r15") _,
options(nostack),
);
}
}};
}
#[inline(never)]
pub fn dbl(ws: &mut Ws) {
block!(
ws,
fe_sqr!(384, 0), fe_sqr!(416, 32), fe_sqr!(448, 64), fe_add!(448, 448, 448), fe_add!(480, 0, 32), fe_sqr!(480, 480), fe_add!(160, 416, 384), fe_sub!(192, 416, 384), fe_sub!(128, 480, 160), fe_sub!(224, 448, 192), );
}
#[inline(never)]
pub fn to_ext(ws: &mut Ws) {
block!(
ws,
fe_mul!(0, 128, 224), fe_mul!(32, 160, 192), fe_mul!(64, 192, 224), fe_mul!(96, 128, 160), );
}
#[inline(never)]
pub fn to_proj(ws: &mut Ws) {
block!(
ws,
fe_mul!(0, 128, 224), fe_mul!(32, 160, 192), fe_mul!(64, 192, 224), );
}
#[inline(never)]
pub fn madd(ws: &mut Ws) {
block!(
ws,
fe_add!(384, 32, 0), fe_sub!(416, 32, 0), fe_mul!(384, 384, 256), fe_mul!(416, 416, 288), fe_mul!(448, 96, 352), fe_add!(480, 64, 64), fe_sub!(128, 384, 416), fe_add!(160, 384, 416), fe_add!(192, 480, 448), fe_sub!(224, 480, 448), );
}
#[inline(never)]
pub fn msub(ws: &mut Ws) {
block!(
ws,
fe_add!(384, 32, 0), fe_sub!(416, 32, 0), fe_mul!(384, 384, 288), fe_mul!(416, 416, 256), fe_mul!(448, 96, 352), fe_add!(480, 64, 64), fe_sub!(128, 384, 416), fe_add!(160, 384, 416), fe_sub!(192, 480, 448), fe_add!(224, 480, 448), );
}
#[inline(never)]
pub fn nadd(ws: &mut Ws) {
block!(
ws,
fe_add!(384, 32, 0), fe_sub!(416, 32, 0), fe_mul!(384, 384, 256), fe_mul!(416, 416, 288), fe_mul!(448, 96, 352), fe_mul!(480, 64, 320), fe_add!(480, 480, 480), fe_sub!(128, 384, 416), fe_add!(160, 384, 416), fe_add!(192, 480, 448), fe_sub!(224, 480, 448), );
}
#[inline(never)]
pub fn nsub(ws: &mut Ws) {
block!(
ws,
fe_add!(384, 32, 0), fe_sub!(416, 32, 0), fe_mul!(384, 384, 288), fe_mul!(416, 416, 256), fe_mul!(448, 96, 352), fe_mul!(480, 64, 320), fe_add!(480, 480, 480), fe_sub!(128, 384, 416), fe_add!(160, 384, 416), fe_sub!(192, 480, 448), fe_add!(224, 480, 448), );
}