xref: /openbmc/linux/arch/arm/lib/findbit.S (revision ecba1060)
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                .text
19
20/*
21 * Purpose  : Find a 'zero' bit
22 * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
23 */
24ENTRY(_find_first_zero_bit_le)
25		teq	r1, #0
26		beq	3f
27		mov	r2, #0
281:		ldrb	r3, [r0, r2, lsr #3]
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
322:		cmp	r2, r1			@ any more?
33		blo	1b
343:		mov	r0, r1			@ no free bits
35		mov	pc, lr
36ENDPROC(_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 */
42ENTRY(_find_next_zero_bit_le)
43		teq	r1, #0
44		beq	3b
45		ands	ip, r2, #7
46		beq	1b			@ If new byte, goto old routine
47		ldrb	r3, [r0, r2, lsr #3]
48		eor	r3, r3, #0xff		@ now looking for a 1 bit
49		movs	r3, r3, lsr ip		@ shift off unused bits
50		bne	.L_found
51		orr	r2, r2, #7		@ if zero, then no bits here
52		add	r2, r2, #1		@ align bit pointer
53		b	2b			@ loop for next bit
54ENDPROC(_find_next_zero_bit_le)
55
56/*
57 * Purpose  : Find a 'one' bit
58 * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
59 */
60ENTRY(_find_first_bit_le)
61		teq	r1, #0
62		beq	3f
63		mov	r2, #0
641:		ldrb	r3, [r0, r2, lsr #3]
65		movs	r3, r3
66		bne	.L_found		@ any now set - found zero bit
67		add	r2, r2, #8		@ next bit pointer
682:		cmp	r2, r1			@ any more?
69		blo	1b
703:		mov	r0, r1			@ no free bits
71		mov	pc, lr
72ENDPROC(_find_first_bit_le)
73
74/*
75 * Purpose  : Find next 'one' bit
76 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
77 */
78ENTRY(_find_next_bit_le)
79		teq	r1, #0
80		beq	3b
81		ands	ip, r2, #7
82		beq	1b			@ If new byte, goto old routine
83		ldrb	r3, [r0, r2, lsr #3]
84		movs	r3, r3, lsr ip		@ shift off unused bits
85		bne	.L_found
86		orr	r2, r2, #7		@ if zero, then no bits here
87		add	r2, r2, #1		@ align bit pointer
88		b	2b			@ loop for next bit
89ENDPROC(_find_next_bit_le)
90
91#ifdef __ARMEB__
92
93ENTRY(_find_first_zero_bit_be)
94		teq	r1, #0
95		beq	3f
96		mov	r2, #0
971:		eor	r3, r2, #0x18		@ big endian byte ordering
98		ldrb	r3, [r0, r3, lsr #3]
99		eors	r3, r3, #0xff		@ invert bits
100		bne	.L_found		@ any now set - found zero bit
101		add	r2, r2, #8		@ next bit pointer
1022:		cmp	r2, r1			@ any more?
103		blo	1b
1043:		mov	r0, r1			@ no free bits
105		mov	pc, lr
106ENDPROC(_find_first_zero_bit_be)
107
108ENTRY(_find_next_zero_bit_be)
109		teq	r1, #0
110		beq	3b
111		ands	ip, r2, #7
112		beq	1b			@ If new byte, goto old routine
113		eor	r3, r2, #0x18		@ big endian byte ordering
114		ldrb	r3, [r0, r3, lsr #3]
115		eor	r3, r3, #0xff		@ now looking for a 1 bit
116		movs	r3, r3, lsr ip		@ shift off unused bits
117		bne	.L_found
118		orr	r2, r2, #7		@ if zero, then no bits here
119		add	r2, r2, #1		@ align bit pointer
120		b	2b			@ loop for next bit
121ENDPROC(_find_next_zero_bit_be)
122
123ENTRY(_find_first_bit_be)
124		teq	r1, #0
125		beq	3f
126		mov	r2, #0
1271:		eor	r3, r2, #0x18		@ big endian byte ordering
128		ldrb	r3, [r0, r3, lsr #3]
129		movs	r3, r3
130		bne	.L_found		@ any now set - found zero bit
131		add	r2, r2, #8		@ next bit pointer
1322:		cmp	r2, r1			@ any more?
133		blo	1b
1343:		mov	r0, r1			@ no free bits
135		mov	pc, lr
136ENDPROC(_find_first_bit_be)
137
138ENTRY(_find_next_bit_be)
139		teq	r1, #0
140		beq	3b
141		ands	ip, r2, #7
142		beq	1b			@ If new byte, goto old routine
143		eor	r3, r2, #0x18		@ big endian byte ordering
144		ldrb	r3, [r0, r3, lsr #3]
145		movs	r3, r3, lsr ip		@ shift off unused bits
146		bne	.L_found
147		orr	r2, r2, #7		@ if zero, then no bits here
148		add	r2, r2, #1		@ align bit pointer
149		b	2b			@ loop for next bit
150ENDPROC(_find_next_bit_be)
151
152#endif
153
154/*
155 * One or more bits in the LSB of r3 are assumed to be set.
156 */
157.L_found:
158#if __LINUX_ARM_ARCH__ >= 5
159		rsb	r1, r3, #0
160		and	r3, r3, r1
161		clz	r3, r3
162		rsb	r3, r3, #31
163		add	r0, r2, r3
164#else
165		tst	r3, #0x0f
166		addeq	r2, r2, #4
167		movne	r3, r3, lsl #4
168		tst	r3, #0x30
169		addeq	r2, r2, #2
170		movne	r3, r3, lsl #2
171		tst	r3, #0x40
172		addeq	r2, r2, #1
173		mov	r0, r2
174#endif
175		mov	pc, lr
176
177