Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: findbit: operate by words

Convert the implementations to operate on words rather than bytes
which makes bitmap searching faster.

Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>

+50 -34
+6
arch/arm/include/asm/assembler.h
··· 761 761 .endif 762 762 .endm 763 763 764 + .if __LINUX_ARM_ARCH__ < 6 765 + .set .Lrev_l_uses_tmp, 1 766 + .else 767 + .set .Lrev_l_uses_tmp, 0 768 + .endif 769 + 764 770 /* 765 771 * bl_r - branch and link to register 766 772 *
+44 -34
arch/arm/lib/findbit.S
··· 14 14 #include <asm/assembler.h> 15 15 .text 16 16 17 + #ifdef __ARMEB__ 18 + #define SWAB_ENDIAN le 19 + #else 20 + #define SWAB_ENDIAN be 21 + #endif 22 + 17 23 .macro find_first, endian, set, name 18 24 ENTRY(_find_first_\name\()bit_\endian) 19 25 teq r1, #0 20 26 beq 3f 21 27 mov r2, #0 22 - 1: 23 - .ifc \endian, be 24 - eor r3, r2, #0x18 25 - ARM( ldrb r3, [r0, r3, lsr #3] ) 26 - THUMB( lsr r3, #3 ) 27 - THUMB( ldrb r3, [r0, r3] ) 28 + 1: ldr r3, [r0], #4 29 + .ifeq \set 30 + mvns r3, r3 @ invert/test bits 28 31 .else 29 - ARM( ldrb r3, [r0, r2, lsr #3] ) 30 - THUMB( lsr r3, r2, #3 ) 31 - THUMB( ldrb r3, [r0, r3] ) 32 + movs r3, r3 @ test bits 32 33 .endif 33 - .ifeq \set 34 - eors r3, r3, #0xff @ invert bits 34 + .ifc \endian, SWAB_ENDIAN 35 + bne .L_found_swab 35 36 .else 36 - movs r3, r3 37 + bne .L_found @ found the bit? 37 38 .endif 38 - bne .L_found @ any now set - found zero bit 39 - add r2, r2, #8 @ next bit pointer 39 + add r2, r2, #32 @ next index 40 40 2: cmp r2, r1 @ any more? 41 41 blo 1b 42 - 3: mov r0, r1 @ no free bits 42 + 3: mov r0, r1 @ no more bits 43 43 ret lr 44 44 ENDPROC(_find_first_\name\()bit_\endian) 45 45 .endm ··· 48 48 ENTRY(_find_next_\name\()bit_\endian) 49 49 cmp r2, r1 50 50 bhs 3b 51 - ands ip, r2, #7 52 - beq 1b @ If new byte, goto old routine 53 - .ifc \endian, be 54 - eor r3, r2, #0x18 55 - ARM( ldrb r3, [r0, r3, lsr #3] ) 56 - THUMB( lsr r3, #3 ) 57 - THUMB( ldrb r3, [r0, r3] ) 58 - .else 59 - ARM( ldrb r3, [r0, r2, lsr #3] ) 60 - THUMB( lsr r3, r2, #3 ) 61 - THUMB( ldrb r3, [r0, r3] ) 51 + mov ip, r2, lsr #5 @ word index 52 + add r0, r0, ip, lsl #2 53 + ands ip, r2, #31 @ bit position 54 + beq 1b 55 + ldr r3, [r0], #4 56 + .ifeq \set 57 + mvn r3, r3 @ invert bits 62 58 .endif 63 - .ifeq \set 64 - eor r3, r3, #0xff @ now looking for a 1 bit 59 + .ifc \endian, SWAB_ENDIAN 60 + rev_l r3, ip 61 + .if .Lrev_l_uses_tmp 62 + @ we need to recompute ip because rev_l will have overwritten 63 + @ it. 64 + and ip, r2, #31 @ bit position 65 + .endif 65 66 .endif 66 67 movs r3, r3, lsr ip @ shift off unused bits 67 68 bne .L_found 68 - orr r2, r2, #7 @ if zero, then no bits here 69 + orr r2, r2, #31 @ no zero bits 69 70 add r2, r2, #1 @ align bit pointer 70 71 b 2b @ loop for next bit 71 72 ENDPROC(_find_next_\name\()bit_\endian) ··· 96 95 /* 97 96 * One or more bits in the LSB of r3 are assumed to be set. 98 97 */ 98 + .L_found_swab: 99 + rev_l r3, ip 99 100 .L_found: 100 101 #if __LINUX_ARM_ARCH__ >= 7 101 102 rbit r3, r3 @ reverse bits ··· 110 107 rsb r3, r3, #31 @ offset of first set bit 111 108 add r0, r2, r3 @ add offset of first set bit 112 109 #else 113 - tst r3, #0x0f 110 + mov ip, #~0 111 + tst r3, ip, lsr #16 @ test bits 0-15 112 + addeq r2, r2, #16 113 + moveq r3, r3, lsr #16 114 + tst r3, #0x00ff 115 + addeq r2, r2, #8 116 + moveq r3, r3, lsr #8 117 + tst r3, #0x000f 114 118 addeq r2, r2, #4 115 - movne r3, r3, lsl #4 116 - tst r3, #0x30 119 + moveq r3, r3, lsr #4 120 + tst r3, #0x0003 117 121 addeq r2, r2, #2 118 - movne r3, r3, lsl #2 119 - tst r3, #0x40 122 + moveq r3, r3, lsr #2 123 + tst r3, #0x0001 120 124 addeq r2, r2, #1 121 125 mov r0, r2 122 126 #endif