summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/math_util.c40
-rw-r--r--include/math_util.h10
2 files changed, 50 insertions, 0 deletions
diff --git a/common/math_util.c b/common/math_util.c
index 8e07b678a5..52b0879626 100644
--- a/common/math_util.c
+++ b/common/math_util.c
@@ -293,3 +293,43 @@ int round_divide(int64_t dividend, int divisor)
(dividend - divisor / 2) / divisor :
(dividend + divisor / 2) / divisor;
}
+
+#if ULONG_MAX == 0xFFFFFFFFUL
+/*
+ * 32 bit processor
+ *
+ * Some 32 bit processors do not include a 64 bit shift
+ * operation. So fall back to 32 bit operations on a
+ * union.
+ */
+uint64_t bitmask_uint64(int offset)
+{
+ union mask64_t {
+ struct {
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ uint32_t lo;
+ uint32_t hi;
+#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ uint32_t hi;
+ uint32_t lo;
+#endif
+ };
+ uint64_t val;
+ } mask;
+
+ /* Clear out the mask */
+ mask.val = 0;
+
+ /*
+ * If the shift is out of range the result should
+ * remain 0, otherwise perform the shift
+ */
+ if (offset >= 0 && offset < 64) {
+ if (offset < 32)
+ mask.lo = BIT(offset);
+ else
+ mask.hi = BIT(offset - 32);
+ }
+ return mask.val;
+}
+#endif
diff --git a/include/math_util.h b/include/math_util.h
index b78523de54..9ee075839e 100644
--- a/include/math_util.h
+++ b/include/math_util.h
@@ -9,6 +9,7 @@
#define __CROS_EC_MATH_UTIL_H
#include <stdint.h>
+#include "limits.h"
#ifdef CONFIG_FPU
typedef float fp_t;
@@ -230,4 +231,13 @@ void rotate_inv(const intv3_t v, const mat33_fp_t R, intv3_t res);
*/
int round_divide(int64_t dividend, int divisor);
+/**
+ * Create a 64 bit bitmask of 2^offset
+ */
+#if ULONG_MAX == 0xFFFFFFFFUL
+uint64_t bitmask_uint64(int offset);
+#else
+#define bitmask_uint64(o) ((uint64_t)1 << (o))
+#endif
+
#endif /* __CROS_EC_MATH_UTIL_H */