llbit.c 1.56 KB
#include "os.h"

#define BITS_PER_LONGLONG 64
/*
 * Need two extract routines because 
 * the unsigned extract should not sign-extend the value,
 * while the signed extract should.
 */
s64
__ll_bit_extract (u64 *addr, unsigned start_bit, unsigned length)
{
	/* assume 32 < length < 64 */
	unsigned words = start_bit / BITS_PER_LONGLONG;
        unsigned lbits = start_bit % BITS_PER_LONGLONG;
	unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
	u64 mask;

	addr += words;
	mask = ((long long)1 << length) - 1;
	mask = mask << rbits;				/* all 1's in field */
	return((*addr & mask) >> rbits);
	
}

u64
__ull_bit_extract (u64 *addr, unsigned start_bit, unsigned length)
{
	/* assume 32 < length < 64 */
	unsigned words = start_bit / BITS_PER_LONGLONG;
        unsigned lbits = start_bit % BITS_PER_LONGLONG;
	unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
	u64 mask;

	addr += words;
	mask = ((long long)1 << length) - 1;
	mask = mask << rbits;				/* all 1's in field */
	return((*addr & mask) >> rbits);
}

u64
__ll_bit_insert (u64 *addr, unsigned start_bit, unsigned length, u64 val)
{
	/* assume 32 < length < 64 */
	unsigned words = start_bit / BITS_PER_LONGLONG;
	unsigned lbits = start_bit % BITS_PER_LONGLONG;
	unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
	unsigned long long llval, mask;

	addr += words;
	mask = ((long long)1 << length) - 1;
	mask <<= rbits;				/* all 1's in field */

	/* clear lhs, rhs */

	llval = (val << ( BITS_PER_LONGLONG - length)) >> lbits;	
	*addr = (*addr & ~mask) | llval;
	llval = llval>> rbits;	/* truncated val */
	return llval;
}