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
37 changes: 36 additions & 1 deletion src/isa/riscv/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3325,7 +3325,8 @@ impl RiscVCpu {
let ei16 = insn.op == Op::Vrgatherei16;
let is_vv = insn.funct3 == 0b000;
// The destination group must not overlap the source vs2 group,
// nor (for vv/ei16) the index vector group; such encodings are
// nor (for vv/ei16) the index vector group; the index group
// must also be aligned to its EMUL. Such encodings are
// reserved and must trap rather than gather in place.
let data_emul: u8 = match self.vtype & 0x7 {
1 => 2,
Expand All @@ -3346,6 +3347,9 @@ impl RiscVCpu {
} else {
data_emul
};
if insn.rs1 % idx_regs != 0 {
return Err(Trap::illegal(insn.raw));
}
if overlaps(vd, data_emul, insn.rs1, idx_regs) {
return Err(Trap::illegal(insn.raw));
}
Expand Down Expand Up @@ -5997,6 +6001,37 @@ mod tests {
));
}

#[test]
fn vrgatherei16_rejects_misaligned_index_group() {
// vrgatherei16.vv (funct6 001110, vv) uses EEW=16 indices whose
// EMUL = ceil(LMUL*16/SEW); the vs1 group must be aligned to that
// EMUL, otherwise the encoding is reserved (RVV 6.3).
// SEW=32, LMUL=4 -> index EMUL=2, so vs1=1 is misaligned.
let mut c = cpu();
c.set_vl_vtype(16, 0b010 | (0b010 << 3)); // e32,m4
assert!(matches!(
run_one(&mut c, op_v(0b001110, 1, 8, 1, 0b000, 16)),
RiscVExit::Trap(_)
));
// Control: vs1=2 (aligned, index EMUL=2) executes.
assert!(matches!(
run_one(&mut c, op_v(0b001110, 1, 8, 2, 0b000, 16)),
RiscVExit::Continue
));
// SEW=32, LMUL=8 -> index EMUL=4, so vs1=2 is misaligned.
let mut c8 = cpu();
c8.set_vl_vtype(32, 0b011 | (0b010 << 3)); // e32,m8
assert!(matches!(
run_one(&mut c8, op_v(0b001110, 1, 8, 2, 0b000, 16)),
RiscVExit::Trap(_)
));
// Control: vs1=4 (aligned) executes.
assert!(matches!(
run_one(&mut c8, op_v(0b001110, 1, 8, 4, 0b000, 16)),
RiscVExit::Continue
));
}

#[test]
fn mask_reductions_reject_nonzero_vstart() {
// vcpop.m/vfirst.m/vmsbf.m/vmsof.m/vmsif.m/viota.m are not restartable;
Expand Down
Loading