findbit.S 2.59 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8
/*
 *  linux/arch/arm/lib/findbit.S
 *
 *  Copyright (C) 1995-2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
9 10 11 12 13 14
 *
 * 16th March 2001 - John Ripley <jripley@sonicblue.com>
 *   Fixed so that "size" is an exclusive not an inclusive quantity.
 *   All users of these functions expect exclusive sizes, and may
 *   also call with zero size.
 * Reworked by rmk.
Linus Torvalds's avatar
Linus Torvalds committed
15 16 17 18 19 20 21
 */
#include <linux/linkage.h>
#include <asm/assembler.h>
                .text

/*
 * Purpose  : Find a 'zero' bit
22
 * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
Linus Torvalds's avatar
Linus Torvalds committed
23
 */
Linus Torvalds's avatar
Linus Torvalds committed
24
ENTRY(_find_first_zero_bit_le)
25 26
		teq	r1, #0	
		beq	3f
Linus Torvalds's avatar
Linus Torvalds committed
27
		mov	r2, #0
Linus Torvalds's avatar
Linus Torvalds committed
28
1:		ldrb	r3, [r0, r2, lsr #3]
Linus Torvalds's avatar
Linus Torvalds committed
29 30 31
		eors	r3, r3, #0xff		@ invert bits
		bne	.found			@ any now set - found zero bit
		add	r2, r2, #8		@ next bit pointer
32 33 34
2:		cmp	r2, r1			@ any more?
		blo	1b
3:		mov	r0, r1			@ no free bits
Linus Torvalds's avatar
Linus Torvalds committed
35 36 37 38
		RETINSTR(mov,pc,lr)

/*
 * Purpose  : Find next 'zero' bit
39
 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
Linus Torvalds's avatar
Linus Torvalds committed
40
 */
Linus Torvalds's avatar
Linus Torvalds committed
41
ENTRY(_find_next_zero_bit_le)
42 43
		teq	r1, #0
		beq	2b
Linus Torvalds's avatar
Linus Torvalds committed
44
		ands	ip, r2, #7
Linus Torvalds's avatar
Linus Torvalds committed
45
		beq	1b			@ If new byte, goto old routine
46
		ldrb	r3, [r0, r2, lsr #3]
Linus Torvalds's avatar
Linus Torvalds committed
47 48
		eor	r3, r3, #0xff		@ now looking for a 1 bit
		movs	r3, r3, lsr ip		@ shift off unused bits
Linus Torvalds's avatar
Linus Torvalds committed
49 50 51
		bne	.found
		orr	r2, r2, #7		@ if zero, then no bits here
		add	r2, r2, #1		@ align bit pointer
52
		b	2b			@ loop for next bit
Linus Torvalds's avatar
Linus Torvalds committed
53 54 55 56

#ifdef __ARMEB__

ENTRY(_find_first_zero_bit_be)
57 58
		teq	r1, #0
		beq	3f
Linus Torvalds's avatar
Linus Torvalds committed
59 60 61 62 63 64
		mov	r2, #0
1:		eor	r3, r2, #0x18		@ big endian byte ordering
		ldrb	r3, [r0, r3, lsr #3]
		eors	r3, r3, #0xff		@ invert bits
		bne	.found			@ any now set - found zero bit
		add	r2, r2, #8		@ next bit pointer
65 66 67
2:		cmp	r2, r1			@ any more?
		blo	1b
3:		mov	r0, r1			@ no free bits
Linus Torvalds's avatar
Linus Torvalds committed
68 69 70 71 72 73
		RETINSTR(mov,pc,lr)

ENTRY(_find_next_zero_bit_be)
		ands	ip, r2, #7
		beq	1b			@ If new byte, goto old routine
		eor	r3, r2, #0x18		@ big endian byte ordering
74
		ldrb	r3, [r0, r3, lsr #3]
Linus Torvalds's avatar
Linus Torvalds committed
75 76
		eor	r3, r3, #0xff		@ now looking for a 1 bit
		movs	r3, r3, lsr ip		@ shift off unused bits
Linus Torvalds's avatar
Linus Torvalds committed
77 78
		orreq	r2, r2, #7		@ if zero, then no bits here
		addeq	r2, r2, #1		@ align bit pointer
79
		beq	2b			@ loop for next bit
Linus Torvalds's avatar
Linus Torvalds committed
80 81

#endif
Linus Torvalds's avatar
Linus Torvalds committed
82 83 84 85

/*
 * One or more bits in the LSB of r3 are assumed to be set.
 */
86 87 88 89 90 91 92 93 94
.found:
#if __LINUX_ARM_ARCH__ >= 5
		rsb	r1, r3, #0
		and	r3, r3, r1
		clz	r3, r3
		rsb	r3, r3, #31
		add	r0, r2, r3
#else
		tst	r3, #0x0f
Linus Torvalds's avatar
Linus Torvalds committed
95 96 97 98 99 100 101 102
		addeq	r2, r2, #4
		movne	r3, r3, lsl #4
		tst	r3, #0x30
		addeq	r2, r2, #2
		movne	r3, r3, lsl #2
		tst	r3, #0x40
		addeq	r2, r2, #1
		mov	r0, r2
103
#endif
Linus Torvalds's avatar
Linus Torvalds committed
104 105
		RETINSTR(mov,pc,lr)