Skip to content

Commit 4977d57

Browse files
committed
added pclmul
1 parent 0d6b868 commit 4977d57

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

coresimd/src/runtime/x86.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ macro_rules! __unstable_detect_feature {
3232
("aes", $unstable_detect_feature:path) => {
3333
$unstable_detect_feature(
3434
$crate::__vendor_runtime::__Feature::aes{}) };
35+
("pclmul", $unstable_detect_feature:path) => {
36+
$unstable_detect_feature(
37+
$crate::__vendor_runtime::__Feature::pclmul{}) };
3538
("tsc", $unstable_detect_feature:path) => {
3639
$unstable_detect_feature(
3740
$crate::__vendor_runtime::__Feature::tsc{}) };
@@ -176,6 +179,8 @@ macro_rules! __unstable_detect_feature {
176179
pub enum __Feature {
177180
/// AES (Advanced Encryption Standard New Instructions AES-NI)
178181
aes,
182+
/// CLMUL (Carry-less Multiplication)
183+
pclmul,
179184
/// TSC (Time Stamp Counter)
180185
tsc,
181186
/// MMX
@@ -351,6 +356,7 @@ pub fn detect_features() -> cache::Initializer {
351356
enable(proc_info_ecx, 20, __Feature::sse4_2);
352357
enable(proc_info_ecx, 23, __Feature::popcnt);
353358
enable(proc_info_ecx, 25, __Feature::aes);
359+
enable(proc_info_ecx, 1, __Feature::pclmul);
354360
enable(proc_info_edx, 4, __Feature::tsc);
355361
enable(proc_info_edx, 23, __Feature::mmx);
356362
enable(proc_info_edx, 24, __Feature::fxsr);
@@ -463,6 +469,7 @@ mod tests {
463469
#[test]
464470
fn dump() {
465471
println!("aes: {:?}", cfg_feature_enabled!("aes"));
472+
println!("pclmul: {:?}", cfg_feature_enabled!("pclmul"));
466473
println!("tsc: {:?}", cfg_feature_enabled!("tsc"));
467474
println!("sse: {:?}", cfg_feature_enabled!("sse"));
468475
println!("sse2: {:?}", cfg_feature_enabled!("sse2"));
@@ -504,6 +511,7 @@ mod tests {
504511
fn compare_with_cupid() {
505512
let information = cupid::master().unwrap();
506513
assert_eq!(cfg_feature_enabled!("aes"), information.aesni());
514+
assert_eq!(cfg_feature_enabled!("pclmul"), information.pclmulqdq());
507515
assert_eq!(cfg_feature_enabled!("tsc"), information.tsc());
508516
assert_eq!(cfg_feature_enabled!("sse"), information.sse());
509517
assert_eq!(cfg_feature_enabled!("sse2"), information.sse2());

coresimd/src/x86/i686/clmul.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use x86::__m128i;
2+
3+
#[cfg(test)]
4+
use stdsimd_test::assert_instr;
5+
6+
#[allow(improper_ctypes)]
7+
extern "C" {
8+
#[link_name = "llvm.x86.pclmulqdq"]
9+
fn pclmulqdq(a: __m128i, round_key: __m128i, imm8: u8) -> __m128i;
10+
}
11+
12+
/// Perform a carry-less multiplication of two 64-bit polynomials over the
13+
/// finite field GF(2^k).
14+
///
15+
/// The immediate byte is used for determining which halves of `a` and `b`
16+
/// should be used. Immediate bits other than 0 and 4 are ignored.
17+
#[inline]
18+
#[target_feature(enable = "pclmul")]
19+
#[cfg_attr(test, assert_instr(pclmulqdq, imm8 = 0))]
20+
pub unsafe fn _mm_clmulepi64_si128(a: __m128i, b: __m128i, imm8: u8) -> __m128i {
21+
macro_rules! call {
22+
($imm8:expr) => (pclmulqdq(a, b, $imm8))
23+
}
24+
constify_imm8!(imm8, call)
25+
}
26+
27+
28+
#[cfg(test)]
29+
mod tests {
30+
// The constants in the tests below are just bit patterns. They should not
31+
// be interpreted as integers; signedness does not make sense for them, but
32+
// __m128i happens to be defined in terms of signed integers.
33+
#![allow(overflowing_literals)]
34+
35+
use stdsimd_test::simd_test;
36+
37+
use x86::*;
38+
39+
#[simd_test = "pclmul"]
40+
unsafe fn test_mm_clmulepi64_si128() {
41+
// Constants taken from https://software.intel.com/sites/default/files/managed/72/cc/clmul-wp-rev-2.02-2014-04-20.pdf
42+
let a = _mm_set_epi64x(0x7b5b546573745665, 0x63746f725d53475d);
43+
let b = _mm_set_epi64x(0x4869285368617929, 0x5b477565726f6e5d);
44+
let r00 = _mm_set_epi64x(0x1d4d84c85c3440c0, 0x929633d5d36f0451);
45+
let r01 = _mm_set_epi64x(0x1bd17c8d556ab5a1, 0x7fa540ac2a281315);
46+
let r10 = _mm_set_epi64x(0x1a2bf6db3a30862f, 0xbabf262df4b7d5c9);
47+
let r11 = _mm_set_epi64x(0x1d1e1f2c592e7c45, 0xd66ee03e410fd4ed);
48+
49+
assert_eq_m128i(_mm_clmulepi64_si128(a, b, 0x00), r00);
50+
assert_eq_m128i(_mm_clmulepi64_si128(a, b, 0x10), r01);
51+
assert_eq_m128i(_mm_clmulepi64_si128(a, b, 0x01), r10);
52+
assert_eq_m128i(_mm_clmulepi64_si128(a, b, 0x11), r11);
53+
54+
let a0 = _mm_set_epi64x(0x0000000000000000, 0x8000000000000000);
55+
let r = _mm_set_epi64x(0x4000000000000000, 0x0000000000000000);
56+
assert_eq_m128i(_mm_clmulepi64_si128(a0, a0, 0x00), r);
57+
}
58+
}

coresimd/src/x86/i686/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
mod aes;
44
pub use self::aes::*;
55

6+
mod clmul;
7+
pub use self::clmul::*;
8+
69
mod mmx;
710
pub use self::mmx::*;
811

0 commit comments

Comments
 (0)