aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c179
1 files changed, 44 insertions, 135 deletions
diff --git a/src/data.c b/src/data.c
index a6bfe50a3bb..4ef326e4cfd 100644
--- a/src/data.c
+++ b/src/data.c
@@ -22,6 +22,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include <stdio.h> 22#include <stdio.h>
23 23
24#include <byteswap.h> 24#include <byteswap.h>
25#include <count-one-bits.h>
26#include <count-trailing-zeros.h>
25#include <intprops.h> 27#include <intprops.h>
26 28
27#include "lisp.h" 29#include "lisp.h"
@@ -2971,108 +2973,16 @@ bool_vector_spare_mask (ptrdiff_t nr_bits)
2971 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1; 2973 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1;
2972} 2974}
2973 2975
2974#if _MSC_VER >= 1500 && (defined _M_IX86 || defined _M_X64) 2976#if SIZE_MAX <= UINT_MAX
2975# define USE_MSC_POPCOUNT 2977# define popcount_size_t count_one_bits
2976# define POPCOUNT_STATIC_INLINE static inline 2978#elif SIZE_MAX <= ULONG_MAX
2977#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 2979# define popcount_size_t count_one_bits_l
2978# define USE_GCC_POPCOUNT 2980#elif SIZE_MAX <= ULLONG_MAX
2979# if 199901L <= __STDC_VERSION__ || !__STRICT_ANSI__ 2981# define popcount_size_t count_one_bits_ll
2980# define POPCOUNT_STATIC_INLINE static inline
2981# endif
2982#else 2982#else
2983# define NEED_GENERIC_POPCOUNT 2983# error "size_t wider than long long? Please file a bug report."
2984#endif
2985#ifndef POPCOUNT_STATIC_INLINE
2986# define POPCOUNT_STATIC_INLINE static
2987#endif
2988
2989#ifdef USE_MSC_POPCOUNT
2990# define NEED_GENERIC_POPCOUNT
2991#endif
2992
2993#ifdef NEED_GENERIC_POPCOUNT
2994POPCOUNT_STATIC_INLINE unsigned int
2995popcount_size_t_generic (size_t val)
2996{
2997 unsigned short j;
2998 unsigned int count = 0;
2999
3000 for (j = 0; j < BITS_PER_SIZE_T; ++j)
3001 count += !!((((size_t) 1) << j) & val);
3002
3003 return count;
3004}
3005#endif 2984#endif
3006 2985
3007#ifdef USE_MSC_POPCOUNT
3008POPCOUNT_STATIC_INLINE unsigned int
3009popcount_size_t_msc (size_t val)
3010{
3011 unsigned int count;
3012
3013#pragma intrinsic __cpuid
3014 /* While gcc falls back to its own generic code if the machine on
3015 which it's running doesn't support popcount, we need to perform the
3016 detection and fallback ourselves when compiling with Microsoft's
3017 compiler. */
3018
3019 static enum {
3020 popcount_unknown_support,
3021 popcount_use_generic,
3022 popcount_use_intrinsic
3023 } popcount_state;
3024
3025 if (popcount_state == popcount_unknown_support)
3026 {
3027 int cpu_info[4];
3028 __cpuid (cpu_info, 1);
3029 if (cpu_info[2] & (1<<23)) /* See MSDN. */
3030 popcount_state = popcount_use_intrinsic;
3031 else
3032 popcount_state = popcount_use_generic;
3033 }
3034
3035 if (popcount_state == popcount_use_intrinsic)
3036 {
3037# if BITS_PER_SIZE_T == 64
3038# pragma intrinsic __popcnt64
3039 count = __popcnt64 (val);
3040# else
3041# pragma intrinsic __popcnt
3042 count = __popcnt (val);
3043# endif
3044 }
3045 else
3046 count = popcount_size_t_generic (val);
3047
3048 return count;
3049}
3050#endif /* USE_MSC_POPCOUNT */
3051
3052#ifdef USE_GCC_POPCOUNT
3053POPCOUNT_STATIC_INLINE unsigned int
3054popcount_size_t_gcc (size_t val)
3055{
3056# if BITS_PER_SIZE_T == 64
3057 return __builtin_popcountll (val);
3058# else
3059 return __builtin_popcount (val);
3060# endif
3061}
3062#endif /* USE_GCC_POPCOUNT */
3063
3064POPCOUNT_STATIC_INLINE unsigned int
3065popcount_size_t (size_t val)
3066{
3067#if defined USE_MSC_POPCOUNT
3068 return popcount_size_t_msc (val);
3069#elif defined USE_GCC_POPCOUNT
3070 return popcount_size_t_gcc (val);
3071#else
3072 return popcount_size_t_generic (val);
3073#endif
3074}
3075
3076enum bool_vector_op { bool_vector_exclusive_or, 2986enum bool_vector_op { bool_vector_exclusive_or,
3077 bool_vector_union, 2987 bool_vector_union,
3078 bool_vector_intersection, 2988 bool_vector_intersection,
@@ -3143,55 +3053,54 @@ bool_vector_binop_driver (Lisp_Object op1,
3143 3053
3144/* Compute the number of trailing zero bits in val. If val is zero, 3054/* Compute the number of trailing zero bits in val. If val is zero,
3145 return the number of bits in val. */ 3055 return the number of bits in val. */
3146static unsigned int 3056static int
3147count_trailing_zero_bits (size_t val) 3057count_trailing_zero_bits (size_t val)
3148{ 3058{
3059 if (SIZE_MAX == UINT_MAX)
3060 return count_trailing_zeros (val);
3061 if (SIZE_MAX == ULONG_MAX)
3062 return count_trailing_zeros_l (val);
3063# if HAVE_UNSIGNED_LONG_LONG_INT
3064 if (SIZE_MAX == ULLONG_MAX)
3065 return count_trailing_zeros_ll (val);
3066# endif
3067
3068 /* The rest of this code is for the unlikely platform where size_t differs
3069 in width from unsigned int, unsigned long, and unsigned long long. */
3149 if (val == 0) 3070 if (val == 0)
3150 return CHAR_BIT * sizeof (val); 3071 return CHAR_BIT * sizeof (val);
3151 3072 if (SIZE_MAX <= UINT_MAX)
3152#if defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 64 3073 return count_trailing_zeros (val);
3153 return __builtin_ctzll (val); 3074 if (SIZE_MAX <= ULONG_MAX)
3154#elif defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 32 3075 return count_trailing_zeros_l (val);
3155 return __builtin_ctz (val);
3156#elif _MSC_VER && BITS_PER_SIZE_T == 64
3157# pragma intrinsic _BitScanForward64
3158 { 3076 {
3159 /* No support test needed: support since 386. */ 3077# if HAVE_UNSIGNED_LONG_LONG_INT
3160 unsigned long result; 3078 verify (SIZE_MAX <= ULLONG_MAX);
3161 _BitScanForward64 (&result, val); 3079 return count_trailing_zeros_ll (val);
3162 return (unsigned int) result; 3080# else
3163 } 3081 verify (SIZE_MAX <= ULONG_MAX);
3164#elif _MSC_VER && BITS_PER_SIZE_T == 32 3082# endif
3165# pragma intrinsic _BitScanForward
3166 {
3167 /* No support test needed: support since 386. */
3168 unsigned long result;
3169 _BitScanForward (&result, val);
3170 return (unsigned int) result;
3171 }
3172#else
3173 {
3174 unsigned int count;
3175 count = 0;
3176 for (val = ~val; val & 1; val >>= 1)
3177 ++count;
3178
3179 return count;
3180 } 3083 }
3181#endif
3182} 3084}
3183 3085
3184static size_t 3086static size_t
3185size_t_to_host_endian (size_t val) 3087size_t_to_host_endian (size_t val)
3186{ 3088{
3187#ifdef WORDS_BIGENDIAN 3089#ifndef WORDS_BIGENDIAN
3188# if BITS_PER_SIZE_T == 64 3090 return val;
3189 return bswap_64 (val); 3091#elif SIZE_MAX >> 31 == 1
3190# else
3191 return bswap_32 (val); 3092 return bswap_32 (val);
3192# endif 3093#elif SIZE_MAX >> 31 >> 31 >> 1 == 1
3094 return bswap_64 (val);
3193#else 3095#else
3194 return val; 3096 int i;
3097 size_t r = 0;
3098 for (i = 0; i < sizeof val; i++)
3099 {
3100 r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1));
3101 val >>= CHAR_BIT;
3102 }
3103 return r;
3195#endif 3104#endif
3196} 3105}
3197 3106