Statistics
| Branch: | Revision:

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
}