1
1
//! ARM DSP Intrinsics.
2
+ //!
3
+ //! Based on "Arm C Language Extensions (ACLE) Version Q2 2018"
4
+ //!
5
+ //! https://developer.arm.com/products/software-development-tools/compilers/arm-compiler-5/docs/101028/0006
2
6
3
7
#[ cfg( test) ]
4
8
use stdsimd_test:: assert_instr;
@@ -54,6 +58,12 @@ extern "C" {
54
58
#[ link_name = "llvm.arm.sasx" ]
55
59
fn arm_sasx ( a : i32 , b : i32 ) -> i32 ;
56
60
61
+ #[ link_name = "llvm.arm.smlad" ]
62
+ fn arm_smlad ( a : i32 , b : i32 , c : i32 ) -> i32 ;
63
+
64
+ #[ link_name = "llvm.arm.smlsd" ]
65
+ fn arm_smlsd ( a : i32 , b : i32 , c : i32 ) -> i32 ;
66
+
57
67
#[ link_name = "llvm.arm.sel" ]
58
68
fn arm_sel ( a : i32 , b : i32 ) -> i32 ;
59
69
@@ -201,6 +211,28 @@ pub unsafe fn sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
201
211
dsp_call ! ( arm_sadd8, a, b)
202
212
}
203
213
214
+ /// Dual 16-bit Signed Multiply with Addition of products
215
+ /// and 32-bit accumulation.
216
+ ///
217
+ /// Returns the 16-bit signed equivalent of
218
+ /// res = a\[0\] * b\[0\] + a\[1\] * b\[1\] + c
219
+ #[ inline]
220
+ #[ cfg_attr( test, assert_instr( smlad) ) ]
221
+ pub unsafe fn smlad ( a : int16x2_t , b : int16x2_t , c : i32 ) -> i32 {
222
+ arm_smlad ( :: mem:: transmute ( a) , :: mem:: transmute ( b) , c)
223
+ }
224
+
225
+ /// Dual 16-bit Signed Multiply with Subtraction of products
226
+ /// and 32-bit accumulation and overflow detection.
227
+ ///
228
+ /// Returns the 16-bit signed equivalent of
229
+ /// res = a\[0\] * b\[0\] - a\[1\] * b\[1\] + c
230
+ #[ inline]
231
+ #[ cfg_attr( test, assert_instr( smlsd) ) ]
232
+ pub unsafe fn smlsd ( a : int16x2_t , b : int16x2_t , c : i32 ) -> i32 {
233
+ arm_smlsd ( :: mem:: transmute ( a) , :: mem:: transmute ( b) , c)
234
+ }
235
+
204
236
/// Returns the 16-bit signed equivalent of
205
237
///
206
238
/// res\[0\] = a\[0\] - b\[1\]
@@ -213,6 +245,8 @@ pub unsafe fn sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
213
245
dsp_call ! ( arm_sasx, a, b)
214
246
}
215
247
248
+ /// Select bytes from each operand according to APSR GE flags
249
+ ///
216
250
/// Returns the equivalent of
217
251
///
218
252
/// res\[0\] = GE\[0\] ? a\[0\] : b\[0\]
@@ -480,6 +514,26 @@ mod tests {
480
514
}
481
515
}
482
516
517
+ #[ test]
518
+ fn smlad ( ) {
519
+ unsafe {
520
+ let a = i16x2:: new ( 1 , 2 ) ;
521
+ let b = i16x2:: new ( 3 , 4 ) ;
522
+ let r = dsp:: smlad ( :: mem:: transmute ( a) , :: mem:: transmute ( b) , 10 ) ;
523
+ assert_eq ! ( r, ( 1 * 3 ) + ( 2 * 4 ) + 10 ) ;
524
+ }
525
+ }
526
+
527
+ #[ test]
528
+ fn smlsd ( ) {
529
+ unsafe {
530
+ let a = i16x2:: new ( 1 , 2 ) ;
531
+ let b = i16x2:: new ( 3 , 4 ) ;
532
+ let r = dsp:: smlsd ( :: mem:: transmute ( a) , :: mem:: transmute ( b) , 10 ) ;
533
+ assert_eq ! ( r, ( ( 1 * 3 ) - ( 2 * 4 ) ) + 10 ) ;
534
+ }
535
+ }
536
+
483
537
#[ test]
484
538
fn sel ( ) {
485
539
unsafe {
0 commit comments