]>
git.proxmox.com Git - rustc.git/blob - library/stdarch/crates/core_arch/src/acle/dsp.rs
3 //! - Section 8.3 "16-bit multiplications"
5 //! Intrinsics that could live here:
24 use stdarch_test
::assert_instr
;
26 use crate::mem
::transmute
;
29 /// ARM-specific 32-bit wide vector of two packed `i16`.
30 pub struct int16x2_t(i16, i16);
31 /// ARM-specific 32-bit wide vector of two packed `u16`.
32 pub struct uint16x2_t(u16, u16);
36 #[link_name = "llvm.arm.smulbb"]
37 fn arm_smulbb(a
: i32, b
: i32) -> i32;
39 #[link_name = "llvm.arm.smulbt"]
40 fn arm_smulbt(a
: i32, b
: i32) -> i32;
42 #[link_name = "llvm.arm.smultb"]
43 fn arm_smultb(a
: i32, b
: i32) -> i32;
45 #[link_name = "llvm.arm.smultt"]
46 fn arm_smultt(a
: i32, b
: i32) -> i32;
48 #[link_name = "llvm.arm.smulwb"]
49 fn arm_smulwb(a
: i32, b
: i32) -> i32;
51 #[link_name = "llvm.arm.smulwt"]
52 fn arm_smulwt(a
: i32, b
: i32) -> i32;
54 #[link_name = "llvm.arm.qadd"]
55 fn arm_qadd(a
: i32, b
: i32) -> i32;
57 #[link_name = "llvm.arm.qsub"]
58 fn arm_qsub(a
: i32, b
: i32) -> i32;
60 #[link_name = "llvm.arm.smlabb"]
61 fn arm_smlabb(a
: i32, b
: i32, c
: i32) -> i32;
63 #[link_name = "llvm.arm.smlabt"]
64 fn arm_smlabt(a
: i32, b
: i32, c
: i32) -> i32;
66 #[link_name = "llvm.arm.smlatb"]
67 fn arm_smlatb(a
: i32, b
: i32, c
: i32) -> i32;
69 #[link_name = "llvm.arm.smlatt"]
70 fn arm_smlatt(a
: i32, b
: i32, c
: i32) -> i32;
72 #[link_name = "llvm.arm.smlawb"]
73 fn arm_smlawb(a
: i32, b
: i32, c
: i32) -> i32;
75 #[link_name = "llvm.arm.smlawt"]
76 fn arm_smlawt(a
: i32, b
: i32, c
: i32) -> i32;
79 /// Insert a SMULBB instruction
81 /// Returns the equivalent of a\[0\] * b\[0\]
82 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
84 #[cfg_attr(test, assert_instr(smulbb))]
85 pub unsafe fn __smulbb(a
: int16x2_t
, b
: int16x2_t
) -> i32 {
86 arm_smulbb(transmute(a
), transmute(b
))
89 /// Insert a SMULTB instruction
91 /// Returns the equivalent of a\[0\] * b\[1\]
92 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
94 #[cfg_attr(test, assert_instr(smultb))]
95 pub unsafe fn __smultb(a
: int16x2_t
, b
: int16x2_t
) -> i32 {
96 arm_smultb(transmute(a
), transmute(b
))
99 /// Insert a SMULTB instruction
101 /// Returns the equivalent of a\[1\] * b\[0\]
102 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
104 #[cfg_attr(test, assert_instr(smulbt))]
105 pub unsafe fn __smulbt(a
: int16x2_t
, b
: int16x2_t
) -> i32 {
106 arm_smulbt(transmute(a
), transmute(b
))
109 /// Insert a SMULTT instruction
111 /// Returns the equivalent of a\[1\] * b\[1\]
112 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
114 #[cfg_attr(test, assert_instr(smultt))]
115 pub unsafe fn __smultt(a
: int16x2_t
, b
: int16x2_t
) -> i32 {
116 arm_smultt(transmute(a
), transmute(b
))
119 /// Insert a SMULWB instruction
121 /// Multiplies the 32-bit signed first operand with the low halfword
122 /// (as a 16-bit signed integer) of the second operand.
123 /// Return the top 32 bits of the 48-bit product
125 #[cfg_attr(test, assert_instr(smulwb))]
126 pub unsafe fn __smulwb(a
: int16x2_t
, b
: i32) -> i32 {
127 arm_smulwb(transmute(a
), b
)
130 /// Insert a SMULWT instruction
132 /// Multiplies the 32-bit signed first operand with the high halfword
133 /// (as a 16-bit signed integer) of the second operand.
134 /// Return the top 32 bits of the 48-bit product
136 #[cfg_attr(test, assert_instr(smulwt))]
137 pub unsafe fn __smulwt(a
: int16x2_t
, b
: i32) -> i32 {
138 arm_smulwt(transmute(a
), b
)
141 /// Signed saturating addition
143 /// Returns the 32-bit saturating signed equivalent of a + b.
144 /// Sets the Q flag if saturation occurs.
146 #[cfg_attr(test, assert_instr(qadd))]
147 pub unsafe fn __qadd(a
: i32, b
: i32) -> i32 {
151 /// Signed saturating subtraction
153 /// Returns the 32-bit saturating signed equivalent of a - b.
154 /// Sets the Q flag if saturation occurs.
156 #[cfg_attr(test, assert_instr(qsub))]
157 pub unsafe fn __qsub(a
: i32, b
: i32) -> i32 {
161 /// Insert a QADD instruction
163 /// Returns the 32-bit saturating signed equivalent of a + a
164 /// Sets the Q flag if saturation occurs.
166 #[cfg_attr(test, assert_instr(qadd))]
167 pub unsafe fn __qdbl(a
: i32) -> i32 {
171 /// Insert a SMLABB instruction
173 /// Returns the equivalent of a\[0\] * b\[0\] + c
174 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
175 /// Sets the Q flag if overflow occurs on the addition.
177 #[cfg_attr(test, assert_instr(smlabb))]
178 pub unsafe fn __smlabb(a
: int16x2_t
, b
: int16x2_t
, c
: i32) -> i32 {
179 arm_smlabb(transmute(a
), transmute(b
), c
)
182 /// Insert a SMLABT instruction
184 /// Returns the equivalent of a\[0\] * b\[1\] + c
185 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
186 /// Sets the Q flag if overflow occurs on the addition.
188 #[cfg_attr(test, assert_instr(smlabt))]
189 pub unsafe fn __smlabt(a
: int16x2_t
, b
: int16x2_t
, c
: i32) -> i32 {
190 arm_smlabt(transmute(a
), transmute(b
), c
)
193 /// Insert a SMLATB instruction
195 /// Returns the equivalent of a\[1\] * b\[0\] + c
196 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
197 /// Sets the Q flag if overflow occurs on the addition.
199 #[cfg_attr(test, assert_instr(smlatb))]
200 pub unsafe fn __smlatb(a
: int16x2_t
, b
: int16x2_t
, c
: i32) -> i32 {
201 arm_smlatb(transmute(a
), transmute(b
), c
)
204 /// Insert a SMLATT instruction
206 /// Returns the equivalent of a\[1\] * b\[1\] + c
207 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
208 /// Sets the Q flag if overflow occurs on the addition.
210 #[cfg_attr(test, assert_instr(smlatt))]
211 pub unsafe fn __smlatt(a
: int16x2_t
, b
: int16x2_t
, c
: i32) -> i32 {
212 arm_smlatt(transmute(a
), transmute(b
), c
)
215 /// Insert a SMLAWB instruction
217 /// Returns the equivalent of (a * b\[0\] + (c << 16)) >> 16
218 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
219 /// Sets the Q flag if overflow occurs on the addition.
221 #[cfg_attr(test, assert_instr(smlawb))]
222 pub unsafe fn __smlawb(a
: i32, b
: int16x2_t
, c
: i32) -> i32 {
223 arm_smlawb(a
, transmute(b
), c
)
226 /// Insert a SMLAWT instruction
228 /// Returns the equivalent of (a * b\[1\] + (c << 16)) >> 16
229 /// where \[0\] is the lower 16 bits and \[1\] is the upper 16 bits.
230 /// Sets the Q flag if overflow occurs on the addition.
232 #[cfg_attr(test, assert_instr(smlawt))]
233 pub unsafe fn __smlawt(a
: i32, b
: int16x2_t
, c
: i32) -> i32 {
234 arm_smlawt(a
, transmute(b
), c
)
239 use crate::core_arch
::{
241 simd
::{i16x2, i8x4, u8x4}
,
243 use std
::mem
::transmute
;
244 use stdarch_test
::simd_test
;
249 let a
= i16x2
::new(10, 20);
250 let b
= i16x2
::new(30, 40);
251 assert_eq
!(super::__smulbb(transmute(a
), transmute(b
)), 10 * 30);
258 let a
= i16x2
::new(10, 20);
259 let b
= i16x2
::new(30, 40);
260 assert_eq
!(super::__smulbt(transmute(a
), transmute(b
)), 10 * 40);
267 let a
= i16x2
::new(10, 20);
268 let b
= i16x2
::new(30, 40);
269 assert_eq
!(super::__smultb(transmute(a
), transmute(b
)), 20 * 30);
276 let a
= i16x2
::new(10, 20);
277 let b
= i16x2
::new(30, 40);
278 assert_eq
!(super::__smultt(transmute(a
), transmute(b
)), 20 * 40);
285 let a
= i16x2
::new(10, 20);
287 assert_eq
!(super::__smulwb(transmute(a
), b
), 20 * b
);
294 let a
= i16x2
::new(10, 20);
296 assert_eq
!(super::__smulwt(transmute(a
), b
), (10 * b
) >> 16);
303 assert_eq
!(super::__qadd(-10, 60), 50);
304 assert_eq
!(super::__qadd(i32::MAX
, 10), i32::MAX
);
305 assert_eq
!(super::__qadd(i32::MIN
, -10), i32::MIN
);
312 assert_eq
!(super::__qsub(10, 60), -50);
313 assert_eq
!(super::__qsub(i32::MAX
, -10), i32::MAX
);
314 assert_eq
!(super::__qsub(i32::MIN
, 10), i32::MIN
);
320 assert_eq
!(super::__qdbl(10), 20);
321 assert_eq
!(super::__qdbl(i32::MAX
), i32::MAX
);
327 let a
= i16x2
::new(10, 20);
328 let b
= i16x2
::new(30, 40);
330 let r
= (10 * 30) + c
;
331 assert_eq
!(super::__smlabb(transmute(a
), transmute(b
), c
), r
);
337 let a
= i16x2
::new(10, 20);
338 let b
= i16x2
::new(30, 40);
340 let r
= (10 * 40) + c
;
341 assert_eq
!(super::__smlabt(transmute(a
), transmute(b
), c
), r
);
347 let a
= i16x2
::new(10, 20);
348 let b
= i16x2
::new(30, 40);
350 let r
= (20 * 30) + c
;
351 assert_eq
!(super::__smlabt(transmute(a
), transmute(b
), c
), r
);
357 let a
= i16x2
::new(10, 20);
358 let b
= i16x2
::new(30, 40);
360 let r
= (20 * 40) + c
;
361 assert_eq
!(super::__smlatt(transmute(a
), transmute(b
), c
), r
);
368 let b
= i16x2
::new(30, 40);
370 let r
: i32 = ((a
* 30) + (c
<< 16)) >> 16;
371 assert_eq
!(super::__smlawb(a
, transmute(b
), c
), r
);
378 let b
= i16x2
::new(30, 40);
380 let r
: i32 = ((a
* 40) + (c
<< 16)) >> 16;
381 assert_eq
!(super::__smlawt(a
, transmute(b
), c
), r
);