Fixture 190
dual role products
C · 5 functions · 4 lanes · 20 of 20 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Two logically distinct values produced by ONE machine operation.
value_split and call_result_split exist to keep such values apart. When they alias, the recovered C is still plausible and still compiles — it simply uses one value where the machine used two. A fixture that returns only one of the pair cannot see this: 02_integer_widths already covers a widening multiply, but every one of its functions consumes a single half, so a decompiler that conflated the halves would still pass it.
Division is the portable form of the shape. On x86-64 a single div writes the quotient to rax and the remainder to rdx — one instruction, two architectural outputs, both live. AArch64 spells it udiv then msub, which is the same dependency with a different shape, and it is the case the dual-role splitters were written for. Using division rather than __int128 also keeps every lane in play: the __int128 functions in 02_integer_widths force i386 and armv7 to declare the whole fixture unsupported.
Each function keeps its pair in the caller's own scratch buffer, so the differential observes the two values directly rather than inferring them from one combined result, and combines them with DISTINCT coefficients, so substituting one for the other moves the return value instead of cancelling.
dp190_quotient_only is the control: the remainder is genuinely dead there, so a decompiler must still eliminate it. Without that, this fixture would be satisfied by one that simply never eliminates anything.
#include <stdint.h>
/* Two logically distinct values produced by ONE machine operation.
*
* `value_split` and `call_result_split` exist to keep such values apart. When
* they alias, the recovered C is still plausible and still compiles — it simply
* uses one value where the machine used two. A fixture that returns only one of
* the pair cannot see this: `02_integer_widths` already covers a widening
* multiply, but every one of its functions consumes a single half, so a
* decompiler that conflated the halves would still pass it.
*
* Division is the portable form of the shape. On x86-64 a single `div` writes
* the quotient to `rax` and the remainder to `rdx` — one instruction, two
* architectural outputs, both live. AArch64 spells it `udiv` then `msub`, which
* is the same dependency with a different shape, and it is the case the
* dual-role splitters were written for. Using division rather than `__int128`
* also keeps every lane in play: the `__int128` functions in `02_integer_widths`
* force i386 and armv7 to declare the whole fixture unsupported.
*
* Each function keeps its pair in the caller's own scratch buffer, so the
* differential observes the two values directly rather than inferring them from
* one combined result, and combines them with DISTINCT coefficients, so
* substituting one for the other moves the return value instead of cancelling.
*
* `dp190_quotient_only` is the control: the remainder is genuinely dead there,
* so a decompiler must still eliminate it. Without that, this fixture would be
* satisfied by one that simply never eliminates anything. */
#define DP190_SLOT_FIRST 0
#define DP190_SLOT_SECOND 1
#define DP190_SLOT_WITNESS 2
/* One `div`: quotient and remainder are both live and play different roles. */
__attribute__((noinline)) uint32_t dp190_div_and_rem(uint32_t *scratch, uint32_t a,
uint32_t b) {
uint32_t quotient;
uint32_t remainder;
if (scratch == 0 || b == 0) {
return 0xFFFFFFFFu;
}
quotient = a / b;
remainder = a % b;
scratch[DP190_SLOT_FIRST] = quotient;
scratch[DP190_SLOT_SECOND] = remainder;
/* Distinct coefficients: aliasing the two outputs changes this, where
* `quotient + remainder` would hide a swap. */
return quotient * 3u + remainder;
}
/* Signed `idiv`. Truncation is toward zero and the remainder takes the sign of
* the dividend, so a swap is observable in the sign as well as the magnitude. */
__attribute__((noinline)) int32_t dp190_sdiv_and_rem(int32_t *scratch, int32_t a,
int32_t b) {
int32_t quotient;
int32_t remainder;
if (scratch == 0 || b == 0) {
return -1;
}
/* INT32_MIN / -1 traps on x86; the original and the recovery would both
* fault, which is not the property under test. */
if (a == (-2147483647 - 1) && b == -1) {
return -2;
}
quotient = a / b;
remainder = a % b;
scratch[DP190_SLOT_FIRST] = quotient;
scratch[DP190_SLOT_SECOND] = remainder;
return quotient * 3 + remainder;
}
/* Widening multiply with BOTH halves live. On i386 this is one `mul` writing
* `edx:eax`; elsewhere it is a wide multiply plus a shift. Either way the two
* halves are distinct values that must not collapse into one. */
__attribute__((noinline)) uint32_t dp190_mul_both_halves(uint32_t *scratch, uint32_t a,
uint32_t b) {
uint64_t product;
uint32_t low;
uint32_t high;
if (scratch == 0) {
return 0xFFFFFFFFu;
}
product = (uint64_t)a * (uint64_t)b;
low = (uint32_t)product;
high = (uint32_t)(product >> 32);
scratch[DP190_SLOT_FIRST] = low;
scratch[DP190_SLOT_SECOND] = high;
return high * 5u + low;
}
/* The pair crosses a branch, so the two values must stay distinct through a
* join rather than only within one straight-line block. */
__attribute__((noinline)) uint32_t dp190_pair_across_join(uint32_t *scratch, uint32_t a,
uint32_t b, uint32_t flag) {
uint32_t quotient;
uint32_t remainder;
uint32_t chosen;
if (scratch == 0 || b == 0) {
return 0xFFFFFFFFu;
}
quotient = a / b;
remainder = a % b;
if (flag) {
chosen = quotient * 7u + remainder;
} else {
chosen = remainder * 7u + quotient;
}
scratch[DP190_SLOT_FIRST] = quotient;
scratch[DP190_SLOT_SECOND] = remainder;
scratch[DP190_SLOT_WITNESS] = chosen;
return chosen;
}
/* CONTROL: only the quotient is used, so the remainder really is dead and must
* still be eliminated. A decompiler that keeps every architectural output alive
* to pass the functions above must not pass this one for free. */
__attribute__((noinline)) uint32_t dp190_quotient_only(uint32_t *scratch, uint32_t a,
uint32_t b) {
uint32_t quotient;
if (scratch == 0 || b == 0) {
return 0xFFFFFFFFu;
}
quotient = a / b;
scratch[DP190_SLOT_FIRST] = quotient;
return quotient * 3u;
} 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
5/5dp190_div_and_rem pass 24 lines
// glaurung: dp190_div_and_rem @ 0x1100
uint32_t dp190_div_and_rem(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
unsigned int remainder;
int local_4;
// x86-64 prologue: save rbp
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);
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) % (unsigned int)(arg2))));
*(int *)((long)arg0) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
local_4 = ((quotient * 3) + remainder);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} dp190_mul_both_halves pass 17 lines
// glaurung: dp190_mul_both_halves @ 0x1200
uint32_t dp190_mul_both_halves(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned long product;
unsigned int low;
unsigned int high;
// x86-64 prologue: save rbp
if ((arg0 != 0)) {
product = ((unsigned long)(arg1) * (unsigned long)(arg2));
low = product;
high = ((unsigned long)(product) >> 32);
*(int *)((long)arg0) = low;
*(int *)(((long)arg0 + 0x4)) = high;
return (unsigned int)(((high * 5) + low));
} else {
return (unsigned int)(-1);
}
} dp190_pair_across_join pass 27 lines
// glaurung: dp190_pair_across_join @ 0x1270
uint32_t dp190_pair_across_join(uint32_t * arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
unsigned int quotient;
unsigned int remainder;
unsigned int chosen;
int local_4;
// x86-64 prologue: save rbp
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);
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) % (unsigned int)(arg2))));
chosen = ((arg3 == 0) ? (((unsigned long)(remainder) * 7) + (unsigned long)(quotient)) : (((unsigned long)(quotient) * 7) + (unsigned long)(remainder)));
*(int *)((long)arg0) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
*(int *)(((long)arg0 + 0x8)) = chosen;
local_4 = chosen;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} dp190_quotient_only pass 21 lines
// glaurung: dp190_quotient_only @ 0x1310
uint32_t dp190_quotient_only(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
int local_4;
// x86-64 prologue: save rbp
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);
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
*(int *)((long)arg0) = quotient;
local_4 = (quotient * 3);
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} dp190_sdiv_and_rem pass 56 lines
// glaurung: dp190_sdiv_and_rem @ 0x1170
int32_t dp190_sdiv_and_rem(int32_t * arg0, int32_t arg1, int32_t arg2) {
int quotient;
int remainder;
int local_4;
long var1;
long var12;
int var13;
long var2;
long var5;
long var7;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((unsigned long)((unsigned int)(arg1)) != 0x80000000)) {
var1 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var2 = ((int)((((long long)(int)(var1) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(arg2)));
quotient = var2;
var5 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var7 = ((int)((((long long)(int)(var5) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(arg2)));
remainder = var7;
*(int *)((long)arg0) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
var12 = ((unsigned long)((unsigned int)(quotient)) * 3);
var13 = (var12 + remainder);
local_4 = var13;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((unsigned long)((unsigned int)(arg2)) != 0xffffffff)) {
var1 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var2 = ((int)((((long long)(int)(var1) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(arg2)));
quotient = var2;
var5 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var7 = ((int)((((long long)(int)(var5) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(arg2)));
remainder = var7;
*(int *)((long)arg0) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
var12 = ((unsigned long)((unsigned int)(quotient)) * 3);
var13 = (var12 + remainder);
local_4 = var13;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
local_4 = -2;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} clang -O2
5/5dp190_div_and_rem pass 19 lines
// glaurung: dp190_div_and_rem @ 0x1100
uint32_t dp190_div_and_rem(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
unsigned int remainder;
long ret;
long var0;
ret = 0xffffffff;
if ((arg0 != 0)) {
var0 = (unsigned long)(arg2);
if ((arg2 != 0)) {
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(var0))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) % (unsigned int)(var0))));
*(int *)(((long)arg0)) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((quotient + (quotient * 2)))) + remainder)));
}
}
return ret;
} dp190_mul_both_halves pass 12 lines
// glaurung: dp190_mul_both_halves @ 0x1170
uint32_t dp190_mul_both_halves(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned long product;
unsigned int high;
if ((arg0 == 0)) {
return 0xffffffff;
}
product = ((unsigned long)(arg2) * (unsigned long)(arg1));
*(long *)(((long)arg0)) = product;
high = ((unsigned long)(product) >> 32);
return (unsigned int)(((unsigned long)((unsigned int)((high + (high * 4)))) + product));
} dp190_pair_across_join pass 22 lines
// glaurung: dp190_pair_across_join @ 0x11a0
uint32_t dp190_pair_across_join(uint32_t * arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
unsigned int chosen;
unsigned int remainder;
unsigned int quotient;
long var1;
int var5;
chosen = 0xffffffff;
if ((arg0 != 0)) {
var1 = (unsigned long)(arg2);
chosen = 0xffffffff;
if ((arg2 != 0)) {
var5 = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(var1))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) % (unsigned int)(var1))));
chosen = ((arg3 != 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) * 8))) - var5))) + remainder))) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((remainder * 8))) - remainder))) + (unsigned long)((unsigned int)(var5))))));
*(int *)(((long)arg0)) = var5;
*(int *)(((long)arg0 + 0x4)) = remainder;
*(int *)(((long)arg0 + 0x8)) = chosen;
}
}
return chosen;
} dp190_quotient_only pass 17 lines
// glaurung: dp190_quotient_only @ 0x11f0
uint32_t dp190_quotient_only(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
long ret;
long var1;
ret = 0xffffffff;
if ((arg0 != 0)) {
var1 = (unsigned long)(arg2);
ret = 0xffffffff;
if ((arg2 != 0)) {
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(var1))));
*(int *)(((long)arg0)) = quotient;
ret = (unsigned long)((unsigned int)((quotient + (quotient * 2))));
}
}
return ret;
} dp190_sdiv_and_rem pass 39 lines
// glaurung: dp190_sdiv_and_rem @ 0x1130
int32_t dp190_sdiv_and_rem(int32_t * arg0, int32_t arg1, int32_t arg2) {
int quotient;
int remainder;
long ret;
long var0;
long var2;
long var5;
int var6;
ret = 0xffffffff;
if ((arg0 != 0)) {
var0 = (unsigned long)((unsigned int)(arg2));
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
return ret;
}
if (((unsigned long)((unsigned int)(arg1)) != 0x80000000)) {
var2 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
quotient = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(var0)));
remainder = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(var0)));
*(int *)(((long)arg0)) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
var5 = (unsigned long)((unsigned int)((quotient + (quotient * 2))));
var6 = (var5 + remainder);
return (unsigned int)(var6);
}
ret = 0xfffffffe;
if (((unsigned long)((unsigned int)(var0)) != 0xffffffff)) {
var2 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
quotient = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(var0)));
remainder = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(var0)));
*(int *)(((long)arg0)) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
var5 = (unsigned long)((unsigned int)((quotient + (quotient * 2))));
var6 = (var5 + remainder);
return (unsigned int)(var6);
}
}
return ret;
} gcc -O0
5/5dp190_div_and_rem pass 20 lines
// glaurung: dp190_div_and_rem @ 0x10f9
uint32_t dp190_div_and_rem(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
unsigned int remainder;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((arg2 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)(arg1)) % (unsigned int)(arg2))));
*(int *)((long)arg0) = quotient;
*(int *)((arg0 + 1)) = remainder;
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(remainder) + (unsigned long)((unsigned int)(((unsigned long)(quotient) + (unsigned long)((unsigned int)(((unsigned long)(quotient) + (unsigned long)(quotient)))))))));
} dp190_mul_both_halves pass 17 lines
// glaurung: dp190_mul_both_halves @ 0x11d7
uint32_t dp190_mul_both_halves(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned long product;
unsigned int low;
unsigned int high;
// x86-64 prologue: save rbp
if ((arg0 != 0)) {
product = ((unsigned long)(arg2) * (unsigned long)(arg1));
low = product;
high = ((unsigned long)(product) >> 32);
*(int *)((long)arg0) = low;
*(int *)((arg0 + 1)) = high;
return (unsigned int)(((unsigned long)(low) + (unsigned long)((unsigned int)(((unsigned long)(high) + (unsigned long)((unsigned int)(((unsigned long)(high) << 2))))))));
} else {
return 0xffffffff;
}
} dp190_pair_across_join pass 23 lines
// glaurung: dp190_pair_across_join @ 0x123e
uint32_t dp190_pair_across_join(uint32_t * arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
unsigned int quotient;
unsigned int remainder;
unsigned int chosen;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((arg2 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)(arg1)) % (unsigned int)(arg2))));
chosen = ((arg3 == 0) ? ((unsigned long)(quotient) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((remainder << 3))) - remainder)))) : ((unsigned long)(remainder) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((quotient << 3))) - quotient)))));
*(int *)((long)arg0) = quotient;
*(int *)((arg0 + 1)) = remainder;
*(int *)((arg0 + 2)) = chosen;
// x86-64 epilogue: restore rbp
return chosen;
} dp190_quotient_only pass 17 lines
// glaurung: dp190_quotient_only @ 0x12db
uint32_t dp190_quotient_only(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if ((arg2 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)(0) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
*(int *)((long)arg0) = quotient;
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(quotient) + (unsigned long)(quotient)))) + (unsigned long)(quotient)));
} dp190_sdiv_and_rem pass 56 lines
// glaurung: dp190_sdiv_and_rem @ 0x1161
int32_t dp190_sdiv_and_rem(int32_t * arg0, int32_t arg1, int32_t arg2) {
int quotient;
int remainder;
long var1;
long var11;
int var15;
int var17;
long var2;
int var20;
long var5;
long var7;
// x86-64 prologue: save rbp
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg1)) != 0x80000000)) {
var1 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var2 = ((int)((((long long)(int)(var1) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(arg2)));
quotient = var2;
var5 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var7 = ((int)((((long long)(int)(var5) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(arg2)));
remainder = var7;
*(int *)((long)arg0) = quotient;
var11 = (long)((arg0 + 1));
*(int *)((var11)) = remainder;
var15 = ((unsigned int)(quotient) + (unsigned int)(quotient));
var17 = ((unsigned int)(quotient) + (unsigned int)(var15));
var20 = ((unsigned int)(remainder) + (unsigned int)(var17));
// x86-64 epilogue: restore rbp
return (unsigned int)(var20);
}
if (((unsigned long)((unsigned int)(arg2)) != 0xffffffff)) {
var1 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var2 = ((int)((((long long)(int)(var1) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(arg2)));
quotient = var2;
var5 = (((unsigned long)((long)(arg1)) >> 32) & 0xffffffff);
var7 = ((int)((((long long)(int)(var5) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) % (int)(arg2)));
remainder = var7;
*(int *)((long)arg0) = quotient;
var11 = (long)((arg0 + 1));
*(int *)((var11)) = remainder;
var15 = ((unsigned int)(quotient) + (unsigned int)(quotient));
var17 = ((unsigned int)(quotient) + (unsigned int)(var15));
var20 = ((unsigned int)(remainder) + (unsigned int)(var17));
// x86-64 epilogue: restore rbp
return (unsigned int)(var20);
}
// x86-64 epilogue: restore rbp
return 0xfffffffe;
} gcc -O2
5/5dp190_div_and_rem pass 19 lines
// glaurung: dp190_div_and_rem @ 0x1100
uint32_t dp190_div_and_rem(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
unsigned int remainder;
long var0;
long var1;
var0 = (unsigned long)(arg1);
var1 = (unsigned long)(arg2);
if ((arg0 != 0)) {
if ((arg2 != 0)) {
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var0)) / (unsigned int)(var1))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var0)) % (unsigned int)(var1))));
*(int *)(((long)arg0)) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
return (unsigned int)(((unsigned long)((unsigned int)((quotient + (quotient * 2)))) + remainder));
}
}
return 0xffffffff;
} dp190_mul_both_halves pass 12 lines
// glaurung: dp190_mul_both_halves @ 0x1180
uint32_t dp190_mul_both_halves(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned long product;
long var4;
if ((arg0 == 0)) {
return 0xffffffff;
}
product = ((unsigned long)(arg1) * (unsigned long)(arg2));
*(long *)(((long)arg0)) = product;
var4 = ((unsigned long)(product) >> 32);
return (unsigned int)(((unsigned long)((unsigned int)((var4 + (var4 * 4)))) + product));
} dp190_pair_across_join pass 19 lines
// glaurung: dp190_pair_across_join @ 0x11b0
uint32_t dp190_pair_across_join(uint32_t * arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) {
unsigned int quotient;
unsigned int remainder;
unsigned int chosen;
if ((arg0 == 0)) {
return 0xffffffff;
}
if ((arg2 == 0)) {
return 0xffffffff;
}
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) / (unsigned int)(arg2))));
remainder = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(arg1)) % (unsigned int)(arg2))));
chosen = ((arg3 != 0) ? (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((quotient * 8))) - quotient))) + remainder))) : (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((quotient + (remainder * 8)))) - remainder))));
*(int *)(((long)arg0)) = quotient;
*(int *)(((long)arg0 + 0x4)) = remainder;
*(int *)(((long)arg0 + 0x8)) = chosen;
return chosen;
} dp190_quotient_only pass 16 lines
// glaurung: dp190_quotient_only @ 0x1200
uint32_t dp190_quotient_only(uint32_t * arg0, uint32_t arg1, uint32_t arg2) {
unsigned int quotient;
long var0;
long var1;
var0 = (unsigned long)(arg1);
var1 = (unsigned long)(arg2);
if ((arg0 != 0)) {
if ((arg2 != 0)) {
quotient = ((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var0)) / (unsigned int)(var1))));
*(int *)(((long)arg0)) = quotient;
return (unsigned int)((quotient + (quotient * 2)));
}
}
return 0xffffffff;
} dp190_sdiv_and_rem pass 39 lines
// glaurung: dp190_sdiv_and_rem @ 0x1130
int32_t dp190_sdiv_and_rem(int32_t * arg0, int32_t arg1, int32_t arg2) {
int quotient;
int remainder;
long var0;
long var1;
long var2;
long var5;
int var6;
var0 = (unsigned long)((unsigned int)(arg1));
var1 = (unsigned long)((unsigned int)(arg2));
if ((arg0 == 0)) {
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg2)) == 0)) {
return 0xffffffff;
}
if (((unsigned long)((unsigned int)(arg1)) != 0x80000000)) {
var2 = (((unsigned long)((long)((int)(var0))) >> 32) & 0xffffffff);
quotient = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)(var0)) / (int)(var1)));
remainder = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)(var0)) % (int)(var1)));
*(int *)(((long)arg0)) = quotient;
var5 = (unsigned long)((unsigned int)((quotient + (quotient * 2))));
*(int *)(((long)arg0 + 0x4)) = remainder;
var6 = (var5 + remainder);
return (unsigned int)(var6);
}
if (((unsigned long)((unsigned int)(arg2)) == 0xffffffff)) {
return 0xfffffffe;
}
var2 = (((unsigned long)((long)((int)(var0))) >> 32) & 0xffffffff);
quotient = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)(var0)) / (int)(var1)));
remainder = ((int)((((long long)(int)(var2) * (((long long)1) << 32)) + (unsigned int)(var0)) % (int)(var1)));
*(int *)(((long)arg0)) = quotient;
var5 = (unsigned long)((unsigned int)((quotient + (quotient * 2))));
*(int *)(((long)arg0 + 0x4)) = remainder;
var6 = (var5 + remainder);
return (unsigned int)(var6);
}