/* * |-----------------------------------------------------------| * | Copyright (c) 1991 MIPS Computer Systems, Inc. | * | All Rights Reserved | * |-----------------------------------------------------------| * | Restricted Rights Legend | * | Use, duplication, or disclosure by the Government is | * | subject to restrictions as set forth in | * | subparagraph (c)(1)(ii) of the Rights in Technical | * | Data and Computer Software Clause of DFARS 52.227-7013. | * | MIPS Computer Systems, Inc. | * | 950 DeGuigne Drive | * | Sunnyvale, CA 94086 | * |-----------------------------------------------------------| */ /* $Header: llbit.c,v 3010.2 91/12/20 10:24:03 murphy Exp $ */ #include #define BITS_PER_LONGLONG 64 #include "lldefs.h" /* Disable bit shift intrinsics so this code will work properly. */ #pragma function(__ll_lshift) #pragma function(__ll_rshift) #pragma function(__ull_rshift) extern ulonglong_t __ull_bit_extract (ulonglong_t *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); llvalue llval, addrval, mask, one; addr += words; addrval.ull = *addr; SET_LL(one, 1); SET_LL(mask, 1); mask.ull = __ll_lshift(mask.ull, length); LL_SUB(mask, mask, one); mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ LL_AND(llval, addrval, mask); llval.ull = __ull_rshift(llval.ull, lbits+rbits); return llval.ull; } extern ulonglong_t __ull_bit_insert (ulonglong_t *addr, unsigned start_bit, unsigned length, ulonglong_t 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); llvalue llval, addrval, mask, nmask, one; addr += words; llval.ull = val; addrval.ull = *addr; SET_LL(one, 1); SET_LL(mask, 1); mask.ull = __ll_lshift(mask.ull, length); LL_SUB(mask, mask, one); mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ LL_NOT(nmask, mask); LL_AND(addrval, addrval, nmask); /* clear the field */ llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */ llval.ull = __ull_rshift(llval.ull, rbits); LL_OR(addrval, addrval, llval); *addr = addrval.ull; llval.ull = __ull_rshift(llval.ull, lbits); /* truncated val */ return llval.ull; } extern longlong_t __ll_bit_extract (ulonglong_t *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); llvalue llval, addrval, mask, one; addr += words; addrval.ull = *addr; SET_LL(one, 1); SET_LL(mask, 1); mask.ull = __ll_lshift(mask.ull, length); LL_SUB(mask, mask, one); mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ LL_AND(llval, addrval, mask); llval.ull = __ll_lshift(llval.ull, rbits); llval.ull = __ll_rshift(llval.ull, lbits+rbits); return llval.ull; } extern longlong_t __ll_bit_insert (ulonglong_t *addr,unsigned start_bit, unsigned length, longlong_t 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); llvalue llval, addrval, mask, nmask, one; addr += words; llval.ull = val; addrval.ull = *addr; SET_LL(one, 1); SET_LL(mask, 1); mask.ull = __ll_lshift(mask.ull, length); LL_SUB(mask, mask, one); mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */ LL_NOT(nmask, mask); LL_AND(addrval, addrval, nmask); /* clear the field */ llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */ llval.ull = __ull_rshift(llval.ull, rbits); LL_OR(addrval, addrval, llval); *addr = addrval.ull; llval.ull = __ll_rshift(llval.ull, lbits); /* truncated val */ return llval.ull; }