diff --git a/crates/core_arch/src/s390x/macros.rs b/crates/core_arch/src/s390x/macros.rs index 6f94d6828e..92faf387bd 100644 --- a/crates/core_arch/src/s390x/macros.rs +++ b/crates/core_arch/src/s390x/macros.rs @@ -2,6 +2,14 @@ #![allow(unused_imports)] // FIXME remove when more tests are added macro_rules! test_impl { + ($fun:ident +($($v:ident : $ty:ty),*) -> $r:ty [$call:ident, $instr:ident]) => { + #[inline] + #[target_feature(enable = "vector")] + #[cfg_attr(test, assert_instr($instr))] + pub unsafe fn $fun ($($v : $ty),*) -> $r { + transmute($call ($($v),*)) + } + }; ($fun:ident ($($v:ident : $ty:ty),*) -> $r:ty [$call:ident, $instr:ident]) => { #[inline] #[target_feature(enable = "vector")] @@ -96,20 +104,22 @@ macro_rules! impl_vec_trait { impl_vec_trait!{ [$Trait $m] $sg (vector_signed_long_long, ~vector_bool_long_long) -> vector_signed_long_long } }; ([$Trait:ident $m:ident] ~($fn:ident)) => { - impl_vec_trait!{ [$Trait $m] ~($fn, $fn, $fn, $fn, $fn, $fn) } + impl_vec_trait!{ [$Trait $m] ~($fn, $fn, $fn, $fn, $fn, $fn, $fn, $fn) } }; - ([$Trait:ident $m:ident] 2 ($ub:ident, $sb:ident, $uh:ident, $sh:ident, $uw:ident, $sw:ident)) => { + ([$Trait:ident $m:ident] 2 ($ub:ident, $sb:ident, $uh:ident, $sh:ident, $uw:ident, $sw:ident, $ug:ident, $sg:ident)) => { impl_vec_trait!{ [$Trait $m] $ub (vector_unsigned_char, vector_unsigned_char) -> vector_unsigned_char } impl_vec_trait!{ [$Trait $m] $sb (vector_signed_char, vector_signed_char) -> vector_signed_char } impl_vec_trait!{ [$Trait $m] $uh (vector_unsigned_short, vector_unsigned_short) -> vector_unsigned_short } impl_vec_trait!{ [$Trait $m] $sh (vector_signed_short, vector_signed_short) -> vector_signed_short } impl_vec_trait!{ [$Trait $m] $uw (vector_unsigned_int, vector_unsigned_int) -> vector_unsigned_int } impl_vec_trait!{ [$Trait $m] $sw (vector_signed_int, vector_signed_int) -> vector_signed_int } + impl_vec_trait!{ [$Trait $m] $ug (vector_unsigned_long_long, vector_unsigned_long_long) -> vector_unsigned_long_long } + impl_vec_trait!{ [$Trait $m] $sg (vector_signed_long_long, vector_signed_long_long) -> vector_signed_long_long } }; ([$Trait:ident $m:ident] 2 ($fn:ident)) => { - impl_vec_trait!{ [$Trait $m] ($fn, $fn, $fn, $fn, $fn, $fn) } + impl_vec_trait!{ [$Trait $m] ($fn, $fn, $fn, $fn, $fn, $fn, $fn, $fn) } }; - ([$Trait:ident $m:ident]+ 2b ($b:ident, $h:ident, $w:ident)) => { + ([$Trait:ident $m:ident]+ 2b ($b:ident, $h:ident, $w:ident, $g:ident)) => { impl_vec_trait!{ [$Trait $m]+ $b (vector_bool_char, vector_bool_char) -> vector_bool_char } impl_vec_trait!{ [$Trait $m]+ $b (vector_unsigned_char, vector_unsigned_char) -> vector_unsigned_char } impl_vec_trait!{ [$Trait $m]+ $b (vector_signed_char, vector_signed_char) -> vector_signed_char } @@ -119,9 +129,29 @@ macro_rules! impl_vec_trait { impl_vec_trait!{ [$Trait $m]+ $w (vector_bool_int, vector_bool_int) -> vector_bool_int } impl_vec_trait!{ [$Trait $m]+ $w (vector_unsigned_int, vector_unsigned_int) -> vector_unsigned_int } impl_vec_trait!{ [$Trait $m]+ $w (vector_signed_int, vector_signed_int) -> vector_signed_int } + impl_vec_trait!{ [$Trait $m]+ $g (vector_unsigned_long_long, vector_unsigned_long_long) -> vector_unsigned_long_long } + impl_vec_trait!{ [$Trait $m]+ $g (vector_signed_long_long, vector_signed_long_long) -> vector_signed_long_long } }; ([$Trait:ident $m:ident]+ 2b ($fn:ident)) => { - impl_vec_trait!{ [$Trait $m]+ 2b ($fn, $fn, $fn) } + impl_vec_trait!{ [$Trait $m]+ 2b ($fn, $fn, $fn, $fn) } + }; + ([$Trait:ident $m:ident]+ 2c ($b:ident, $h:ident, $w:ident, $g:ident, $s:ident, $d:ident)) => { + impl_vec_trait!{ [$Trait $m]+ $b (vector_bool_char, vector_bool_char) -> vector_bool_char } + impl_vec_trait!{ [$Trait $m]+ $b (vector_unsigned_char, vector_unsigned_char) -> vector_unsigned_char } + impl_vec_trait!{ [$Trait $m]+ $b (vector_signed_char, vector_signed_char) -> vector_signed_char } + impl_vec_trait!{ [$Trait $m]+ $h (vector_bool_short, vector_bool_short) -> vector_bool_short } + impl_vec_trait!{ [$Trait $m]+ $h (vector_unsigned_short, vector_unsigned_short) -> vector_unsigned_short } + impl_vec_trait!{ [$Trait $m]+ $h (vector_signed_short, vector_signed_short) -> vector_signed_short } + impl_vec_trait!{ [$Trait $m]+ $w (vector_bool_int, vector_bool_int) -> vector_bool_int } + impl_vec_trait!{ [$Trait $m]+ $w (vector_unsigned_int, vector_unsigned_int) -> vector_unsigned_int } + impl_vec_trait!{ [$Trait $m]+ $w (vector_signed_int, vector_signed_int) -> vector_signed_int } + impl_vec_trait!{ [$Trait $m]+ $g (vector_unsigned_long_long, vector_unsigned_long_long) -> vector_unsigned_long_long } + impl_vec_trait!{ [$Trait $m]+ $g (vector_signed_long_long, vector_signed_long_long) -> vector_signed_long_long } + impl_vec_trait!{ [$Trait $m]+ $s (vector_float, vector_float) -> vector_float } + impl_vec_trait!{ [$Trait $m]+ $d (vector_double, vector_double) -> vector_double } + }; + ([$Trait:ident $m:ident]+ 2c ($fn:ident)) => { + impl_vec_trait!{ [$Trait $m]+ 2c ($fn, $fn, $fn, $fn, $fn, $fn) } }; } diff --git a/crates/core_arch/src/s390x/vector.rs b/crates/core_arch/src/s390x/vector.rs index 56996cef5c..7dfdb7a8dd 100644 --- a/crates/core_arch/src/s390x/vector.rs +++ b/crates/core_arch/src/s390x/vector.rs @@ -450,6 +450,185 @@ mod sealed { (u64, u64x2, vector_bool_long_long), (i64, i64x2, vector_bool_long_long) } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait CountBits { + type Result; + + unsafe fn vec_cntlz(self) -> Self::Result; + unsafe fn vec_cnttz(self) -> Self::Result; + unsafe fn vec_popcnt(self) -> Self::Result; + } + + macro_rules! impl_count_bits { + ($ty:tt) => { + #[unstable(feature = "stdarch_s390x", issue = "135681")] + impl CountBits for $ty { + type Result = t_u!($ty); + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_cntlz(self) -> Self::Result { + transmute(simd_ctlz(self)) + } + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_cnttz(self) -> Self::Result { + transmute(simd_cttz(self)) + } + + #[inline] + #[target_feature(enable = "vector")] + unsafe fn vec_popcnt(self) -> Self::Result { + transmute(simd_ctpop(self)) + } + } + }; + } + + impl_count_bits!(vector_signed_char); + impl_count_bits!(vector_unsigned_char); + impl_count_bits!(vector_signed_short); + impl_count_bits!(vector_unsigned_short); + impl_count_bits!(vector_signed_int); + impl_count_bits!(vector_unsigned_int); + impl_count_bits!(vector_signed_long_long); + impl_count_bits!(vector_unsigned_long_long); + + test_impl! { vec_clzb_signed +(a: vector_signed_char) -> vector_unsigned_char [simd_ctlz, vclzb] } + test_impl! { vec_clzh_signed +(a: vector_signed_short) -> vector_unsigned_short [simd_ctlz, vclzh] } + test_impl! { vec_clzf_signed +(a: vector_signed_int) -> vector_unsigned_int [simd_ctlz, vclzf] } + test_impl! { vec_clzg_signed +(a: vector_signed_long_long) -> vector_unsigned_long_long [simd_ctlz, vclzg] } + + test_impl! { vec_clzb_unsigned +(a: vector_unsigned_char) -> vector_unsigned_char [simd_ctlz, vclzb] } + test_impl! { vec_clzh_unsigned +(a: vector_unsigned_short) -> vector_unsigned_short [simd_ctlz, vclzh] } + test_impl! { vec_clzf_unsigned +(a: vector_unsigned_int) -> vector_unsigned_int [simd_ctlz, vclzf] } + test_impl! { vec_clzg_unsigned +(a: vector_unsigned_long_long) -> vector_unsigned_long_long [simd_ctlz, vclzg] } + + test_impl! { vec_ctzb_signed +(a: vector_signed_char) -> vector_unsigned_char [simd_cttz, vctzb] } + test_impl! { vec_ctzh_signed +(a: vector_signed_short) -> vector_unsigned_short [simd_cttz, vctzh] } + test_impl! { vec_ctzf_signed +(a: vector_signed_int) -> vector_unsigned_int [simd_cttz, vctzf] } + test_impl! { vec_ctzg_signed +(a: vector_signed_long_long) -> vector_unsigned_long_long [simd_cttz, vctzg] } + + test_impl! { vec_ctzb_unsigned +(a: vector_unsigned_char) -> vector_unsigned_char [simd_cttz, vctzb] } + test_impl! { vec_ctzh_unsigned +(a: vector_unsigned_short) -> vector_unsigned_short [simd_cttz, vctzh] } + test_impl! { vec_ctzf_unsigned +(a: vector_unsigned_int) -> vector_unsigned_int [simd_cttz, vctzf] } + test_impl! { vec_ctzg_unsigned +(a: vector_unsigned_long_long) -> vector_unsigned_long_long [simd_cttz, vctzg] } + + // FIXME(vector-enhancements-1) other integer types are emulated, but get their own + // instructions in later facilities. Add tests when possible. + test_impl! { vec_popcnt_signed +(a: vector_signed_char) -> vector_signed_char [simd_ctpop, vpopctb] } + test_impl! { vec_popcnt_unsigned +(a: vector_unsigned_char) -> vector_unsigned_char [simd_ctpop, vpopctb] } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorAnd { + type Result; + unsafe fn vec_and(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorAnd vec_and] ~(simd_and) } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorOr { + type Result; + unsafe fn vec_or(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorOr vec_or] ~(simd_or) } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorXor { + type Result; + unsafe fn vec_xor(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorXor vec_xor] ~(simd_xor) } + + #[inline] + #[target_feature(enable = "vector")] + // FIXME(vector-enhancements-1) #[cfg_attr(test, assert_instr(vno))] + unsafe fn nor(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char { + let a: u8x16 = transmute(a); + let b: u8x16 = transmute(b); + transmute(simd_xor(simd_or(a, b), u8x16::splat(0xff))) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorNor { + type Result; + unsafe fn vec_nor(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorNor vec_nor]+ 2c (nor) } + + #[inline] + #[target_feature(enable = "vector")] + // FIXME(vector-enhancements-1) #[cfg_attr(test, assert_instr(vnn))] + unsafe fn nand(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char { + let a: u8x16 = transmute(a); + let b: u8x16 = transmute(b); + transmute(simd_xor(simd_and(a, b), u8x16::splat(0xff))) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorNand { + type Result; + unsafe fn vec_nand(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorNand vec_nand]+ 2c (nand) } + + #[inline] + #[target_feature(enable = "vector")] + // FIXME(vector-enhancements-1) #[cfg_attr(test, assert_instr(vnx))] + unsafe fn eqv(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char { + let a: u8x16 = transmute(a); + let b: u8x16 = transmute(b); + transmute(simd_xor(simd_xor(a, b), u8x16::splat(0xff))) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorEqv { + type Result; + unsafe fn vec_eqv(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorEqv vec_eqv]+ 2c (eqv) } + + #[inline] + #[target_feature(enable = "vector")] + // FIXME(vector-enhancements-1) #[cfg_attr(test, assert_instr(vnc))] + unsafe fn andc(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char { + let a = transmute(a); + let b = transmute(b); + transmute(simd_and(simd_xor(u8x16::splat(0xff), b), a)) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorAndc { + type Result; + unsafe fn vec_andc(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorAndc vec_andc]+ 2c (andc) } + + #[inline] + #[target_feature(enable = "vector")] + // FIXME(vector-enhancements-1) #[cfg_attr(test, assert_instr(voc))] + unsafe fn orc(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char { + let a = transmute(a); + let b = transmute(b); + transmute(simd_or(simd_xor(u8x16::splat(0xff), b), a)) + } + + #[unstable(feature = "stdarch_s390x", issue = "135681")] + pub trait VectorOrc { + type Result; + unsafe fn vec_orc(self, b: Other) -> Self::Result; + } + + impl_vec_trait! { [VectorOrc vec_orc]+ 2c (orc) } } /// Vector element-wise addition. @@ -491,6 +670,41 @@ where a.vec_mul(b) } +/// Vector Count Leading Zeros +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_cntlz(a: T) -> ::Result +where + T: sealed::CountBits, +{ + a.vec_cntlz() +} + +/// Vector Count Trailing Zeros +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_cnttz(a: T) -> ::Result +where + T: sealed::CountBits, +{ + a.vec_cnttz() +} + +/// Vector Population Count +/// +/// Computes the population count (number of set bits) in each element of the input. +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_popcnt(a: T) -> ::Result +where + T: sealed::CountBits, +{ + a.vec_popcnt() +} + /// Vector element-wise maximum. #[inline] #[target_feature(enable = "vector")] @@ -535,6 +749,100 @@ where a.vec_splats() } +/// Vector and +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_and(a: T, b: U) -> >::Result +where + T: sealed::VectorAnd, +{ + a.vec_and(b) +} + +/// Vector or +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_or(a: T, b: U) -> >::Result +where + T: sealed::VectorOr, +{ + a.vec_or(b) +} + +/// Vector xor +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_xor(a: T, b: U) -> >::Result +where + T: sealed::VectorXor, +{ + a.vec_xor(b) +} + +/// Vector nor +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_nor(a: T, b: U) -> >::Result +where + T: sealed::VectorNor, +{ + a.vec_nor(b) +} + +/// Vector nand +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_nand(a: T, b: U) -> >::Result +where + T: sealed::VectorNand, +{ + a.vec_nand(b) +} + +/// Vector xnor +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_eqv(a: T, b: U) -> >::Result +where + T: sealed::VectorEqv, +{ + a.vec_eqv(b) +} + +/// Vector andc. +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_andc(a: T, b: U) -> >::Result +where + T: sealed::VectorAndc, +{ + a.vec_andc(b) +} + +/// Vector OR with Complement +/// +/// ## Purpose +/// Performs a bitwise OR of the first vector with the bitwise-complemented second vector. +/// +/// ## Result value +/// r is the bitwise OR of a and the bitwise complement of b. +#[inline] +#[target_feature(enable = "vector")] +#[unstable(feature = "stdarch_s390x", issue = "135681")] +pub unsafe fn vec_orc(a: T, b: U) -> >::Result +where + T: sealed::VectorOrc, +{ + a.vec_orc(b) +} + #[cfg(test)] mod tests { use super::*; @@ -711,4 +1019,44 @@ mod tests { test_vec_abs! { test_vec_abs_i64, i64x2, -42i64, 42i64 } test_vec_abs! { test_vec_abs_f32, f32x4, -42f32, 42f32 } test_vec_abs! { test_vec_abs_f64, f64x2, -42f64, 42f64 } + + test_vec_2! { test_vec_andc, vec_andc, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b10000000], + [0b11001100, 0b00001100, 0b11000000, 0b01001100] } + + test_vec_2! { test_vec_and, vec_and, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [0b00000000, 0b11000000, 0b00001100, 0b00000000] } + + test_vec_2! { test_vec_nand, vec_nand, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [!0b00000000, !0b11000000, !0b00001100, !0b00000000] } + + test_vec_2! { test_vec_orc, vec_orc, u32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [0b11001100 | !0b00110011, 0b11001100 | !0b11110011, 0b11001100 | !0b00001100, 0b11001100 | !0b00000000] } + + test_vec_2! { test_vec_or, vec_or, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [0b11111111, 0b11111111, 0b11001100, 0b11001100] } + + test_vec_2! { test_vec_nor, vec_nor, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [!0b11111111, !0b11111111, !0b11001100, !0b11001100] } + + test_vec_2! { test_vec_xor, vec_xor, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [0b11111111, 0b00111111, 0b11000000, 0b11001100] } + + test_vec_2! { test_vec_eqv, vec_eqv, i32x4, + [0b11001100, 0b11001100, 0b11001100, 0b11001100], + [0b00110011, 0b11110011, 0b00001100, 0b00000000], + [!0b11111111, !0b00111111, !0b11000000, !0b11001100] } }