blob: 8c4defc4f3c482bf598f7dad0c519798b80f66ef [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +000030 bne .L_found @ any now set - found zero bit
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 add r2, r2, #8 @ next bit pointer
322: cmp r2, r1 @ any more?
33 blo 1b
343: mov r0, r1 @ no free bits
Russell King7999d8d2006-06-25 11:17:23 +010035 mov pc, lr
Catalin Marinas93ed3972008-08-28 11:22:32 +010036ENDPROC(_find_first_zero_bit_le)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +000050 bne .L_found
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 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
Catalin Marinas93ed3972008-08-28 11:22:32 +010054ENDPROC(_find_next_zero_bit_le)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +000066 bne .L_found @ any now set - found zero bit
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 add r2, r2, #8 @ next bit pointer
682: cmp r2, r1 @ any more?
69 blo 1b
703: mov r0, r1 @ no free bits
Russell King7999d8d2006-06-25 11:17:23 +010071 mov pc, lr
Catalin Marinas93ed3972008-08-28 11:22:32 +010072ENDPROC(_find_first_bit_le)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +000085 bne .L_found
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 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
Catalin Marinas93ed3972008-08-28 11:22:32 +010089ENDPROC(_find_next_bit_le)
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +0000100 bne .L_found @ any now set - found zero bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 add r2, r2, #8 @ next bit pointer
1022: cmp r2, r1 @ any more?
103 blo 1b
1043: mov r0, r1 @ no free bits
Russell King7999d8d2006-06-25 11:17:23 +0100105 mov pc, lr
Catalin Marinas93ed3972008-08-28 11:22:32 +0100106ENDPROC(_find_first_zero_bit_be)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +0000117 bne .L_found
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 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
Catalin Marinas93ed3972008-08-28 11:22:32 +0100121ENDPROC(_find_next_zero_bit_be)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +0000130 bne .L_found @ any now set - found zero bit
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 add r2, r2, #8 @ next bit pointer
1322: cmp r2, r1 @ any more?
133 blo 1b
1343: mov r0, r1 @ no free bits
Russell King7999d8d2006-06-25 11:17:23 +0100135 mov pc, lr
Catalin Marinas93ed3972008-08-28 11:22:32 +0100136ENDPROC(_find_first_bit_be)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
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
Nicolas Pitre8adbb372005-11-11 21:51:49 +0000146 bne .L_found
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 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
Catalin Marinas93ed3972008-08-28 11:22:32 +0100150ENDPROC(_find_next_bit_be)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
152#endif
153
154/*
155 * One or more bits in the LSB of r3 are assumed to be set.
156 */
Nicolas Pitre8adbb372005-11-11 21:51:49 +0000157.L_found:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158#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
Russell King7999d8d2006-06-25 11:17:23 +0100175 mov pc, lr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176