1/*
2 * Copyright (C) 2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/linkage.h>
9
10	.text
11	/*
12	 * unsigned long find_first_zero_bit(const unsigned long *addr,
13	 *				     unsigned long size)
14	 */
15ENTRY(find_first_zero_bit)
16	cp.w	r11, 0
17	reteq	r11
18	mov	r9, r11
191:	ld.w	r8, r12[0]
20	com	r8
21	brne	.L_found
22	sub	r12, -4
23	sub	r9, 32
24	brgt	1b
25	retal	r11
26
27	/*
28	 * unsigned long find_next_zero_bit(const unsigned long *addr,
29	 *				    unsigned long size,
30	 *				    unsigned long offset)
31	 */
32ENTRY(find_next_zero_bit)
33	lsr	r8, r10, 5
34	sub	r9, r11, r10
35	retle	r11
36
37	lsl	r8, 2
38	add	r12, r8
39	andl	r10, 31, COH
40	breq	1f
41
42	/* offset is not word-aligned. Handle the first (32 - r10) bits */
43	ld.w	r8, r12[0]
44	com	r8
45	sub	r12, -4
46	lsr	r8, r8, r10
47	brne	.L_found
48
49	/* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
50	add	r9, r10
51	sub	r9, 32
52	retle	r11
53
54	/* Main loop. offset must be word-aligned */
551:	ld.w	r8, r12[0]
56	com	r8
57	brne	.L_found
58	sub	r12, -4
59	sub	r9, 32
60	brgt	1b
61	retal	r11
62
63	/* Common return path for when a bit is actually found. */
64.L_found:
65	brev	r8
66	clz	r10, r8
67	rsub	r9, r11
68	add	r10, r9
69
70	/* XXX: If we don't have to return exactly "size" when the bit
71	   is not found, we may drop this "min" thing */
72	min	r12, r11, r10
73	retal	r12
74
75	/*
76	 * unsigned long find_first_bit(const unsigned long *addr,
77	 *				unsigned long size)
78	 */
79ENTRY(find_first_bit)
80	cp.w	r11, 0
81	reteq	r11
82	mov	r9, r11
831:	ld.w	r8, r12[0]
84	cp.w	r8, 0
85	brne	.L_found
86	sub	r12, -4
87	sub	r9, 32
88	brgt	1b
89	retal	r11
90
91	/*
92	 * unsigned long find_next_bit(const unsigned long *addr,
93	 *			       unsigned long size,
94	 *			       unsigned long offset)
95	 */
96ENTRY(find_next_bit)
97	lsr	r8, r10, 5
98	sub	r9, r11, r10
99	retle	r11
100
101	lsl	r8, 2
102	add	r12, r8
103	andl	r10, 31, COH
104	breq	1f
105
106	/* offset is not word-aligned. Handle the first (32 - r10) bits */
107	ld.w	r8, r12[0]
108	sub	r12, -4
109	lsr	r8, r8, r10
110	brne	.L_found
111
112	/* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
113	add	r9, r10
114	sub	r9, 32
115	retle	r11
116
117	/* Main loop. offset must be word-aligned */
1181:	ld.w	r8, r12[0]
119	cp.w	r8, 0
120	brne	.L_found
121	sub	r12, -4
122	sub	r9, 32
123	brgt	1b
124	retal	r11
125
126ENTRY(find_next_bit_le)
127	lsr	r8, r10, 5
128	sub	r9, r11, r10
129	retle	r11
130
131	lsl	r8, 2
132	add	r12, r8
133	andl	r10, 31, COH
134	breq	1f
135
136	/* offset is not word-aligned. Handle the first (32 - r10) bits */
137	ldswp.w	r8, r12[0]
138	sub	r12, -4
139	lsr	r8, r8, r10
140	brne	.L_found
141
142	/* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
143	add	r9, r10
144	sub	r9, 32
145	retle	r11
146
147	/* Main loop. offset must be word-aligned */
1481:	ldswp.w	r8, r12[0]
149	cp.w	r8, 0
150	brne	.L_found
151	sub	r12, -4
152	sub	r9, 32
153	brgt	1b
154	retal	r11
155
156ENTRY(find_next_zero_bit_le)
157	lsr	r8, r10, 5
158	sub	r9, r11, r10
159	retle	r11
160
161	lsl	r8, 2
162	add	r12, r8
163	andl	r10, 31, COH
164	breq	1f
165
166	/* offset is not word-aligned. Handle the first (32 - r10) bits */
167	ldswp.w	r8, r12[0]
168	sub	r12, -4
169	com	r8
170	lsr	r8, r8, r10
171	brne	.L_found
172
173	/* r9 = r9 - (32 - r10) = r9 + r10 - 32 */
174	add	r9, r10
175	sub	r9, 32
176	retle	r11
177
178	/* Main loop. offset must be word-aligned */
1791:	ldswp.w	r8, r12[0]
180	com	r8
181	brne	.L_found
182	sub	r12, -4
183	sub	r9, 32
184	brgt	1b
185	retal	r11
186