/* Copyright (c) 2018 ZAO "MCST". All rights reserved. */

#ifndef _X86INTRIN_H_INCLUDED
# error "Never use <ia32intrin.h> directly; include <x86intrin.h> instead."
#endif

#include <e2kbuiltin.h> /* реализация ia32 билтынов */

/* Define the default attributes for the functions in this file */
#define __DEFAULT_FUNCS_ATTRS __attribute__((/*__gnu_inline__,*/ __always_inline__, __artificial__))

/* 32bit bsf */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__bsfd (int __X)
{
  return __builtin_ctz (__X);
}

/* 32bit bsr */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__bsrd (int __X)
{
  return __builtin_ia32_bsrsi (__X);
}

/* 32bit bswap */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__bswapd (int __X)
{
  return __builtin_bswap32 (__X);
}

#ifdef __SSE4_2__
/* 32bit accumulate CRC32 (polynomial 0x11EDC6F41) value.  */
__E2K_INLINE unsigned int __DEFAULT_FUNCS_ATTRS
__crc32b (unsigned int __C, unsigned char __V)
{
  return __builtin_ia32_crc32qi (__C, __V);
}

__E2K_INLINE unsigned int __DEFAULT_FUNCS_ATTRS
__crc32w (unsigned int __C, unsigned short __V)
{
  return __builtin_ia32_crc32hi (__C, __V);
}

__E2K_INLINE unsigned int __DEFAULT_FUNCS_ATTRS
__crc32d (unsigned int __C, unsigned int __V)
{
  return __builtin_ia32_crc32si (__C, __V);
}
#endif /* SSE4.2 */

/* 32bit popcnt */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__popcntd (unsigned int __X)
{
  return __builtin_popcount (__X);
}

/* rdpmc */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__rdpmc (int __S)
{
  return __builtin_ia32_rdpmc (__S);
}

/* rdtsc */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__rdtsc (void)
{
  return __builtin_ia32_rdtsc ();
}

/* rdtscp */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__rdtscp (unsigned int *__A)
{
  return __builtin_ia32_rdtscp (__A);
}

/* 8bit rol */
__E2K_INLINE unsigned char __DEFAULT_FUNCS_ATTRS
__rolb (unsigned char __X, int __C)
{
  return __builtin_ia32_rolqi (__X, __C);
}

/* 16bit rol */
__E2K_INLINE unsigned short __DEFAULT_FUNCS_ATTRS
__rolw (unsigned short __X, int __C)
{
  return __builtin_ia32_rolhi (__X, __C);
}

/* 32bit rol */
__E2K_INLINE unsigned int __DEFAULT_FUNCS_ATTRS
__rold (unsigned int __X, int __C)
{
  return __builtin_e2k_scls (__X, __C);
}

/* 8bit ror */
__E2K_INLINE unsigned char __DEFAULT_FUNCS_ATTRS
__rorb (unsigned char __X, int __C)
{
  return __builtin_ia32_rorqi (__X, __C);
}

/* 16bit ror */
__E2K_INLINE unsigned short __DEFAULT_FUNCS_ATTRS
__rorw (unsigned short __X, int __C)
{
  return __builtin_ia32_rorhi (__X, __C);
}

/* 32bit ror */
__E2K_INLINE unsigned int __DEFAULT_FUNCS_ATTRS
__rord (unsigned int __X, int __C)
{
  return __builtin_e2k_scrs (__X, __C);
}

/* Pause */
__E2K_INLINE void __DEFAULT_FUNCS_ATTRS
__pause (void)
{
  __builtin_ia32_pause ();
}

/* 64bit bsf */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__bsfq (long long __X)
{
  return __builtin_ctzll (__X);
}

/* 64bit bsr */
__E2K_INLINE int __DEFAULT_FUNCS_ATTRS
__bsrq (long long __X)
{
  return __builtin_ia32_bsrdi (__X);
}

/* 64bit bswap */
__E2K_INLINE long long __DEFAULT_FUNCS_ATTRS
__bswapq (long long __X)
{
  return __builtin_bswap64 (__X);
}

#ifdef __SSE4_2__
/* 64bit accumulate CRC32 (polynomial 0x11EDC6F41) value.  */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__crc32q (unsigned long long __C, unsigned long long __V)
{
  return __builtin_ia32_crc32di (__C, __V);
}
#endif

/* 64bit popcnt */
__E2K_INLINE long long __DEFAULT_FUNCS_ATTRS
__popcntq (unsigned long long __X)
{
  return __builtin_popcountll (__X);
}

/* 64bit rol */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__rolq (unsigned long long __X, int __C)
{
  return __builtin_e2k_scld (__X, __C);
}

/* 64bit ror */
__E2K_INLINE unsigned long long __DEFAULT_FUNCS_ATTRS
__rorq (unsigned long long __X, int __C)
{
  return __builtin_e2k_scrd (__X, __C);
}

#define _bswap64(a)             __bswapq(a)
#define _popcnt64(a)            __popcntq(a)

/* On LP64 systems, longs are 64-bit.  Use the appropriate rotate
 * function.  */
#ifdef __LP64__
#define _lrotl(a,b)             __rolq((a), (b))
#define _lrotr(a,b)             __rorq((a), (b))
#else
#define _lrotl(a,b)             __rold((a), (b))
#define _lrotr(a,b)             __rord((a), (b))
#endif

#define _bit_scan_forward(a)    __bsfd(a)
#define _bit_scan_reverse(a)    __bsrd(a)
#define _bswap(a)               __bswapd(a)
#define _popcnt32(a)            __popcntd(a)
#define _rdpmc(a)               __rdpmc(a)
#define _rdtscp(a)              __rdtscp(a)
#define _rdtsc()                __rdtsc()
#define _rotwl(a,b)             __rolw((a), (b))
#define _rotwr(a,b)             __rorw((a), (b))
#define _rotl(a,b)              __rold((a), (b))
#define _rotr(a,b)              __rord((a), (b))

#undef __DEFAULT_FUNCS_ATTRS
