1/* $NetBSD: bitops.h,v 1.11 2015/10/13 00:42:59 riastradh Exp $ */
2
3/*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#ifndef _LINUX_BITOPS_H_
33#define _LINUX_BITOPS_H_
34
35#include <sys/cdefs.h>
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/atomic.h>
39#include <sys/bitops.h>
40
41#include <machine/limits.h>
42
43#include <lib/libkern/libkern.h>
44
45/*
46 * Linux __ffs/__ffs64 is zero-based; zero input is undefined. Our
47 * ffs/ffs64 is one-based; zero input yields zero.
48 */
49static inline unsigned long
50__ffs(unsigned long x)
51{
52
53 KASSERT(x != 0);
54 return ffs64(x) - 1;
55}
56
57static inline unsigned long
58__ffs64(uint64_t x)
59{
60
61 KASSERT(x != 0);
62 return ffs64(x) - 1;
63}
64
65static inline unsigned int
66hweight16(uint16_t n)
67{
68 return popcount32(n);
69}
70
71static inline unsigned int
72hweight32(uint16_t n)
73{
74 return popcount32(n);
75}
76
77/*
78 * XXX Don't define BITS_PER_LONG as sizeof(unsigned long)*CHAR_BIT
79 * because that won't work in preprocessor conditionals, where it often
80 * turns up.
81 */
82
83#define BITS_TO_LONGS(n) \
84 roundup2((n), (sizeof(unsigned long) * CHAR_BIT))
85
86#define BIT(n) ((uintmax_t)1 << (n))
87
88static inline int
89test_bit(unsigned int n, const volatile unsigned long *p)
90{
91 const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
92
93 return ((p[n / units] & (1UL << (n % units))) != 0);
94}
95
96static inline void
97__set_bit(unsigned int n, volatile unsigned long *p)
98{
99 const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
100
101 p[n / units] |= (1UL << (n % units));
102}
103
104static inline void
105__clear_bit(unsigned int n, volatile unsigned long *p)
106{
107 const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
108
109 p[n / units] &= ~(1UL << (n % units));
110}
111
112static inline void
113__change_bit(unsigned int n, volatile unsigned long *p)
114{
115 const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
116
117 p[n / units] ^= (1UL << (n % units));
118}
119
120static inline unsigned long
121__test_and_set_bit(unsigned int bit, volatile unsigned long *ptr)
122{
123 const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
124 volatile unsigned long *const p = &ptr[bit / units];
125 const unsigned long mask = (1UL << (bit % units));
126 unsigned long v;
127
128 v = *p;
129 *p |= mask;
130
131 return ((v & mask) != 0);
132}
133
134static inline unsigned long
135__test_and_clear_bit(unsigned int bit, volatile unsigned long *ptr)
136{
137 const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
138 volatile unsigned long *const p = &ptr[bit / units];
139 const unsigned long mask = (1UL << (bit % units));
140 unsigned long v;
141
142 v = *p;
143 *p &= ~mask;
144
145 return ((v & mask) != 0);
146}
147
148static inline unsigned long
149__test_and_change_bit(unsigned int bit, volatile unsigned long *ptr)
150{
151 const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
152 volatile unsigned long *const p = &ptr[bit / units];
153 const unsigned long mask = (1UL << (bit % units));
154 unsigned long v;
155
156 v = *p;
157 *p ^= mask;
158
159 return ((v & mask) != 0);
160}
161
162static inline unsigned long
163find_first_zero_bit(const unsigned long *ptr, unsigned long nbits)
164{
165 const size_t bpl = (CHAR_BIT * sizeof(*ptr));
166 const unsigned long *p;
167 unsigned long result = 0;
168
169 for (p = ptr; bpl < nbits; nbits -= bpl, p++, result += bpl) {
170 if (~*p)
171 break;
172 }
173
174 result += ffs(~*p | (~0UL << MIN(nbits, bpl)));
175 return result;
176}
177
178static inline unsigned
179hweight8(unsigned w)
180{
181
182 return popcount(w & 0xff);
183}
184
185#endif /* _LINUX_BITOPS_H_ */
186