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