sphlib
|
00001 /* $Id: sph_types.h 262 2011-07-21 01:15:22Z tp $ */ 00047 #ifndef SPH_TYPES_H__ 00048 #define SPH_TYPES_H__ 00049 00050 #include <limits.h> 00051 00052 /* 00053 * All our I/O functions are defined over octet streams. We do not know 00054 * how to handle input data if bytes are not octets. 00055 */ 00056 #if CHAR_BIT != 8 00057 #error This code requires 8-bit bytes 00058 #endif 00059 00060 /* ============= BEGIN documentation block for Doxygen ============ */ 00061 00062 #ifdef DOXYGEN_IGNORE 00063 00386 typedef __arch_dependant__ sph_u32; 00387 00392 typedef __arch_dependant__ sph_s32; 00393 00404 typedef __arch_dependant__ sph_u64; 00405 00410 typedef __arch_dependant__ sph_s64; 00411 00420 #define SPH_C32(x) 00421 00428 #define SPH_T32(x) 00429 00440 #define SPH_ROTL32(x, n) 00441 00452 #define SPH_ROTR32(x, n) 00453 00458 #define SPH_64 00459 00464 #define SPH_64_TRUE 00465 00475 #define SPH_C64(x) 00476 00484 #define SPH_T64(x) 00485 00497 #define SPH_ROTL64(x, n) 00498 00510 #define SPH_ROTR64(x, n) 00511 00519 #define SPH_INLINE 00520 00527 #define SPH_LITTLE_ENDIAN 00528 00535 #define SPH_BIG_ENDIAN 00536 00544 #define SPH_LITTLE_FAST 00545 00553 #define SPH_BIG_FAST 00554 00561 #define SPH_UPTR 00562 00568 #define SPH_UNALIGNED 00569 00578 static inline sph_u32 sph_bswap32(sph_u32 x); 00579 00589 static inline sph_u64 sph_bswap64(sph_u64 x); 00590 00598 static inline unsigned sph_dec16le(const void *src); 00599 00607 static inline void sph_enc16le(void *dst, unsigned val); 00608 00616 static inline unsigned sph_dec16be(const void *src); 00617 00625 static inline void sph_enc16be(void *dst, unsigned val); 00626 00634 static inline sph_u32 sph_dec32le(const void *src); 00635 00646 static inline sph_u32 sph_dec32le_aligned(const void *src); 00647 00655 static inline void sph_enc32le(void *dst, sph_u32 val); 00656 00667 static inline void sph_enc32le_aligned(void *dst, sph_u32 val); 00668 00676 static inline sph_u32 sph_dec32be(const void *src); 00677 00688 static inline sph_u32 sph_dec32be_aligned(const void *src); 00689 00697 static inline void sph_enc32be(void *dst, sph_u32 val); 00698 00709 static inline void sph_enc32be_aligned(void *dst, sph_u32 val); 00710 00719 static inline sph_u64 sph_dec64le(const void *src); 00720 00732 static inline sph_u64 sph_dec64le_aligned(const void *src); 00733 00742 static inline void sph_enc64le(void *dst, sph_u64 val); 00743 00756 static inline void sph_enc64le_aligned(void *dst, sph_u64 val); 00757 00766 static inline sph_u64 sph_dec64be(const void *src); 00767 00779 static inline sph_u64 sph_dec64be_aligned(const void *src); 00780 00789 static inline void sph_enc64be(void *dst, sph_u64 val); 00790 00803 static inline void sph_enc64be_aligned(void *dst, sph_u64 val); 00804 00805 #endif 00806 00807 /* ============== END documentation block for Doxygen ============= */ 00808 00809 #ifndef DOXYGEN_IGNORE 00810 00811 /* 00812 * We want to define the types "sph_u32" and "sph_u64" which hold 00813 * unsigned values of at least, respectively, 32 and 64 bits. These 00814 * tests should select appropriate types for most platforms. The 00815 * macro "SPH_64" is defined if the 64-bit is supported. 00816 */ 00817 00818 #undef SPH_64 00819 #undef SPH_64_TRUE 00820 00821 #if defined __STDC__ && __STDC_VERSION__ >= 199901L 00822 00823 /* 00824 * On C99 implementations, we can use <stdint.h> to get an exact 64-bit 00825 * type, if any, or otherwise use a wider type (which must exist, for 00826 * C99 conformance). 00827 */ 00828 00829 #include <stdint.h> 00830 00831 #ifdef UINT32_MAX 00832 typedef uint32_t sph_u32; 00833 typedef int32_t sph_s32; 00834 #else 00835 typedef uint_fast32_t sph_u32; 00836 typedef int_fast32_t sph_s32; 00837 #endif 00838 #if !SPH_NO_64 00839 #ifdef UINT64_MAX 00840 typedef uint64_t sph_u64; 00841 typedef int64_t sph_s64; 00842 #else 00843 typedef uint_fast64_t sph_u64; 00844 typedef int_fast64_t sph_s64; 00845 #endif 00846 #endif 00847 00848 #define SPH_C32(x) ((sph_u32)(x)) 00849 #if !SPH_NO_64 00850 #define SPH_C64(x) ((sph_u64)(x)) 00851 #define SPH_64 1 00852 #endif 00853 00854 #else 00855 00856 /* 00857 * On non-C99 systems, we use "unsigned int" if it is wide enough, 00858 * "unsigned long" otherwise. This supports all "reasonable" architectures. 00859 * We have to be cautious: pre-C99 preprocessors handle constants 00860 * differently in '#if' expressions. Hence the shifts to test UINT_MAX. 00861 */ 00862 00863 #if ((UINT_MAX >> 11) >> 11) >= 0x3FF 00864 00865 typedef unsigned int sph_u32; 00866 typedef int sph_s32; 00867 00868 #define SPH_C32(x) ((sph_u32)(x ## U)) 00869 00870 #else 00871 00872 typedef unsigned long sph_u32; 00873 typedef long sph_s32; 00874 00875 #define SPH_C32(x) ((sph_u32)(x ## UL)) 00876 00877 #endif 00878 00879 #if !SPH_NO_64 00880 00881 /* 00882 * We want a 64-bit type. We use "unsigned long" if it is wide enough (as 00883 * is common on 64-bit architectures such as AMD64, Alpha or Sparcv9), 00884 * "unsigned long long" otherwise, if available. We use ULLONG_MAX to 00885 * test whether "unsigned long long" is available; we also know that 00886 * gcc features this type, even if the libc header do not know it. 00887 */ 00888 00889 #if ((ULONG_MAX >> 31) >> 31) >= 3 00890 00891 typedef unsigned long sph_u64; 00892 typedef long sph_s64; 00893 00894 #define SPH_C64(x) ((sph_u64)(x ## UL)) 00895 00896 #define SPH_64 1 00897 00898 #elif ((ULLONG_MAX >> 31) >> 31) >= 3 || defined __GNUC__ 00899 00900 typedef unsigned long long sph_u64; 00901 typedef long long sph_s64; 00902 00903 #define SPH_C64(x) ((sph_u64)(x ## ULL)) 00904 00905 #define SPH_64 1 00906 00907 #else 00908 00909 /* 00910 * No 64-bit type... 00911 */ 00912 00913 #endif 00914 00915 #endif 00916 00917 #endif 00918 00919 /* 00920 * If the "unsigned long" type has length 64 bits or more, then this is 00921 * a "true" 64-bit architectures. This is also true with Visual C on 00922 * amd64, even though the "long" type is limited to 32 bits. 00923 */ 00924 #if SPH_64 && (((ULONG_MAX >> 31) >> 31) >= 3 || defined _M_X64) 00925 #define SPH_64_TRUE 1 00926 #endif 00927 00928 /* 00929 * Implementation note: some processors have specific opcodes to perform 00930 * a rotation. Recent versions of gcc recognize the expression above and 00931 * use the relevant opcodes, when appropriate. 00932 */ 00933 00934 #define SPH_T32(x) ((x) & SPH_C32(0xFFFFFFFF)) 00935 #define SPH_ROTL32(x, n) SPH_T32(((x) << (n)) | ((x) >> (32 - (n)))) 00936 #define SPH_ROTR32(x, n) SPH_ROTL32(x, (32 - (n))) 00937 00938 #if SPH_64 00939 00940 #define SPH_T64(x) ((x) & SPH_C64(0xFFFFFFFFFFFFFFFF)) 00941 #define SPH_ROTL64(x, n) SPH_T64(((x) << (n)) | ((x) >> (64 - (n)))) 00942 #define SPH_ROTR64(x, n) SPH_ROTL64(x, (64 - (n))) 00943 00944 #endif 00945 00946 #ifndef DOXYGEN_IGNORE 00947 /* 00948 * Define SPH_INLINE to be an "inline" qualifier, if available. We define 00949 * some small macro-like functions which benefit greatly from being inlined. 00950 */ 00951 #if (defined __STDC__ && __STDC_VERSION__ >= 199901L) || defined __GNUC__ 00952 #define SPH_INLINE inline 00953 #elif defined _MSC_VER 00954 #define SPH_INLINE __inline 00955 #else 00956 #define SPH_INLINE 00957 #endif 00958 #endif 00959 00960 /* 00961 * We define some macros which qualify the architecture. These macros 00962 * may be explicit set externally (e.g. as compiler parameters). The 00963 * code below sets those macros if they are not already defined. 00964 * 00965 * Most macros are boolean, thus evaluate to either zero or non-zero. 00966 * The SPH_UPTR macro is special, in that it evaluates to a C type, 00967 * or is not defined. 00968 * 00969 * SPH_UPTR if defined: unsigned type to cast pointers into 00970 * 00971 * SPH_UNALIGNED non-zero if unaligned accesses are efficient 00972 * SPH_LITTLE_ENDIAN non-zero if architecture is known to be little-endian 00973 * SPH_BIG_ENDIAN non-zero if architecture is known to be big-endian 00974 * SPH_LITTLE_FAST non-zero if little-endian decoding is fast 00975 * SPH_BIG_FAST non-zero if big-endian decoding is fast 00976 * 00977 * If SPH_UPTR is defined, then encoding and decoding of 32-bit and 64-bit 00978 * values will try to be "smart". Either SPH_LITTLE_ENDIAN or SPH_BIG_ENDIAN 00979 * _must_ be non-zero in those situations. The 32-bit and 64-bit types 00980 * _must_ also have an exact width. 00981 * 00982 * SPH_SPARCV9_GCC_32 UltraSPARC-compatible with gcc, 32-bit mode 00983 * SPH_SPARCV9_GCC_64 UltraSPARC-compatible with gcc, 64-bit mode 00984 * SPH_SPARCV9_GCC UltraSPARC-compatible with gcc 00985 * SPH_I386_GCC x86-compatible (32-bit) with gcc 00986 * SPH_I386_MSVC x86-compatible (32-bit) with Microsoft Visual C 00987 * SPH_AMD64_GCC x86-compatible (64-bit) with gcc 00988 * SPH_AMD64_MSVC x86-compatible (64-bit) with Microsoft Visual C 00989 * SPH_PPC32_GCC PowerPC, 32-bit, with gcc 00990 * SPH_PPC64_GCC PowerPC, 64-bit, with gcc 00991 * 00992 * TODO: enhance automatic detection, for more architectures and compilers. 00993 * Endianness is the most important. SPH_UNALIGNED and SPH_UPTR help with 00994 * some very fast functions (e.g. MD4) when using unaligned input data. 00995 * The CPU-specific-with-GCC macros are useful only for inline assembly, 00996 * normally restrained to this header file. 00997 */ 00998 00999 /* 01000 * 32-bit x86, aka "i386 compatible". 01001 */ 01002 #if defined __i386__ || defined _M_IX86 01003 01004 #define SPH_DETECT_UNALIGNED 1 01005 #define SPH_DETECT_LITTLE_ENDIAN 1 01006 #define SPH_DETECT_UPTR sph_u32 01007 #ifdef __GNUC__ 01008 #define SPH_DETECT_I386_GCC 1 01009 #endif 01010 #ifdef _MSC_VER 01011 #define SPH_DETECT_I386_MSVC 1 01012 #endif 01013 01014 /* 01015 * 64-bit x86, hereafter known as "amd64". 01016 */ 01017 #elif defined __x86_64 || defined _M_X64 01018 01019 #define SPH_DETECT_UNALIGNED 1 01020 #define SPH_DETECT_LITTLE_ENDIAN 1 01021 #define SPH_DETECT_UPTR sph_u64 01022 #ifdef __GNUC__ 01023 #define SPH_DETECT_AMD64_GCC 1 01024 #endif 01025 #ifdef _MSC_VER 01026 #define SPH_DETECT_AMD64_MSVC 1 01027 #endif 01028 01029 /* 01030 * 64-bit Sparc architecture (implies v9). 01031 */ 01032 #elif ((defined __sparc__ || defined __sparc) && defined __arch64__) \ 01033 || defined __sparcv9 01034 01035 #define SPH_DETECT_BIG_ENDIAN 1 01036 #define SPH_DETECT_UPTR sph_u64 01037 #ifdef __GNUC__ 01038 #define SPH_DETECT_SPARCV9_GCC_64 1 01039 #define SPH_DETECT_LITTLE_FAST 1 01040 #endif 01041 01042 /* 01043 * 32-bit Sparc. 01044 */ 01045 #elif (defined __sparc__ || defined __sparc) \ 01046 && !(defined __sparcv9 || defined __arch64__) 01047 01048 #define SPH_DETECT_BIG_ENDIAN 1 01049 #define SPH_DETECT_UPTR sph_u32 01050 #if defined __GNUC__ && defined __sparc_v9__ 01051 #define SPH_DETECT_SPARCV9_GCC_32 1 01052 #define SPH_DETECT_LITTLE_FAST 1 01053 #endif 01054 01055 /* 01056 * ARM, little-endian. 01057 */ 01058 #elif defined __arm__ && __ARMEL__ 01059 01060 #define SPH_DETECT_LITTLE_ENDIAN 1 01061 01062 /* 01063 * MIPS, little-endian. 01064 */ 01065 #elif MIPSEL || _MIPSEL || __MIPSEL || __MIPSEL__ 01066 01067 #define SPH_DETECT_LITTLE_ENDIAN 1 01068 01069 /* 01070 * MIPS, big-endian. 01071 */ 01072 #elif MIPSEB || _MIPSEB || __MIPSEB || __MIPSEB__ 01073 01074 #define SPH_DETECT_BIG_ENDIAN 1 01075 01076 /* 01077 * PowerPC. 01078 */ 01079 #elif defined __powerpc__ || defined __POWERPC__ || defined __ppc__ \ 01080 || defined _ARCH_PPC 01081 01082 /* 01083 * Note: we do not declare cross-endian access to be "fast": even if 01084 * using inline assembly, implementation should still assume that 01085 * keeping the decoded word in a temporary is faster than decoding 01086 * it again. 01087 */ 01088 #if defined __GNUC__ 01089 #if SPH_64_TRUE 01090 #define SPH_DETECT_PPC64_GCC 1 01091 #else 01092 #define SPH_DETECT_PPC32_GCC 1 01093 #endif 01094 #endif 01095 01096 #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN 01097 #define SPH_DETECT_BIG_ENDIAN 1 01098 #elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN 01099 #define SPH_DETECT_LITTLE_ENDIAN 1 01100 #endif 01101 01102 /* 01103 * Itanium, 64-bit. 01104 */ 01105 #elif defined __ia64 || defined __ia64__ \ 01106 || defined __itanium__ || defined _M_IA64 01107 01108 #if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN 01109 #define SPH_DETECT_BIG_ENDIAN 1 01110 #else 01111 #define SPH_DETECT_LITTLE_ENDIAN 1 01112 #endif 01113 #if defined __LP64__ || defined _LP64 01114 #define SPH_DETECT_UPTR sph_u64 01115 #else 01116 #define SPH_DETECT_UPTR sph_u32 01117 #endif 01118 01119 #endif 01120 01121 #if defined SPH_DETECT_SPARCV9_GCC_32 || defined SPH_DETECT_SPARCV9_GCC_64 01122 #define SPH_DETECT_SPARCV9_GCC 1 01123 #endif 01124 01125 #if defined SPH_DETECT_UNALIGNED && !defined SPH_UNALIGNED 01126 #define SPH_UNALIGNED SPH_DETECT_UNALIGNED 01127 #endif 01128 #if defined SPH_DETECT_UPTR && !defined SPH_UPTR 01129 #define SPH_UPTR SPH_DETECT_UPTR 01130 #endif 01131 #if defined SPH_DETECT_LITTLE_ENDIAN && !defined SPH_LITTLE_ENDIAN 01132 #define SPH_LITTLE_ENDIAN SPH_DETECT_LITTLE_ENDIAN 01133 #endif 01134 #if defined SPH_DETECT_BIG_ENDIAN && !defined SPH_BIG_ENDIAN 01135 #define SPH_BIG_ENDIAN SPH_DETECT_BIG_ENDIAN 01136 #endif 01137 #if defined SPH_DETECT_LITTLE_FAST && !defined SPH_LITTLE_FAST 01138 #define SPH_LITTLE_FAST SPH_DETECT_LITTLE_FAST 01139 #endif 01140 #if defined SPH_DETECT_BIG_FAST && !defined SPH_BIG_FAST 01141 #define SPH_BIG_FAST SPH_DETECT_BIG_FAST 01142 #endif 01143 #if defined SPH_DETECT_SPARCV9_GCC_32 && !defined SPH_SPARCV9_GCC_32 01144 #define SPH_SPARCV9_GCC_32 SPH_DETECT_SPARCV9_GCC_32 01145 #endif 01146 #if defined SPH_DETECT_SPARCV9_GCC_64 && !defined SPH_SPARCV9_GCC_64 01147 #define SPH_SPARCV9_GCC_64 SPH_DETECT_SPARCV9_GCC_64 01148 #endif 01149 #if defined SPH_DETECT_SPARCV9_GCC && !defined SPH_SPARCV9_GCC 01150 #define SPH_SPARCV9_GCC SPH_DETECT_SPARCV9_GCC 01151 #endif 01152 #if defined SPH_DETECT_I386_GCC && !defined SPH_I386_GCC 01153 #define SPH_I386_GCC SPH_DETECT_I386_GCC 01154 #endif 01155 #if defined SPH_DETECT_I386_MSVC && !defined SPH_I386_MSVC 01156 #define SPH_I386_MSVC SPH_DETECT_I386_MSVC 01157 #endif 01158 #if defined SPH_DETECT_AMD64_GCC && !defined SPH_AMD64_GCC 01159 #define SPH_AMD64_GCC SPH_DETECT_AMD64_GCC 01160 #endif 01161 #if defined SPH_DETECT_AMD64_MSVC && !defined SPH_AMD64_MSVC 01162 #define SPH_AMD64_MSVC SPH_DETECT_AMD64_MSVC 01163 #endif 01164 #if defined SPH_DETECT_PPC32_GCC && !defined SPH_PPC32_GCC 01165 #define SPH_PPC32_GCC SPH_DETECT_PPC32_GCC 01166 #endif 01167 #if defined SPH_DETECT_PPC64_GCC && !defined SPH_PPC64_GCC 01168 #define SPH_PPC64_GCC SPH_DETECT_PPC64_GCC 01169 #endif 01170 01171 #if SPH_LITTLE_ENDIAN && !defined SPH_LITTLE_FAST 01172 #define SPH_LITTLE_FAST 1 01173 #endif 01174 #if SPH_BIG_ENDIAN && !defined SPH_BIG_FAST 01175 #define SPH_BIG_FAST 1 01176 #endif 01177 01178 #if defined SPH_UPTR && !(SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN) 01179 #error SPH_UPTR defined, but endianness is not known. 01180 #endif 01181 01182 #if SPH_I386_GCC && !SPH_NO_ASM 01183 01184 /* 01185 * On x86 32-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit 01186 * values. 01187 */ 01188 01189 static SPH_INLINE sph_u32 01190 sph_bswap32(sph_u32 x) 01191 { 01192 __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); 01193 return x; 01194 } 01195 01196 #if SPH_64 01197 01198 static SPH_INLINE sph_u64 01199 sph_bswap64(sph_u64 x) 01200 { 01201 return ((sph_u64)sph_bswap32((sph_u32)x) << 32) 01202 | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); 01203 } 01204 01205 #endif 01206 01207 #elif SPH_AMD64_GCC && !SPH_NO_ASM 01208 01209 /* 01210 * On x86 64-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit 01211 * and 64-bit values. 01212 */ 01213 01214 static SPH_INLINE sph_u32 01215 sph_bswap32(sph_u32 x) 01216 { 01217 __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); 01218 return x; 01219 } 01220 01221 #if SPH_64 01222 01223 static SPH_INLINE sph_u64 01224 sph_bswap64(sph_u64 x) 01225 { 01226 __asm__ __volatile__ ("bswapq %0" : "=r" (x) : "0" (x)); 01227 return x; 01228 } 01229 01230 #endif 01231 01232 /* 01233 * Disabled code. Apparently, Microsoft Visual C 2005 is smart enough 01234 * to generate proper opcodes for endianness swapping with the pure C 01235 * implementation below. 01236 * 01237 01238 #elif SPH_I386_MSVC && !SPH_NO_ASM 01239 01240 static __inline sph_u32 __declspec(naked) __fastcall 01241 sph_bswap32(sph_u32 x) 01242 { 01243 __asm { 01244 bswap ecx 01245 mov eax,ecx 01246 ret 01247 } 01248 } 01249 01250 #if SPH_64 01251 01252 static SPH_INLINE sph_u64 01253 sph_bswap64(sph_u64 x) 01254 { 01255 return ((sph_u64)sph_bswap32((sph_u32)x) << 32) 01256 | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); 01257 } 01258 01259 #endif 01260 01261 * 01262 * [end of disabled code] 01263 */ 01264 01265 #else 01266 01267 static SPH_INLINE sph_u32 01268 sph_bswap32(sph_u32 x) 01269 { 01270 x = SPH_T32((x << 16) | (x >> 16)); 01271 x = ((x & SPH_C32(0xFF00FF00)) >> 8) 01272 | ((x & SPH_C32(0x00FF00FF)) << 8); 01273 return x; 01274 } 01275 01276 #if SPH_64 01277 01284 static SPH_INLINE sph_u64 01285 sph_bswap64(sph_u64 x) 01286 { 01287 x = SPH_T64((x << 32) | (x >> 32)); 01288 x = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16) 01289 | ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16); 01290 x = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8) 01291 | ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8); 01292 return x; 01293 } 01294 01295 #endif 01296 01297 #endif 01298 01299 #if SPH_SPARCV9_GCC && !SPH_NO_ASM 01300 01301 /* 01302 * On UltraSPARC systems, native ordering is big-endian, but it is 01303 * possible to perform little-endian read accesses by specifying the 01304 * address space 0x88 (ASI_PRIMARY_LITTLE). Basically, either we use 01305 * the opcode "lda [%reg]0x88,%dst", where %reg is the register which 01306 * contains the source address and %dst is the destination register, 01307 * or we use "lda [%reg+imm]%asi,%dst", which uses the %asi register 01308 * to get the address space name. The latter format is better since it 01309 * combines an addition and the actual access in a single opcode; but 01310 * it requires the setting (and subsequent resetting) of %asi, which is 01311 * slow. Some operations (i.e. MD5 compression function) combine many 01312 * successive little-endian read accesses, which may share the same 01313 * %asi setting. The macros below contain the appropriate inline 01314 * assembly. 01315 */ 01316 01317 #define SPH_SPARCV9_SET_ASI \ 01318 sph_u32 sph_sparcv9_asi; \ 01319 __asm__ __volatile__ ( \ 01320 "rd %%asi,%0\n\twr %%g0,0x88,%%asi" : "=r" (sph_sparcv9_asi)); 01321 01322 #define SPH_SPARCV9_RESET_ASI \ 01323 __asm__ __volatile__ ("wr %%g0,%0,%%asi" : : "r" (sph_sparcv9_asi)); 01324 01325 #define SPH_SPARCV9_DEC32LE(base, idx) ({ \ 01326 sph_u32 sph_sparcv9_tmp; \ 01327 __asm__ __volatile__ ("lda [%1+" #idx "*4]%%asi,%0" \ 01328 : "=r" (sph_sparcv9_tmp) : "r" (base)); \ 01329 sph_sparcv9_tmp; \ 01330 }) 01331 01332 #endif 01333 01334 static SPH_INLINE void 01335 sph_enc16be(void *dst, unsigned val) 01336 { 01337 ((unsigned char *)dst)[0] = (val >> 8); 01338 ((unsigned char *)dst)[1] = val; 01339 } 01340 01341 static SPH_INLINE unsigned 01342 sph_dec16be(const void *src) 01343 { 01344 return ((unsigned)(((const unsigned char *)src)[0]) << 8) 01345 | (unsigned)(((const unsigned char *)src)[1]); 01346 } 01347 01348 static SPH_INLINE void 01349 sph_enc16le(void *dst, unsigned val) 01350 { 01351 ((unsigned char *)dst)[0] = val; 01352 ((unsigned char *)dst)[1] = val >> 8; 01353 } 01354 01355 static SPH_INLINE unsigned 01356 sph_dec16le(const void *src) 01357 { 01358 return (unsigned)(((const unsigned char *)src)[0]) 01359 | ((unsigned)(((const unsigned char *)src)[1]) << 8); 01360 } 01361 01368 static SPH_INLINE void 01369 sph_enc32be(void *dst, sph_u32 val) 01370 { 01371 #if defined SPH_UPTR 01372 #if SPH_UNALIGNED 01373 #if SPH_LITTLE_ENDIAN 01374 val = sph_bswap32(val); 01375 #endif 01376 *(sph_u32 *)dst = val; 01377 #else 01378 if (((SPH_UPTR)dst & 3) == 0) { 01379 #if SPH_LITTLE_ENDIAN 01380 val = sph_bswap32(val); 01381 #endif 01382 *(sph_u32 *)dst = val; 01383 } else { 01384 ((unsigned char *)dst)[0] = (val >> 24); 01385 ((unsigned char *)dst)[1] = (val >> 16); 01386 ((unsigned char *)dst)[2] = (val >> 8); 01387 ((unsigned char *)dst)[3] = val; 01388 } 01389 #endif 01390 #else 01391 ((unsigned char *)dst)[0] = (val >> 24); 01392 ((unsigned char *)dst)[1] = (val >> 16); 01393 ((unsigned char *)dst)[2] = (val >> 8); 01394 ((unsigned char *)dst)[3] = val; 01395 #endif 01396 } 01397 01405 static SPH_INLINE void 01406 sph_enc32be_aligned(void *dst, sph_u32 val) 01407 { 01408 #if SPH_LITTLE_ENDIAN 01409 *(sph_u32 *)dst = sph_bswap32(val); 01410 #elif SPH_BIG_ENDIAN 01411 *(sph_u32 *)dst = val; 01412 #else 01413 ((unsigned char *)dst)[0] = (val >> 24); 01414 ((unsigned char *)dst)[1] = (val >> 16); 01415 ((unsigned char *)dst)[2] = (val >> 8); 01416 ((unsigned char *)dst)[3] = val; 01417 #endif 01418 } 01419 01426 static SPH_INLINE sph_u32 01427 sph_dec32be(const void *src) 01428 { 01429 #if defined SPH_UPTR 01430 #if SPH_UNALIGNED 01431 #if SPH_LITTLE_ENDIAN 01432 return sph_bswap32(*(const sph_u32 *)src); 01433 #else 01434 return *(const sph_u32 *)src; 01435 #endif 01436 #else 01437 if (((SPH_UPTR)src & 3) == 0) { 01438 #if SPH_LITTLE_ENDIAN 01439 return sph_bswap32(*(const sph_u32 *)src); 01440 #else 01441 return *(const sph_u32 *)src; 01442 #endif 01443 } else { 01444 return ((sph_u32)(((const unsigned char *)src)[0]) << 24) 01445 | ((sph_u32)(((const unsigned char *)src)[1]) << 16) 01446 | ((sph_u32)(((const unsigned char *)src)[2]) << 8) 01447 | (sph_u32)(((const unsigned char *)src)[3]); 01448 } 01449 #endif 01450 #else 01451 return ((sph_u32)(((const unsigned char *)src)[0]) << 24) 01452 | ((sph_u32)(((const unsigned char *)src)[1]) << 16) 01453 | ((sph_u32)(((const unsigned char *)src)[2]) << 8) 01454 | (sph_u32)(((const unsigned char *)src)[3]); 01455 #endif 01456 } 01457 01465 static SPH_INLINE sph_u32 01466 sph_dec32be_aligned(const void *src) 01467 { 01468 #if SPH_LITTLE_ENDIAN 01469 return sph_bswap32(*(const sph_u32 *)src); 01470 #elif SPH_BIG_ENDIAN 01471 return *(const sph_u32 *)src; 01472 #else 01473 return ((sph_u32)(((const unsigned char *)src)[0]) << 24) 01474 | ((sph_u32)(((const unsigned char *)src)[1]) << 16) 01475 | ((sph_u32)(((const unsigned char *)src)[2]) << 8) 01476 | (sph_u32)(((const unsigned char *)src)[3]); 01477 #endif 01478 } 01479 01486 static SPH_INLINE void 01487 sph_enc32le(void *dst, sph_u32 val) 01488 { 01489 #if defined SPH_UPTR 01490 #if SPH_UNALIGNED 01491 #if SPH_BIG_ENDIAN 01492 val = sph_bswap32(val); 01493 #endif 01494 *(sph_u32 *)dst = val; 01495 #else 01496 if (((SPH_UPTR)dst & 3) == 0) { 01497 #if SPH_BIG_ENDIAN 01498 val = sph_bswap32(val); 01499 #endif 01500 *(sph_u32 *)dst = val; 01501 } else { 01502 ((unsigned char *)dst)[0] = val; 01503 ((unsigned char *)dst)[1] = (val >> 8); 01504 ((unsigned char *)dst)[2] = (val >> 16); 01505 ((unsigned char *)dst)[3] = (val >> 24); 01506 } 01507 #endif 01508 #else 01509 ((unsigned char *)dst)[0] = val; 01510 ((unsigned char *)dst)[1] = (val >> 8); 01511 ((unsigned char *)dst)[2] = (val >> 16); 01512 ((unsigned char *)dst)[3] = (val >> 24); 01513 #endif 01514 } 01515 01523 static SPH_INLINE void 01524 sph_enc32le_aligned(void *dst, sph_u32 val) 01525 { 01526 #if SPH_LITTLE_ENDIAN 01527 *(sph_u32 *)dst = val; 01528 #elif SPH_BIG_ENDIAN 01529 *(sph_u32 *)dst = sph_bswap32(val); 01530 #else 01531 ((unsigned char *)dst)[0] = val; 01532 ((unsigned char *)dst)[1] = (val >> 8); 01533 ((unsigned char *)dst)[2] = (val >> 16); 01534 ((unsigned char *)dst)[3] = (val >> 24); 01535 #endif 01536 } 01537 01544 static SPH_INLINE sph_u32 01545 sph_dec32le(const void *src) 01546 { 01547 #if defined SPH_UPTR 01548 #if SPH_UNALIGNED 01549 #if SPH_BIG_ENDIAN 01550 return sph_bswap32(*(const sph_u32 *)src); 01551 #else 01552 return *(const sph_u32 *)src; 01553 #endif 01554 #else 01555 if (((SPH_UPTR)src & 3) == 0) { 01556 #if SPH_BIG_ENDIAN 01557 #if SPH_SPARCV9_GCC && !SPH_NO_ASM 01558 sph_u32 tmp; 01559 01560 /* 01561 * "__volatile__" is needed here because without it, 01562 * gcc-3.4.3 miscompiles the code and performs the 01563 * access before the test on the address, thus triggering 01564 * a bus error... 01565 */ 01566 __asm__ __volatile__ ( 01567 "lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); 01568 return tmp; 01569 /* 01570 * On PowerPC, this turns out not to be worth the effort: the inline 01571 * assembly makes GCC optimizer uncomfortable, which tends to nullify 01572 * the decoding gains. 01573 * 01574 * For most hash functions, using this inline assembly trick changes 01575 * hashing speed by less than 5% and often _reduces_ it. The biggest 01576 * gains are for MD4 (+11%) and CubeHash (+30%). For all others, it is 01577 * less then 10%. The speed gain on CubeHash is probably due to the 01578 * chronic shortage of registers that CubeHash endures; for the other 01579 * functions, the generic code appears to be efficient enough already. 01580 * 01581 #elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM 01582 sph_u32 tmp; 01583 01584 __asm__ __volatile__ ( 01585 "lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); 01586 return tmp; 01587 */ 01588 #else 01589 return sph_bswap32(*(const sph_u32 *)src); 01590 #endif 01591 #else 01592 return *(const sph_u32 *)src; 01593 #endif 01594 } else { 01595 return (sph_u32)(((const unsigned char *)src)[0]) 01596 | ((sph_u32)(((const unsigned char *)src)[1]) << 8) 01597 | ((sph_u32)(((const unsigned char *)src)[2]) << 16) 01598 | ((sph_u32)(((const unsigned char *)src)[3]) << 24); 01599 } 01600 #endif 01601 #else 01602 return (sph_u32)(((const unsigned char *)src)[0]) 01603 | ((sph_u32)(((const unsigned char *)src)[1]) << 8) 01604 | ((sph_u32)(((const unsigned char *)src)[2]) << 16) 01605 | ((sph_u32)(((const unsigned char *)src)[3]) << 24); 01606 #endif 01607 } 01608 01616 static SPH_INLINE sph_u32 01617 sph_dec32le_aligned(const void *src) 01618 { 01619 #if SPH_LITTLE_ENDIAN 01620 return *(const sph_u32 *)src; 01621 #elif SPH_BIG_ENDIAN 01622 #if SPH_SPARCV9_GCC && !SPH_NO_ASM 01623 sph_u32 tmp; 01624 01625 __asm__ __volatile__ ("lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); 01626 return tmp; 01627 /* 01628 * Not worth it generally. 01629 * 01630 #elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM 01631 sph_u32 tmp; 01632 01633 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); 01634 return tmp; 01635 */ 01636 #else 01637 return sph_bswap32(*(const sph_u32 *)src); 01638 #endif 01639 #else 01640 return (sph_u32)(((const unsigned char *)src)[0]) 01641 | ((sph_u32)(((const unsigned char *)src)[1]) << 8) 01642 | ((sph_u32)(((const unsigned char *)src)[2]) << 16) 01643 | ((sph_u32)(((const unsigned char *)src)[3]) << 24); 01644 #endif 01645 } 01646 01647 #if SPH_64 01648 01655 static SPH_INLINE void 01656 sph_enc64be(void *dst, sph_u64 val) 01657 { 01658 #if defined SPH_UPTR 01659 #if SPH_UNALIGNED 01660 #if SPH_LITTLE_ENDIAN 01661 val = sph_bswap64(val); 01662 #endif 01663 *(sph_u64 *)dst = val; 01664 #else 01665 if (((SPH_UPTR)dst & 7) == 0) { 01666 #if SPH_LITTLE_ENDIAN 01667 val = sph_bswap64(val); 01668 #endif 01669 *(sph_u64 *)dst = val; 01670 } else { 01671 ((unsigned char *)dst)[0] = (val >> 56); 01672 ((unsigned char *)dst)[1] = (val >> 48); 01673 ((unsigned char *)dst)[2] = (val >> 40); 01674 ((unsigned char *)dst)[3] = (val >> 32); 01675 ((unsigned char *)dst)[4] = (val >> 24); 01676 ((unsigned char *)dst)[5] = (val >> 16); 01677 ((unsigned char *)dst)[6] = (val >> 8); 01678 ((unsigned char *)dst)[7] = val; 01679 } 01680 #endif 01681 #else 01682 ((unsigned char *)dst)[0] = (val >> 56); 01683 ((unsigned char *)dst)[1] = (val >> 48); 01684 ((unsigned char *)dst)[2] = (val >> 40); 01685 ((unsigned char *)dst)[3] = (val >> 32); 01686 ((unsigned char *)dst)[4] = (val >> 24); 01687 ((unsigned char *)dst)[5] = (val >> 16); 01688 ((unsigned char *)dst)[6] = (val >> 8); 01689 ((unsigned char *)dst)[7] = val; 01690 #endif 01691 } 01692 01700 static SPH_INLINE void 01701 sph_enc64be_aligned(void *dst, sph_u64 val) 01702 { 01703 #if SPH_LITTLE_ENDIAN 01704 *(sph_u64 *)dst = sph_bswap64(val); 01705 #elif SPH_BIG_ENDIAN 01706 *(sph_u64 *)dst = val; 01707 #else 01708 ((unsigned char *)dst)[0] = (val >> 56); 01709 ((unsigned char *)dst)[1] = (val >> 48); 01710 ((unsigned char *)dst)[2] = (val >> 40); 01711 ((unsigned char *)dst)[3] = (val >> 32); 01712 ((unsigned char *)dst)[4] = (val >> 24); 01713 ((unsigned char *)dst)[5] = (val >> 16); 01714 ((unsigned char *)dst)[6] = (val >> 8); 01715 ((unsigned char *)dst)[7] = val; 01716 #endif 01717 } 01718 01725 static SPH_INLINE sph_u64 01726 sph_dec64be(const void *src) 01727 { 01728 #if defined SPH_UPTR 01729 #if SPH_UNALIGNED 01730 #if SPH_LITTLE_ENDIAN 01731 return sph_bswap64(*(const sph_u64 *)src); 01732 #else 01733 return *(const sph_u64 *)src; 01734 #endif 01735 #else 01736 if (((SPH_UPTR)src & 7) == 0) { 01737 #if SPH_LITTLE_ENDIAN 01738 return sph_bswap64(*(const sph_u64 *)src); 01739 #else 01740 return *(const sph_u64 *)src; 01741 #endif 01742 } else { 01743 return ((sph_u64)(((const unsigned char *)src)[0]) << 56) 01744 | ((sph_u64)(((const unsigned char *)src)[1]) << 48) 01745 | ((sph_u64)(((const unsigned char *)src)[2]) << 40) 01746 | ((sph_u64)(((const unsigned char *)src)[3]) << 32) 01747 | ((sph_u64)(((const unsigned char *)src)[4]) << 24) 01748 | ((sph_u64)(((const unsigned char *)src)[5]) << 16) 01749 | ((sph_u64)(((const unsigned char *)src)[6]) << 8) 01750 | (sph_u64)(((const unsigned char *)src)[7]); 01751 } 01752 #endif 01753 #else 01754 return ((sph_u64)(((const unsigned char *)src)[0]) << 56) 01755 | ((sph_u64)(((const unsigned char *)src)[1]) << 48) 01756 | ((sph_u64)(((const unsigned char *)src)[2]) << 40) 01757 | ((sph_u64)(((const unsigned char *)src)[3]) << 32) 01758 | ((sph_u64)(((const unsigned char *)src)[4]) << 24) 01759 | ((sph_u64)(((const unsigned char *)src)[5]) << 16) 01760 | ((sph_u64)(((const unsigned char *)src)[6]) << 8) 01761 | (sph_u64)(((const unsigned char *)src)[7]); 01762 #endif 01763 } 01764 01772 static SPH_INLINE sph_u64 01773 sph_dec64be_aligned(const void *src) 01774 { 01775 #if SPH_LITTLE_ENDIAN 01776 return sph_bswap64(*(const sph_u64 *)src); 01777 #elif SPH_BIG_ENDIAN 01778 return *(const sph_u64 *)src; 01779 #else 01780 return ((sph_u64)(((const unsigned char *)src)[0]) << 56) 01781 | ((sph_u64)(((const unsigned char *)src)[1]) << 48) 01782 | ((sph_u64)(((const unsigned char *)src)[2]) << 40) 01783 | ((sph_u64)(((const unsigned char *)src)[3]) << 32) 01784 | ((sph_u64)(((const unsigned char *)src)[4]) << 24) 01785 | ((sph_u64)(((const unsigned char *)src)[5]) << 16) 01786 | ((sph_u64)(((const unsigned char *)src)[6]) << 8) 01787 | (sph_u64)(((const unsigned char *)src)[7]); 01788 #endif 01789 } 01790 01797 static SPH_INLINE void 01798 sph_enc64le(void *dst, sph_u64 val) 01799 { 01800 #if defined SPH_UPTR 01801 #if SPH_UNALIGNED 01802 #if SPH_BIG_ENDIAN 01803 val = sph_bswap64(val); 01804 #endif 01805 *(sph_u64 *)dst = val; 01806 #else 01807 if (((SPH_UPTR)dst & 7) == 0) { 01808 #if SPH_BIG_ENDIAN 01809 val = sph_bswap64(val); 01810 #endif 01811 *(sph_u64 *)dst = val; 01812 } else { 01813 ((unsigned char *)dst)[0] = val; 01814 ((unsigned char *)dst)[1] = (val >> 8); 01815 ((unsigned char *)dst)[2] = (val >> 16); 01816 ((unsigned char *)dst)[3] = (val >> 24); 01817 ((unsigned char *)dst)[4] = (val >> 32); 01818 ((unsigned char *)dst)[5] = (val >> 40); 01819 ((unsigned char *)dst)[6] = (val >> 48); 01820 ((unsigned char *)dst)[7] = (val >> 56); 01821 } 01822 #endif 01823 #else 01824 ((unsigned char *)dst)[0] = val; 01825 ((unsigned char *)dst)[1] = (val >> 8); 01826 ((unsigned char *)dst)[2] = (val >> 16); 01827 ((unsigned char *)dst)[3] = (val >> 24); 01828 ((unsigned char *)dst)[4] = (val >> 32); 01829 ((unsigned char *)dst)[5] = (val >> 40); 01830 ((unsigned char *)dst)[6] = (val >> 48); 01831 ((unsigned char *)dst)[7] = (val >> 56); 01832 #endif 01833 } 01834 01842 static SPH_INLINE void 01843 sph_enc64le_aligned(void *dst, sph_u64 val) 01844 { 01845 #if SPH_LITTLE_ENDIAN 01846 *(sph_u64 *)dst = val; 01847 #elif SPH_BIG_ENDIAN 01848 *(sph_u64 *)dst = sph_bswap64(val); 01849 #else 01850 ((unsigned char *)dst)[0] = val; 01851 ((unsigned char *)dst)[1] = (val >> 8); 01852 ((unsigned char *)dst)[2] = (val >> 16); 01853 ((unsigned char *)dst)[3] = (val >> 24); 01854 ((unsigned char *)dst)[4] = (val >> 32); 01855 ((unsigned char *)dst)[5] = (val >> 40); 01856 ((unsigned char *)dst)[6] = (val >> 48); 01857 ((unsigned char *)dst)[7] = (val >> 56); 01858 #endif 01859 } 01860 01867 static SPH_INLINE sph_u64 01868 sph_dec64le(const void *src) 01869 { 01870 #if defined SPH_UPTR 01871 #if SPH_UNALIGNED 01872 #if SPH_BIG_ENDIAN 01873 return sph_bswap64(*(const sph_u64 *)src); 01874 #else 01875 return *(const sph_u64 *)src; 01876 #endif 01877 #else 01878 if (((SPH_UPTR)src & 7) == 0) { 01879 #if SPH_BIG_ENDIAN 01880 #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM 01881 sph_u64 tmp; 01882 01883 __asm__ __volatile__ ( 01884 "ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); 01885 return tmp; 01886 /* 01887 * Not worth it generally. 01888 * 01889 #elif SPH_PPC32_GCC && !SPH_NO_ASM 01890 return (sph_u64)sph_dec32le_aligned(src) 01891 | ((sph_u64)sph_dec32le_aligned( 01892 (const char *)src + 4) << 32); 01893 #elif SPH_PPC64_GCC && !SPH_NO_ASM 01894 sph_u64 tmp; 01895 01896 __asm__ __volatile__ ( 01897 "ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); 01898 return tmp; 01899 */ 01900 #else 01901 return sph_bswap64(*(const sph_u64 *)src); 01902 #endif 01903 #else 01904 return *(const sph_u64 *)src; 01905 #endif 01906 } else { 01907 return (sph_u64)(((const unsigned char *)src)[0]) 01908 | ((sph_u64)(((const unsigned char *)src)[1]) << 8) 01909 | ((sph_u64)(((const unsigned char *)src)[2]) << 16) 01910 | ((sph_u64)(((const unsigned char *)src)[3]) << 24) 01911 | ((sph_u64)(((const unsigned char *)src)[4]) << 32) 01912 | ((sph_u64)(((const unsigned char *)src)[5]) << 40) 01913 | ((sph_u64)(((const unsigned char *)src)[6]) << 48) 01914 | ((sph_u64)(((const unsigned char *)src)[7]) << 56); 01915 } 01916 #endif 01917 #else 01918 return (sph_u64)(((const unsigned char *)src)[0]) 01919 | ((sph_u64)(((const unsigned char *)src)[1]) << 8) 01920 | ((sph_u64)(((const unsigned char *)src)[2]) << 16) 01921 | ((sph_u64)(((const unsigned char *)src)[3]) << 24) 01922 | ((sph_u64)(((const unsigned char *)src)[4]) << 32) 01923 | ((sph_u64)(((const unsigned char *)src)[5]) << 40) 01924 | ((sph_u64)(((const unsigned char *)src)[6]) << 48) 01925 | ((sph_u64)(((const unsigned char *)src)[7]) << 56); 01926 #endif 01927 } 01928 01936 static SPH_INLINE sph_u64 01937 sph_dec64le_aligned(const void *src) 01938 { 01939 #if SPH_LITTLE_ENDIAN 01940 return *(const sph_u64 *)src; 01941 #elif SPH_BIG_ENDIAN 01942 #if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM 01943 sph_u64 tmp; 01944 01945 __asm__ __volatile__ ("ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); 01946 return tmp; 01947 /* 01948 * Not worth it generally. 01949 * 01950 #elif SPH_PPC32_GCC && !SPH_NO_ASM 01951 return (sph_u64)sph_dec32le_aligned(src) 01952 | ((sph_u64)sph_dec32le_aligned((const char *)src + 4) << 32); 01953 #elif SPH_PPC64_GCC && !SPH_NO_ASM 01954 sph_u64 tmp; 01955 01956 __asm__ __volatile__ ("ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); 01957 return tmp; 01958 */ 01959 #else 01960 return sph_bswap64(*(const sph_u64 *)src); 01961 #endif 01962 #else 01963 return (sph_u64)(((const unsigned char *)src)[0]) 01964 | ((sph_u64)(((const unsigned char *)src)[1]) << 8) 01965 | ((sph_u64)(((const unsigned char *)src)[2]) << 16) 01966 | ((sph_u64)(((const unsigned char *)src)[3]) << 24) 01967 | ((sph_u64)(((const unsigned char *)src)[4]) << 32) 01968 | ((sph_u64)(((const unsigned char *)src)[5]) << 40) 01969 | ((sph_u64)(((const unsigned char *)src)[6]) << 48) 01970 | ((sph_u64)(((const unsigned char *)src)[7]) << 56); 01971 #endif 01972 } 01973 01974 #endif 01975 01976 #endif /* Doxygen excluded block */ 01977 01978 #endif