// File: /workspace/github_c_makefile_star2_O3/983[P]bigint/bigint.c
// Function: bigint_div_mod
bigint* bigint_div_mod(
    bigint *dst_quotient,
    bigint *dst_remainder,
    const bigint *src_numerator,
    const bigint *src_denominator
){
    int shift;
    int src_numerator_neg = src_numerator->neg;
    int src_denominator_neg = src_denominator->neg;
    bigint denominator[1], *remainder = dst_remainder, *quotient = dst_quotient;

    if (src_denominator->size == 0) return NULL;

    /* fast path for native word size */
    if (src_numerator->size == 1 && src_denominator->size == 1){
        /* make sure this is not overwritten */
        bigint_word a = src_numerator->words[0];
        bigint_word b = src_denominator->words[0];
        bigint_from_word(quotient, a / b);
        bigint_from_word(remainder, a % b);
        quotient->neg = src_numerator_neg ^ src_denominator_neg;
        remainder->neg = src_numerator_neg;
        return dst_quotient;
    }

    /* fast path for half word size */
    if (src_denominator->size == 1 &&
        src_denominator->words[0] <= BIGINT_HALF_WORD_MAX
    ){
        bigint_word rem;
        bigint_cpy(quotient, src_numerator);
        bigint_div_mod_half_word(quotient, &rem, src_denominator->words[0]);
        bigint_from_word(remainder, rem);
        quotient->neg = src_numerator_neg ^ src_denominator_neg;
        remainder->neg = src_numerator_neg;
        return dst_quotient;
    }

    bigint_cpy(remainder, src_numerator);
    remainder->neg = 0;
    quotient->size = 0;

    if (bigint_cmp_abs(remainder, src_denominator) >= 0){
        shift = bigint_bitlength(remainder) - bigint_bitlength(src_denominator);

        bigint_init(denominator);
        bigint_shift_left(denominator, src_denominator, shift);
        denominator->neg = 0;

        /* divide bit by bit */
        for (; shift >= 0; shift--) {
            if (bigint_cmp_abs(remainder, denominator) >= 0) {
                bigint_sub(remainder, remainder, denominator);
                bigint_set_bit(quotient, shift);
            }
            bigint_shift_right(denominator, denominator, 1);
        }

        bigint_free(denominator);
    }

    quotient->neg = src_numerator_neg ^ src_denominator_neg;
    remainder->neg = src_numerator_neg;
    return dst_quotient;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl 0xc(%rcx), %eax
testl %eax, %eax
je 0x305c
movq %rcx, %r15
movq %rsi, %r14
movq %rdi, %rbx
movl 0x8(%rdx), %r13d
movl 0x8(%rcx), %ebp
cmpl $0x1, %eax
jne 0x3063
cmpl $0x1, 0xc(%rdx)
jne 0x3063
movq (%rdx), %rax
movl %r13d, 0x8(%rsp)
movl %ebp, %r13d
movl (%rax), %ebp
movq (%r15), %rax
movl (%rax), %r12d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x1a55
movq (%rbx), %rcx
movl %ebp, %eax
xorl %edx, %edx
divl %r12d
movl %edx, %r15d
xorl %edx, %edx
cmpl %ebp, %r12d
setbe %dl
movl %eax, (%rcx)
movl %edx, 0xc(%rbx)
movl $0x0, 0x8(%rbx)
movq %r14, %rdi
movl $0x1, %esi
callq 0x1a55
movq (%r14), %rax
movl %r15d, (%rax)
xorl %eax, %eax
testl %r15d, %r15d
setne %al
movl %eax, 0xc(%r14)
movl 0x8(%rsp), %eax
xorl %eax, %r13d
movl %r13d, 0x8(%rbx)
movl %eax, 0x8(%r14)
jmp 0x3210
xorl %ebx, %ebx
jmp 0x3210
cmpl $0x1, %eax
jne 0x30c2
movq (%r15), %rax
cmpl $0xffff, (%rax)         # imm = 0xFFFF
ja 0x30c2
movq %rbx, %rdi
movq %rdx, %rsi
callq 0x1c42
movq (%r15), %rax
movl (%rax), %edx
leaq 0x10(%rsp), %r15
movq %rbx, %rdi
movq %r15, %rsi
callq 0x3222
movl %ebp, %r12d
movl (%r15), %ebp
movq %r14, %rdi
movl $0x1, %esi
callq 0x1a55
movq (%r14), %rax
movl %ebp, (%rax)
xorl %eax, %eax
testl %ebp, %ebp
setne %al
movl %eax, 0xc(%r14)
xorl %r13d, %r12d
movl %r12d, 0x8(%rbx)
jmp 0x320c
movq %r14, %rdi
movq %rdx, %rsi
callq 0x1c42
xorl %r12d, %r12d
movl %r12d, 0x8(%r14)
movl %r12d, 0xc(%rbx)
movq (%r14), %rdi
movl 0xc(%r14), %esi
movq (%r15), %rdx
movl 0xc(%r15), %ecx
callq 0x1ae4
testl %eax, %eax
js 0x3206
movl 0xc(%r14), %eax
testl %eax, %eax
jle 0x3122
movq (%r14), %rcx
decl %eax
movl (%rcx,%rax,4), %edx
movl $0x20, %ecx
leal -0x1(%rcx), %esi
movzbl %sil, %esi
btl %esi, %edx
jb 0x311a
decl %ecx
jne 0x3108
xorl %ecx, %ecx
shll $0x5, %eax
addl %ecx, %eax
movl %eax, %r12d
movl %ebp, 0xc(%rsp)
movl %r13d, 0x8(%rsp)
movl 0xc(%r15), %eax
xorl %edi, %edi
movl $0x0, %ebp
testl %eax, %eax
jle 0x3160
movq (%r15), %rcx
decl %eax
movl (%rcx,%rax,4), %edx
movl $0x20, %ecx
leal -0x1(%rcx), %esi
movzbl %sil, %esi
btl %esi, %edx
jb 0x3159
decl %ecx
jne 0x3147
xorl %ecx, %ecx
shll $0x5, %eax
addl %ecx, %eax
movl %eax, %ebp
leaq 0x10(%rsp), %r13
movl %edi, 0x10(%r13)
xorps %xmm0, %xmm0
movaps %xmm0, (%r13)
movl %r12d, %edx
subl %ebp, %edx
movq %r13, %rdi
movq %r15, %rsi
callq 0x2e85
subl %ebp, %r12d
movl $0x0, %eax
movl %eax, 0x8(%r13)
movl 0x8(%rsp), %r13d
movl 0xc(%rsp), %ebp
js 0x31fc
leaq 0x10(%rsp), %r15
movq (%r14), %rdi
movl 0xc(%r14), %esi
movq 0x10(%rsp), %rdx
movl 0x1c(%rsp), %ecx
callq 0x1ae4
testl %eax, %eax
js 0x31df
movl 0x8(%r14), %edx
xorl %r8d, %r8d
cmpl $0x0, 0x18(%rsp)
sete %r8b
movq %r14, %rdi
movq %r14, %rsi
movq %r15, %rcx
callq 0x2a19
movq %rbx, %rdi
movl %r12d, %esi
callq 0x1d1d
movq %r15, %rdi
movq %r15, %rsi
movl $0x1, %edx
callq 0x2ed1
leal -0x1(%r12), %eax
testl %r12d, %r12d
movl %eax, %r12d
jg 0x319d
movq 0x10(%rsp), %rdi
callq 0x1030
xorl %r13d, %ebp
movl %ebp, 0x8(%rbx)
movl %r13d, 0x8(%r14)
movq %rbx, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq