root / util / bitops.c @ 29b358f9
History | View | Annotate | Download (3.8 kB)
1 | e0e53b2f | Corentin Chary | /*
|
---|---|---|---|
2 | e0e53b2f | Corentin Chary | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
3 | e0e53b2f | Corentin Chary | * Written by David Howells (dhowells@redhat.com)
|
4 | e0e53b2f | Corentin Chary | * Copyright (C) 2008 IBM Corporation
|
5 | e0e53b2f | Corentin Chary | * Written by Rusty Russell <rusty@rustcorp.com.au>
|
6 | e0e53b2f | Corentin Chary | * (Inspired by David Howell's find_next_bit implementation)
|
7 | e0e53b2f | Corentin Chary | *
|
8 | e0e53b2f | Corentin Chary | * This program is free software; you can redistribute it and/or
|
9 | e0e53b2f | Corentin Chary | * modify it under the terms of the GNU General Public License
|
10 | e0e53b2f | Corentin Chary | * as published by the Free Software Foundation; either version
|
11 | e0e53b2f | Corentin Chary | * 2 of the License, or (at your option) any later version.
|
12 | e0e53b2f | Corentin Chary | */
|
13 | e0e53b2f | Corentin Chary | |
14 | 1de7afc9 | Paolo Bonzini | #include "qemu/bitops.h" |
15 | e0e53b2f | Corentin Chary | |
16 | e0e53b2f | Corentin Chary | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
17 | e0e53b2f | Corentin Chary | |
18 | e0e53b2f | Corentin Chary | /*
|
19 | e0e53b2f | Corentin Chary | * Find the next set bit in a memory region.
|
20 | e0e53b2f | Corentin Chary | */
|
21 | e0e53b2f | Corentin Chary | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, |
22 | e0e53b2f | Corentin Chary | unsigned long offset) |
23 | e0e53b2f | Corentin Chary | { |
24 | e0e53b2f | Corentin Chary | const unsigned long *p = addr + BITOP_WORD(offset); |
25 | e0e53b2f | Corentin Chary | unsigned long result = offset & ~(BITS_PER_LONG-1); |
26 | e0e53b2f | Corentin Chary | unsigned long tmp; |
27 | e0e53b2f | Corentin Chary | |
28 | e0e53b2f | Corentin Chary | if (offset >= size) {
|
29 | e0e53b2f | Corentin Chary | return size;
|
30 | e0e53b2f | Corentin Chary | } |
31 | e0e53b2f | Corentin Chary | size -= result; |
32 | e0e53b2f | Corentin Chary | offset %= BITS_PER_LONG; |
33 | e0e53b2f | Corentin Chary | if (offset) {
|
34 | e0e53b2f | Corentin Chary | tmp = *(p++); |
35 | e0e53b2f | Corentin Chary | tmp &= (~0UL << offset);
|
36 | e0e53b2f | Corentin Chary | if (size < BITS_PER_LONG) {
|
37 | e0e53b2f | Corentin Chary | goto found_first;
|
38 | e0e53b2f | Corentin Chary | } |
39 | e0e53b2f | Corentin Chary | if (tmp) {
|
40 | e0e53b2f | Corentin Chary | goto found_middle;
|
41 | e0e53b2f | Corentin Chary | } |
42 | e0e53b2f | Corentin Chary | size -= BITS_PER_LONG; |
43 | e0e53b2f | Corentin Chary | result += BITS_PER_LONG; |
44 | e0e53b2f | Corentin Chary | } |
45 | 49f676a0 | Peter Lieven | while (size >= 4*BITS_PER_LONG) { |
46 | 49f676a0 | Peter Lieven | unsigned long d1, d2, d3; |
47 | 49f676a0 | Peter Lieven | tmp = *p; |
48 | 49f676a0 | Peter Lieven | d1 = *(p+1);
|
49 | 49f676a0 | Peter Lieven | d2 = *(p+2);
|
50 | 49f676a0 | Peter Lieven | d3 = *(p+3);
|
51 | 49f676a0 | Peter Lieven | if (tmp) {
|
52 | 49f676a0 | Peter Lieven | goto found_middle;
|
53 | 49f676a0 | Peter Lieven | } |
54 | 49f676a0 | Peter Lieven | if (d1 | d2 | d3) {
|
55 | 49f676a0 | Peter Lieven | break;
|
56 | 49f676a0 | Peter Lieven | } |
57 | 49f676a0 | Peter Lieven | p += 4;
|
58 | 49f676a0 | Peter Lieven | result += 4*BITS_PER_LONG;
|
59 | 49f676a0 | Peter Lieven | size -= 4*BITS_PER_LONG;
|
60 | 49f676a0 | Peter Lieven | } |
61 | 49f676a0 | Peter Lieven | while (size >= BITS_PER_LONG) {
|
62 | e0e53b2f | Corentin Chary | if ((tmp = *(p++))) {
|
63 | e0e53b2f | Corentin Chary | goto found_middle;
|
64 | e0e53b2f | Corentin Chary | } |
65 | e0e53b2f | Corentin Chary | result += BITS_PER_LONG; |
66 | e0e53b2f | Corentin Chary | size -= BITS_PER_LONG; |
67 | e0e53b2f | Corentin Chary | } |
68 | e0e53b2f | Corentin Chary | if (!size) {
|
69 | e0e53b2f | Corentin Chary | return result;
|
70 | e0e53b2f | Corentin Chary | } |
71 | e0e53b2f | Corentin Chary | tmp = *p; |
72 | e0e53b2f | Corentin Chary | |
73 | e0e53b2f | Corentin Chary | found_first:
|
74 | e0e53b2f | Corentin Chary | tmp &= (~0UL >> (BITS_PER_LONG - size));
|
75 | e0e53b2f | Corentin Chary | if (tmp == 0UL) { /* Are any bits set? */ |
76 | e0e53b2f | Corentin Chary | return result + size; /* Nope. */ |
77 | e0e53b2f | Corentin Chary | } |
78 | e0e53b2f | Corentin Chary | found_middle:
|
79 | 265ce4a5 | Richard Henderson | return result + ctzl(tmp);
|
80 | e0e53b2f | Corentin Chary | } |
81 | e0e53b2f | Corentin Chary | |
82 | e0e53b2f | Corentin Chary | /*
|
83 | e0e53b2f | Corentin Chary | * This implementation of find_{first,next}_zero_bit was stolen from
|
84 | e0e53b2f | Corentin Chary | * Linus' asm-alpha/bitops.h.
|
85 | e0e53b2f | Corentin Chary | */
|
86 | e0e53b2f | Corentin Chary | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, |
87 | e0e53b2f | Corentin Chary | unsigned long offset) |
88 | e0e53b2f | Corentin Chary | { |
89 | e0e53b2f | Corentin Chary | const unsigned long *p = addr + BITOP_WORD(offset); |
90 | e0e53b2f | Corentin Chary | unsigned long result = offset & ~(BITS_PER_LONG-1); |
91 | e0e53b2f | Corentin Chary | unsigned long tmp; |
92 | e0e53b2f | Corentin Chary | |
93 | e0e53b2f | Corentin Chary | if (offset >= size) {
|
94 | e0e53b2f | Corentin Chary | return size;
|
95 | e0e53b2f | Corentin Chary | } |
96 | e0e53b2f | Corentin Chary | size -= result; |
97 | e0e53b2f | Corentin Chary | offset %= BITS_PER_LONG; |
98 | e0e53b2f | Corentin Chary | if (offset) {
|
99 | e0e53b2f | Corentin Chary | tmp = *(p++); |
100 | e0e53b2f | Corentin Chary | tmp |= ~0UL >> (BITS_PER_LONG - offset);
|
101 | e0e53b2f | Corentin Chary | if (size < BITS_PER_LONG) {
|
102 | e0e53b2f | Corentin Chary | goto found_first;
|
103 | e0e53b2f | Corentin Chary | } |
104 | e0e53b2f | Corentin Chary | if (~tmp) {
|
105 | e0e53b2f | Corentin Chary | goto found_middle;
|
106 | e0e53b2f | Corentin Chary | } |
107 | e0e53b2f | Corentin Chary | size -= BITS_PER_LONG; |
108 | e0e53b2f | Corentin Chary | result += BITS_PER_LONG; |
109 | e0e53b2f | Corentin Chary | } |
110 | e0e53b2f | Corentin Chary | while (size & ~(BITS_PER_LONG-1)) { |
111 | e0e53b2f | Corentin Chary | if (~(tmp = *(p++))) {
|
112 | e0e53b2f | Corentin Chary | goto found_middle;
|
113 | e0e53b2f | Corentin Chary | } |
114 | e0e53b2f | Corentin Chary | result += BITS_PER_LONG; |
115 | e0e53b2f | Corentin Chary | size -= BITS_PER_LONG; |
116 | e0e53b2f | Corentin Chary | } |
117 | e0e53b2f | Corentin Chary | if (!size) {
|
118 | e0e53b2f | Corentin Chary | return result;
|
119 | e0e53b2f | Corentin Chary | } |
120 | e0e53b2f | Corentin Chary | tmp = *p; |
121 | e0e53b2f | Corentin Chary | |
122 | e0e53b2f | Corentin Chary | found_first:
|
123 | e0e53b2f | Corentin Chary | tmp |= ~0UL << size;
|
124 | e0e53b2f | Corentin Chary | if (tmp == ~0UL) { /* Are any bits zero? */ |
125 | e0e53b2f | Corentin Chary | return result + size; /* Nope. */ |
126 | e0e53b2f | Corentin Chary | } |
127 | e0e53b2f | Corentin Chary | found_middle:
|
128 | 0f9d8bd3 | Richard Henderson | return result + ctzl(~tmp);
|
129 | e0e53b2f | Corentin Chary | } |
130 | e0e53b2f | Corentin Chary | |
131 | e0e53b2f | Corentin Chary | unsigned long find_last_bit(const unsigned long *addr, unsigned long size) |
132 | e0e53b2f | Corentin Chary | { |
133 | e0e53b2f | Corentin Chary | unsigned long words; |
134 | e0e53b2f | Corentin Chary | unsigned long tmp; |
135 | e0e53b2f | Corentin Chary | |
136 | e0e53b2f | Corentin Chary | /* Start at final word. */
|
137 | e0e53b2f | Corentin Chary | words = size / BITS_PER_LONG; |
138 | e0e53b2f | Corentin Chary | |
139 | e0e53b2f | Corentin Chary | /* Partial final word? */
|
140 | e0e53b2f | Corentin Chary | if (size & (BITS_PER_LONG-1)) { |
141 | e0e53b2f | Corentin Chary | tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
|
142 | e0e53b2f | Corentin Chary | - (size & (BITS_PER_LONG-1)))));
|
143 | e0e53b2f | Corentin Chary | if (tmp) {
|
144 | e0e53b2f | Corentin Chary | goto found;
|
145 | e0e53b2f | Corentin Chary | } |
146 | e0e53b2f | Corentin Chary | } |
147 | e0e53b2f | Corentin Chary | |
148 | e0e53b2f | Corentin Chary | while (words) {
|
149 | e0e53b2f | Corentin Chary | tmp = addr[--words]; |
150 | e0e53b2f | Corentin Chary | if (tmp) {
|
151 | e0e53b2f | Corentin Chary | found:
|
152 | 4932398f | Richard Henderson | return words * BITS_PER_LONG + BITS_PER_LONG - 1 - clzl(tmp); |
153 | e0e53b2f | Corentin Chary | } |
154 | e0e53b2f | Corentin Chary | } |
155 | e0e53b2f | Corentin Chary | |
156 | e0e53b2f | Corentin Chary | /* Not found */
|
157 | e0e53b2f | Corentin Chary | return size;
|
158 | e0e53b2f | Corentin Chary | } |