SPARK  0.1.0
A general purpose game engine written in C++.
Loading...
Searching...
No Matches
Uuid.h
1#pragma once
2
3#include "spark/base/Endianness.h"
4
5// ReSharper disable CppClangTidyClangDiagnosticCastAlign
6// ReSharper disable CppClangTidyClangDiagnosticImplicitIntConversion
7// ReSharper disable CppCStyleCast
8// ReSharper disable CppInconsistentNaming
9// ReSharper disable IdentifierTypo
10
11namespace spark::lib::details
12{
20 void inline m128itos(__m128i x, char* mem)
21 {
22 // Expand each byte in x to two bytes in res
23 // i.e. 0x12345678 -> 0x0102030405060708
24 // Then translate each byte to its hex ascii representation
25 // i.e. 0x0102030405060708 -> 0x3132333435363738
26 const __m256i mask = _mm256_set1_epi8(0x0F);
27 const __m256i add = _mm256_set1_epi8(0x06);
28 const __m256i alpha_mask = _mm256_set1_epi8(0x10);
29 const __m256i alpha_offset = _mm256_set1_epi8(0x57);
30
31 __m256i a = _mm256_castsi128_si256(x);
32 __m256i as = _mm256_srli_epi64(a, 4);
33 __m256i lo = _mm256_unpacklo_epi8(as, a);
34 __m128i hi = _mm256_castsi256_si128(_mm256_unpackhi_epi8(as, a));
35 __m256i c = _mm256_inserti128_si256(lo, hi, 1);
36 __m256i d = _mm256_and_si256(c, mask);
37 __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(_mm256_add_epi8(d, add), alpha_mask), 3);
38 __m256i offset = _mm256_blendv_epi8(_mm256_slli_epi64(add, 3), alpha_offset, alpha);
39 __m256i res = _mm256_add_epi8(d, offset);
40
41 // Add dashes between blocks as specified in RFC-4122
42 // 8-4-4-4-12
43 const __m256i dash_shuffle = _mm256_set_epi32(0x0b0a0908, 0x07060504, 0x80030201, 0x00808080, 0x0d0c800b, 0x0a090880, 0x07060504, 0x03020100);
44 const __m256i dash = _mm256_set_epi64x(0x0000000000000000ull, 0x2d000000002d0000ull, 0x00002d000000002d, 0x0000000000000000ull);
45
46 __m256i resd = _mm256_shuffle_epi8(res, dash_shuffle);
47 resd = _mm256_or_si256(resd, dash);
48
49 _mm256_storeu_si256((__m256i*)mem, betole256(resd));
50 *(uint16_t*)(mem + 16) = static_cast<uint16_t>(betole16(_mm256_extract_epi16(res, 7)));
51 *(uint32_t*)(mem + 32) = static_cast<uint16_t>(betole32(_mm256_extract_epi32(res, 7)));
52 }
53
61 __m128i inline stom128i(char* mem)
62 {
63 // Remove dashes and pack hex ascii bytes in a 256-bits int
64 const __m256i dash_shuffle = _mm256_set_epi32(0x80808080, 0x0f0e0d0c, 0x0b0a0908, 0x06050403, 0x80800f0e, 0x0c0b0a09, 0x07060504, 0x03020100);
65
66 __m256i x = betole256(_mm256_loadu_si256((__m256i*)mem));
67 x = _mm256_shuffle_epi8(x, dash_shuffle);
68 x = _mm256_insert_epi16(x, betole16(*(uint16_t*)(mem + 16)), 7);
69 x = _mm256_insert_epi32(x, betole32(*(uint32_t*)(mem + 32)), 7);
70
71 // Build a mask to apply a different offset to alphas and digits
72 const __m256i sub = _mm256_set1_epi8(0x2F);
73 const __m256i mask = _mm256_set1_epi8(0x20);
74 const __m256i alpha_offset = _mm256_set1_epi8(0x28);
75 const __m256i digits_offset = _mm256_set1_epi8(0x01);
76 const __m256i unweave = _mm256_set_epi32(0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200, 0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200);
77 const __m256i shift = _mm256_set_epi32(0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004);
78
79 // Translate ascii bytes to their value
80 // i.e. 0x3132333435363738 -> 0x0102030405060708
81 // Shift hi-digits
82 // i.e. 0x0102030405060708 -> 0x1002300450067008
83 // Horizontal add
84 // i.e. 0x1002300450067008 -> 0x12345678
85 __m256i a = _mm256_sub_epi8(x, sub);
86 __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(a, mask), 2);
87 __m256i sub_mask = _mm256_blendv_epi8(digits_offset, alpha_offset, alpha);
88 a = _mm256_sub_epi8(a, sub_mask);
89 a = _mm256_shuffle_epi8(a, unweave);
90 a = _mm256_sllv_epi32(a, shift);
91 a = _mm256_hadd_epi32(a, _mm256_setzero_si256());
92 a = _mm256_permute4x64_epi64(a, 0b00001000);
93
94 return _mm256_castsi256_si128(a);
95 }
96}