14d7988dPaul Dagnelie/*
24d7988dPaul Dagnelie * CDDL HEADER START
34d7988dPaul Dagnelie *
44d7988dPaul Dagnelie * The contents of this file are subject to the terms of the
54d7988dPaul Dagnelie * Common Development and Distribution License (the "License").
64d7988dPaul Dagnelie * You may not use this file except in compliance with the License.
74d7988dPaul Dagnelie *
84d7988dPaul Dagnelie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d7988dPaul Dagnelie * or http://www.opensolaris.org/os/licensing.
104d7988dPaul Dagnelie * See the License for the specific language governing permissions
114d7988dPaul Dagnelie * and limitations under the License.
124d7988dPaul Dagnelie *
134d7988dPaul Dagnelie * When distributing Covered Code, include this CDDL HEADER in each
144d7988dPaul Dagnelie * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d7988dPaul Dagnelie * If applicable, add the following below this CDDL HEADER, with the
164d7988dPaul Dagnelie * fields enclosed by brackets "[]" replaced with your own identifying
174d7988dPaul Dagnelie * information: Portions Copyright [yyyy] [name of copyright owner]
184d7988dPaul Dagnelie *
194d7988dPaul Dagnelie * CDDL HEADER END
204d7988dPaul Dagnelie */
214d7988dPaul Dagnelie/*
224d7988dPaul Dagnelie * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
234d7988dPaul Dagnelie * Copyright (c) 2011, 2019 by Delphix. All rights reserved.
244d7988dPaul Dagnelie * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
254d7988dPaul Dagnelie * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
264d7988dPaul Dagnelie * Copyright 2013 Saso Kiselkov. All rights reserved.
274d7988dPaul Dagnelie * Copyright (c) 2014 Integros [integros.com]
284d7988dPaul Dagnelie * Copyright 2017 Joyent, Inc.
294d7988dPaul Dagnelie * Copyright (c) 2017 Datto Inc.
304d7988dPaul Dagnelie */
314d7988dPaul Dagnelie
324d7988dPaul Dagnelie#ifndef _SYS_BITOPS_H
334d7988dPaul Dagnelie#define	_SYS_BITOPS_H
344d7988dPaul Dagnelie
354d7988dPaul Dagnelie#include <sys/zfs_context.h>
364d7988dPaul Dagnelie
374d7988dPaul Dagnelie#ifdef	__cplusplus
384d7988dPaul Dagnelieextern "C" {
394d7988dPaul Dagnelie#endif
404d7988dPaul Dagnelie
414d7988dPaul Dagnelie/*
424d7988dPaul Dagnelie * General-purpose 32-bit and 64-bit bitfield encodings.
434d7988dPaul Dagnelie */
444d7988dPaul Dagnelie#define	BF32_DECODE(x, low, len)	P2PHASE((x) >> (low), 1U << (len))
454d7988dPaul Dagnelie#define	BF64_DECODE(x, low, len)	P2PHASE((x) >> (low), 1ULL << (len))
464d7988dPaul Dagnelie#define	BF32_ENCODE(x, low, len)	(P2PHASE((x), 1U << (len)) << (low))
474d7988dPaul Dagnelie#define	BF64_ENCODE(x, low, len)	(P2PHASE((x), 1ULL << (len)) << (low))
484d7988dPaul Dagnelie
494d7988dPaul Dagnelie#define	BF32_GET(x, low, len)		BF32_DECODE(x, low, len)
504d7988dPaul Dagnelie#define	BF64_GET(x, low, len)		BF64_DECODE(x, low, len)
514d7988dPaul Dagnelie
524d7988dPaul Dagnelie#define	BF32_SET(x, low, len, val) do { \
534d7988dPaul Dagnelie	ASSERT3U(val, <, 1U << (len)); \
544d7988dPaul Dagnelie	ASSERT3U(low + len, <=, 32); \
554d7988dPaul Dagnelie	(x) ^= BF32_ENCODE((x >> low) ^ (val), low, len); \
564d7988dPaul Dagnelie_NOTE(CONSTCOND) } while (0)
574d7988dPaul Dagnelie
584d7988dPaul Dagnelie#define	BF64_SET(x, low, len, val) do { \
594d7988dPaul Dagnelie	ASSERT3U(val, <, 1ULL << (len)); \
604d7988dPaul Dagnelie	ASSERT3U(low + len, <=, 64); \
614d7988dPaul Dagnelie	((x) ^= BF64_ENCODE((x >> low) ^ (val), low, len)); \
624d7988dPaul Dagnelie_NOTE(CONSTCOND) } while (0)
634d7988dPaul Dagnelie
644d7988dPaul Dagnelie#define	BF32_GET_SB(x, low, len, shift, bias)	\
654d7988dPaul Dagnelie	((BF32_GET(x, low, len) + (bias)) << (shift))
664d7988dPaul Dagnelie#define	BF64_GET_SB(x, low, len, shift, bias)	\
674d7988dPaul Dagnelie	((BF64_GET(x, low, len) + (bias)) << (shift))
684d7988dPaul Dagnelie
694d7988dPaul Dagnelie/*
704d7988dPaul Dagnelie * We use ASSERT3U instead of ASSERT in these macros to prevent a lint error in
714d7988dPaul Dagnelie * the case where val is a constant.  We can't fix ASSERT because it's used as
724d7988dPaul Dagnelie * an expression in several places in the kernel; as a result, changing it to
734d7988dPaul Dagnelie * the do{} while() syntax to allow us to _NOTE the CONSTCOND is not an option.
744d7988dPaul Dagnelie */
754d7988dPaul Dagnelie#define	BF32_SET_SB(x, low, len, shift, bias, val) do { \
764d7988dPaul Dagnelie	ASSERT3U(IS_P2ALIGNED(val, 1U << shift), !=, B_FALSE); \
774d7988dPaul Dagnelie	ASSERT3S((val) >> (shift), >=, bias); \
784d7988dPaul Dagnelie	BF32_SET(x, low, len, ((val) >> (shift)) - (bias)); \
794d7988dPaul Dagnelie_NOTE(CONSTCOND) } while (0)
804d7988dPaul Dagnelie#define	BF64_SET_SB(x, low, len, shift, bias, val) do { \
814d7988dPaul Dagnelie	ASSERT3U(IS_P2ALIGNED(val, 1ULL << shift), !=, B_FALSE); \
824d7988dPaul Dagnelie	ASSERT3S((val) >> (shift), >=, bias); \
834d7988dPaul Dagnelie	BF64_SET(x, low, len, ((val) >> (shift)) - (bias)); \
844d7988dPaul Dagnelie_NOTE(CONSTCOND) } while (0)
854d7988dPaul Dagnelie
864d7988dPaul Dagnelie#ifdef	__cplusplus
874d7988dPaul Dagnelie}
884d7988dPaul Dagnelie#endif
894d7988dPaul Dagnelie
904d7988dPaul Dagnelie#endif /* _SYS_BITOPS_H */