// File: simap[P]ecctools/lib/uECC.c
// Function: uECC_vli_mmod(unsigned long*, unsigned long*, unsigned long const*, signed char)
uECC_VLI_API void uECC_vli_mmod(uECC_word_t *result,
                                uECC_word_t *product,
                                const uECC_word_t *mod,
                                wordcount_t num_words) {
    uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
    uECC_word_t tmp[2 * uECC_MAX_WORDS];
    uECC_word_t *v[2] = {tmp, product};
    uECC_word_t index;

    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
    wordcount_t word_shift = shift / uECC_WORD_BITS;
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
    uECC_word_t carry = 0;
    uECC_vli_clear(mod_multiple, word_shift);
    if (bit_shift > 0) {
        for(index = 0; index < (uECC_word_t)num_words; ++index) {
            mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
            carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
        }
    } else {
        uECC_vli_set(mod_multiple + word_shift, mod, num_words);
    }

    for (index = 1; shift >= 0; --shift) {
        uECC_word_t borrow = 0;
        wordcount_t i;
        for (i = 0; i < num_words * 2; ++i) {
            uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
            if (diff != v[index][i]) {
                borrow = (diff > v[index][i]);
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
    }
    uECC_vli_set(result, v[index], num_words);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movb %al, -0x19(%rbp)
leaq -0xa0(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xa8(%rbp)
movsbl -0x19(%rbp), %eax
shll %eax
shll $0x6, %eax
movl %eax, -0xe4(%rbp)
movq -0x18(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x40a0
movw %ax, %cx
movl -0xe4(%rbp), %eax
movswl %cx, %ecx
subl %ecx, %eax
movw %ax, -0xba(%rbp)
movswl -0xba(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movb %al, -0xbb(%rbp)
movswl -0xba(%rbp), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movb %dl, %al
movb %al, -0xbc(%rbp)
movq $0x0, -0xc8(%rbp)
leaq -0x60(%rbp), %rdi
movsbl -0xbb(%rbp), %esi
callq 0x4170
movsbl -0xbc(%rbp), %eax
cmpl $0x0, %eax
jle 0x63f4
movq $0x0, -0xb8(%rbp)
movq -0xb8(%rbp), %rax
movsbq -0x19(%rbp), %rcx
cmpq %rcx, %rax
jae 0x63f2
movq -0x18(%rbp), %rax
movq -0xb8(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbl -0xbc(%rbp), %ecx
movl %ecx, %ecx
shlq %cl, %rax
movq %rax, %rcx
orq -0xc8(%rbp), %rcx
movsbq -0xbb(%rbp), %rax
addq -0xb8(%rbp), %rax
movq %rcx, -0x60(%rbp,%rax,8)
movq -0x18(%rbp), %rax
movq -0xb8(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbl -0xbc(%rbp), %edx
movl $0x40, %ecx
subl %edx, %ecx
movl %ecx, %ecx
shrq %cl, %rax
movq %rax, -0xc8(%rbp)
movq -0xb8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb8(%rbp)
jmp 0x6368
jmp 0x6415
leaq -0x60(%rbp), %rdi
movsbl -0xbb(%rbp), %eax
cltq
shlq $0x3, %rax
addq %rax, %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x3db0
movq $0x1, -0xb8(%rbp)
movswl -0xba(%rbp), %eax
cmpl $0x0, %eax
jl 0x659e
movq $0x0, -0xd0(%rbp)
movb $0x0, -0xd1(%rbp)
movsbl -0xd1(%rbp), %eax
movsbl -0x19(%rbp), %ecx
shll %ecx
cmpl %ecx, %eax
jge 0x651c
movq -0xb8(%rbp), %rax
movq -0xb0(%rbp,%rax,8), %rax
movsbq -0xd1(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsbq -0xd1(%rbp), %rcx
subq -0x60(%rbp,%rcx,8), %rax
subq -0xd0(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
movq -0xb8(%rbp), %rcx
movq -0xb0(%rbp,%rcx,8), %rcx
movsbq -0xd1(%rbp), %rdx
cmpq (%rcx,%rdx,8), %rax
je 0x64e2
movq -0xe0(%rbp), %rax
movq -0xb8(%rbp), %rcx
movq -0xb0(%rbp,%rcx,8), %rcx
movsbq -0xd1(%rbp), %rdx
cmpq (%rcx,%rdx,8), %rax
seta %al
andb $0x1, %al
movzbl %al, %eax
movq %rax, -0xd0(%rbp)
movq -0xe0(%rbp), %rdx
movl $0x1, %eax
subq -0xb8(%rbp), %rax
movq -0xb0(%rbp,%rax,8), %rax
movsbq -0xd1(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movb -0xd1(%rbp), %al
addb $0x1, %al
movb %al, -0xd1(%rbp)
jmp 0x6442
movq -0xb8(%rbp), %rax
xorq -0xd0(%rbp), %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movq %rax, -0xb8(%rbp)
leaq -0x60(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
movsbq -0x19(%rbp), %rax
movq -0x60(%rbp,%rax,8), %rcx
shlq $0x3f, %rcx
movsbl -0x19(%rbp), %eax
subl $0x1, %eax
cltq
orq -0x60(%rbp,%rax,8), %rcx
movq %rcx, -0x60(%rbp,%rax,8)
leaq -0x60(%rbp), %rdi
movsbl -0x19(%rbp), %eax
cltq
shlq $0x3, %rax
addq %rax, %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
movw -0xba(%rbp), %ax
addw $-0x1, %ax
movw %ax, -0xba(%rbp)
jmp 0x6420
movq -0x8(%rbp), %rdi
movq -0xb8(%rbp), %rax
movq -0xb0(%rbp,%rax,8), %rsi
movsbl -0x19(%rbp), %edx
callq 0x3db0
addq $0xf0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)