Commit | Line | Data |
---|---|---|
1da177e4 LT |
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> | |
4dd1837d | 18 | #include <asm/export.h> |
1da177e4 LT |
19 | .text |
20 | ||
21 | /* | |
22 | * Purpose : Find a 'zero' bit | |
23 | * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit); | |
24 | */ | |
25 | ENTRY(_find_first_zero_bit_le) | |
26 | teq r1, #0 | |
27 | beq 3f | |
28 | mov r2, #0 | |
8b592783 CM |
29 | 1: |
30 | ARM( ldrb r3, [r0, r2, lsr #3] ) | |
31 | THUMB( lsr r3, r2, #3 ) | |
32 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 33 | eors r3, r3, #0xff @ invert bits |
8adbb371 | 34 | bne .L_found @ any now set - found zero bit |
1da177e4 LT |
35 | add r2, r2, #8 @ next bit pointer |
36 | 2: cmp r2, r1 @ any more? | |
37 | blo 1b | |
38 | 3: mov r0, r1 @ no free bits | |
6ebbf2ce | 39 | ret lr |
93ed3970 | 40 | ENDPROC(_find_first_zero_bit_le) |
4dd1837d | 41 | EXPORT_SYMBOL(_find_first_zero_bit_le) |
1da177e4 LT |
42 | |
43 | /* | |
44 | * Purpose : Find next 'zero' bit | |
45 | * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset) | |
46 | */ | |
47 | ENTRY(_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 | |
8b592783 CM |
52 | ARM( ldrb r3, [r0, r2, lsr #3] ) |
53 | THUMB( lsr r3, r2, #3 ) | |
54 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 LT |
55 | eor r3, r3, #0xff @ now looking for a 1 bit |
56 | movs r3, r3, lsr ip @ shift off unused bits | |
8adbb371 | 57 | bne .L_found |
1da177e4 LT |
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 | |
93ed3970 | 61 | ENDPROC(_find_next_zero_bit_le) |
4dd1837d | 62 | EXPORT_SYMBOL(_find_next_zero_bit_le) |
1da177e4 LT |
63 | |
64 | /* | |
65 | * Purpose : Find a 'one' bit | |
66 | * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit); | |
67 | */ | |
68 | ENTRY(_find_first_bit_le) | |
69 | teq r1, #0 | |
70 | beq 3f | |
71 | mov r2, #0 | |
8b592783 CM |
72 | 1: |
73 | ARM( ldrb r3, [r0, r2, lsr #3] ) | |
74 | THUMB( lsr r3, r2, #3 ) | |
75 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 76 | movs r3, r3 |
8adbb371 | 77 | bne .L_found @ any now set - found zero bit |
1da177e4 LT |
78 | add r2, r2, #8 @ next bit pointer |
79 | 2: cmp r2, r1 @ any more? | |
80 | blo 1b | |
81 | 3: mov r0, r1 @ no free bits | |
6ebbf2ce | 82 | ret lr |
93ed3970 | 83 | ENDPROC(_find_first_bit_le) |
4dd1837d | 84 | EXPORT_SYMBOL(_find_first_bit_le) |
1da177e4 LT |
85 | |
86 | /* | |
87 | * Purpose : Find next 'one' bit | |
88 | * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset) | |
89 | */ | |
90 | ENTRY(_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 | |
8b592783 CM |
95 | ARM( ldrb r3, [r0, r2, lsr #3] ) |
96 | THUMB( lsr r3, r2, #3 ) | |
97 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 98 | movs r3, r3, lsr ip @ shift off unused bits |
8adbb371 | 99 | bne .L_found |
1da177e4 LT |
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 | |
93ed3970 | 103 | ENDPROC(_find_next_bit_le) |
4dd1837d | 104 | EXPORT_SYMBOL(_find_next_bit_le) |
1da177e4 LT |
105 | |
106 | #ifdef __ARMEB__ | |
107 | ||
108 | ENTRY(_find_first_zero_bit_be) | |
109 | teq r1, #0 | |
110 | beq 3f | |
111 | mov r2, #0 | |
112 | 1: eor r3, r2, #0x18 @ big endian byte ordering | |
8b592783 CM |
113 | ARM( ldrb r3, [r0, r3, lsr #3] ) |
114 | THUMB( lsr r3, #3 ) | |
115 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 116 | eors r3, r3, #0xff @ invert bits |
8adbb371 | 117 | bne .L_found @ any now set - found zero bit |
1da177e4 LT |
118 | add r2, r2, #8 @ next bit pointer |
119 | 2: cmp r2, r1 @ any more? | |
120 | blo 1b | |
121 | 3: mov r0, r1 @ no free bits | |
6ebbf2ce | 122 | ret lr |
93ed3970 | 123 | ENDPROC(_find_first_zero_bit_be) |
4dd1837d | 124 | EXPORT_SYMBOL(_find_first_zero_bit_be) |
1da177e4 LT |
125 | |
126 | ENTRY(_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 | |
8b592783 CM |
132 | ARM( ldrb r3, [r0, r3, lsr #3] ) |
133 | THUMB( lsr r3, #3 ) | |
134 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 LT |
135 | eor r3, r3, #0xff @ now looking for a 1 bit |
136 | movs r3, r3, lsr ip @ shift off unused bits | |
8adbb371 | 137 | bne .L_found |
1da177e4 LT |
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 | |
93ed3970 | 141 | ENDPROC(_find_next_zero_bit_be) |
4dd1837d | 142 | EXPORT_SYMBOL(_find_next_zero_bit_be) |
1da177e4 LT |
143 | |
144 | ENTRY(_find_first_bit_be) | |
145 | teq r1, #0 | |
146 | beq 3f | |
147 | mov r2, #0 | |
148 | 1: eor r3, r2, #0x18 @ big endian byte ordering | |
8b592783 CM |
149 | ARM( ldrb r3, [r0, r3, lsr #3] ) |
150 | THUMB( lsr r3, #3 ) | |
151 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 152 | movs r3, r3 |
8adbb371 | 153 | bne .L_found @ any now set - found zero bit |
1da177e4 LT |
154 | add r2, r2, #8 @ next bit pointer |
155 | 2: cmp r2, r1 @ any more? | |
156 | blo 1b | |
157 | 3: mov r0, r1 @ no free bits | |
6ebbf2ce | 158 | ret lr |
93ed3970 | 159 | ENDPROC(_find_first_bit_be) |
4dd1837d | 160 | EXPORT_SYMBOL(_find_first_bit_be) |
1da177e4 LT |
161 | |
162 | ENTRY(_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 | |
8b592783 CM |
168 | ARM( ldrb r3, [r0, r3, lsr #3] ) |
169 | THUMB( lsr r3, #3 ) | |
170 | THUMB( ldrb r3, [r0, r3] ) | |
1da177e4 | 171 | movs r3, r3, lsr ip @ shift off unused bits |
8adbb371 | 172 | bne .L_found |
1da177e4 LT |
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 | |
93ed3970 | 176 | ENDPROC(_find_next_bit_be) |
4dd1837d | 177 | EXPORT_SYMBOL(_find_next_bit_be) |
1da177e4 LT |
178 | |
179 | #endif | |
180 | ||
181 | /* | |
182 | * One or more bits in the LSB of r3 are assumed to be set. | |
183 | */ | |
8adbb371 | 184 | .L_found: |
1da177e4 | 185 | #if __LINUX_ARM_ARCH__ >= 5 |
0e91ec0c JJ |
186 | rsb r0, r3, #0 |
187 | and r3, r3, r0 | |
1da177e4 LT |
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 | |
0e91ec0c JJ |
202 | cmp r1, r0 @ Clamp to maxbit |
203 | movlo r0, r1 | |
6ebbf2ce | 204 | ret lr |
1da177e4 | 205 |