use core::arch::asm;
#[inline(always)]
pub(super) unsafe fn submul_1(r: *mut u64, x: *const u64, n: usize, y: u64) -> u64 {
let borrow: u64;
unsafe {
asm!(
"mov {hp}, #0",
"cmp xzr, xzr",
"tbz {n}, #0, 1f",
"ldr {a0}, [{xp}], #8",
"ldr {u0}, [{rp}]",
"mul {l0}, {a0}, {y}", "umulh {h0}, {a0}, {y}",
"sbcs {u0}, {u0}, {l0}",
"cinc {h0}, {h0}, cc",
"subs {u0}, {u0}, {hp}",
"mov {hp}, {h0}",
"str {u0}, [{rp}], #8",
"1:",
"tbz {n}, #1, 1f",
"ldp {a0}, {a1}, [{xp}], #16",
"ldp {u0}, {u1}, [{rp}]",
"mul {l0}, {a0}, {y}", "umulh {h0}, {a0}, {y}",
"mul {l1}, {a1}, {y}", "umulh {h1}, {a1}, {y}",
"sbcs {u0}, {u0}, {l0}",
"sbcs {u1}, {u1}, {l1}",
"cinc {h1}, {h1}, cc",
"subs {u0}, {u0}, {hp}",
"sbcs {u1}, {u1}, {h0}",
"mov {hp}, {h1}",
"stp {u0}, {u1}, [{rp}], #16",
"1:",
"tbz {n}, #2, 1f",
"ldp {a0}, {a1}, [{xp}]",
"mul {l0}, {a0}, {y}", "umulh {h0}, {a0}, {y}",
"mul {l1}, {a1}, {y}", "umulh {h1}, {a1}, {y}",
"ldp {a0}, {a1}, [{xp}, #16]",
"mul {l2}, {a0}, {y}", "umulh {h2}, {a0}, {y}",
"mul {l3}, {a1}, {y}", "umulh {h3}, {a1}, {y}",
"ldp {u0}, {u1}, [{rp}]",
"ldp {u2}, {u3}, [{rp}, #16]",
"sbcs {u0}, {u0}, {l0}",
"sbcs {u1}, {u1}, {l1}",
"sbcs {u2}, {u2}, {l2}",
"sbcs {u3}, {u3}, {l3}",
"cinc {h3}, {h3}, cc",
"subs {u0}, {u0}, {hp}",
"sbcs {u1}, {u1}, {h0}",
"sbcs {u2}, {u2}, {h1}",
"sbcs {u3}, {u3}, {h2}",
"mov {hp}, {h3}",
"stp {u0}, {u1}, [{rp}]",
"stp {u2}, {u3}, [{rp}, #16]",
"add {xp}, {xp}, #32",
"add {rp}, {rp}, #32",
"1:",
"lsr {n}, {n}, #3",
"cbz {n}, 3f",
"2:",
"ldp {a0}, {a1}, [{xp}]",
"mul {l0}, {a0}, {y}", "umulh {h0}, {a0}, {y}",
"mul {l1}, {a1}, {y}", "umulh {h1}, {a1}, {y}",
"ldp {a0}, {a1}, [{xp}, #16]",
"mul {l2}, {a0}, {y}", "umulh {h2}, {a0}, {y}",
"mul {l3}, {a1}, {y}", "umulh {h3}, {a1}, {y}",
"ldp {u0}, {u1}, [{rp}]",
"ldp {u2}, {u3}, [{rp}, #16]",
"sbcs {u0}, {u0}, {l0}",
"sbcs {u1}, {u1}, {l1}",
"sbcs {u2}, {u2}, {l2}",
"sbcs {u3}, {u3}, {l3}",
"ldp {a0}, {a1}, [{xp}, #32]",
"mul {l0}, {a0}, {y}", "umulh {h4}, {a0}, {y}",
"mul {l1}, {a1}, {y}", "umulh {h5}, {a1}, {y}",
"ldp {a0}, {a1}, [{xp}, #48]",
"mul {l2}, {a0}, {y}", "umulh {h6}, {a0}, {y}",
"mul {l3}, {a1}, {y}", "umulh {h7}, {a1}, {y}",
"ldp {u4}, {u5}, [{rp}, #32]",
"ldp {u6}, {u7}, [{rp}, #48]",
"sbcs {u4}, {u4}, {l0}",
"sbcs {u5}, {u5}, {l1}",
"sbcs {u6}, {u6}, {l2}",
"sbcs {u7}, {u7}, {l3}",
"cinc {h7}, {h7}, cc",
"subs {u0}, {u0}, {hp}",
"sbcs {u1}, {u1}, {h0}",
"sbcs {u2}, {u2}, {h1}",
"sbcs {u3}, {u3}, {h2}",
"sbcs {u4}, {u4}, {h3}",
"sbcs {u5}, {u5}, {h4}",
"sbcs {u6}, {u6}, {h5}",
"sbcs {u7}, {u7}, {h6}",
"mov {hp}, {h7}",
"stp {u0}, {u1}, [{rp}]",
"stp {u2}, {u3}, [{rp}, #16]",
"stp {u4}, {u5}, [{rp}, #32]",
"stp {u6}, {u7}, [{rp}, #48]",
"add {xp}, {xp}, #64",
"add {rp}, {rp}, #64",
"sub {n}, {n}, #1",
"cbnz {n}, 2b",
"3:",
"cinc {hp}, {hp}, cc",
rp = inout(reg) r => _, xp = inout(reg) x => _, n = inout(reg) n => _, y = in(reg) y,
hp = out(reg) borrow,
a0 = out(reg) _, a1 = out(reg) _,
l0 = out(reg) _, l1 = out(reg) _, l2 = out(reg) _, l3 = out(reg) _,
h0 = out(reg) _, h1 = out(reg) _, h2 = out(reg) _, h3 = out(reg) _,
h4 = out(reg) _, h5 = out(reg) _, h6 = out(reg) _, h7 = out(reg) _,
u0 = out(reg) _, u1 = out(reg) _, u2 = out(reg) _, u3 = out(reg) _,
u4 = out(reg) _, u5 = out(reg) _, u6 = out(reg) _, u7 = out(reg) _,
options(nostack),
);
}
borrow
}