macro_rules! fe_mul_rows {
($a:literal, $b:literal) => {
concat!(
"mov rdx, qword ptr [rdi + ",
$b,
"]\n",
"mulx r9, r8, qword ptr [rdi + ",
$a,
"]\n",
"mulx r10, rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"add r9, rax\n",
"mulx r11, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adc r10, rax\n",
"mulx r12, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adc r11, rax\n",
"adc r12, 0\n",
"mov rdx, qword ptr [rdi + ",
$b,
" + 8]\n",
"xor esi, esi\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
"]\n",
"adcx r9, rax\n",
"adox r10, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"adcx r10, rax\n",
"adox r11, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adcx r11, rax\n",
"adox r12, rcx\n",
"mulx r13, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adcx r12, rax\n",
"adox r13, rsi\n",
"adcx r13, rsi\n",
"mov rdx, qword ptr [rdi + ",
$b,
" + 16]\n",
"xor esi, esi\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
"]\n",
"adcx r10, rax\n",
"adox r11, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"adcx r11, rax\n",
"adox r12, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adcx r12, rax\n",
"adox r13, rcx\n",
"mulx r14, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adcx r13, rax\n",
"adox r14, rsi\n",
"adcx r14, rsi\n",
"mov rdx, qword ptr [rdi + ",
$b,
" + 24]\n",
"xor esi, esi\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
"]\n",
"adcx r11, rax\n",
"adox r12, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"adcx r12, rax\n",
"adox r13, rcx\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adcx r13, rax\n",
"adox r14, rcx\n",
"mulx r15, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adcx r14, rax\n",
"adox r15, rsi\n",
"adcx r15, rsi\n",
)
};
}
macro_rules! fe_mul {
($d:literal, $a:literal, $b:literal) => {
concat!(fe_mul_rows!($a, $b), fe_reduce_store!($d))
};
}
macro_rules! fe_mul5 {
($d:literal, $a:literal, $b:literal) => {
concat!(
fe_mul_rows!($a, $b),
"mov edx, 38\n",
"xor esi, esi\n",
"mulx rcx, rax, r12\n",
"adcx r8, rax\n",
"adox r9, rcx\n",
"mulx rcx, rax, r13\n",
"adcx r9, rax\n",
"adox r10, rcx\n",
"mulx rcx, rax, r14\n",
"adcx r10, rax\n",
"adox r11, rcx\n",
"mulx r12, rax, r15\n",
"adcx r11, rax\n",
"adox r12, rsi\n",
"adcx r12, rsi\n",
"mov qword ptr [rdi + ",
$d,
"], r8\n",
"mov qword ptr [rdi + ",
$d,
" + 8], r9\n",
"mov qword ptr [rdi + ",
$d,
" + 16], r10\n",
"mov qword ptr [rdi + ",
$d,
" + 24], r11\n",
"mov qword ptr [rdi + ",
$d,
" + 32], r12\n",
)
};
}
macro_rules! fe_fold5_store {
($d:literal) => {
concat!(
"shld r12, r11, 1\n",
"btr r11, 63\n",
"imul r12, r12, 19\n",
"add r8, r12\n",
"adc r9, 0\n",
"adc r10, 0\n",
"adc r11, 0\n",
"mov qword ptr [rdi + ",
$d,
"], r8\n",
"mov qword ptr [rdi + ",
$d,
" + 8], r9\n",
"mov qword ptr [rdi + ",
$d,
" + 16], r10\n",
"mov qword ptr [rdi + ",
$d,
" + 24], r11\n",
)
};
}
macro_rules! fe_add5_fold {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov r8, qword ptr [rdi + ",
$a,
"]\n",
"add r8, qword ptr [rdi + ",
$b,
"]\n",
"mov r9, qword ptr [rdi + ",
$a,
" + 8]\n",
"adc r9, qword ptr [rdi + ",
$b,
" + 8]\n",
"mov r10, qword ptr [rdi + ",
$a,
" + 16]\n",
"adc r10, qword ptr [rdi + ",
$b,
" + 16]\n",
"mov r11, qword ptr [rdi + ",
$a,
" + 24]\n",
"adc r11, qword ptr [rdi + ",
$b,
" + 24]\n",
"mov r12, qword ptr [rdi + ",
$a,
" + 32]\n",
"adc r12, qword ptr [rdi + ",
$b,
" + 32]\n",
fe_fold5_store!($d),
)
};
}
macro_rules! fe_sub5_fold {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov r8, qword ptr [rdi + ",
$a,
"]\n",
"sub r8, qword ptr [rdi + ",
$b,
"]\n",
"mov r9, qword ptr [rdi + ",
$a,
" + 8]\n",
"sbb r9, qword ptr [rdi + ",
$b,
" + 8]\n",
"mov r10, qword ptr [rdi + ",
$a,
" + 16]\n",
"sbb r10, qword ptr [rdi + ",
$b,
" + 16]\n",
"mov r11, qword ptr [rdi + ",
$a,
" + 24]\n",
"sbb r11, qword ptr [rdi + ",
$b,
" + 24]\n",
"mov r12, qword ptr [rdi + ",
$a,
" + 32]\n",
"sbb r12, qword ptr [rdi + ",
$b,
" + 32]\n",
"sub r8, 2432\n",
"sbb r9, 0\n",
"sbb r10, 0\n",
"sbb r11, 0\n",
"sbb r12, -64\n",
fe_fold5_store!($d),
)
};
}
macro_rules! fe_sqr {
($d:literal, $a:literal) => {
concat!(
"mov rdx, qword ptr [rdi + ",
$a,
"]\n",
"mulx r10, r9, qword ptr [rdi + ",
$a,
" + 8]\n",
"mulx r11, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"add r10, rax\n",
"mulx r12, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adc r11, rax\n",
"adc r12, 0\n",
"mov rdx, qword ptr [rdi + ",
$a,
" + 8]\n",
"xor esi, esi\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adcx r11, rax\n",
"adox r12, rcx\n",
"mulx r13, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adcx r12, rax\n",
"adox r13, rsi\n",
"adcx r13, rsi\n",
"mov rdx, qword ptr [rdi + ",
$a,
" + 16]\n",
"mulx r14, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"add r13, rax\n",
"adc r14, rsi\n",
"mov rdx, qword ptr [rdi + ",
$a,
"]\n",
"mulx rcx, r8, rdx\n",
"xor r15d, r15d\n",
"adcx r9, r9\n",
"adox r9, rcx\n",
"mov rdx, qword ptr [rdi + ",
$a,
" + 8]\n",
"mulx rcx, rax, rdx\n",
"adcx r10, r10\n",
"adox r10, rax\n",
"adcx r11, r11\n",
"adox r11, rcx\n",
"mov rdx, qword ptr [rdi + ",
$a,
" + 16]\n",
"mulx rcx, rax, rdx\n",
"adcx r12, r12\n",
"adox r12, rax\n",
"adcx r13, r13\n",
"adox r13, rcx\n",
"mov rdx, qword ptr [rdi + ",
$a,
" + 24]\n",
"mulx rcx, rax, rdx\n",
"adcx r14, r14\n",
"adox r14, rax\n",
"adcx r15, r15\n",
"adox r15, rcx\n",
fe_reduce_store!($d),
)
};
}
macro_rules! fe_reduce_store {
($d:literal) => {
concat!(
"mov edx, 38\n",
"xor esi, esi\n",
"mulx rcx, rax, r12\n",
"adcx r8, rax\n",
"adox r9, rcx\n",
"mulx rcx, rax, r13\n",
"adcx r9, rax\n",
"adox r10, rcx\n",
"mulx rcx, rax, r14\n",
"adcx r10, rax\n",
"adox r11, rcx\n",
"mulx r12, rax, r15\n",
"adcx r11, rax\n",
"adox r12, rsi\n",
"adcx r12, rsi\n",
"shld r12, r11, 1\n",
"btr r11, 63\n",
"imul r12, r12, 19\n",
"add r8, r12\n",
"adc r9, rsi\n",
"adc r10, rsi\n",
"adc r11, rsi\n",
"mov qword ptr [rdi + ",
$d,
"], r8\n",
"mov qword ptr [rdi + ",
$d,
" + 8], r9\n",
"mov qword ptr [rdi + ",
$d,
" + 16], r10\n",
"mov qword ptr [rdi + ",
$d,
" + 24], r11\n",
)
};
}
#[cfg(any(feature = "std", feature = "ct-probes"))]
macro_rules! fe_sub {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov r8, qword ptr [rdi + ",
$a,
"]\n",
"sub r8, qword ptr [rdi + ",
$b,
"]\n",
"mov r9, qword ptr [rdi + ",
$a,
" + 8]\n",
"sbb r9, qword ptr [rdi + ",
$b,
" + 8]\n",
"mov r10, qword ptr [rdi + ",
$a,
" + 16]\n",
"sbb r10, qword ptr [rdi + ",
$b,
" + 16]\n",
"mov r11, qword ptr [rdi + ",
$a,
" + 24]\n",
"sbb r11, qword ptr [rdi + ",
$b,
" + 24]\n",
"sbb rax, rax\n",
"and eax, 38\n",
"sub r8, rax\n",
"sbb r9, 0\n",
"sbb r10, 0\n",
"sbb r11, 0\n",
"sbb rax, rax\n",
"and eax, 38\n",
"sub r8, rax\n",
"mov qword ptr [rdi + ",
$d,
"], r8\n",
"mov qword ptr [rdi + ",
$d,
" + 8], r9\n",
"mov qword ptr [rdi + ",
$d,
" + 16], r10\n",
"mov qword ptr [rdi + ",
$d,
" + 24], r11\n",
)
};
}
macro_rules! fe_mul121666_add {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov edx, 121666\n",
"mulx r9, r8, qword ptr [rdi + ",
$a,
"]\n",
"mulx r10, rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"add r9, rax\n",
"mulx r11, rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"adc r10, rax\n",
"mulx rcx, rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"adc r11, rax\n",
"adc rcx, 0\n",
"add r8, qword ptr [rdi + ",
$b,
"]\n",
"adc r9, qword ptr [rdi + ",
$b,
" + 8]\n",
"adc r10, qword ptr [rdi + ",
$b,
" + 16]\n",
"adc r11, qword ptr [rdi + ",
$b,
" + 24]\n",
"adc rcx, 0\n",
"imul rcx, rcx, 38\n",
"add r8, rcx\n",
"adc r9, 0\n",
"adc r10, 0\n",
"adc r11, 0\n",
"sbb rax, rax\n",
"and eax, 38\n",
"add r8, rax\n",
"mov qword ptr [rdi + ",
$d,
"], r8\n",
"mov qword ptr [rdi + ",
$d,
" + 8], r9\n",
"mov qword ptr [rdi + ",
$d,
" + 16], r10\n",
"mov qword ptr [rdi + ",
$d,
" + 24], r11\n",
)
};
}
macro_rules! fe_cmovnz {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov rax, qword ptr [rdi + ",
$a,
"]\n",
"cmovnz rax, qword ptr [rdi + ",
$b,
"]\n",
"mov qword ptr [rdi + ",
$d,
"], rax\n",
"mov rax, qword ptr [rdi + ",
$a,
" + 8]\n",
"cmovnz rax, qword ptr [rdi + ",
$b,
" + 8]\n",
"mov qword ptr [rdi + ",
$d,
" + 8], rax\n",
"mov rax, qword ptr [rdi + ",
$a,
" + 16]\n",
"cmovnz rax, qword ptr [rdi + ",
$b,
" + 16]\n",
"mov qword ptr [rdi + ",
$d,
" + 16], rax\n",
"mov rax, qword ptr [rdi + ",
$a,
" + 24]\n",
"cmovnz rax, qword ptr [rdi + ",
$b,
" + 24]\n",
"mov qword ptr [rdi + ",
$d,
" + 24], rax\n",
)
};
}
macro_rules! fe_add_once {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov r8, qword ptr [rdi + ",
$a,
"]
",
"add r8, qword ptr [rdi + ",
$b,
"]
",
"mov r9, qword ptr [rdi + ",
$a,
" + 8]
",
"adc r9, qword ptr [rdi + ",
$b,
" + 8]
",
"mov r10, qword ptr [rdi + ",
$a,
" + 16]
",
"adc r10, qword ptr [rdi + ",
$b,
" + 16]
",
"mov r11, qword ptr [rdi + ",
$a,
" + 24]
",
"adc r11, qword ptr [rdi + ",
$b,
" + 24]
",
"sbb rax, rax
",
"and eax, 38
",
"add r8, rax
",
"adc r9, 0
",
"adc r10, 0
",
"adc r11, 0
",
"mov qword ptr [rdi + ",
$d,
"], r8
",
"mov qword ptr [rdi + ",
$d,
" + 8], r9
",
"mov qword ptr [rdi + ",
$d,
" + 16], r10
",
"mov qword ptr [rdi + ",
$d,
" + 24], r11
",
)
};
}
macro_rules! fe_sub_once {
($d:literal, $a:literal, $b:literal) => {
concat!(
"mov r8, qword ptr [rdi + ",
$a,
"]
",
"sub r8, qword ptr [rdi + ",
$b,
"]
",
"mov r9, qword ptr [rdi + ",
$a,
" + 8]
",
"sbb r9, qword ptr [rdi + ",
$b,
" + 8]
",
"mov r10, qword ptr [rdi + ",
$a,
" + 16]
",
"sbb r10, qword ptr [rdi + ",
$b,
" + 16]
",
"mov r11, qword ptr [rdi + ",
$a,
" + 24]
",
"sbb r11, qword ptr [rdi + ",
$b,
" + 24]
",
"sbb rax, rax
",
"and eax, 38
",
"sub r8, rax
",
"sbb r9, 0
",
"sbb r10, 0
",
"sbb r11, 0
",
"mov qword ptr [rdi + ",
$d,
"], r8
",
"mov qword ptr [rdi + ",
$d,
" + 8], r9
",
"mov qword ptr [rdi + ",
$d,
" + 16], r10
",
"mov qword ptr [rdi + ",
$d,
" + 24], r11
",
)
};
}