Skip to content

Commit cf05f82

Browse files
committed
add vec_genmask and vec_genmasks
1 parent 085df43 commit cf05f82

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

crates/core_arch/src/s390x/vector.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,39 @@ impl<const N: usize> ShuffleMask<N> {
154154
}
155155
}
156156

157+
const fn genmask<const MASK: u16>() -> [u8; 16] {
158+
let mut bits = MASK;
159+
let mut elements = [0u8; 16];
160+
161+
let mut i = 0;
162+
while i < 16 {
163+
elements[i] = match bits & (1u16 << 15) {
164+
0 => 0,
165+
_ => 0xFF,
166+
};
167+
168+
bits <<= 1;
169+
i += 1;
170+
}
171+
172+
elements
173+
}
174+
175+
const fn genmasks(bit_width: u32, a: u8, b: u8) -> u64 {
176+
let bit_width = bit_width as u8;
177+
let a = a % bit_width;
178+
let mut b = b % bit_width;
179+
if a > b {
180+
b = bit_width - 1;
181+
}
182+
183+
// of course these indices start from the left
184+
let a = (bit_width - 1) - a;
185+
let b = (bit_width - 1) - b;
186+
187+
((1u64.wrapping_shl(a as u32 + 1)) - 1) & !((1u64.wrapping_shl(b as u32)) - 1)
188+
}
189+
157190
#[macro_use]
158191
mod sealed {
159192
use super::*;
@@ -1731,6 +1764,52 @@ where
17311764
a.vec_mergel(b)
17321765
}
17331766

1767+
/// Generates byte masks for elements in the return vector. For each bit in a, if the bit is one, all bit positions
1768+
/// in the corresponding byte element of d are set to ones. Otherwise, if the bit is zero, the corresponding byte element is set to zero.
1769+
#[inline]
1770+
#[target_feature(enable = "vector")]
1771+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1772+
#[cfg_attr(test, assert_instr(vgbm, MASK = 0x00FF))]
1773+
pub unsafe fn vec_genmask<const MASK: u16>() -> vector_unsigned_char {
1774+
vector_unsigned_char(const { genmask::<MASK>() })
1775+
}
1776+
1777+
/// Vector Generate Mask (Byte)
1778+
#[inline]
1779+
#[target_feature(enable = "vector")]
1780+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1781+
#[cfg_attr(test, assert_instr(vrepib, L = 3, H = 5))]
1782+
pub unsafe fn vec_genmasks_8<const L: u8, const H: u8>() -> vector_unsigned_char {
1783+
vector_unsigned_char(const { [genmasks(u8::BITS, L, H) as u8; 16] })
1784+
}
1785+
1786+
/// Vector Generate Mask (Halfword)
1787+
#[inline]
1788+
#[target_feature(enable = "vector")]
1789+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1790+
#[cfg_attr(test, assert_instr(vrepih, L = 3, H = 5))]
1791+
pub unsafe fn vec_genmasks_16<const L: u8, const H: u8>() -> vector_unsigned_short {
1792+
vector_unsigned_short(const { [genmasks(u16::BITS, L, H) as u16; 8] })
1793+
}
1794+
1795+
/// Vector Generate Mask (Word)
1796+
#[inline]
1797+
#[target_feature(enable = "vector")]
1798+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1799+
#[cfg_attr(test, assert_instr(vgmf, L = 3, H = 5))]
1800+
pub unsafe fn vec_genmasks_32<const L: u8, const H: u8>() -> vector_unsigned_int {
1801+
vector_unsigned_int(const { [genmasks(u32::BITS, L, H) as u32; 4] })
1802+
}
1803+
1804+
/// Vector Generate Mask (Doubleword)
1805+
#[inline]
1806+
#[target_feature(enable = "vector")]
1807+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1808+
#[cfg_attr(test, assert_instr(vgmg, L = 3, H = 5))]
1809+
pub unsafe fn vec_genmasks_64<const L: u8, const H: u8>() -> vector_unsigned_long_long {
1810+
vector_unsigned_long_long(const { [genmasks(u64::BITS, L, H); 2] })
1811+
}
1812+
17341813
#[cfg(test)]
17351814
mod tests {
17361815
use super::*;
@@ -1755,6 +1834,36 @@ mod tests {
17551834
assert_eq!(ShuffleMask::<4>::merge_high().0, [0, 4, 1, 5]);
17561835
}
17571836

1837+
#[test]
1838+
fn test_vec_mask() {
1839+
assert_eq!(
1840+
genmask::<0x00FF>(),
1841+
[
1842+
0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1843+
]
1844+
);
1845+
}
1846+
1847+
#[test]
1848+
fn test_genmasks() {
1849+
assert_eq!(genmasks(u8::BITS, 3, 5), 28);
1850+
assert_eq!(genmasks(u8::BITS, 3, 7), 31);
1851+
1852+
// If a or b is greater than 8, the operation is performed as if the value gets modulo by 8.
1853+
assert_eq!(genmasks(u8::BITS, 3 + 8, 7 + 8), 31);
1854+
// If a is greater than b, the operation is perform as if b equals 7.
1855+
assert_eq!(genmasks(u8::BITS, 5, 4), genmasks(u8::BITS, 5, 7));
1856+
1857+
assert_eq!(
1858+
genmasks(u16::BITS, 4, 12) as u16,
1859+
u16::from_be_bytes([15, -8i8 as u8])
1860+
);
1861+
assert_eq!(
1862+
genmasks(u32::BITS, 4, 29) as u32,
1863+
u32::from_be_bytes([15, 0xFF, 0xFF, -4i8 as u8])
1864+
);
1865+
}
1866+
17581867
macro_rules! test_vec_1 {
17591868
{ $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => {
17601869
#[simd_test(enable = "vector")]

0 commit comments

Comments
 (0)