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