#[inline(always)]
pub unsafe fn fmopa_s<
const ZAD: u32,
const ZN: u32,
const ZM: u32,
const PN: u32,
const PM: u32,
>() {
const {
assert!(ZAD < 4, "FMOPA.S ZAd must be 0..3");
assert!(ZN < 32 && ZM < 16);
assert!(PN < 8 && PM < 8);
}
core::arch::asm!(
".word {enc}",
enc = const 0x80800000 | (ZM << 16) | (PM << 13) | (PN << 10) | (ZN << 5) | ZAD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn mova_z_from_za_h_s<
const ZD: u32,
const PG: u32,
const ZAS: u32,
const WBASE: u32,
const OFFSET: u32,
>() {
const {
assert!(ZD < 32 && PG < 8 && ZAS < 4 && WBASE < 4 && OFFSET < 4);
}
core::arch::asm!(
".word {enc}",
enc = const 0xC0820000
| ((ZAS & 0x3) << 7)
| (WBASE << 13)
| (PG << 10)
| ((OFFSET & 0x3) << 5)
| ZD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn mova_za_h_from_z_s<
const ZAD: u32,
const WBASE: u32,
const OFFSET: u32,
const PG: u32,
const ZN: u32,
>() {
const {
assert!(ZAD < 4 && WBASE < 4 && OFFSET < 4 && PG < 8 && ZN < 32);
}
core::arch::asm!(
".word {enc}",
enc = const 0xC0800000
| ((ZAD & 0x3) << 3)
| (WBASE << 13)
| (PG << 10)
| (ZN << 5)
| (OFFSET & 0x3),
options(nostack),
);
}
#[inline(always)]
pub unsafe fn smopa_int16_s<
const ZAD: u32,
const ZN: u32,
const ZM: u32,
const PN: u32,
const PM: u32,
>() {
const {
assert!(ZAD < 4, "SMOPA.S ZAd must be 0..3");
assert!(ZN < 32 && ZM < 32);
assert!(PN < 8 && PM < 8);
}
core::arch::asm!(
".word {enc}",
enc = const 0xA080_0008 | (ZM << 16) | (PM << 13) | (PN << 10) | (ZN << 5) | ZAD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn umopa_int16_s<
const ZAD: u32,
const ZN: u32,
const ZM: u32,
const PN: u32,
const PM: u32,
>() {
const {
assert!(ZAD < 4, "UMOPA.S ZAd must be 0..3");
assert!(ZN < 32 && ZM < 32);
assert!(PN < 8 && PM < 8);
}
core::arch::asm!(
".word {enc}",
enc = const 0xA180_0008 | (ZM << 16) | (PM << 13) | (PN << 10) | (ZN << 5) | ZAD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn smopa_int16_d<
const ZAD: u32,
const ZN: u32,
const ZM: u32,
const PN: u32,
const PM: u32,
>() {
const {
assert!(ZAD < 8, "SMOPA.D ZAd must be 0..7");
assert!(ZN < 32 && ZM < 32);
assert!(PN < 8 && PM < 8);
}
core::arch::asm!(
".word {enc}",
enc = const 0xA0C0_0000 | (ZM << 16) | (PM << 13) | (PN << 10) | (ZN << 5) | ZAD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn umopa_int16_d<
const ZAD: u32,
const ZN: u32,
const ZM: u32,
const PN: u32,
const PM: u32,
>() {
const {
assert!(ZAD < 8, "UMOPA.D ZAd must be 0..7");
assert!(ZN < 32 && ZM < 32);
assert!(PN < 8 && PM < 8);
}
core::arch::asm!(
".word {enc}",
enc = const 0xA1E0_0000 | (ZM << 16) | (PM << 13) | (PN << 10) | (ZN << 5) | ZAD,
options(nostack),
);
}
#[inline(always)]
pub unsafe fn mova_z_from_za_h_d<const ZD: u32, const PG: u32, const ZAS: u32, const WBASE: u32>() {
const {
assert!(ZD < 32 && PG < 8 && ZAS < 8 && WBASE < 4);
}
core::arch::asm!(
".word {enc}",
enc = const 0xC0C2_0000
| ((ZAS & 0x7) << 6)
| (WBASE << 13)
| (PG << 10)
| ZD,
options(nostack),
);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::streaming::Stream;
#[test]
fn encoders_int16_assemble() {
if !crate::probe::scan().has_sme {
eprintln!("skip: FEAT_SME not present");
return;
}
let _s = Stream::new().unwrap();
unsafe {
smopa_int16_s::<0, 0, 1, 0, 0>();
smopa_int16_s::<3, 31, 31, 7, 7>();
umopa_int16_s::<0, 0, 1, 0, 0>();
umopa_int16_s::<2, 5, 6, 1, 2>();
if crate::probe::scan().has_sme_i16i64 {
smopa_int16_d::<0, 0, 1, 0, 0>();
smopa_int16_d::<7, 31, 31, 7, 7>();
umopa_int16_d::<0, 0, 1, 0, 0>();
mova_z_from_za_h_d::<0, 0, 0, 0>();
mova_z_from_za_h_d::<31, 7, 7, 0>();
}
}
}
}