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