// File: /workspace/github_c_makefile_star2_O2/cyb70289[P]tt/src/apn/decimal/basic.c
// Function: tt_dec_div
int tt_dec_div(struct tt_dec *dst, const struct tt_dec *src1,
		const struct tt_dec *src2)
{
	int ret = 0, sign = src1->_sign ^ src2->_sign;

	dst->_sign = sign;

	/* Check NaN, Inf */
	if (src1->_inf_nan == TT_DEC_NAN || src2->_inf_nan == TT_DEC_NAN) {
		dst->_inf_nan = TT_DEC_NAN;
		return TT_APN_EINVAL;
	}
	if (src1->_inf_nan == TT_DEC_INF) {
		if (src2->_inf_nan == TT_DEC_INF) {
			dst->_inf_nan = TT_DEC_NAN;
			return TT_APN_EINVAL;
		} else {
			dst->_inf_nan = TT_DEC_INF;
			return TT_APN_EOVERFLOW;
		}
	}
	if (src2->_inf_nan == TT_DEC_INF) {
		_tt_dec_zero(dst);
		return 0;
	}

	/* Check zero */
	if (_tt_dec_is_zero(src2)) {
		if (_tt_dec_is_zero(src1)) {
			dst->_inf_nan = TT_DEC_NAN;
			return TT_APN_EDIV_UNDEF;
		} else {
			dst->_inf_nan = TT_DEC_INF;
			return TT_APN_EDIV_0;
		}
	}
	if (_tt_dec_is_zero(src1)) {
		if (src1->_exp == 0) {
			dst->_exp = 0;	/* True zero */
		} else {
			dst->_exp = (src1->_exp + src1->_msb) -
				(src2->_exp + src2->_msb);
			if (dst->_exp > 0)
				dst->_exp = 0;
		}
		dst->_inf_nan = 0;
		dst->_msb = 1;
		memset(dst->_dig32, 0, dst->_digsz);
		return 0;
	}

	/* Allocate a new DEC if dst overlaps src */
	struct tt_dec *quotient = dst;
	if (quotient == src1 || quotient == src2) {
		quotient = tt_dec_alloc(quotient->_prec);
		if (!quotient)
			return TT_ENOMEM;
	} else {
		_tt_dec_zero(quotient);
	}

	quotient->_sign = sign;
	quotient->_exp = src1->_exp - src2->_exp;

	/* Allocate dividend, divisor buffer */
	const int uints = (_tt_max(src1->_msb, src2->_msb) + 1 + 8) / 9;
	uint *dividend = calloc(uints, 4);
	uint *divisor = calloc(uints, 4);
	if (!dividend || !divisor) {
		ret = TT_ENOMEM;
		goto out;
	}
	memcpy(dividend, src1->_dig32, _tt_min(src1->_digsz, uints*4));
	memcpy(divisor, src2->_dig32, _tt_min(src2->_digsz, uints*4));

	int msb_dividend = src1->_msb;
	int msb_divisor = src2->_msb;

	/* Get highest digit */
	int top_dividend = _tt_dec_get_dig(dividend, msb_dividend-1);
	int top_divisor = _tt_dec_get_dig(divisor, msb_divisor-1);
	tt_assert_fa(top_divisor && top_dividend);

	/* Make dividend/divisor within [1, 10) */
	int adj = msb_dividend - msb_divisor;
	quotient->_exp += adj;
	if (adj < 0)
		msb_dividend = shift_digs(dividend, 0,
				dividend, msb_dividend, -adj);
	else if (adj > 0)
		msb_divisor = shift_digs(divisor, 0, divisor, msb_divisor, adj);
	if (cmp_digs(dividend, msb_dividend, divisor, msb_divisor) < 0) {
		quotient->_exp--;
		msb_dividend = shift_digs(dividend, 0, dividend, msb_dividend, 1);
		tt_assert_fa(msb_dividend == msb_divisor + 1);
	} else {
		tt_assert_fa(msb_dividend == msb_divisor);
	}

	/* Remove common trailing zeros */
	while (1) {
		if (msb_dividend <= 9 || msb_divisor <= 9)
			break;
		if (dividend[0] || divisor[0])
			break;
		const int sz_dividend = (msb_dividend + 8) / 9 * 4;
		const int sz_divisor = (msb_divisor + 8) / 9 * 4;
		msb_dividend = shift_digs(dividend, sz_dividend,
				dividend, msb_dividend, -9);
		msb_divisor = shift_digs(divisor, sz_divisor,
				divisor, msb_divisor, -9);
	}

	int msb_result = 1;
	uint *result = quotient->_dig32;
	while (1) {
		tt_assert_fa(msb_result <= (quotient->_prec + 1));

		/* Repeat sub divisor from dividend till remainder < divisor */
		int r;
		for (r = 1; r < 10; r++) {
			msb_dividend = sub_digs(dividend, dividend, msb_dividend,
					divisor, msb_divisor);
			if ((msb_dividend < msb_divisor) ||
					(msb_dividend == msb_divisor &&
					 cmp_digs(dividend, msb_dividend,
						 divisor, msb_divisor) < 0))
				break;
		}
		tt_assert_fa(r < 10 && cmp_digs(dividend, msb_dividend,
					divisor, msb_divisor) < 0);

		/* Store quotient */
		tt_assert_fa(result[0] % 10 == 0);
		result[0] += r;

		/* Precision+rounding reached or residue is zero */
		if ((msb_result > quotient->_prec) ||
				(msb_dividend == 1 && dividend[0] == 0))
			break;

		/* Get highest digit */
		top_dividend = _tt_dec_get_dig(dividend, msb_dividend-1);
		top_divisor = _tt_dec_get_dig(divisor, msb_divisor-1);
		tt_assert_fa(top_divisor && top_dividend);

		/* Make dividend/divisor within [1, 10)
		 * - dividend is less than divisor now
		 */
		adj = msb_dividend - msb_divisor;
		if (adj < 0)
			msb_dividend = shift_digs(dividend, 0,
					dividend, msb_dividend, -adj);
		if (cmp_digs(dividend, msb_dividend, divisor, msb_divisor) < 0) {
			adj--;
			msb_dividend = shift_digs(dividend, 0,
					dividend, msb_dividend, 1);
			tt_assert_fa(msb_dividend == msb_divisor + 1);
		} else {
			tt_assert_fa(msb_dividend == msb_divisor);
		}
		tt_assert_fa(adj < 0);
		adj = -adj;

		/* Append zero to quotient */
		int prec_left = quotient->_prec - msb_result;
		if (adj > (prec_left+1)) {
			/* Precision+rounding reached */
			msb_result = shift_digs(result, 0,
					result, msb_result, prec_left);
			quotient->_exp -= prec_left;
			ret = TT_APN_EROUNDED;
			break;
		}
		msb_result = shift_digs(result, 0, result, msb_result, adj);
		quotient->_exp -= adj;
	}

	/* Check rounding */
	if (msb_result > quotient->_prec) {
		if (_tt_round(_tt_dec_get_dig(result, 1) & 1,
				_tt_dec_get_dig(result, 0), 0)) {
			const uint ten = 10;
			msb_result = add_digs(result, msb_result, &ten, 2);
		}
		adj = msb_result - quotient->_prec;
		msb_result = shift_digs(result, quotient->_digsz,
				result, msb_result, -adj);
		quotient->_exp += adj;
		ret = TT_APN_EROUNDED;
	}

	quotient->_msb = msb_result;

	/* Switch buffer if dst overlaps src */
	if (quotient != dst) {
		free(dst->_dig32);
		memcpy(dst, quotient, sizeof(struct tt_dec));
		free(quotient);
		quotient = NULL;
	}

out:
	if (dividend)
		free(dividend);
	if (divisor)
		free(divisor);
	if (quotient && quotient != dst)
		tt_dec_free(quotient);

	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movzwl (%rdx), %r14d
xorw (%rsi), %r14w
movq %rdi, %r15
movw %r14w, (%rdi)
movzwl 0x2(%rsi), %ecx
cmpw $0x2, %cx
je 0x341a
movq %rdx, %rbx
movzwl 0x2(%rdx), %eax
cmpw $0x2, %ax
jne 0x3439
movw $0x2, 0x2(%r15)
movl $0xffffff32, %r14d      # imm = 0xFFFFFF32
movl %r14d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpw $0x1, %cx
jne 0x3454
cmpw $0x1, %ax
je 0x341a
movw $0x1, 0x2(%r15)
movl $0xffffff36, %r14d      # imm = 0xFFFFFF36
jmp 0x3427
cmpw $0x1, %ax
jne 0x3467
movq %r15, %rdi
callq 0x1b01
xorl %r14d, %r14d
jmp 0x3427
movq %rsi, %r12
movq %rbx, %rdi
callq 0x3009
movl %eax, %ebp
movq %r12, %rdi
callq 0x3009
testb %bpl, %bpl
je 0x3494
testb %al, %al
je 0x34e3
movw $0x2, 0x2(%r15)
movl $0xffffff33, %r14d      # imm = 0xFFFFFF33
jmp 0x3427
testb %al, %al
je 0x34f5
movl 0x4(%r12), %eax
xorl %r14d, %r14d
movl $0x0, %ecx
testl %eax, %eax
je 0x34bd
movl 0x4(%rbx), %ecx
addl 0x14(%r12), %eax
addl 0x14(%rbx), %ecx
subl %ecx, %eax
movl %eax, %ecx
sarl $0x1f, %ecx
andl %eax, %ecx
movl %ecx, 0x4(%r15)
andw $0x0, 0x2(%r15)
movl $0x1, 0x14(%r15)
movq 0x18(%r15), %rdi
movl 0x10(%r15), %edx
xorl %esi, %esi
callq 0x10e0
jmp 0x3427
movw $0x1, 0x2(%r15)
movl $0xffffff34, %r14d      # imm = 0xFFFFFF34
jmp 0x3427
cmpq %r12, %r15
setne %al
cmpq %rbx, %r15
setne %cl
testb %cl, %al
jne 0x351c
movl 0x8(%r15), %edi
callq 0x1a14
testq %rax, %rax
jne 0x3527
pushq $-0x1
popq %r14
jmp 0x3427
movq %r15, %rdi
callq 0x1b01
movq %r15, %rax
movq %r15, 0x20(%rsp)
movw %r14w, (%rax)
movl 0x4(%r12), %edx
subl 0x4(%rbx), %edx
movq %rax, (%rsp)
movl %edx, 0x4(%rax)
movl 0x14(%r12), %ebp
movl 0x14(%rbx), %r13d
movl %ebp, %eax
subl %r13d, %eax
movl %eax, 0x8(%rsp)
movl %r13d, %eax
cmovgl %ebp, %eax
addl $0x9, %eax
pushq $0x9
popq %rcx
cltd
idivl %ecx
movq %rax, 0x10(%rsp)
movslq %eax, %r14
pushq $0x4
popq %rsi
movq %r14, %rdi
callq 0x1100
movq %rax, %r15
movq %r14, %rdi
pushq $0x4
popq %rsi
callq 0x1100
movq %rax, %r14
testq %r15, %r15
sete %al
testq %r14, %r14
sete %cl
orb %al, %cl
movq %r14, 0x28(%rsp)
jne 0x3620
movq 0x18(%r12), %rsi
movl 0x10(%r12), %edx
movq 0x10(%rsp), %r12
shll $0x2, %r12d
cmpl %r12d, %edx
cmovael %r12d, %edx
movq %r15, %rdi
callq 0x1120
movq 0x18(%rbx), %rsi
movl 0x10(%rbx), %eax
cmpl %r12d, %eax
cmovbl %eax, %r12d
movq %r14, %rdi
movq %r12, %rdx
callq 0x1120
leal -0x1(%rbp), %esi
movq %r15, %rdi
callq 0x1c07
movl %eax, %ebx
leal -0x1(%r13), %esi
movq %r14, %rdi
callq 0x1c07
testl %eax, %eax
je 0x3acc
testl %ebx, %ebx
je 0x3acc
movq %r14, %r12
movq (%rsp), %rax
movl 0x8(%rsp), %r8d
addl %r8d, 0x4(%rax)
testl %r8d, %r8d
js 0x362e
cmpl %r13d, %ebp
jne 0x3644
movl %ebp, %r13d
jmp 0x3657
pushq $-0x1
popq %r14
movq 0x20(%rsp), %r12
jmp 0x39af
negl %r8d
movq %r15, %rdi
xorl %esi, %esi
movq %r15, %rdx
movl %ebp, %ecx
callq 0x3024
movl %eax, %ebp
jmp 0x3657
movq %r12, %rdi
xorl %esi, %esi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x3024
movl %eax, %r13d
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x3b0a
testl %eax, %eax
js 0x3692
cmpl %r13d, %ebp
je 0x36ba
leaq 0x131f5(%rip), %rsi     # 0x1686c
leaq 0x6a04(%rip), %rdx      # 0xa082
leaq 0x131cf(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x2ff, %r8d            # imm = 0x2FF
jmp 0x3ac0
movq (%rsp), %rax
decl 0x4(%rax)
pushq $0x1
popq %r8
movq %r15, %rdi
xorl %esi, %esi
movq %r15, %rdx
movl %ebp, %ecx
callq 0x3024
movl %eax, %ebp
leal 0x1(%r13), %eax
cmpl %eax, %ebp
jne 0x3aeb
pushq $-0x9
popq %rbx
cmpl $0xa, %ebp
jl 0x3721
cmpl $0xa, %r13d
jl 0x3721
cmpl $0x0, (%r15)
jne 0x3721
cmpl $0x0, (%r12)
jne 0x3721
leal 0x8(%rbp), %eax
xorl %edx, %edx
pushq $0x9
popq %rcx
divl %ecx
leal (,%rax,4), %esi
leal 0x8(%r13), %eax
xorl %edx, %edx
divl %ecx
leal (,%rax,4), %r14d
movq %r15, %rdi
movq %r15, %rdx
movl %ebp, %ecx
movl %ebx, %r8d
callq 0x3024
movl %eax, %ebp
movq %r12, %rdi
movl %r14d, %esi
movq %r12, %rdx
movl %r13d, %ecx
movl %ebx, %r8d
callq 0x3024
movl %eax, %r13d
jmp 0x36bd
movq (%rsp), %r12
movq 0x18(%r12), %rax
movq %rax, 0x8(%rsp)
leal -0x1(%r13), %eax
movl %eax, 0x1c(%rsp)
leal 0x1(%r13), %eax
movl %eax, 0x18(%rsp)
pushq $0x1
popq %rax
movl 0x8(%r12), %ecx
incl %ecx
movl %eax, 0x10(%rsp)
cmpl %ecx, %eax
jg 0x3a05
pushq $-0x1
popq %rbx
movq 0x28(%rsp), %r12
movq 0x8(%rsp), %r14
cmpl $-0xa, %ebx
je 0x39e3
movq %r15, %rdi
movq %r15, %rsi
movl %ebp, %edx
movq %r12, %rcx
movl %r13d, %r8d
callq 0x3b5e
movl %eax, %ebp
cmpl %r13d, %eax
jl 0x37a3
jne 0x379c
movq %r15, %rdi
movl %r13d, %esi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x3b0a
testl %eax, %eax
js 0x37a0
decl %ebx
jmp 0x3762
movl %r13d, %ebp
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x3b0a
testl %eax, %eax
jns 0x39e3
movl (%r14), %ecx
movl %ecx, %eax
xorl %edx, %edx
pushq $0xa
popq %rsi
divl %esi
testl %edx, %edx
movl 0x10(%rsp), %eax
jne 0x3a27
subl %ebx, %ecx
movl %ecx, (%r14)
movq (%rsp), %rcx
movl 0x8(%rcx), %edx
xorl %r14d, %r14d
cmpl %edx, %eax
jg 0x38f2
cmpl $0x1, %ebp
jne 0x37f9
cmpl $0x0, (%r15)
je 0x38f2
leal -0x1(%rbp), %esi
movq %r15, %rdi
callq 0x1c07
movl %eax, %ebx
movq %r12, %rdi
movl 0x1c(%rsp), %esi
callq 0x1c07
testl %eax, %eax
je 0x3a46
testl %ebx, %ebx
je 0x3a46
movl %ebp, %r14d
subl %r13d, %r14d
jns 0x3841
movl %r14d, %r8d
negl %r8d
movq %r15, %rdi
xorl %esi, %esi
movq %r15, %rdx
movl %ebp, %ecx
callq 0x3024
movl %eax, %ebp
movq %r15, %rdi
movl %ebp, %esi
movq %r12, %rdx
movl %r13d, %ecx
callq 0x3b0a
testl %eax, %eax
js 0x386a
cmpl %r13d, %ebp
movl %r13d, %ebp
movq (%rsp), %r12
movl 0x10(%rsp), %ecx
je 0x3896
jmp 0x3a84
movq %r15, %rdi
xorl %esi, %esi
movq %r15, %rdx
movl %ebp, %ecx
pushq $0x1
popq %r8
callq 0x3024
movl 0x18(%rsp), %ecx
cmpl %ecx, %eax
jne 0x3aa3
decl %r14d
movl %ecx, %ebp
movq (%rsp), %r12
movl 0x10(%rsp), %ecx
testl %r14d, %r14d
jns 0x3a65
movl %r14d, %r8d
negl %r8d
movl 0x8(%r12), %ebx
subl %ecx, %ebx
leal 0x1(%rbx), %eax
cmpl %r8d, %eax
jl 0x38cd
movq 0x8(%rsp), %rdi
xorl %esi, %esi
movq %rdi, %rdx
callq 0x3024
addl %r14d, 0x4(%r12)
jmp 0x3742
movq 0x8(%rsp), %rdi
xorl %esi, %esi
movq %rdi, %rdx
movl %ebx, %r8d
callq 0x3024
subl %ebx, 0x4(%r12)
movl 0x8(%r12), %edx
movl $0xc9, %r14d
movq %r12, %rcx
cmpl %edx, %eax
movq 0x20(%rsp), %r12
jle 0x3978
movl %eax, %ebp
pushq $0x1
popq %rsi
movq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0x1c07
movl %eax, %ebx
andl $0x1, %ebx
movq %r14, %rdi
xorl %esi, %esi
callq 0x1c07
movl %ebx, %edi
movl %eax, %esi
xorl %edx, %edx
callq 0x829c
testl %eax, %eax
je 0x394a
leaq 0x34(%rsp), %rdx
movl $0xa, (%rdx)
pushq $0x2
popq %rcx
movq %r14, %rdi
movl %ebp, %esi
callq 0x32b5
movl %eax, %ecx
movq %r14, %rdi
jmp 0x394f
movq %r14, %rdi
movl %ebp, %ecx
movl %ecx, %ebx
movq (%rsp), %r14
subl 0x8(%r14), %ebx
movl 0x10(%r14), %esi
movl %ebx, %r8d
negl %r8d
movq %rdi, %rdx
callq 0x3024
movq %r14, %rcx
addl %ebx, 0x4(%r14)
movl $0xc9, %r14d
movl %eax, 0x14(%rcx)
cmpq %r12, %rcx
je 0x39af
movq %rcx, %rbx
movq 0x18(%r12), %rdi
callq 0x1030
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movups %xmm1, 0x10(%r12)
movups %xmm0, (%r12)
movq %rbx, %rdi
callq 0x1030
movq $0x0, (%rsp)
movq %r15, %rdi
callq 0x1030
movq 0x28(%rsp), %rdi
callq 0x1030
movq (%rsp), %rdi
testq %rdi, %rdi
sete %al
cmpq %r12, %rdi
sete %cl
orb %al, %cl
jne 0x3427
callq 0x1aeb
jmp 0x3427
leaq 0x12e82(%rip), %rsi     # 0x1686c
leaq 0x6691(%rip), %rdx      # 0xa082
leaq 0x12e5c(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x321, %r8d            # imm = 0x321
jmp 0x3ac0
leaq 0x12e60(%rip), %rsi     # 0x1686c
leaq 0x666f(%rip), %rdx      # 0xa082
leaq 0x12e3a(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x313, %r8d            # imm = 0x313
jmp 0x3ac0
leaq 0x12e3e(%rip), %rsi     # 0x1686c
leaq 0x664d(%rip), %rdx      # 0xa082
leaq 0x12e18(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x324, %r8d            # imm = 0x324
jmp 0x3ac0
leaq 0x12e1f(%rip), %rsi     # 0x1686c
leaq 0x662e(%rip), %rdx      # 0xa082
leaq 0x12df9(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x32f, %r8d            # imm = 0x32F
jmp 0x3ac0
leaq 0x12e00(%rip), %rsi     # 0x1686c
leaq 0x660f(%rip), %rdx      # 0xa082
leaq 0x12dda(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x340, %r8d            # imm = 0x340
jmp 0x3ac0
leaq 0x12de1(%rip), %rsi     # 0x1686c
leaq 0x65f0(%rip), %rdx      # 0xa082
leaq 0x12dbb(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x33e, %r8d            # imm = 0x33E
jmp 0x3ac0
leaq 0x12dc2(%rip), %rsi     # 0x1686c
leaq 0x65d1(%rip), %rdx      # 0xa082
leaq 0x12d9c(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x33c, %r8d            # imm = 0x33C
xorl %eax, %eax
callq 0x7de8
callq 0x1050
leaq 0x12d99(%rip), %rsi     # 0x1686c
leaq 0x65a8(%rip), %rdx      # 0xa082
leaq 0x12d73(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x2f0, %r8d            # imm = 0x2F0
jmp 0x3ac0
leaq 0x12d7a(%rip), %rsi     # 0x1686c
leaq 0x6589(%rip), %rdx      # 0xa082
leaq 0x12d54(%rip), %rcx     # 0x16854
xorl %edi, %edi
movl $0x2fd, %r8d            # imm = 0x2FD
jmp 0x3ac0