Fixture 149
mba expressions
C · 6 functions · 4 lanes · 24 of 24 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Mixed boolean-arithmetic (MBA): expressions that interleave a boolean algebra (&, |, ^, ~) with a ring (+, -, *) over the same words. Because the two structures do not distribute over each other, there is no normal form a compiler's simplifier can push everything into, and rewriting requires per-identity knowledge:
x + y == (x ^ y) + 2 * (x & y) x + y == (x | y) + (x & y) x + y == 2 * (x | y) - (x ^ y) x - y == (x ^ y) - 2 * (~x & y) x | y == (x & y) + (x ^ y) x & y == (x | y) - (x ^ y) 0 == (x ^ y) + 2 * (x & y) - (x | y) - (x & y) [zero polynomial]
Each holds for every uint32_t pair, wraparound included: they are identities over Z/2^32, derived from the fact that x + y splits into the carry-less sum x ^ y plus twice the carries x & y.
Why this breaks decompilers: MBA is the standard defence against symbolic simplification precisely because bit-blasting an MBA expression to a satisfiability query is exponential in the word size, and syntactic peephole rules cover only the handful of forms someone thought to encode. Two failures follow. A simplifier that misses the identity emits fifteen lines of masking where the program adds two numbers — technically faithful, analytically useless, and it drags a bogus "this is a bitmask/flags field" type inference along with it. A simplifier that over-matches applies a rule whose side condition it did not check: (x ^ y) + (x & y) and (x | y) + (x ^ y) look one token away from the identities above but equal neither x + y nor x | y. The zero polynomial is the sharpest case: it is an additive nonce that must fold away entirely, and a decompiler that folds it *almost* right emits confident, readable, wrong arithmetic.
Everything is unsigned, all shifts are by literal counts below 32, and the one buffer-taking function validates its length against a small bound.
#include <stdint.h>
/* Mixed boolean-arithmetic (MBA): expressions that interleave a boolean algebra
* (&, |, ^, ~) with a ring (+, -, *) over the same words. Because the two
* structures do not distribute over each other, there is no normal form a
* compiler's simplifier can push everything into, and rewriting requires
* per-identity knowledge:
*
* x + y == (x ^ y) + 2 * (x & y)
* x + y == (x | y) + (x & y)
* x + y == 2 * (x | y) - (x ^ y)
* x - y == (x ^ y) - 2 * (~x & y)
* x | y == (x & y) + (x ^ y)
* x & y == (x | y) - (x ^ y)
* 0 == (x ^ y) + 2 * (x & y) - (x | y) - (x & y) [zero polynomial]
*
* Each holds for every uint32_t pair, wraparound included: they are identities
* over Z/2^32, derived from the fact that `x + y` splits into the carry-less
* sum `x ^ y` plus twice the carries `x & y`.
*
* Why this breaks decompilers: MBA is the standard defence against symbolic
* simplification precisely because bit-blasting an MBA expression to a
* satisfiability query is exponential in the word size, and syntactic peephole
* rules cover only the handful of forms someone thought to encode. Two failures
* follow. A simplifier that misses the identity emits fifteen lines of masking
* where the program adds two numbers — technically faithful, analytically
* useless, and it drags a bogus "this is a bitmask/flags field" type inference
* along with it. A simplifier that over-matches applies a rule whose side
* condition it did not check: `(x ^ y) + (x & y)` and `(x | y) + (x ^ y)` look
* one token away from the identities above but equal neither `x + y` nor
* `x | y`. The zero polynomial is the sharpest case: it is an additive nonce
* that must fold away entirely, and a decompiler that folds it *almost* right
* emits confident, readable, wrong arithmetic.
*
* Everything is unsigned, all shifts are by literal counts below 32, and the
* one buffer-taking function validates its length against a small bound.
*/
#define MBA149_MAX_BYTES 16
static uint32_t mba149_add_xor_and(uint32_t x, uint32_t y) {
return (x ^ y) + ((x & y) << 1);
}
static uint32_t mba149_add_or_and(uint32_t x, uint32_t y) {
return (x | y) + (x & y);
}
static uint32_t mba149_add_or_xor(uint32_t x, uint32_t y) {
return ((x | y) << 1) - (x ^ y);
}
static uint32_t mba149_sub_xor_andnot(uint32_t x, uint32_t y) {
return (x ^ y) - (((~x) & y) << 1);
}
/* Identically zero for every input pair: (x + y) - (x | y) - (x & y). */
static uint32_t mba149_zero(uint32_t x, uint32_t y) {
return ((x ^ y) + ((x & y) << 1)) - (x | y) - (x & y);
}
/* Three independent encodings of the same addition, combined. `divergence` is
* zero in every execution — it is an opaque zero built out of the identities
* disagreeing with each other, which they never do. */
__attribute__((noinline)) uint32_t
mba_add_identities(uint32_t x, uint32_t y) {
uint32_t a = mba149_add_xor_and(x, y);
uint32_t b = mba149_add_or_and(x, y);
uint32_t c = mba149_add_or_xor(x, y);
uint32_t divergence = (a ^ b) | (b ^ c);
return (a + (c ^ 0x9E3779B9u)) ^ divergence;
}
/* Subtraction via the carry-borrow identity, then re-added through a different
* identity: the round trip must recover `x`. */
__attribute__((noinline)) uint32_t
mba_sub_identity(uint32_t x, uint32_t y) {
uint32_t difference = mba149_sub_xor_andnot(x, y);
return mba149_add_or_and(difference, y) ^ difference;
}
/* An MBA zero polynomial used as an additive nonce around a real computation.
* Correct output is `x * y + (x ^ y)`; anything else means the nonce did not
* fold to zero. */
__attribute__((noinline)) uint32_t
mba_zero_polynomial(uint32_t x, uint32_t y) {
uint32_t nonce = mba149_zero(x, y);
uint32_t nonce2 = mba149_zero(y, x ^ 0xFFFFu);
return (x * y) + (x ^ y) + nonce + (nonce2 << 3);
}
/* Branchless select written in MBA form. `flag`'s low bit picks a value; the
* mask is built by negation and the blend by xor-and-xor, so no comparison and
* no branch appear in the source at all. */
__attribute__((noinline)) uint32_t
mba_select(uint32_t x, uint32_t y, uint32_t flag) {
uint32_t mask = 0u - (flag & 1u);
uint32_t blended = x ^ ((x ^ y) & mask);
return mba149_add_xor_and(blended, mba149_zero(x, y));
}
/* Bit-count by the classic SWAR reduction, but with every add replaced by an
* MBA encoding. The closed form is popcount; a decompiler that recovers the
* masks but mangles one adder returns a plausible near-popcount. */
__attribute__((noinline)) uint32_t
mba_bit_population(uint32_t value) {
uint32_t v = value - ((value >> 1) & 0x55555555u);
v = mba149_add_or_and(v & 0x33333333u, (v >> 2) & 0x33333333u);
v = mba149_add_xor_and(v, v >> 4) & 0x0F0F0F0Fu;
return (v * 0x01010101u) >> 24;
}
/* An MBA-mixed rolling hash over a caller-owned byte buffer. Each round uses a
* different identity so no single peephole rule cleans the loop up. */
__attribute__((noinline)) uint32_t
mba_mix_buffer(uint8_t *data, int32_t length, uint32_t seed) {
int32_t index;
uint32_t acc = seed;
if (data == 0 || length < 0 || length > MBA149_MAX_BYTES) {
return 0u;
}
for (index = 0; index < length; ++index) {
uint32_t byte = (uint32_t)data[index];
acc = mba149_add_xor_and(acc, byte);
acc = mba149_add_or_xor(acc << 3, acc >> 7);
acc = mba149_sub_xor_andnot(acc, mba149_zero(acc, byte));
}
return mba149_add_or_and(acc, (uint32_t)length);
} 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
6/6mba_add_identities pass 23 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int divergence;
unsigned int var0;
unsigned int var2;
unsigned int var4;
// x86-64 prologue: save rbp, frame 32 bytes
var0 = mba149_add_xor_and(arg0, arg1);
a = var0;
var2 = mba149_add_or_and(arg0, arg1);
b = var2;
var4 = mba149_add_or_xor(arg0, arg1);
c = var4;
divergence = ((unsigned int)((a ^ b)) | (unsigned int)((b ^ c)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(a) + (unsigned long)((unsigned int)(((unsigned long)(c) ^ -0x61c88647LL)))))) ^ divergence));
} mba_bit_population pass 16 lines
// glaurung: mba_bit_population @ 0x12e0
uint32_t mba_bit_population(uint32_t arg0) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
unsigned int v;
unsigned int var16;
unsigned int var21;
// x86-64 prologue: save rbp, frame 16 bytes
v = (arg0 - (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)));
var16 = mba149_add_or_and((unsigned long)((unsigned int)((v & 0x33333333))), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(v) >> 2))) & 0x33333333))));
v = var16;
var21 = mba149_add_xor_and(v, (unsigned long)((unsigned int)(((unsigned int)(v) >> 4))));
v = (var21 & 0xf0f0f0f);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)((v * 0x1010101))) >> 24));
} mba_mix_buffer pass 47 lines
// glaurung: mba_mix_buffer @ 0x1350
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int acc;
int index;
unsigned int byte;
int local_28;
int local_4;
unsigned int var14;
unsigned int var17;
unsigned int var19;
unsigned int var24;
unsigned int var7;
// x86-64 prologue: save rbp, frame 48 bytes
acc = arg2;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
for (index = 0; (index < arg1); index++) {
byte = (unsigned char)(arg0[index]);
var7 = mba149_add_xor_and(acc, byte);
acc = var7;
var14 = mba149_add_or_xor((unsigned long)((unsigned int)((acc << 3))), (unsigned long)((unsigned int)(((unsigned int)(acc) >> 7))));
acc = var14;
local_28 = acc;
var17 = mba149_zero(acc, byte);
var19 = mba149_sub_xor_andnot((unsigned long)((unsigned int)(local_28)), var17);
acc = var19;
}
var24 = mba149_add_or_and(acc, (unsigned long)((unsigned int)(arg1)));
local_4 = var24;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} mba_select pass 18 lines
// glaurung: mba_select @ 0x1290
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int mask;
unsigned int blended;
int local_18;
unsigned int ret;
unsigned int var16;
// x86-64 prologue: save rbp, frame 32 bytes
mask = (0 - (unsigned int)((arg2 & 1)));
blended = (arg0 ^ (unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) & mask)));
local_18 = blended;
var16 = mba149_zero(arg0, arg1);
ret = mba149_add_xor_and((unsigned long)((unsigned int)(local_18)), var16);
// x86-64 epilogue: restore rbp
return ret;
} mba_sub_identity pass 14 lines
// glaurung: mba_sub_identity @ 0x11c0
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
unsigned int difference;
unsigned int var0;
unsigned int var2;
// x86-64 prologue: save rbp, frame 16 bytes
var0 = mba149_sub_xor_andnot(arg0, arg1);
difference = var0;
var2 = mba149_add_or_and(difference, arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)((var2 ^ difference));
} mba_zero_polynomial pass 15 lines
// glaurung: mba_zero_polynomial @ 0x1210
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int nonce;
unsigned int nonce2;
unsigned int var0;
unsigned int var4;
// x86-64 prologue: save rbp, frame 16 bytes
var0 = mba149_zero(arg0, arg1);
nonce = var0;
var4 = mba149_zero(arg1, (unsigned long)((unsigned int)((arg0 ^ 0xffff))));
nonce2 = var4;
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + (unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1)))))) + nonce))) + (unsigned long)((unsigned int)(((unsigned long)(nonce2) << 3)))));
} clang -O2
6/6mba_add_identities pass 17 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int divergence;
long var12;
long var2;
long var7;
long var9;
var2 = (unsigned long)((unsigned int)((arg1 ^ arg0)));
a = (unsigned long)((unsigned int)((var2 + ((unsigned long)((unsigned int)((arg1 & arg0))) * 2))));
var7 = (unsigned long)((unsigned int)((arg1 + arg0)));
var9 = (unsigned long)((unsigned int)((arg1 | arg0)));
var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var9 + var9))) - var2)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var12 ^ -0x61c88647LL))) + a))) ^ (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var7 ^ var12))) | (unsigned long)((unsigned int)(((unsigned long)(a) ^ var7))))))));
} mba_bit_population pass 11 lines
// glaurung: mba_bit_population @ 0x11b0
uint32_t mba_bit_population(uint32_t arg0) {
unsigned int v;
int var16;
long var21;
long var7;
var7 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
var16 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) >> 2))) & 0x33333333)) + (unsigned int)(((unsigned long)((unsigned int)(var7)) & 0x33333333)));
var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 4)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) ^ (unsigned long)((unsigned int)(var16))))) + ((unsigned long)((unsigned int)((var21 & (unsigned long)((unsigned int)(var16))))) * 2)))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
} mba_mix_buffer pass 43 lines
// glaurung: mba_mix_buffer @ 0x11f0
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
int index;
unsigned int byte;
unsigned int acc;
long ret;
long var1;
long var13;
long var14;
long var17;
long var20;
long var37;
long var43;
long var47;
long var6;
ret = 0;
if ((arg0 == 0)) {
return ret;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return ret;
}
var1 = (unsigned long)(arg2);
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
index = 0;
var6 = (unsigned long)(arg2);
while (((unsigned long)((unsigned int)(arg1)) != index)) {
byte = (unsigned int)((unsigned char)(*(char *)(((long)arg0 + index))));
var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var6)) ^ byte))) + ((unsigned long)((unsigned int)((var6 & byte))) * 2))));
var14 = (unsigned long)((unsigned int)((var13 * 8)));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var13)) >> 7)));
var20 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) | var14)));
acc = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var20 + var20))) - (unsigned long)((unsigned int)((var17 ^ var14))))));
var37 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((acc ^ byte))) - (unsigned long)((unsigned int)((byte + acc)))))) + ((unsigned long)((unsigned int)((acc & byte))) * 2))));
var43 = (unsigned long)((unsigned int)(((~acc) & var37)));
var47 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var37)) ^ acc))) - (unsigned long)((unsigned int)((var43 + var43))))));
index = (index + 1);
var6 = var47;
var1 = var47;
}
}
return (unsigned int)((var1 + arg1));
} mba_select pass 12 lines
// glaurung: mba_select @ 0x1180
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
unsigned int blended;
unsigned int mask;
long var17;
long var5;
long var9;
var5 = (unsigned long)((unsigned int)((arg1 ^ arg0)));
var9 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((-(unsigned long)((unsigned int)((arg2 & 1)))) & var5))) ^ arg0)));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var5 - (unsigned long)((unsigned int)((arg1 + arg0)))))) + ((unsigned long)((unsigned int)((arg1 & arg0))) * 2))));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) ^ var17))) + ((unsigned long)((unsigned int)((var9 & var17))) * 2)));
} mba_sub_identity pass 8 lines
// glaurung: mba_sub_identity @ 0x1130
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
unsigned int difference;
long var5;
var5 = (unsigned long)((unsigned int)(((~arg0) & arg1)));
difference = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 ^ arg0))) - (unsigned long)((unsigned int)((var5 + var5))))));
return (unsigned int)(((unsigned long)((unsigned int)((arg1 + difference))) ^ difference));
} mba_zero_polynomial pass 7 lines
// glaurung: mba_zero_polynomial @ 0x1150
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
unsigned int nonce2;
long var2;
var2 = (unsigned long)((unsigned int)((arg0 ^ 0xffff)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg1) * arg0))) - (unsigned long)((unsigned int)((arg1 + arg0)))))) + ((unsigned long)((unsigned int)(((unsigned long)(arg1) | arg0))) * 2)))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) ^ arg1))) - (unsigned long)((unsigned int)((var2 + arg1)))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) & arg1))) * 2)))) * 8)));
} gcc -O0
6/6mba_add_identities pass 23 lines
// glaurung: mba_add_identities @ 0x11b0
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int divergence;
unsigned int var10;
unsigned int var2;
unsigned int var6;
// x86-64 prologue: save rbp, frame 24 bytes
var2 = mba149_add_xor_and(arg0, arg1);
a = var2;
var6 = mba149_add_or_and(arg0, arg1);
b = var6;
var10 = mba149_add_or_xor(arg0, arg1);
c = var10;
divergence = ((unsigned int)((b ^ c)) | (unsigned int)((a ^ b)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(a) + (unsigned long)((unsigned int)(((unsigned long)(c) ^ -0x61c88647LL)))))) ^ divergence));
} mba_bit_population pass 16 lines
// glaurung: mba_bit_population @ 0x1302
uint32_t mba_bit_population(uint32_t arg0) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
unsigned int v;
unsigned int var20;
unsigned int var28;
// x86-64 prologue: save rbp, frame 24 bytes
v = (arg0 - (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)));
var20 = mba149_add_or_and((unsigned long)((unsigned int)((v & 0x33333333))), (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(v) >> 2))) & 0x33333333))));
v = var20;
var28 = mba149_add_xor_and(v, (unsigned long)((unsigned int)(((unsigned int)(v) >> 4))));
v = (var28 & 0xf0f0f0f);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(v) * 0x1010101))) >> 24));
} mba_mix_buffer pass 43 lines
// glaurung: mba_mix_buffer @ 0x1370
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_add_or_xor(unsigned int, unsigned int);
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int acc;
int index;
unsigned int byte;
unsigned int ret;
unsigned int var10;
unsigned int var20;
unsigned int var24;
unsigned int var28;
// x86-64 prologue: save rbp, frame 32 bytes
acc = arg2;
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
for (index = 0; (index < arg1); index++) {
byte = (unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255));
var10 = mba149_add_xor_and(acc, byte);
acc = var10;
var20 = mba149_add_or_xor((unsigned long)((unsigned int)((acc << 3))), (unsigned long)((unsigned int)(((unsigned int)(acc) >> 7))));
acc = var20;
var24 = mba149_zero(acc, byte);
var28 = mba149_sub_xor_andnot(acc, var24);
acc = var28;
}
ret = mba149_add_or_and(acc, (unsigned long)((unsigned int)(arg1)));
// x86-64 epilogue: restore rbp
return ret;
} mba_select pass 16 lines
// glaurung: mba_select @ 0x12b4
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
extern unsigned int mba149_add_xor_and(unsigned int, unsigned int);
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int mask;
unsigned int blended;
unsigned int ret;
unsigned int var13;
// x86-64 prologue: save rbp, frame 32 bytes
mask = (-(unsigned long)((unsigned int)((arg2 & 1))));
blended = ((unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) & mask)) ^ arg0);
var13 = mba149_zero(arg0, arg1);
ret = mba149_add_xor_and(blended, var13);
// x86-64 epilogue: restore rbp
return ret;
} mba_sub_identity pass 14 lines
// glaurung: mba_sub_identity @ 0x121f
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_add_or_and(unsigned int, unsigned int);
extern unsigned int mba149_sub_xor_andnot(unsigned int, unsigned int);
unsigned int difference;
unsigned int var2;
unsigned int var6;
// x86-64 prologue: save rbp, frame 24 bytes
var2 = mba149_sub_xor_andnot(arg0, arg1);
difference = var2;
var6 = mba149_add_or_and(difference, arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)((var6 ^ difference));
} mba_zero_polynomial pass 15 lines
// glaurung: mba_zero_polynomial @ 0x1257
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
extern unsigned int mba149_zero(unsigned int, unsigned int);
unsigned int nonce;
unsigned int nonce2;
unsigned int var2;
unsigned int var9;
// x86-64 prologue: save rbp, frame 24 bytes
var2 = mba149_zero(arg0, arg1);
nonce = var2;
var9 = mba149_zero(arg1, (unsigned long)((unsigned int)((arg0 ^ 0xffff))));
nonce2 = var9;
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(nonce2) << 3))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + (unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1)))))) + (unsigned long)(nonce))))));
} gcc -O2
6/6mba_add_identities pass 17 lines
// glaurung: mba_add_identities @ 0x1100
uint32_t mba_add_identities(uint32_t arg0, uint32_t arg1) {
unsigned int a;
unsigned int b;
unsigned int c;
unsigned int divergence;
long var13;
long var3;
long var7;
long var9;
var3 = (unsigned long)((unsigned int)((arg0 ^ arg1)));
a = (unsigned long)((unsigned int)((var3 + ((unsigned long)((unsigned int)((arg0 & arg1))) * 2))));
var7 = (unsigned long)((unsigned int)((arg0 + arg1)));
var9 = (unsigned long)((unsigned int)((arg0 | arg1)));
var13 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var9 + var9))) - var3)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) ^ a))) | (unsigned long)((unsigned int)((var7 ^ var13)))))) ^ (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var13 ^ -0x61c88647LL))) + a)))));
} mba_bit_population pass 11 lines
// glaurung: mba_bit_population @ 0x11d0
uint32_t mba_bit_population(uint32_t arg0) {
unsigned int v;
int var16;
long var21;
long var7;
var7 = (unsigned long)((unsigned int)((arg0 - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
var16 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var7)) >> 2))) & 0x33333333)) + (unsigned int)((var7 & 0x33333333)));
var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) >> 4)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var21 ^ (unsigned long)((unsigned int)(var16))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) & (unsigned long)((unsigned int)(var16))))) * 2)))) & 0xf0f0f0f))) * 0x1010101))) >> 24));
} mba_mix_buffer pass 52 lines
// glaurung: mba_mix_buffer @ 0x1210
uint32_t mba_mix_buffer(uint8_t * arg0, int32_t arg1, uint32_t arg2) {
unsigned int byte;
unsigned int acc;
int index;
long var0;
long var15;
long var18;
long var2;
long var21;
long var26;
int var3;
long var33;
long var44;
long var5;
long var50;
long var54;
long var6;
long var7;
var0 = (unsigned long)((unsigned int)(arg1));
if ((arg0 == 0)) {
return 0;
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return 0;
}
var2 = (unsigned long)(arg2);
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
var3 = (var0 + var2);
return (unsigned int)(var3);
}
var5 = (long)((((long)arg0 + (unsigned long)((unsigned int)((arg1 - 1)))) + 1));
var6 = (long)arg0;
var7 = (unsigned long)(arg2);
do {
byte = (unsigned int)((unsigned char)(*(char *)((var6))));
var6 = (var6 + 1);
var15 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var7 ^ byte))) + ((unsigned long)((unsigned int)((byte & var7))) * 2))));
var18 = (unsigned long)((unsigned int)((var15 << 3)));
var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) >> 7)));
var26 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) | var18)));
acc = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var26 + var26))) - (unsigned long)((unsigned int)((var21 ^ var18))))));
var33 = (unsigned long)((unsigned int)((byte & acc)));
var44 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var33 + var33))) - (unsigned long)((unsigned int)((byte | acc)))))) + (unsigned long)((unsigned int)((byte ^ acc)))))) - var33)));
var50 = (unsigned long)((unsigned int)(((~acc) & var44)));
var54 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) ^ acc))) - (unsigned long)((unsigned int)((var50 + var50))))));
var7 = var54;
var2 = var54;
} while ((var5 != var6));
var3 = (var0 + var2);
return (unsigned int)(var3);
} mba_select pass 12 lines
// glaurung: mba_select @ 0x11a0
uint32_t mba_select(uint32_t arg0, uint32_t arg1, uint32_t arg2) {
unsigned int blended;
unsigned int mask;
long var14;
long var18;
long var5;
var5 = (unsigned long)((unsigned int)((arg0 ^ arg1)));
var14 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((-(unsigned long)((unsigned int)((arg2 & 1)))) & var5))) ^ arg0)));
var18 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var5 + (unsigned long)((unsigned int)((arg0 & arg1)))))) - (unsigned long)((unsigned int)((arg0 | arg1))))));
return (unsigned int)(((unsigned long)((unsigned int)((var14 ^ var18))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var14)) & var18))) * 2)));
} mba_sub_identity pass 8 lines
// glaurung: mba_sub_identity @ 0x1130
uint32_t mba_sub_identity(uint32_t arg0, uint32_t arg1) {
unsigned int difference;
long var3;
var3 = (unsigned long)((unsigned int)(((~arg0) & arg1)));
difference = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) - (unsigned long)((unsigned int)((var3 + var3))))));
return (unsigned int)(((unsigned long)((unsigned int)((arg1 + difference))) ^ difference));
} mba_zero_polynomial pass 10 lines
// glaurung: mba_zero_polynomial @ 0x1150
uint32_t mba_zero_polynomial(uint32_t arg0, uint32_t arg1) {
long var17;
long var4;
long var8;
var4 = (unsigned long)((unsigned int)((arg0 & arg1)));
var8 = (unsigned long)((unsigned int)((arg0 ^ 0xffff)));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) & arg1)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) ^ arg1))) + var4))) * 2)))) - (unsigned long)((unsigned int)((arg0 | arg1)))))) - var4))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var17 + var17))) - (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) | arg1)))))) + (unsigned long)((unsigned int)((var8 ^ arg1)))))) - var17))) * 8)));
}