1 //! `simd` offers a basic interface to the SIMD functionality of CPUs.
2 #![no_std]
3 
4 #![feature(cfg_target_feature, repr_simd, platform_intrinsics, const_fn)]
5 #![allow(non_camel_case_types)]
6 
7 #[cfg(feature = "with-serde")]
8 extern crate serde;
9 #[cfg(feature = "with-serde")]
10 #[macro_use]
11 extern crate serde_derive;
12 
13 use core::mem;
14 
15 /// Boolean type for 8-bit integers.
16 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
17 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
18 pub struct bool8i(i8);
19 /// Boolean type for 16-bit integers.
20 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
21 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
22 pub struct bool16i(i16);
23 /// Boolean type for 32-bit integers.
24 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
25 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
26 pub struct bool32i(i32);
27 /// Boolean type for 32-bit floats.
28 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
29 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
30 pub struct bool32f(i32);
31 
32 macro_rules! bool {
33     ($($name: ident, $inner: ty;)*) => {
34         $(
35             impl From<bool> for $name {
36                 #[inline]
37                 fn from(b: bool) -> $name {
38                     $name(-(b as $inner))
39                 }
40             }
41             impl From<$name> for bool {
42                 #[inline]
43                 fn from(b: $name) -> bool {
44                     b.0 != 0
45                 }
46             }
47             )*
48     }
49 }
50 bool! {
51     bool8i, i8;
52     bool16i, i16;
53     bool32i, i32;
54     bool32f, i32;
55 }
56 
57 /// Types that are SIMD vectors.
58 pub unsafe trait Simd {
59     /// The corresponding boolean vector type.
60     type Bool: Simd;
61     /// The element that this vector stores.
62     type Elem;
63 }
64 
65 /// A SIMD vector of 4 `u32`s.
66 #[repr(simd)]
67 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
68 #[derive(Debug, Copy)]
69 pub struct u32x4(u32, u32, u32, u32);
70 /// A SIMD vector of 4 `i32`s.
71 #[repr(simd)]
72 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
73 #[derive(Debug, Copy)]
74 pub struct i32x4(i32, i32, i32, i32);
75 /// A SIMD vector of 4 `f32`s.
76 #[repr(simd)]
77 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
78 #[derive(Debug, Copy)]
79 pub struct f32x4(f32, f32, f32, f32);
80 /// A SIMD boolean vector for length-4 vectors of 32-bit integers.
81 #[repr(simd)]
82 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
83 #[derive(Debug, Copy)]
84 pub struct bool32ix4(i32, i32, i32, i32);
85 /// A SIMD boolean vector for length-4 vectors of 32-bit floats.
86 #[repr(simd)]
87 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
88 #[derive(Debug, Copy)]
89 pub struct bool32fx4(i32, i32, i32, i32);
90 
91 #[allow(dead_code)]
92 #[repr(simd)]
93 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
94 #[derive(Debug, Copy)]
95 struct u32x2(u32, u32);
96 #[allow(dead_code)]
97 #[repr(simd)]
98 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
99 #[derive(Debug, Copy)]
100 struct i32x2(i32, i32);
101 #[allow(dead_code)]
102 #[repr(simd)]
103 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
104 #[derive(Debug, Copy)]
105 struct f32x2(f32, f32);
106 #[allow(dead_code)]
107 #[repr(simd)]
108 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
109 #[derive(Debug, Copy)]
110 struct bool32ix2(i32, i32);
111 #[allow(dead_code)]
112 #[repr(simd)]
113 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
114 #[derive(Debug, Copy)]
115 struct bool32fx2(i32, i32);
116 
117 /// A SIMD vector of 8 `u16`s.
118 #[repr(simd)]
119 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
120 #[derive(Debug, Copy)]
121 pub struct u16x8(u16, u16, u16, u16,
122                  u16, u16, u16, u16);
123 /// A SIMD vector of 8 `i16`s.
124 #[repr(simd)]
125 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
126 #[derive(Debug, Copy)]
127 pub struct i16x8(i16, i16, i16, i16,
128                  i16, i16, i16, i16);
129 /// A SIMD boolean vector for length-8 vectors of 16-bit integers.
130 #[repr(simd)]
131 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
132 #[derive(Debug, Copy)]
133 pub struct bool16ix8(i16, i16, i16, i16,
134                      i16, i16, i16, i16);
135 
136 /// A SIMD vector of 16 `u8`s.
137 #[repr(simd)]
138 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
139 #[derive(Debug, Copy)]
140 pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8,
141                  u8, u8, u8, u8, u8, u8, u8, u8);
142 /// A SIMD vector of 16 `i8`s.
143 #[repr(simd)]
144 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
145 #[derive(Debug, Copy)]
146 pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
147                  i8, i8, i8, i8, i8, i8, i8, i8);
148 /// A SIMD boolean vector for length-16 vectors of 8-bit integers.
149 #[repr(simd)]
150 #[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
151 #[derive(Debug, Copy)]
152 pub struct bool8ix16(i8, i8, i8, i8, i8, i8, i8, i8,
153                      i8, i8, i8, i8, i8, i8, i8, i8);
154 
155 
156 macro_rules! simd {
157     ($($bool: ty: $($ty: ty = $elem: ty),*;)*) => {
158         $($(unsafe impl Simd for $ty {
159             type Bool = $bool;
160             type Elem = $elem;
161         }
162             impl Clone for $ty { #[inline] fn clone(&self) -> Self { *self } }
163             )*)*}
164 }
165 simd! {
166     bool8ix16: i8x16 = i8, u8x16 = u8, bool8ix16 = bool8i;
167     bool16ix8: i16x8 = i16, u16x8 = u16, bool16ix8 = bool16i;
168     bool32ix4: i32x4 = i32, u32x4 = u32, bool32ix4 = bool32i;
169     bool32fx4: f32x4 = f32, bool32fx4 = bool32f;
170 
171     bool32ix2: i32x2 = i32, u32x2 = u32, bool32ix2 = bool32i;
172     bool32fx2: f32x2 = f32, bool32fx2 = bool32f;
173 }
174 
175 #[allow(dead_code)]
176 #[inline]
bitcast<T: Simd, U: Simd>(x: T) -> U177 fn bitcast<T: Simd, U: Simd>(x: T) -> U {
178     assert_eq!(mem::size_of::<T>(),
179                mem::size_of::<U>());
180     unsafe {mem::transmute_copy(&x)}
181 }
182 
183 #[allow(dead_code)]
184 extern "platform-intrinsic" {
simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U185     fn simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U186     fn simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U187     fn simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U188     fn simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U189     fn simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U190     fn simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
191 
simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U192     fn simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U;
simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U193     fn simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U;
simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U194     fn simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U;
simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U195     fn simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U;
196 
simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T197     fn simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T;
simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U198     fn simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U;
199 
simd_cast<T: Simd, U: Simd>(x: T) -> U200     fn simd_cast<T: Simd, U: Simd>(x: T) -> U;
201 
simd_add<T: Simd>(x: T, y: T) -> T202     fn simd_add<T: Simd>(x: T, y: T) -> T;
simd_sub<T: Simd>(x: T, y: T) -> T203     fn simd_sub<T: Simd>(x: T, y: T) -> T;
simd_mul<T: Simd>(x: T, y: T) -> T204     fn simd_mul<T: Simd>(x: T, y: T) -> T;
simd_div<T: Simd>(x: T, y: T) -> T205     fn simd_div<T: Simd>(x: T, y: T) -> T;
simd_shl<T: Simd>(x: T, y: T) -> T206     fn simd_shl<T: Simd>(x: T, y: T) -> T;
simd_shr<T: Simd>(x: T, y: T) -> T207     fn simd_shr<T: Simd>(x: T, y: T) -> T;
simd_and<T: Simd>(x: T, y: T) -> T208     fn simd_and<T: Simd>(x: T, y: T) -> T;
simd_or<T: Simd>(x: T, y: T) -> T209     fn simd_or<T: Simd>(x: T, y: T) -> T;
simd_xor<T: Simd>(x: T, y: T) -> T210     fn simd_xor<T: Simd>(x: T, y: T) -> T;
211 }
212 #[repr(packed)]
213 #[derive(Copy)]
214 struct Unalign<T>(T);
215 
216 impl<T: Clone> Clone for Unalign<T> {
clone(&self) -> Unalign<T>217     fn clone(&self) -> Unalign<T> {
218         Unalign(unsafe { self.0.clone() })
219     }
220 }
221 
222 #[macro_use]
223 mod common;
224 mod sixty_four;
225 mod v256;
226 
227 #[cfg(any(feature = "doc",
228           target_arch = "x86",
229           target_arch = "x86_64"))]
230 pub mod x86;
231 #[cfg(any(feature = "doc", target_arch = "arm"))]
232 pub mod arm;
233 #[cfg(any(feature = "doc", target_arch = "aarch64"))]
234 pub mod aarch64;
235