Skinny-C
 All Data Structures Files Functions Variables Groups Pages
skinny-internal.c
1 /*
2  * Copyright (C) 2017 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "skinny-internal.h"
24 #include <stdlib.h>
25 
26 #if defined(__x86_64) || defined(__x86_64__) || \
27  defined(__i386) || defined(__i386__)
28 #define SKINNY_X86 1
29 #else
30 #define SKINNY_X86 0
31 #endif
32 #if SKINNY_X86 && (defined(__GNUC__) || defined(__clang__))
33 #define SKINNY_X86_CPUID 1
34 #else
35 #define SKINNY_X86_CPUID 0
36 #endif
37 #if SKINNY_X86_CPUID
38 #include <cpuid.h>
39 #endif
40 
41 int _skinny_has_vec128(void)
42 {
43  int detected = 0;
44 #if SKINNY_VEC128_MATH
45 #if SKINNY_X86_CPUID && defined(__SSE2__)
46  /* 128-bit SIMD vectors are available on x86 if we have SSE2 */
47  uint32_t eax = 0;
48  uint32_t ebx = 0;
49  uint32_t ecx = 0;
50  uint32_t edx = 0;
51  __cpuid(1, eax, ebx, ecx, edx);
52  detected = (edx & (1 << 26)) != 0;
53 #elif defined(__arm) || defined(__arm__)
54 #if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__ARM_NEON_FP)
55  /* Don't know how to do a runtime check so assume that if the user
56  compiled with NEON instructions enabled, they wanted to use them */
57  detected = 1;
58 #endif
59 #endif
60 #endif
61  return detected;
62 }
63 
64 int _skinny_has_vec256(void)
65 {
66  int detected = 0;
67 #if SKINNY_VEC256_MATH
68 #if SKINNY_X86_CPUID && defined(__AVX2__)
69  /* 256-bit SIMD vectors are available on x86 if we have AVX2 */
70  uint32_t eax = 0;
71  uint32_t ebx = 0;
72  uint32_t ecx = 0;
73  uint32_t edx = 0;
74  __cpuid(7, eax, ebx, ecx, edx);
75  detected = (ebx & (1 << 5)) != 0;
76 #endif
77 #endif
78  return detected;
79 }
80 
81 void *skinny_calloc(size_t size, void **base_ptr)
82 {
83  /* We use 256-bit aligned structures in some of the back ends but
84  calloc() may align to less than that. This wrapper fixes things */
85  void *ptr = calloc(1, size + 31);
86  if (ptr) {
87  *base_ptr = ptr;
88  ptr = (void *)((((uintptr_t)ptr) + 31) & ~((uintptr_t)31));
89  }
90  return ptr;
91 }