migrated msb postionting function to moo-utl.h

This commit is contained in:
hyunghwan.chung 2019-05-04 04:27:27 +00:00
parent 80b05e9d95
commit eba44fc039
12 changed files with 193 additions and 119 deletions

View File

@ -134,96 +134,14 @@ static const moo_uint8_t debruijn_64[64] =
# define LOG2_FOR_POW2_64(x) (debruijn_64[(moo_uint64_t)((moo_uint64_t)(x) * 0x022fdd63cc95386d) >> 58]) # define LOG2_FOR_POW2_64(x) (debruijn_64[(moo_uint64_t)((moo_uint64_t)(x) * 0x022fdd63cc95386d) >> 58])
#endif #endif
static MOO_INLINE int get_pos_of_msb_set_pow2 (moo_oow_t x)
{
/* the caller must ensure that x is power of 2. if x happens to be zero,
* the return value is undefined as each method used may give different result. */
#if defined(MOO_HAVE_BUILTIN_CTZLL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG_LONG)
return __builtin_ctzll(x); /* count the number of trailing zeros */
#elif defined(MOO_HAVE_BUILTIN_CTZL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG)
return __builtin_ctzl(x); /* count the number of trailing zeros */
#elif defined(MOO_HAVE_BUILTIN_CTZ) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT)
return __builtin_ctz(x); /* count the number of trailing zeros */
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
moo_oow_t pos;
/* use the Bit Scan Forward instruction */
#if 1
__asm__ volatile (
"bsf %1,%0\n\t"
: "=r"(pos) /* output */
: "r"(x) /* input */
);
#else
__asm__ volatile (
"bsf %[X],%[EXP]\n\t"
: [EXP]"=r"(pos) /* output */
: [X]"r"(x) /* input */
);
#endif
return (int)pos;
#elif defined(__GNUC__) && defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 5))
moo_oow_t n;
/* CLZ is available in ARMv5T and above. there is no instruction to
* count trailing zeros or something similar. using RBIT with CLZ
* would be good in ARMv6T2 and above to avoid further calculation
* afte CLZ */
__asm__ volatile (
"clz %0,%1\n\t"
: "=r"(n) /* output */
: "r"(x) /* input */
);
return (int)(MOO_OOW_BITS - n - 1);
/* TODO: PPC - use cntlz, cntlzw, cntlzd, SPARC - use lzcnt, MIPS clz */
#else
int pos = 0;
while (x >>= 1) pos++;
return pos;
#endif
}
static MOO_INLINE int get_pos_of_msb_set (moo_oow_t x)
{
/* x doesn't have to be power of 2. if x is zero, the result is undefined */
#if defined(MOO_HAVE_BUILTIN_CLZLL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG_LONG)
return MOO_OOW_BITS - __builtin_clzll(x) - 1; /* count the number of leading zeros */
#elif defined(MOO_HAVE_BUILTIN_CLZL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG)
return MOO_OOW_BITS - __builtin_clzl(x) - 1; /* count the number of leading zeros */
#elif defined(MOO_HAVE_BUILTIN_CLZ) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT)
return MOO_OOW_BITS - __builtin_clz(x) - 1; /* count the number of leading zeros */
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
/* bit scan reverse. not all x86 CPUs have LZCNT. */
moo_oow_t pos;
__asm__ volatile (
"bsr %1,%0\n\t"
: "=r"(pos) /* output */
: "r"(x) /* input */
);
return (int)pos;
#elif defined(__GNUC__) && defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 5))
moo_oow_t n;
__asm__ volatile (
"clz %0,%1\n\t"
: "=r"(n) /* output */
: "r"(x) /* input */
);
return (int)(MOO_OOW_BITS - n - 1);
/* TODO: PPC - use cntlz, cntlzw, cntlzd, SPARC - use lzcnt, MIPS clz */
#else
int pos = 0;
while (x >>= 1) pos++;
return pos;
#endif
}
#if defined(MOO_HAVE_UINT32_T) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_UINT32_T) #if defined(MOO_HAVE_UINT32_T) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_UINT32_T)
# define LOG2_FOR_POW2(x) LOG2_FOR_POW2_32(x) # define LOG2_FOR_POW2(x) LOG2_FOR_POW2_32(x)
#elif defined(MOO_HAVE_UINT64_T) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_UINT64_T) #elif defined(MOO_HAVE_UINT64_T) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_UINT64_T)
# define LOG2_FOR_POW2(x) LOG2_FOR_POW2_64(x) # define LOG2_FOR_POW2(x) LOG2_FOR_POW2_64(x)
#else #else
# define LOG2_FOR_POW2(x) get_pos_of_msb_set_pow2(x) # define LOG2_FOR_POW2(x) moo_get_pos_of_msb_set_pow2(x)
#endif #endif
#if (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT) && defined(MOO_HAVE_BUILTIN_UADD_OVERFLOW) #if (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT) && defined(MOO_HAVE_BUILTIN_UADD_OVERFLOW)
# define oow_add_overflow(a,b,c) __builtin_uadd_overflow(a,b,c) # define oow_add_overflow(a,b,c) __builtin_uadd_overflow(a,b,c)
#elif (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG) && defined(MOO_HAVE_BUILTIN_UADDL_OVERFLOW) #elif (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG) && defined(MOO_HAVE_BUILTIN_UADDL_OVERFLOW)
@ -1924,9 +1842,9 @@ static void divide_unsigned_array3 (moo_t* moo, const moo_liw_t* x, moo_oow_t xs
#endif #endif
y1 = y[ys - 1]; y1 = y[ys - 1];
/*s = MOO_LIW_BITS - ((y1 == 0)? -1: get_pos_of_msb_set(y1)) - 1;*/ /*s = MOO_LIW_BITS - ((y1 == 0)? -1: moo_get_pos_of_msb_set(y1)) - 1;*/
MOO_ASSERT (moo, y1 > 0); /* the highest word can't be non-zero in the context where this function is called */ MOO_ASSERT (moo, y1 > 0); /* the highest word can't be non-zero in the context where this function is called */
s = MOO_LIW_BITS - get_pos_of_msb_set(y1) - 1; s = MOO_LIW_BITS - moo_get_pos_of_msb_set(y1) - 1;
for (i = ys; i > 1; ) for (i = ys; i > 1; )
{ {
--i; --i;

View File

@ -42,7 +42,7 @@ floting-point conversion implementation*/
/* Max number conversion buffer length: /* Max number conversion buffer length:
* moo_intmax_t in base 2, plus NUL byte. */ * moo_intmax_t in base 2, plus NUL byte. */
#define MAXNBUF (MOO_SIZEOF(moo_intmax_t) * 8 + 1) #define MAXNBUF (MOO_SIZEOF(moo_intmax_t) * MOO_BITS_PER_BYTE + 1)
enum enum
{ {

View File

@ -999,7 +999,7 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v
#else #else
register int shift = i * MOO_SIZEOF(moo_oow_t); register int shift = i * MOO_SIZEOF(moo_oow_t);
moo_oow_t x = va_arg (ap, moo_oow_t); moo_oow_t x = va_arg (ap, moo_oow_t);
num |= (moo_uintmax_t)x << (shift * 8); num |= (moo_uintmax_t)x << (shift * MOO_BITS_PER_BYTE);
#endif #endif
} }
#else #else
@ -1043,7 +1043,7 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v
#else #else
register int shift = i * MOO_SIZEOF(moo_oow_t); register int shift = i * MOO_SIZEOF(moo_oow_t);
moo_oow_t x = va_arg (ap, moo_oow_t); moo_oow_t x = va_arg (ap, moo_oow_t);
num |= (moo_uintmax_t)x << (shift * 8); num |= (moo_uintmax_t)x << (shift * MOO_BITS_PER_BYTE);
#endif #endif
} }
#else #else

View File

@ -71,6 +71,8 @@
# define __ARM_ARCH 6 # define __ARM_ARCH 6
# elif defined(__ARM_ARCH_5__) # elif defined(__ARM_ARCH_5__)
# define __ARM_ARCH 5 # define __ARM_ARCH 5
# elif defined(__ARM_ARCH_4__)
# define __ARM_ARCH 4
# endif # endif
#endif #endif
@ -334,6 +336,13 @@
# error UNKNOWN INTMAX SIZE # error UNKNOWN INTMAX SIZE
#endif #endif
/* =========================================================================
* BASIC HARD-CODED DEFINES
* ========================================================================= */
#define MOO_BITS_PER_BYTE (8)
/* the maximum number of bch charaters to represent a single uch character */
#define MOO_BCSIZE_MAX 6
/* ========================================================================= /* =========================================================================
* BASIC MOO TYPES * BASIC MOO TYPES
* ========================================================================= */ * ========================================================================= */
@ -373,11 +382,15 @@ typedef moo_uintptr_t moo_oow_t;
typedef moo_intptr_t moo_ooi_t; typedef moo_intptr_t moo_ooi_t;
#define MOO_SIZEOF_OOW_T MOO_SIZEOF_UINTPTR_T #define MOO_SIZEOF_OOW_T MOO_SIZEOF_UINTPTR_T
#define MOO_SIZEOF_OOI_T MOO_SIZEOF_INTPTR_T #define MOO_SIZEOF_OOI_T MOO_SIZEOF_INTPTR_T
#define MOO_OOW_BITS (MOO_SIZEOF_OOW_T * MOO_BITS_PER_BYTE)
#define MOO_OOI_BITS (MOO_SIZEOF_OOI_T * MOO_BITS_PER_BYTE)
typedef moo_ushortptr_t moo_oohw_t; /* half word - half word */ typedef moo_ushortptr_t moo_oohw_t; /* half word - half word */
typedef moo_shortptr_t moo_oohi_t; /* signed half word */ typedef moo_shortptr_t moo_oohi_t; /* signed half word */
#define MOO_SIZEOF_OOHW_T MOO_SIZEOF_USHORTPTR_T #define MOO_SIZEOF_OOHW_T MOO_SIZEOF_USHORTPTR_T
#define MOO_SIZEOF_OOHI_T MOO_SIZEOF_SHORTPTR_T #define MOO_SIZEOF_OOHI_T MOO_SIZEOF_SHORTPTR_T
#define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * MOO_BITS_PER_BYTE)
#define MOO_OOHI_BITS (MOO_SIZEOF_OOHI_T * MOO_BITS_PER_BYTE)
struct moo_ucs_t struct moo_ucs_t
{ {
@ -409,14 +422,9 @@ typedef struct moo_bcs_t moo_bcs_t;
# define MOO_SIZEOF_OOCH_T MOO_SIZEOF_BCH_T # define MOO_SIZEOF_OOCH_T MOO_SIZEOF_BCH_T
#endif #endif
/* the maximum number of bch charaters to represent a single uch character */
#define MOO_BCSIZE_MAX 6
/* ========================================================================= /* =========================================================================
* BASIC OOP ENCODING * BASIC OOP ENCODING
* ========================================================================= */ * ========================================================================= */
/* actual structure defined in moo.h */ /* actual structure defined in moo.h */
typedef struct moo_obj_t moo_obj_t; typedef struct moo_obj_t moo_obj_t;
typedef struct moo_obj_t* moo_oop_t; typedef struct moo_obj_t* moo_oop_t;
@ -637,11 +645,11 @@ struct moo_ntime_t
/* make a bit mask that can mask off low n bits */ /* make a bit mask that can mask off low n bits */
#define MOO_LBMASK(type,n) (~(~((type)0) << (n))) #define MOO_LBMASK(type,n) (~(~((type)0) << (n)))
#define MOO_LBMASK_SAFE(type,n) (((n) < MOO_SIZEOF(type) * 8)? MOO_LBMASK(type,n): ~(type)0) #define MOO_LBMASK_SAFE(type,n) (((n) < MOO_SIZEOF(type) * MOO_BITS_PER_BYTE)? MOO_LBMASK(type,n): ~(type)0)
/* make a bit mask that can mask off hig n bits */ /* make a bit mask that can mask off hig n bits */
#define MOO_HBMASK(type,n) (~(~((type)0) >> (n))) #define MOO_HBMASK(type,n) (~(~((type)0) >> (n)))
#define MOO_HBMASK_SAFE(type,n) (((n) < MOO_SIZEOF(type) * 8)? MOO_HBMASK(type,n): ~(type)0) #define MOO_HBMASK_SAFE(type,n) (((n) < MOO_SIZEOF(type) * MOO_BITS_PER_BYTE)? MOO_HBMASK(type,n): ~(type)0)
/* get 'length' bits starting from the bit at the 'offset' */ /* get 'length' bits starting from the bit at the 'offset' */
#define MOO_GETBITS(type,value,offset,length) \ #define MOO_GETBITS(type,value,offset,length) \
@ -668,7 +676,7 @@ struct moo_ntime_t
* \endcode * \endcode
*/ */
/*#define MOO_BITS_MAX(type,nbits) ((((type)1) << (nbits)) - 1)*/ /*#define MOO_BITS_MAX(type,nbits) ((((type)1) << (nbits)) - 1)*/
#define MOO_BITS_MAX(type,nbits) ((~(type)0) >> (MOO_SIZEOF(type) * 8 - (nbits))) #define MOO_BITS_MAX(type,nbits) ((~(type)0) >> (MOO_SIZEOF(type) * MOO_BITS_PER_BYTE - (nbits)))
/* ========================================================================= /* =========================================================================
* MMGR * MMGR
@ -819,11 +827,11 @@ typedef struct moo_t moo_t;
#define MOO_TYPE_IS_UNSIGNED(type) (((type)0) < ((type)-1)) #define MOO_TYPE_IS_UNSIGNED(type) (((type)0) < ((type)-1))
#define MOO_TYPE_SIGNED_MAX(type) \ #define MOO_TYPE_SIGNED_MAX(type) \
((type)~((type)1 << ((type)MOO_SIZEOF(type) * 8 - 1))) ((type)~((type)1 << ((type)MOO_SIZEOF(type) * MOO_BITS_PER_BYTE - 1)))
#define MOO_TYPE_UNSIGNED_MAX(type) ((type)(~(type)0)) #define MOO_TYPE_UNSIGNED_MAX(type) ((type)(~(type)0))
#define MOO_TYPE_SIGNED_MIN(type) \ #define MOO_TYPE_SIGNED_MIN(type) \
((type)((type)1 << ((type)MOO_SIZEOF(type) * 8 - 1))) ((type)((type)1 << ((type)MOO_SIZEOF(type) * MOO_BITS_PER_BYTE - 1)))
#define MOO_TYPE_UNSIGNED_MIN(type) ((type)0) #define MOO_TYPE_UNSIGNED_MIN(type) ((type)0)
#define MOO_TYPE_MAX(type) \ #define MOO_TYPE_MAX(type) \

View File

@ -250,10 +250,10 @@
* 2. the maximum number of bit shifts can be represented in the moo_oow_t type. * 2. the maximum number of bit shifts can be represented in the moo_oow_t type.
*/ */
# define MOO_OBJ_SIZE_MAX ((moo_oow_t)MOO_SMOOI_MAX) # define MOO_OBJ_SIZE_MAX ((moo_oow_t)MOO_SMOOI_MAX)
# define MOO_OBJ_SIZE_BITS_MAX (MOO_OBJ_SIZE_MAX * 8) # define MOO_OBJ_SIZE_BITS_MAX (MOO_OBJ_SIZE_MAX * MOO_BITS_PER_BYTE)
#else #else
# define MOO_OBJ_SIZE_MAX ((moo_oow_t)MOO_TYPE_MAX(moo_oow_t)) # define MOO_OBJ_SIZE_MAX ((moo_oow_t)MOO_TYPE_MAX(moo_oow_t))
# define MOO_OBJ_SIZE_BITS_MAX (MOO_OBJ_SIZE_MAX * 8) # define MOO_OBJ_SIZE_BITS_MAX (MOO_OBJ_SIZE_MAX * MOO_BITS_PER_BYTE)
#endif #endif

View File

@ -736,8 +736,9 @@ MOO_EXPORT moo_oow_t moo_utf16_to_uc (
moo_uch_t* uc moo_uch_t* uc
); );
/* ------------------------------------------------------------------------- */ /* =========================================================================
* BIT SWAP
* ========================================================================= */
#if defined(MOO_HAVE_INLINE) #if defined(MOO_HAVE_INLINE)
#if defined(MOO_HAVE_UINT16_T) #if defined(MOO_HAVE_UINT16_T)
@ -748,8 +749,9 @@ static MOO_INLINE moo_uint16_t moo_bswap16 (moo_uint16_t x)
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386)) #elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
__asm__ /*volatile*/ ("xchgb %b0, %h0" : "=Q"(x): "0"(x)); __asm__ /*volatile*/ ("xchgb %b0, %h0" : "=Q"(x): "0"(x));
return x; return x;
#elif defined(__GNUC__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 6)) #elif defined(__GNUC__) && defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 6))
__asm__ /*volatile*/ ("rev16 %0, %0" : "+r"(x)); __asm__ /*volatile*/ ("rev16 %0, %0" : "+r"(x));
return x;
#else #else
return (x << 8) | (x >> 8); return (x << 8) | (x >> 8);
#endif #endif
@ -764,8 +766,12 @@ static MOO_INLINE moo_uint32_t moo_bswap32 (moo_uint32_t x)
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386)) #elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
__asm__ /*volatile*/ ("bswapl %0" : "=r"(x) : "0"(x)); __asm__ /*volatile*/ ("bswapl %0" : "=r"(x) : "0"(x));
return x; return x;
#elif defined(__GNUC__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 6)) #elif defined(__GNUC__) && defined(__aarch64__)
__asm__ /*volatile*/ ("rev32 %0, %0" : "+r"(x)); __asm__ /*volatile*/ ("rev32 %0, %0" : "+r"(x));
return x;
#elif defined(__GNUC__) && defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 6))
__asm__ /*volatile*/ ("rev %0, %0" : "+r"(x));
return x;
#elif defined(__GNUC__) && defined(__ARM_ARCH) #elif defined(__GNUC__) && defined(__ARM_ARCH)
moo_uint32_t tmp; moo_uint32_t tmp;
__asm__ /*volatile*/ ( __asm__ /*volatile*/ (
@ -794,7 +800,8 @@ static MOO_INLINE moo_uint64_t moo_bswap64 (moo_uint64_t x)
__asm__ /*volatile*/ ("bswapq %0" : "=r"(x) : "0"(x)); __asm__ /*volatile*/ ("bswapq %0" : "=r"(x) : "0"(x));
return x; return x;
#elif defined(__GNUC__) && defined(__aarch64__) #elif defined(__GNUC__) && defined(__aarch64__)
__asm__ /*volatile*/ ("rev64 %0, %0" : "+r"(x)); __asm__ /*volatile*/ ("rev %0, %0" : "+r"(x));
return x;
#else #else
return ((x >> 56)) | return ((x >> 56)) |
((x >> 40) & ((moo_uint64_t)0xff << 8)) | ((x >> 40) & ((moo_uint64_t)0xff << 8)) |
@ -837,17 +844,28 @@ static MOO_INLINE moo_uint128_t moo_bswap128 (moo_uint128_t x)
#else #else
#if defined(MOO_HAVE_UINT16_T) #if defined(MOO_HAVE_UINT16_T)
# if defined(MOO_HAVE_BUILTIN_BSWAP16)
# define moo_bswap16(x) ((moo_uint16_t)__builtin_bswap16((moo_uint16_t)(x)))
# else
# define moo_bswap16(x) ((moo_uint16_t)(((moo_uint16_t)(x)) << 8) | (((moo_uint16_t)(x)) >> 8)) # define moo_bswap16(x) ((moo_uint16_t)(((moo_uint16_t)(x)) << 8) | (((moo_uint16_t)(x)) >> 8))
# endif # endif
#endif
#if defined(MOO_HAVE_UINT32_T) #if defined(MOO_HAVE_UINT32_T)
# if defined(MOO_HAVE_BUILTIN_BSWAP32)
# define moo_bswap32(x) ((moo_uint32_t)__builtin_bswap32((moo_uint32_t)(x)))
# else
# define moo_bswap32(x) ((moo_uint32_t)(((((moo_uint32_t)(x)) >> 24)) | \ # define moo_bswap32(x) ((moo_uint32_t)(((((moo_uint32_t)(x)) >> 24)) | \
((((moo_uint32_t)(x)) >> 8) & ((moo_uint32_t)0xff << 8)) | \ ((((moo_uint32_t)(x)) >> 8) & ((moo_uint32_t)0xff << 8)) | \
((((moo_uint32_t)(x)) << 8) & ((moo_uint32_t)0xff << 16)) | \ ((((moo_uint32_t)(x)) << 8) & ((moo_uint32_t)0xff << 16)) | \
((((moo_uint32_t)(x)) << 24)))) ((((moo_uint32_t)(x)) << 24))))
# endif # endif
#endif
#if defined(MOO_HAVE_UINT64_T) #if defined(MOO_HAVE_UINT64_T)
# if defined(MOO_HAVE_BUILTIN_BSWAP64)
# define moo_bswap64(x) ((moo_uint64_t)__builtin_bswap64((moo_uint64_t)(x)))
# else
# define moo_bswap64(x) ((moo_uint64_t)(((((moo_uint64_t)(x)) >> 56)) | \ # define moo_bswap64(x) ((moo_uint64_t)(((((moo_uint64_t)(x)) >> 56)) | \
((((moo_uint64_t)(x)) >> 40) & ((moo_uint64_t)0xff << 8)) | \ ((((moo_uint64_t)(x)) >> 40) & ((moo_uint64_t)0xff << 8)) | \
((((moo_uint64_t)(x)) >> 24) & ((moo_uint64_t)0xff << 16)) | \ ((((moo_uint64_t)(x)) >> 24) & ((moo_uint64_t)0xff << 16)) | \
@ -857,8 +875,12 @@ static MOO_INLINE moo_uint128_t moo_bswap128 (moo_uint128_t x)
((((moo_uint64_t)(x)) << 40) & ((moo_uint64_t)0xff << 48)) | \ ((((moo_uint64_t)(x)) << 40) & ((moo_uint64_t)0xff << 48)) | \
((((moo_uint64_t)(x)) << 56)))) ((((moo_uint64_t)(x)) << 56))))
# endif # endif
#endif
#if defined(MOO_HAVE_UINT128_T) #if defined(MOO_HAVE_UINT128_T)
# if defined(MOO_HAVE_BUILTIN_BSWAP128)
# define moo_bswap128(x) ((moo_uint128_t)__builtin_bswap128((moo_uint128_t)(x)))
# else
# define moo_bswap128(x) ((moo_uint128_t)(((((moo_uint128_t)(x)) >> 120)) | \ # define moo_bswap128(x) ((moo_uint128_t)(((((moo_uint128_t)(x)) >> 120)) | \
((((moo_uint128_t)(x)) >> 104) & ((moo_uint128_t)0xff << 8)) | \ ((((moo_uint128_t)(x)) >> 104) & ((moo_uint128_t)0xff << 8)) | \
((((moo_uint128_t)(x)) >> 88) & ((moo_uint128_t)0xff << 16)) | \ ((((moo_uint128_t)(x)) >> 88) & ((moo_uint128_t)0xff << 16)) | \
@ -876,6 +898,7 @@ static MOO_INLINE moo_uint128_t moo_bswap128 (moo_uint128_t x)
((((moo_uint128_t)(x)) << 104) & ((moo_uint128_t)0xff << 112)) | \ ((((moo_uint128_t)(x)) << 104) & ((moo_uint128_t)0xff << 112)) | \
((((moo_uint128_t)(x)) << 120)))) ((((moo_uint128_t)(x)) << 120))))
# endif # endif
#endif
#endif /* MOO_HAVE_INLINE */ #endif /* MOO_HAVE_INLINE */
@ -961,9 +984,92 @@ static MOO_INLINE moo_uint128_t moo_bswap128 (moo_uint128_t x)
# error UNKNOWN ENDIAN # error UNKNOWN ENDIAN
#endif #endif
/* =========================================================================
* BIT POSITION
* ========================================================================= */
static MOO_INLINE int moo_get_pos_of_msb_set_pow2 (moo_oow_t x)
{
/* the caller must ensure that x is power of 2. if x happens to be zero,
* the return value is undefined as each method used may give different result. */
#if defined(MOO_HAVE_BUILTIN_CTZLL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG_LONG)
return __builtin_ctzll(x); /* count the number of trailing zeros */
#elif defined(MOO_HAVE_BUILTIN_CTZL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG)
return __builtin_ctzl(x); /* count the number of trailing zeros */
#elif defined(MOO_HAVE_BUILTIN_CTZ) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT)
return __builtin_ctz(x); /* count the number of trailing zeros */
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
moo_oow_t pos;
/* use the Bit Scan Forward instruction */
#if 1
__asm__ volatile (
"bsf %1,%0\n\t"
: "=r"(pos) /* output */
: "r"(x) /* input */
);
#else
__asm__ volatile (
"bsf %[X],%[EXP]\n\t"
: [EXP]"=r"(pos) /* output */
: [X]"r"(x) /* input */
);
#endif
return (int)pos;
#elif defined(__GNUC__) && defined(__aarch64__) || (defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 5)))
moo_oow_t n;
/* CLZ is available in ARMv5T and above. there is no instruction to
* count trailing zeros or something similar. using RBIT with CLZ
* would be good in ARMv6T2 and above to avoid further calculation
* afte CLZ */
__asm__ volatile (
"clz %0,%1\n\t"
: "=r"(n) /* output */
: "r"(x) /* input */
);
return (int)(MOO_OOW_BITS - n - 1);
/* TODO: PPC - use cntlz, cntlzw, cntlzd, SPARC - use lzcnt, MIPS clz */
#else
int pos = 0;
while (x >>= 1) pos++;
return pos;
#endif
}
static MOO_INLINE int moo_get_pos_of_msb_set (moo_oow_t x)
{
/* x doesn't have to be power of 2. if x is zero, the result is undefined */
#if defined(MOO_HAVE_BUILTIN_CLZLL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG_LONG)
return MOO_OOW_BITS - __builtin_clzll(x) - 1; /* count the number of leading zeros */
#elif defined(MOO_HAVE_BUILTIN_CLZL) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_LONG)
return MOO_OOW_BITS - __builtin_clzl(x) - 1; /* count the number of leading zeros */
#elif defined(MOO_HAVE_BUILTIN_CLZ) && (MOO_SIZEOF_OOW_T == MOO_SIZEOF_INT)
return MOO_OOW_BITS - __builtin_clz(x) - 1; /* count the number of leading zeros */
#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64) || defined(__i386) || defined(i386))
/* bit scan reverse. not all x86 CPUs have LZCNT. */
moo_oow_t pos;
__asm__ volatile (
"bsr %1,%0\n\t"
: "=r"(pos) /* output */
: "r"(x) /* input */
);
return (int)pos;
#elif defined(__GNUC__) && defined(__aarch64__) || (defined(__arm__) && (defined(__ARM_ARCH) && (__ARM_ARCH >= 5)))
moo_oow_t n;
__asm__ volatile (
"clz %0,%1\n\t"
: "=r"(n) /* output */
: "r"(x) /* input */
);
return (int)(MOO_OOW_BITS - n - 1);
/* TODO: PPC - use cntlz, cntlzw, cntlzd, SPARC - use lzcnt, MIPS clz */
#else
int pos = 0;
while (x >>= 1) pos++;
return pos;
#endif
}
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
#endif #endif

View File

@ -153,11 +153,7 @@ typedef struct moo_obj_byte_t* moo_oop_byte_t;
typedef struct moo_obj_halfword_t* moo_oop_halfword_t; typedef struct moo_obj_halfword_t* moo_oop_halfword_t;
typedef struct moo_obj_word_t* moo_oop_word_t; typedef struct moo_obj_word_t* moo_oop_word_t;
#define MOO_OOW_BITS (MOO_SIZEOF_OOW_T * 8) #define MOO_OOP_BITS (MOO_SIZEOF_OOP_T * MOO_BITS_PER_BYTE)
#define MOO_OOI_BITS (MOO_SIZEOF_OOI_T * 8)
#define MOO_OOP_BITS (MOO_SIZEOF_OOP_T * 8)
#define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * 8)
/* ========================================================================= /* =========================================================================
* BIGINT TYPES AND MACROS * BIGINT TYPES AND MACROS
@ -174,7 +170,7 @@ typedef struct moo_obj_word_t* moo_oop_word_t;
# define MOO_SIZEOF_LIW_T MOO_SIZEOF_OOW_T # define MOO_SIZEOF_LIW_T MOO_SIZEOF_OOW_T
# define MOO_SIZEOF_LIDW_T MOO_SIZEOF_UINTMAX_T # define MOO_SIZEOF_LIDW_T MOO_SIZEOF_UINTMAX_T
# define MOO_LIW_BITS MOO_OOW_BITS # define MOO_LIW_BITS MOO_OOW_BITS
# define MOO_LIDW_BITS (MOO_SIZEOF_UINTMAX_T * 8) # define MOO_LIDW_BITS (MOO_SIZEOF_UINTMAX_T * MOO_BITS_PER_BYTE)
typedef moo_oop_word_t moo_oop_liword_t; typedef moo_oop_word_t moo_oop_liword_t;
# define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_WORD # define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_WORD

View File

@ -256,7 +256,7 @@ static MOO_INLINE int _store_raw_int (moo_t* moo, moo_uint8_t* rawptr, moo_oow_t
} }
/* assume 2's complement */ /* assume 2's complement */
max = (moo_ooi_t)(~(moo_oow_t)0 >> ((MOO_SIZEOF_OOW_T - size) * 8 + 1)); max = (moo_ooi_t)(~(moo_oow_t)0 >> ((MOO_SIZEOF_OOW_T - size) * MOO_BITS_PER_BYTE + 1));
min = -max - 1; min = -max - 1;
if (w > max || w < min) if (w > max || w < min)
@ -314,7 +314,7 @@ static MOO_INLINE int _store_raw_uint (moo_t* moo, moo_uint8_t* rawptr, moo_oow_
return -1; return -1;
} }
max = (~(moo_oow_t)0 >> ((MOO_SIZEOF_OOW_T - size) * 8)); max = (~(moo_oow_t)0 >> ((MOO_SIZEOF_OOW_T - size) * MOO_BITS_PER_BYTE));
if (w > max) if (w > max)
{ {
moo_seterrbfmt (moo, MOO_ERANGE, "value %ju out of supported range for raw unsigned memory store", w); moo_seterrbfmt (moo, MOO_ERANGE, "value %ju out of supported range for raw unsigned memory store", w);

View File

@ -404,7 +404,7 @@ moo_bch_t* moo_find_bchar_in_bcstr (const moo_bch_t* ptr, moo_bch_t c)
moo_oow_t moo_byte_to_bcstr (moo_uint8_t byte, moo_bch_t* buf, moo_oow_t size, int flagged_radix, moo_bch_t fill) moo_oow_t moo_byte_to_bcstr (moo_uint8_t byte, moo_bch_t* buf, moo_oow_t size, int flagged_radix, moo_bch_t fill)
{ {
moo_bch_t tmp[(MOO_SIZEOF(moo_uint8_t) * 8)]; moo_bch_t tmp[(MOO_SIZEOF(moo_uint8_t) * MOO_BITS_PER_BYTE)];
moo_bch_t* p = tmp, * bp = buf, * be = buf + size - 1; moo_bch_t* p = tmp, * bp = buf, * be = buf + size - 1;
int radix; int radix;
moo_bch_t radix_char; moo_bch_t radix_char;

View File

@ -16,5 +16,6 @@ if WIN32
LDADD += $(SOCKET_LIBS) LDADD += $(SOCKET_LIBS)
endif endif
bin_PROGRAMS = t-001 bin_PROGRAMS = t-001 t-002
t_001_SOURCES = t-001.c t_001_SOURCES = t-001.c
t_002_SOURCES = t-002.c

View File

@ -89,7 +89,7 @@ POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
@WIN32_TRUE@am__append_1 = $(SOCKET_LIBS) @WIN32_TRUE@am__append_1 = $(SOCKET_LIBS)
bin_PROGRAMS = t-001$(EXEEXT) bin_PROGRAMS = t-001$(EXEEXT) t-002$(EXEEXT)
subdir = t subdir = t
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \
@ -110,9 +110,13 @@ PROGRAMS = $(bin_PROGRAMS)
am_t_001_OBJECTS = t-001.$(OBJEXT) am_t_001_OBJECTS = t-001.$(OBJEXT)
t_001_OBJECTS = $(am_t_001_OBJECTS) t_001_OBJECTS = $(am_t_001_OBJECTS)
t_001_LDADD = $(LDADD) t_001_LDADD = $(LDADD)
am_t_002_OBJECTS = t-002.$(OBJEXT)
t_002_OBJECTS = $(am_t_002_OBJECTS)
t_002_LDADD = $(LDADD)
am__DEPENDENCIES_1 = am__DEPENDENCIES_1 =
@WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) @WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
t_001_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) t_001_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
t_002_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent am__v_lt_0 = --silent
@ -151,8 +155,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 = am__v_CCLD_1 =
SOURCES = $(t_001_SOURCES) SOURCES = $(t_001_SOURCES) $(t_002_SOURCES)
DIST_SOURCES = $(t_001_SOURCES) DIST_SOURCES = $(t_001_SOURCES) $(t_002_SOURCES)
am__can_run_installinfo = \ am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \ case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \ n|no|NO) false;; \
@ -344,6 +348,7 @@ AM_CPPFLAGS = \
AM_LDFLAGS = -L$(abs_builddir)/../lib -L$(libdir) AM_LDFLAGS = -L$(abs_builddir)/../lib -L$(libdir)
LDADD = -lmoo $(PTHREAD_LIBS) $(am__append_1) LDADD = -lmoo $(PTHREAD_LIBS) $(am__append_1)
t_001_SOURCES = t-001.c t_001_SOURCES = t-001.c
t_002_SOURCES = t-002.c
all: all-am all: all-am
.SUFFIXES: .SUFFIXES:
@ -431,6 +436,10 @@ t-001$(EXEEXT): $(t_001_OBJECTS) $(t_001_DEPENDENCIES) $(EXTRA_t_001_DEPENDENCIE
@rm -f t-001$(EXEEXT) @rm -f t-001$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_001_OBJECTS) $(t_001_LDADD) $(LIBS) $(AM_V_CCLD)$(LINK) $(t_001_OBJECTS) $(t_001_LDADD) $(LIBS)
t-002$(EXEEXT): $(t_002_OBJECTS) $(t_002_DEPENDENCIES) $(EXTRA_t_002_DEPENDENCIES)
@rm -f t-002$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_002_OBJECTS) $(t_002_LDADD) $(LIBS)
mostlyclean-compile: mostlyclean-compile:
-rm -f *.$(OBJEXT) -rm -f *.$(OBJEXT)
@ -438,6 +447,7 @@ distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-001.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-001.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-002.Po@am__quote@
.c.o: .c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\

35
moo/t/t-002.c Normal file
View File

@ -0,0 +1,35 @@
/* test bit position functions */
#include <moo-utl.h>
#include <stdio.h>
#include "t.h"
int main ()
{
int i, j;
moo_oow_t v;
printf ("QSE_OOW_BITS => %d, sizeof(moo_oow_t)=%d\n", (int)MOO_OOW_BITS, (int)sizeof(moo_oow_t));
for (i = 0; i < MOO_OOW_BITS; i++)
{
v = ((moo_oow_t)1 << i);
j = moo_get_pos_of_msb_set_pow2(v);
printf ("msb(pow2) %d %d ==> %llx\n", i, j, (long long int)v);
T_ASSERT1 (i == j, "msb(pow2) position tester");
}
for (i = 0; i < MOO_OOW_BITS; i++)
{
v = ((moo_oow_t)1 << i);
v |= 1;
j = moo_get_pos_of_msb_set(v);
printf ("msb %d %d ==> %llx\n", i, j, (long long int)v);
T_ASSERT1 (i == j, "msb position tester");
}
return 0;
oops:
return -1;
}