Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/isa/riscv/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,18 @@ impl RiscVCpu {
}
Op::Vslide1down | Op::Vfslide1down => {
// vd[i] = vs2[i+1] for i < vl-1; vd[vl-1] = scalar.
// Both register groups must be LMUL-aligned; the downward
// slide permits vd == vs2 (RVV 16.3.4; QEMU vext_check_slide
// with is_over=false).
let emul: u8 = match self.vtype & 0x7 {
1 => 2,
2 => 4,
3 => 8,
_ => 1,
};
if vd % emul != 0 || vs2 % emul != 0 {
return Err(Trap::illegal(insn.raw));
}
let eb = self.sew_bytes();
let mask = Self::sew_mask(eb);
let scalar = if insn.op == Op::Vfslide1down {
Expand Down Expand Up @@ -6024,6 +6036,36 @@ mod tests {
}
}

#[test]
fn vslide1down_rejects_misaligned_groups() {
// vslide1down.vx/vfslide1down.vf require both the vd and vs2 groups
// to be LMUL-aligned; vd == vs2 is legal (RVV 16.3.4; QEMU
// vext_check_slide with is_over=false). e32,m2 -> EMUL=2.
let mut c = cpu_e8m1();
c.set_vl_vtype(4, 0b010_001); // e32, m2
c.set_x(5, 1);
// vslide1down.vx v0, v1, x5 (vs2=v1 misaligned) -> illegal.
assert!(matches!(
run_one(&mut c, op_v(0b001111, 1, 1, 5, 0b110, 0)),
RiscVExit::Trap(_)
));
// vslide1down.vx v3, v4, x5 (vd=v3 misaligned) -> illegal.
assert!(matches!(
run_one(&mut c, op_v(0b001111, 1, 4, 5, 0b110, 3)),
RiscVExit::Trap(_)
));
// vslide1down.vx v4, v4, x5 (aligned, vd == vs2) -> runs.
assert!(matches!(
run_one(&mut c, op_v(0b001111, 1, 4, 5, 0b110, 4)),
RiscVExit::Continue
));
// vslide1down.vx v0, v2, x5 (aligned) -> runs.
assert!(matches!(
run_one(&mut c, op_v(0b001111, 1, 2, 5, 0b110, 0)),
RiscVExit::Continue
));
}

#[test]
fn vmvr_rejects_reserved_encodings() {
// vmv<nr>r.v: funct6=0b100111, funct3=0b011, OP-V (0x57). Only nr in
Expand Down
Loading