Skip to content

Commit 696e957

Browse files
paolotetialexcrichton
authored andcommitted
Dual 16-bit Signed Multiply with Addition/Subtraction (rust-lang#543)
Add support for `smlad` and `smlsd`. - `smlad`: Dual 16-bit Signed Multiply with Addition and 32-bit accumulation - `smlsd`: Dual 16-bit Signed Multiply with Subtraction and 32-bit accumulation
1 parent f67c5b6 commit 696e957

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

coresimd/arm/dsp.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
//! 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
26
37
#[cfg(test)]
48
use stdsimd_test::assert_instr;
@@ -54,6 +58,12 @@ extern "C" {
5458
#[link_name = "llvm.arm.sasx"]
5559
fn arm_sasx(a: i32, b: i32) -> i32;
5660

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+
5767
#[link_name = "llvm.arm.sel"]
5868
fn arm_sel(a: i32, b: i32) -> i32;
5969

@@ -201,6 +211,28 @@ pub unsafe fn sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
201211
dsp_call!(arm_sadd8, a, b)
202212
}
203213

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+
204236
/// Returns the 16-bit signed equivalent of
205237
///
206238
/// res\[0\] = a\[0\] - b\[1\]
@@ -213,6 +245,8 @@ pub unsafe fn sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
213245
dsp_call!(arm_sasx, a, b)
214246
}
215247

248+
/// Select bytes from each operand according to APSR GE flags
249+
///
216250
/// Returns the equivalent of
217251
///
218252
/// res\[0\] = GE\[0\] ? a\[0\] : b\[0\]
@@ -480,6 +514,26 @@ mod tests {
480514
}
481515
}
482516

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+
483537
#[test]
484538
fn sel() {
485539
unsafe {

0 commit comments

Comments
 (0)