Fixture 02
integer widths
C · 28 functions · 4 lanes · 112 of 112 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Integer width / signedness fixture. Every function is a pure integer function whose result depends on the EXACT bit width and signedness of the operations a correct decompilation must recover. A width- or sign-broken lowering (dropped 32-bit zero-extension, >> on the wrong signedness, a missing truncation mask, a sign-extend where a zero-extend belonged) sends the return value to a different constant, which an execution-differential test catches.
Targets review #2 (integer width & sign). Keep every function pure (no globals, no memory beyond passed-in pointers, no libc) and deterministic in its integer arguments. Every function returns an int that differs between a correct and a width-broken lowering.
/* 02_integer_widths.c
*
* Integer width / signedness fixture. Every function is a pure integer function
* whose result depends on the EXACT bit width and signedness of the operations
* a correct decompilation must recover. A width- or sign-broken lowering
* (dropped 32-bit zero-extension, `>>` on the wrong signedness, a missing
* truncation mask, a sign-extend where a zero-extend belonged) sends the return
* value to a different constant, which an execution-differential test catches.
*
* Targets review #2 (integer width & sign). Keep every function pure (no
* globals, no memory beyond passed-in pointers, no libc) and deterministic in
* its integer arguments. Every function returns an int that differs between a
* correct and a width-broken lowering.
*/
#include <stdint.h>
/* --- round-trips through each unsigned width --------------------------- */
/* uint8_t round-trip: value must survive an 8-bit store/load, i.e. be masked
* to the low byte. A decompiler that widens the temporary loses the & 0xFF. */
int rt_u8(unsigned x) {
uint8_t v = (uint8_t)x;
return (int)v; /* == x & 0xFF */
}
/* uint16_t round-trip. */
int rt_u16(unsigned x) {
uint16_t v = (uint16_t)x;
return (int)v; /* == x & 0xFFFF */
}
/* uint32_t round-trip: return the full 32-bit value as a signed int. */
int rt_u32(unsigned x) {
uint32_t v = (uint32_t)x;
return (int)v;
}
/* uint64_t round-trip: pack a value into 64 bits, fold the halves back to an
* int. If the high 32 bits are dropped the fold changes. */
int rt_u64(unsigned x) {
uint64_t v = ((uint64_t)x << 20) | (uint64_t)x;
return (int)((v >> 20) ^ (v & 0xFFFFFF));
}
/* --- sign extension ---------------------------------------------------- */
/* Return an int8_t param as int: the top bit must sign-extend. For x=0xFF the
* result is -1, not 255. A zero-extend here is the classic bug. */
int sext_i8(int x) {
int8_t v = (int8_t)x;
return (int)v;
}
/* Sign-extend a 16-bit quantity. */
int sext_i16(int x) {
int16_t v = (int16_t)x;
return (int)v;
}
/* --- zero extension of architecture-defined 32-bit writes -------------- */
/* Write a 32-bit value into a 64-bit register: on x86-64 a 32-bit write
* zero-extends the full 64-bit register. Compute in 64 bits and mask so the
* value is unambiguous; a lowering that treats the write as sign-extending or
* leaves the high bits dirty produces a different masked result. */
int zext_u32_to_u64(uint32_t x) {
uint64_t r = x; /* zero-extended by definition */
r += 0x100000000ULL; /* deposit into the high word */
return (int)(r >> 32); /* == 1 for every x if zero-extended */
}
/* A 32-bit subtract that underflows: the borrow must NOT propagate into a
* 64-bit register. (a - b) as uint32_t wraps mod 2^32; widened math would not. */
int wrap_sub_u32(uint32_t a, uint32_t b) {
uint32_t r = a - b;
return (int)(r >> 24); /* top byte of the wrapped difference */
}
/* --- truncation -------------------------------------------------------- */
/* Truncate to a byte. */
int trunc_u8(unsigned x) {
return (uint8_t)x; /* low 8 bits, zero-extended to int */
}
/* Truncate to a halfword after an arithmetic op that overflows 16 bits. */
int trunc_u16_after_mul(unsigned x) {
uint16_t v = (uint16_t)(x * 3u);
return (int)v;
}
/* --- partial-word write / deposit -------------------------------------- */
/* Overwrite only the low byte of a word, keep the upper three bytes. A
* decompiler that clobbers the whole word instead of doing a byte deposit
* returns a different value. */
int deposit_low_byte(unsigned x, unsigned b) {
uint32_t v = (uint32_t)x;
v = (v & 0xFFFFFF00u) | (b & 0xFFu);
return (int)v;
}
/* Deposit into the second byte lane [15:8]. */
int deposit_byte1(unsigned x, unsigned b) {
uint32_t v = (uint32_t)x;
v = (v & 0xFFFF00FFu) | ((b & 0xFFu) << 8);
return (int)v;
}
/* --- byte extraction --------------------------------------------------- */
/* Extract byte lane 1: (x >> 8) & 0xFF. */
int extract_byte1(unsigned x) {
return (int)((x >> 8) & 0xFFu);
}
/* Extract byte lane 3 (top byte of a 32-bit word). */
int extract_byte3(unsigned x) {
return (int)((x >> 24) & 0xFFu);
}
/* --- hi<<32 | lo reconstruction ---------------------------------------- */
/* Reassemble a 64-bit value from two 32-bit halves, then fold to an int. If
* `hi` is not shifted into the true high word (e.g. shifted in 32-bit math and
* lost) the fold differs. */
int reconstruct_64(uint32_t hi, uint32_t lo) {
uint64_t v = ((uint64_t)hi << 32) | (uint64_t)lo;
return (int)((v >> 32) - (v & 0xFFFFFFFFu));
}
/* --- signed vs unsigned right shift (MUST differ for negatives) -------- */
/* Arithmetic right shift on a signed int: sign bit replicates. For x<0 the
* result stays negative. */
int sar_signed(int x) {
return x >> 4;
}
/* Logical right shift on an unsigned: zero fill. For the SAME negative bit
* pattern this must NOT equal sar_signed — that divergence is the whole point. */
int shr_unsigned(unsigned x) {
return (int)(x >> 4);
}
/* Right shift after casting a negative int to unsigned: forces the logical
* (zero-fill) form even though the source looks signed. */
int shr_via_cast(int x) {
return (int)(((unsigned)x) >> 1);
}
/* --- overflow-sensitive add / mul -------------------------------------- */
/* 32-bit signed add that is allowed to wrap: the result is only correct if the
* add is performed at 32 bits. Computed through uint32_t to keep it defined. */
int add_wrap32(int a, int b) {
uint32_t r = (uint32_t)a + (uint32_t)b;
return (int)r;
}
/* 32-bit multiply that discards the high product. If the decompiler promotes to
* a 64-bit multiply and keeps the high bits, the masked result changes. */
int mul_wrap32(unsigned a, unsigned b) {
uint32_t r = a * b;
return (int)(r & 0x7FFFFFFF);
}
/* Widening multiply: the product genuinely needs 64 bits; folding it back
* exercises the high half that a 32-bit-only lowering would drop. */
int mul_widen(uint32_t a, uint32_t b) {
uint64_t r = (uint64_t)a * (uint64_t)b;
return (int)((r >> 32) ^ (r & 0xFFFFFFFFu));
}
/* Full-width x86 multiply and divide have TWO architectural outputs. These
* functions force both signed and unsigned high-product/remainder paths and
* return the complete 64-bit result so dropping either half is observable. */
uint64_t umul_high64(uint64_t a, uint64_t b) {
return (uint64_t)(((unsigned __int128)a * (unsigned __int128)b) >> 64);
}
int64_t smul_high64(int64_t a, int64_t b) {
return (int64_t)(((__int128)a * (__int128)b) >> 64);
}
uint64_t urem64(uint64_t a, uint64_t b) {
return a % b;
}
int64_t srem64(int64_t a, int64_t b) {
return a % b;
}
/* --- rotates written in portable C ------------------------------------- */
/* Rotate-left by a fixed amount, 32-bit. The (x >> (32-n)) half must use
* 32-bit unsigned semantics; a wrong width leaks or loses bits. */
int rotl32_7(uint32_t x) {
uint32_t r = (x << 7) | (x >> (32 - 7));
return (int)r;
}
/* Rotate-right by a variable amount masked to 5 bits. */
int rotr32(uint32_t x, unsigned n) {
n &= 31u;
uint32_t r = (x >> n) | (x << ((32 - n) & 31));
return (int)r;
}
/* 16-bit rotate: the wrap distance is 16, and the intermediate must be masked
* to 16 bits or the two halves collide. */
int rotl16_3(unsigned x) {
uint16_t v = (uint16_t)x;
uint16_t r = (uint16_t)((v << 3) | (v >> (16 - 3)));
return (int)r;
} 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
28/28add_wrap32 pass 8 lines
// glaurung: add_wrap32 @ 0x1360
int add_wrap32(int arg0, int arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = ((unsigned int)(arg0) + arg1);
// x86-64 epilogue: restore rbp
return r;
} deposit_byte1 pass 9 lines
// glaurung: deposit_byte1 @ 0x1280
int deposit_byte1(unsigned int arg0, unsigned int arg1) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
v = ((unsigned int)((v & -0xff01LL)) | (unsigned int)(((unsigned long)((unsigned int)((arg1 & 255))) << 8)));
// x86-64 epilogue: restore rbp
return v;
} deposit_low_byte pass 9 lines
// glaurung: deposit_low_byte @ 0x1250
int deposit_low_byte(unsigned int arg0, unsigned int arg1) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
v = ((unsigned int)((v & -256)) | (unsigned int)((arg1 & 255)));
// x86-64 epilogue: restore rbp
return v;
} extract_byte1 pass 6 lines
// glaurung: extract_byte1 @ 0x12b0
int extract_byte1(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 8))) & 255));
} extract_byte3 pass 6 lines
// glaurung: extract_byte3 @ 0x12d0
int extract_byte3(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 24))) & 255));
} mul_widen pass 8 lines
// glaurung: mul_widen @ 0x13a0
int mul_widen(uint32_t arg0, uint32_t arg1) {
unsigned long r;
// x86-64 prologue: save rbp
r = ((unsigned long)(arg0) * (unsigned long)(arg1));
// x86-64 epilogue: restore rbp
return (((unsigned long)(r) >> 32) ^ (0xffffffff & r));
} mul_wrap32 pass 8 lines
// glaurung: mul_wrap32 @ 0x1380
int mul_wrap32(unsigned int arg0, unsigned int arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = (arg0 * arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(r) & 0x7fffffff));
} reconstruct_64 pass 8 lines
// glaurung: reconstruct_64 @ 0x12f0
int reconstruct_64(uint32_t arg0, uint32_t arg1) {
unsigned long v;
// x86-64 prologue: save rbp
v = (((unsigned long)(arg0) << 32) | (unsigned long)(arg1));
// x86-64 epilogue: restore rbp
return (((unsigned long)(v) >> 32) - (0xffffffff & v));
} rotl16_3 pass 10 lines
// glaurung: rotl16_3 @ 0x14c0
int rotl16_3(unsigned int arg0) {
unsigned short v;
unsigned short r;
// x86-64 prologue: save rbp
v = arg0;
r = ((unsigned long)((unsigned int)(((unsigned int)(v) << 3))) | (unsigned long)((unsigned int)(((int)(v) >> 13))));
// x86-64 epilogue: restore rbp
return (unsigned int)(r);
} rotl32_7 pass 8 lines
// glaurung: rotl32_7 @ 0x1460
int rotl32_7(uint32_t arg0) {
unsigned int r;
// x86-64 prologue: save rbp
r = ((unsigned int)((arg0 << 7)) | (unsigned int)(((unsigned int)(arg0) >> 25)));
// x86-64 epilogue: restore rbp
return r;
} rotr32 pass 9 lines
// glaurung: rotr32 @ 0x1480
int rotr32(uint32_t arg0, unsigned int arg1) {
unsigned int r;
// x86-64 prologue: save rbp
arg1 = (arg1 & 31);
r = ((unsigned int)(((unsigned long)(arg0) >> (arg1 & 31))) | (unsigned int)((arg0 << ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((32 - arg1))) & 31))) & 31))));
// x86-64 epilogue: restore rbp
return r;
} rt_u16 pass 8 lines
// glaurung: rt_u16 @ 0x1120
int rt_u16(unsigned int arg0) {
unsigned short v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} rt_u32 pass 8 lines
// glaurung: rt_u32 @ 0x1140
int rt_u32(unsigned int arg0) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} rt_u64 pass 8 lines
// glaurung: rt_u64 @ 0x1160
int rt_u64(unsigned int arg0) {
unsigned long v;
// x86-64 prologue: save rbp
v = (((unsigned long)(arg0) << 20) | (unsigned long)(arg0));
// x86-64 epilogue: restore rbp
return (((unsigned long)(v) >> 20) ^ (v & 0xffffff));
} rt_u8 pass 8 lines
// glaurung: rt_u8 @ 0x1100
int rt_u8(unsigned int arg0) {
unsigned char v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} sar_signed pass 6 lines
// glaurung: sar_signed @ 0x1330
int sar_signed(int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((int)(arg0) >> 4));
} sext_i16 pass 8 lines
// glaurung: sext_i16 @ 0x11b0
int sext_i16(int arg0) {
short v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} sext_i8 pass 8 lines
// glaurung: sext_i8 @ 0x1190
int sext_i8(int arg0) {
signed char v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} shr_unsigned pass 6 lines
// glaurung: shr_unsigned @ 0x1340
int shr_unsigned(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) >> 4));
} shr_via_cast pass 6 lines
// glaurung: shr_via_cast @ 0x1350
int shr_via_cast(int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 1));
} smul_high64 pass 6 lines
// glaurung: smul_high64 @ 0x1400
int64_t smul_high64(int64_t arg0, int64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((long)(((unsigned __int128)((__int128)(long)(arg0) * (__int128)(long)(arg1))) >> 64));
} srem64 pass 6 lines
// glaurung: srem64 @ 0x1440
int64_t srem64(int64_t arg0, int64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((long)((((__int128)(long)(((long)(arg0) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(arg0)) % (long)(arg1)));
} trunc_u16_after_mul pass 8 lines
// glaurung: trunc_u16_after_mul @ 0x1230
int trunc_u16_after_mul(unsigned int arg0) {
unsigned short v;
// x86-64 prologue: save rbp
v = (arg0 * 3);
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} trunc_u8 pass 6 lines
// glaurung: trunc_u8 @ 0x1220
int trunc_u8(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)((unsigned char)(((unsigned long)(arg0) & 255)));
} umul_high64 pass 6 lines
// glaurung: umul_high64 @ 0x13e0
uint64_t umul_high64(uint64_t arg0, uint64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)(((unsigned __int128)(unsigned long)(arg0) * (unsigned __int128)(unsigned long)(arg1)) >> 64));
} urem64 pass 6 lines
// glaurung: urem64 @ 0x1420
uint64_t urem64(uint64_t arg0, uint64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)(((((unsigned __int128)(unsigned long)((unsigned long)((unsigned int)((unsigned long)((unsigned int)(0))))) << 64) | (unsigned long)(arg0)) % (unsigned long)(arg1))));
} wrap_sub_u32 pass 8 lines
// glaurung: wrap_sub_u32 @ 0x1200
int wrap_sub_u32(uint32_t arg0, uint32_t arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = (arg0 - arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(r) >> 24));
} zext_u32_to_u64 pass 9 lines
// glaurung: zext_u32_to_u64 @ 0x11d0
int zext_u32_to_u64(uint32_t arg0) {
unsigned long r;
// x86-64 prologue: save rbp
r = arg0;
r = (0x100000000 + r);
// x86-64 epilogue: restore rbp
return ((unsigned long)(r) >> 32);
} clang -O2
28/28add_wrap32 pass 5 lines
// glaurung: add_wrap32 @ 0x1230
int add_wrap32(int arg0, int arg1) {
unsigned int r;
return (unsigned int)((arg0 + arg1));
} deposit_byte1 pass 5 lines
// glaurung: deposit_byte1 @ 0x11c0
int deposit_byte1(unsigned int arg0, unsigned int arg1) {
unsigned int v;
return (unsigned int)(((unsigned int)((unsigned short)(((unsigned long)((unsigned int)((arg1 << 8))) & 0xffff))) | (unsigned long)((unsigned int)((arg0 & -0xff01LL)))));
} deposit_low_byte pass 5 lines
// glaurung: deposit_low_byte @ 0x11b0
int deposit_low_byte(unsigned int arg0, unsigned int arg1) {
unsigned int v;
return (unsigned int)(((unsigned int)((unsigned char)((arg1 & 255))) | (unsigned long)((unsigned int)((arg0 & -256)))));
} extract_byte1 pass 4 lines
// glaurung: extract_byte1 @ 0x11d0
int extract_byte1(unsigned int arg0) {
return (unsigned int)((unsigned char)((((unsigned long)(arg0) >> 8) & 255)));
} extract_byte3 pass 4 lines
// glaurung: extract_byte3 @ 0x11e0
int extract_byte3(unsigned int arg0) {
return (unsigned int)(((unsigned long)(arg0) >> 24));
} mul_widen pass 6 lines
// glaurung: mul_widen @ 0x1250
int mul_widen(uint32_t arg0, uint32_t arg1) {
unsigned long r;
r = ((unsigned long)(arg1) * (unsigned long)(arg0));
return (unsigned int)((((unsigned long)(r) >> 32) ^ r));
} mul_wrap32 pass 5 lines
// glaurung: mul_wrap32 @ 0x1240
int mul_wrap32(unsigned int arg0, unsigned int arg1) {
unsigned int r;
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) * arg1))) & 0x7fffffff));
} reconstruct_64 pass 4 lines
// glaurung: reconstruct_64 @ 0x11f0
int reconstruct_64(uint32_t arg0, uint32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) - arg1));
} rotl16_3 pass 6 lines
// glaurung: rotl16_3 @ 0x12f0
int rotl16_3(unsigned int arg0) {
int var0;
var0 = (unsigned int)((unsigned short)((arg0 & 0xffff)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 13))) + ((unsigned long)((unsigned int)((var0 & 0x1fff))) * 8)));
} rotl32_7 pass 5 lines
// glaurung: rotl32_7 @ 0x12d0
int rotl32_7(uint32_t arg0) {
unsigned int r;
return (((unsigned long)(arg0) << 7) | ((unsigned long)(arg0) >> 25));
} rotr32 pass 7 lines
// glaurung: rotr32 @ 0x12e0
int rotr32(uint32_t arg0, unsigned int arg1) {
unsigned int r;
long t41;
t41 = ((unsigned long)(arg1) & 31);
return (((unsigned long)(arg0) >> t41) | ((unsigned long)(arg0) << ((32 - t41) & 31)));
} rt_u16 pass 4 lines
// glaurung: rt_u16 @ 0x1110
int rt_u16(unsigned int arg0) {
return (unsigned int)((unsigned short)((arg0 & 0xffff)));
} rt_u32 pass 4 lines
// glaurung: rt_u32 @ 0x1120
int rt_u32(unsigned int arg0) {
return arg0;
} rt_u64 pass 7 lines
// glaurung: rt_u64 @ 0x1130
int rt_u64(unsigned int arg0) {
unsigned long v;
long var3;
var3 = (((unsigned long)(arg0) << 20) | (unsigned long)(arg0));
return (unsigned int)((((unsigned long)(var3) >> 20) ^ (unsigned long)((unsigned int)((var3 & 0xffffff)))));
} rt_u8 pass 4 lines
// glaurung: rt_u8 @ 0x1100
int rt_u8(unsigned int arg0) {
return (unsigned int)((unsigned char)((arg0 & 255)));
} sar_signed pass 4 lines
// glaurung: sar_signed @ 0x1200
int sar_signed(int arg0) {
return (unsigned int)(((int)(arg0) >> 4));
} sext_i16 pass 4 lines
// glaurung: sext_i16 @ 0x1160
int sext_i16(int arg0) {
return (int)((short)((arg0 & 0xffff)));
} sext_i8 pass 4 lines
// glaurung: sext_i8 @ 0x1150
int sext_i8(int arg0) {
return (int)((signed char)((arg0 & 255)));
} shr_unsigned pass 4 lines
// glaurung: shr_unsigned @ 0x1210
int shr_unsigned(unsigned int arg0) {
return (unsigned int)(((unsigned long)(arg0) >> 4));
} shr_via_cast pass 4 lines
// glaurung: shr_via_cast @ 0x1220
int shr_via_cast(int arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 1));
} smul_high64 pass 4 lines
// glaurung: smul_high64 @ 0x1280
int64_t smul_high64(int64_t arg0, int64_t arg1) {
return ((long)(((unsigned __int128)((__int128)(long)(arg1) * (__int128)(long)(arg0))) >> 64));
} srem64 pass 9 lines
// glaurung: srem64 @ 0x12b0
int64_t srem64(int64_t arg0, int64_t arg1) {
long var0;
var0 = arg0;
if ((((unsigned long)((arg0 | arg1)) >> 32) == 0)) {
return (unsigned long)((unsigned int)(((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var0)) % (unsigned int)(arg1))))));
}
return ((long)((((__int128)(long)(((long)(arg0) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(arg0)) % (long)(arg1)));
} trunc_u16_after_mul pass 5 lines
// glaurung: trunc_u16_after_mul @ 0x11a0
int trunc_u16_after_mul(unsigned int arg0) {
unsigned short v;
return (unsigned int)((unsigned short)(((unsigned long)((unsigned int)((arg0 + (arg0 * 2)))) & 0xffff)));
} trunc_u8 pass 4 lines
// glaurung: trunc_u8 @ 0x1190
int trunc_u8(unsigned int arg0) {
return (unsigned int)((unsigned char)((arg0 & 255)));
} umul_high64 pass 4 lines
// glaurung: umul_high64 @ 0x1270
uint64_t umul_high64(uint64_t arg0, uint64_t arg1) {
return ((unsigned long)(((unsigned __int128)(unsigned long)(arg1) * (unsigned __int128)(unsigned long)(arg0)) >> 64));
} urem64 pass 9 lines
// glaurung: urem64 @ 0x1290
uint64_t urem64(uint64_t arg0, uint64_t arg1) {
long var0;
var0 = arg0;
if ((((unsigned long)((arg0 | arg1)) >> 32) == 0)) {
return (unsigned long)((unsigned int)(((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)(var0)) % (unsigned int)(arg1))))));
}
return ((unsigned long)(((((unsigned __int128)(unsigned long)((unsigned long)((unsigned int)(0))) << 64) | (unsigned long)(arg0)) % (unsigned long)(arg1))));
} wrap_sub_u32 pass 5 lines
// glaurung: wrap_sub_u32 @ 0x1180
int wrap_sub_u32(uint32_t arg0, uint32_t arg1) {
unsigned int r;
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) - arg1))) >> 24));
} zext_u32_to_u64 pass 4 lines
// glaurung: zext_u32_to_u64 @ 0x1170
int zext_u32_to_u64(uint32_t arg0) {
return 1;
} gcc -O0
28/28add_wrap32 pass 8 lines
// glaurung: add_wrap32 @ 0x1311
int add_wrap32(int arg0, int arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = ((unsigned int)(arg1) + (unsigned int)(arg0));
// x86-64 epilogue: restore rbp
return r;
} deposit_byte1 pass 9 lines
// glaurung: deposit_byte1 @ 0x124a
int deposit_byte1(unsigned int arg0, unsigned int arg1) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
v = ((unsigned int)((unsigned short)(((unsigned long)((unsigned int)((arg1 << 8))) & 0xffff))) | (unsigned int)((v & -0xff01LL)));
// x86-64 epilogue: restore rbp
return v;
} deposit_low_byte pass 9 lines
// glaurung: deposit_low_byte @ 0x121f
int deposit_low_byte(unsigned int arg0, unsigned int arg1) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
v = ((unsigned int)((unsigned char)((arg1 & 255))) | (unsigned int)((v & -256)));
// x86-64 epilogue: restore rbp
return v;
} extract_byte1 pass 6 lines
// glaurung: extract_byte1 @ 0x1278
int extract_byte1(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 8))) & 255)));
} extract_byte3 pass 6 lines
// glaurung: extract_byte3 @ 0x128e
int extract_byte3(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) >> 24));
} mul_widen pass 8 lines
// glaurung: mul_widen @ 0x1351
int mul_widen(uint32_t arg0, uint32_t arg1) {
unsigned long r;
// x86-64 prologue: save rbp
r = ((unsigned long)(arg1) * (unsigned long)(arg0));
// x86-64 epilogue: restore rbp
return (unsigned int)((r ^ (unsigned long)((unsigned int)(((unsigned long)(r) >> 32)))));
} mul_wrap32 pass 8 lines
// glaurung: mul_wrap32 @ 0x132f
int mul_wrap32(unsigned int arg0, unsigned int arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = (arg0 * arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(r) & 0x7fffffff));
} reconstruct_64 pass 8 lines
// glaurung: reconstruct_64 @ 0x12a1
int reconstruct_64(uint32_t arg0, uint32_t arg1) {
unsigned long v;
// x86-64 prologue: save rbp
v = ((unsigned long)(arg1) | ((unsigned long)(arg0) << 32));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(v) >> 32))) - (unsigned long)((unsigned int)(v))));
} rotl16_3 pass 10 lines
// glaurung: rotl16_3 @ 0x14a6
int rotl16_3(unsigned int arg0) {
unsigned short v;
unsigned short r;
// x86-64 prologue: save rbp
v = arg0;
r = ((((unsigned long)((unsigned short)((v & 0xffff))) >> 13) & 0xffff) | (unsigned long)((unsigned int)(((unsigned int)(v) << 3))));
// x86-64 epilogue: restore rbp
return (unsigned int)(r);
} rotl32_7 pass 8 lines
// glaurung: rotl32_7 @ 0x1467
int rotl32_7(uint32_t arg0) {
unsigned int r;
// x86-64 prologue: save rbp
r = ((arg0 << 7) | ((unsigned int)(arg0) >> 25));
// x86-64 epilogue: restore rbp
return r;
} rotr32 pass 11 lines
// glaurung: rotr32 @ 0x1480
int rotr32(uint32_t arg0, unsigned int arg1) {
unsigned int r;
long t41;
// x86-64 prologue: save rbp
arg1 = (arg1 & 31);
t41 = ((unsigned long)(arg1) & 31);
r = (((unsigned long)(arg0) >> t41) | (arg0 << ((32 - t41) & 31)));
// x86-64 epilogue: restore rbp
return r;
} rt_u16 pass 8 lines
// glaurung: rt_u16 @ 0x1110
int rt_u16(unsigned int arg0) {
unsigned short v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} rt_u32 pass 8 lines
// glaurung: rt_u32 @ 0x1128
int rt_u32(unsigned int arg0) {
unsigned int v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} rt_u64 pass 8 lines
// glaurung: rt_u64 @ 0x113e
int rt_u64(unsigned int arg0) {
unsigned long v;
// x86-64 prologue: save rbp
v = ((unsigned long)(arg0) | ((unsigned long)(arg0) << 20));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)((v & 0xffffff))) ^ (unsigned long)((unsigned int)(((unsigned long)(v) >> 20)))));
} rt_u8 pass 8 lines
// glaurung: rt_u8 @ 0x10f9
int rt_u8(unsigned int arg0) {
unsigned char v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} sar_signed pass 6 lines
// glaurung: sar_signed @ 0x12d9
int sar_signed(int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((int)(arg0) >> 4));
} sext_i16 pass 8 lines
// glaurung: sext_i16 @ 0x118b
int sext_i16(int arg0) {
short v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} sext_i8 pass 8 lines
// glaurung: sext_i8 @ 0x1174
int sext_i8(int arg0) {
signed char v;
// x86-64 prologue: save rbp
v = arg0;
// x86-64 epilogue: restore rbp
return v;
} shr_unsigned pass 6 lines
// glaurung: shr_unsigned @ 0x12ec
int shr_unsigned(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) >> 4));
} shr_via_cast pass 6 lines
// glaurung: shr_via_cast @ 0x12ff
int shr_via_cast(int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 1));
} smul_high64 pass 6 lines
// glaurung: smul_high64 @ 0x13ce
int64_t smul_high64(int64_t arg0, int64_t arg1) {
// x86-64 prologue: save rbp, frame 8 bytes
// x86-64 epilogue: restore rbp
return (((((long)(arg1) >> 63) * arg0) + (((long)(arg0) >> 63) * arg1)) + ((unsigned long)(((unsigned __int128)(unsigned long)(arg1) * (unsigned __int128)(unsigned long)(arg0)) >> 64)));
} srem64 pass 6 lines
// glaurung: srem64 @ 0x1448
int64_t srem64(int64_t arg0, int64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((long)((((__int128)(long)(((long)(arg0) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(arg0)) % (long)(arg1)));
} trunc_u16_after_mul pass 8 lines
// glaurung: trunc_u16_after_mul @ 0x11ff
int trunc_u16_after_mul(unsigned int arg0) {
unsigned short v;
// x86-64 prologue: save rbp
v = ((unsigned long)((unsigned int)((arg0 + arg0))) + arg0);
// x86-64 epilogue: restore rbp
return (unsigned int)(v);
} trunc_u8 pass 6 lines
// glaurung: trunc_u8 @ 0x11ec
int trunc_u8(unsigned int arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)((unsigned char)(((unsigned long)(arg0) & 255)));
} umul_high64 pass 6 lines
// glaurung: umul_high64 @ 0x137f
uint64_t umul_high64(uint64_t arg0, uint64_t arg1) {
// x86-64 prologue: save rbp, frame 8 bytes
// x86-64 epilogue: restore rbp
return ((unsigned long)(((unsigned __int128)(unsigned long)(arg1) * (unsigned __int128)(unsigned long)(arg0)) >> 64));
} urem64 pass 6 lines
// glaurung: urem64 @ 0x1426
uint64_t urem64(uint64_t arg0, uint64_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)(((((unsigned __int128)(unsigned long)(0) << 64) | (unsigned long)(arg0)) % (unsigned long)(arg1))));
} wrap_sub_u32 pass 8 lines
// glaurung: wrap_sub_u32 @ 0x11cd
int wrap_sub_u32(uint32_t arg0, uint32_t arg1) {
unsigned int r;
// x86-64 prologue: save rbp
r = (arg0 - arg1);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(r) >> 24));
} zext_u32_to_u64 pass 9 lines
// glaurung: zext_u32_to_u64 @ 0x11a3
int zext_u32_to_u64(uint32_t arg0) {
unsigned long r;
// x86-64 prologue: save rbp
r = arg0;
r = (r + 0x100000000);
// x86-64 epilogue: restore rbp
return ((unsigned long)(r) >> 32);
} gcc -O2
28/28add_wrap32 pass 5 lines
// glaurung: add_wrap32 @ 0x1240
int add_wrap32(int arg0, int arg1) {
unsigned int r;
return (unsigned int)((arg0 + arg1));
} deposit_byte1 pass 4 lines
// glaurung: deposit_byte1 @ 0x11c0
int deposit_byte1(unsigned int arg0, unsigned int arg1) {
return (unsigned int)(((unsigned int)((unsigned short)(((unsigned long)((unsigned int)((arg1 << 8))) & 0xffff))) | (unsigned long)((unsigned int)((arg0 & -0xff01LL)))));
} deposit_low_byte pass 4 lines
// glaurung: deposit_low_byte @ 0x11b0
int deposit_low_byte(unsigned int arg0, unsigned int arg1) {
return (unsigned int)(((unsigned long)((unsigned int)((arg0 & -256))) | (unsigned int)((unsigned char)((arg1 & 255)))));
} extract_byte1 pass 4 lines
// glaurung: extract_byte1 @ 0x11e0
int extract_byte1(unsigned int arg0) {
return (unsigned int)((unsigned char)((((unsigned long)(arg0) >> 8) & 255)));
} extract_byte3 pass 4 lines
// glaurung: extract_byte3 @ 0x11f0
int extract_byte3(unsigned int arg0) {
return (unsigned int)(((unsigned long)(arg0) >> 24));
} mul_widen pass 6 lines
// glaurung: mul_widen @ 0x1260
int mul_widen(uint32_t arg0, uint32_t arg1) {
unsigned long r;
r = ((unsigned long)(arg0) * (unsigned long)(arg1));
return (unsigned int)((((unsigned long)(r) >> 32) ^ r));
} mul_wrap32 pass 5 lines
// glaurung: mul_wrap32 @ 0x1250
int mul_wrap32(unsigned int arg0, unsigned int arg1) {
unsigned int r;
return (unsigned int)(((unsigned long)((unsigned int)((arg0 * arg1))) & 0x7fffffff));
} reconstruct_64 pass 4 lines
// glaurung: reconstruct_64 @ 0x1200
int reconstruct_64(uint32_t arg0, uint32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) - arg1));
} rotl16_3 pass 7 lines
// glaurung: rotl16_3 @ 0x12e0
int rotl16_3(unsigned int arg0) {
unsigned short v;
long t40;
t40 = ((unsigned long)(arg0) & 0xffff);
return (unsigned int)((unsigned short)((((t40 << 3) | ((unsigned long)(t40) >> 13)) & 0xffff)));
} rotl32_7 pass 5 lines
// glaurung: rotl32_7 @ 0x12c0
int rotl32_7(uint32_t arg0) {
unsigned int r;
return (((unsigned long)(arg0) << 7) | ((unsigned long)(arg0) >> 25));
} rotr32 pass 6 lines
// glaurung: rotr32 @ 0x12d0
int rotr32(uint32_t arg0, unsigned int arg1) {
long t41;
t41 = ((unsigned long)(arg1) & 31);
return (((unsigned long)(arg0) >> t41) | ((unsigned long)(arg0) << ((32 - t41) & 31)));
} rt_u16 pass 4 lines
// glaurung: rt_u16 @ 0x1110
int rt_u16(unsigned int arg0) {
return (unsigned int)((unsigned short)((arg0 & 0xffff)));
} rt_u32 pass 5 lines
// glaurung: rt_u32 @ 0x1120
int rt_u32(unsigned int arg0) {
unsigned int v;
return arg0;
} rt_u64 pass 7 lines
// glaurung: rt_u64 @ 0x1130
int rt_u64(unsigned int arg0) {
unsigned long v;
long var3;
var3 = (((unsigned long)(arg0) << 20) | (unsigned long)(arg0));
return (unsigned int)(((unsigned long)((unsigned int)((var3 & 0xffffff))) ^ ((unsigned long)(var3) >> 20)));
} rt_u8 pass 4 lines
// glaurung: rt_u8 @ 0x1100
int rt_u8(unsigned int arg0) {
return (unsigned int)((unsigned char)((arg0 & 255)));
} sar_signed pass 4 lines
// glaurung: sar_signed @ 0x1210
int sar_signed(int arg0) {
return (unsigned int)(((int)(arg0) >> 4));
} sext_i16 pass 4 lines
// glaurung: sext_i16 @ 0x1160
int sext_i16(int arg0) {
return (int)((short)((arg0 & 0xffff)));
} sext_i8 pass 4 lines
// glaurung: sext_i8 @ 0x1150
int sext_i8(int arg0) {
return (int)((signed char)((arg0 & 255)));
} shr_unsigned pass 4 lines
// glaurung: shr_unsigned @ 0x1220
int shr_unsigned(unsigned int arg0) {
return (unsigned int)(((unsigned long)(arg0) >> 4));
} shr_via_cast pass 4 lines
// glaurung: shr_via_cast @ 0x1230
int shr_via_cast(int arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 1));
} smul_high64 pass 4 lines
// glaurung: smul_high64 @ 0x1290
int64_t smul_high64(int64_t arg0, int64_t arg1) {
return ((long)(((unsigned __int128)((__int128)(long)(arg0) * (__int128)(long)(arg1))) >> 64));
} srem64 pass 4 lines
// glaurung: srem64 @ 0x12b0
int64_t srem64(int64_t arg0, int64_t arg1) {
return ((long)((((__int128)(long)(((long)(arg0) >> 63)) * (((__int128)1) << 64)) + (unsigned long)(arg0)) % (long)(arg1)));
} trunc_u16_after_mul pass 4 lines
// glaurung: trunc_u16_after_mul @ 0x11a0
int trunc_u16_after_mul(unsigned int arg0) {
return (unsigned int)((unsigned short)(((unsigned long)((unsigned int)((arg0 + (arg0 * 2)))) & 0xffff)));
} trunc_u8 pass 4 lines
// glaurung: trunc_u8 @ 0x1190
unsigned int trunc_u8(signed char arg0) {
return (unsigned int)((unsigned char)((arg0 & 255)));
} umul_high64 pass 4 lines
// glaurung: umul_high64 @ 0x1280
uint64_t umul_high64(uint64_t arg0, uint64_t arg1) {
return ((unsigned long)(((unsigned __int128)(unsigned long)(arg0) * (unsigned __int128)(unsigned long)(arg1)) >> 64));
} urem64 pass 4 lines
// glaurung: urem64 @ 0x12a0
uint64_t urem64(uint64_t arg0, uint64_t arg1) {
return ((unsigned long)(((((unsigned __int128)(unsigned long)((unsigned long)((unsigned int)(0))) << 64) | (unsigned long)(arg0)) % (unsigned long)(arg1))));
} wrap_sub_u32 pass 5 lines
// glaurung: wrap_sub_u32 @ 0x1180
int wrap_sub_u32(uint32_t arg0, uint32_t arg1) {
unsigned int r;
return (unsigned int)(((unsigned long)((unsigned int)((arg0 - arg1))) >> 24));
} zext_u32_to_u64 pass 4 lines
// glaurung: zext_u32_to_u64 @ 0x1170
int zext_u32_to_u64(uint32_t arg0) {
return 1;
}