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}