#[cfg(test)]
mod tests;
use crate::instructions::Instruction;
use crate::registers::general_purpose::Register;
use crate::registers::vector::VReg;
use ab_riscv_macros::instruction;
use core::fmt;
#[instruction]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[rustfmt::skip]
#[doc(hidden)]
pub enum Zve64xMulDivInstruction<Reg> {
VmulVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VmulVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VmulhVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VmulhVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VmulhuVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VmulhuVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VmulhsuVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VmulhsuVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VdivuVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VdivuVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VdivVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VdivVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VremuVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VremuVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VremVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VremVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VwmulVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VwmulVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VwmuluVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VwmuluVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VwmulsuVv { vd: VReg, vs2: VReg, vs1: VReg, vm: bool },
VwmulsuVx { vd: VReg, vs2: VReg, rs1: Reg, vm: bool },
VmaccVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VmaccVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VnmsacVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VnmsacVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VmaddVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VmaddVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VnmsubVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VnmsubVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VwmaccuVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VwmaccuVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VwmaccVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VwmaccVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VwmaccsuVv { vd: VReg, vs1: VReg, vs2: VReg, vm: bool },
VwmaccsuVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
VwmaccusVx { vd: VReg, rs1: Reg, vs2: VReg, vm: bool },
}
#[instruction]
impl<Reg> const Instruction for Zve64xMulDivInstruction<Reg>
where
Reg: [const] Register,
{
type Reg = Reg;
#[inline(always)]
fn try_decode(instruction: u32) -> Option<Self> {
let opcode = (instruction & 0b111_1111) as u8;
if opcode != 0b1010111 {
None?;
}
let vd_bits = ((instruction >> 7) & 0x1f) as u8;
let funct3 = ((instruction >> 12) & 0b111) as u8;
let vs1_or_rs1_bits = ((instruction >> 15) & 0x1f) as u8;
let vs2_bits = ((instruction >> 20) & 0x1f) as u8;
let vm = ((instruction >> 25) & 1) != 0;
let funct6 = ((instruction >> 26) & 0b111111) as u8;
let vd = VReg::from_bits(vd_bits)?;
let vs2 = VReg::from_bits(vs2_bits)?;
match funct3 {
0b010 => {
let vs1 = VReg::from_bits(vs1_or_rs1_bits)?;
match funct6 {
0b100000 => Some(Self::VdivuVv { vd, vs2, vs1, vm }),
0b100001 => Some(Self::VdivVv { vd, vs2, vs1, vm }),
0b100010 => Some(Self::VremuVv { vd, vs2, vs1, vm }),
0b100011 => Some(Self::VremVv { vd, vs2, vs1, vm }),
0b100100 => Some(Self::VmulhuVv { vd, vs2, vs1, vm }),
0b100101 => Some(Self::VmulVv { vd, vs2, vs1, vm }),
0b100110 => Some(Self::VmulhsuVv { vd, vs2, vs1, vm }),
0b100111 => Some(Self::VmulhVv { vd, vs2, vs1, vm }),
0b101001 => Some(Self::VmaddVv { vd, vs1, vs2, vm }),
0b101011 => Some(Self::VnmsubVv { vd, vs1, vs2, vm }),
0b101101 => Some(Self::VmaccVv { vd, vs1, vs2, vm }),
0b101111 => Some(Self::VnmsacVv { vd, vs1, vs2, vm }),
0b111000 => Some(Self::VwmuluVv { vd, vs2, vs1, vm }),
0b111010 => Some(Self::VwmulsuVv { vd, vs2, vs1, vm }),
0b111011 => Some(Self::VwmulVv { vd, vs2, vs1, vm }),
0b111100 => Some(Self::VwmaccuVv { vd, vs1, vs2, vm }),
0b111101 => Some(Self::VwmaccVv { vd, vs1, vs2, vm }),
0b111111 => Some(Self::VwmaccsuVv { vd, vs1, vs2, vm }),
_ => None,
}
}
0b110 => {
let rs1 = Reg::from_bits(vs1_or_rs1_bits)?;
match funct6 {
0b100000 => Some(Self::VdivuVx { vd, vs2, rs1, vm }),
0b100001 => Some(Self::VdivVx { vd, vs2, rs1, vm }),
0b100010 => Some(Self::VremuVx { vd, vs2, rs1, vm }),
0b100011 => Some(Self::VremVx { vd, vs2, rs1, vm }),
0b100100 => Some(Self::VmulhuVx { vd, vs2, rs1, vm }),
0b100101 => Some(Self::VmulVx { vd, vs2, rs1, vm }),
0b100110 => Some(Self::VmulhsuVx { vd, vs2, rs1, vm }),
0b100111 => Some(Self::VmulhVx { vd, vs2, rs1, vm }),
0b101001 => Some(Self::VmaddVx { vd, rs1, vs2, vm }),
0b101011 => Some(Self::VnmsubVx { vd, rs1, vs2, vm }),
0b101101 => Some(Self::VmaccVx { vd, rs1, vs2, vm }),
0b101111 => Some(Self::VnmsacVx { vd, rs1, vs2, vm }),
0b111000 => Some(Self::VwmuluVx { vd, vs2, rs1, vm }),
0b111010 => Some(Self::VwmulsuVx { vd, vs2, rs1, vm }),
0b111011 => Some(Self::VwmulVx { vd, vs2, rs1, vm }),
0b111100 => Some(Self::VwmaccuVx { vd, rs1, vs2, vm }),
0b111101 => Some(Self::VwmaccVx { vd, rs1, vs2, vm }),
0b111110 => Some(Self::VwmaccusVx { vd, rs1, vs2, vm }),
0b111111 => Some(Self::VwmaccsuVx { vd, rs1, vs2, vm }),
_ => None,
}
}
_ => None,
}
}
#[inline(always)]
fn alignment() -> u8 {
size_of::<u32>() as u8
}
#[inline(always)]
fn size(&self) -> u8 {
size_of::<u32>() as u8
}
}
impl<Reg> fmt::Display for Zve64xMulDivInstruction<Reg>
where
Reg: fmt::Display,
{
#[rustfmt::skip]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[rustfmt::skip]
match self {
Self::VmulVv { vd, vs2, vs1, vm } => write!(f, "vmul.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VmulVx { vd, vs2, rs1, vm } => write!(f, "vmul.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VmulhVv { vd, vs2, vs1, vm } => write!(f, "vmulh.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VmulhVx { vd, vs2, rs1, vm } => write!(f, "vmulh.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VmulhuVv { vd, vs2, vs1, vm } => write!(f, "vmulhu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VmulhuVx { vd, vs2, rs1, vm } => write!(f, "vmulhu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VmulhsuVv { vd, vs2, vs1, vm } => write!(f, "vmulhsu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VmulhsuVx { vd, vs2, rs1, vm } => write!(f, "vmulhsu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VdivuVv { vd, vs2, vs1, vm } => write!(f, "vdivu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VdivuVx { vd, vs2, rs1, vm } => write!(f, "vdivu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VdivVv { vd, vs2, vs1, vm } => write!(f, "vdiv.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VdivVx { vd, vs2, rs1, vm } => write!(f, "vdiv.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VremuVv { vd, vs2, vs1, vm } => write!(f, "vremu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VremuVx { vd, vs2, rs1, vm } => write!(f, "vremu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VremVv { vd, vs2, vs1, vm } => write!(f, "vrem.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VremVx { vd, vs2, rs1, vm } => write!(f, "vrem.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VwmulVv { vd, vs2, vs1, vm } => write!(f, "vwmul.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VwmulVx { vd, vs2, rs1, vm } => write!(f, "vwmul.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VwmuluVv { vd, vs2, vs1, vm } => write!(f, "vwmulu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VwmuluVx { vd, vs2, rs1, vm } => write!(f, "vwmulu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VwmulsuVv { vd, vs2, vs1, vm } => write!(f, "vwmulsu.vv {vd}, {vs2}, {vs1}{}", mask_suffix(vm)),
Self::VwmulsuVx { vd, vs2, rs1, vm } => write!(f, "vwmulsu.vx {vd}, {vs2}, {rs1}{}", mask_suffix(vm)),
Self::VmaccVv { vd, vs1, vs2, vm } => write!(f, "vmacc.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VmaccVx { vd, rs1, vs2, vm } => write!(f, "vmacc.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VnmsacVv { vd, vs1, vs2, vm } => write!(f, "vnmsac.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VnmsacVx { vd, rs1, vs2, vm } => write!(f, "vnmsac.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VmaddVv { vd, vs1, vs2, vm } => write!(f, "vmadd.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VmaddVx { vd, rs1, vs2, vm } => write!(f, "vmadd.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VnmsubVv { vd, vs1, vs2, vm } => write!(f, "vnmsub.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VnmsubVx { vd, rs1, vs2, vm } => write!(f, "vnmsub.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccuVv { vd, vs1, vs2, vm } => write!(f, "vwmaccu.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccuVx { vd, rs1, vs2, vm } => write!(f, "vwmaccu.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccVv { vd, vs1, vs2, vm } => write!(f, "vwmacc.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccVx { vd, rs1, vs2, vm } => write!(f, "vwmacc.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccsuVv { vd, vs1, vs2, vm } => write!(f, "vwmaccsu.vv {vd}, {vs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccsuVx { vd, rs1, vs2, vm } => write!(f, "vwmaccsu.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
Self::VwmaccusVx { vd, rs1, vs2, vm } => write!(f, "vwmaccus.vx {vd}, {rs1}, {vs2}{}", mask_suffix(vm)),
}
}
}
#[inline(always)]
fn mask_suffix(vm: &bool) -> &'static str {
if *vm { "" } else { ", v0.t" }
}