summaryrefslogtreecommitdiffstats
path: root/library/stdarch/crates/core_arch/src/x86/aes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/stdarch/crates/core_arch/src/x86/aes.rs')
-rw-r--r--library/stdarch/crates/core_arch/src/x86/aes.rs171
1 files changed, 171 insertions, 0 deletions
diff --git a/library/stdarch/crates/core_arch/src/x86/aes.rs b/library/stdarch/crates/core_arch/src/x86/aes.rs
new file mode 100644
index 000000000..ffded1a0d
--- /dev/null
+++ b/library/stdarch/crates/core_arch/src/x86/aes.rs
@@ -0,0 +1,171 @@
+//! AES New Instructions (AES-NI)
+//!
+//! The intrinsics here correspond to those in the `wmmintrin.h` C header.
+//!
+//! The reference is [Intel 64 and IA-32 Architectures Software Developer's
+//! Manual Volume 2: Instruction Set Reference, A-Z][intel64_ref].
+//!
+//! [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
+
+use crate::core_arch::x86::__m128i;
+
+#[cfg(test)]
+use stdarch_test::assert_instr;
+
+#[allow(improper_ctypes)]
+extern "C" {
+ #[link_name = "llvm.x86.aesni.aesdec"]
+ fn aesdec(a: __m128i, round_key: __m128i) -> __m128i;
+ #[link_name = "llvm.x86.aesni.aesdeclast"]
+ fn aesdeclast(a: __m128i, round_key: __m128i) -> __m128i;
+ #[link_name = "llvm.x86.aesni.aesenc"]
+ fn aesenc(a: __m128i, round_key: __m128i) -> __m128i;
+ #[link_name = "llvm.x86.aesni.aesenclast"]
+ fn aesenclast(a: __m128i, round_key: __m128i) -> __m128i;
+ #[link_name = "llvm.x86.aesni.aesimc"]
+ fn aesimc(a: __m128i) -> __m128i;
+ #[link_name = "llvm.x86.aesni.aeskeygenassist"]
+ fn aeskeygenassist(a: __m128i, imm8: u8) -> __m128i;
+}
+
+/// Performs one round of an AES decryption flow on data (state) in `a`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdec_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aesdec))]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aesdec_si128(a: __m128i, round_key: __m128i) -> __m128i {
+ aesdec(a, round_key)
+}
+
+/// Performs the last round of an AES decryption flow on data (state) in `a`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesdeclast_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aesdeclast))]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aesdeclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
+ aesdeclast(a, round_key)
+}
+
+/// Performs one round of an AES encryption flow on data (state) in `a`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenc_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aesenc))]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aesenc_si128(a: __m128i, round_key: __m128i) -> __m128i {
+ aesenc(a, round_key)
+}
+
+/// Performs the last round of an AES encryption flow on data (state) in `a`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aesenclast))]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aesenclast_si128(a: __m128i, round_key: __m128i) -> __m128i {
+ aesenclast(a, round_key)
+}
+
+/// Performs the `InvMixColumns` transformation on `a`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesimc_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aesimc))]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aesimc_si128(a: __m128i) -> __m128i {
+ aesimc(a)
+}
+
+/// Assist in expanding the AES cipher key.
+///
+/// Assist in expanding the AES cipher key by computing steps towards
+/// generating a round key for encryption cipher using data from `a` and an
+/// 8-bit round constant `IMM8`.
+///
+/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aeskeygenassist_si128)
+#[inline]
+#[target_feature(enable = "aes")]
+#[cfg_attr(test, assert_instr(aeskeygenassist, IMM8 = 0))]
+#[rustc_legacy_const_generics(1)]
+#[stable(feature = "simd_x86", since = "1.27.0")]
+pub unsafe fn _mm_aeskeygenassist_si128<const IMM8: i32>(a: __m128i) -> __m128i {
+ static_assert_imm8!(IMM8);
+ aeskeygenassist(a, IMM8 as u8)
+}
+
+#[cfg(test)]
+mod tests {
+ // The constants in the tests below are just bit patterns. They should not
+ // be interpreted as integers; signedness does not make sense for them, but
+ // __m128i happens to be defined in terms of signed integers.
+ #![allow(overflowing_literals)]
+
+ use stdarch_test::simd_test;
+
+ use crate::core_arch::x86::*;
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aesdec_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+ let e = _mm_set_epi64x(0x044e4f5176fec48f, 0xb57ecfa381da39ee);
+ let r = _mm_aesdec_si128(a, k);
+ assert_eq_m128i(r, e);
+ }
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aesdeclast_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+ let e = _mm_set_epi64x(0x36cad57d9072bf9e, 0xf210dd981fa4a493);
+ let r = _mm_aesdeclast_si128(a, k);
+ assert_eq_m128i(r, e);
+ }
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aesenc_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+ let e = _mm_set_epi64x(0x16ab0e57dfc442ed, 0x28e4ee1884504333);
+ let r = _mm_aesenc_si128(a, k);
+ assert_eq_m128i(r, e);
+ }
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aesenclast_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let k = _mm_set_epi64x(0x1133557799bbddff, 0x0022446688aaccee);
+ let e = _mm_set_epi64x(0xb6dd7df25d7ab320, 0x4b04f98cf4c860f8);
+ let r = _mm_aesenclast_si128(a, k);
+ assert_eq_m128i(r, e);
+ }
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aesimc_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc714195.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let e = _mm_set_epi64x(0xc66c82284ee40aa0, 0x6633441122770055);
+ let r = _mm_aesimc_si128(a);
+ assert_eq_m128i(r, e);
+ }
+
+ #[simd_test(enable = "aes")]
+ unsafe fn test_mm_aeskeygenassist_si128() {
+ // Constants taken from https://msdn.microsoft.com/en-us/library/cc714138.aspx.
+ let a = _mm_set_epi64x(0x0123456789abcdef, 0x8899aabbccddeeff);
+ let e = _mm_set_epi64x(0x857c266b7c266e85, 0xeac4eea9c4eeacea);
+ let r = _mm_aeskeygenassist_si128::<5>(a);
+ assert_eq_m128i(r, e);
+ }
+}