// File: /workspace/github_c_makefile_star2_O1/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 0x2a87
movq 0x18(%r14), %rax
cmpl $0x0, (%rax)
jne 0x2a87
cmpw $0x0, 0x2(%r14)
je 0x2b43
movabsq $0x7ff0000000000000, %rbp # imm = 0x7FF0000000000000
movzwl 0x2(%r14), %eax
movl $0xffffff36, %r12d      # imm = 0xFFFFFF36
cmpl $0x1, %eax
je 0x2b48
cmpl $0x2, %eax
jne 0x2abb
movl $0xffffff32, %r12d      # imm = 0xFFFFFF32
xorl %r15d, %r15d
movq %r13, %rbp
jmp 0x2b4b
xorl %edi, %edi
callq 0x244c
movq %rax, %r15
movq 0x14fbb(%rip), %xmm0    # 0x17a88
movq %rax, %rdi
callq 0x284b
movq %r14, %rdi
movq %r15, %rsi
callq 0x475d
testl %eax, %eax
js 0x2b00
leaq 0x14cdb(%rip), %rsi     # 0x177c6
leaq 0x14ce4(%rip), %rdx     # 0x177d6
movl $0x1, %edi
xorl %eax, %eax
callq 0x8c46
jmp 0x2b4b
movq 0x14f88(%rip), %xmm0    # 0x17a90
movq %r15, %rdi
callq 0x284b
movq %r15, %rdi
movq %r14, %rsi
callq 0x475d
testl %eax, %eax
js 0x2b7c
leaq 0x14ca0(%rip), %rsi     # 0x177c6
leaq 0x14cb8(%rip), %rdx     # 0x177e5
xorl %ebp, %ebp
movl $0x1, %edi
xorl %eax, %eax
callq 0x8c46
movl $0xffffff35, %r12d      # imm = 0xFFFFFF35
jmp 0x2b4b
xorl %r12d, %r12d
xorl %ebp, %ebp
xorl %r15d, %r15d
testq %r15, %r15
je 0x2b58
movq %r15, %rdi
callq 0x252a
incq %r13
orq %rbp, %r13
cmpw $0x0, (%r14)
cmoveq %rbp, %r13
movq %r13, (%rbx)
movl %r12d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl 0x14(%r14), %r12d
fldz
xorl %ebp, %ebp
fld %st(0)
cmpl $0x14, %r12d
jl 0x2bd1
fstp %st(1)
fstp %st(0)
leal -0x13(%r12), %ebp
movq 0x18(%r14), %rdi
movl %ebp, %esi
callq 0x269c
andl $0x1, %eax
movl %eax, 0xc(%rsp)
movq 0x18(%r14), %rdi
addl $-0x14, %r12d
movl %r12d, %esi
callq 0x269c
movl 0xc(%rsp), %edi
movl %eax, %esi
movl $0x2, %edx
callq 0x9052
fldz
movl %eax, 0x8(%rsp)
fildl 0x8(%rsp)
fstpt 0x2c(%rsp)
movl 0x14(%r14), %r12d
cmpl %ebp, %r12d
jle 0x2c11
fstp %st(0)
fldz
decl %r12d
fmuls 0x14ed5(%rip)           # 0x17ac0
fstpt 0xc(%rsp)
movq 0x18(%r14), %rdi
movl %r12d, %esi
callq 0x269c
movl %eax, %eax
movq %rax, 0x20(%rsp)
fildll 0x20(%rsp)
fldt 0xc(%rsp)
faddp %st, %st(1)
cmpl %ebp, %r12d
jg 0x2be2
fldt 0x2c(%rsp)
faddp %st, %st(1)
addl 0x4(%r14), %ebp
jle 0x2c4c
movl $0x8, %ecx
leaq 0x8557(%rip), %rax      # 0xb180
movl $0x1, %esi
shll %cl, %esi
movl %ebp, %edx
subl %esi, %edx
jae 0x2c3a
movl %ebp, %edx
jmp 0x2c40
fldt (%rax)
fmulp %st, %st(1)
movl %edx, %ebp
decl %ecx
addq $-0x10, %rax
testl %edx, %edx
jg 0x2c29
jmp 0x2c7d
je 0x2c7d
negl %ebp
movl $0x8, %ecx
leaq 0x8524(%rip), %rax      # 0xb180
movl $0x1, %esi
shll %cl, %esi
movl %ebp, %edx
subl %esi, %edx
jae 0x2c6d
movl %ebp, %edx
jmp 0x2c73
fldt (%rax)
fdivrp %st, %st(1)
movl %edx, %ebp
decl %ecx
addq $-0x10, %rax
testl %edx, %edx
jg 0x2c5c
fstpl 0x18(%rsp)
movq 0x18(%rsp), %xmm0
movq %xmm0, %rbp
xorl %r12d, %r12d
jmp 0x2b4b