summaryrefslogtreecommitdiff
path: root/include/linux/bitfield.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/bitfield.h')
-rw-r--r--include/linux/bitfield.h18
1 files changed, 17 insertions, 1 deletions
diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
index 54aeeef1f0ec..14f86e455a67 100644
--- a/include/linux/bitfield.h
+++ b/include/linux/bitfield.h
@@ -44,7 +44,7 @@
* FIELD_MODIFY(REG_FIELD_C, &reg, c);
*/
-#define __bf_shf(x) (__builtin_ffsll(x) - 1)
+#define __bf_shf __builtin_ctzll
#define __scalar_type_to_unsigned_cases(type) \
unsigned type: (unsigned type)0, \
@@ -179,6 +179,22 @@
})
/**
+ * FIELD_GET_SIGNED() - extract a signed bitfield element
+ * @mask: shifted mask defining the field's length and position
+ * @reg: value of entire bitfield
+ *
+ * Returns the sign-extended field specified by @_mask from the
+ * bitfield passed in as @reg by masking and shifting it down.
+ */
+#define FIELD_GET_SIGNED(mask, reg) \
+ ({ \
+ __BF_FIELD_CHECK(mask, reg, 0U, "FIELD_GET_SIGNED: "); \
+ ((__signed_scalar_typeof(mask)) \
+ (((long long)(reg) << __builtin_clzll(mask)) >> \
+ (__builtin_clzll(mask) + __builtin_ctzll(mask)))); \
+ })
+
+/**
* FIELD_MODIFY() - modify a bitfield element
* @_mask: shifted mask defining the field's length and position
* @_reg_p: pointer to the memory that should be updated