// File: /workspace/github_c_makefile_star2_O2/mbitsnbites[P]SoftFP/./softfp_template.h
// Function: fma_sf64
F_UINT fma_sf(F_UINT a, F_UINT b, F_UINT c, RoundingModeEnum rm,
              uint32_t *pfflags)
{
    uint32_t a_sign, b_sign, c_sign, r_sign;
    int32_t a_exp, b_exp, c_exp, r_exp, shift;
    F_UINT a_mant, b_mant, c_mant, r_mant1, r_mant0, c_mant1, c_mant0, mask;

    a_sign = a >> (F_SIZE - 1);
    b_sign = b >> (F_SIZE - 1);
    c_sign = c >> (F_SIZE - 1);
    r_sign = a_sign ^ b_sign;
    a_exp = (a >> MANT_SIZE) & EXP_MASK;
    b_exp = (b >> MANT_SIZE) & EXP_MASK;
    c_exp = (c >> MANT_SIZE) & EXP_MASK;
    a_mant = a & MANT_MASK;
    b_mant = b & MANT_MASK;
    c_mant = c & MANT_MASK;
    if (a_exp == EXP_MASK || b_exp == EXP_MASK || c_exp == EXP_MASK) {
        if (isnan_sf(a) || isnan_sf(b) || isnan_sf(c)) {
            if (issignan_sf(a) || issignan_sf(b) || issignan_sf(c)) {
                *pfflags |= FFLAG_INVALID_OP;
            }
            return F_QNAN;
        } else {
            /* infinities */
            if ((a_exp == EXP_MASK && (b_exp == 0 && b_mant == 0)) ||
                (b_exp == EXP_MASK && (a_exp == 0 && a_mant == 0)) ||
                ((a_exp == EXP_MASK || b_exp == EXP_MASK) &&
                 (c_exp == EXP_MASK && r_sign != c_sign))) {
                *pfflags |= FFLAG_INVALID_OP;
                return F_QNAN;
            } else if (c_exp == EXP_MASK) {
                return pack_sf(c_sign, EXP_MASK, 0);
            } else {
                return pack_sf(r_sign, EXP_MASK, 0);
            }
        }
    }
    if (a_exp == 0) {
        if (a_mant == 0)
            goto mul_zero;
        a_mant = normalize_subnormal_sf(&a_exp, a_mant);
    } else {
        a_mant |= (F_UINT)1 << MANT_SIZE;
    }
    if (b_exp == 0) {
        if (b_mant == 0) {
        mul_zero:
            if (c_exp == 0 && c_mant == 0) {
                if (c_sign != r_sign)
                    r_sign = (rm == RM_RDN);
                return pack_sf(r_sign, 0, 0);
            } else {
                return c;
            }
        }
        b_mant = normalize_subnormal_sf(&b_exp, b_mant);
    } else {
        b_mant |= (F_UINT)1 << MANT_SIZE;
    }
    /* multiply */
    r_exp = a_exp + b_exp - (1 << (EXP_SIZE - 1)) + 3;
    
    r_mant1 = mul_u(&r_mant0, a_mant << RND_SIZE, b_mant << RND_SIZE);
    /* normalize to F_SIZE - 3 */
    if (r_mant1 < ((F_UINT)1 << (F_SIZE - 3))) {
        r_mant1 = (r_mant1 << 1) | (r_mant0 >> (F_SIZE - 1));
        r_mant0 <<= 1;
        r_exp--;
    }

    /* add */
    if (c_exp == 0) {
        if (c_mant == 0) {
            /* add zero */
            r_mant1 |= (r_mant0 != 0);
            return normalize_sf(r_sign, r_exp, r_mant1, rm, pfflags);
        }
        c_mant = normalize_subnormal_sf(&c_exp, c_mant);
    } else {
        c_mant |= (F_UINT)1 << MANT_SIZE;
    }
    c_exp++;
    c_mant1 = c_mant << (RND_SIZE - 1);
    c_mant0 = 0;

    //    printf("r_s=%d r_exp=%d r_mant=%08x %08x\n", r_sign, r_exp, (uint32_t)r_mant1, (uint32_t)r_mant0);
    //    printf("c_s=%d c_exp=%d c_mant=%08x %08x\n", c_sign, c_exp, (uint32_t)c_mant1, (uint32_t)c_mant0);

    /* ensure that abs(r) >= abs(c) */
    if (!(r_exp > c_exp || (r_exp == c_exp && r_mant1 >= c_mant1))) {
        F_UINT tmp;
        int32_t c_tmp;
        /* swap */
        tmp = r_mant1; r_mant1 = c_mant1; c_mant1 = tmp;
        tmp = r_mant0; r_mant0 = c_mant0; c_mant0 = tmp;
        c_tmp = r_exp; r_exp = c_exp; c_exp = c_tmp;
        c_tmp = r_sign; r_sign = c_sign; c_sign = c_tmp;
    }
    /* right shift c_mant */
    shift = r_exp - c_exp;
    if (shift >= 2 * F_SIZE) {
        c_mant0 = (c_mant0 | c_mant1) != 0;
        c_mant1 = 0;
    } else if (shift >= F_SIZE + 1) {
        c_mant0 = rshift_rnd(c_mant1, shift - F_SIZE);
        c_mant1 = 0;
    } else if (shift == F_SIZE) {
        c_mant0 = c_mant1 | (c_mant0 != 0);
        c_mant1 = 0;
    } else if (shift != 0) {
        mask = ((F_UINT)1 << shift) - 1;
        c_mant0 = (c_mant1 << (F_SIZE - shift)) | (c_mant0 >> shift) | ((c_mant0 & mask) != 0);
        c_mant1 = c_mant1 >> shift;
    }
    //    printf("  r_mant=%08x %08x\n", (uint32_t)r_mant1, (uint32_t)r_mant0);
    //    printf("  c_mant=%08x %08x\n", (uint32_t)c_mant1, (uint32_t)c_mant0);
    /* add or subtract */
    if (r_sign == c_sign) {
        r_mant0 += c_mant0;
        r_mant1 += c_mant1 + (r_mant0 < c_mant0);
    } else {
        F_UINT tmp;
        tmp = r_mant0;
        r_mant0 -= c_mant0;
        r_mant1 = r_mant1 - c_mant1 - (r_mant0 > tmp);
        if ((r_mant0 | r_mant1) == 0) {
            /* zero result : the sign needs a specific handling */
            r_sign = (rm == RM_RDN);
        }
    }
#if 0
    //    printf("  r1_mant=%08x %08x\n", (uint32_t)r_mant1, (uint32_t)r_mant0);
    /* normalize */
    if (r_mant1 == 0) {
        r_mant1 = r_mant0;
        r_exp -= F_SIZE;
    } else {
        shift = clz(r_mant1) - (F_SIZE - 1 - IMANT_SIZE);
        if (shift != 0) {
            r_mant1 = (r_mant1 << shift) | (r_mant0 >> (F_SIZE - shift));
            r_mant0 <<= shift;
            r_exp -= shift;
        }
        r_mant1 |= (r_mant0 != 0);
    }
    return normalize_sf(r_sign, r_exp, r_mant1, rm, pfflags);
#else
    return normalize2_sf(r_sign, r_exp, r_mant1, r_mant0, rm, pfflags);
#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %r8, 0x10(%rsp)
movl %ecx, 0x4(%rsp)
movq %rsi, %rcx
movabsq $0xfffffffffffff, %r15  # imm = 0xFFFFFFFFFFFFF
movq %rdx, %rax
shrq $0x3f, %rax
movq %rax, 0x8(%rsp)
movq %rsi, %rax
xorq %rdi, %rax
movq %rax, %r14
shrq $0x3f, %r14
movq %rdi, %r11
shrq $0x34, %r11
movl $0x7ff, %ebp            # imm = 0x7FF
andl %ebp, %r11d
shrq $0x34, %rsi
andl %ebp, %esi
movq %rdx, %r9
shrq $0x34, %r9
andl %ebp, %r9d
movq %rdi, %rbx
andq %r15, %rbx
movq %rcx, %r8
andq %r15, %r8
movq %rdx, %r10
andq %r15, %r10
cmpl %ebp, %r11d
sete %r12b
cmpl %ebp, %esi
sete %r13b
orb %r12b, %r13b
cmpl %ebp, %r9d
sete %bpl
orb %r13b, %bpl
cmpb $0x1, %bpl
jne 0x5d9e
movabsq $0x7ff0000000000000, %r15 # imm = 0x7FF0000000000000
movq %rdi, %r12
notq %r12
testq %r15, %r12
sete %bpl
testq %rbx, %rbx
setne %r12b
testb %r12b, %bpl
jne 0x5dae
movq %rcx, %r12
notq %r12
testq %r12, %r15
sete %bpl
testq %r8, %r8
setne %r12b
testb %r12b, %bpl
jne 0x5dae
movq %rdx, %r12
notq %r12
testq %r12, %r15
setne %bpl
testq %r10, %r10
sete %r12b
orb %bpl, %r12b
je 0x5dae
testq %r8, %r8
jne 0x5d41
cmpl $0x7ff, %r11d           # imm = 0x7FF
jne 0x5d41
testl %esi, %esi
je 0x5d92
cmpl $0x7ff, %esi            # imm = 0x7FF
sete %cl
testl %r11d, %r11d
sete %dil
testq %rbx, %rbx
sete %r8b
andb %dil, %r8b
testb %cl, %r8b
jne 0x5d92
movl $0x7ff, %edi            # imm = 0x7FF
cmpl %edi, %esi
sete %cl
cmpl %edi, %r11d
sete %sil
cmpl 0x8(%rsp), %r14d
je 0x6099
orb %cl, %sil
je 0x6099
cmpl $0x7ff, %r9d            # imm = 0x7FF
jne 0x6099
movabsq $0x7ff8000000000000, %rax # imm = 0x7FF8000000000000
jmp 0x5df6
pushq $0xc
popq %rdi
testl %r11d, %r11d
je 0x5e0d
addq %r15, %rbx
incq %rbx
jmp 0x5e2d
testq %rbx, %rbx
setne %sil
movabsq $0x7ff8000000000000, %rax # imm = 0x7FF8000000000000
andq %rax, %rdi
cmpq %r15, %rdi
sete %dil
testb %sil, %dil
jne 0x5df6
andq %rax, %rcx
cmpq %r15, %rcx
sete %cl
testq %r8, %r8
setne %sil
testb %sil, %cl
jne 0x5df6
andq %rax, %rdx
cmpq %r15, %rdx
setne %cl
testq %r10, %r10
sete %dl
orb %cl, %dl
jne 0x5dfe
movq 0x10(%rsp), %rcx
orb $0x10, (%rcx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %rbx, %rbx
je 0x5ee6
bsrq %rbx, %rax
xorl $0x3f, %eax
movl $0xfffffff5, %ecx       # imm = 0xFFFFFFF5
addl %eax, %ecx
movl %edi, %r11d
subl %eax, %r11d
shlq %cl, %rbx
testl %esi, %esi
je 0x5e39
addq %r15, %r8
incq %r8
jmp 0x5e57
testq %r8, %r8
je 0x5ee6
bsrq %r8, %rax
xorl $0x3f, %eax
movl $0xfffffff5, %ecx       # imm = 0xFFFFFFF5
addl %eax, %ecx
movl %edi, %esi
subl %eax, %esi
shlq %cl, %r8
shlq $0xa, %rbx
shlq $0xa, %r8
movq %r8, %rax
mulq %rbx
movq %rdx, %rcx
shrq $0x3d, %rcx
jne 0x5e81
addl %r11d, %esi
shldq $0x1, %rax, %rdx
addq %rax, %rax
addl $0xfffffc02, %esi       # imm = 0xFFFFFC02
jmp 0x5e8a
addl %r11d, %esi
addl $0xfffffc03, %esi       # imm = 0xFFFFFC03
testl %r9d, %r9d
je 0x5e97
addq %r15, %r10
incq %r10
jmp 0x5eb9
testq %r10, %r10
je 0x5ff4
bsrq %r10, %r8
xorl $0x3f, %r8d
movl $0xfffffff5, %ecx       # imm = 0xFFFFFFF5
addl %r8d, %ecx
subl %r8d, %edi
shlq %cl, %r10
movl %edi, %r9d
incl %r9d
shlq $0x9, %r10
cmpl %r9d, %esi
jle 0x5eca
movl %r9d, %edi
jmp 0x5ed3
jne 0x5f19
cmpq %r10, %rdx
jb 0x5f19
movl %esi, %edi
movq %rax, %rbx
movq %rdx, %rbp
movq %r10, %rdx
xorl %eax, %eax
movl %esi, %r15d
movl %r14d, %r12d
jmp 0x5f2b
testl %r9d, %r9d
setne %al
testq %r10, %r10
setne %cl
orb %al, %cl
movq %rdx, %rax
jne 0x5dfe
xorl %eax, %eax
cmpl $0x2, 0x4(%rsp)
sete %al
cmpl %r14d, 0x8(%rsp)
cmoveq %r14, %rax
shlq $0x3f, %rax
jmp 0x5dfe
xorl %ebx, %ebx
movl %esi, %edi
movq %r10, %rbp
movl %r9d, %r15d
movq 0x8(%rsp), %rcx
movl %ecx, %r12d
movl %r15d, %ecx
subl %edi, %ecx
cmpl $0x80, %ecx
jl 0x5f47
xorl %ecx, %ecx
orq %rdx, %rax
setne %cl
xorl %edx, %edx
movq %rcx, %rax
jmp 0x5f74
cmpl $0x41, %ecx
jl 0x5f5b
addl $-0x40, %ecx
movq %rdx, %rdi
movl %ecx, %esi
callq 0x59ff
jmp 0x5f72
cmpl $0x40, %ecx
jne 0x6068
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
movq %rdx, %rax
orq %rcx, %rax
xorl %edx, %edx
movl 0x4(%rsp), %r8d
cmpl 0x8(%rsp), %r14d
jne 0x5f88
addq %rbx, %rax
adcq %rbp, %rdx
jmp 0x5fa7
subq %rax, %rbx
sbbq %rdx, %rbp
xorl %eax, %eax
cmpl $0x2, %r8d
sete %al
movq %rbp, %rcx
orq %rbx, %rcx
cmovel %eax, %r12d
movq %rbx, %rax
movq %rbp, %rdx
testq %rdx, %rdx
je 0x5fcf
bsrq %rdx, %rdi
xorq $0x3f, %rdi
je 0x60c5
movl %edi, %esi
decl %esi
jne 0x6021
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
orq %rcx, %rdx
xorl %esi, %esi
jmp 0x6044
pushq $0x40
popq %rdi
movq %rdi, %rcx
testq %rax, %rax
je 0x5fe2
bsrq %rax, %rcx
xorq $0x3f, %rcx
testq %rcx, %rcx
je 0x601e
leal 0x3f(%rcx), %esi
decb %cl
shlq %cl, %rax
movq %rax, %rdx
jmp 0x6044
xorl %ecx, %ecx
testq %rax, %rax
setne %cl
orq %rcx, %rdx
movl %r14d, %edi
movl 0x4(%rsp), %ecx
movq 0x10(%rsp), %r8
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5a35
pushq $0x3f
popq %rsi
movl %esi, %ecx
shlq %cl, %rdx
movb $0x41, %cl
subb %dil, %cl
movq %rax, %rdi
shrq %cl, %rdi
orq %rdx, %rdi
movl %esi, %ecx
shlq %cl, %rax
xorl %edx, %edx
testq %rax, %rax
setne %dl
orq %rdi, %rdx
subl %esi, %r15d
movl %r12d, %edi
movl %r15d, %esi
movl %r8d, %ecx
movq 0x10(%rsp), %r8
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x8d34
cmpl %r9d, %esi
je 0x5f74
pushq $-0x1
popq %rsi
shlq %cl, %rsi
movq %rax, %rdi
shrdq %cl, %rdx, %rdi
notq %rsi
xorl %r8d, %r8d
testq %rsi, %rax
setne %r8b
orq %rdi, %r8
shrq %cl, %rdx
movq %r8, %rax
jmp 0x5f74
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
cmpl $0x7ff, %r9d            # imm = 0x7FF
jne 0x60ba
andq %rcx, %rdx
orq %r15, %rdx
movq %rdx, %rax
jmp 0x5dfe
andq %rcx, %rax
orq %r15, %rax
jmp 0x5dfe
leaq 0xe43a(%rip), %rdi      # 0x14506
leaq 0xe43e(%rip), %rsi      # 0x14511
leaq 0xe543(%rip), %rcx      # 0x1461d
movl $0xc9, %edx
callq 0x1080