summaryrefslogtreecommitdiffstats
path: root/source/base/base_simd.cpp
blob: 4be5a85f66ae8372a23f03345374626684d009f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#if ARCH_ARM
#include <arm_neon.h>

typedef __u128 __u128;

#define u8x16 uint8x16_t

#define CheckSIMDNeon() do { CheckFPAdvSIMDEnabled64(); } while(0);
internal void neon_compare_u8(u8 *a,u8 *b) {

 // TODO: ...

}

#elif ARCH_X86 || ARCH_x86_64

#include <immintrin.h>
#if COMPILER_MSVC
#include <intrin.h>
#endif

internal u32 simd_ctz32(u32 x) {
#if COMPILER_MSVC
 unsigned long index;
 _BitScanForward(&index, x);
 return (u32)index;
#else
 return (u32)__builtin_ctz(x);
#endif
}

internal u64 simd_find_byte(u8 *data, u64 size, u8 byte) {
 u64 index = 0;
 m128i needle = _mm_set1_epi8((char)byte);

 for(; index + 16 <= size; index += 16) {
  m128i chunk = _mm_loadu_si128((m128i *)(data + index));
  m128i eq    = _mm_cmpeq_epi8(chunk, needle);
  u32 mask      = (u32)_mm_movemask_epi8(eq);
  if(mask != 0) {
   return index + simd_ctz32(mask); // form what i understand is that we check the lowest bit because that is the earliest thing we cann check? from the packed check that we did? or  something like tha?
  }
 }

 for(; index < size; ++index) {
  if(data[index] == byte) {
   return index;
  }
 }
 return size;
}

#endif // ARCH