Fixture 205

x87 long double

C · 5 functions · 4 lanes · 4 of 20 function-lanes behave identically

4 of 4 lanes have a function that returns a different result after decompilation: clang-O0 (0/5), gcc-O0 (0/5), gcc-O2 (1/5), clang-O2 (3/5).

long double is the only portable way to reach x87 from C on x86-64, and x87 is where this decompiler's unmodelled-instruction hole actually lives.

A census of the 158 x86-64 binaries in the frozen DecBench sample-set found 89,363 instructions that the lifter declines to model AND that declare no register write -- 99.997% of them x87 (fstp alone is 89,258, in 25 of the binaries), and 12 of the 158 scored target functions contain one. An instruction lifted to Op::Unknown / Op::opaque reports no definition to use_def::defs_uses, so ssa::write_regs places no phi and never bumps the destination's version: the value that was live BEFORE the instruction flows past it into every later reader. Worse, a destination nothing defines is read as an incoming argument, so the recovered prototype grows parameters the function never had.

Before this file the fixture corpus had no long double anywhere, so none of that was covered. Every function here returns an INTEGER derived from the computation, because the harness diffs executed results and a printed long double is neither portable nor exactly comparable. Every constant is an exact binary fraction, so the answers do not depend on whether the target evaluates in 80-bit (x86-64 x87), 128-bit (AArch64) or 64-bit (ARM32) precision -- only on the arithmetic being carried out at all.

tests/decompiler_fixtures/src/205_x87_long_double.c source
#include <stdint.h>

/* `long double` is the only portable way to reach x87 from C on x86-64, and
 * x87 is where this decompiler's unmodelled-instruction hole actually lives.
 *
 * A census of the 158 x86-64 binaries in the frozen DecBench sample-set found
 * 89,363 instructions that the lifter declines to model AND that declare no
 * register write -- 99.997% of them x87 (`fstp` alone is 89,258, in 25 of the
 * binaries), and 12 of the 158 scored target functions contain one. An
 * instruction lifted to `Op::Unknown` / `Op::opaque` reports no definition to
 * `use_def::defs_uses`, so `ssa::write_regs` places no phi and never bumps the
 * destination's version: the value that was live BEFORE the instruction flows
 * past it into every later reader. Worse, a destination nothing defines is
 * read as an incoming argument, so the recovered prototype grows parameters
 * the function never had.
 *
 * Before this file the fixture corpus had no `long double` anywhere, so none of
 * that was covered. Every function here returns an INTEGER derived from the
 * computation, because the harness diffs executed results and a printed
 * `long double` is neither portable nor exactly comparable. Every constant is
 * an exact binary fraction, so the answers do not depend on whether the target
 * evaluates in 80-bit (x86-64 x87), 128-bit (AArch64) or 64-bit (ARM32)
 * precision -- only on the arithmetic being carried out at all.
 */

/* A running sum in extended precision. On x86-64 this is fld/faddp/fstp; a
 * stale-value bug returns the accumulator's PREVIOUS state rather than the
 * sum. */
__attribute__((noinline)) int64_t x87_accumulate(int32_t count) {
    long double total = 0.0L;
    if (count < 0) {
        return -1;
    }
    if (count > 64) {
        count = 64;
    }
    for (int32_t i = 0; i < count; i++) {
        total += (long double)i * 0.25L;
    }
    return (int64_t)(total * 4.0L);
}

/* A product chain: fmul/fmulp, and one fdiv. Exact halves keep the result
 * representable in every long double format. */
__attribute__((noinline)) int64_t x87_product_chain(int32_t count) {
    long double product = 1.0L;
    if (count < 0 || count > 20) {
        return -1;
    }
    for (int32_t i = 0; i < count; i++) {
        product *= 1.5L;
    }
    product /= 0.5L;
    return (int64_t)(product * 1024.0L);
}

/* Comparison and sign manipulation: fcom/fucomi, fchs, fabs. The classify
 * result is a small integer so an incorrect compare is a visible diff rather
 * than a rounding difference. */
__attribute__((noinline)) int32_t x87_compare_classify(int32_t left,
                                                       int32_t right) {
    long double a = (long double)left * 0.5L;
    long double b = (long double)right * 0.25L;
    long double negated = -a;
    int32_t code = 0;
    if (a > b) {
        code |= 1;
    }
    if (a == b) {
        code |= 2;
    }
    if (negated < b) {
        code |= 4;
    }
    if (a != 0.0L && b != 0.0L) {
        code |= 8;
    }
    return code;
}

/* Width mixing: float -> long double -> double -> integer. On x86-64 this is
 * the fld/fstp traffic that dominates the census, and it is where a dropped
 * destination write turns one width's value into another's. */
__attribute__((noinline)) int64_t x87_mixed_widths(int32_t seed) {
    float narrow = (float)(seed & 0xff) * 0.5f;
    long double wide = (long double)narrow + 0.125L;
    double middle = (double)(wide * 8.0L);
    long double back = (long double)middle - 1.0L;
    return (int64_t)(back * 2.0L);
}

/* Several live extended-precision values at once. On x86-64 the x87 register
 * stack is only eight deep and the compiler spills with fstp, so this is the
 * shape that produces the most stack traffic per source line. */
__attribute__((noinline)) int64_t x87_many_live_values(int32_t seed) {
    long double a = (long double)(seed & 7) + 0.5L;
    long double b = a * 2.0L;
    long double c = b + 0.25L;
    long double d = c * a;
    long double e = d - b;
    long double f = e + c;
    long double g = f * 0.5L;
    long double h = g + d;
    return (int64_t)((a + b + c + d + e + f + g + h) * 16.0L);
}

Recovered C

Generated by glaurung decompile --style decbench at b47f6b43. baseline.json records the result after recompiling the C and calling it beside the original with seeded inputs.

clang -O0

0/5
x87_accumulate fail 38 lines
// glaurung: x87_accumulate @ 0x1100
int64_t x87_accumulate(int32_t arg0) {
    int i;
    long local_30;
    int local_34;
    short local_36;
    short local_38;
    int local_c;
    // x86-64 prologue: save rbp
    local_c = arg0;
    /* asm: x87.fldz */
    /* asm: x87.fstp */
    if ((0 <= (long)(local_c))) {
        if (((((unsigned long)((unsigned int)(local_c)) == 64) | ((long)(local_c) < 64)) == 0)) {
            local_c = 64;
        }
        for (i = 0; (i < local_c); i++) {
            local_34 = i;
            /* asm: x87.fild */
            /* asm: x87.fld */
            /* asm: x87.fld */
            /* asm: x87.fmulp */
            /* asm: x87.faddp */
            /* asm: x87.fstp */
        }
        /* asm: x87.fld */
        /* asm: x87.fld */
        /* asm: x87.fmulp */
        /* asm: x87.fnstcw */
        local_38 = ((unsigned short)(local_36) | 3072);
        /* asm: x87.fldcw */
        /* asm: x87.fistp */
        /* asm: x87.fldcw */
        return local_30;
    } else {
        return -1;
    }
}
x87_compare_classify fail 113 lines
// glaurung: x87_compare_classify @ 0x1240
int32_t x87_compare_classify(int32_t arg0, int32_t arg1) {
    extern long __unknown(long, ...);
    int code;
    long cf_0;
    long cf_2;
    long cf_4;
    long pf_0;
    long pf_1;
    long pf_2;
    long pf_3;
    long pf_4;
    long pf_5;
    long pf_6;
    int var12;
    int var3;
    int var6;
    int var9;
    long zf_0;
    long zf_2;
    long zf_4;
    long zf_6;
    // x86-64 prologue: save rbp
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fchs */
    /* asm: x87.fstp */
    code = 0;
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fxch */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    zf_2 = zf_0;
    cf_2 = cf_0;
    pf_2 = pf_0;
    if (((cf_0 | zf_0) == 0)) {
        var3 = ((unsigned int)(code) | 1);
        pf_1 = __unknown(0);
        code = var3;
        zf_2 = ((unsigned long)((unsigned int)(var3)) == 0);
        cf_2 = 0;
        pf_2 = pf_1;
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fxch */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    zf_4 = zf_2;
    cf_4 = cf_2;
    pf_4 = pf_2;
    if ((zf_2 != 0)) {
        zf_4 = zf_2;
        cf_4 = cf_2;
        pf_4 = pf_2;
        if ((pf_2 == 0)) {
            var6 = ((unsigned int)(code) | 2);
            pf_3 = __unknown(0);
            code = var6;
            zf_4 = ((unsigned long)((unsigned int)(var6)) == 0);
            cf_4 = 0;
            pf_4 = pf_3;
        }
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    zf_6 = zf_4;
    pf_6 = pf_4;
    if (((cf_4 | zf_4) == 0)) {
        var9 = ((unsigned int)(code) | 4);
        pf_5 = __unknown(0);
        code = var9;
        zf_6 = ((unsigned long)((unsigned int)(var9)) == 0);
        pf_6 = pf_5;
    }
    /* asm: x87.fld */
    /* asm: x87.fldz */
    /* asm: x87.fxch */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    if (((zf_6 == 0) || pf_6)) {
        /* asm: x87.fld */
        /* asm: x87.fldz */
        /* asm: x87.fxch */
        /* asm: x87.fucomip */
        /* asm: x87.fstp */
        if ((zf_6 == 0)) {
            var12 = ((unsigned int)(code) | 8);
            code = var12;
            // x86-64 epilogue: restore rbp
            return (unsigned int)(code);
        }
        if (pf_6) {
            var12 = ((unsigned int)(code) | 8);
            code = var12;
            // x86-64 epilogue: restore rbp
            return (unsigned int)(code);
        }
    } else {
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(code);
}
x87_many_live_values fail 64 lines
// glaurung: x87_many_live_values @ 0x13a0
int64_t x87_many_live_values(int32_t arg0) {
    long local_98;
    int local_9c;
    short local_9e;
    short local_a0;
    // x86-64 prologue: save rbp, frame 32 bytes
    local_9c = ((unsigned int)(arg0) & 7);
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fsubp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fnstcw */
    local_a0 = ((unsigned short)(local_9e) | 3072);
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    // x86-64 epilogue: restore rbp
    return local_98;
}
x87_mixed_widths fail 35 lines
// glaurung: x87_mixed_widths @ 0x1330
int64_t x87_mixed_widths(int32_t arg0) {
    extern long __unknown(long, ...);
    float narrow;
    double middle;
    long local_48;
    short local_4a;
    short local_4c;
    float var8;
    // x86-64 prologue: save rbp
    var8 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(__unknown(0)) }).value;
    narrow = var8;
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld1 */
    /* asm: x87.fchs */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fnstcw */
    local_4c = ((unsigned short)(local_4a) | 3072);
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    // x86-64 epilogue: restore rbp
    return local_48;
}
x87_product_chain fail 42 lines
// glaurung: x87_product_chain @ 0x11a0
int64_t x87_product_chain(int32_t arg0) {
    int i;
    long local_30;
    short local_32;
    short local_34;
    long local_8;
    // x86-64 prologue: save rbp
    /* asm: x87.fld1 */
    /* asm: x87.fstp */
    if (((long)(arg0) < 0)) {
        local_8 = -1;
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 20) | ((long)(arg0) < 20)) == 0)) {
        local_8 = -1;
        // x86-64 epilogue: restore rbp
        return local_8;
    }
    for (i = 0; (i < arg0); i++) {
        /* asm: x87.fld */
        /* asm: x87.fld */
        /* asm: x87.fmulp */
        /* asm: x87.fstp */
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fdivp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fnstcw */
    local_34 = ((unsigned short)(local_32) | 3072);
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    local_8 = local_30;
    // x86-64 epilogue: restore rbp
    return local_8;
}

gcc -O0

0/5
x87_accumulate fail 36 lines
// glaurung: x87_accumulate @ 0x10f9
int64_t x87_accumulate(int32_t arg0) {
    int i;
    int local_24;
    short local_26;
    short local_28;
    long local_30;
    // x86-64 prologue: save rbp
    local_24 = arg0;
    /* asm: x87.fldz */
    /* asm: x87.fstp */
    if ((0 <= (long)(local_24))) {
        if (((((unsigned long)((unsigned int)(local_24)) == 64) | ((long)(local_24) < 64)) == 0)) {
            local_24 = 64;
        }
        for (i = 0; (i < local_24); i++) {
            /* asm: x87.fild */
            /* asm: x87.fld */
            /* asm: x87.fmulp */
            /* asm: x87.fld */
            /* asm: x87.faddp */
            /* asm: x87.fstp */
        }
        /* asm: x87.fld */
        /* asm: x87.fld */
        /* asm: x87.fmulp */
        /* asm: x87.fnstcw */
        local_28 = (((unsigned short)(local_26) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_26)) >> 8) & 255) | 12) & 255) << 8));
        /* asm: x87.fldcw */
        /* asm: x87.fistp */
        /* asm: x87.fldcw */
        return local_30;
    } else {
        return -1;
    }
}
x87_compare_classify fail 123 lines
// glaurung: x87_compare_classify @ 0x11f3
int32_t x87_compare_classify(int32_t arg0, int32_t arg1) {
    extern long __unknown(long, ...);
    int code;
    long cf_0;
    long cf_2;
    long cf_4;
    long local_10;
    int local_58;
    long local_60;
    int local_8;
    long pf_0;
    long pf_1;
    long pf_2;
    long pf_3;
    long pf_4;
    long pf_5;
    long pf_6;
    long t132;
    long t134;
    long t136;
    long zf_0;
    long zf_2;
    long zf_4;
    long zf_6;
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fchs */
    /* asm: x87.fstp */
    local_10 = local_60;
    local_8 = local_58;
    code = 0;
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fcomip */
    /* asm: x87.fstp */
    zf_2 = zf_0;
    cf_2 = cf_0;
    pf_2 = pf_0;
    if (((cf_0 | zf_0) == 0)) {
        t132 = ((unsigned long)((unsigned int)(code)) | 1);
        pf_1 = __unknown(0);
        code = t132;
        zf_2 = ((unsigned long)((unsigned int)(t132)) == 0);
        cf_2 = 0;
        pf_2 = pf_1;
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    zf_4 = zf_2;
    cf_4 = cf_2;
    pf_4 = pf_2;
    if ((pf_2 == 0)) {
        /* asm: x87.fld */
        /* asm: x87.fld */
        /* asm: x87.fucomip */
        /* asm: x87.fstp */
        zf_4 = zf_2;
        cf_4 = cf_2;
        pf_4 = pf_2;
        if ((zf_2 != 0)) {
            t134 = ((unsigned long)((unsigned int)(code)) | 2);
            pf_3 = __unknown(0);
            code = t134;
            zf_4 = ((unsigned long)((unsigned int)(t134)) == 0);
            cf_4 = 0;
            pf_4 = pf_3;
        }
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fcomip */
    /* asm: x87.fstp */
    zf_6 = zf_4;
    pf_6 = pf_4;
    if (((cf_4 | zf_4) == 0)) {
        t136 = ((unsigned long)((unsigned int)(code)) | 4);
        pf_5 = __unknown(0);
        code = t136;
        zf_6 = ((unsigned long)((unsigned int)(t136)) == 0);
        pf_6 = pf_5;
    }
    /* asm: x87.fld */
    /* asm: x87.fldz */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    if ((pf_6 == 0)) {
        /* asm: x87.fld */
        /* asm: x87.fldz */
        /* asm: x87.fucomip */
        /* asm: x87.fstp */
        if (zf_6) {
            // x86-64 epilogue: restore rbp
            return (unsigned int)(code);
        }
    }
    /* asm: x87.fld */
    /* asm: x87.fldz */
    /* asm: x87.fucomip */
    /* asm: x87.fstp */
    if ((pf_6 == 0)) {
        /* asm: x87.fld */
        /* asm: x87.fldz */
        /* asm: x87.fucomip */
        /* asm: x87.fstp */
        if (zf_6) {
            // x86-64 epilogue: restore rbp
            return (unsigned int)(code);
        }
    }
    code = (code | 8);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(code);
}
x87_many_live_values fail 63 lines
// glaurung: x87_many_live_values @ 0x131d
int64_t x87_many_live_values(int32_t arg0) {
    short local_86;
    short local_88;
    int local_90;
    // x86-64 prologue: save rbp, frame 24 bytes
    local_90 = ((unsigned int)(arg0) & 7);
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fsubp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fnstcw */
    local_88 = (((unsigned short)(local_86) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_86)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    // x86-64 epilogue: restore rbp
    return (unsigned long)((unsigned int)(local_90));
}
x87_mixed_widths fail 34 lines
// glaurung: x87_mixed_widths @ 0x12ab
int64_t x87_mixed_widths(int32_t arg0) {
    extern long __unknown(long, ...);
    float narrow;
    double middle;
    short local_36;
    short local_38;
    long local_40;
    float var14;
    // x86-64 prologue: save rbp
    var14 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(__unknown(0)) }).value;
    narrow = var14;
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.faddp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld1 */
    /* asm: x87.fsubp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fnstcw */
    local_38 = (((unsigned short)(local_36) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_36)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    // x86-64 epilogue: restore rbp
    return local_40;
}
x87_product_chain fail 38 lines
// glaurung: x87_product_chain @ 0x1175
int64_t x87_product_chain(int32_t arg0) {
    int i;
    short local_26;
    short local_28;
    long local_30;
    // x86-64 prologue: save rbp
    /* asm: x87.fld1 */
    /* asm: x87.fstp */
    if (((long)(arg0) < 0)) {
        // x86-64 epilogue: restore rbp
        return -1;
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 20) | ((long)(arg0) < 20)) == 0)) {
        // x86-64 epilogue: restore rbp
        return -1;
    }
    for (i = 0; (i < arg0); i++) {
        /* asm: x87.fld */
        /* asm: x87.fld */
        /* asm: x87.fmulp */
        /* asm: x87.fstp */
    }
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fdivp */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fmulp */
    /* asm: x87.fnstcw */
    local_28 = (((unsigned short)(local_26) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_26)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    // x86-64 epilogue: restore rbp
    return local_30;
}

gcc -O2

1/5
x87_accumulate fail 36 lines
// glaurung: x87_accumulate @ 0x1100
int64_t x87_accumulate(int32_t arg0) {
    int i;
    int local_18;
    short local_a;
    short local_c;
    int var1;
    long var5;
    int var6;
    if (((long)(arg0) < 0)) {
        return -1;
    }
    var1 = ((((unsigned long)((unsigned int)(arg0)) == 64) | ((long)(arg0) < 64)) ? arg0 : 64);
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 0;
    }
    /* asm: x87.fldz */
    /* asm: x87.fld */
    var5 = 0;
    do {
        local_18 = var5;
        /* asm: x87.fild */
        var6 = (var5 + 1);
        /* asm: x87.fmul */
        /* asm: x87.faddp */
        var5 = (unsigned long)((unsigned int)(var6));
    } while (((((unsigned int)(var1) == (unsigned int)(var6)) | (var1 < var6)) == 0));
    /* asm: x87.fstp */
    /* asm: x87.fnstcw */
    /* asm: x87.fmul */
    local_c = (((unsigned short)(local_a) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_a)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return (unsigned long)((unsigned int)(local_18));
}
x87_compare_classify pass 51 lines
// glaurung: x87_compare_classify @ 0x11e0
int32_t x87_compare_classify(int32_t arg0, int32_t arg1) {
    int code;
    int local_c;
    long var11;
    double var12;
    double var13;
    long var14;
    long var17;
    double var20;
    double var21;
    double var23;
    double var3;
    double var5;
    double var8;
    double var9;
    long zf_3;
    local_c = arg0;
    var3 = ((double)((int)(local_c)) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value));
    local_c = arg1;
    var5 = ((double)((int)(local_c)) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3e800000) }).value));
    var8 = var3;
    var9 = (-var3);
    var11 = ((((var3 < var5) | ((var3 != var3) | (var5 != var5))) | ((var3 == var5) | ((var3 != var3) | (var5 != var5)))) == 0);
    zf_3 = ((var3 == var5) | ((var3 != var3) | (var5 != var5)));
    if (((var3 != var3) | (var5 != var5))) {
        var12 = var5;
        var13 = var8;
        var14 = var11;
    } else {
        if ((zf_3 == 0)) {
            var12 = var5;
            var13 = var8;
            var14 = var11;
        } else {
            var12 = var5;
            var13 = var8;
            var14 = (unsigned long)((unsigned int)((var11 | 2)));
        }
    }
    var17 = 1;
    var20 = var12;
    var21 = 0.0;
    code = (((((var12 < var9) | ((var12 != var12) | (var9 != var9))) | ((var12 == var9) | ((var12 != var12) | (var9 != var9)))) == 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var14)) | 4))) : var14);
    var23 = var21;
    if (((unsigned long)((unsigned char)((((((var21 == var13) | ((var21 != var21) | (var13 != var13))) == 0) ? 1 : (((var21 != var21) | (var13 != var13)) & 255)) & 255))) == 0)) {
        return code;
    } else {
        return (((unsigned long)((unsigned char)((((((var23 == var20) | ((var23 != var23) | (var20 != var20))) == 0) ? var17 : (((var23 != var23) | (var20 != var20)) & 255)) & 255))) != 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(code)) | 8))) : code);
    }
}
x87_many_live_values fail 42 lines
// glaurung: x87_many_live_values @ 0x12d0
int64_t x87_many_live_values(int32_t arg0) {
    int local_18;
    short local_a;
    short local_c;
    /* asm: x87.fnstcw */
    local_18 = (arg0 & 7);
    /* asm: x87.fild */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    local_c = (((unsigned short)(local_a) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_a)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fld */
    /* asm: x87.fmul */
    /* asm: x87.fld */
    /* asm: x87.fsub */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fmul */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.faddp */
    /* asm: x87.fmul */
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return (unsigned long)((unsigned int)(local_18));
}
x87_mixed_widths fail 24 lines
// glaurung: x87_mixed_widths @ 0x1270
int64_t x87_mixed_widths(int32_t arg0) {
    extern long __unknown(long, ...);
    float local_18;
    short local_a;
    short local_c;
    float var8;
    /* asm: x87.fnstcw */
    var8 = ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(__unknown(0)) }).value;
    local_c = (((unsigned short)(local_a) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_a)) >> 8) & 255) | 12) & 255) << 8));
    local_18 = var8;
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fmul */
    /* asm: x87.fstp */
    /* asm: x87.fld */
    /* asm: x87.fld1 */
    /* asm: x87.fsubp */
    /* asm: x87.fadd */
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return ((union { unsigned int bits; float value; }){ .value = local_18 }).bits;
}
x87_product_chain fail 31 lines
// glaurung: x87_product_chain @ 0x1170
int64_t x87_product_chain(int32_t arg0) {
    int i;
    long local_18;
    short local_a;
    short local_c;
    int var3;
    if (((unsigned long)(20) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
        return -1;
    }
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 2048;
    }
    /* asm: x87.fld1 */
    /* asm: x87.fld */
    i = 0;
    do {
        var3 = (i + 1);
        i = (unsigned long)((unsigned int)(var3));
        /* asm: x87.fmul */
    } while (((unsigned int)(arg0) != (unsigned int)(var3)));
    /* asm: x87.fstp */
    /* asm: x87.fnstcw */
    /* asm: x87.fadd */
    /* asm: x87.fmul */
    local_c = (((unsigned short)(local_a) & -0xff01LL) | ((((((unsigned int)((unsigned short)(local_a)) >> 8) & 255) | 12) & 255) << 8));
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return local_18;
}

clang -O2

3/5
x87_accumulate fail 81 lines
// glaurung: x87_accumulate @ 0x1100
int64_t x87_accumulate(int32_t arg0) {
    int i;
    int local_10;
    int local_14;
    int local_18;
    short local_1a;
    short local_1c;
    long local_8;
    int local_c;
    long ret;
    int var1;
    long var11;
    int var15;
    int var18;
    long var6;
    long var7;
    long var9;
    if (((long)(arg0) < 0)) {
        return -1;
    }
    var1 = (((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)(64)) ? arg0 : 64);
    ret = 0;
    if (((unsigned long)((unsigned int)(var1)) == 0)) {
        return ret;
    }
    var6 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & 3)));
    /* asm: x87.fldz */
    /* asm: x87.fldz */
    var7 = 0;
    if (((unsigned long)(3) <= (unsigned long)((unsigned long)((unsigned int)((var1 - 1)))))) {
        /* asm: x87.fstp */
        /* asm: x87.fstp */
        var9 = (unsigned long)((unsigned int)((var1 & 124)));
        var11 = 0;
        /* asm: x87.fldz */
        /* asm: x87.fld */
        /* asm: x87.fxch */
        do {
            /* asm: x87.fld */
            /* asm: x87.fld */
            /* asm: x87.fmul */
            local_c = (var11 + 1);
            /* asm: x87.fld */
            /* asm: x87.fimul */
            /* asm: x87.fxch */
            /* asm: x87.faddp */
            /* asm: x87.faddp */
            local_10 = (var11 + 2);
            /* asm: x87.fld */
            /* asm: x87.fimul */
            /* asm: x87.faddp */
            local_14 = (var11 + 3);
            /* asm: x87.fimul */
            /* asm: x87.faddp */
            /* asm: x87.fadd */
            var15 = (var11 + 4);
            var11 = (unsigned long)((unsigned int)(var15));
            var7 = (unsigned long)((unsigned int)(var15));
        } while (((unsigned int)(var9) != (unsigned int)(var15)));
    }
    /* asm: x87.fstp */
    if (((unsigned long)((unsigned int)(var6)) != 0)) {
        do {
            local_18 = var7;
            /* asm: x87.fild */
            /* asm: x87.fmul */
            /* asm: x87.faddp */
            var18 = (var6 - 1);
            var6 = (unsigned long)((unsigned int)(var18));
            var7 = (unsigned long)((unsigned int)((var7 + 1)));
        } while (((unsigned long)((unsigned int)(var18)) != 0));
    }
    /* asm: x87.fmul */
    /* asm: x87.fnstcw */
    local_1a = ((unsigned short)(local_1c) | 3072);
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return local_8;
}
x87_compare_classify pass 22 lines
// glaurung: x87_compare_classify @ 0x12a0
int32_t x87_compare_classify(int32_t arg0, int32_t arg1) {
    int code;
    long var14;
    double var17;
    long var22;
    double var25;
    int var28;
    double var6;
    double var7;
    long var9;
    var6 = ((double)((int)(arg0)) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value));
    var7 = ((double)((int)(arg1)) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3e800000) }).value));
    var9 = ((((var6 < var7) | ((var6 != var6) | (var7 != var7))) | ((var6 == var7) | ((var6 != var6) | (var7 != var7)))) == 0);
    var14 = (((var6 != var6) | (var7 != var7)) ? var9 : ((((var6 == var7) | ((var6 != var6) | (var7 != var7))) == 0) ? var9 : (unsigned long)((unsigned int)((var9 + 2)))));
    var17 = (-var6);
    code = ((((var7 < var17) | ((var7 != var7) | (var17 != var17))) | ((var7 == var17) | ((var7 != var7) | (var17 != var17)))) ? var14 : (unsigned long)((unsigned int)((var14 + 4))));
    var22 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(code)) | 8)));
    var25 = 0.0;
    var28 = (((var7 != var7) | (var25 != var25)) ? var22 : ((((var7 == var25) | ((var7 != var7) | (var25 != var25))) == 0) ? var22 : (unsigned long)((unsigned int)(code))));
    return (((var6 != var6) | (var25 != var25)) ? var28 : ((((var6 == var25) | ((var6 != var6) | (var25 != var25))) == 0) ? var28 : code));
}
x87_many_live_values fail 42 lines
// glaurung: x87_many_live_values @ 0x1370
int64_t x87_many_live_values(int32_t arg0) {
    short local_10;
    long local_8;
    int local_c;
    short local_e;
    local_c = (arg0 & 7);
    /* asm: x87.fld */
    /* asm: x87.fld */
    /* asm: x87.fiadd */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fld */
    /* asm: x87.fadd */
    /* asm: x87.fld */
    /* asm: x87.fmul */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.fsubr */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.faddp */
    /* asm: x87.fmul */
    /* asm: x87.faddp */
    /* asm: x87.fxch */
    /* asm: x87.fadd */
    /* asm: x87.fxch */
    /* asm: x87.faddp */
    /* asm: x87.faddp */
    /* asm: x87.fmul */
    /* asm: x87.fnstcw */
    local_e = ((unsigned short)(local_10) | 3072);
    /* asm: x87.fldcw */
    /* asm: x87.fistp */
    /* asm: x87.fldcw */
    return local_8;
}
x87_mixed_widths pass 23 lines
// glaurung: x87_mixed_widths @ 0x1300
int64_t x87_mixed_widths(int32_t arg0) {
    extern long __unknown(long, ...);
    double middle;
    float narrow;
    double local_10;
    float local_18;
    float local_1c;
    short local_1e;
    short local_20;
    long local_8;
    double var15;
    local_1c = ((float)((int)((unsigned int)((unsigned char)((arg0 & 255))))) * ((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3f000000) }).value);
    local_10 = (((double)(local_1c) + (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3e000000) }).value)) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x41000000) }).value));
    local_18 = (float)(local_10);
    var15 = ((-1.0) + (double)(local_18));
    local_20 = __unknown(0);
    local_1e = ((unsigned short)(local_20) | 3072);
    /* asm: x87.fldcw(...) */
    local_8 = (long long)((var15 + var15));
    /* asm: x87.fldcw(...) */
    return local_8;
}
x87_product_chain pass 57 lines
// glaurung: x87_product_chain @ 0x11e0
int64_t x87_product_chain(int32_t arg0) {
    extern long __unknown(long, ...);
    int i;
    long local_8;
    short local_a;
    short local_c;
    long ret;
    double var10;
    double var13;
    double var21;
    int var23;
    double var25;
    int var29;
    long var3;
    double var4;
    double var5;
    long var7;
    ret = -1;
    if (((unsigned long)(20) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 2048;
    }
    var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 7)));
    var4 = 1.0;
    var5 = 0.0;
    if (((unsigned long)(7) <= (unsigned long)((unsigned long)((unsigned int)((arg0 - 1)))))) {
        var7 = (unsigned long)((unsigned int)((arg0 & -8)));
        var10 = 1.0;
        do {
            var13 = (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3fc00000) }).value);
            var21 = ((((((((var10 * var13) * var13) * var13) * var13) * var13) * var13) * var13) * var13);
            var23 = (var7 - 8);
            var7 = (unsigned long)((unsigned int)(var23));
            var10 = var21;
            var4 = var21;
            var5 = var21;
        } while (((unsigned long)((unsigned int)(var23)) != 0));
    }
    if (((unsigned long)((unsigned int)(var3)) != 0)) {
        var25 = var4;
        do {
            var29 = (var3 - 1);
            var3 = (unsigned long)((unsigned int)(var29));
            var25 = (var25 * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x3fc00000) }).value));
            var5 = var25;
        } while (((unsigned long)((unsigned int)(var29)) != 0));
    }
    local_c = __unknown(0);
    local_a = ((unsigned short)(local_c) | 3072);
    /* asm: x87.fldcw(...) */
    local_8 = (long long)(((var5 + var5) * (double)(((union { unsigned int bits; float value; }){ .bits = (unsigned int)(0x44800000) }).value)));
    /* asm: x87.fldcw(...) */
    return local_8;
}

← 213 fixtures