// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 */
#ifndef __LIBFROG_BITMASK_H_
#define __LIBFROG_BITMASK_H_

#define BIT_MASK(nr)	(1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr)	((nr) / BITS_PER_LONG)

static inline void set_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

	*p  |= mask;
}

static inline void clear_bit(int nr, volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

	*p &= ~mask;
}

static inline int test_bit(int nr, const volatile unsigned long *addr)
{
	unsigned long mask = BIT_MASK(nr);
	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

	return *p & mask;
}

/* Sets and returns original value of the bit */
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
	if (test_bit(nr, addr))
		return 1;
	set_bit(nr, addr);
	return 0;
}

/* Get high bit set out of 64-bit argument, -1 if none set */
static inline int xfrog_highbit64(uint64_t v)
{
	return fls64(v) - 1;
}

#endif /* __LIBFROG_BITMASK_H_ */
