xref: /openbmc/linux/arch/arm/lib/findbit.S (revision f3a8b664)
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 <linux/linkage.h>
17#include <asm/assembler.h>
18#include <asm/export.h>
19                .text
20
21/*
22 * Purpose  : Find a 'zero' bit
23 * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
24 */
25ENTRY(_find_first_zero_bit_le)
26		teq	r1, #0
27		beq	3f
28		mov	r2, #0
291:
30 ARM(		ldrb	r3, [r0, r2, lsr #3]	)
31 THUMB(		lsr	r3, r2, #3		)
32 THUMB(		ldrb	r3, [r0, r3]		)
33		eors	r3, r3, #0xff		@ invert bits
34		bne	.L_found		@ any now set - found zero bit
35		add	r2, r2, #8		@ next bit pointer
362:		cmp	r2, r1			@ any more?
37		blo	1b
383:		mov	r0, r1			@ no free bits
39		ret	lr
40ENDPROC(_find_first_zero_bit_le)
41EXPORT_SYMBOL(_find_first_zero_bit_le)
42
43/*
44 * Purpose  : Find next 'zero' bit
45 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
46 */
47ENTRY(_find_next_zero_bit_le)
48		teq	r1, #0
49		beq	3b
50		ands	ip, r2, #7
51		beq	1b			@ If new byte, goto old routine
52 ARM(		ldrb	r3, [r0, r2, lsr #3]	)
53 THUMB(		lsr	r3, r2, #3		)
54 THUMB(		ldrb	r3, [r0, r3]		)
55		eor	r3, r3, #0xff		@ now looking for a 1 bit
56		movs	r3, r3, lsr ip		@ shift off unused bits
57		bne	.L_found
58		orr	r2, r2, #7		@ if zero, then no bits here
59		add	r2, r2, #1		@ align bit pointer
60		b	2b			@ loop for next bit
61ENDPROC(_find_next_zero_bit_le)
62EXPORT_SYMBOL(_find_next_zero_bit_le)
63
64/*
65 * Purpose  : Find a 'one' bit
66 * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
67 */
68ENTRY(_find_first_bit_le)
69		teq	r1, #0
70		beq	3f
71		mov	r2, #0
721:
73 ARM(		ldrb	r3, [r0, r2, lsr #3]	)
74 THUMB(		lsr	r3, r2, #3		)
75 THUMB(		ldrb	r3, [r0, r3]		)
76		movs	r3, r3
77		bne	.L_found		@ any now set - found zero bit
78		add	r2, r2, #8		@ next bit pointer
792:		cmp	r2, r1			@ any more?
80		blo	1b
813:		mov	r0, r1			@ no free bits
82		ret	lr
83ENDPROC(_find_first_bit_le)
84EXPORT_SYMBOL(_find_first_bit_le)
85
86/*
87 * Purpose  : Find next 'one' bit
88 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
89 */
90ENTRY(_find_next_bit_le)
91		teq	r1, #0
92		beq	3b
93		ands	ip, r2, #7
94		beq	1b			@ If new byte, goto old routine
95 ARM(		ldrb	r3, [r0, r2, lsr #3]	)
96 THUMB(		lsr	r3, r2, #3		)
97 THUMB(		ldrb	r3, [r0, r3]		)
98		movs	r3, r3, lsr ip		@ shift off unused bits
99		bne	.L_found
100		orr	r2, r2, #7		@ if zero, then no bits here
101		add	r2, r2, #1		@ align bit pointer
102		b	2b			@ loop for next bit
103ENDPROC(_find_next_bit_le)
104EXPORT_SYMBOL(_find_next_bit_le)
105
106#ifdef __ARMEB__
107
108ENTRY(_find_first_zero_bit_be)
109		teq	r1, #0
110		beq	3f
111		mov	r2, #0
1121:		eor	r3, r2, #0x18		@ big endian byte ordering
113 ARM(		ldrb	r3, [r0, r3, lsr #3]	)
114 THUMB(		lsr	r3, #3			)
115 THUMB(		ldrb	r3, [r0, r3]		)
116		eors	r3, r3, #0xff		@ invert bits
117		bne	.L_found		@ any now set - found zero bit
118		add	r2, r2, #8		@ next bit pointer
1192:		cmp	r2, r1			@ any more?
120		blo	1b
1213:		mov	r0, r1			@ no free bits
122		ret	lr
123ENDPROC(_find_first_zero_bit_be)
124EXPORT_SYMBOL(_find_first_zero_bit_be)
125
126ENTRY(_find_next_zero_bit_be)
127		teq	r1, #0
128		beq	3b
129		ands	ip, r2, #7
130		beq	1b			@ If new byte, goto old routine
131		eor	r3, r2, #0x18		@ big endian byte ordering
132 ARM(		ldrb	r3, [r0, r3, lsr #3]	)
133 THUMB(		lsr	r3, #3			)
134 THUMB(		ldrb	r3, [r0, r3]		)
135		eor	r3, r3, #0xff		@ now looking for a 1 bit
136		movs	r3, r3, lsr ip		@ shift off unused bits
137		bne	.L_found
138		orr	r2, r2, #7		@ if zero, then no bits here
139		add	r2, r2, #1		@ align bit pointer
140		b	2b			@ loop for next bit
141ENDPROC(_find_next_zero_bit_be)
142EXPORT_SYMBOL(_find_next_zero_bit_be)
143
144ENTRY(_find_first_bit_be)
145		teq	r1, #0
146		beq	3f
147		mov	r2, #0
1481:		eor	r3, r2, #0x18		@ big endian byte ordering
149 ARM(		ldrb	r3, [r0, r3, lsr #3]	)
150 THUMB(		lsr	r3, #3			)
151 THUMB(		ldrb	r3, [r0, r3]		)
152		movs	r3, r3
153		bne	.L_found		@ any now set - found zero bit
154		add	r2, r2, #8		@ next bit pointer
1552:		cmp	r2, r1			@ any more?
156		blo	1b
1573:		mov	r0, r1			@ no free bits
158		ret	lr
159ENDPROC(_find_first_bit_be)
160EXPORT_SYMBOL(_find_first_bit_be)
161
162ENTRY(_find_next_bit_be)
163		teq	r1, #0
164		beq	3b
165		ands	ip, r2, #7
166		beq	1b			@ If new byte, goto old routine
167		eor	r3, r2, #0x18		@ big endian byte ordering
168 ARM(		ldrb	r3, [r0, r3, lsr #3]	)
169 THUMB(		lsr	r3, #3			)
170 THUMB(		ldrb	r3, [r0, r3]		)
171		movs	r3, r3, lsr ip		@ shift off unused bits
172		bne	.L_found
173		orr	r2, r2, #7		@ if zero, then no bits here
174		add	r2, r2, #1		@ align bit pointer
175		b	2b			@ loop for next bit
176ENDPROC(_find_next_bit_be)
177EXPORT_SYMBOL(_find_next_bit_be)
178
179#endif
180
181/*
182 * One or more bits in the LSB of r3 are assumed to be set.
183 */
184.L_found:
185#if __LINUX_ARM_ARCH__ >= 5
186		rsb	r0, r3, #0
187		and	r3, r3, r0
188		clz	r3, r3
189		rsb	r3, r3, #31
190		add	r0, r2, r3
191#else
192		tst	r3, #0x0f
193		addeq	r2, r2, #4
194		movne	r3, r3, lsl #4
195		tst	r3, #0x30
196		addeq	r2, r2, #2
197		movne	r3, r3, lsl #2
198		tst	r3, #0x40
199		addeq	r2, r2, #1
200		mov	r0, r2
201#endif
202		cmp	r1, r0			@ Clamp to maxbit
203		movlo	r0, r1
204		ret	lr
205
206