Fixture 57

bignum

C · 2 functions · 4 lanes · 8 of 8 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

Multi-limb unsigned arithmetic over base 2^16 limbs. Carry propagation across limbs is the whole point: a lost carry or a truncated intermediate is invisible in structure but fatal in the differential.

tests/decompiler_fixtures/src/57_bignum.c source
#include <stdint.h>

/* Multi-limb unsigned arithmetic over base 2^16 limbs.  Carry propagation
 * across limbs is the whole point: a lost carry or a truncated intermediate is
 * invisible in structure but fatal in the differential. */

#define LIMB_MAX 8
#define LIMB_BASE 65536u

__attribute__((noinline)) int32_t
bignum_add(const uint32_t *left, int32_t left_limbs, const uint32_t *right,
           int32_t right_limbs, uint32_t *output, int32_t capacity) {
    uint32_t carry = 0;
    int32_t index;
    int32_t limbs;
    if (left == 0 || right == 0 || output == 0 || left_limbs < 0 ||
        right_limbs < 0 || left_limbs > LIMB_MAX || right_limbs > LIMB_MAX ||
        capacity < 1 || capacity > LIMB_MAX) {
        return -1;
    }
    limbs = (left_limbs > right_limbs) ? left_limbs : right_limbs;
    if (limbs > capacity) {
        return -2;
    }
    for (index = 0; index < limbs; ++index) {
        uint32_t a = (index < left_limbs) ? (left[index] % LIMB_BASE) : 0u;
        uint32_t b = (index < right_limbs) ? (right[index] % LIMB_BASE) : 0u;
        uint32_t sum = a + b + carry;
        output[index] = sum % LIMB_BASE;
        carry = sum / LIMB_BASE;
    }
    if (carry != 0u && limbs < capacity) {
        output[limbs] = carry;
        limbs += 1;
    }
    return limbs;
}

__attribute__((noinline)) int32_t
bignum_mul_small(const uint32_t *value, int32_t limbs, uint32_t multiplier,
                 uint32_t *output, int32_t capacity) {
    uint32_t carry = 0;
    int32_t index;
    int32_t produced;
    if (value == 0 || output == 0 || limbs < 0 || limbs > LIMB_MAX ||
        capacity < 1 || capacity > LIMB_MAX || multiplier >= LIMB_BASE) {
        return -1;
    }
    if (limbs > capacity) {
        return -2;
    }
    for (index = 0; index < limbs; ++index) {
        uint32_t product = (value[index] % LIMB_BASE) * multiplier + carry;
        output[index] = product % LIMB_BASE;
        carry = product / LIMB_BASE;
    }
    produced = limbs;
    while (carry != 0u && produced < capacity) {
        output[produced] = carry % LIMB_BASE;
        carry /= LIMB_BASE;
        produced += 1;
    }
    return produced;
}

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

2/2
bignum_add pass 82 lines
// glaurung: bignum_add @ 0x1100
int32_t bignum_add(const uint32_t * arg0, int32_t arg1, const uint32_t * arg2, int32_t arg3, uint32_t * arg4, int32_t arg5) {
    unsigned int carry;
    int limbs;
    int index;
    unsigned int a;
    unsigned int b;
    unsigned int sum;
    int local_4;
    int local_50;
    int local_54;
    int local_58;
    // x86-64 prologue: save rbp
    carry = 0;
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg2 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg4 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg3) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg3)) == 8) | ((long)(arg3) < 8)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg5) < 1)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg5)) == 8) | ((long)(arg5) < 8)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_50 = ((((unsigned int)(arg1) == (unsigned int)(arg3)) | (arg1 < arg3)) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg1)));
    limbs = local_50;
    if ((((unsigned int)(limbs) == (unsigned int)(arg5)) | (limbs < arg5))) {
        for (index = 0; (index < limbs); index++) {
            local_54 = ((arg1 <= index) ? 0 : ((unsigned long)((unsigned int)(arg0[(long)(index)])) & 0xffff));
            a = local_54;
            local_58 = ((arg3 <= index) ? 0 : ((unsigned long)((unsigned int)(arg2[(long)(index)])) & 0xffff));
            b = local_58;
            sum = ((unsigned int)((a + b)) + carry);
            arg4[(long)(index)] = (sum & 0xffff);
            carry = ((unsigned int)(sum) >> 16);
        }
        if ((carry != 0)) {
            if ((limbs < arg5)) {
                arg4[(long)(limbs)] = carry;
                limbs = ((unsigned int)(limbs) + 1);
            }
        }
        return (unsigned int)(limbs);
    } else {
        return (unsigned int)(-2);
    }
}
bignum_mul_small pass 58 lines
// glaurung: bignum_mul_small @ 0x12b0
int32_t bignum_mul_small(const uint32_t * arg0, int32_t arg1, uint32_t arg2, uint32_t * arg3, int32_t arg4) {
    unsigned int carry;
    int index;
    unsigned int product;
    int produced;
    signed char local_35;
    int local_4;
    carry = 0;
    if ((arg0 != 0)) {
        if ((arg3 != 0)) {
            if ((0 <= (long)(arg1))) {
                if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) != 0)) {
                    if ((1 <= (long)(arg4))) {
                        if (((((unsigned long)((unsigned int)(arg4)) == 8) | ((long)(arg4) < 8)) != 0)) {
                            if (((unsigned long)(arg2) < (unsigned long)(0x10000))) {
                                goto L_1324;
                            }
                        }
                    }
                }
            }
        }
    }
    local_4 = -1;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
    L_1324: ;
    if (((((unsigned int)(arg1) == (unsigned int)(arg4)) | (arg1 < arg4)) == 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    index = 0;
    L_1343: ;
    if ((index < arg1)) {
        product = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0[(long)(index)])) & 0xffff))) * arg2)) + carry);
        arg3[(long)(index)] = (product & 0xffff);
        carry = ((unsigned int)(product) >> 16);
        index = ((unsigned int)(index) + 1);
        goto L_1343;
    }
    produced = arg1;
    L_139a: ;
    local_35 = 0;
    if ((carry != 0)) {
        local_35 = (produced < arg4);
    }
    if (((unsigned long)((unsigned char)((local_35 & 1))) != 0)) {
        arg3[(long)(produced)] = (carry & 0xffff);
        carry = ((unsigned int)(carry) >> 16);
        produced = ((unsigned int)(produced) + 1);
        goto L_139a;
    }
    local_4 = produced;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}

clang -O2

2/2
bignum_add pass 90 lines
// glaurung: bignum_add @ 0x1100
int32_t bignum_add(const uint32_t * arg0, int32_t arg1, const uint32_t * arg2, int32_t arg3, uint32_t * arg4, int32_t arg5) {
    int limbs;
    int index;
    unsigned int carry;
    unsigned int b;
    unsigned int sum;
    unsigned int a;
    long local_10;
    long local_18;
    long ret;
    long var0;
    long var1;
    long var11;
    long var12;
    long var13;
    long var14;
    long var23;
    int var31;
    long var37;
    local_10 = var0;
    local_18 = var1;
    ret = 0xffffffff;
    if (((unsigned long)((unsigned long)((unsigned int)((arg5 - 9)))) < (unsigned long)(0xfffffff8))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((((unsigned long)((unsigned int)(arg3)) == 8) | ((long)(arg3) < 8)) == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((long)((int)(((unsigned long)((unsigned int)(arg3)) | arg1))) < 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg2 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if ((arg4 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    limbs = (((((unsigned int)(arg1) == (unsigned int)(arg3)) | (arg1 < arg3)) == 0) ? arg1 : (unsigned long)((unsigned int)(arg3)));
    ret = 0xfffffffe;
    if (((((unsigned int)(limbs) == (unsigned int)(arg5)) | (limbs < arg5)) == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var11 = (unsigned long)((unsigned int)(limbs));
    if (((((unsigned long)((unsigned int)(limbs)) == 0) | ((long)(limbs) < 0)) == 0)) {
        var12 = (long)(arg1);
        var13 = (long)(arg3);
        var14 = (unsigned long)((unsigned int)(limbs));
        index = 0;
        carry = 0;
        do {
            var23 = 0;
            if ((index < var12)) {
                var23 = (unsigned int)((unsigned short)(*(short *)(((long)arg0 + index * 4))));
            }
            b = 0;
            if ((index < var13)) {
                b = (unsigned int)((unsigned short)(*(short *)(((long)arg2 + index * 4))));
            }
            var31 = ((unsigned int)((var23 + carry)) + b);
            sum = (unsigned long)((unsigned int)(var31));
            *(int *)(((long)arg4 + index * 4)) = (unsigned short)(((unsigned long)((unsigned int)(var31)) & 0xffff));
            carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) >> 16)));
            var37 = ((unsigned long)((unsigned int)(index)) + 1);
            index = var37;
        } while ((var14 != var37));
        var11 = (unsigned long)((unsigned int)(limbs));
        if (((limbs < arg5) && ((unsigned long)(0x10000) <= (unsigned long)(sum)))) {
            arg4[(long)(limbs)] = 1;
            var11 = (unsigned long)((unsigned int)((limbs + 1)));
        }
    }
    ret = (unsigned long)((unsigned int)(var11));
    // x86-64 epilogue: tear down frame
    return (unsigned int)(var11);
}
bignum_mul_small pass 93 lines
// glaurung: bignum_mul_small @ 0x11e0
int32_t bignum_mul_small(const uint32_t * arg0, int32_t arg1, uint32_t arg2, uint32_t * arg3, int32_t arg4) {
    unsigned int product;
    unsigned int carry;
    int index;
    long ret;
    int var12;
    int var20;
    int var28;
    int var36;
    int var44;
    int var52;
    int var60;
    long var66;
    ret = 0xffffffff;
    if (((unsigned long)(0xffff) < (unsigned long)(arg2))) {
        return ret;
    }
    if (((unsigned long)((unsigned long)((unsigned int)((arg4 - 9)))) < (unsigned long)(0xfffffff8))) {
        return ret;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if ((arg0 == 0)) {
        return ret;
    }
    if ((arg3 == 0)) {
        return ret;
    }
    ret = 0xfffffffe;
    if (((unsigned long)((unsigned long)((unsigned int)(arg4))) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return 0;
    }
    product = (unsigned long)((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0)))) * arg2)));
    *(int *)(((long)arg3)) = (unsigned short)((product & 0xffff));
    carry = (unsigned long)((unsigned int)(((unsigned int)(product) >> 16)));
    if (((unsigned long)((unsigned int)(arg1)) != 1)) {
        var12 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x4)))) * arg2)) + carry);
        product = (unsigned long)((unsigned int)(var12));
        *(int *)(((long)arg3 + 0x4)) = (unsigned short)(((unsigned long)((unsigned int)(var12)) & 0xffff));
        carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var12)) >> 16)));
        if (((unsigned long)((unsigned int)(arg1)) != 2)) {
            var20 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x8)))) * arg2)) + carry);
            product = (unsigned long)((unsigned int)(var20));
            *(int *)(((long)arg3 + 0x8)) = (unsigned short)(((unsigned long)((unsigned int)(var20)) & 0xffff));
            carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var20)) >> 16)));
            if (((unsigned long)((unsigned int)(arg1)) != 3)) {
                var28 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0xc)))) * arg2)) + carry);
                product = (unsigned long)((unsigned int)(var28));
                *(int *)(((long)arg3 + 0xc)) = (unsigned short)(((unsigned long)((unsigned int)(var28)) & 0xffff));
                carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var28)) >> 16)));
                if (((unsigned long)((unsigned int)(arg1)) != 4)) {
                    var36 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x10)))) * arg2)) + carry);
                    product = (unsigned long)((unsigned int)(var36));
                    *(int *)(((long)arg3 + 0x10)) = (unsigned short)(((unsigned long)((unsigned int)(var36)) & 0xffff));
                    carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var36)) >> 16)));
                    if (((unsigned long)((unsigned int)(arg1)) != 5)) {
                        var44 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x14)))) * arg2)) + carry);
                        product = (unsigned long)((unsigned int)(var44));
                        *(int *)(((long)arg3 + 0x14)) = (unsigned short)(((unsigned long)((unsigned int)(var44)) & 0xffff));
                        carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) >> 16)));
                        if (((unsigned long)((unsigned int)(arg1)) != 6)) {
                            var52 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x18)))) * arg2)) + carry);
                            product = (unsigned long)((unsigned int)(var52));
                            *(int *)(((long)arg3 + 0x18)) = (unsigned short)(((unsigned long)((unsigned int)(var52)) & 0xffff));
                            carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var52)) >> 16)));
                            if (((unsigned long)((unsigned int)(arg1)) != 7)) {
                                var60 = ((unsigned int)(((unsigned int)((unsigned short)(*(short *)(((long)arg0 + 0x1c)))) * arg2)) + carry);
                                product = (unsigned long)((unsigned int)(var60));
                                *(int *)(((long)arg3 + 0x1c)) = (unsigned short)(((unsigned long)((unsigned int)(var60)) & 0xffff));
                                carry = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var60)) >> 16)));
                            }
                        }
                    }
                }
            }
        }
    }
    var66 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(0x10000) <= (unsigned long)(product))) {
        var66 = (unsigned long)((unsigned int)(arg1));
        if ((arg4 <= arg1)) {
            return (unsigned int)(var66);
        }
        arg3[(long)(arg1)] = carry;
        var66 = (unsigned long)((unsigned int)((arg1 + 1)));
    }
    return (unsigned int)(var66);
}

gcc -O0

2/2
bignum_add pass 66 lines
// glaurung: bignum_add @ 0x10f9
int32_t bignum_add(const uint32_t * arg0, int32_t arg1, const uint32_t * arg2, int32_t arg3, uint32_t * arg4, int32_t arg5) {
    unsigned int carry;
    int limbs;
    int index;
    unsigned int a;
    unsigned int b;
    unsigned int sum;
    // x86-64 prologue: save rbp
    carry = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((arg2 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((arg4 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg3) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg3)) == 8) | ((long)(arg3) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg5)) == 0) | ((long)(arg5) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg5)) == 8) | ((long)(arg5) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    limbs = ((arg1 <= arg3) ? (unsigned long)((unsigned int)(arg3)) : (unsigned long)((unsigned int)(arg1)));
    if ((((unsigned int)(limbs) == (unsigned int)(arg5)) | (limbs < arg5))) {
        for (index = 0; (index < limbs); index++) {
            a = ((arg1 <= index) ? 0 : (unsigned int)((unsigned short)(((unsigned long)((unsigned int)(arg0[(long)(index)])) & 0xffff))));
            b = ((arg3 <= index) ? 0 : (unsigned int)((unsigned short)(((unsigned long)((unsigned int)(arg2[(long)(index)])) & 0xffff))));
            sum = (carry + (unsigned int)((a + b)));
            arg4[(long)(index)] = (unsigned short)((sum & 0xffff));
            carry = ((unsigned int)(sum) >> 16);
        }
        if ((carry != 0)) {
            if ((limbs < arg5)) {
                arg4[(long)(limbs)] = carry;
                limbs = (limbs + 1);
            }
        }
        return (unsigned int)(limbs);
    } else {
        return 0xfffffffe;
    }
}
bignum_mul_small pass 56 lines
// glaurung: bignum_mul_small @ 0x1258
int32_t bignum_mul_small(const uint32_t * arg0, int32_t arg1, uint32_t arg2, uint32_t * arg3, int32_t arg4) {
    unsigned int carry;
    int index;
    unsigned int product;
    int produced;
    // x86-64 prologue: save rbp
    carry = 0;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((arg3 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 8) | ((long)(arg1) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg4)) == 0) | ((long)(arg4) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg4)) == 8) | ((long)(arg4) < 8)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((unsigned long)(0xffff) < (unsigned long)(arg2))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned int)(arg1) == (unsigned int)(arg4)) | (arg1 < arg4))) {
        for (index = 0; (index < arg1); index++) {
            product = (carry + (unsigned int)(((unsigned int)((unsigned short)(((unsigned long)((unsigned int)(arg0[(long)(index)])) & 0xffff))) * arg2)));
            arg3[(long)(index)] = (unsigned short)((product & 0xffff));
            carry = ((unsigned int)(product) >> 16);
        }
        produced = arg1;
        while ((carry != 0)) {
            if ((arg4 <= produced)) {
                break;
            }
            arg3[(long)(produced)] = (unsigned short)((carry & 0xffff));
            carry = ((unsigned int)(carry) >> 16);
            produced = (produced + 1);
        }
        return (unsigned int)(produced);
    } else {
        return 0xfffffffe;
    }
}

gcc -O2

2/2
bignum_add pass 96 lines
// glaurung: bignum_add @ 0x1100
int32_t bignum_add(const uint32_t * arg0, int32_t arg1, const uint32_t * arg2, int32_t arg3, uint32_t * arg4, int32_t arg5) {
    int limbs;
    int index;
    unsigned int carry;
    unsigned int a;
    unsigned int sum;
    long local_10;
    long var0;
    long var1;
    long var18;
    long var19;
    long var22;
    long var24;
    long var3;
    long var32;
    long var33;
    long var6;
    long var7;
    long var9;
    local_10 = var0;
    var1 = (long)arg0;
    if ((arg0 == 0)) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var6 = (long)arg2;
    if ((arg2 == 0)) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if ((arg4 == 0)) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var7 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    if (((unsigned long)(7) < (unsigned long)((unsigned long)((unsigned int)((arg5 - 1)))))) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    var9 = (unsigned long)((unsigned int)(arg3));
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg3))))) {
        var3 = 0xffffffff;
        // x86-64 epilogue: tear down frame
        return 0xffffffff;
    }
    limbs = ((arg3 <= arg1) ? arg1 : (unsigned long)((unsigned int)(arg3)));
    if ((arg5 < limbs)) {
        return 0xfffffffe;
    }
    var3 = (unsigned long)((unsigned int)(limbs));
    if (((unsigned long)((unsigned int)(limbs)) == 0)) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var3);
    }
    index = 0;
    var18 = 0;
    do {
        var19 = (unsigned long)((unsigned int)(index));
        var22 = 0;
        if (((((unsigned int)(var7) == (unsigned int)(index)) | ((long)((int)(var7)) < (long)(index))) == 0)) {
            var22 = (unsigned int)((unsigned short)(*(short *)((var1 + index * 4))));
        }
        var24 = var22;
        if (((((unsigned int)(var9) == (unsigned int)(var19)) | ((long)((int)(var9)) < (long)((int)(var19)))) == 0)) {
            var24 = (unsigned long)((unsigned int)((var22 + (unsigned int)((unsigned short)(*(short *)((var6 + index * 4)))))));
        }
        carry = (var18 + var24);
        var32 = (unsigned long)((unsigned int)(((unsigned int)(carry) >> 16)));
        *(int *)(((long)arg4 + index * 4)) = (unsigned short)((carry & 0xffff));
        var33 = ((unsigned long)((unsigned int)(index)) + 1);
        index = var33;
        var18 = var32;
    } while (((((unsigned int)(limbs) == (unsigned int)(var33)) | ((long)(limbs) < (long)((int)(var33)))) == 0));
    var3 = (unsigned long)((unsigned int)(limbs));
    if ((((unsigned int)(arg5) == (unsigned int)(limbs)) | (arg5 < limbs))) {
        // x86-64 epilogue: tear down frame
        return (unsigned int)(var3);
    }
    var3 = (unsigned long)((unsigned int)(limbs));
    if (((unsigned long)((unsigned int)((var32 & 1))) != 0)) {
        arg4[(long)(limbs)] = 1;
        var3 = (unsigned long)((unsigned int)((limbs + 1)));
    }
    // x86-64 epilogue: tear down frame
    return (unsigned int)(var3);
}
bignum_mul_small pass 57 lines
// glaurung: bignum_mul_small @ 0x11c0
int32_t bignum_mul_small(const uint32_t * arg0, int32_t arg1, uint32_t arg2, uint32_t * arg3, int32_t arg4) {
    int produced;
    int index;
    unsigned int carry;
    unsigned int product;
    long var0;
    long var1;
    long var16;
    long var18;
    int var19;
    long var7;
    var0 = (long)arg0;
    produced = (unsigned long)((unsigned int)(arg1));
    var1 = (unsigned long)(arg2);
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    if ((arg3 == 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)(7) < (unsigned long)((unsigned long)((unsigned int)((arg4 - 1)))))) {
        return 0xffffffff;
    }
    if (((unsigned long)(8) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0xffffffff;
    }
    if (((unsigned long)(0xffff) < (unsigned long)((unsigned long)(arg2)))) {
        return 0xffffffff;
    }
    if (((((unsigned int)(arg1) == (unsigned int)(arg4)) | (arg1 < arg4)) == 0)) {
        return 0xfffffffe;
    }
    index = 0;
    var7 = 0;
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        return produced;
    }
    do {
        carry = (var7 + (unsigned int)(((unsigned int)((unsigned short)(*(short *)((var0 + index * 4)))) * var1)));
        var16 = (unsigned long)((unsigned int)(((unsigned int)(carry) >> 16)));
        *(int *)(((long)arg3 + index * 4)) = (unsigned short)((carry & 0xffff));
        index = (index + 1);
        var7 = var16;
    } while (((((unsigned int)(produced) == (unsigned int)(index)) | ((long)(produced) < (long)(index))) == 0));
    if (((long)(arg4) <= (long)(produced))) {
        return produced;
    }
    if (((unsigned long)((unsigned int)(var16)) == 0)) {
        return produced;
    }
    var18 = (long)(produced);
    var19 = (produced + 1);
    produced = (unsigned long)((unsigned int)(var19));
    *(int *)(((long)arg3 + var18 * 4)) = var16;
    return (unsigned int)(var19);
}

← 213 fixtures