diff options
author | Alessandro Gatti <a.gatti@frob.it> | 2024-08-22 00:48:55 +0200 |
---|---|---|
committer | Alessandro Gatti <a.gatti@frob.it> | 2025-01-01 10:44:53 +0100 |
commit | 3044233ea3726e9d8727d8f6a76f32c48e6fae5e (patch) | |
tree | d8fc0c7ddf3845917b644f69903b36e4b76705fe /py | |
parent | a5270c84cfdab6136d0dd4e63d41007f9a37b108 (diff) | |
download | micropython-3044233ea3726e9d8727d8f6a76f32c48e6fae5e.tar.gz micropython-3044233ea3726e9d8727d8f6a76f32c48e6fae5e.zip |
py/misc: Add a popcount(uint32_t) implementation.
This makes the existing popcount(uint32_t) implementation found in the
RV32 emitter available to the rest of the codebase. This version of
popcount will use intrinsic or builtin implementations if they are
available, falling back to a generic implementation if that is not the
case.
Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
Diffstat (limited to 'py')
-rw-r--r-- | py/asmrv32.c | 24 | ||||
-rw-r--r-- | py/misc.h | 17 |
2 files changed, 19 insertions, 22 deletions
diff --git a/py/asmrv32.c b/py/asmrv32.c index 3f3395842e..6aa3ec1654 100644 --- a/py/asmrv32.c +++ b/py/asmrv32.c @@ -29,6 +29,7 @@ #include <string.h> #include "py/emit.h" +#include "py/misc.h" #include "py/mpconfig.h" // wrapper around everything in this file @@ -43,27 +44,6 @@ #define DEBUG_printf(...) (void)0 #endif -#ifndef MP_POPCOUNT -#ifdef _MSC_VER -#include <intrin.h> -#define MP_POPCOUNT __popcnt -#else -#if defined __has_builtin -#if __has_builtin(__builtin_popcount) -#define MP_POPCOUNT __builtin_popcount -#endif -#else -static uint32_t fallback_popcount(uint32_t value) { - value = value - ((value >> 1) & 0x55555555); - value = (value & 0x33333333) + ((value >> 2) & 0x33333333); - value = (value + (value >> 4)) & 0x0F0F0F0F; - return value * 0x01010101; -} -#define MP_POPCOUNT fallback_popcount -#endif -#endif -#endif - #define INTERNAL_TEMPORARY ASM_RV32_REG_S0 #define AVAILABLE_REGISTERS_COUNT 32 @@ -249,7 +229,7 @@ static void adjust_stack(asm_rv32_t *state, mp_int_t stack_size) { // stack to hold all the tainted registers and an arbitrary amount of space // for locals. static void emit_function_prologue(asm_rv32_t *state, mp_uint_t registers) { - mp_uint_t registers_count = MP_POPCOUNT(registers); + mp_uint_t registers_count = mp_popcount(registers); state->stack_size = (registers_count + state->locals_count) * sizeof(uint32_t); mp_uint_t old_saved_registers_mask = state->saved_registers_mask; // Move stack pointer up. @@ -370,12 +370,29 @@ static inline uint32_t mp_ctz(uint32_t x) { static inline bool mp_check(bool value) { return value; } + +static inline uint32_t mp_popcount(uint32_t x) { + return __popcnt(x); +} #else #define mp_clz(x) __builtin_clz(x) #define mp_clzl(x) __builtin_clzl(x) #define mp_clzll(x) __builtin_clzll(x) #define mp_ctz(x) __builtin_ctz(x) #define mp_check(x) (x) +#if defined __has_builtin +#if __has_builtin(__builtin_popcount) +#define mp_popcount(x) __builtin_popcount(x) +#endif +#endif +#if !defined(mp_popcount) +static inline uint32_t mp_popcount(uint32_t x) { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + return x * 0x01010101; +} +#endif #endif // mp_int_t can be larger than long, i.e. Windows 64-bit, nan-box variants |