66#![ allow( non_camel_case_types) ]
77
88/// A single unconstrained byte (0-255).
9- #[ derive( Copy , Clone , Debug ) ]
10- pub struct ImmByte ( u8 ) ;
11- impl ImmByte {
12- /// Constructor
13- #[ inline]
14- #[ rustc_args_required_const( 0 ) ]
15- pub const fn new ( value : u8 ) -> Self {
16- ImmByte ( value)
17- }
18- }
19-
20- macro_rules! impl_laneidx {
21- ( $id: ident( $ty: ty) : [ $_from: expr, $_to: expr] | $( #[ $doc: meta] ) * ) => {
22- #[ derive( Copy , Clone , Debug ) ]
23- pub struct $id( $ty) ;
24- impl $id {
25- #[ inline]
26- #[ rustc_args_required_const( 0 ) ]
27- pub const fn new( x: $ty) -> Self {
28- // FIXME: not allowed in const fn:
29- // * if statements
30- // * unreachable_unchecked / panic / abort
31- //
32- // if x < $from || x > $to {
33- // unsafe { ::_core::hint::unreachable_unchecked() };
34- // debug_assert!(...)
35- // }
36- $id( x)
37- }
38- }
39- } ;
40- }
41- impl_laneidx ! ( LaneIdx2 ( u8 ) : [ 0 , 1 ] | /// A byte with values in the range 0–1 identifying a lane.
42- ) ;
43- impl_laneidx ! ( LaneIdx4 ( u8 ) : [ 0 , 3 ] | /// A byte with values in the range 0–3 identifying a lane.
44- ) ;
45- impl_laneidx ! ( LaneIdx8 ( u8 ) : [ 0 , 7 ] | /// A byte with values in the range 0–7 identifying a lane.
46- ) ;
47- impl_laneidx ! ( LaneIdx16 ( u8 ) : [ 0 , 15 ] | /// A byte with values in the range 0–15 identifying a lane.
48- ) ;
49- impl_laneidx ! ( LaneIdx32 ( u8 ) : [ 0 , 31 ] | /// A byte with values in the range 0–31 identifying a lane.
50- ) ;
9+ pub type ImmByte = u8 ;
10+ /// A byte with values in the range 0–1 identifying a lane.
11+ pub type LaneIdx2 = u8 ;
12+ /// A byte with values in the range 0–3 identifying a lane.
13+ pub type LaneIdx4 = u8 ;
14+ /// A byte with values in the range 0–7 identifying a lane.
15+ pub type LaneIdx8 = u8 ;
16+ /// A byte with values in the range 0–15 identifying a lane.
17+ pub type LaneIdx16 = u8 ;
18+ /// A byte with values in the range 0–31 identifying a lane.
19+ pub type LaneIdx32 = u8 ;
5120
5221types ! {
5322 /// WASM-specific 128-bit wide SIMD vector type
@@ -102,6 +71,9 @@ mod sealed {
10271 fn sqrt_v4f32 ( x : f32x4 ) -> f32x4 ;
10372 #[ link_name = "llvm.sqrt.v2f64" ]
10473 fn sqrt_v2f64 ( x : f64x2 ) -> f64x2 ;
74+ #[ link_name = "shufflevector" ]
75+ pub fn shufflevector_v16i8 ( x : v8x16 , y : v8x16 , i : v8x16 ) -> v8x16 ;
76+
10577 }
10678 impl f32x4 {
10779 #[ inline( always) ]
@@ -214,7 +186,7 @@ macro_rules! impl_extract_lane {
214186 a: v128
215187 }
216188 // the vectors store a signed integer => extract into it
217- let v: $selem_ty = simd_extract( U { a } . vec, imm. 0 as u32 /* zero-extends index */ ) ;
189+ let v: $selem_ty = simd_extract( U { a } . vec, imm as u32 /* zero-extends index */ ) ;
218190 v as $x_ty
219191 }
220192
@@ -233,7 +205,7 @@ macro_rules! impl_extract_lane {
233205 a: v128
234206 }
235207 // the vectors store a signed integer => extract into it
236- let v: $selem_ty = simd_extract( U { a } . vec, imm. 0 as u32 /* zero-extends index */ ) ;
208+ let v: $selem_ty = simd_extract( U { a } . vec, imm as u32 /* zero-extends index */ ) ;
237209 // re-interpret the signed integer as an unsigned one of the same size (no-op)
238210 let v: $uelem_ty= :: mem:: transmute( v) ;
239211 // cast the internal unsigned integer to a larger signed integer (zero-extends)
@@ -258,7 +230,7 @@ macro_rules! impl_extract_lane {
258230 a: v128
259231 }
260232 // the vectors store a signed integer => extract into it
261- simd_extract( U { a } . vec, imm. 0 as u32 /* zero-extends index */ )
233+ simd_extract( U { a } . vec, imm as u32 /* zero-extends index */ )
262234 }
263235 }
264236 } ;
@@ -291,7 +263,7 @@ macro_rules! impl_replace_lane {
291263 // the vectors store a signed integer => extract into it
292264 :: mem:: transmute(
293265 simd_insert( U { a } . vec,
294- imm. 0 as u32 /* zero-extends index */ ,
266+ imm as u32 /* zero-extends index */ ,
295267 x as $ielem_ty)
296268 )
297269 }
@@ -306,23 +278,44 @@ impl_replace_lane!(i64x2[v64x2:i64](LaneIdx2) <= i64);
306278impl_replace_lane ! ( f32x4[ f32x4: f32 ] ( LaneIdx4 ) <= f32 ) ;
307279impl_replace_lane ! ( f64x2[ f64x2: f64 ] ( LaneIdx2 ) <= f64 ) ;
308280
309- impl v8x16 {
310- /// Shuffle lanes
311- ///
312- /// Create vector with lanes selected from the lanes of two input vectors
313- /// `a` and `b` by the indices specified in the immediate mode operand
314- /// `imm`. Each index selects an element of the result vector, where the
315- /// indices `i` in range `[0, 15]` select the `i`-th elements of `a`, and
316- /// the indices in range `[16, 31]` select the `i - 16`-th element of `b`.
317- #[ inline]
318- // #[target_feature(enable = "simd128")]
319- // FIXME: #[cfg_attr(test, assert_instr(v8x16.shuffle))]
320- #[ rustc_args_required_const( 2 ) ]
321- pub unsafe fn shuffle ( a : v128 , b : v128 , imm : [ LaneIdx32 ; 16 ] ) -> v128 {
322- // FIXME: LLVM does not support v8x16.shuffle (use inline assembly?)
323- let result: v128 ;
324- asm ! ( "v8x16.shuffle $0, $1, $2" : "=r" ( result) : "r" ( a) , "r" ( b) , "r" ( imm) : : ) ;
325- result
281+ pub use :: coresimd:: simd_llvm:: simd_shuffle16 as __internal_v8x16_shuffle;
282+ pub use self :: sealed:: v8x16 as __internal_v8x16;
283+
284+ /// Shuffle lanes
285+ ///
286+ /// Create vector with lanes selected from the lanes of two input vectors
287+ /// `a` and `b` by the indices specified in the immediate mode operand
288+ /// `imm`. Each index selects an element of the result vector, where the
289+ /// indices `i` in range `[0, 15]` select the `i`-th elements of `a`, and
290+ /// the indices in range `[16, 31]` select the `i - 16`-th element of `b`.
291+ #[ macro_export]
292+ macro_rules! v8x16_shuffle {
293+ ( $a: expr, $b: expr, [
294+ $imm0: expr, $imm1: expr, $imm2: expr, $imm3: expr,
295+ $imm4: expr, $imm5: expr, $imm6: expr, $imm7: expr,
296+ $imm8: expr, $imm9: expr, $imm10: expr, $imm11: expr,
297+ $imm12: expr, $imm13: expr, $imm14: expr, $imm15: expr
298+ ] ) => {
299+ #[ allow( unused_unsafe) ]
300+ unsafe {
301+ let a: $crate:: arch:: wasm32:: v128 = $a;
302+ let b: $crate:: arch:: wasm32:: v128 = $b;
303+ union U {
304+ e: v128,
305+ i: $crate:: arch:: wasm32:: __internal_v8x16,
306+ }
307+ let a = U { e: a } . i;
308+ let b = U { e: b } . i;
309+
310+ let r: $crate:: arch:: wasm32:: __internal_v8x16 =
311+ $crate:: arch:: wasm32:: __internal_v8x16_shuffle( a, b, [
312+ $imm0 as u32 , $imm1, $imm2, $imm3,
313+ $imm4, $imm5, $imm6, $imm7,
314+ $imm8, $imm9, $imm10, $imm11,
315+ $imm12, $imm13, $imm14, $imm15
316+ ] ) ;
317+ U { i: r } . e
318+ }
326319 }
327320}
328321
@@ -557,6 +550,9 @@ impl_boolean_reduction!(i64x2[v64x2]);
557550
558551macro_rules! impl_comparisons {
559552 ( $id: ident[ $ivec_ty: ident] ) => {
553+ impl_comparisons!( $id[ $ivec_ty=>$ivec_ty] ) ;
554+ } ;
555+ ( $id: ident[ $ivec_ty: ident=>$rvec_ty: ident] ) => {
560556 impl $id {
561557 /// Equality
562558 #[ inline]
@@ -566,7 +562,7 @@ macro_rules! impl_comparisons {
566562 use coresimd:: simd_llvm:: simd_eq;
567563 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
568564 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
569- let c: sealed:: $ivec_ty = simd_eq( a, b) ;
565+ let c: sealed:: $rvec_ty = simd_eq( a, b) ;
570566 :: mem:: transmute( c)
571567 }
572568 /// Non-Equality
@@ -577,7 +573,7 @@ macro_rules! impl_comparisons {
577573 use coresimd:: simd_llvm:: simd_ne;
578574 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
579575 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
580- let c: sealed:: $ivec_ty = simd_ne( a, b) ;
576+ let c: sealed:: $rvec_ty = simd_ne( a, b) ;
581577 :: mem:: transmute( c)
582578 }
583579 /// Less-than
@@ -588,7 +584,7 @@ macro_rules! impl_comparisons {
588584 use coresimd:: simd_llvm:: simd_lt;
589585 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
590586 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
591- let c: sealed:: $ivec_ty = simd_lt( a, b) ;
587+ let c: sealed:: $rvec_ty = simd_lt( a, b) ;
592588 :: mem:: transmute( c)
593589 }
594590
@@ -600,7 +596,7 @@ macro_rules! impl_comparisons {
600596 use coresimd:: simd_llvm:: simd_le;
601597 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
602598 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
603- let c: sealed:: $ivec_ty = simd_le( a, b) ;
599+ let c: sealed:: $rvec_ty = simd_le( a, b) ;
604600 :: mem:: transmute( c)
605601 }
606602
@@ -612,7 +608,7 @@ macro_rules! impl_comparisons {
612608 use coresimd:: simd_llvm:: simd_gt;
613609 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
614610 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
615- let c: sealed:: $ivec_ty = simd_gt( a, b) ;
611+ let c: sealed:: $rvec_ty = simd_gt( a, b) ;
616612 :: mem:: transmute( c)
617613 }
618614
@@ -624,7 +620,7 @@ macro_rules! impl_comparisons {
624620 use coresimd:: simd_llvm:: simd_ge;
625621 let a: sealed:: $ivec_ty = :: mem:: transmute( a) ;
626622 let b: sealed:: $ivec_ty = :: mem:: transmute( b) ;
627- let c: sealed:: $ivec_ty = simd_ge( a, b) ;
623+ let c: sealed:: $rvec_ty = simd_ge( a, b) ;
628624 :: mem:: transmute( c)
629625 }
630626 }
@@ -635,8 +631,8 @@ impl_comparisons!(i8x16[v8x16]);
635631impl_comparisons ! ( i16x8[ v16x8] ) ;
636632impl_comparisons ! ( i32x4[ v32x4] ) ;
637633impl_comparisons ! ( i64x2[ v64x2] ) ;
638- impl_comparisons ! ( f32x4[ f32x4] ) ;
639- impl_comparisons ! ( f64x2[ f64x2] ) ;
634+ impl_comparisons ! ( f32x4[ f32x4=>v32x4 ] ) ;
635+ impl_comparisons ! ( f64x2[ f64x2=>v64x2 ] ) ;
640636
641637// Load and store
642638impl v128 {
@@ -696,10 +692,7 @@ macro_rules! impl_floating_point_ops {
696692 // #[target_feature(enable = "simd128")]
697693 // FIXME: #[cfg_attr(test, assert_instr($id.min))]
698694 pub unsafe fn min( a: v128, b: v128) -> v128 {
699- use coresimd:: simd_llvm:: simd_fmin;
700- let a: sealed:: $id = :: mem:: transmute( a) ;
701- let b: sealed:: $id = :: mem:: transmute( b) ;
702- :: mem:: transmute( simd_fmin( a, b) )
695+ v128:: bitselect( a, b, $id:: lt( a, b) )
703696 }
704697
705698 /// NaN-propagating maximum
@@ -709,10 +702,7 @@ macro_rules! impl_floating_point_ops {
709702 // #[target_feature(enable = "simd128")]
710703 // FIXME: #[cfg_attr(test, assert_instr($id.max))]
711704 pub unsafe fn max( a: v128, b: v128) -> v128 {
712- use coresimd:: simd_llvm:: simd_fmax;
713- let a: sealed:: $id = :: mem:: transmute( a) ;
714- let b: sealed:: $id = :: mem:: transmute( b) ;
715- :: mem:: transmute( simd_fmax( a, b) )
705+ v128:: bitselect( a, b, $id:: gt( a, b) )
716706 }
717707
718708 /// Square-root
@@ -794,7 +784,7 @@ macro_rules! impl_conversion {
794784
795785// Integer to floating point
796786impl_conversion ! ( convert_s_i32x4[ "f32x4.convert_s/i32x4" ] : v32x4 => f32x4 | f32x4) ;
797- impl_conversion ! ( convert_u_i32x4[ "f32x4.convert_u/i32x4" ] : v32x4 => f32x4 | f32x4) ;
787+ impl_conversion ! ( convert_u_i32x4[ "f32x4.convert_u/i32x4" ] : u32x4 => f32x4 | f32x4) ;
798788impl_conversion ! ( convert_s_i64x2[ "f64x2.convert_s/i64x2" ] : v64x2 => f64x2 | f64x2) ;
799789impl_conversion ! ( convert_u_i64x2[ "f64x2.convert_u/i64x2" ] : v64x2 => f64x2 | f64x2) ;
800790
0 commit comments