summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorAlessandro Gatti <a.gatti@frob.it>2024-08-22 00:48:55 +0200
committerAlessandro Gatti <a.gatti@frob.it>2025-01-01 10:44:53 +0100
commit3044233ea3726e9d8727d8f6a76f32c48e6fae5e (patch)
treed8fc0c7ddf3845917b644f69903b36e4b76705fe /py
parenta5270c84cfdab6136d0dd4e63d41007f9a37b108 (diff)
downloadmicropython-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.c24
-rw-r--r--py/misc.h17
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.
diff --git a/py/misc.h b/py/misc.h
index 2629d0c46c..e05fbe61a9 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -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