1/*
2 * Copyright 1995, Russell King.
3 * Various bits and pieces copyrights include:
4 * Linus Torvalds (test_bit).
5 *
6 * Copyright (C) 2017 Andes Technology Corporation
7 * Rick Chen, Andes Technology Corporation <rick@andestech.com>
8 *
9 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
10 *
11 * Please note that the code in this file should never be included
12 * from user space.  Many of these are not implemented in assembler
13 * since they would be too costly.  Also, they require priviledged
14 * instructions (which are not available from user mode) to ensure
15 * that they are atomic.
16 */
17
18#ifndef __ASM_RISCV_BITOPS_H
19#define __ASM_RISCV_BITOPS_H
20
21#ifdef __KERNEL__
22
23#include <asm/system.h>
24#include <asm-generic/bitops/fls.h>
25#include <asm-generic/bitops/__fls.h>
26#include <asm-generic/bitops/fls64.h>
27#include <asm-generic/bitops/__ffs.h>
28
29#define smp_mb__before_clear_bit()	do { } while (0)
30#define smp_mb__after_clear_bit()	do { } while (0)
31
32/*
33 * Function prototypes to keep gcc -Wall happy.
34 */
35static inline void __set_bit(int nr, void *addr)
36{
37	int *a = (int *)addr;
38	int mask;
39
40	a += nr >> 5;
41	mask = 1 << (nr & 0x1f);
42	*a |= mask;
43}
44
45#define PLATFORM__SET_BIT
46
47static inline void __clear_bit(int nr, void *addr)
48{
49	int *a = (int *)addr;
50	int mask;
51
52	a += nr >> 5;
53	mask = 1 << (nr & 0x1f);
54	*a &= ~mask;
55}
56
57#define PLATFORM__CLEAR_BIT
58
59static inline void __change_bit(int nr, void *addr)
60{
61	int mask;
62	unsigned long *ADDR = (unsigned long *)addr;
63
64	ADDR += nr >> 5;
65	mask = 1 << (nr & 31);
66	*ADDR ^= mask;
67}
68
69static inline int __test_and_set_bit(int nr, void *addr)
70{
71	int mask, retval;
72	unsigned int *a = (unsigned int *)addr;
73
74	a += nr >> 5;
75	mask = 1 << (nr & 0x1f);
76	retval = (mask & *a) != 0;
77	*a |= mask;
78	return retval;
79}
80
81static inline int __test_and_clear_bit(int nr, void *addr)
82{
83	int mask, retval;
84	unsigned int *a = (unsigned int *)addr;
85
86	a += nr >> 5;
87	mask = 1 << (nr & 0x1f);
88	retval = (mask & *a) != 0;
89	*a &= ~mask;
90	return retval;
91}
92
93static inline int __test_and_change_bit(int nr, void *addr)
94{
95	int mask, retval;
96	unsigned int *a = (unsigned int *)addr;
97
98	a += nr >> 5;
99	mask = 1 << (nr & 0x1f);
100	retval = (mask & *a) != 0;
101	*a ^= mask;
102	return retval;
103}
104
105/*
106 * This routine doesn't need to be atomic.
107 */
108static inline int test_bit(int nr, const void *addr)
109{
110	return ((unsigned char *)addr)[nr >> 3] & (1U << (nr & 7));
111}
112
113/*
114 * ffz = Find First Zero in word. Undefined if no zero exists,
115 * so code should check against ~0UL first..
116 */
117static inline unsigned long ffz(unsigned long word)
118{
119	int k;
120
121	word = ~word;
122	k = 31;
123	if (word & 0x0000ffff) {
124		k -= 16; word <<= 16;
125	}
126	if (word & 0x00ff0000) {
127		k -= 8;  word <<= 8;
128	}
129	if (word & 0x0f000000) {
130		k -= 4;  word <<= 4;
131	}
132	if (word & 0x30000000) {
133		k -= 2;  word <<= 2;
134	}
135	if (word & 0x40000000)
136		k -= 1;
137
138	return k;
139}
140
141/*
142 * ffs: find first bit set. This is defined the same way as
143 * the libc and compiler builtin ffs routines, therefore
144 * differs in spirit from the above ffz (man ffs).
145 */
146
147/*
148 * redefined in include/linux/bitops.h
149 * #define ffs(x) generic_ffs(x)
150 */
151
152/*
153 * hweightN: returns the hamming weight (i.e. the number
154 * of bits set) of a N-bit word
155 */
156
157#define hweight32(x) generic_hweight32(x)
158#define hweight16(x) generic_hweight16(x)
159#define hweight8(x) generic_hweight8(x)
160
161#define test_and_set_bit		__test_and_set_bit
162#define test_and_clear_bit		__test_and_clear_bit
163
164#define ext2_set_bit			test_and_set_bit
165#define ext2_clear_bit			test_and_clear_bit
166#define ext2_test_bit			test_bit
167#define ext2_find_first_zero_bit	find_first_zero_bit
168#define ext2_find_next_zero_bit		find_next_zero_bit
169
170/* Bitmap functions for the minix filesystem. */
171#define minix_test_and_set_bit(nr, addr)	test_and_set_bit(nr, addr)
172#define minix_set_bit(nr, addr)			set_bit(nr, addr)
173#define minix_test_and_clear_bit(nr, addr)	test_and_clear_bit(nr, addr)
174#define minix_test_bit(nr, addr)		test_bit(nr, addr)
175#define minix_find_first_zero_bit(addr, size)	find_first_zero_bit(addr, size)
176
177#endif /* __KERNEL__ */
178
179#endif /* __ASM_RISCV_BITOPS_H */
180