// File: simap[P]ecctools/lib/uECC.c
// Function: uECC_vli_modInv(unsigned long*, unsigned long const*, unsigned long const*, signed char)
uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result,
                                  const uECC_word_t *input,
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
    uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
    cmpresult_t cmpResult;

    if (uECC_vli_isZero(input, num_words)) {
        uECC_vli_clear(result, num_words);
        return;
    }

    uECC_vli_set(a, input, num_words);
    uECC_vli_set(b, mod, num_words);
    uECC_vli_clear(u, num_words);
    u[0] = 1;
    uECC_vli_clear(v, num_words);
    while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
        if (EVEN(a)) {
            uECC_vli_rshift1(a, num_words);
            vli_modInv_update(u, mod, num_words);
        } else if (EVEN(b)) {
            uECC_vli_rshift1(b, num_words);
            vli_modInv_update(v, mod, num_words);
        } else if (cmpResult > 0) {
            uECC_vli_sub(a, a, b, num_words);
            uECC_vli_rshift1(a, num_words);
            if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
                uECC_vli_add(u, u, mod, num_words);
            }
            uECC_vli_sub(u, u, v, num_words);
            vli_modInv_update(u, mod, num_words);
        } else {
            uECC_vli_sub(b, b, a, num_words);
            uECC_vli_rshift1(b, num_words);
            if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
                uECC_vli_add(v, v, mod, num_words);
            }
            uECC_vli_sub(v, v, u, num_words);
            vli_modInv_update(v, mod, num_words);
        }
    }
    uECC_vli_set(result, u, num_words);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movb %al, -0x19(%rbp)
movq -0x10(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x22e0
cmpq $0x0, %rax
je 0x3a01
movq -0x8(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4170
jmp 0x3c03
leaq -0x40(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x3db0
leaq -0x60(%rbp), %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x3db0
leaq -0x80(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4170
movq $0x1, -0x80(%rbp)
leaq -0xa0(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4170
leaq -0x40(%rbp), %rdi
leaq -0x60(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x2640
movb %al, -0xa1(%rbp)
movsbl %al, %eax
cmpl $0x0, %eax
je 0x3bf2
movq -0x40(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x3a9c
leaq -0x40(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
leaq -0x80(%rbp), %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x6080
jmp 0x3bed
movq -0x60(%rbp), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x3ad0
leaq -0x60(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
leaq -0xa0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x6080
jmp 0x3beb
movsbl -0xa1(%rbp), %eax
cmpl $0x0, %eax
jle 0x3b61
leaq -0x40(%rbp), %rdi
leaq -0x40(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x24b0
leaq -0x40(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
leaq -0x80(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x2640
movsbl %al, %eax
cmpl $0x0, %eax
jge 0x3b33
leaq -0x80(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x48c0
leaq -0x80(%rbp), %rdi
leaq -0x80(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x24b0
leaq -0x80(%rbp), %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x6080
jmp 0x3be9
leaq -0x60(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x40(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x24b0
leaq -0x60(%rbp), %rdi
movsbl -0x19(%rbp), %esi
callq 0x4960
leaq -0xa0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x2640
movsbl %al, %eax
cmpl $0x0, %eax
jge 0x3bba
leaq -0xa0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
movq -0x18(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x48c0
leaq -0xa0(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x80(%rbp), %rdx
movsbl -0x19(%rbp), %ecx
callq 0x24b0
leaq -0xa0(%rbp), %rdi
movq -0x18(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x6080
jmp 0x3beb
jmp 0x3bed
jmp 0x3a48
movq -0x8(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movsbl -0x19(%rbp), %edx
callq 0x3db0
addq $0xb0, %rsp
popq %rbp
retq
nopl (%rax)