@@ -48,6 +48,8 @@ impl<const N: usize> Simd<u8, N> {
4848 target_endian = "little"
4949 ) ) ]
5050 16 => transize ( armv7_neon_swizzle_u8x16, self , idxs) ,
51+ #[ cfg( all( target_arch = "loongarch64" , target_feature = "lsx" ) ) ]
52+ 16 => transize ( loong64_lsx_swizzle, self , idxs) ,
5153 #[ cfg( all( target_feature = "avx2" , not( target_feature = "avx512vbmi" ) ) ) ]
5254 32 => transize ( avx2_pshufb, self , idxs) ,
5355 #[ cfg( all( target_feature = "avx512vl" , target_feature = "avx512vbmi" ) ) ]
@@ -62,6 +64,8 @@ impl<const N: usize> Simd<u8, N> {
6264 } ;
6365 transize ( swizzler, self , idxs)
6466 }
67+ #[ cfg( all( target_arch = "loongarch64" , target_feature = "lasx" ) ) ]
68+ 32 => transize ( loong64_lasx_swizzle, self , idxs) ,
6569 // Notable absence: avx512bw pshufb shuffle
6670 #[ cfg( all( target_feature = "avx512vl" , target_feature = "avx512vbmi" ) ) ]
6771 64 => {
@@ -220,6 +224,38 @@ unsafe fn avx2_pshufb(bytes: Simd<u8, 32>, idxs: Simd<u8, 32>) -> Simd<u8, 32> {
220224 }
221225}
222226
227+ /// LoongArch64 LSX supports swizzling `u8x16`
228+ ///
229+ /// # Safety
230+ /// This requires LoongArch LSX to work
231+ #[ cfg( all( target_arch = "loongarch64" , target_feature = "lsx" ) ) ]
232+ unsafe fn loong64_lsx_swizzle ( bytes : Simd < u8 , 16 > , idxs : Simd < u8 , 16 > ) -> Simd < u8 , 16 > {
233+ use core:: arch:: loongarch64:: { lsx_vand_v, lsx_vshuf_b, lsx_vslei_bu} ;
234+ // SAFETY: Caller promised loongarch lsx support
235+ unsafe {
236+ let bytes = lsx_vshuf_b ( bytes. into ( ) , bytes. into ( ) , idxs. into ( ) ) ;
237+ let mask = lsx_vslei_bu :: < 15 > ( idxs. into ( ) ) ;
238+ lsx_vand_v ( bytes, mask) . into ( )
239+ }
240+ }
241+
242+ /// LoongArch64 LASX supports swizzling `u8x32`
243+ ///
244+ /// # Safety
245+ /// This requires LoongArch LASX to work
246+ #[ cfg( all( target_arch = "loongarch64" , target_feature = "lasx" ) ) ]
247+ unsafe fn loong64_lasx_swizzle ( bytes : Simd < u8 , 32 > , idxs : Simd < u8 , 32 > ) -> Simd < u8 , 32 > {
248+ use core:: arch:: loongarch64:: { lasx_xvand_v, lasx_xvpermi_q, lasx_xvshuf_b, lasx_xvslei_bu} ;
249+ // SAFETY: Caller promised loongarch lasx support
250+ unsafe {
251+ let lolo = lasx_xvpermi_q :: < 0x00 > ( bytes. into ( ) , bytes. into ( ) ) ;
252+ let hihi = lasx_xvpermi_q :: < 0x11 > ( bytes. into ( ) , bytes. into ( ) ) ;
253+ let bytes = lasx_xvshuf_b ( hihi, lolo, idxs. into ( ) ) ;
254+ let mask = lasx_xvslei_bu :: < 31 > ( idxs. into ( ) ) ;
255+ lasx_xvand_v ( bytes, mask) . into ( )
256+ }
257+ }
258+
223259/// This sets up a call to an architecture-specific function, and in doing so
224260/// it persuades rustc that everything is the correct size. Which it is.
225261/// This would not be needed if one could convince Rust that, by matching on N,
0 commit comments