]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/x86/lib/bitops_64.c
568467d390c0c8baacf6996e899f5804a086e35c
[linux-2.6-omap-h63xx.git] / arch / x86 / lib / bitops_64.c
1 #ifndef CONFIG_GENERIC_FIND_FIRST_BIT
2 #include <linux/bitops.h>
3
4 #undef find_first_zero_bit
5 #undef find_first_bit
6
7 static inline long
8 __find_first_zero_bit(const unsigned long * addr, unsigned long size)
9 {
10         long d0, d1, d2;
11         long res;
12
13         /*
14          * We must test the size in words, not in bits, because
15          * otherwise incoming sizes in the range -63..-1 will not run
16          * any scasq instructions, and then the flags used by the je
17          * instruction will have whatever random value was in place
18          * before.  Nobody should call us like that, but
19          * find_next_zero_bit() does when offset and size are at the
20          * same word and it fails to find a zero itself.
21          */
22         size += 63;
23         size >>= 6;
24         if (!size)
25                 return 0;
26         asm volatile(
27                 "  repe; scasq\n"
28                 "  je 1f\n"
29                 "  xorq -8(%%rdi),%%rax\n"
30                 "  subq $8,%%rdi\n"
31                 "  bsfq %%rax,%%rdx\n"
32                 "1:  subq %[addr],%%rdi\n"
33                 "  shlq $3,%%rdi\n"
34                 "  addq %%rdi,%%rdx"
35                 :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
36                 :"0" (0ULL), "1" (size), "2" (addr), "3" (-1ULL),
37                  [addr] "S" (addr) : "memory");
38         /*
39          * Any register would do for [addr] above, but GCC tends to
40          * prefer rbx over rsi, even though rsi is readily available
41          * and doesn't have to be saved.
42          */
43         return res;
44 }
45
46 /**
47  * find_first_zero_bit - find the first zero bit in a memory region
48  * @addr: The address to start the search at
49  * @size: The maximum size to search
50  *
51  * Returns the bit-number of the first zero bit, not the number of the byte
52  * containing a bit.
53  */
54 long find_first_zero_bit(const unsigned long * addr, unsigned long size)
55 {
56         return __find_first_zero_bit (addr, size);
57 }
58
59 static inline long
60 __find_first_bit(const unsigned long * addr, unsigned long size)
61 {
62         long d0, d1;
63         long res;
64
65         /*
66          * We must test the size in words, not in bits, because
67          * otherwise incoming sizes in the range -63..-1 will not run
68          * any scasq instructions, and then the flags used by the jz
69          * instruction will have whatever random value was in place
70          * before.  Nobody should call us like that, but
71          * find_next_bit() does when offset and size are at the same
72          * word and it fails to find a one itself.
73          */
74         size += 63;
75         size >>= 6;
76         if (!size)
77                 return 0;
78         asm volatile(
79                 "   repe; scasq\n"
80                 "   jz 1f\n"
81                 "   subq $8,%%rdi\n"
82                 "   bsfq (%%rdi),%%rax\n"
83                 "1: subq %[addr],%%rdi\n"
84                 "   shlq $3,%%rdi\n"
85                 "   addq %%rdi,%%rax"
86                 :"=a" (res), "=&c" (d0), "=&D" (d1)
87                 :"0" (0ULL), "1" (size), "2" (addr),
88                  [addr] "r" (addr) : "memory");
89         return res;
90 }
91
92 /**
93  * find_first_bit - find the first set bit in a memory region
94  * @addr: The address to start the search at
95  * @size: The maximum size to search
96  *
97  * Returns the bit-number of the first set bit, not the number of the byte
98  * containing a bit.
99  */
100 long find_first_bit(const unsigned long * addr, unsigned long size)
101 {
102         return __find_first_bit(addr,size);
103 }
104
105 #include <linux/module.h>
106
107 EXPORT_SYMBOL(find_first_bit);
108 EXPORT_SYMBOL(find_first_zero_bit);
109 #endif