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
54 changes: 53 additions & 1 deletion src/isa/riscv/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3277,7 +3277,9 @@ impl RiscVCpu {
return Err(Trap::illegal(insn.raw));
}
let total = nreg as usize * VLENB as usize;
for i in 0..total {
// Whole-register moves follow the same vstart rule as every
// other vector instruction: earlier bytes stay undisturbed.
for i in vstart.min(total)..total {
let b = self.velem(vs2, i, 1);
self.set_velem(vd, i, 1, b);
}
Expand Down Expand Up @@ -6076,6 +6078,56 @@ mod tests {
assert_eq!(c.vreg(8), pat);
}

#[test]
fn vmvr_resumes_from_vstart() {
// vmv<nr>r.v is not exempt from norm:vstart_op: the copy begins at
// the element number in vstart and earlier destination bytes stay
// undisturbed (QEMU's gen_helper_vmvr_v resumes from the vstart
// byte). vmv1r.v v8, v16 with vstart=1 must keep v8[0].
let op_mvr = |vs2: u32, vd: u32| -> u32 {
(0b100111u32 << 26)
| (1 << 25)
| (vs2 << 20)
| (0 << 15)
| (0b011 << 12)
| (vd << 7)
| 0x57
};
let mut c = cpu();
// vsetvli x1, x0, e8, m1 -> valid (non-vill) vtype.
run_one(
&mut c,
(0u32 << 20) | (0 << 15) | (7 << 12) | (1 << 7) | 0x57,
);
let src: [u8; VLENB as usize] = core::array::from_fn(|i| (i as u8).wrapping_add(0x10));
let mut dst = [0xAAu8; VLENB as usize];
c.set_vreg(16, &src);
c.set_vreg(8, &dst);

// vstart=1: v8[0] (0xAA) must survive; bytes 1..16 come from v16.
c.set_vstart(1);
assert!(matches!(
run_one(&mut c, op_mvr(16, 8)),
RiscVExit::Continue
));
assert_eq!(c.vreg(8)[0], 0xAA);
assert_eq!(c.vreg(8)[1], src[1]);

// vstart=0: full copy, v8[0] overwritten.
let mut c2 = cpu();
run_one(
&mut c2,
(0u32 << 20) | (0 << 15) | (7 << 12) | (1 << 7) | 0x57,
);
c2.set_vreg(16, &src);
c2.set_vreg(8, &dst);
assert!(matches!(
run_one(&mut c2, op_mvr(16, 8)),
RiscVExit::Continue
));
assert_eq!(c2.vreg(8)[0], src[0]);
}

#[test]
fn vector_config() {
let mut c = cpu();
Expand Down
Loading