/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include void bit_set_range(unsigned long *bitfield, usize first, usize count) { /* skip ahead to the longword containing the first bit we need to set */ bitfield += first / LONG_BIT; unsigned int bit = first % LONG_BIT; /* test if the entire bit range is contained within this longword */ if (bit + count < LONG_BIT) { unsigned long low_mask = (1lu << bit) - 1; /* 0b000..011 */ unsigned long high_mask = ~( (1lu << (bit + count)) - 1 ); /* 0b110..000 */ *bitfield |= ~(low_mask | high_mask); } else { /* if the first bit isn't longword aligned, manually set the upper * bits in that longword, starting from the first bit's position */ if (bit != 0) { unsigned long mask = (1lu << bit) - 1; *bitfield++ |= ~mask; count -= LONG_BIT - bit; } /* write out full longwords while we can */ while (count >= LONG_BIT) { *bitfield++ = ~0lu; count -= LONG_BIT; } /* set the remaining lower bits in the last longword, if any */ if (count != 0) { unsigned long mask = (1lu << count) - 1; *bitfield |= mask; } } } /* this works the same way as bit_set_range, it's just the inverse */ void bit_clr_range(unsigned long *bitfield, usize first, usize count) { bitfield += first / LONG_BIT; unsigned int bit = first % LONG_BIT; if (bit + count < LONG_BIT) { unsigned long low_mask = (1lu << bit) - 1; unsigned long high_mask = ~( (1lu << (bit + count)) - 1 ); *bitfield &= low_mask | high_mask; } else { if (bit != 0) { unsigned long mask = (1lu << bit) - 1; *bitfield++ &= mask; count -= LONG_BIT - bit; } while (count >= LONG_BIT) { *bitfield++ = 0; count -= LONG_BIT; } if (count != 0) { unsigned long mask = (1lu << count) - 1; *bitfield &= ~mask; } } } bool bit_tst(const unsigned long *bitfield, usize pos) { usize index = pos / LONG_BIT; unsigned long mask = 1 << (pos % LONG_BIT); return (bitfield[index] & mask) != 0; } void bit_set(unsigned long *bitfield, usize pos) { usize index = pos / LONG_BIT; unsigned long mask = 1 << (pos % LONG_BIT); bitfield[index] |= mask; } void bit_clr(unsigned long *bitfield, usize pos) { usize index = pos / LONG_BIT; unsigned long mask = 1 << (pos % LONG_BIT); bitfield[index] &= ~mask; }