| ... | @@ -428,17 +428,21 @@ zig_mul_sat_s(int, int, long) | ... | @@ -428,17 +428,21 @@ zig_mul_sat_s(int, int, long) |
| 428 | zig_mul_sat_s(long, long, long long) | 428 | zig_mul_sat_s(long, long, long long) |
| 429 | | 429 | |
| 430 | #define zig_shl_sat_u(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T max) { \ | 430 | #define zig_shl_sat_u(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T max) { \ |
| 431 | T leading_zeros = __builtin_clz(x); \ | 431 | if(x == 0) return 0; \ |
| 432 | return (leading_zeros + y > bits) ? max : x << y; \ | 432 | T bits_set = 64 - __builtin_clzll(x); \ |
| | 433 | return (bits_set + y > bits) ? max : x << y; \ |
| 433 | } | 434 | } |
| 434 | | 435 | |
| 435 | #define zig_shl_sat_s(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T min, T max) { \ | 436 | #define zig_shl_sat_s(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T min, T max) { \ |
| 436 | T leading_zeros = __builtin_clz(x & ~max); \ | 437 | if(x == 0) return 0; \ |
| 437 | return (leading_zeros + y > bits) ? max : x << y; \ | 438 | T x_twos_comp = x < 0 ? -x : x; \ |
| | 439 | T bits_set = 64 - __builtin_clzll(x_twos_comp); \ |
| | 440 | T min_or_max = (x < 0) ? min : max; \ |
| | 441 | return (y + bits_set > bits ) ? min_or_max : x << y; \ |
| 438 | } | 442 | } |
| 439 | | 443 | |
| 440 | zig_shl_sat_u(u8, uint8_t, 8) | 444 | zig_shl_sat_u(u8, uint8_t, 8) |
| 441 | zig_shl_sat_s(i8, int8_t, 7) | 445 | zig_shl_sat_s(i8, int8_t, 7) |
| 442 | zig_shl_sat_u(u16, uint16_t, 16) | 446 | zig_shl_sat_u(u16, uint16_t, 16) |
| 443 | zig_shl_sat_s(i16, int16_t, 15) | 447 | zig_shl_sat_s(i16, int16_t, 15) |
| 444 | zig_shl_sat_u(u32, uint32_t, 32) | 448 | zig_shl_sat_u(u32, uint32_t, 32) |