blake2/
simd.rs

1// Copyright 2015 blake2-rfc Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8mod simd_opt;
9mod simdint;
10mod simdop;
11mod simdty;
12
13pub use self::simdty::{u32x4, u64x4};
14
15pub trait Vector4<T>: Copy {
16    fn gather(src: &[T], i0: usize, i1: usize, i2: usize, i3: usize) -> Self;
17
18    #[allow(clippy::wrong_self_convention)]
19    fn from_le(self) -> Self;
20    fn to_le(self) -> Self;
21
22    fn wrapping_add(self, rhs: Self) -> Self;
23
24    fn rotate_right_const(self, n: u32) -> Self;
25
26    fn shuffle_left_1(self) -> Self;
27    fn shuffle_left_2(self) -> Self;
28    fn shuffle_left_3(self) -> Self;
29
30    #[inline(always)]
31    fn shuffle_right_1(self) -> Self {
32        self.shuffle_left_3()
33    }
34    #[inline(always)]
35    fn shuffle_right_2(self) -> Self {
36        self.shuffle_left_2()
37    }
38    #[inline(always)]
39    fn shuffle_right_3(self) -> Self {
40        self.shuffle_left_1()
41    }
42}
43
44macro_rules! impl_vector4 {
45    ($vec:ident, $word:ident) => {
46        impl Vector4<$word> for $vec {
47            #[inline(always)]
48            fn gather(src: &[$word], i0: usize, i1: usize, i2: usize, i3: usize) -> Self {
49                $vec::new(src[i0], src[i1], src[i2], src[i3])
50            }
51
52            #[cfg(target_endian = "little")]
53            #[inline(always)]
54            fn from_le(self) -> Self {
55                self
56            }
57
58            #[cfg(not(target_endian = "little"))]
59            #[inline(always)]
60            fn from_le(self) -> Self {
61                $vec::new(
62                    $word::from_le(self.0),
63                    $word::from_le(self.1),
64                    $word::from_le(self.2),
65                    $word::from_le(self.3),
66                )
67            }
68
69            #[cfg(target_endian = "little")]
70            #[inline(always)]
71            fn to_le(self) -> Self {
72                self
73            }
74
75            #[cfg(not(target_endian = "little"))]
76            #[inline(always)]
77            fn to_le(self) -> Self {
78                $vec::new(
79                    self.0.to_le(),
80                    self.1.to_le(),
81                    self.2.to_le(),
82                    self.3.to_le(),
83                )
84            }
85
86            #[inline(always)]
87            fn wrapping_add(self, rhs: Self) -> Self {
88                self + rhs
89            }
90
91            #[inline(always)]
92            fn rotate_right_const(self, n: u32) -> Self {
93                simd_opt::$vec::rotate_right_const(self, n)
94            }
95
96            #[cfg(feature = "simd")]
97            #[inline(always)]
98            fn shuffle_left_1(self) -> Self {
99                use crate::simd::simdint::simd_shuffle4;
100                const IDX: [u32; 4] = [1, 2, 3, 0];
101                unsafe { simd_shuffle4(self, self, IDX) }
102            }
103
104            #[cfg(not(feature = "simd"))]
105            #[inline(always)]
106            fn shuffle_left_1(self) -> Self {
107                $vec::new(self.1, self.2, self.3, self.0)
108            }
109
110            #[cfg(feature = "simd")]
111            #[inline(always)]
112            fn shuffle_left_2(self) -> Self {
113                use crate::simd::simdint::simd_shuffle4;
114                const IDX: [u32; 4] = [2, 3, 0, 1];
115                unsafe { simd_shuffle4(self, self, IDX) }
116            }
117
118            #[cfg(not(feature = "simd"))]
119            #[inline(always)]
120            fn shuffle_left_2(self) -> Self {
121                $vec::new(self.2, self.3, self.0, self.1)
122            }
123
124            #[cfg(feature = "simd")]
125            #[inline(always)]
126            fn shuffle_left_3(self) -> Self {
127                use crate::simd::simdint::simd_shuffle4;
128                const IDX: [u32; 4] = [3, 0, 1, 2];
129                unsafe { simd_shuffle4(self, self, IDX) }
130            }
131
132            #[cfg(not(feature = "simd"))]
133            #[inline(always)]
134            fn shuffle_left_3(self) -> Self {
135                $vec::new(self.3, self.0, self.1, self.2)
136            }
137        }
138    };
139}
140
141impl_vector4!(u32x4, u32);
142impl_vector4!(u64x4, u64);