aboutsummaryrefslogtreecommitdiffstats
path: root/bitops.h
blob: f20c88082767a775e8dc5da38386a94c731cdb78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#ident "$Id$"
/* ----------------------------------------------------------------------- *
 *   
 *   Copyright 2000-2001 H. Peter Anvin - All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as
 *   published by the Free Software Foundation, Inc.,
 *   59 Temple Place Ste 330, Boston MA 02111-1307, USA, version 2.1,
 *   incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * bitops.h
 *
 * Internals for LPSM: bitmap operations.  Not to be used by applications.
 */

#ifndef LPSM_BITOPS_H
#define LPSM_BITOPS_H

#include <inttypes.h>
#include "system.h"		/* System-specific constants */

/* The data type to use for bitfield scanning.  Typically should equal
   the "natural" size on the machine; defined in system.h. */
#if MACHINE_SIZE_LG2 == 6
  typedef uint64_t bitscan_t;
#else
  typedef uint32_t bitscan_t;
#endif
#define BITSCAN_SHIFT		MACHINE_SIZE_LG2
#define BITSCAN_BITS		(1 << BITSCAN_SHIFT)
#define BITSCAN_MASK		(BITSCAN_BITS-1)
#define BITSCAN_0		((bitscan_t)0)
#define BITSCAN_1		((bitscan_t)1)

/*
 * These should be revamped to be thread-safe at some point.  That
 * may mean doing things that are architecture-specific...
 *
 * Important: "bit" can be negative, and that needs to be handled
 * correctly!
 */
static inline int test_bit(const void *ptr, int bit)
{
#if defined(__GNUC__) && defined(__i386__)
  int rv;
  asm("xorl %0,%0 ; btl %2,%1 ; adcl %0,%0"
      : "=&r" (rv) : "m" (*(const bitscan_t *)ptr), "r" (bit) : "cc");
  return rv;
#else
  const bitscan_t *cp;

  cp = (const bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
  return (int)((*cp >> (bit & BITSCAN_MASK)) & BITSCAN_1);
#endif
}

static inline void set_bit(void *ptr, int bit)
{
#if defined(__GNUC__) && defined(__i386__)
  asm volatile("btsl %1,%0" : "=m" (*(bitscan_t *)ptr) : "r" (bit) : "cc");
#else
  bitscan_t *cp;

  cp = (bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
  *cp |= (BITSCAN_1 << (bit & BITSCAN_MASK));
#endif
}

static inline void clr_bit(void *ptr, int bit)
{
#if defined(__GNUC__) && defined(__i386__)
  asm volatile("btcl %1,%0" : "=m" (*(bitscan_t *)ptr) : "r" (bit) : "cc");
#else
  bitscan_t *cp;

  cp = (bitscan_t *)ptr + (bit >> BITSCAN_SHIFT);
  *cp &= ~(BITSCAN_1 << (bit & BITSCAN_MASK));
#endif
}

int lpsm_find_set_bit(const void *ptr, int start, int count, int err);

#endif