mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
4.2 KiB
127 lines
4.2 KiB
/*
|
|
* |-----------------------------------------------------------|
|
|
* | 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 <limits.h>
|
|
#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;
|
|
}
|
|
|