// File: /workspace/github_c_makefile_star2_O3/cyb70289[P]tt/src/apn/decimal/mach.c
// Function: tt_dec_to_float
int tt_dec_to_float(const struct tt_dec *dec, double *num)
{
	int ret = 0;
	union {
		uint64_t i;
		double d;
	} v;
	struct tt_dec *dec_mm = NULL;

	/* Check zero */
	if (_tt_dec_is_zero(dec)) {
		v.i = 0;
		goto out;
	}

	/* Check NaN, Inf */
	if (dec->_inf_nan == TT_DEC_INF) {
		v.i = 2047ULL << 52;    /* Inf */
		ret = TT_APN_EOVERFLOW;
		goto out;
	} else if (dec->_inf_nan == TT_DEC_NAN) {
		v.i = (2047ULL << 52) | ((1ULL << 52) - 1);
		ret = TT_APN_EINVAL;
		goto out;
	}

	dec_mm = tt_dec_alloc(0);

	/* Check overflow */
	v.i = (2046ULL << 52) | ((1ULL << 52) - 1);	/* Max double */
	tt_dec_from_float(dec_mm, v.d);
	if (tt_dec_cmp_abs(dec, dec_mm) >= 0) {
		v.i = 2047ULL << 52;	/* Inf */
		ret = TT_APN_EOVERFLOW;
		tt_warn("Float overflow");
		goto out;
	}

	/* Check underflow
	 * XXX: Unnormalized double bound may cause underrun in the div loop.
	 */
#if 1
	v.i = 1;		/* Unnormalized, 4.94E-324 */
#else
	v.i = 1ULL << 52;	/* Normalized, 2.22E-308 */
#endif
	tt_dec_from_float(dec_mm, v.d);
	if (tt_dec_cmp_abs(dec_mm, dec) >= 0) {
		v.i = 0;
		ret = TT_APN_EUNDERFLOW;
		tt_warn("Float underflow");
		goto out;
	}

	/* Round to 19 significands */
	int sfr = 0, rnd = 0;
	if (dec->_msb > 19) {
		sfr = dec->_msb - 19;
		rnd = _tt_round(_tt_dec_get_dig(dec->_dig32, sfr) & 1,
					_tt_dec_get_dig(dec->_dig32, sfr-1),
					TT_ROUND_HALF_AWAY0);
	}

	/* Calculate significand */
	long double ld = 0;
	for (int i = dec->_msb - 1; i >= sfr; i--) {
		/* We can do much better here. Is it necessary? */
		ld *= 10;
		ld += _tt_dec_get_dig(dec->_dig32, i);
	}
	ld += rnd;	/* May cause overflow? */

	/* Multiply/divide exponent */
	int _exp = dec->_exp + sfr;
	int i = ARRAY_SIZE(_exp10) - 1;	/* _exp = 10^(2^i) */
	if (_exp > 0) {
		while (_exp > 0) {
			if (_exp >= 1U << i) {
				ld *= _exp10[i];
				_exp -= 1U << i;
			}
			i--;
		}
	} else if (_exp < 0) {
		_exp = -_exp;
		while (_exp > 0) {
			if (_exp >= 1U << i) {
				ld /= _exp10[i];
				_exp -= 1U << i;
			}
			i--;
		}
	}
	v.d = ld;

out:
	if (dec_mm)
		tt_dec_free(dec_mm);

	/* Check sign */
	if (dec->_sign)
		v.i |= 1ULL << 63;

	*num = v.d;
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %rbx
movq %rdi, %r14
movabsq $0x7fffffffffffffff, %r13 # imm = 0x7FFFFFFFFFFFFFFF
cmpl $0x1, 0x14(%rdi)
jne 0x29ff
movq 0x18(%r14), %rax
cmpl $0x0, (%rax)
jne 0x29ff
cmpw $0x0, 0x2(%r14)
je 0x2ac2
movabsq $0x7ff0000000000000, %r12 # imm = 0x7FF0000000000000
movzwl 0x2(%r14), %eax
cmpl $0x1, %eax
je 0x2a25
cmpl $0x2, %eax
jne 0x2a2f
movl $0xffffff32, %ebp       # imm = 0xFFFFFF32
movq %r13, %r12
jmp 0x2bef
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x2bef
xorl %edi, %edi
callq 0x23c8
movq %rax, %r15
movq 0x15047(%rip), %xmm0    # 0x17a88
movq %rax, %rdi
callq 0x27c3
movq %r14, %rdi
movq %r15, %rsi
callq 0x4773
testl %eax, %eax
js 0x2a7c
leaq 0x14d67(%rip), %rsi     # 0x177c6
leaq 0x14d70(%rip), %rdx     # 0x177d6
movl $0x1, %edi
xorl %eax, %eax
callq 0x8cca
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x2be2
movq 0x1500c(%rip), %xmm0    # 0x17a90
movq %r15, %rdi
callq 0x27c3
movq %r15, %rdi
movq %r14, %rsi
callq 0x4773
testl %eax, %eax
js 0x2acc
leaq 0x14d24(%rip), %rsi     # 0x177c6
leaq 0x14d3c(%rip), %rdx     # 0x177e5
xorl %r12d, %r12d
movl $0x1, %edi
xorl %eax, %eax
callq 0x8cca
movl $0xffffff35, %ebp       # imm = 0xFFFFFF35
jmp 0x2be2
xorl %r12d, %r12d
xorl %ebp, %ebp
jmp 0x2bef
movl 0x14(%r14), %r12d
fldz
xorl %ebp, %ebp
cmpl $0x14, %r12d
jl 0x2b27
fstp %st(0)
leal -0x13(%r12), %ebp
movq 0x18(%r14), %rdi
movl %ebp, %esi
callq 0x2607
andl $0x1, %eax
movl %eax, 0x10(%rsp)
movq 0x18(%r14), %rdi
addl $-0x14, %r12d
movl %r12d, %esi
callq 0x2607
movl 0x10(%rsp), %edi
movl %eax, %esi
movl $0x2, %edx
callq 0x90d6
fldz
movl %eax, 0xc(%rsp)
fildl 0xc(%rsp)
fstpt 0x1c(%rsp)
movl 0x14(%r14), %r12d
jmp 0x2b2d
fld %st(0)
fstpt 0x1c(%rsp)
cmpl %ebp, %r12d
jle 0x2b65
fstp %st(0)
fldz
decl %r12d
fmuls 0x14f81(%rip)           # 0x17ac0
fstpt 0x10(%rsp)
movq 0x18(%r14), %rdi
movl %r12d, %esi
callq 0x2607
movl %eax, %eax
movq %rax, 0x30(%rsp)
fildll 0x30(%rsp)
fldt 0x10(%rsp)
faddp %st, %st(1)
cmpl %ebp, %r12d
jg 0x2b36
fldt 0x1c(%rsp)
faddp %st, %st(1)
addl 0x4(%r14), %ebp
jle 0x2ba0
movl $0x8, %ecx
leaq 0x8603(%rip), %rax      # 0xb180
movl $0x1, %esi
shll %cl, %esi
movl %ebp, %edx
subl %esi, %edx
jae 0x2b8e
movl %ebp, %edx
jmp 0x2b94
fldt (%rax)
fmulp %st, %st(1)
movl %edx, %ebp
decl %ecx
addq $-0x10, %rax
testl %edx, %edx
jg 0x2b7d
jmp 0x2bd1
je 0x2bd1
negl %ebp
movl $0x8, %ecx
leaq 0x85d0(%rip), %rax      # 0xb180
movl $0x1, %esi
shll %cl, %esi
movl %ebp, %edx
subl %esi, %edx
jae 0x2bc1
movl %ebp, %edx
jmp 0x2bc7
fldt (%rax)
fdivrp %st, %st(1)
movl %edx, %ebp
decl %ecx
addq $-0x10, %rax
testl %edx, %edx
jg 0x2bb0
fstpl 0x28(%rsp)
movq 0x28(%rsp), %xmm0
movq %xmm0, %r12
xorl %ebp, %ebp
testq %r15, %r15
je 0x2bef
movq %r15, %rdi
callq 0x24a6
incq %r13
orq %r12, %r13
cmpw $0x0, (%r14)
cmoveq %r12, %r13
movq %r13, (%rbx)
movl %ebp, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop