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