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

	int sign1 = src1->_sign;
	int sign2 = src2->_sign;
	if (sub)
		sign2 = !sign2;

	/* 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;
		dst->_sign = (src1->_inf_nan == TT_DEC_INF ? sign1 : sign2);
		return TT_APN_EOVERFLOW;
	}
	dst->_inf_nan = 0;

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

	/* Check exponent alignment.
	 * Swap src1 and src2 if exponent of src1 is smaller, and make src1
	 * the one needs to adjust exponent(left shift signifcands).
	 */
	int exp_adj1 = src1->_exp - src2->_exp, exp_adj2 = 0;
	if (exp_adj1 < 0) {
		exp_adj1 = -exp_adj1;
		__tt_swap(src1, src2);
		__tt_swap(sign1, sign2);
	}

	/* Check rounding */
	int msb_dst = src1->_msb;
	/* Shifting "0" can't influence precision */
	if (!_tt_dec_is_zero(src1))
		msb_dst += exp_adj1;
	if (msb_dst < src2->_msb)
		msb_dst = src2->_msb;
	if (msb_dst > dst2->_prec) {
		int adj_adj = msb_dst - dst2->_prec;
		exp_adj1 -= adj_adj;
		exp_adj2 -= adj_adj;
	}
	if ((exp_adj1 < 0 && !_tt_dec_is_true_zero(src1)) ||
			(exp_adj2 < 0 && !_tt_dec_is_true_zero(src2)))
		ret = TT_APN_EROUNDED;

	/* Set result exponent, may adjust later */
	dst2->_exp = src1->_exp - exp_adj1;

	/* Use rounding guard digits to gain precision */
	int adj_adj = 0;
	if (exp_adj2 < 0) {
		int guard_adj = -exp_adj2;
		if (guard_adj > TT_DEC_PREC_RND)
			guard_adj = TT_DEC_PREC_RND;
		if (-(exp_adj2 + guard_adj) < src2->_msb) {
			exp_adj1 += guard_adj;
			exp_adj2 += guard_adj;
			adj_adj += guard_adj;
		}
	}

	/* If both operands need shift, make src1 align-9 shifting */
	if ((exp_adj1 % 9) && (exp_adj2 % 9)) {
		int align_adj = 9 - exp_adj1 % 9;
		if (align_adj > 9)	/* exp_adj may be negative */
			align_adj -= 9;
		exp_adj1 += align_adj;
		exp_adj2 += align_adj;
		adj_adj += align_adj;
	}

	/* "0" needn't shift */
	if (_tt_dec_is_zero(src1))
		exp_adj1 = 0;
	if (_tt_dec_is_zero(src2))
		exp_adj2 = 0;

	/* Copy adjusted significand of src1 to dst */
	tt_assert_fa(dst2->_prec_full > (src1->_msb + exp_adj1));
	shift_digs(dst2->_dig32, dst2->_digsz, src1->_dig32, src1->_msb, exp_adj1);

	/* Copy adjusted significand of src2 to temporary buffer */
	uint *tmpdig = malloc(dst2->_digsz);
	if (!tmpdig) {
		if (dst2 != dst)
			free(dst2);
		return TT_ENOMEM;
	}
	memset(tmpdig, 0, dst2->_digsz);
	tt_assert_fa(dst2->_prec_full > (src2->_msb + exp_adj2));
	shift_digs(tmpdig, dst2->_digsz, src2->_dig32, src2->_msb, exp_adj2);

	/* Compare sign, decide to do "+" or "-" */
	int msb;
	if (sign1 == sign2) {
		/* Adding... */
		dst2->_sign = sign1;
		/* Add aligned significands */
		msb = add_digs(dst2->_dig32, src1->_msb + exp_adj1,
				tmpdig, src2->_msb + exp_adj2);
	} else {
		/* Substracting... */
		/* Pick bigger value */
		int cmp12 = cmp_digs(dst2->_dig32, src1->_msb + exp_adj1,
				tmpdig, src2->_msb + exp_adj2);
		/* Substract aligned significands */
		if (cmp12 >= 0) {
			dst2->_sign = sign1;
			msb = sub_digs(dst2->_dig32,
					dst2->_dig32, src1->_msb + exp_adj1,
					tmpdig, src2->_msb + exp_adj2);
		} else {
			dst2->_sign = sign2;
			msb = sub_digs(dst2->_dig32,
					tmpdig, src2->_msb + exp_adj2,
					dst2->_dig32, src1->_msb + exp_adj1);
		}
	}

	/* Check rounding */
	if (adj_adj) {
		if (_tt_round(_tt_dec_get_dig(dst2->_dig32, adj_adj) & 1,
				_tt_dec_get_dig(dst2->_dig32, adj_adj-1), 0)) {
			/* Construct 10^adj_adj */
			tt_assert_fa(adj_adj < 36);
			uint one[4] = { 0, 0, 0, 0 };
			one[adj_adj / 9] = one_tbl[adj_adj % 9];
			msb = add_digs(dst2->_dig32, msb, one, adj_adj+1);
		}
	}
	/* Adjust significand, msb */
	dst2->_msb = msb - adj_adj;
	/* Only happen on substracting */
	if (dst2->_msb <= 0)
		dst2->_msb = 1;
	tt_assert_fa(dst2->_msb >= 1 && dst2->_msb <= (dst2->_prec+1));
	/* Only happen on adding */
	if (dst2->_msb > dst2->_prec) {
		adj_adj++;
		dst2->_msb--;
		dst2->_exp++;
		ret = TT_APN_EROUNDED;
	}
	shift_digs(dst2->_dig32, dst2->_digsz, dst2->_dig32, msb, -adj_adj);

	free(tmpdig);

	/* Switch buffer if dst overlap with src */
	if (dst2 != dst) {
		free(dst->_dig32);
		memcpy(dst, dst2, sizeof(struct tt_dec));
		free(dst2);
	}

	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %r15
movq %rdi, %rbx
movzwl 0x2(%rsi), %eax
movswl (%rdx), %edx
xorl %r13d, %r13d
testl %edx, %edx
sete %r13b
testl %ecx, %ecx
cmovel %edx, %r13d
cmpw $0x2, %ax
je 0x3253
movzwl 0x2(%r15), %ecx
cmpw $0x2, %cx
jne 0x326f
movw $0x2, 0x2(%rbx)
movl $0xffffff32, %ebp       # imm = 0xFFFFFF32
movl %ebp, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rsi, %r12
movzwl (%rsi), %ebp
movswl %bp, %edx
cmpw $0x1, %ax
setne %al
cmpw $0x1, %cx
setne %cl
testb %cl, %al
jne 0x32a6
movw $0x1, 0x2(%rbx)
cmpw $0x1, 0x2(%r12)
cmovel %edx, %r13d
movw %r13w, (%rbx)
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x325e
movl %edx, 0x10(%rsp)
movw $0x0, 0x2(%rbx)
cmpq %r12, %rbx
setne %al
cmpq %r15, %rbx
setne %cl
testb %cl, %al
jne 0x32d7
movl 0x8(%rbx), %edi
callq 0x244c
movq %rax, %r14
testq %rax, %rax
jne 0x32e2
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x325e
movq %rbx, %rdi
callq 0x2540
movq %rbx, %r14
movl 0x4(%r12), %r8d
subl 0x4(%r15), %r8d
js 0x32fa
movl %r13d, 0x24(%rsp)
movq %r15, %r10
movq %r12, %r15
jmp 0x330b
negl %r8d
movl 0x10(%rsp), %eax
movl %eax, 0x24(%rsp)
movl %r13d, %ebp
movq %r12, %r10
movw %bp, 0xa(%rsp)
movl 0x14(%r15), %ecx
movl %r8d, %edx
cmpl $0x1, %ecx
jne 0x3334
movq 0x18(%r15), %rax
cmpl $0x0, (%rax)
movl %r8d, %edx
jne 0x3334
xorl %edx, %edx
cmpw $0x0, 0x2(%r15)
cmovnel %r8d, %edx
addl %ecx, %edx
movl 0x14(%r10), %eax
cmpl %eax, %edx
cmovlel %eax, %edx
movl 0x8(%r14), %esi
movl %edx, %r12d
subl %esi, %r12d
negl %r12d
xorl %r11d, %r11d
subl %esi, %edx
cmovlel %r11d, %edx
cmovlel %r11d, %r12d
subl %edx, %r8d
js 0x3382
testl %r12d, %r12d
jns 0x33a5
cmpl $0x1, %eax
jne 0x339f
movq 0x18(%r10), %rdx
cmpl $0x0, (%rdx)
jne 0x339f
cmpw $0x0, 0x2(%r10)
jne 0x339f
cmpl $0x0, 0x4(%r10)
jne 0x339f
jmp 0x33a5
cmpl $0x1, %ecx
jne 0x339f
movq 0x18(%r15), %rdx
cmpl $0x0, (%rdx)
jne 0x339f
cmpw $0x0, 0x2(%r15)
jne 0x339f
cmpl $0x0, 0x4(%r15)
je 0x335e
movl $0xc9, %r11d
movl 0x4(%r15), %edx
subl %r8d, %edx
movl %edx, 0x4(%r14)
movq $0x0, 0x18(%rsp)
testl %r12d, %r12d
jns 0x33ee
movl %r12d, %edx
negl %edx
cmpl $0x9, %edx
movl $0x9, %esi
cmovll %edx, %esi
leal (%rsi,%r12), %edx
movl %edx, %edi
negl %edi
xorl %r9d, %r9d
cmpl %edi, %eax
cmovgl %esi, %r9d
cmovlel %r12d, %edx
movq %r9, 0x18(%rsp)
addl %r9d, %r8d
movl %edx, %r12d
movslq %r8d, %rdx
imulq $0x38e38e39, %rdx, %rsi # imm = 0x38E38E39
movq %rsi, %rdi
shrq $0x3f, %rdi
sarq $0x21, %rsi
addl %edi, %esi
leal (%rsi,%rsi,8), %esi
subl %esi, %edx
je 0x3448
movslq %r12d, %rsi
imulq $0x38e38e39, %rsi, %rdi # imm = 0x38E38E39
movq %rdi, %r9
shrq $0x3f, %r9
sarq $0x21, %rdi
addl %r9d, %edi
leal (%rdi,%rdi,8), %edi
subl %edi, %esi
je 0x3448
movl %edx, %esi
notl %esi
shrl $0x1f, %esi
leal (%rsi,%rsi,8), %esi
subl %edx, %esi
addl %esi, %r8d
addl %esi, %r12d
addl 0x18(%rsp), %esi
movl %esi, %edx
movq %rdx, 0x18(%rsp)
cmpl $0x1, %ecx
jne 0x3462
movq 0x18(%r15), %rdx
cmpl $0x0, (%rdx)
jne 0x3462
xorl %edx, %edx
cmpw $0x0, 0x2(%r15)
cmovel %edx, %r8d
cmpl $0x1, %eax
jne 0x347c
movq 0x18(%r10), %rax
cmpl $0x0, (%rax)
jne 0x347c
xorl %eax, %eax
cmpw $0x0, 0x2(%r10)
cmovel %eax, %r12d
movl %r11d, 0xc(%rsp)
movq %r10, 0x38(%rsp)
movq %rbx, 0x30(%rsp)
leal (%r8,%rcx), %eax
cmpl %eax, 0xc(%r14)
jle 0x36dd
movq 0x18(%r14), %rdi
movl 0x10(%r14), %esi
movq 0x18(%r15), %rdx
movq %r8, 0x28(%rsp)
callq 0x3b20
movl 0x10(%r14), %ebx
movq %rbx, %rdi
callq 0x1140
testq %rax, %rax
je 0x3535
movq %rax, %rbp
movq %rax, %rdi
xorl %esi, %esi
movq %rbx, %rdx
callq 0x10e0
movq 0x38(%rsp), %rbx
movl 0x14(%rbx), %ecx
leal (%rcx,%r12), %eax
cmpl %eax, 0xc(%r14)
jle 0x36e2
movl 0x10(%r14), %esi
movq 0x18(%rbx), %rdx
movq %rbp, %rdi
movl %r12d, %r8d
callq 0x3b20
cmpl 0x10(%rsp), %r13d
jne 0x354a
movzwl 0xa(%rsp), %eax
movw %ax, (%r14)
movq 0x18(%r14), %rdi
movq 0x28(%rsp), %rsi
addl 0x14(%r15), %esi
addl 0x14(%rbx), %r12d
movq %rbp, %rdx
movl %r12d, %ecx
callq 0x3e17
movl %eax, %r15d
movq 0x18(%rsp), %r13
movq %rbp, %rbx
jmp 0x35ba
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpq 0x30(%rsp), %r14
jne 0x36d0
jmp 0x325e
movq 0x18(%r14), %rdi
movq 0x28(%rsp), %rax
addl 0x14(%r15), %eax
movq %rax, %r15
addl 0x14(%rbx), %r12d
movq %rdi, 0x10(%rsp)
movl %r15d, %esi
movq %rbp, %rdx
movl %r12d, %ecx
callq 0x45e9
testl %eax, %eax
movq 0x18(%rsp), %r13
movq %rbp, %rbx
js 0x3599
movzwl 0xa(%rsp), %eax
movw %ax, (%r14)
movq 0x10(%rsp), %rdi
movq %rdi, %rsi
movl %r15d, %edx
movq %rbx, %rcx
movl %r12d, %r8d
jmp 0x35b2
movl 0x24(%rsp), %eax
movw %ax, (%r14)
movq 0x10(%rsp), %rcx
movq %rcx, %rdi
movq %rbx, %rsi
movl %r12d, %edx
movl %r15d, %r8d
callq 0x4644
movl %eax, %r15d
movl 0xc(%rsp), %ebp
testl %r13d, %r13d
je 0x3652
movq 0x18(%r14), %rdi
movl %r13d, %esi
callq 0x269c
movq %r14, %rcx
movl %eax, %r14d
andl $0x1, %r14d
movq %rcx, %r12
movq 0x18(%rcx), %rdi
leal -0x1(%r13), %esi
callq 0x269c
movl %r14d, %edi
movl %eax, %esi
xorl %edx, %edx
callq 0x9052
testl %eax, %eax
je 0x364f
cmpl $0x24, %r13d
jge 0x36ec
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %rdx
movaps %xmm0, (%rdx)
movl %r13d, %eax
imulq $0x38e38e39, %rax, %rax # imm = 0x38E38E39
shrq $0x21, %rax
leal (%rax,%rax,8), %ecx
movl %r13d, %esi
subl %ecx, %esi
leaq 0x7b61(%rip), %rcx      # 0xb190
movl (%rcx,%rsi,4), %ecx
movl %ecx, 0x40(%rsp,%rax,4)
movq %r12, %r14
movq 0x18(%r12), %rdi
leal 0x1(%r13), %ecx
movl %r15d, %esi
callq 0x3e17
movl %eax, %r15d
jmp 0x3652
movq %r12, %r14
movl %r15d, %ecx
subl %r13d, %ecx
cmpl $0x2, %ecx
movl $0x1, %eax
cmovgel %ecx, %eax
movl %eax, 0x14(%r14)
movl 0x8(%r14), %ecx
leal 0x1(%rcx), %edx
cmpl %edx, %eax
jg 0x36e7
cmpl %ecx, %eax
jle 0x3688
incl %r13d
decl %eax
movl %eax, 0x14(%r14)
incl 0x4(%r14)
movl $0xc9, %ebp
movq 0x18(%r14), %rdi
movl 0x10(%r14), %esi
negl %r13d
movq %rdi, %rdx
movl %r15d, %ecx
movl %r13d, %r8d
callq 0x3b20
movq %rbx, %rdi
callq 0x1030
movq 0x30(%rsp), %rbx
cmpq %rbx, %r14
je 0x325e
movq 0x18(%rbx), %rdi
callq 0x1030
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movups %xmm1, 0x10(%rbx)
movups %xmm0, (%rbx)
movq %r14, %rdi
callq 0x1030
jmp 0x325e
callq 0x1316
callq 0x1340
callq 0x1394
callq 0x136a