@@ -8,10 +8,46 @@ pub fn _mm_abs_epi8(a: i8x16) -> u8x16 {
8
8
unsafe { pabsb128 ( a) }
9
9
}
10
10
11
+
12
+
13
+ /// Shuffle bytes from `a` according to the content of `b`.
14
+ ///
15
+ /// The last 4 bits of each byte of `b` are used as addresses
16
+ /// into the 16 bytes of `a`.
17
+ ///
18
+ /// In addition, if the highest significant bit of a byte of `b`
19
+ /// is set, the respective destination byte is set to 0.
20
+ ///
21
+ /// Picturing `a` and `b` as `[u8; 16]`, `_mm_shuffle_epi8` is
22
+ /// logically equivalent to:
23
+ ///
24
+ /// ```
25
+ /// fn mm_shuffle_epi8(a: [u8; 16], b: [u8; 16]) -> [u8; 16] {
26
+ /// let mut r = [0u8; 16];
27
+ /// for i in 0..16 {
28
+ /// // if the most significant bit of b is set,
29
+ /// // then the destination byte is set to 0.
30
+ /// if b[i] & 0x80 == 0u8 {
31
+ /// r[i] = a[(b[i] % 16) as usize];
32
+ /// }
33
+ /// }
34
+ /// r
35
+ /// }
36
+ /// ```
37
+ #[ inline( always) ]
38
+ #[ target_feature = "+ssse3" ]
39
+ pub fn _mm_shuffle_epi8 ( a : u8x16 , b : u8x16 ) -> u8x16 {
40
+ unsafe { pshufb128 ( a, b) }
41
+ }
42
+
43
+
11
44
#[ allow( improper_ctypes) ]
12
45
extern {
13
46
#[ link_name = "llvm.x86.ssse3.pabs.b.128" ]
14
47
fn pabsb128 ( a : i8x16 ) -> u8x16 ;
48
+
49
+ #[ link_name = "llvm.x86.ssse3.pshuf.b.128" ]
50
+ fn pshufb128 ( a : u8x16 , b : u8x16 ) -> u8x16 ;
15
51
}
16
52
17
53
#[ cfg( test) ]
@@ -25,4 +61,14 @@ mod tests {
25
61
let r = ssse3:: _mm_abs_epi8 ( i8x16:: splat ( -5 ) ) ;
26
62
assert_eq ! ( r, u8x16:: splat( 5 ) ) ;
27
63
}
64
+
65
+ #[ test]
66
+ #[ target_feature = "+ssse3" ]
67
+ fn _mm_shuffle_epi8 ( ) {
68
+ let a = u8x16:: new ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 ) ;
69
+ let b = u8x16:: new ( 4 , 128 , 4 , 3 , 24 , 12 , 6 , 19 , 12 , 5 , 5 , 10 , 4 , 1 , 8 , 0 ) ;
70
+ let expected = u8x16:: new ( 5 , 0 , 5 , 4 , 9 , 13 , 7 , 4 , 13 , 6 , 6 , 11 , 5 , 2 , 9 , 1 ) ;
71
+ let r = ssse3:: _mm_shuffle_epi8 ( a, b) ;
72
+ assert_eq ! ( r, expected) ;
73
+ }
28
74
}
0 commit comments