// File: /workspace/github_c_makefile_star2_O1/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 $0x48, %rsp
movzwl (%rdx), %ebp
xorw (%rsi), %bp
movq %rdi, %r15
movw %bp, (%rdi)
movzwl 0x2(%rsi), %eax
cmpw $0x2, %ax
je 0x3f72
movq %rdx, %rbx
movzwl 0x2(%rdx), %edx
cmpw $0x2, %dx
jne 0x3f8f
movw $0x2, 0x2(%r15)
movl $0xffffff32, %ebx       # imm = 0xFFFFFF32
movl %ebx, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpw $0x1, %ax
jne 0x3fa9
cmpw $0x1, %dx
je 0x3f72
movw $0x1, 0x2(%r15)
movl $0xffffff36, %ebx       # imm = 0xFFFFFF36
jmp 0x3f7e
cmpw $0x1, %dx
jne 0x3fbb
movq %r15, %rdi
callq 0x2540
xorl %ebx, %ebx
jmp 0x3f7e
movq %rsi, %r14
movl 0x14(%rbx), %ecx
cmpl $0x1, %ecx
jne 0x4006
testw %dx, %dx
jne 0x4006
movq 0x18(%rbx), %rdx
cmpl $0x0, (%rdx)
jne 0x4006
cmpl $0x1, 0x14(%r14)
jne 0x41a4
testw %ax, %ax
jne 0x41a4
movq 0x18(%r14), %rax
cmpl $0x0, (%rax)
jne 0x41a4
movw $0x2, 0x2(%r15)
movl $0xffffff33, %ebx       # imm = 0xFFFFFF33
jmp 0x3f7e
movl 0x14(%r14), %edx
cmpl $0x1, %edx
jne 0x4040
testw %ax, %ax
jne 0x4040
movq 0x18(%r14), %rax
cmpl $0x0, (%rax)
jne 0x4040
movl 0x4(%r14), %eax
testl %eax, %eax
je 0x44f6
addl %eax, %edx
addl 0x4(%rbx), %ecx
subl %ecx, %edx
movl %edx, %eax
sarl $0x1f, %eax
andl %edx, %eax
movl %eax, 0x4(%r15)
jmp 0x44fe
cmpq %r14, %r15
setne %al
cmpq %rbx, %r15
setne %cl
testb %cl, %al
jne 0x4068
movl 0x8(%r15), %edi
callq 0x244c
testq %rax, %rax
jne 0x4073
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
jmp 0x3f7e
movq %r15, %rdi
callq 0x2540
movq %r15, %rax
movq %r15, 0x30(%rsp)
movw %bp, (%rax)
movl 0x4(%r14), %ecx
subl 0x4(%rbx), %ecx
movq %rax, 0x20(%rsp)
movl %ecx, 0x4(%rax)
movl 0x14(%r14), %ebp
movl 0x14(%rbx), %r13d
movl %ebp, %eax
subl %r13d, %eax
movl %eax, 0x10(%rsp)
movl %r13d, %eax
cmovgl %ebp, %eax
addl $0x9, %eax
cltq
imulq $0x38e38e39, %rax, %rcx # imm = 0x38E38E39
movq %rcx, %rax
shrq $0x3f, %rax
sarq $0x21, %rcx
addl %eax, %ecx
movq %rcx, 0x28(%rsp)
movslq %ecx, %r15
movl $0x4, %esi
movq %r15, %rdi
callq 0x1100
movq %rax, %r12
movl $0x4, %esi
movq %r15, %rdi
callq 0x1100
movq %rax, %r15
testq %r12, %r12
sete %al
testq %r15, %r15
sete %cl
movl $0xffffffff, 0xc(%rsp)  # imm = 0xFFFFFFFF
orb %al, %cl
movq %r15, 0x18(%rsp)
jne 0x4195
movq 0x18(%r14), %rsi
movl 0x10(%r14), %edx
movq 0x28(%rsp), %r14
shll $0x2, %r14d
cmpl %r14d, %edx
cmovael %r14d, %edx
movq %r12, %rdi
callq 0x1120
movq 0x18(%rbx), %rsi
movl 0x10(%rbx), %eax
cmpl %r14d, %eax
cmovbl %eax, %r14d
movq %r15, %rdi
movq %r14, %rdx
callq 0x1120
leal -0x1(%rbp), %esi
movq %r12, %rdi
callq 0x269c
movl %eax, %ebx
leal -0x1(%r13), %esi
movq %r15, %rdi
callq 0x269c
testl %eax, %eax
je 0x45df
testl %ebx, %ebx
je 0x45df
movq %r15, %r14
movq 0x20(%rsp), %r15
movl 0x10(%rsp), %r8d
addl %r8d, 0x4(%r15)
testl %r8d, %r8d
js 0x41b5
cmpl %r13d, %ebp
je 0x41c9
movq %r14, %rdi
xorl %esi, %esi
movq %r14, %rdx
movl %r13d, %ecx
callq 0x3b20
movl %eax, %r13d
jmp 0x41c9
movq 0x30(%rsp), %r14
movq 0x20(%rsp), %r15
jmp 0x457b
movw $0x1, 0x2(%r15)
movl $0xffffff34, %ebx       # imm = 0xFFFFFF34
jmp 0x3f7e
negl %r8d
movq %r12, %rdi
xorl %esi, %esi
movq %r12, %rdx
movl %ebp, %ecx
callq 0x3b20
movl %eax, %ebp
movq %r12, %rdi
movl %ebp, %esi
movq %r14, %rdx
movl %r13d, %ecx
callq 0x45e9
testl %eax, %eax
js 0x41e7
cmpl %r13d, %ebp
je 0x420e
callq 0x14b6
decl 0x4(%r15)
movq %r12, %rdi
xorl %esi, %esi
movq %r12, %rdx
movl %ebp, %ecx
movl $0x1, %r8d
callq 0x3b20
movl %eax, %ebp
leal 0x1(%r13), %eax
cmpl %eax, %ebp
jne 0x45e4
cmpl $0xa, %ebp
jl 0x4286
cmpl $0xa, %r13d
jl 0x4286
cmpl $0x0, (%r12)
jne 0x4286
cmpl $0x0, (%r14)
jne 0x4286
leal 0x8(%rbp), %eax
imulq $0x38e38e39, %rax, %rsi # imm = 0x38E38E39
shrq $0x20, %rsi
addl %esi, %esi
andl $-0x4, %esi
leal 0x8(%r13), %eax
imulq $0x38e38e39, %rax, %rbx # imm = 0x38E38E39
shrq $0x20, %rbx
addl %ebx, %ebx
andl $-0x4, %ebx
movq %r12, %rdi
movq %r12, %rdx
movl %ebp, %ecx
movl $0xfffffff7, %r8d       # imm = 0xFFFFFFF7
callq 0x3b20
movl %eax, %ebp
movq %r14, %rdi
movl %ebx, %esi
movq %r14, %rdx
movl %r13d, %ecx
movl $0xfffffff7, %r8d       # imm = 0xFFFFFFF7
callq 0x3b20
movl %eax, %r13d
cmpl $0xa, %ebp
jl 0x4286
cmpl $0x9, %r13d
jg 0x4219
movq 0x18(%r15), %rdi
leal -0x1(%r13), %eax
movl %eax, 0x40(%rsp)
leal 0x1(%r13), %eax
movl %eax, 0x3c(%rsp)
movl $0x0, 0xc(%rsp)
movl $0x1, %eax
movq %rdi, 0x10(%rsp)
movl 0x8(%r15), %ecx
incl %ecx
cmpl %ecx, %eax
jg 0x45c1
movl %eax, 0x28(%rsp)
movq %r12, %rdi
movq %r12, %rsi
movl %ebp, %edx
movq %r14, %rcx
movl %r13d, %r8d
callq 0x4644
movl %eax, %ebp
movb $0x1, %r14b
movl $0x1, %ebx
cmpl %r13d, %eax
jl 0x4324
cmpl %r13d, %ebp
jne 0x42fb
movq %r12, %rdi
movl %ebp, %esi
movq 0x18(%rsp), %rdx
movl %r13d, %ecx
callq 0x45e9
testl %eax, %eax
js 0x4324
cmpl $0x9, %ebx
setb %r14b
je 0x431f
movq %r12, %rdi
movq %r12, %rsi
movl %ebp, %edx
movq 0x18(%rsp), %rcx
movl %r13d, %r8d
callq 0x4644
movl %eax, %ebp
incl %ebx
jmp 0x42db
movl $0xa, %ebx
testb $0x1, %r14b
movq 0x18(%rsp), %r14
je 0x45bc
movq %r12, %rdi
movl %ebp, %esi
movq %r14, %rdx
movl %r13d, %ecx
callq 0x45e9
testl %eax, %eax
jns 0x45bc
movq 0x10(%rsp), %rdi
movl (%rdi), %eax
imull $0xcccccccd, %eax, %ecx # imm = 0xCCCCCCCD
rorl %ecx
cmpl $0x1999999a, %ecx       # imm = 0x1999999A
jae 0x45c6
addl %ebx, %eax
movl %eax, (%rdi)
movl 0x28(%rsp), %eax
cmpl 0x8(%r15), %eax
jle 0x437c
xorl %r15d, %r15d
jmp 0x448b
cmpl $0x1, %ebp
jne 0x4388
cmpl $0x0, (%r12)
je 0x4374
leal -0x1(%rbp), %esi
movq %r12, %rdi
callq 0x269c
movl %eax, %ebx
movq %r14, %rdi
movl 0x40(%rsp), %esi
callq 0x269c
testl %eax, %eax
je 0x45cb
testl %ebx, %ebx
je 0x45cb
movl %ebp, %r14d
subl %r13d, %r14d
jns 0x43d0
movl %r14d, %r8d
negl %r8d
movq %r12, %rdi
xorl %esi, %esi
movq %r12, %rdx
movl %ebp, %ecx
callq 0x3b20
movl %eax, %ebp
movq %r12, %rdi
movl %ebp, %esi
movq 0x18(%rsp), %rdx
movl %r13d, %ecx
callq 0x45e9
testl %eax, %eax
js 0x43f4
cmpl %r13d, %ebp
movl 0x28(%rsp), %ecx
je 0x441c
jmp 0x45d5
movq %r12, %rdi
xorl %esi, %esi
movq %r12, %rdx
movl %ebp, %ecx
movl $0x1, %r8d
callq 0x3b20
cmpl 0x3c(%rsp), %eax
jne 0x45da
movl %eax, %ebp
decl %r14d
movl 0x28(%rsp), %ecx
testl %r14d, %r14d
jns 0x45d0
movl %r14d, %r8d
negl %r8d
movl 0x8(%r15), %ebx
subl %ecx, %ebx
leal 0x1(%rbx), %eax
cmpl %r8d, %eax
setge %r15b
jl 0x4457
movq 0x10(%rsp), %rdi
xorl %esi, %esi
movq %rdi, %rdx
callq 0x3b20
movq 0x20(%rsp), %rcx
addl 0x4(%rcx), %r14d
jmp 0x447d
movq 0x10(%rsp), %rdi
xorl %esi, %esi
movq %rdi, %rdx
movl %ebx, %r8d
callq 0x3b20
movq 0x20(%rsp), %rcx
movl 0x4(%rcx), %r14d
subl %ebx, %r14d
movl $0xc9, 0xc(%rsp)
movl %r14d, 0x4(%rcx)
movq 0x18(%rsp), %r14
movq 0x10(%rsp), %rdi
testb %r15b, %r15b
movq 0x20(%rsp), %r15
jne 0x42ac
cmpl 0x8(%r15), %eax
jle 0x44ef
movl %eax, %ebp
movl $0x1, %esi
movq %rdi, %r13
callq 0x269c
movl %eax, %ebx
andl $0x1, %ebx
movq %r13, %rdi
xorl %esi, %esi
callq 0x269c
movl %ebx, %edi
movl %eax, %esi
xorl %edx, %edx
callq 0x9052
testl %eax, %eax
movq 0x30(%rsp), %r14
je 0x4523
leaq 0x44(%rsp), %rdx
movl $0xa, (%rdx)
movq %r13, %rdi
movl %ebp, %esi
movl $0x2, %ecx
callq 0x3e17
movl %eax, %ecx
jmp 0x4525
movq 0x30(%rsp), %r14
jmp 0x454c
movl $0x0, 0x4(%r15)
movw $0x0, 0x2(%r15)
movl $0x1, 0x14(%r15)
movq 0x18(%r15), %rdi
movl 0x10(%r15), %edx
xorl %ebx, %ebx
xorl %esi, %esi
callq 0x10e0
jmp 0x3f7e
movl %ebp, %ecx
movl %ecx, %ebx
subl 0x8(%r15), %ebx
movl 0x10(%r15), %esi
movl %ebx, %r8d
negl %r8d
movq %r13, %rdi
movq %r13, %rdx
callq 0x3b20
addl %ebx, 0x4(%r15)
movl $0xc9, 0xc(%rsp)
movl %eax, 0x14(%r15)
cmpq %r14, %r15
je 0x457b
movq 0x18(%r14), %rdi
callq 0x1030
movups (%r15), %xmm0
movups 0x10(%r15), %xmm1
movups %xmm1, 0x10(%r14)
movups %xmm0, (%r14)
movq %r15, %rdi
callq 0x1030
xorl %r15d, %r15d
testq %r12, %r12
je 0x4588
movq %r12, %rdi
callq 0x1030
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
movl 0xc(%rsp), %ebx
je 0x459b
callq 0x1030
testq %r15, %r15
sete %al
cmpq %r14, %r15
sete %cl
orb %al, %cl
jne 0x3f7e
movq %r15, %rdi
callq 0x252a
jmp 0x3f7e
callq 0x15dc
callq 0x1606
callq 0x150a
callq 0x15b2
callq 0x1588
callq 0x1534
callq 0x155e
callq 0x1630
callq 0x14e0