15
15
16
16
use coresimd:: simd:: * ;
17
17
use coresimd:: simd_llvm:: * ;
18
+
19
+ use mem;
20
+
18
21
#[ cfg( test) ]
19
22
use stdsimd_test:: assert_instr;
20
23
@@ -355,10 +358,46 @@ impl_from_bits_!(
355
358
vector_bool_int
356
359
) ;
357
360
361
+ #[ allow( improper_ctypes) ]
362
+ extern "C" {
363
+ #[ link_name = "llvm.ppc.altivec.vperm" ]
364
+ fn vperm ( a : vector_signed_int , b : vector_signed_int , c : vector_unsigned_char ) -> vector_signed_int ;
365
+ }
366
+
358
367
mod sealed {
359
368
360
369
use super :: * ;
361
370
371
+ pub trait VectorPerm {
372
+ unsafe fn vec_vperm ( self , b : Self , c : vector_unsigned_char ) -> Self ;
373
+ }
374
+
375
+ macro_rules! vector_perm {
376
+ { $impl: ident} => {
377
+ impl VectorPerm for $impl {
378
+ #[ inline]
379
+ #[ target_feature( enable = "altivec" ) ]
380
+ unsafe fn vec_vperm( self , b: Self , c: vector_unsigned_char) -> Self {
381
+ mem:: transmute( vperm( mem:: transmute( self ) , mem:: transmute( b) , c) )
382
+ }
383
+ }
384
+ }
385
+ }
386
+
387
+ vector_perm ! { vector_signed_char }
388
+ vector_perm ! { vector_unsigned_char }
389
+ vector_perm ! { vector_bool_char }
390
+
391
+ vector_perm ! { vector_signed_short }
392
+ vector_perm ! { vector_unsigned_short }
393
+ vector_perm ! { vector_bool_short }
394
+
395
+ vector_perm ! { vector_signed_int }
396
+ vector_perm ! { vector_unsigned_int }
397
+ vector_perm ! { vector_bool_int }
398
+
399
+ vector_perm ! { vector_float }
400
+
362
401
pub trait VectorAdd < Other > {
363
402
type Result ;
364
403
unsafe fn vec_add ( self , other : Other ) -> Self :: Result ;
@@ -655,6 +694,28 @@ where
655
694
a. vec_add ( b)
656
695
}
657
696
697
+ /// Vector permute.
698
+ #[ inline]
699
+ #[ target_feature( enable = "altivec" ) ]
700
+ pub unsafe fn vec_perm < T > ( a : T , b : T , c : vector_unsigned_char ) -> T
701
+ where
702
+ T : sealed:: VectorPerm ,
703
+ {
704
+
705
+ if cfg ! ( target_endian = "little" ) {
706
+ // vperm has big-endian bias
707
+ //
708
+ // Xor the mask and flip the arguments
709
+ let d = u8x16:: new ( 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 ,
710
+ 255 , 255 , 255 , 255 , 255 , 255 , 255 , 255 ) . into_bits ( ) ;
711
+ let c = simd_xor ( c, d) ;
712
+
713
+ b. vec_vperm ( a, c)
714
+ } else {
715
+ a. vec_vperm ( b, c)
716
+ }
717
+ }
718
+
658
719
#[ cfg( test) ]
659
720
mod tests {
660
721
#[ cfg( target_arch = "powerpc" ) ]
@@ -666,6 +727,18 @@ mod tests {
666
727
use simd:: * ;
667
728
use stdsimd_test:: simd_test;
668
729
730
+ #[ simd_test( enable = "altivec" ) ]
731
+ unsafe fn vec_perm_u16x8 ( ) {
732
+ let a: vector_signed_short = u16x8:: new ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ) . into_bits ( ) ;
733
+ let b = u16x8:: new ( 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 ) . into_bits ( ) ;
734
+
735
+ let c = u8x16:: new ( 0x00 , 0x01 , 0x10 , 0x11 , 0x02 , 0x03 , 0x12 , 0x13 ,
736
+ 0x04 , 0x05 , 0x14 , 0x15 , 0x06 , 0x07 , 0x16 , 0x17 ) . into_bits ( ) ;
737
+ let d = u16x8:: new ( 0 , 10 , 1 , 11 , 2 , 12 , 3 , 13 ) ;
738
+
739
+ assert_eq ! ( d, vec_perm( a, b, c) . into_bits( ) ) ;
740
+ }
741
+
669
742
#[ simd_test( enable = "altivec" ) ]
670
743
unsafe fn vec_add_i32x4_i32x4 ( ) {
671
744
let x = i32x4:: new ( 1 , 2 , 3 , 4 ) ;
0 commit comments