native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
native.x86.sm3.ccm
1// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
2module;
3#include "native/isa_import.h"
4#include "native/config.h"
5#include "native/attributes.h"
6#include <array>
7#include <bit>
8#include <cstdint>
9#include <immintrin.h>
10#include "native/x86/detail/constant_lanes.h"
11export module native.x86.sm3;
12export import native.x86.features;
13export import native.simd;
14
15namespace native::detail::x86_sm3_constant {
16 template<class V> constexpr V sm3msg1(V a, V b, V c) noexcept {
17 auto x = x86_constant::lanes(a), y = x86_constant::lanes(b), z = x86_constant::lanes(c);
18 for (unsigned i = 0; i < 4; ++i) {
19 auto t = x[i] ^ z[i];
20 if (i < 3) t ^= std::rotl(y[i], 15);
21 x[i] = t ^ std::rotl(t, 15) ^ std::rotl(t, 23);
22 }
23 return x86_constant::pack<V>(x);
24 }
25 template<class V> constexpr V sm3msg2(V a, V b, V c) noexcept {
26 auto x = x86_constant::lanes(a), y = x86_constant::lanes(b), z = x86_constant::lanes(c);
27 for (unsigned i = 0; i < 4; ++i) x[i] ^= std::rotl(y[i], 7) ^ z[i];
28 x[3] ^= std::rotl(x[0], 6) ^ std::rotl(x[0], 15) ^ std::rotl(x[0], 30);
29 return x86_constant::pack<V>(x);
30 }
31 template<unsigned Imm8, class V> constexpr V sm3rnds2(V cdgh, V abef, V message) noexcept {
32 auto x = x86_constant::lanes(cdgh), y = x86_constant::lanes(abef);
33 auto words = x86_constant::lanes(message);
34 auto a = y[3], b = y[2], c = std::rotl(x[3], 9), d = std::rotl(x[2], 9);
35 auto e = y[1], f = y[0], g = std::rotl(x[1], 19), h = std::rotl(x[0], 19);
36 constexpr unsigned round = Imm8 & 62;
37 auto k = std::rotl(std::uint32_t(round < 16 ? 0x79cc4519 : 0x7a879d8a), int(round));
38 for (unsigned i = 0; i < 2; ++i) {
39 auto ss1 = std::rotl(std::rotl(a, 12) + e + k, 7);
40 auto ss2 = ss1 ^ std::rotl(a, 12);
41 auto ff = round < 16 ? a ^ b ^ c : (a & b) | (a & c) | (b & c);
42 auto gg = round < 16 ? e ^ f ^ g : (e & f) | (~e & g);
43 auto tt1 = ff + d + ss2 + (words[i] ^ words[i + 2]);
44 auto tt2 = gg + h + ss1 + words[i];
45 d = c; c = std::rotl(b, 9); b = a; a = tt1;
46 h = g; g = std::rotl(f, 19); f = e;
47 e = tt2 ^ std::rotl(tt2, 9) ^ std::rotl(tt2, 17);
48 k = std::rotl(k, 1);
49 }
50 return x86_constant::pack<V>(std::array{f, e, b, a});
51 }
52}
53
54export namespace native {
61
63 template<isa<x86> Arch>
64 requires(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx))
66 constexpr simd<std::uint32_t, 4, Arch> sm3msg1(simd<std::uint32_t, 4, Arch> a, simd<std::uint32_t, 4, Arch> b, simd<std::uint32_t, 4, Arch> c) noexcept {
67 if consteval { return detail::x86_sm3_constant::sm3msg1(a, b, c); }
68 else { return simd<std::uint32_t, 4, Arch>::from_native(_mm_sm3msg1_epi32(a.to_native(), b.to_native(), c.to_native())); }
69 }
70
72 template<isa<x86> Arch>
73 requires(!(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx)) &&
74 requires { sizeof(simd<std::uint32_t, 4, Arch>); })
76 return detail::x86_sm3_constant::sm3msg1(a, b, c);
77 }
78
80 template<isa<x86> Arch>
81 requires(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx))
84 if consteval { return detail::x86_sm3_constant::sm3msg2(a, b, c); }
85 else { return simd<std::uint32_t, 4, Arch>::from_native(_mm_sm3msg2_epi32(a.to_native(), b.to_native(), c.to_native())); }
86 }
87
89 template<isa<x86> Arch>
90 requires(!(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx)) &&
91 requires { sizeof(simd<std::uint32_t, 4, Arch>); })
93 return detail::x86_sm3_constant::sm3msg2(a, b, c);
94 }
95
97 template<isa<x86> Arch, unsigned Imm8>
98 requires(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx) && Imm8 <= 255)
101 if consteval { return detail::x86_sm3_constant::sm3rnds2<Imm8>(a, b, c); }
102 else { return simd<std::uint32_t, 4, Arch>::from_native(_mm_sm3rnds2_epi32(a.to_native(), b.to_native(), c.to_native(), Imm8)); }
103 }
104
106 template<isa<x86> Arch, unsigned Imm8>
107 requires(!(Arch.has(x86_feature::sm3) && Arch.has(x86_feature::avx)) && Imm8 <= 255 &&
108 requires { sizeof(simd<std::uint32_t, 4, Arch>); })
110 return detail::x86_sm3_constant::sm3rnds2<Imm8>(a, b, c);
111 }
112
114 template<isa<x86> Arch, class... Args> void sm3msg1(Args...) = delete;
115
117 template<isa<x86> Arch, class... Args> void sm3msg2(Args...) = delete;
118
120 template<isa<x86> Arch, unsigned Imm8, class... Args> void sm3rnds2(Args...) = delete;
122}
Compiler attributes for host code, with shader-safe shared modifiers.
#define native_inline
inline [[always_inline]]
Definition attributes.h:212
#define native_nodiscard
C++17 [[nodiscard]].
Definition attributes.h:189
#define native_const
[[const]] is not const
Definition attributes.h:108
#define native_target(x)
this indicates a required feature set for the current multiversioned function.
Definition attributes.h:476
constexpr simd< std::uint32_t, 4, Arch > sm3msg2(simd< std::uint32_t, 4, Arch > a, simd< std::uint32_t, 4, Arch > b, simd< std::uint32_t, 4, Arch > c) noexcept
Final SM3 schedule step.
constexpr simd< std::uint32_t, 4, Arch > sm3msg1(simd< std::uint32_t, 4, Arch > a, simd< std::uint32_t, 4, Arch > b, simd< std::uint32_t, 4, Arch > c) noexcept
First SM3 schedule step.
constexpr simd< std::uint32_t, 4, Arch > sm3rnds2(simd< std::uint32_t, 4, Arch > a, simd< std::uint32_t, 4, Arch > b, simd< std::uint32_t, 4, Arch > c) noexcept
Two SM3 rounds; Imm8 is masked with 0x3e. a holds unrotated CDGH and b holds ABEF.
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
Standard-library adaptations documented here for SIMD value types.
Omitted architecture arguments use the native.simd provider's baseline.