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