// File: /workspace/github_c_makefile_star2_O2/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 0x1ff9
movq 0x18(%r14), %rax
cmpl $0x0, (%rax)
jne 0x1ff9
cmpw $0x0, 0x2(%r14)
je 0x20b8
movabsq $0x7ff0000000000000, %r12 # imm = 0x7FF0000000000000
movzwl 0x2(%r14), %eax
cmpl $0x1, %eax
je 0x201f
cmpl $0x2, %eax
jne 0x2029
movl $0xffffff32, %ebp       # imm = 0xFFFFFF32
movq %r13, %r12
jmp 0x21a7
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x21a7
xorl %edi, %edi
callq 0x1a14
movq %rax, %r15
movsd 0x14a3d(%rip), %xmm0    # 0x16a78
movq %rax, %rdi
callq 0x1d8d
movq %r14, %rdi
movq %r15, %rsi
callq 0x3ca6
testl %eax, %eax
js 0x2074
leaq 0x1474d(%rip), %rsi     # 0x167a6
leaq 0x14756(%rip), %rdx     # 0x167b6
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x7de8
movl $0xffffff36, %ebp       # imm = 0xFFFFFF36
jmp 0x219a
movsd 0x14a04(%rip), %xmm0    # 0x16a80
movq %r15, %rdi
callq 0x1d8d
movq %r15, %rdi
movq %r14, %rsi
callq 0x3ca6
testl %eax, %eax
js 0x20c2
leaq 0x1470c(%rip), %rsi     # 0x167a6
leaq 0x14724(%rip), %rdx     # 0x167c5
xorl %r12d, %r12d
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x7de8
movl $0xffffff35, %ebp       # imm = 0xFFFFFF35
jmp 0x219a
xorl %r12d, %r12d
xorl %ebp, %ebp
jmp 0x21a7
movl 0x14(%r14), %r12d
fldz
xorl %ebp, %ebp
cmpl $0x14, %r12d
jl 0x211b
fstp %st(0)
leal -0x13(%r12), %ebp
movq 0x18(%r14), %rdi
movl %ebp, %esi
callq 0x1c07
andl $0x1, %eax
movl %eax, 0x10(%rsp)
movq 0x18(%r14), %rdi
addl $-0x14, %r12d
movl %r12d, %esi
callq 0x1c07
pushq $0x2
popq %rdx
movl 0x10(%rsp), %edi
movl %eax, %esi
callq 0x829c
fldz
movl %eax, 0xc(%rsp)
fildl 0xc(%rsp)
fstpt 0x1c(%rsp)
movl 0x14(%r14), %r12d
jmp 0x214d
fld %st(0)
fstpt 0x1c(%rsp)
jmp 0x214d
decl %r12d
fmuls 0x14984(%rip)           # 0x16ab0
fstpt 0x10(%rsp)
movq 0x18(%r14), %rdi
movl %r12d, %esi
callq 0x1c07
movl %eax, %eax
movq %rax, 0x28(%rsp)
fildll 0x28(%rsp)
fldt 0x10(%rsp)
faddp %st, %st(1)
cmpl %ebp, %r12d
jg 0x2123
fldt 0x1c(%rsp)
faddp %st, %st(1)
addl 0x4(%r14), %ebp
jle 0x2187
leaq 0x7ffb(%rip), %rax      # 0xa160
pushq $0x8
popq %rcx
pushq $0x1
popq %rdx
testl %ebp, %ebp
jle 0x2189
movl %edx, %edi
shll %cl, %edi
movl %ebp, %esi
subl %edi, %esi
jb 0x217f
fldt (%rax)
fmulp %st, %st(1)
movl %esi, %ebp
addq $-0x10, %rax
decl %ecx
jmp 0x216b
js 0x21ca
fstpl 0x30(%rsp)
movq 0x30(%rsp), %xmm0
movq %xmm0, %r12
xorl %ebp, %ebp
testq %r15, %r15
je 0x21a7
movq %r15, %rdi
callq 0x1aeb
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
negl %ebp
leaq 0x7f8d(%rip), %rax      # 0xa160
pushq $0x8
popq %rcx
pushq $0x1
popq %rdx
testl %ebp, %ebp
jle 0x2189
movl %edx, %edi
shll %cl, %edi
movl %ebp, %esi
subl %edi, %esi
jb 0x21ed
fldt (%rax)
fdivrp %st, %st(1)
movl %esi, %ebp
addq $-0x10, %rax
decl %ecx
jmp 0x21d9
nopl (%rax)