Skip to main content

core/stdarch/crates/core_arch/src/aarch64/sve/
mod.rs

1//! SVE intrinsics
2
3#![allow(non_camel_case_types)]
4
5// `generated.rs` has a `super::*` and this import is for that
6use crate::intrinsics::{simd::*, *};
7
8#[rustfmt::skip]
9mod generated;
10#[rustfmt::skip]
11#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
12pub use self::generated::*;
13
14use crate::{marker::ConstParamTy, mem::transmute};
15
16pub(super) trait AsUnsigned {
17    type Unsigned;
18    unsafe fn as_unsigned(self) -> Self::Unsigned;
19}
20
21pub(super) trait AsSigned {
22    type Signed;
23    unsafe fn as_signed(self) -> Self::Signed;
24}
25
26/// Same as `Into` but with into being unsafe so that it can have the required `target_feature`
27pub(super) trait SveInto<T>: Sized {
28    unsafe fn sve_into(self) -> T;
29}
30
31impl<T> SveInto<T> for T {
32    #[inline]
33    #[target_feature(enable = "sve")]
34    unsafe fn sve_into(self) -> T {
35        self
36    }
37}
38
39macro_rules! impl_sve_type {
40    ($(($v:vis, $elem_type:ty, $name:ident, $elt:literal))*) => ($(
41        #[doc = concat!("Scalable vector of type ", stringify!($elem_type))]
42        #[derive(Clone, Copy, Debug)]
43        #[rustc_scalable_vector($elt)]
44        #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
45        $v struct $name($elem_type);
46    )*)
47}
48
49macro_rules! impl_sve_tuple_type {
50    ($(($v:vis, $vec_type:ty, $elt:tt, $name:ident))*) => ($(
51        impl_sve_tuple_type!(@ ($v, $vec_type, $elt, $name));
52    )*);
53    (@ ($v:vis, $vec_type:ty, 2, $name:ident)) => (
54        #[doc = concat!("Two-element tuple of scalable vectors of type ", stringify!($vec_type))]
55        #[derive(Clone, Copy, Debug)]
56        #[rustc_scalable_vector]
57        #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
58        $v struct $name($vec_type, $vec_type);
59    );
60    (@ ($v:vis, $vec_type:ty, 3, $name:ident)) => (
61        #[doc = concat!("Three-element tuple of scalable vectors of type ", stringify!($vec_type))]
62        #[derive(Clone, Copy, Debug)]
63        #[rustc_scalable_vector]
64        #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
65        $v struct $name($vec_type, $vec_type, $vec_type);
66    );
67    (@ ($v:vis, $vec_type:ty, 4, $name:ident)) => (
68        #[doc = concat!("Four-element tuple of scalable vectors of type ", stringify!($vec_type))]
69        #[derive(Clone, Copy, Debug)]
70        #[rustc_scalable_vector]
71        #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
72        $v struct $name($vec_type, $vec_type, $vec_type, $vec_type);
73    );
74}
75
76macro_rules! impl_sign_conversions_sv {
77    ($(($signed:ty, $unsigned:ty))*) => ($(
78        impl AsUnsigned for $signed {
79            type Unsigned = $unsigned;
80
81            #[inline]
82            #[target_feature(enable = "sve")]
83            unsafe fn as_unsigned(self) -> $unsigned {
84                transmute_unchecked(self)
85            }
86        }
87
88        impl AsSigned for $unsigned {
89            type Signed = $signed;
90
91            #[inline]
92            #[target_feature(enable = "sve")]
93            unsafe fn as_signed(self) -> $signed {
94                transmute_unchecked(self)
95            }
96        }
97    )*)
98}
99
100macro_rules! impl_sign_conversions {
101    ($(($signed:ty, $unsigned:ty))*) => ($(
102        impl AsUnsigned for $signed {
103            type Unsigned = $unsigned;
104
105            #[inline]
106            #[target_feature(enable = "sve")]
107            unsafe fn as_unsigned(self) -> $unsigned {
108                transmute(self)
109            }
110        }
111
112        impl AsSigned for $unsigned {
113            type Signed = $signed;
114
115            #[inline]
116            #[target_feature(enable = "sve")]
117            unsafe fn as_signed(self) -> $signed {
118                transmute(self)
119            }
120        }
121    )*)
122}
123
124/// LLVM requires the predicate lane count to be the same as the lane count
125/// it's working with. However the ACLE only defines one bool type and the
126/// instruction set doesn't have this distinction. As a result we have to
127/// create these internal types so we can match the LLVM signature. Each of
128/// these internal types can be converted to the public `svbool_t` type and
129/// the `svbool_t` type can be converted into these.
130macro_rules! impl_internal_sve_predicate {
131    ($(($name:ident, $elt:literal))*) => ($(
132        impl_sve_type! {
133            (pub(super), bool, $name, $elt)
134        }
135
136        impl SveInto<svbool_t> for $name {
137            #[inline]
138            #[target_feature(enable = "sve")]
139            unsafe fn sve_into(self) -> svbool_t {
140                #[allow(improper_ctypes)]
141                unsafe extern "unadjusted" {
142                    #[cfg_attr(
143                        target_arch = "aarch64",
144                        link_name = concat!("llvm.aarch64.sve.convert.to.svbool.nxv", $elt, "i1")
145                    )]
146                    fn convert_to_svbool(b: $name) -> svbool_t;
147                }
148                unsafe { convert_to_svbool(self) }
149            }
150        }
151
152        #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
153        impl SveInto<$name> for svbool_t {
154            #[inline]
155            #[target_feature(enable = "sve")]
156            unsafe fn sve_into(self) -> $name {
157                #[allow(improper_ctypes)]
158                unsafe extern "unadjusted" {
159                    #[cfg_attr(
160                        target_arch = "aarch64",
161                        link_name = concat!("llvm.aarch64.sve.convert.from.svbool.nxv", $elt, "i1")
162                    )]
163                    fn convert_from_svbool(b: svbool_t) -> $name;
164                }
165                unsafe { convert_from_svbool(self) }
166            }
167        }
168    )*)
169}
170
171impl_sve_type! {
172    (pub, bool, svbool_t, 16)
173
174    (pub, i8, svint8_t, 16)
175    (pub, u8, svuint8_t, 16)
176
177    (pub, i16, svint16_t, 8)
178    (pub, u16, svuint16_t, 8)
179    (pub, f32, svfloat32_t, 4)
180    (pub, i32, svint32_t, 4)
181    (pub, u32, svuint32_t, 4)
182    (pub, f64, svfloat64_t, 2)
183    (pub, i64, svint64_t, 2)
184    (pub, u64, svuint64_t, 2)
185
186    // Internal types:
187    (pub(super), i8, nxv2i8, 2)
188    (pub(super), i8, nxv4i8, 4)
189    (pub(super), i8, nxv8i8, 8)
190
191    (pub(super), i16, nxv2i16, 2)
192    (pub(super), i16, nxv4i16, 4)
193
194    (pub(super), i32, nxv2i32, 2)
195
196    (pub(super), u8, nxv2u8, 2)
197    (pub(super), u8, nxv4u8, 4)
198    (pub(super), u8, nxv8u8, 8)
199
200    (pub(super), u16, nxv2u16, 2)
201    (pub(super), u16, nxv4u16, 4)
202
203    (pub(super), u32, nxv2u32, 2)
204}
205
206impl_sve_tuple_type! {
207    (pub, svint8_t, 2, svint8x2_t)
208    (pub, svuint8_t, 2, svuint8x2_t)
209    (pub, svint16_t, 2, svint16x2_t)
210    (pub, svuint16_t, 2, svuint16x2_t)
211    (pub, svfloat32_t, 2, svfloat32x2_t)
212    (pub, svint32_t, 2, svint32x2_t)
213    (pub, svuint32_t, 2, svuint32x2_t)
214    (pub, svfloat64_t, 2, svfloat64x2_t)
215    (pub, svint64_t, 2, svint64x2_t)
216    (pub, svuint64_t, 2, svuint64x2_t)
217
218    (pub, svint8_t, 3, svint8x3_t)
219    (pub, svuint8_t, 3, svuint8x3_t)
220    (pub, svint16_t, 3, svint16x3_t)
221    (pub, svuint16_t, 3, svuint16x3_t)
222    (pub, svfloat32_t, 3, svfloat32x3_t)
223    (pub, svint32_t, 3, svint32x3_t)
224    (pub, svuint32_t, 3, svuint32x3_t)
225    (pub, svfloat64_t, 3, svfloat64x3_t)
226    (pub, svint64_t, 3, svint64x3_t)
227    (pub, svuint64_t, 3, svuint64x3_t)
228
229    (pub, svint8_t, 4, svint8x4_t)
230    (pub, svuint8_t, 4, svuint8x4_t)
231    (pub, svint16_t, 4, svint16x4_t)
232    (pub, svuint16_t, 4, svuint16x4_t)
233    (pub, svfloat32_t, 4, svfloat32x4_t)
234    (pub, svint32_t, 4, svint32x4_t)
235    (pub, svuint32_t, 4, svuint32x4_t)
236    (pub, svfloat64_t, 4, svfloat64x4_t)
237    (pub, svint64_t, 4, svint64x4_t)
238    (pub, svuint64_t, 4, svuint64x4_t)
239}
240
241impl_sign_conversions! {
242    (i8, u8)
243    (i16, u16)
244    (i32, u32)
245    (i64, u64)
246    (*const i8, *const u8)
247    (*const i16, *const u16)
248    (*const i32, *const u32)
249    (*const i64, *const u64)
250    (*mut i8, *mut u8)
251    (*mut i16, *mut u16)
252    (*mut i32, *mut u32)
253    (*mut i64, *mut u64)
254}
255
256impl_sign_conversions_sv! {
257    (svint8_t, svuint8_t)
258    (svint16_t, svuint16_t)
259    (svint32_t, svuint32_t)
260    (svint64_t, svuint64_t)
261
262    (svint8x2_t, svuint8x2_t)
263    (svint16x2_t, svuint16x2_t)
264    (svint32x2_t, svuint32x2_t)
265    (svint64x2_t, svuint64x2_t)
266
267    (svint8x3_t, svuint8x3_t)
268    (svint16x3_t, svuint16x3_t)
269    (svint32x3_t, svuint32x3_t)
270    (svint64x3_t, svuint64x3_t)
271
272    (svint8x4_t, svuint8x4_t)
273    (svint16x4_t, svuint16x4_t)
274    (svint32x4_t, svuint32x4_t)
275    (svint64x4_t, svuint64x4_t)
276
277    // Internal types:
278    (nxv2i8, nxv2u8)
279    (nxv4i8, nxv4u8)
280    (nxv8i8, nxv8u8)
281
282    (nxv2i16, nxv2u16)
283    (nxv4i16, nxv4u16)
284
285    (nxv2i32, nxv2u32)
286}
287
288impl_internal_sve_predicate! {
289    (svbool2_t, 2)
290    (svbool4_t, 4)
291    (svbool8_t, 8)
292}
293
294/// Patterns returned by a `PTRUE`
295#[repr(i32)]
296#[allow(non_camel_case_types)]
297#[derive(Clone, Copy, Debug, PartialEq, Eq, ConstParamTy)]
298#[non_exhaustive]
299#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
300pub enum svpattern {
301    /// Activate the largest power-of-two number of elements that is less than the vector length
302    SV_POW2 = 0,
303    /// Activate the first element
304    SV_VL1 = 1,
305    /// Activate the first two elements
306    SV_VL2 = 2,
307    /// Activate the first three elements
308    SV_VL3 = 3,
309    /// Activate the first four elements
310    SV_VL4 = 4,
311    /// Activate the first five elements
312    SV_VL5 = 5,
313    /// Activate the first six elements
314    SV_VL6 = 6,
315    /// Activate the first seven elements
316    SV_VL7 = 7,
317    /// Activate the first eight elements
318    SV_VL8 = 8,
319    /// Activate the first sixteen elements
320    SV_VL16 = 9,
321    /// Activate the first thirty-two elements
322    SV_VL32 = 10,
323    /// Activate the first sixty-four elements
324    SV_VL64 = 11,
325    /// Activate the first one-hundred-and-twenty-eight elements
326    SV_VL128 = 12,
327    /// Activate the first two-hundred-and-fifty-six elements
328    SV_VL256 = 13,
329    /// Activate the largest multiple-of-four number of elements that is less than the vector length
330    SV_MUL4 = 29,
331    /// Activate the largest multiple-of-three number of elements that is less than the vector
332    /// length
333    SV_MUL3 = 30,
334    /// Activate all elements
335    SV_ALL = 31,
336}
337
338/// Addressing mode for prefetch intrinsics - allows the specification of the expected access
339/// kind (read or write), the cache level to load the data, the data retention policy
340/// (temporal or streaming)
341#[repr(i32)]
342#[allow(non_camel_case_types)]
343#[derive(Clone, Copy, Debug, PartialEq, Eq, ConstParamTy)]
344#[non_exhaustive]
345#[unstable(feature = "stdarch_aarch64_sve", issue = "145052")]
346pub enum svprfop {
347    /// Temporal fetch of the addressed location for reading to the L1 cache (i.e. allocate in
348    /// cache normally)
349    SV_PLDL1KEEP = 0,
350    /// Streaming fetch of the addressed location for reading to the L1 cache (i.e. memory only
351    /// used once)
352    SV_PLDL1STRM = 1,
353    /// Temporal fetch of the addressed location for reading to the L2 cache (i.e. allocate in
354    /// cache normally)
355    SV_PLDL2KEEP = 2,
356    /// Streaming fetch of the addressed location for reading to the L2 cache (i.e. memory only
357    /// used once)
358    SV_PLDL2STRM = 3,
359    /// Temporal fetch of the addressed location for reading to the L3 cache (i.e. allocate in
360    /// cache normally)
361    SV_PLDL3KEEP = 4,
362    /// Streaming fetch of the addressed location for reading to the L3 cache (i.e. memory only
363    /// used once)
364    SV_PLDL3STRM = 5,
365    /// Temporal fetch of the addressed location for writing to the L1 cache (i.e. allocate in
366    /// cache normally)
367    SV_PSTL1KEEP = 8,
368    /// Temporal fetch of the addressed location for writing to the L1 cache (i.e. memory only
369    /// used once)
370    SV_PSTL1STRM = 9,
371    /// Temporal fetch of the addressed location for writing to the L2 cache (i.e. allocate in
372    /// cache normally)
373    SV_PSTL2KEEP = 10,
374    /// Temporal fetch of the addressed location for writing to the L2 cache (i.e. memory only
375    /// used once)
376    SV_PSTL2STRM = 11,
377    /// Temporal fetch of the addressed location for writing to the L3 cache (i.e. allocate in
378    /// cache normally)
379    SV_PSTL3KEEP = 12,
380    /// Temporal fetch of the addressed location for writing to the L3 cache (i.e. memory only
381    /// used once)
382    SV_PSTL3STRM = 13,
383}
384
385#[cfg(test)]
386#[path = "ld_st_tests_aarch64.rs"]
387mod ld_st_tests;