#![allow(unsafe_op_in_unsafe_fn, clippy::missing_safety_doc)]
use core::arch::asm;
#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;
use half::f16;
pub const CMP_LT_OQ: i32 = 0x11;
pub const CMP_LE_OQ: i32 = 0x12;
pub const CMP_GE_OQ: i32 = 0x1d;
pub const CMP_GT_OQ: i32 = 0x1e;
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn load(p: *const f16) -> __m512i {
core::ptr::read_unaligned(p as *const __m512i)
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn store(p: *mut f16, v: __m512i) {
core::ptr::write_unaligned(p as *mut __m512i, v)
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn splat(v: f16) -> __m512i {
_mm512_set1_epi16(v.to_bits() as i16)
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn neg(a: __m512i) -> __m512i {
_mm512_xor_si512(a, _mm512_set1_epi16(0x8000u16 as i16))
}
macro_rules! binop {
($name:ident, $mnem:literal) => {
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn $name(a: __m512i, b: __m512i) -> __m512i {
let r;
asm!(
concat!($mnem, " {r}, {a}, {b}"),
r = lateout(zmm_reg) r, a = in(zmm_reg) a, b = in(zmm_reg) b,
options(pure, nomem, nostack, preserves_flags),
);
r
}
};
}
binop!(add, "vaddph");
binop!(sub, "vsubph");
binop!(mul, "vmulph");
binop!(div, "vdivph");
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn min(a: __m512i, b: __m512i) -> __m512i {
let r;
asm!(
"vminph {r}, {a}, {b}",
"vcmpph {k}, {b}, {b}, 3",
"vmovdqu16 {r}{{{k}}}, {a}",
r = out(zmm_reg) r, a = in(zmm_reg) a, b = in(zmm_reg) b, k = out(kreg) _,
options(pure, nomem, nostack, preserves_flags),
);
r
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn max(a: __m512i, b: __m512i) -> __m512i {
let r;
asm!(
"vmaxph {r}, {a}, {b}",
"vcmpph {k}, {b}, {b}, 3",
"vmovdqu16 {r}{{{k}}}, {a}",
r = out(zmm_reg) r, a = in(zmm_reg) a, b = in(zmm_reg) b, k = out(kreg) _,
options(pure, nomem, nostack, preserves_flags),
);
r
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn sqrt(a: __m512i) -> __m512i {
let r;
asm!(
"vsqrtph {r}, {a}",
r = lateout(zmm_reg) r, a = in(zmm_reg) a,
options(pure, nomem, nostack, preserves_flags),
);
r
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn fma(a: __m512i, b: __m512i, c: __m512i) -> __m512i {
let mut dst = a;
asm!(
"vfmadd213ph {dst}, {b}, {c}",
dst = inout(zmm_reg) dst, b = in(zmm_reg) b, c = in(zmm_reg) c,
options(pure, nomem, nostack, preserves_flags),
);
dst
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn cmp<const IMM: i32>(a: __m512i, b: __m512i) -> u32 {
let m: u32;
asm!(
"vcmpph k1, {a}, {b}, {imm}",
"kmovd {m:e}, k1",
a = in(zmm_reg) a, b = in(zmm_reg) b, m = lateout(reg) m, imm = const IMM,
out("k1") _,
options(pure, nomem, nostack, preserves_flags),
);
m
}
#[target_feature(enable = "avx512fp16,avx512f,avx512bw")]
#[inline]
pub unsafe fn select(mask: u32, a: __m512i, b: __m512i) -> __m512i {
let r;
asm!(
"kmovd k1, {m:e}",
"vpblendmw {r}{{k1}}, {b}, {a}",
m = in(reg) mask, a = in(zmm_reg) a, b = in(zmm_reg) b, r = lateout(zmm_reg) r,
out("k1") _,
options(pure, nomem, nostack, preserves_flags),
);
r
}