vsimd/
simulation.rs

1use crate::vector::V128;
2
3use core::mem::transmute as t;
4
5#[cfg(miri)]
6use core::cmp::{max, min};
7
8// TODO: waiting for MIRI's support
9
10#[cfg(miri)]
11#[inline(always)]
12pub fn u8x16_max(a: V128, b: V128) -> V128 {
13    let (a, b) = (a.as_bytes(), b.as_bytes());
14    let mut c = [0; 16];
15    for i in 0..16 {
16        c[i] = max(a[i], b[i]);
17    }
18    V128::from_bytes(c)
19}
20
21#[cfg(miri)]
22#[inline(always)]
23pub fn u8x16_min(a: V128, b: V128) -> V128 {
24    let (a, b) = (a.as_bytes(), b.as_bytes());
25    let mut c = [0; 16];
26    for i in 0..16 {
27        c[i] = min(a[i], b[i]);
28    }
29    V128::from_bytes(c)
30}
31
32#[allow(clippy::needless_range_loop)]
33#[inline(always)]
34pub fn u8x16_bitmask(a: V128) -> u16 {
35    // FIXME: is it defined behavior?
36    // https://github.com/rust-lang/miri/issues/2617
37    // https://github.com/rust-lang/stdarch/issues/1347
38
39    let a = a.as_bytes();
40    let mut m: u16 = 0;
41    for i in 0..16 {
42        m |= ((a[i] >> 7) as u16) << i;
43    }
44    m
45}
46
47#[allow(clippy::needless_range_loop)]
48#[inline(always)]
49pub fn u16x8_shr(a: V128, imm8: u8) -> V128 {
50    let mut a: [u16; 8] = unsafe { t(a) };
51    for i in 0..8 {
52        a[i] >>= imm8;
53    }
54    unsafe { t(a) }
55}
56
57#[allow(clippy::needless_range_loop)]
58#[inline(always)]
59pub fn u16x8_shl(a: V128, imm8: u8) -> V128 {
60    let mut a: [u16; 8] = unsafe { t(a) };
61    for i in 0..8 {
62        a[i] <<= imm8;
63    }
64    unsafe { t(a) }
65}
66
67#[inline(always)]
68pub fn i16x8_packus(a: V128, b: V128) -> V128 {
69    let a: [i16; 8] = unsafe { t(a) };
70    let b: [i16; 8] = unsafe { t(b) };
71    let sat_u8 = |x: i16| {
72        if x < 0 {
73            0
74        } else if x > 255 {
75            255
76        } else {
77            x as u8
78        }
79    };
80    let mut c: [u8; 16] = [0; 16];
81    for i in 0..8 {
82        c[i] = sat_u8(a[i]);
83        c[i + 8] = sat_u8(b[i]);
84    }
85    V128::from_bytes(c)
86}