]> git.proxmox.com Git - rustc.git/blob - src/stdarch/crates/core_arch/src/acle/simd32.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / stdarch / crates / core_arch / src / acle / simd32.rs
1 //! # References
2 //!
3 //! - Section 8.5 "32-bit SIMD intrinsics" of ACLE
4 //!
5 //! Intrinsics that could live here
6 //!
7 //! - \[x\] __sel
8 //! - \[ \] __ssat16
9 //! - \[ \] __usat16
10 //! - \[ \] __sxtab16
11 //! - \[ \] __sxtb16
12 //! - \[ \] __uxtab16
13 //! - \[ \] __uxtb16
14 //! - \[x\] __qadd8
15 //! - \[x\] __qsub8
16 //! - \[x\] __sadd8
17 //! - \[x\] __shadd8
18 //! - \[x\] __shsub8
19 //! - \[x\] __ssub8
20 //! - \[ \] __uadd8
21 //! - \[ \] __uhadd8
22 //! - \[ \] __uhsub8
23 //! - \[ \] __uqadd8
24 //! - \[ \] __uqsub8
25 //! - \[x\] __usub8
26 //! - \[x\] __usad8
27 //! - \[x\] __usada8
28 //! - \[x\] __qadd16
29 //! - \[x\] __qasx
30 //! - \[x\] __qsax
31 //! - \[x\] __qsub16
32 //! - \[x\] __sadd16
33 //! - \[x\] __sasx
34 //! - \[x\] __shadd16
35 //! - \[ \] __shasx
36 //! - \[ \] __shsax
37 //! - \[x\] __shsub16
38 //! - \[ \] __ssax
39 //! - \[ \] __ssub16
40 //! - \[ \] __uadd16
41 //! - \[ \] __uasx
42 //! - \[ \] __uhadd16
43 //! - \[ \] __uhasx
44 //! - \[ \] __uhsax
45 //! - \[ \] __uhsub16
46 //! - \[ \] __uqadd16
47 //! - \[ \] __uqasx
48 //! - \[x\] __uqsax
49 //! - \[ \] __uqsub16
50 //! - \[ \] __usax
51 //! - \[ \] __usub16
52 //! - \[x\] __smlad
53 //! - \[ \] __smladx
54 //! - \[ \] __smlald
55 //! - \[ \] __smlaldx
56 //! - \[x\] __smlsd
57 //! - \[ \] __smlsdx
58 //! - \[ \] __smlsld
59 //! - \[ \] __smlsldx
60 //! - \[x\] __smuad
61 //! - \[x\] __smuadx
62 //! - \[x\] __smusd
63 //! - \[x\] __smusdx
64
65 #[cfg(test)]
66 use stdarch_test::assert_instr;
67
68 use crate::{core_arch::acle::dsp::int16x2_t, mem::transmute};
69
70 types! {
71 /// ARM-specific 32-bit wide vector of four packed `i8`.
72 pub struct int8x4_t(i8, i8, i8, i8);
73 /// ARM-specific 32-bit wide vector of four packed `u8`.
74 pub struct uint8x4_t(u8, u8, u8, u8);
75 }
76
77 macro_rules! dsp_call {
78 ($name:expr, $a:expr, $b:expr) => {
79 transmute($name(transmute($a), transmute($b)))
80 };
81 }
82
83 extern "C" {
84 #[link_name = "llvm.arm.qadd8"]
85 fn arm_qadd8(a: i32, b: i32) -> i32;
86
87 #[link_name = "llvm.arm.qsub8"]
88 fn arm_qsub8(a: i32, b: i32) -> i32;
89
90 #[link_name = "llvm.arm.qsub16"]
91 fn arm_qsub16(a: i32, b: i32) -> i32;
92
93 #[link_name = "llvm.arm.qadd16"]
94 fn arm_qadd16(a: i32, b: i32) -> i32;
95
96 #[link_name = "llvm.arm.qasx"]
97 fn arm_qasx(a: i32, b: i32) -> i32;
98
99 #[link_name = "llvm.arm.qsax"]
100 fn arm_qsax(a: i32, b: i32) -> i32;
101
102 #[link_name = "llvm.arm.sadd16"]
103 fn arm_sadd16(a: i32, b: i32) -> i32;
104
105 #[link_name = "llvm.arm.sadd8"]
106 fn arm_sadd8(a: i32, b: i32) -> i32;
107
108 #[link_name = "llvm.arm.smlad"]
109 fn arm_smlad(a: i32, b: i32, c: i32) -> i32;
110
111 #[link_name = "llvm.arm.smlsd"]
112 fn arm_smlsd(a: i32, b: i32, c: i32) -> i32;
113
114 #[link_name = "llvm.arm.sasx"]
115 fn arm_sasx(a: i32, b: i32) -> i32;
116
117 #[link_name = "llvm.arm.sel"]
118 fn arm_sel(a: i32, b: i32) -> i32;
119
120 #[link_name = "llvm.arm.shadd8"]
121 fn arm_shadd8(a: i32, b: i32) -> i32;
122
123 #[link_name = "llvm.arm.shadd16"]
124 fn arm_shadd16(a: i32, b: i32) -> i32;
125
126 #[link_name = "llvm.arm.shsub8"]
127 fn arm_shsub8(a: i32, b: i32) -> i32;
128
129 #[link_name = "llvm.arm.ssub8"]
130 fn arm_ssub8(a: i32, b: i32) -> i32;
131
132 #[link_name = "llvm.arm.usub8"]
133 fn arm_usub8(a: i32, b: i32) -> i32;
134
135 #[link_name = "llvm.arm.shsub16"]
136 fn arm_shsub16(a: i32, b: i32) -> i32;
137
138 #[link_name = "llvm.arm.smuad"]
139 fn arm_smuad(a: i32, b: i32) -> i32;
140
141 #[link_name = "llvm.arm.smuadx"]
142 fn arm_smuadx(a: i32, b: i32) -> i32;
143
144 #[link_name = "llvm.arm.smusd"]
145 fn arm_smusd(a: i32, b: i32) -> i32;
146
147 #[link_name = "llvm.arm.smusdx"]
148 fn arm_smusdx(a: i32, b: i32) -> i32;
149
150 #[link_name = "llvm.arm.usad8"]
151 fn arm_usad8(a: i32, b: i32) -> u32;
152 }
153
154 /// Saturating four 8-bit integer additions
155 ///
156 /// Returns the 8-bit signed equivalent of
157 ///
158 /// res\[0\] = a\[0\] + b\[0\]
159 /// res\[1\] = a\[1\] + b\[1\]
160 /// res\[2\] = a\[2\] + b\[2\]
161 /// res\[3\] = a\[3\] + b\[3\]
162 #[inline]
163 #[cfg_attr(test, assert_instr(qadd8))]
164 pub unsafe fn __qadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
165 dsp_call!(arm_qadd8, a, b)
166 }
167
168 /// Saturating two 8-bit integer subtraction
169 ///
170 /// Returns the 8-bit signed equivalent of
171 ///
172 /// res\[0\] = a\[0\] - b\[0\]
173 /// res\[1\] = a\[1\] - b\[1\]
174 /// res\[2\] = a\[2\] - b\[2\]
175 /// res\[3\] = a\[3\] - b\[3\]
176 #[inline]
177 #[cfg_attr(test, assert_instr(qsub8))]
178 pub unsafe fn __qsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
179 dsp_call!(arm_qsub8, a, b)
180 }
181
182 /// Saturating two 16-bit integer subtraction
183 ///
184 /// Returns the 16-bit signed equivalent of
185 ///
186 /// res\[0\] = a\[0\] - b\[0\]
187 /// res\[1\] = a\[1\] - b\[1\]
188 #[inline]
189 #[cfg_attr(test, assert_instr(qsub16))]
190 pub unsafe fn __qsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
191 dsp_call!(arm_qsub16, a, b)
192 }
193
194 /// Saturating two 16-bit integer additions
195 ///
196 /// Returns the 16-bit signed equivalent of
197 ///
198 /// res\[0\] = a\[0\] + b\[0\]
199 /// res\[1\] = a\[1\] + b\[1\]
200 #[inline]
201 #[cfg_attr(test, assert_instr(qadd16))]
202 pub unsafe fn __qadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
203 dsp_call!(arm_qadd16, a, b)
204 }
205
206 /// Returns the 16-bit signed saturated equivalent of
207 ///
208 /// res\[0\] = a\[0\] - b\[1\]
209 /// res\[1\] = a\[1\] + b\[0\]
210 #[inline]
211 #[cfg_attr(test, assert_instr(qasx))]
212 pub unsafe fn __qasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
213 dsp_call!(arm_qasx, a, b)
214 }
215
216 /// Returns the 16-bit signed saturated equivalent of
217 ///
218 /// res\[0\] = a\[0\] + b\[1\]
219 /// res\[1\] = a\[1\] - b\[0\]
220 #[inline]
221 #[cfg_attr(test, assert_instr(qsax))]
222 pub unsafe fn __qsax(a: int16x2_t, b: int16x2_t) -> int16x2_t {
223 dsp_call!(arm_qsax, a, b)
224 }
225
226 /// Returns the 16-bit signed saturated equivalent of
227 ///
228 /// res\[0\] = a\[0\] + b\[1\]
229 /// res\[1\] = a\[1\] + b\[0\]
230 ///
231 /// and the GE bits of the APSR are set.
232 #[inline]
233 #[cfg_attr(test, assert_instr(sadd16))]
234 pub unsafe fn __sadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
235 dsp_call!(arm_sadd16, a, b)
236 }
237
238 /// Returns the 8-bit signed saturated equivalent of
239 ///
240 /// res\[0\] = a\[0\] + b\[1\]
241 /// res\[1\] = a\[1\] + b\[0\]
242 /// res\[2\] = a\[2\] + b\[2\]
243 /// res\[3\] = a\[3\] + b\[3\]
244 ///
245 /// and the GE bits of the APSR are set.
246 #[inline]
247 #[cfg_attr(test, assert_instr(sadd8))]
248 pub unsafe fn __sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
249 dsp_call!(arm_sadd8, a, b)
250 }
251
252 /// Dual 16-bit Signed Multiply with Addition of products
253 /// and 32-bit accumulation.
254 ///
255 /// Returns the 16-bit signed equivalent of
256 /// res = a\[0\] * b\[0\] + a\[1\] * b\[1\] + c
257 #[inline]
258 #[cfg_attr(test, assert_instr(smlad))]
259 pub unsafe fn __smlad(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
260 arm_smlad(transmute(a), transmute(b), c)
261 }
262
263 /// Dual 16-bit Signed Multiply with Subtraction of products
264 /// and 32-bit accumulation and overflow detection.
265 ///
266 /// Returns the 16-bit signed equivalent of
267 /// res = a\[0\] * b\[0\] - a\[1\] * b\[1\] + c
268 #[inline]
269 #[cfg_attr(test, assert_instr(smlsd))]
270 pub unsafe fn __smlsd(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
271 arm_smlsd(transmute(a), transmute(b), c)
272 }
273
274 /// Returns the 16-bit signed equivalent of
275 ///
276 /// res\[0\] = a\[0\] - b\[1\]
277 /// res\[1\] = a\[1\] + b\[0\]
278 ///
279 /// and the GE bits of the APSR are set.
280 #[inline]
281 #[cfg_attr(test, assert_instr(sasx))]
282 pub unsafe fn __sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
283 dsp_call!(arm_sasx, a, b)
284 }
285
286 /// Select bytes from each operand according to APSR GE flags
287 ///
288 /// Returns the equivalent of
289 ///
290 /// res\[0\] = GE\[0\] ? a\[0\] : b\[0\]
291 /// res\[1\] = GE\[1\] ? a\[1\] : b\[1\]
292 /// res\[2\] = GE\[2\] ? a\[2\] : b\[2\]
293 /// res\[3\] = GE\[3\] ? a\[3\] : b\[3\]
294 ///
295 /// where GE are bits of APSR
296 #[inline]
297 #[cfg_attr(test, assert_instr(sel))]
298 pub unsafe fn __sel(a: int8x4_t, b: int8x4_t) -> int8x4_t {
299 dsp_call!(arm_sel, a, b)
300 }
301
302 /// Signed halving parallel byte-wise addition.
303 ///
304 /// Returns the 8-bit signed equivalent of
305 ///
306 /// res\[0\] = (a\[0\] + b\[0\]) / 2
307 /// res\[1\] = (a\[1\] + b\[1\]) / 2
308 /// res\[2\] = (a\[2\] + b\[2\]) / 2
309 /// res\[3\] = (a\[3\] + b\[3\]) / 2
310 #[inline]
311 #[cfg_attr(test, assert_instr(shadd8))]
312 pub unsafe fn __shadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
313 dsp_call!(arm_shadd8, a, b)
314 }
315
316 /// Signed halving parallel halfword-wise addition.
317 ///
318 /// Returns the 16-bit signed equivalent of
319 ///
320 /// res\[0\] = (a\[0\] + b\[0\]) / 2
321 /// res\[1\] = (a\[1\] + b\[1\]) / 2
322 #[inline]
323 #[cfg_attr(test, assert_instr(shadd16))]
324 pub unsafe fn __shadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
325 dsp_call!(arm_shadd16, a, b)
326 }
327
328 /// Signed halving parallel byte-wise subtraction.
329 ///
330 /// Returns the 8-bit signed equivalent of
331 ///
332 /// res\[0\] = (a\[0\] - b\[0\]) / 2
333 /// res\[1\] = (a\[1\] - b\[1\]) / 2
334 /// res\[2\] = (a\[2\] - b\[2\]) / 2
335 /// res\[3\] = (a\[3\] - b\[3\]) / 2
336 #[inline]
337 #[cfg_attr(test, assert_instr(shsub8))]
338 pub unsafe fn __shsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
339 dsp_call!(arm_shsub8, a, b)
340 }
341
342 /// Inserts a `USUB8` instruction.
343 ///
344 /// Returns the 8-bit unsigned equivalent of
345 ///
346 /// res\[0\] = a\[0\] - a\[0\]
347 /// res\[1\] = a\[1\] - a\[1\]
348 /// res\[2\] = a\[2\] - a\[2\]
349 /// res\[3\] = a\[3\] - a\[3\]
350 ///
351 /// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
352 /// The GE bits of the APSR are set.
353 #[inline]
354 #[cfg_attr(test, assert_instr(usub8))]
355 pub unsafe fn __usub8(a: uint8x4_t, b: uint8x4_t) -> uint8x4_t {
356 dsp_call!(arm_usub8, a, b)
357 }
358
359 /// Inserts a `SSUB8` instruction.
360 ///
361 /// Returns the 8-bit signed equivalent of
362 ///
363 /// res\[0\] = a\[0\] - a\[0\]
364 /// res\[1\] = a\[1\] - a\[1\]
365 /// res\[2\] = a\[2\] - a\[2\]
366 /// res\[3\] = a\[3\] - a\[3\]
367 ///
368 /// where \[0\] is the lower 8 bits and \[3\] is the upper 8 bits.
369 /// The GE bits of the APSR are set.
370 #[inline]
371 #[cfg_attr(test, assert_instr(ssub8))]
372 pub unsafe fn __ssub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
373 dsp_call!(arm_ssub8, a, b)
374 }
375
376 /// Signed halving parallel halfword-wise subtraction.
377 ///
378 /// Returns the 16-bit signed equivalent of
379 ///
380 /// res\[0\] = (a\[0\] - b\[0\]) / 2
381 /// res\[1\] = (a\[1\] - b\[1\]) / 2
382 #[inline]
383 #[cfg_attr(test, assert_instr(shsub16))]
384 pub unsafe fn __shsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
385 dsp_call!(arm_shsub16, a, b)
386 }
387
388 /// Signed Dual Multiply Add.
389 ///
390 /// Returns the equivalent of
391 ///
392 /// res = a\[0\] * b\[0\] + a\[1\] * b\[1\]
393 ///
394 /// and sets the Q flag if overflow occurs on the addition.
395 #[inline]
396 #[cfg_attr(test, assert_instr(smuad))]
397 pub unsafe fn __smuad(a: int16x2_t, b: int16x2_t) -> i32 {
398 arm_smuad(transmute(a), transmute(b))
399 }
400
401 /// Signed Dual Multiply Add Reversed.
402 ///
403 /// Returns the equivalent of
404 ///
405 /// res = a\[0\] * b\[1\] + a\[1\] * b\[0\]
406 ///
407 /// and sets the Q flag if overflow occurs on the addition.
408 #[inline]
409 #[cfg_attr(test, assert_instr(smuadx))]
410 pub unsafe fn __smuadx(a: int16x2_t, b: int16x2_t) -> i32 {
411 arm_smuadx(transmute(a), transmute(b))
412 }
413
414 /// Signed Dual Multiply Subtract.
415 ///
416 /// Returns the equivalent of
417 ///
418 /// res = a\[0\] * b\[0\] - a\[1\] * b\[1\]
419 ///
420 /// and sets the Q flag if overflow occurs on the addition.
421 #[inline]
422 #[cfg_attr(test, assert_instr(smusd))]
423 pub unsafe fn __smusd(a: int16x2_t, b: int16x2_t) -> i32 {
424 arm_smusd(transmute(a), transmute(b))
425 }
426
427 /// Signed Dual Multiply Subtract Reversed.
428 ///
429 /// Returns the equivalent of
430 ///
431 /// res = a\[0\] * b\[1\] - a\[1\] * b\[0\]
432 ///
433 /// and sets the Q flag if overflow occurs on the addition.
434 #[inline]
435 #[cfg_attr(test, assert_instr(smusdx))]
436 pub unsafe fn __smusdx(a: int16x2_t, b: int16x2_t) -> i32 {
437 arm_smusdx(transmute(a), transmute(b))
438 }
439
440 /// Sum of 8-bit absolute differences.
441 ///
442 /// Returns the 8-bit unsigned equivalent of
443 ///
444 /// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
445 /// (a\[2\] - b\[2\]) + (a\[3\] - b\[3\])
446 #[inline]
447 #[cfg_attr(test, assert_instr(usad8))]
448 pub unsafe fn __usad8(a: int8x4_t, b: int8x4_t) -> u32 {
449 arm_usad8(transmute(a), transmute(b))
450 }
451
452 /// Sum of 8-bit absolute differences and constant.
453 ///
454 /// Returns the 8-bit unsigned equivalent of
455 ///
456 /// res = abs(a\[0\] - b\[0\]) + abs(a\[1\] - b\[1\]) +\
457 /// (a\[2\] - b\[2\]) + (a\[3\] - b\[3\]) + c
458 #[inline]
459 #[cfg_attr(test, assert_instr(usad8))]
460 pub unsafe fn __usada8(a: int8x4_t, b: int8x4_t, c: u32) -> u32 {
461 __usad8(a, b) + c
462 }
463
464 #[cfg(test)]
465 mod tests {
466 use crate::core_arch::simd::{i16x2, i8x4, u8x4};
467 use std::mem::transmute;
468 use stdarch_test::simd_test;
469
470 #[test]
471 fn qadd8() {
472 unsafe {
473 let a = i8x4::new(1, 2, 3, i8::MAX);
474 let b = i8x4::new(2, -1, 0, 1);
475 let c = i8x4::new(3, 1, 3, i8::MAX);
476 let r: i8x4 = dsp_call!(super::__qadd8, a, b);
477 assert_eq!(r, c);
478 }
479 }
480
481 #[test]
482 fn qsub8() {
483 unsafe {
484 let a = i8x4::new(1, 2, 3, i8::MIN);
485 let b = i8x4::new(2, -1, 0, 1);
486 let c = i8x4::new(-1, 3, 3, i8::MIN);
487 let r: i8x4 = dsp_call!(super::__qsub8, a, b);
488 assert_eq!(r, c);
489 }
490 }
491
492 #[test]
493 fn qadd16() {
494 unsafe {
495 let a = i16x2::new(1, 2);
496 let b = i16x2::new(2, -1);
497 let c = i16x2::new(3, 1);
498 let r: i16x2 = dsp_call!(super::__qadd16, a, b);
499 assert_eq!(r, c);
500 }
501 }
502
503 #[test]
504 fn qsub16() {
505 unsafe {
506 let a = i16x2::new(10, 20);
507 let b = i16x2::new(20, -10);
508 let c = i16x2::new(-10, 30);
509 let r: i16x2 = dsp_call!(super::__qsub16, a, b);
510 assert_eq!(r, c);
511 }
512 }
513
514 #[test]
515 fn qasx() {
516 unsafe {
517 let a = i16x2::new(1, i16::MAX);
518 let b = i16x2::new(2, 2);
519 let c = i16x2::new(-1, i16::MAX);
520 let r: i16x2 = dsp_call!(super::__qasx, a, b);
521 assert_eq!(r, c);
522 }
523 }
524
525 #[test]
526 fn qsax() {
527 unsafe {
528 let a = i16x2::new(1, i16::MAX);
529 let b = i16x2::new(2, 2);
530 let c = i16x2::new(3, i16::MAX - 2);
531 let r: i16x2 = dsp_call!(super::__qsax, a, b);
532 assert_eq!(r, c);
533 }
534 }
535
536 #[test]
537 fn sadd16() {
538 unsafe {
539 let a = i16x2::new(1, i16::MAX);
540 let b = i16x2::new(2, 2);
541 let c = i16x2::new(3, -i16::MAX);
542 let r: i16x2 = dsp_call!(super::__sadd16, a, b);
543 assert_eq!(r, c);
544 }
545 }
546
547 #[test]
548 fn sadd8() {
549 unsafe {
550 let a = i8x4::new(1, 2, 3, i8::MAX);
551 let b = i8x4::new(4, 3, 2, 2);
552 let c = i8x4::new(5, 5, 5, -i8::MAX);
553 let r: i8x4 = dsp_call!(super::__sadd8, a, b);
554 assert_eq!(r, c);
555 }
556 }
557
558 #[test]
559 fn sasx() {
560 unsafe {
561 let a = i16x2::new(1, 2);
562 let b = i16x2::new(2, 1);
563 let c = i16x2::new(0, 4);
564 let r: i16x2 = dsp_call!(super::__sasx, a, b);
565 assert_eq!(r, c);
566 }
567 }
568
569 #[test]
570 fn smlad() {
571 unsafe {
572 let a = i16x2::new(1, 2);
573 let b = i16x2::new(3, 4);
574 let r = super::__smlad(transmute(a), transmute(b), 10);
575 assert_eq!(r, (1 * 3) + (2 * 4) + 10);
576 }
577 }
578
579 #[test]
580 fn smlsd() {
581 unsafe {
582 let a = i16x2::new(1, 2);
583 let b = i16x2::new(3, 4);
584 let r = super::__smlsd(transmute(a), transmute(b), 10);
585 assert_eq!(r, ((1 * 3) - (2 * 4)) + 10);
586 }
587 }
588
589 #[test]
590 fn sel() {
591 unsafe {
592 let a = i8x4::new(1, 2, 3, i8::MAX);
593 let b = i8x4::new(4, 3, 2, 2);
594 // call sadd8() to set GE bits
595 super::__sadd8(transmute(a), transmute(b));
596 let c = i8x4::new(1, 2, 3, i8::MAX);
597 let r: i8x4 = dsp_call!(super::__sel, a, b);
598 assert_eq!(r, c);
599 }
600 }
601
602 #[test]
603 fn shadd8() {
604 unsafe {
605 let a = i8x4::new(1, 2, 3, 4);
606 let b = i8x4::new(5, 4, 3, 2);
607 let c = i8x4::new(3, 3, 3, 3);
608 let r: i8x4 = dsp_call!(super::__shadd8, a, b);
609 assert_eq!(r, c);
610 }
611 }
612
613 #[test]
614 fn shadd16() {
615 unsafe {
616 let a = i16x2::new(1, 2);
617 let b = i16x2::new(5, 4);
618 let c = i16x2::new(3, 3);
619 let r: i16x2 = dsp_call!(super::__shadd16, a, b);
620 assert_eq!(r, c);
621 }
622 }
623
624 #[test]
625 fn shsub8() {
626 unsafe {
627 let a = i8x4::new(1, 2, 3, 4);
628 let b = i8x4::new(5, 4, 3, 2);
629 let c = i8x4::new(-2, -1, 0, 1);
630 let r: i8x4 = dsp_call!(super::__shsub8, a, b);
631 assert_eq!(r, c);
632 }
633 }
634
635 #[test]
636 fn ssub8() {
637 unsafe {
638 let a = i8x4::new(1, 2, 3, 4);
639 let b = i8x4::new(5, 4, 3, 2);
640 let c = i8x4::new(-4, -2, 0, 2);
641 let r: i8x4 = dsp_call!(super::__ssub8, a, b);
642 assert_eq!(r, c);
643 }
644 }
645
646 #[test]
647 fn usub8() {
648 unsafe {
649 let a = u8x4::new(1, 2, 3, 4);
650 let b = u8x4::new(5, 4, 3, 2);
651 let c = u8x4::new(252, 254, 0, 2);
652 let r: u8x4 = dsp_call!(super::__usub8, a, b);
653 assert_eq!(r, c);
654 }
655 }
656
657 #[test]
658 fn shsub16() {
659 unsafe {
660 let a = i16x2::new(1, 2);
661 let b = i16x2::new(5, 4);
662 let c = i16x2::new(-2, -1);
663 let r: i16x2 = dsp_call!(super::__shsub16, a, b);
664 assert_eq!(r, c);
665 }
666 }
667
668 #[test]
669 fn smuad() {
670 unsafe {
671 let a = i16x2::new(1, 2);
672 let b = i16x2::new(5, 4);
673 let r = super::__smuad(transmute(a), transmute(b));
674 assert_eq!(r, 13);
675 }
676 }
677
678 #[test]
679 fn smuadx() {
680 unsafe {
681 let a = i16x2::new(1, 2);
682 let b = i16x2::new(5, 4);
683 let r = super::__smuadx(transmute(a), transmute(b));
684 assert_eq!(r, 14);
685 }
686 }
687
688 #[test]
689 fn smusd() {
690 unsafe {
691 let a = i16x2::new(1, 2);
692 let b = i16x2::new(5, 4);
693 let r = super::__smusd(transmute(a), transmute(b));
694 assert_eq!(r, -3);
695 }
696 }
697
698 #[test]
699 fn smusdx() {
700 unsafe {
701 let a = i16x2::new(1, 2);
702 let b = i16x2::new(5, 4);
703 let r = super::__smusdx(transmute(a), transmute(b));
704 assert_eq!(r, -6);
705 }
706 }
707
708 #[test]
709 fn usad8() {
710 unsafe {
711 let a = i8x4::new(1, 2, 3, 4);
712 let b = i8x4::new(4, 3, 2, 1);
713 let r = super::__usad8(transmute(a), transmute(b));
714 assert_eq!(r, 8);
715 }
716 }
717
718 #[test]
719 fn usad8a() {
720 unsafe {
721 let a = i8x4::new(1, 2, 3, 4);
722 let b = i8x4::new(4, 3, 2, 1);
723 let c = 10;
724 let r = super::__usada8(transmute(a), transmute(b), c);
725 assert_eq!(r, 8 + c);
726 }
727 }
728 }