1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  *  linux/arch/arm/lib/findbit.S
4  *
5  *  Copyright (C) 1995-2000 Russell King
6  *
7  * 16th March 2001 - John Ripley <jripley@sonicblue.com>
8  *   Fixed so that "size" is an exclusive not an inclusive quantity.
9  *   All users of these functions expect exclusive sizes, and may
10  *   also call with zero size.
11  * Reworked by rmk.
12  */
13 #include <linux/linkage.h>
14 #include <asm/assembler.h>
15                 .text
16 
17 /*
18  * Purpose  : Find a 'zero' bit
19  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
20  */
21 ENTRY(_find_first_zero_bit_le)
22 		teq	r1, #0
23 		beq	3f
24 		mov	r2, #0
25 1:
26  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
27  THUMB(		lsr	r3, r2, #3		)
28  THUMB(		ldrb	r3, [r0, r3]		)
29 		eors	r3, r3, #0xff		@ invert bits
30 		bne	.L_found		@ any now set - found zero bit
31 		add	r2, r2, #8		@ next bit pointer
32 2:		cmp	r2, r1			@ any more?
33 		blo	1b
34 3:		mov	r0, r1			@ no free bits
35 		ret	lr
36 ENDPROC(_find_first_zero_bit_le)
37 
38 /*
39  * Purpose  : Find next 'zero' bit
40  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
41  */
42 ENTRY(_find_next_zero_bit_le)
43 		cmp	r2, r1
44 		bhs	3b
45 		ands	ip, r2, #7
46 		beq	1b			@ If new byte, goto old routine
47  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
48  THUMB(		lsr	r3, r2, #3		)
49  THUMB(		ldrb	r3, [r0, r3]		)
50 		eor	r3, r3, #0xff		@ now looking for a 1 bit
51 		movs	r3, r3, lsr ip		@ shift off unused bits
52 		bne	.L_found
53 		orr	r2, r2, #7		@ if zero, then no bits here
54 		add	r2, r2, #1		@ align bit pointer
55 		b	2b			@ loop for next bit
56 ENDPROC(_find_next_zero_bit_le)
57 
58 /*
59  * Purpose  : Find a 'one' bit
60  * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
61  */
62 ENTRY(_find_first_bit_le)
63 		teq	r1, #0
64 		beq	3f
65 		mov	r2, #0
66 1:
67  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
68  THUMB(		lsr	r3, r2, #3		)
69  THUMB(		ldrb	r3, [r0, r3]		)
70 		movs	r3, r3
71 		bne	.L_found		@ any now set - found zero bit
72 		add	r2, r2, #8		@ next bit pointer
73 2:		cmp	r2, r1			@ any more?
74 		blo	1b
75 3:		mov	r0, r1			@ no free bits
76 		ret	lr
77 ENDPROC(_find_first_bit_le)
78 
79 /*
80  * Purpose  : Find next 'one' bit
81  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
82  */
83 ENTRY(_find_next_bit_le)
84 		cmp	r2, r1
85 		bhs	3b
86 		ands	ip, r2, #7
87 		beq	1b			@ If new byte, goto old routine
88  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
89  THUMB(		lsr	r3, r2, #3		)
90  THUMB(		ldrb	r3, [r0, r3]		)
91 		movs	r3, r3, lsr ip		@ shift off unused bits
92 		bne	.L_found
93 		orr	r2, r2, #7		@ if zero, then no bits here
94 		add	r2, r2, #1		@ align bit pointer
95 		b	2b			@ loop for next bit
96 ENDPROC(_find_next_bit_le)
97 
98 #ifdef __ARMEB__
99 
100 ENTRY(_find_first_zero_bit_be)
101 		teq	r1, #0
102 		beq	3f
103 		mov	r2, #0
104 1:		eor	r3, r2, #0x18		@ big endian byte ordering
105  ARM(		ldrb	r3, [r0, r3, lsr #3]	)
106  THUMB(		lsr	r3, #3			)
107  THUMB(		ldrb	r3, [r0, r3]		)
108 		eors	r3, r3, #0xff		@ invert bits
109 		bne	.L_found		@ any now set - found zero bit
110 		add	r2, r2, #8		@ next bit pointer
111 2:		cmp	r2, r1			@ any more?
112 		blo	1b
113 3:		mov	r0, r1			@ no free bits
114 		ret	lr
115 ENDPROC(_find_first_zero_bit_be)
116 
117 ENTRY(_find_next_zero_bit_be)
118 		cmp	r2, r1
119 		bhs	3b
120 		ands	ip, r2, #7
121 		beq	1b			@ If new byte, goto old routine
122 		eor	r3, r2, #0x18		@ big endian byte ordering
123  ARM(		ldrb	r3, [r0, r3, lsr #3]	)
124  THUMB(		lsr	r3, #3			)
125  THUMB(		ldrb	r3, [r0, r3]		)
126 		eor	r3, r3, #0xff		@ now looking for a 1 bit
127 		movs	r3, r3, lsr ip		@ shift off unused bits
128 		bne	.L_found
129 		orr	r2, r2, #7		@ if zero, then no bits here
130 		add	r2, r2, #1		@ align bit pointer
131 		b	2b			@ loop for next bit
132 ENDPROC(_find_next_zero_bit_be)
133 
134 ENTRY(_find_first_bit_be)
135 		teq	r1, #0
136 		beq	3f
137 		mov	r2, #0
138 1:		eor	r3, r2, #0x18		@ big endian byte ordering
139  ARM(		ldrb	r3, [r0, r3, lsr #3]	)
140  THUMB(		lsr	r3, #3			)
141  THUMB(		ldrb	r3, [r0, r3]		)
142 		movs	r3, r3
143 		bne	.L_found		@ any now set - found zero bit
144 		add	r2, r2, #8		@ next bit pointer
145 2:		cmp	r2, r1			@ any more?
146 		blo	1b
147 3:		mov	r0, r1			@ no free bits
148 		ret	lr
149 ENDPROC(_find_first_bit_be)
150 
151 ENTRY(_find_next_bit_be)
152 		cmp	r2, r1
153 		bhs	3b
154 		ands	ip, r2, #7
155 		beq	1b			@ If new byte, goto old routine
156 		eor	r3, r2, #0x18		@ big endian byte ordering
157  ARM(		ldrb	r3, [r0, r3, lsr #3]	)
158  THUMB(		lsr	r3, #3			)
159  THUMB(		ldrb	r3, [r0, r3]		)
160 		movs	r3, r3, lsr ip		@ shift off unused bits
161 		bne	.L_found
162 		orr	r2, r2, #7		@ if zero, then no bits here
163 		add	r2, r2, #1		@ align bit pointer
164 		b	2b			@ loop for next bit
165 ENDPROC(_find_next_bit_be)
166 
167 #endif
168 
169 /*
170  * One or more bits in the LSB of r3 are assumed to be set.
171  */
172 .L_found:
173 #if __LINUX_ARM_ARCH__ >= 5
174 		rsb	r0, r3, #0
175 		and	r3, r3, r0
176 		clz	r3, r3
177 		rsb	r3, r3, #31
178 		add	r0, r2, r3
179 #else
180 		tst	r3, #0x0f
181 		addeq	r2, r2, #4
182 		movne	r3, r3, lsl #4
183 		tst	r3, #0x30
184 		addeq	r2, r2, #2
185 		movne	r3, r3, lsl #2
186 		tst	r3, #0x40
187 		addeq	r2, r2, #1
188 		mov	r0, r2
189 #endif
190 		cmp	r1, r0			@ Clamp to maxbit
191 		movlo	r0, r1
192 		ret	lr
193 
194