// File: /workspace/github_c_makefile_star2_O3/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, %r12
movq %rdi, %rbx
movzwl 0x2(%rsi), %eax
movswl (%rdx), %edx
xorl %r15d, %r15d
testl %edx, %edx
sete %r15b
testl %ecx, %ecx
cmovel %edx, %r15d
cmpw $0x2, %ax
je 0x31a8
movzwl 0x2(%r12), %ecx
cmpw $0x2, %cx
jne 0x31c4
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, %r13
movzwl (%rsi), %ebp
movswl %bp, %edx
cmpw $0x1, %ax
setne %al
cmpw $0x1, %cx
setne %cl
testb %cl, %al
jne 0x31fa
movw $0x1, 0x2(%rbx)
cmpw $0x1, 0x2(%r13)
cmovel %edx, %r15d
movw %r15w, (%rbx)
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x31b3
movl %edx, 0xc(%rsp)
movw $0x0, 0x2(%rbx)
cmpq %r13, %rbx
setne %al
cmpq %r12, %rbx
setne %cl
testb %cl, %al
jne 0x322b
movl 0x8(%rbx), %edi
callq 0x23c8
movq %rax, %r14
testq %rax, %rax
jne 0x3236
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x31b3
movq %rbx, %rdi
callq 0x24bc
movq %rbx, %r14
movl 0x4(%r13), %r8d
subl 0x4(%r12), %r8d
js 0x324e
movl %r15d, 0x8(%rsp)
movq %r12, %r9
movq %r13, %r12
jmp 0x325f
negl %r8d
movl 0xc(%rsp), %eax
movl %eax, 0x8(%rsp)
movl %r15d, %ebp
movq %r13, %r9
movl 0x14(%r12), %ecx
cmpl $0x1, %ecx
jne 0x3277
movq 0x18(%r12), %rax
cmpl $0x0, (%rax)
je 0x3504
leal (%rcx,%r8), %edx
movl 0x14(%r9), %eax
cmpl %eax, %edx
cmovlel %eax, %edx
movl 0x8(%r14), %esi
movl %edx, %r11d
subl %esi, %r11d
negl %r11d
xorl %edi, %edi
subl %esi, %edx
cmovlel %edi, %edx
cmovlel %edi, %r11d
subl %edx, %r8d
movq %r9, 0x10(%rsp)
movw %bp, 0x6(%rsp)
js 0x32c6
testl %r11d, %r11d
js 0x3301
movl 0x4(%r12), %edx
subl %r8d, %edx
movl %edx, 0x4(%r14)
xorl %ebp, %ebp
xorl %r10d, %r10d
jmp 0x335e
cmpl $0x1, %ecx
jne 0x32e6
movq 0x18(%r12), %rdx
cmpl $0x0, (%rdx)
jne 0x32e6
cmpw $0x0, 0x2(%r12)
jne 0x32e6
cmpl $0x0, 0x4(%r12)
je 0x32ab
movl 0x4(%r12), %edx
subl %r8d, %edx
movl %edx, 0x4(%r14)
xorl %r10d, %r10d
movl $0xc9, %ebp
testl %r11d, %r11d
jns 0x335e
jmp 0x3333
cmpl $0x1, %eax
jne 0x3322
movq 0x18(%r9), %rdx
cmpl $0x0, (%rdx)
jne 0x3322
cmpw $0x0, 0x2(%r9)
jne 0x3322
cmpl $0x0, 0x4(%r9)
je 0x3690
movl $0xc9, %ebp
movl 0x4(%r12), %edx
subl %r8d, %edx
movl %edx, 0x4(%r14)
movl %r11d, %edx
negl %edx
cmpl $0x9, %edx
movl $0x9, %esi
cmovbl %edx, %esi
leal (%rsi,%r11), %edx
movl %edx, %edi
negl %edi
xorl %r10d, %r10d
cmpl %edi, %eax
cmovgl %esi, %r10d
cmovlel %r11d, %edx
addl %r10d, %r8d
movl %edx, %r11d
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 0x33b3
movslq %r11d, %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 0x33b3
movl %edx, %esi
notl %esi
shrl $0x1f, %esi
leal (%rsi,%rsi,8), %esi
subl %edx, %esi
addl %esi, %r8d
addl %esi, %r11d
addl %r10d, %esi
movl %esi, %r10d
cmpl $0x1, %ecx
jne 0x33cf
movq 0x18(%r12), %rdx
cmpl $0x0, (%rdx)
jne 0x33cf
xorl %edx, %edx
cmpw $0x0, 0x2(%r12)
cmovel %edx, %r8d
cmpl $0x1, %eax
jne 0x33ed
movq 0x10(%rsp), %rdx
movq 0x18(%rdx), %rax
cmpl $0x0, (%rax)
jne 0x33ed
xorl %eax, %eax
cmpw $0x0, 0x2(%rdx)
cmovel %eax, %r11d
movq %r11, 0x38(%rsp)
movq %r10, 0x30(%rsp)
leal (%r8,%rcx), %eax
cmpl %eax, 0xc(%r14)
jle 0x3697
movq 0x18(%r14), %rdi
movl 0x10(%r14), %esi
movq 0x18(%r12), %rdx
movq %r8, 0x28(%rsp)
callq 0x3ac9
movl 0x10(%r14), %r13d
movl $0x1, %edi
movq %r13, %rsi
callq 0x1100
testq %rax, %rax
je 0x34b0
movq %rax, %rdi
movq 0x10(%rsp), %r9
movl 0x14(%r9), %ecx
movq 0x38(%rsp), %r8
leal (%rcx,%r8), %eax
movq %r14, 0x20(%rsp)
cmpl %eax, 0xc(%r14)
jle 0x369c
movq 0x18(%r9), %rdx
movl %r13d, %esi
movq %r8, %r13
movq %rdi, 0x18(%rsp)
callq 0x3ac9
cmpl 0xc(%rsp), %r15d
jne 0x34c3
movq 0x20(%rsp), %r14
movzwl 0x6(%rsp), %eax
movw %ax, (%r14)
movq 0x18(%r14), %rdi
movq 0x28(%rsp), %rsi
addl 0x14(%r12), %esi
movq 0x10(%rsp), %rax
addl 0x14(%rax), %r13d
movq 0x18(%rsp), %rdx
movl %r13d, %ecx
callq 0x3dca
movl %eax, %r13d
movq 0x30(%rsp), %r15
jmp 0x3541
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpq %rbx, %r14
jne 0x363f
jmp 0x31b3
movq 0x20(%rsp), %r14
movq 0x18(%r14), %rdi
movq 0x10(%rsp), %rax
addl 0x14(%rax), %r13d
movq 0x28(%rsp), %r9
addl 0x14(%r12), %r9d
movq 0x30(%rsp), %r15
movq 0x18(%rsp), %rcx
jg 0x351c
testl %r13d, %r13d
jg 0x351c
movzwl 0x6(%rsp), %eax
movw %ax, (%r14)
movq %rdi, %rsi
movl %r9d, %edx
movl %r13d, %r8d
jmp 0x3539
cmpw $0x0, 0x2(%r12)
leal 0x1(%r8), %eax
movl $0x1, %edx
cmovnel %eax, %edx
jmp 0x327b
cmpl %r13d, %r9d
jge 0x364c
movl 0x8(%rsp), %eax
movw %ax, (%r14)
movq %rcx, %rsi
movl %r13d, %edx
movq %rdi, %rcx
movl %r9d, %r8d
callq 0x4667
movl %eax, %r13d
testl %r15d, %r15d
je 0x35c0
movq 0x18(%r14), %rdi
movl %r15d, %esi
callq 0x2607
movq %r14, %r12
movl %eax, %r14d
andl $0x1, %r14d
movq 0x18(%r12), %rdi
leal -0x1(%r15), %esi
callq 0x2607
movl %r14d, %edi
movl %eax, %esi
xorl %edx, %edx
callq 0x90d6
testl %eax, %eax
je 0x35bd
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %rdx
movaps %xmm0, (%rdx)
movl %r15d, %eax
imulq $0x38e38e39, %rax, %rax # imm = 0x38E38E39
shrq $0x21, %rax
leal (%rax,%rax,8), %ecx
movl %r15d, %esi
subl %ecx, %esi
leaq 0x7bee(%rip), %rcx      # 0xb190
movl (%rcx,%rsi,4), %ecx
movl %ecx, 0x40(%rsp,%rax,4)
movq 0x18(%r12), %rdi
leal 0x1(%r15), %ecx
movl %r13d, %esi
callq 0x3dca
movl %eax, %r13d
movq %r12, %r14
movl %r13d, %ecx
subl %r15d, %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 0x36a1
cmpl %ecx, %eax
jbe 0x35fa
incl %r15d
decl %eax
movl %eax, 0x14(%r14)
incl 0x4(%r14)
movl $0xc9, %ebp
movq 0x18(%r14), %rdi
movl 0x10(%r14), %esi
negl %r15d
movq %rdi, %rdx
movl %r13d, %ecx
movl %r15d, %r8d
callq 0x3ac9
movq 0x18(%rsp), %rdi
callq 0x1030
cmpq %rbx, %r14
je 0x31b3
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 0x31b3
jg 0x34f0
leal 0x8(%r9), %eax
cltq
imulq $0x38e38e39, %rax, %rax # imm = 0x38E38E39
movq %rax, %rdx
shrq $0x3f, %rdx
sarq $0x21, %rax
addl %edx, %eax
testl %eax, %eax
jle 0x34f0
movl -0x4(%rdi,%rax,4), %esi
movl -0x4(%rcx,%rax,4), %edx
cmpl %edx, %esi
ja 0x34f0
decq %rax
cmpl %edx, %esi
jae 0x366c
jmp 0x3525
xorl %ebp, %ebp
jmp 0x3327
callq 0x1316
callq 0x1340
callq 0x136a