mirror of
https://github.com/JayDDee/cpuminer-opt.git
synced 2025-09-17 23:44:27 +00:00
199 lines
4.5 KiB
C
199 lines
4.5 KiB
C
#ifndef __SIMD_COMPAT_H__
|
|
#define __SIMD_COMPAT_H__
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
/*
|
|
* This file desfines some helper function for cross-platform compatibility.
|
|
*/
|
|
|
|
#if defined __GNUC_PREREQ && (! defined __STRICT_ANSI__)
|
|
#define GNU_EXT
|
|
#endif
|
|
|
|
/*
|
|
* First define some integer types.
|
|
*/
|
|
|
|
#if defined __STDC__ && __STDC_VERSION__ >= 199901L
|
|
|
|
/*
|
|
* On C99 implementations, we can use <stdint.h> to get an exact 32-bit
|
|
* type, if any, or otherwise use a wider type.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "compat/brg_types.h"
|
|
|
|
#define C32(x) ((u32)(x))
|
|
|
|
#define HAS_64 1
|
|
|
|
#else
|
|
|
|
/*
|
|
* On non-C99 systems, we use "unsigned int" if it is wide enough,
|
|
* "unsigned long" otherwise. This supports all "reasonable" architectures.
|
|
* We have to be cautious: pre-C99 preprocessors handle constants
|
|
* differently in '#if' expressions. Hence the shifts to test UINT_MAX.
|
|
*/
|
|
|
|
#if ((UINT_MAX >> 11) >> 11) >= 0x3FF
|
|
|
|
typedef unsigned int u32;
|
|
|
|
#define C32(x) ((u32)(x ## U))
|
|
|
|
#else
|
|
|
|
typedef unsigned long u32;
|
|
|
|
#define C32(x) ((u32)(x ## UL))
|
|
|
|
#endif
|
|
|
|
/*
|
|
* We want a 64-bit type. We use "unsigned long" if it is wide enough (as
|
|
* is common on 64-bit architectures such as AMD64, Alpha or Sparcv9),
|
|
* "unsigned long long" otherwise, if available. We use ULLONG_MAX to
|
|
* test whether "unsigned long long" is available; we also know that
|
|
* gcc features this type, even if the libc header do not know it.
|
|
*/
|
|
|
|
#if ((ULONG_MAX >> 31) >> 31) >= 3
|
|
|
|
typedef unsigned long u64;
|
|
|
|
#define HAS_64 1
|
|
|
|
#elif ((ULLONG_MAX >> 31) >> 31) >= 3 || defined __GNUC__
|
|
|
|
typedef unsigned long long u64;
|
|
|
|
#define HAS_64 1
|
|
|
|
#else
|
|
|
|
/*
|
|
* No 64-bit type...
|
|
*/
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
* fft_t should be at least 16 bits wide.
|
|
* using short int will require less memory, but int is faster...
|
|
*/
|
|
|
|
typedef int fft_t;
|
|
|
|
|
|
/*
|
|
* Implementation note: some processors have specific opcodes to perform
|
|
* a rotation. Recent versions of gcc recognize the expression above and
|
|
* use the relevant opcodes, when appropriate.
|
|
*/
|
|
|
|
#define T32(x) ((x) & C32(0xFFFFFFFF))
|
|
#define ROTL32(x, n) T32(((x) << (n)) | ((x) >> (32 - (n))))
|
|
#define ROTR32(x, n) ROTL32(x, (32 - (n)))
|
|
|
|
|
|
|
|
/*
|
|
* The macro MAYBE_INLINE expands to an inline qualifier, is available.
|
|
*/
|
|
|
|
#if (defined __STDC__ && __STDC_VERSION__ >= 199901L) || defined GNU_EXT
|
|
#define MAYBE_INLINE static inline
|
|
#elif defined _MSC_VER
|
|
#define MAYBE_INLINE __inline
|
|
#else
|
|
#define MAYBE_INLINE
|
|
#endif
|
|
|
|
|
|
/* */
|
|
|
|
#if defined __GNUC__ && ( defined __i386__ || defined __x86_64__ )
|
|
|
|
#define rdtsc() \
|
|
({ \
|
|
u32 lo, hi; \
|
|
__asm__ __volatile__ ( /* serialize */ \
|
|
"xorl %%eax,%%eax \n cpuid" \
|
|
::: "%rax", "%rbx", "%rcx", "%rdx"); \
|
|
/* We cannot use "=A", since this would use %rax on x86_64 */ \
|
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); \
|
|
(u64)hi << 32 | lo; \
|
|
}) \
|
|
|
|
#elif defined _MSC_VER && (defined _M_IX86 || defined _M_X64)
|
|
|
|
#define rdtsc __rdtsc
|
|
|
|
#endif
|
|
|
|
/*
|
|
* The IS_ALIGNED macro tests if a char* pointer is aligned to an
|
|
* n-bit boundary.
|
|
* It is defined as false on unknown architectures.
|
|
*/
|
|
|
|
|
|
#define CHECK_ALIGNED(p,n) ((((unsigned char *) (p) - (unsigned char *) NULL) & ((n)-1)) == 0)
|
|
|
|
#if defined __i386__ || defined __x86_64 || defined _M_IX86 || defined _M_X64
|
|
/*
|
|
* Unaligned 32-bit access are not expensive on x86 so we don't care
|
|
*/
|
|
#define IS_ALIGNED(p,n) (n<=4 || CHECK_ALIGNED(p,n))
|
|
|
|
#elif defined __sparcv9 || defined __sparc || defined __arm || \
|
|
defined __ia64 || defined __ia64__ || \
|
|
defined __itanium__ || defined __M_IA64 || \
|
|
defined __powerpc__ || defined __powerpc
|
|
#define IS_ALIGNED(p,n) CHECK_ALIGNED(p,n)
|
|
|
|
#else
|
|
/*
|
|
* Unkonwn architecture: play safe
|
|
*/
|
|
#define IS_ALIGNED(p,n) 0
|
|
#endif
|
|
|
|
|
|
|
|
/* checks for endianness */
|
|
|
|
#if defined (__linux__) || defined (__GLIBC__)
|
|
# include <endian.h>
|
|
#elif defined (__FreeBSD__)
|
|
# include <machine/endian.h>
|
|
#elif defined (__OpenBSD__)
|
|
# include <sys/endian.h>
|
|
#endif
|
|
|
|
#ifdef __BYTE_ORDER
|
|
|
|
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
# define SIMD_LITTLE_ENDIAN
|
|
# elif __BYTE_ORDER == __BIG_ENDIAN
|
|
# define SIMD_BIG_ENDIAN
|
|
# endif
|
|
|
|
#else
|
|
|
|
# if defined __i386__ || defined __x86_64 || defined _M_IX86 || defined _M_X64
|
|
# define SIMD_LITTLE_ENDIAN
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|