Skip to content

Commit d46b0ac

Browse files
committed
added pclmul
1 parent 80a524d commit d46b0ac

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

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/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)