// File: /workspace/github_c_makefile_star2_O3/cyb70289[P]tt/src/apn/decimal/basic.c
// Function: tt_dec_mul
int tt_dec_mul(struct tt_dec *dst, const struct tt_dec *src1,
		const struct tt_dec *src2)
{
	int ret = 0;

	dst->_sign = src1->_sign ^ src2->_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 || src2->_inf_nan == TT_DEC_INF) {
		dst->_inf_nan = TT_DEC_INF;
		return TT_APN_EOVERFLOW;
	}
	dst->_inf_nan = 0;

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

	dst->_exp = src1->_exp + src2->_exp;

	/* Allocate result buffer
	 * - add one extra rounding guard digits
	 * - add 18 digits for extra 0 introduced by uint boundary
	 */
	const int uints = (src1->_msb + src2->_msb + 1 + 18 + 8) / 9;
	uint *digr = calloc(uints, 4);
	if (!digr)
		return TT_ENOMEM;

	/* Multiply */
	int msb = mul_digs(digr, src1->_dig32, src1->_msb,
			src2->_dig32, src2->_msb);

	/* Adjust significand, msb */
	int adj = 0;
	if (msb > dst->_prec) {
		adj = msb - dst->_prec;

		/* Check rounding */
		if (_tt_round(_tt_dec_get_dig(digr, adj) & 1,
				_tt_dec_get_dig(digr, adj-1), 0)) {
			/* Shift digr to have 1~9 extra digs */
			if (adj >= 10) {
				int shift = (adj - 1) / 9;
				shift *= 9;
				shift_digs(digr, uints*4, digr, msb, -shift);
				adj -= shift;
				msb -= shift;
				dst->_exp += shift;
			}
			/* Add 10^adj */
			tt_assert_fa(adj >=1 && adj <= 9);
			uint one[2] = { 0, 0 };
			one[adj / 9] = one_tbl[adj % 9];
			msb = add_digs(digr, msb, one, adj+1);
			/* Get new exponent adjust */
			adj = msb - dst->_prec;
			tt_assert_fa(adj >= 1);
		}

		dst->_exp += adj;
		dst->_msb = dst->_prec;
		ret = TT_APN_EROUNDED;
	} else {
		dst->_msb = msb;
	}

	/* Copy to dst */
	memset(dst->_dig32, 0, dst->_digsz);
	shift_digs(dst->_dig32, dst->_digsz, digr, msb, -adj);

	free(digr);
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movzwl (%rdx), %eax
xorw (%rsi), %ax
movq %rdi, %rbx
movw %ax, (%rdi)
movzwl 0x2(%rsi), %eax
cmpw $0x2, %ax
je 0x36e1
movq %rdx, %r15
movzwl 0x2(%rdx), %ecx
cmpw $0x2, %cx
jne 0x36ff
movw $0x2, 0x2(%rbx)
movl $0xffffff32, %r12d      # imm = 0xFFFFFF32
movl %r12d, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpw $0x1, %ax
setne %al
cmpw $0x1, %cx
setne %cl
testb %cl, %al
jne 0x371f
movw $0x1, 0x2(%rbx)
movl $0xffffff36, %r12d      # imm = 0xFFFFFF36
jmp 0x36ed
movq %rsi, %r12
movw $0x0, 0x2(%rbx)
movl 0x14(%rsi), %ebp
cmpl $0x1, %ebp
jne 0x3747
movq 0x18(%r12), %rax
cmpl $0x0, (%rax)
jne 0x3747
cmpw $0x0, 0x2(%r12)
je 0x38b8
movl 0x14(%r15), %r14d
cmpl $0x1, %r14d
jne 0x3766
movq 0x18(%r15), %rax
cmpl $0x0, (%rax)
jne 0x3766
cmpw $0x0, 0x2(%r15)
je 0x38b8
movl 0x4(%r15), %eax
addl 0x4(%r12), %eax
movl %eax, 0x4(%rbx)
leal (%r14,%rbp), %eax
addl $0x1b, %eax
cltq
imulq $0x38e38e39, %rax, %r13 # imm = 0x38E38E39
movq %r13, %rax
shrq $0x3f, %rax
sarq $0x21, %r13
addl %eax, %r13d
movslq %r13d, %rdi
movl $0x4, %esi
callq 0x1100
testq %rax, %rax
je 0x38a5
movq 0x18(%r12), %rsi
movq 0x18(%r15), %rcx
movq %rax, %rdi
movl %ebp, %edx
movl %r14d, %r8d
movq %rax, %r14
callq 0x395f
movl %eax, %ebp
xorl %r12d, %r12d
movl %eax, %r15d
subl 0x8(%rbx), %r15d
movq %r14, 0x8(%rsp)
jle 0x38b0
movq %r14, %rdi
movl %r15d, %esi
callq 0x2607
movl %eax, %r12d
andl $0x1, %r12d
leal -0x1(%r15), %eax
movq %r14, %rdi
movl %eax, %r14d
movl %eax, %esi
callq 0x2607
movl %r12d, %edi
movl %eax, %esi
xorl %edx, %edx
callq 0x90d6
testl %eax, %eax
je 0x38e9
cmpl $0xa, %r15d
jl 0x384b
movl %r14d, %eax
imulq $0x38e38e39, %rax, %rax # imm = 0x38E38E39
shrq $0x21, %rax
leal (%rax,%rax,8), %r14d
shll $0x2, %r13d
movl %r14d, %r8d
negl %r8d
movq 0x8(%rsp), %rdi
movl %r13d, %esi
movq %rdi, %rdx
movl %ebp, %ecx
callq 0x3ac9
subl %r14d, %r15d
subl %r14d, %ebp
addl %r14d, 0x4(%rbx)
leal -0xa(%r15), %eax
cmpl $-0xa, %eax
jbe 0x395a
leaq 0x10(%rsp), %rdx
movq $0x0, (%rdx)
xorl %eax, %eax
movl %r15d, %ecx
subl $0x9, %ecx
cmovbl %r15d, %ecx
leaq 0x7919(%rip), %rsi      # 0xb190
movl (%rsi,%rcx,4), %ecx
setae %al
movl %ecx, 0x10(%rsp,%rax,4)
incl %r15d
movq 0x8(%rsp), %rdi
movl %ebp, %esi
movl %r15d, %ecx
callq 0x3dca
movl %eax, %ebp
movl 0x8(%rbx), %eax
movl %ebp, %r15d
subl %eax, %r15d
jg 0x38ec
callq 0x1394
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
jmp 0x36ed
movl %ebp, %r14d
xorl %r15d, %r15d
jmp 0x38fb
movl 0x4(%r12), %eax
testl %eax, %eax
je 0x3936
movl 0x4(%r15), %ecx
testl %ecx, %ecx
je 0x3936
movl 0x14(%r15), %edx
addl %eax, %ebp
addl %ecx, %ebp
leal (%rdx,%rbp), %eax
decl %eax
leal (%rdx,%rbp), %ecx
addl $-0x2, %ecx
xorl %edx, %edx
cmpl $0x2, %eax
cmovll %ecx, %edx
movl %edx, 0x4(%rbx)
jmp 0x393d
movl 0x8(%rbx), %eax
addl %r15d, 0x4(%rbx)
movl %ebp, %r14d
movl $0xc9, %r12d
movl %eax, %ebp
movl %ebp, 0x14(%rbx)
movq 0x18(%rbx), %rdi
movl 0x10(%rbx), %edx
xorl %esi, %esi
callq 0x10e0
movq 0x18(%rbx), %rdi
movl 0x10(%rbx), %esi
negl %r15d
movq 0x8(%rsp), %rbx
movq %rbx, %rdx
movl %r14d, %ecx
movl %r15d, %r8d
callq 0x3ac9
movq %rbx, %rdi
callq 0x1030
jmp 0x36ed
movl $0x0, 0x4(%rbx)
movl $0x1, 0x14(%rbx)
movq 0x18(%rbx), %rdi
movl 0x10(%rbx), %edx
xorl %r12d, %r12d
xorl %esi, %esi
callq 0x10e0
jmp 0x36ed
callq 0x13be