mod scalar;
mod vector;
use crate::exec::compute::vector::mem::{
is_vec_load, is_vec_store, vec_mem_dst_count, vec_mem_emul_regs,
};
use crate::exec::signals::{ControlSignals, OpASrc, OpBSrc};
use crate::isa::encoding::rvv::opcodes as v_opcodes;
use crate::isa::instruction::{Decoded, decode as instruction_decode};
use crate::isa::op::{AluOp, VectorOp};
use crate::isa::privileged::Trap;
use crate::isa::rvv::{VtypeFields, parse_vtype};
pub(super) const VEC_WIDTH_8: u32 = 0b000;
pub(super) const VEC_WIDTH_16: u32 = 0b101;
pub(super) const VEC_WIDTH_32: u32 = 0b110;
pub(super) const VEC_WIDTH_64: u32 = 0b111;
fn decode_instruction(inst: u32, pc: u64, d: &Decoded) -> Result<ControlSignals, Trap> {
let mut c = ControlSignals {
a_src: OpASrc::Reg1,
b_src: OpBSrc::Imm,
alu: AluOp::Add,
..Default::default()
};
match d.opcode {
v_opcodes::OP_V | v_opcodes::OP_V_CRYPTO => vector::decode(&mut c, inst, d)?,
_ => scalar::decode(&mut c, inst, pc, d)?,
}
Ok(c)
}
#[derive(Clone, Debug)]
pub struct DecodedInst {
pub fields: Decoded,
pub ctrl: ControlSignals,
pub trap: Option<Trap>,
}
#[must_use]
pub fn decode_inst(inst: u32, pc: u64, vtype_bits: u64) -> DecodedInst {
let fields = instruction_decode(inst);
let (mut ctrl, mut trap) = match decode_instruction(inst, pc, &fields) {
Ok(ctrl) => (ctrl, None),
Err(trap) => (ControlSignals::default(), Some(trap)),
};
let vtype = parse_vtype(vtype_bits);
if ctrl.vec_op != VectorOp::None && !ctrl.vec_op.is_config() && !vtype.vill {
ctrl.vec_lmul_regs = vtype.vlmul.group_regs().regs();
ctrl.vec_lmul_is_fractional = vtype.vlmul.is_fractional();
if trap.is_none() && vector_groups_misaligned(&ctrl, vtype) {
ctrl = ControlSignals::default();
trap = Some(Trap::IllegalInstruction(inst));
}
}
DecodedInst { fields, ctrl, trap }
}
fn vector_groups_misaligned(ctrl: &ControlSignals, vtype: VtypeFields) -> bool {
let misaligned = |reg: u8, group: u8| {
group > 1 && (!reg.is_multiple_of(group) || reg.saturating_add(group) > 32)
};
let vd = ctrl.vd.as_u8();
let vs2 = ctrl.vs2.as_u8();
if is_vec_load(ctrl.vec_op) || is_vec_store(ctrl.vec_op) {
let total =
vec_mem_dst_count(ctrl.vec_op, ctrl.vec_eew, vtype.vsew, vtype.vlmul, ctrl.vec_nf);
let (data_emul, index_emul) =
vec_mem_emul_regs(ctrl.vec_op, ctrl.vec_eew, vtype.vsew, vtype.vlmul);
let vd_misaligned = data_emul > 1 && !vd.is_multiple_of(data_emul);
return vd_misaligned || vd.saturating_add(total) > 32 || misaligned(vs2, index_emul);
}
let groups = ctrl.vec_op.operand_groups(
ctrl.vec_lmul_regs,
ctrl.vec_lmul_is_fractional,
ctrl.vec_src_encoding,
ctrl.vec_nf,
ctrl.vec_broadcast_vs2,
);
misaligned(vd, groups.vd)
|| misaligned(vs2, groups.vs2)
|| misaligned(ctrl.vs1.as_u8(), groups.vs1)
}