1use crate::{
2 core_arch::{simd::*, x86::*},
3 mem::transmute,
4};
5
6#[allow(improper_ctypes)]
7extern "C" {
8 #[link_name = "llvm.x86.sha1msg1"]
9 fn sha1msg1(a: i32x4, b: i32x4) -> i32x4;
10 #[link_name = "llvm.x86.sha1msg2"]
11 fn sha1msg2(a: i32x4, b: i32x4) -> i32x4;
12 #[link_name = "llvm.x86.sha1nexte"]
13 fn sha1nexte(a: i32x4, b: i32x4) -> i32x4;
14 #[link_name = "llvm.x86.sha1rnds4"]
15 fn sha1rnds4(a: i32x4, b: i32x4, c: i8) -> i32x4;
16 #[link_name = "llvm.x86.sha256msg1"]
17 fn sha256msg1(a: i32x4, b: i32x4) -> i32x4;
18 #[link_name = "llvm.x86.sha256msg2"]
19 fn sha256msg2(a: i32x4, b: i32x4) -> i32x4;
20 #[link_name = "llvm.x86.sha256rnds2"]
21 fn sha256rnds2(a: i32x4, b: i32x4, k: i32x4) -> i32x4;
22}
23
24#[cfg(test)]
25use stdarch_test::assert_instr;
26
27/// Performs an intermediate calculation for the next four SHA1 message values
28/// (unsigned 32-bit integers) using previous message values from `a` and `b`,
29/// and returning the result.
30///
31/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg1_epu32)
32#[inline]
33#[target_feature(enable = "sha")]
34#[cfg_attr(test, assert_instr(sha1msg1))]
35#[stable(feature = "simd_x86", since = "1.27.0")]
36pub unsafe fn _mm_sha1msg1_epu32(a: __m128i, b: __m128i) -> __m128i {
37 transmute(src:sha1msg1(a:a.as_i32x4(), b:b.as_i32x4()))
38}
39
40/// Performs the final calculation for the next four SHA1 message values
41/// (unsigned 32-bit integers) using the intermediate result in `a` and the
42/// previous message values in `b`, and returns the result.
43///
44/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg2_epu32)
45#[inline]
46#[target_feature(enable = "sha")]
47#[cfg_attr(test, assert_instr(sha1msg2))]
48#[stable(feature = "simd_x86", since = "1.27.0")]
49pub unsafe fn _mm_sha1msg2_epu32(a: __m128i, b: __m128i) -> __m128i {
50 transmute(src:sha1msg2(a:a.as_i32x4(), b:b.as_i32x4()))
51}
52
53/// Calculate SHA1 state variable E after four rounds of operation from the
54/// current SHA1 state variable `a`, add that value to the scheduled values
55/// (unsigned 32-bit integers) in `b`, and returns the result.
56///
57/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1nexte_epu32)
58#[inline]
59#[target_feature(enable = "sha")]
60#[cfg_attr(test, assert_instr(sha1nexte))]
61#[stable(feature = "simd_x86", since = "1.27.0")]
62pub unsafe fn _mm_sha1nexte_epu32(a: __m128i, b: __m128i) -> __m128i {
63 transmute(src:sha1nexte(a:a.as_i32x4(), b:b.as_i32x4()))
64}
65
66/// Performs four rounds of SHA1 operation using an initial SHA1 state (A,B,C,D)
67/// from `a` and some pre-computed sum of the next 4 round message values
68/// (unsigned 32-bit integers), and state variable E from `b`, and return the
69/// updated SHA1 state (A,B,C,D). `FUNC` contains the logic functions and round
70/// constants.
71///
72/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1rnds4_epu32)
73#[inline]
74#[target_feature(enable = "sha")]
75#[cfg_attr(test, assert_instr(sha1rnds4, FUNC = 0))]
76#[rustc_legacy_const_generics(2)]
77#[stable(feature = "simd_x86", since = "1.27.0")]
78pub unsafe fn _mm_sha1rnds4_epu32<const FUNC: i32>(a: __m128i, b: __m128i) -> __m128i {
79 static_assert_uimm_bits!(FUNC, 2);
80 transmute(src:sha1rnds4(a:a.as_i32x4(), b:b.as_i32x4(), FUNC as i8))
81}
82
83/// Performs an intermediate calculation for the next four SHA256 message values
84/// (unsigned 32-bit integers) using previous message values from `a` and `b`,
85/// and return the result.
86///
87/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256msg1_epu32)
88#[inline]
89#[target_feature(enable = "sha")]
90#[cfg_attr(test, assert_instr(sha256msg1))]
91#[stable(feature = "simd_x86", since = "1.27.0")]
92pub unsafe fn _mm_sha256msg1_epu32(a: __m128i, b: __m128i) -> __m128i {
93 transmute(src:sha256msg1(a:a.as_i32x4(), b:b.as_i32x4()))
94}
95
96/// Performs the final calculation for the next four SHA256 message values
97/// (unsigned 32-bit integers) using previous message values from `a` and `b`,
98/// and return the result.
99///
100/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256msg2_epu32)
101#[inline]
102#[target_feature(enable = "sha")]
103#[cfg_attr(test, assert_instr(sha256msg2))]
104#[stable(feature = "simd_x86", since = "1.27.0")]
105pub unsafe fn _mm_sha256msg2_epu32(a: __m128i, b: __m128i) -> __m128i {
106 transmute(src:sha256msg2(a:a.as_i32x4(), b:b.as_i32x4()))
107}
108
109/// Performs 2 rounds of SHA256 operation using an initial SHA256 state
110/// (C,D,G,H) from `a`, an initial SHA256 state (A,B,E,F) from `b`, and a
111/// pre-computed sum of the next 2 round message values (unsigned 32-bit
112/// integers) and the corresponding round constants from `k`, and store the
113/// updated SHA256 state (A,B,E,F) in dst.
114///
115/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256rnds2_epu32)
116#[inline]
117#[target_feature(enable = "sha")]
118#[cfg_attr(test, assert_instr(sha256rnds2))]
119#[stable(feature = "simd_x86", since = "1.27.0")]
120pub unsafe fn _mm_sha256rnds2_epu32(a: __m128i, b: __m128i, k: __m128i) -> __m128i {
121 transmute(src:sha256rnds2(a:a.as_i32x4(), b:b.as_i32x4(), k:k.as_i32x4()))
122}
123
124#[cfg(test)]
125mod tests {
126 use std::{
127 f32,
128 f64::{self, NAN},
129 i32,
130 mem::{self, transmute},
131 };
132
133 use crate::{
134 core_arch::{simd::*, x86::*},
135 hint::black_box,
136 };
137 use stdarch_test::simd_test;
138
139 #[simd_test(enable = "sha")]
140 #[allow(overflowing_literals)]
141 unsafe fn test_mm_sha1msg1_epu32() {
142 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
143 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
144 let expected = _mm_set_epi64x(0x98829f34f74ad457, 0xda2b1a44d0b5ad3c);
145 let r = _mm_sha1msg1_epu32(a, b);
146 assert_eq_m128i(r, expected);
147 }
148
149 #[simd_test(enable = "sha")]
150 #[allow(overflowing_literals)]
151 unsafe fn test_mm_sha1msg2_epu32() {
152 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
153 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
154 let expected = _mm_set_epi64x(0xf714b202d863d47d, 0x90c30d946b3d3b35);
155 let r = _mm_sha1msg2_epu32(a, b);
156 assert_eq_m128i(r, expected);
157 }
158
159 #[simd_test(enable = "sha")]
160 #[allow(overflowing_literals)]
161 unsafe fn test_mm_sha1nexte_epu32() {
162 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
163 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
164 let expected = _mm_set_epi64x(0x2589d5be923f82a4, 0x59f111f13956c25b);
165 let r = _mm_sha1nexte_epu32(a, b);
166 assert_eq_m128i(r, expected);
167 }
168
169 #[simd_test(enable = "sha")]
170 #[allow(overflowing_literals)]
171 unsafe fn test_mm_sha1rnds4_epu32() {
172 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
173 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
174 let expected = _mm_set_epi64x(0x32b13cd8322f5268, 0xc54420862bd9246f);
175 let r = _mm_sha1rnds4_epu32::<0>(a, b);
176 assert_eq_m128i(r, expected);
177
178 let expected = _mm_set_epi64x(0x6d4c43e56a3c25d9, 0xa7e00fb775cbd3fe);
179 let r = _mm_sha1rnds4_epu32::<1>(a, b);
180 assert_eq_m128i(r, expected);
181
182 let expected = _mm_set_epi64x(0xb304e383c01222f4, 0x66f6b3b1f89d8001);
183 let r = _mm_sha1rnds4_epu32::<2>(a, b);
184 assert_eq_m128i(r, expected);
185
186 let expected = _mm_set_epi64x(0x8189b758bfabfa79, 0xdb08f6e78cae098b);
187 let r = _mm_sha1rnds4_epu32::<3>(a, b);
188 assert_eq_m128i(r, expected);
189 }
190
191 #[simd_test(enable = "sha")]
192 #[allow(overflowing_literals)]
193 unsafe fn test_mm_sha256msg1_epu32() {
194 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
195 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
196 let expected = _mm_set_epi64x(0xeb84973fd5cda67d, 0x2857b88f406b09ee);
197 let r = _mm_sha256msg1_epu32(a, b);
198 assert_eq_m128i(r, expected);
199 }
200
201 #[simd_test(enable = "sha")]
202 #[allow(overflowing_literals)]
203 unsafe fn test_mm_sha256msg2_epu32() {
204 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
205 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
206 let expected = _mm_set_epi64x(0xb58777ce887fd851, 0x15d1ec8b73ac8450);
207 let r = _mm_sha256msg2_epu32(a, b);
208 assert_eq_m128i(r, expected);
209 }
210
211 #[simd_test(enable = "sha")]
212 #[allow(overflowing_literals)]
213 unsafe fn test_mm_sha256rnds2_epu32() {
214 let a = _mm_set_epi64x(0xe9b5dba5b5c0fbcf, 0x71374491428a2f98);
215 let b = _mm_set_epi64x(0xab1c5ed5923f82a4, 0x59f111f13956c25b);
216 let k = _mm_set_epi64x(0, 0x12835b01d807aa98);
217 let expected = _mm_set_epi64x(0xd3063037effb15ea, 0x187ee3db0d6d1d19);
218 let r = _mm_sha256rnds2_epu32(a, b, k);
219 assert_eq_m128i(r, expected);
220 }
221}
222