1#[cfg(test)]
66use stdarch_test::assert_instr;
67
68use crate::mem::transmute;
69
70#[allow(non_camel_case_types)]
72#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
73pub type int8x4_t = i32;
74
75#[allow(non_camel_case_types)]
77#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
78pub type uint8x4_t = u32;
79
80#[allow(non_camel_case_types)]
82#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
83pub type int16x2_t = i32;
84
85#[allow(non_camel_case_types)]
87#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
88pub type uint16x2_t = u32;
89
90macro_rules! dsp_call {
91 ($name:expr, $a:expr, $b:expr) => {
92 transmute($name(transmute($a), transmute($b)))
93 };
94}
95
96extern "unadjusted" {
97 #[link_name = "llvm.arm.qadd8"]
98 fn arm_qadd8(a: i32, b: i32) -> i32;
99
100 #[link_name = "llvm.arm.qsub8"]
101 fn arm_qsub8(a: i32, b: i32) -> i32;
102
103 #[link_name = "llvm.arm.qsub16"]
104 fn arm_qsub16(a: i32, b: i32) -> i32;
105
106 #[link_name = "llvm.arm.qadd16"]
107 fn arm_qadd16(a: i32, b: i32) -> i32;
108
109 #[link_name = "llvm.arm.qasx"]
110 fn arm_qasx(a: i32, b: i32) -> i32;
111
112 #[link_name = "llvm.arm.qsax"]
113 fn arm_qsax(a: i32, b: i32) -> i32;
114
115 #[link_name = "llvm.arm.sadd16"]
116 fn arm_sadd16(a: i32, b: i32) -> i32;
117
118 #[link_name = "llvm.arm.sadd8"]
119 fn arm_sadd8(a: i32, b: i32) -> i32;
120
121 #[link_name = "llvm.arm.smlad"]
122 fn arm_smlad(a: i32, b: i32, c: i32) -> i32;
123
124 #[link_name = "llvm.arm.smlsd"]
125 fn arm_smlsd(a: i32, b: i32, c: i32) -> i32;
126
127 #[link_name = "llvm.arm.sasx"]
128 fn arm_sasx(a: i32, b: i32) -> i32;
129
130 #[link_name = "llvm.arm.sel"]
131 fn arm_sel(a: i32, b: i32) -> i32;
132
133 #[link_name = "llvm.arm.shadd8"]
134 fn arm_shadd8(a: i32, b: i32) -> i32;
135
136 #[link_name = "llvm.arm.shadd16"]
137 fn arm_shadd16(a: i32, b: i32) -> i32;
138
139 #[link_name = "llvm.arm.shsub8"]
140 fn arm_shsub8(a: i32, b: i32) -> i32;
141
142 #[link_name = "llvm.arm.ssub8"]
143 fn arm_ssub8(a: i32, b: i32) -> i32;
144
145 #[link_name = "llvm.arm.usub8"]
146 fn arm_usub8(a: i32, b: i32) -> i32;
147
148 #[link_name = "llvm.arm.shsub16"]
149 fn arm_shsub16(a: i32, b: i32) -> i32;
150
151 #[link_name = "llvm.arm.smuad"]
152 fn arm_smuad(a: i32, b: i32) -> i32;
153
154 #[link_name = "llvm.arm.smuadx"]
155 fn arm_smuadx(a: i32, b: i32) -> i32;
156
157 #[link_name = "llvm.arm.smusd"]
158 fn arm_smusd(a: i32, b: i32) -> i32;
159
160 #[link_name = "llvm.arm.smusdx"]
161 fn arm_smusdx(a: i32, b: i32) -> i32;
162
163 #[link_name = "llvm.arm.usad8"]
164 fn arm_usad8(a: i32, b: i32) -> u32;
165}
166
167#[inline]
176#[cfg_attr(test, assert_instr(qadd8))]
177#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
178pub unsafe fn __qadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
179 dsp_call!(arm_qadd8, a, b)
180}
181
182#[inline]
191#[cfg_attr(test, assert_instr(qsub8))]
192#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
193pub unsafe fn __qsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
194 dsp_call!(arm_qsub8, a, b)
195}
196
197#[inline]
204#[cfg_attr(test, assert_instr(qsub16))]
205#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
206pub unsafe fn __qsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
207 dsp_call!(arm_qsub16, a, b)
208}
209
210#[inline]
217#[cfg_attr(test, assert_instr(qadd16))]
218#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
219pub unsafe fn __qadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
220 dsp_call!(arm_qadd16, a, b)
221}
222
223#[inline]
228#[cfg_attr(test, assert_instr(qasx))]
229#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
230pub unsafe fn __qasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
231 dsp_call!(arm_qasx, a, b)
232}
233
234#[inline]
239#[cfg_attr(test, assert_instr(qsax))]
240#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
241pub unsafe fn __qsax(a: int16x2_t, b: int16x2_t) -> int16x2_t {
242 dsp_call!(arm_qsax, a, b)
243}
244
245#[inline]
252#[cfg_attr(test, assert_instr(sadd16))]
253#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
254pub unsafe fn __sadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
255 dsp_call!(arm_sadd16, a, b)
256}
257
258#[inline]
267#[cfg_attr(test, assert_instr(sadd8))]
268#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
269pub unsafe fn __sadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
270 dsp_call!(arm_sadd8, a, b)
271}
272
273#[inline]
279#[cfg_attr(test, assert_instr(smlad))]
280#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
281pub unsafe fn __smlad(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
282 arm_smlad(transmute(a), transmute(b), c)
283}
284
285#[inline]
291#[cfg_attr(test, assert_instr(smlsd))]
292#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
293pub unsafe fn __smlsd(a: int16x2_t, b: int16x2_t, c: i32) -> i32 {
294 arm_smlsd(transmute(a), transmute(b), c)
295}
296
297#[inline]
304#[cfg_attr(test, assert_instr(sasx))]
305#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
306pub unsafe fn __sasx(a: int16x2_t, b: int16x2_t) -> int16x2_t {
307 dsp_call!(arm_sasx, a, b)
308}
309
310#[inline]
321#[cfg_attr(test, assert_instr(sel))]
322#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
323pub unsafe fn __sel(a: int8x4_t, b: int8x4_t) -> int8x4_t {
324 dsp_call!(arm_sel, a, b)
325}
326
327#[inline]
336#[cfg_attr(test, assert_instr(shadd8))]
337#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
338pub unsafe fn __shadd8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
339 dsp_call!(arm_shadd8, a, b)
340}
341
342#[inline]
349#[cfg_attr(test, assert_instr(shadd16))]
350#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
351pub unsafe fn __shadd16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
352 dsp_call!(arm_shadd16, a, b)
353}
354
355#[inline]
364#[cfg_attr(test, assert_instr(shsub8))]
365#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
366pub unsafe fn __shsub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
367 dsp_call!(arm_shsub8, a, b)
368}
369
370#[inline]
382#[cfg_attr(test, assert_instr(usub8))]
383#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
384pub unsafe fn __usub8(a: uint8x4_t, b: uint8x4_t) -> uint8x4_t {
385 dsp_call!(arm_usub8, a, b)
386}
387
388#[inline]
400#[cfg_attr(test, assert_instr(ssub8))]
401#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
402pub unsafe fn __ssub8(a: int8x4_t, b: int8x4_t) -> int8x4_t {
403 dsp_call!(arm_ssub8, a, b)
404}
405
406#[inline]
413#[cfg_attr(test, assert_instr(shsub16))]
414#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
415pub unsafe fn __shsub16(a: int16x2_t, b: int16x2_t) -> int16x2_t {
416 dsp_call!(arm_shsub16, a, b)
417}
418
419#[inline]
427#[cfg_attr(test, assert_instr(smuad))]
428#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
429pub unsafe fn __smuad(a: int16x2_t, b: int16x2_t) -> i32 {
430 arm_smuad(transmute(a), transmute(b))
431}
432
433#[inline]
441#[cfg_attr(test, assert_instr(smuadx))]
442#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
443pub unsafe fn __smuadx(a: int16x2_t, b: int16x2_t) -> i32 {
444 arm_smuadx(transmute(a), transmute(b))
445}
446
447#[inline]
455#[cfg_attr(test, assert_instr(smusd))]
456#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
457pub unsafe fn __smusd(a: int16x2_t, b: int16x2_t) -> i32 {
458 arm_smusd(transmute(a), transmute(b))
459}
460
461#[inline]
469#[cfg_attr(test, assert_instr(smusdx))]
470#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
471pub unsafe fn __smusdx(a: int16x2_t, b: int16x2_t) -> i32 {
472 arm_smusdx(transmute(a), transmute(b))
473}
474
475#[inline]
482#[cfg_attr(test, assert_instr(usad8))]
483#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
484pub unsafe fn __usad8(a: int8x4_t, b: int8x4_t) -> u32 {
485 arm_usad8(transmute(a), transmute(b))
486}
487
488#[inline]
495#[cfg_attr(test, assert_instr(usad8))]
496#[unstable(feature = "stdarch_arm_dsp", issue = "117237")]
497pub unsafe fn __usada8(a: int8x4_t, b: int8x4_t, c: u32) -> u32 {
498 __usad8(a, b) + c
499}
500
501#[cfg(test)]
502mod tests {
503 use crate::core_arch::simd::{i16x2, i8x4, u8x4};
504 use std::mem::transmute;
505 use stdarch_test::simd_test;
506
507 #[test]
508 fn qadd8() {
509 unsafe {
510 let a = i8x4::new(1, 2, 3, i8::MAX);
511 let b = i8x4::new(2, -1, 0, 1);
512 let c = i8x4::new(3, 1, 3, i8::MAX);
513 let r: i8x4 = dsp_call!(super::__qadd8, a, b);
514 assert_eq!(r, c);
515 }
516 }
517
518 #[test]
519 fn qsub8() {
520 unsafe {
521 let a = i8x4::new(1, 2, 3, i8::MIN);
522 let b = i8x4::new(2, -1, 0, 1);
523 let c = i8x4::new(-1, 3, 3, i8::MIN);
524 let r: i8x4 = dsp_call!(super::__qsub8, a, b);
525 assert_eq!(r, c);
526 }
527 }
528
529 #[test]
530 fn qadd16() {
531 unsafe {
532 let a = i16x2::new(1, 2);
533 let b = i16x2::new(2, -1);
534 let c = i16x2::new(3, 1);
535 let r: i16x2 = dsp_call!(super::__qadd16, a, b);
536 assert_eq!(r, c);
537 }
538 }
539
540 #[test]
541 fn qsub16() {
542 unsafe {
543 let a = i16x2::new(10, 20);
544 let b = i16x2::new(20, -10);
545 let c = i16x2::new(-10, 30);
546 let r: i16x2 = dsp_call!(super::__qsub16, a, b);
547 assert_eq!(r, c);
548 }
549 }
550
551 #[test]
552 fn qasx() {
553 unsafe {
554 let a = i16x2::new(1, i16::MAX);
555 let b = i16x2::new(2, 2);
556 let c = i16x2::new(-1, i16::MAX);
557 let r: i16x2 = dsp_call!(super::__qasx, a, b);
558 assert_eq!(r, c);
559 }
560 }
561
562 #[test]
563 fn qsax() {
564 unsafe {
565 let a = i16x2::new(1, i16::MAX);
566 let b = i16x2::new(2, 2);
567 let c = i16x2::new(3, i16::MAX - 2);
568 let r: i16x2 = dsp_call!(super::__qsax, a, b);
569 assert_eq!(r, c);
570 }
571 }
572
573 #[test]
574 fn sadd16() {
575 unsafe {
576 let a = i16x2::new(1, i16::MAX);
577 let b = i16x2::new(2, 2);
578 let c = i16x2::new(3, -i16::MAX);
579 let r: i16x2 = dsp_call!(super::__sadd16, a, b);
580 assert_eq!(r, c);
581 }
582 }
583
584 #[test]
585 fn sadd8() {
586 unsafe {
587 let a = i8x4::new(1, 2, 3, i8::MAX);
588 let b = i8x4::new(4, 3, 2, 2);
589 let c = i8x4::new(5, 5, 5, -i8::MAX);
590 let r: i8x4 = dsp_call!(super::__sadd8, a, b);
591 assert_eq!(r, c);
592 }
593 }
594
595 #[test]
596 fn sasx() {
597 unsafe {
598 let a = i16x2::new(1, 2);
599 let b = i16x2::new(2, 1);
600 let c = i16x2::new(0, 4);
601 let r: i16x2 = dsp_call!(super::__sasx, a, b);
602 assert_eq!(r, c);
603 }
604 }
605
606 #[test]
607 fn smlad() {
608 unsafe {
609 let a = i16x2::new(1, 2);
610 let b = i16x2::new(3, 4);
611 let r = super::__smlad(transmute(a), transmute(b), 10);
612 assert_eq!(r, (1 * 3) + (2 * 4) + 10);
613 }
614 }
615
616 #[test]
617 fn smlsd() {
618 unsafe {
619 let a = i16x2::new(1, 2);
620 let b = i16x2::new(3, 4);
621 let r = super::__smlsd(transmute(a), transmute(b), 10);
622 assert_eq!(r, ((1 * 3) - (2 * 4)) + 10);
623 }
624 }
625
626 #[test]
627 fn sel() {
628 unsafe {
629 let a = i8x4::new(1, 2, 3, i8::MAX);
630 let b = i8x4::new(4, 3, 2, 2);
631 super::__sadd8(transmute(a), transmute(b));
633 let c = i8x4::new(1, 2, 3, i8::MAX);
634 let r: i8x4 = dsp_call!(super::__sel, a, b);
635 assert_eq!(r, c);
636 }
637 }
638
639 #[test]
640 fn shadd8() {
641 unsafe {
642 let a = i8x4::new(1, 2, 3, 4);
643 let b = i8x4::new(5, 4, 3, 2);
644 let c = i8x4::new(3, 3, 3, 3);
645 let r: i8x4 = dsp_call!(super::__shadd8, a, b);
646 assert_eq!(r, c);
647 }
648 }
649
650 #[test]
651 fn shadd16() {
652 unsafe {
653 let a = i16x2::new(1, 2);
654 let b = i16x2::new(5, 4);
655 let c = i16x2::new(3, 3);
656 let r: i16x2 = dsp_call!(super::__shadd16, a, b);
657 assert_eq!(r, c);
658 }
659 }
660
661 #[test]
662 fn shsub8() {
663 unsafe {
664 let a = i8x4::new(1, 2, 3, 4);
665 let b = i8x4::new(5, 4, 3, 2);
666 let c = i8x4::new(-2, -1, 0, 1);
667 let r: i8x4 = dsp_call!(super::__shsub8, a, b);
668 assert_eq!(r, c);
669 }
670 }
671
672 #[test]
673 fn ssub8() {
674 unsafe {
675 let a = i8x4::new(1, 2, 3, 4);
676 let b = i8x4::new(5, 4, 3, 2);
677 let c = i8x4::new(-4, -2, 0, 2);
678 let r: i8x4 = dsp_call!(super::__ssub8, a, b);
679 assert_eq!(r, c);
680 }
681 }
682
683 #[test]
684 fn usub8() {
685 unsafe {
686 let a = u8x4::new(1, 2, 3, 4);
687 let b = u8x4::new(5, 4, 3, 2);
688 let c = u8x4::new(252, 254, 0, 2);
689 let r: u8x4 = dsp_call!(super::__usub8, a, b);
690 assert_eq!(r, c);
691 }
692 }
693
694 #[test]
695 fn shsub16() {
696 unsafe {
697 let a = i16x2::new(1, 2);
698 let b = i16x2::new(5, 4);
699 let c = i16x2::new(-2, -1);
700 let r: i16x2 = dsp_call!(super::__shsub16, a, b);
701 assert_eq!(r, c);
702 }
703 }
704
705 #[test]
706 fn smuad() {
707 unsafe {
708 let a = i16x2::new(1, 2);
709 let b = i16x2::new(5, 4);
710 let r = super::__smuad(transmute(a), transmute(b));
711 assert_eq!(r, 13);
712 }
713 }
714
715 #[test]
716 fn smuadx() {
717 unsafe {
718 let a = i16x2::new(1, 2);
719 let b = i16x2::new(5, 4);
720 let r = super::__smuadx(transmute(a), transmute(b));
721 assert_eq!(r, 14);
722 }
723 }
724
725 #[test]
726 fn smusd() {
727 unsafe {
728 let a = i16x2::new(1, 2);
729 let b = i16x2::new(5, 4);
730 let r = super::__smusd(transmute(a), transmute(b));
731 assert_eq!(r, -3);
732 }
733 }
734
735 #[test]
736 fn smusdx() {
737 unsafe {
738 let a = i16x2::new(1, 2);
739 let b = i16x2::new(5, 4);
740 let r = super::__smusdx(transmute(a), transmute(b));
741 assert_eq!(r, -6);
742 }
743 }
744
745 #[test]
746 fn usad8() {
747 unsafe {
748 let a = i8x4::new(1, 2, 3, 4);
749 let b = i8x4::new(4, 3, 2, 1);
750 let r = super::__usad8(transmute(a), transmute(b));
751 assert_eq!(r, 8);
752 }
753 }
754
755 #[test]
756 fn usad8a() {
757 unsafe {
758 let a = i8x4::new(1, 2, 3, 4);
759 let b = i8x4::new(4, 3, 2, 1);
760 let c = 10;
761 let r = super::__usada8(transmute(a), transmute(b), c);
762 assert_eq!(r, 8 + c);
763 }
764 }
765}