risc-v: 0.980 files: 0.974 permissions: 0.945 register: 0.940 ppc: 0.933 assembly: 0.932 PID: 0.927 graphic: 0.923 kernel: 0.919 performance: 0.908 socket: 0.905 user-level: 0.905 device: 0.889 architecture: 0.888 arm: 0.883 semantic: 0.871 hypervisor: 0.857 debug: 0.855 mistranslation: 0.852 network: 0.828 virtual: 0.816 boot: 0.801 vnc: 0.783 TCG: 0.709 x86: 0.697 VMM: 0.680 i386: 0.666 KVM: 0.642 peripherals: 0.504 `vill` not set after reserved `vsetvli` instruction usage Description of problem: The ["AVL encoding" section of the RISC-V V Spec 1.0](https://github.com/riscv/riscv-isa-manual/blob/main/src/v-st-ext.adoc#avl-encoding) states that a `vsetvli x0,x0,...` that changes VLMAX is reserved and "Implementations may set `vill`" in this case. QEMU does not set `vill` in this case. Doing so would help detect code generation issues and non-portable code. Here is the quote from the spec: > When `rs1=x0` and `rd=x0`, the instruction operates as if the current > vector length in `vl` is used as the AVL, and the resulting value is > written to `vl`, but not to a destination register. This form can > only be used when VLMAX and hence `vl` is not actually changed by the > new SEW/LMUL ratio. Use of the instruction with a new SEW/LMUL ratio > that would result in a change of VLMAX is reserved. > Use of the instruction is also reserved if `vill` was 1 beforehand. > Implementations may set `vill` in either case. Note, I have not checked QEMU's behaviour for the other case mentioned in the quote: "Use of the instruction is also reserved if `vill` was 1 beforehand". Steps to reproduce: 1. Create `test.c` ```C #include /* Position of vill in vtype. */ #define VILL_BIT (__riscv_xlen - 1) /* Return true if vill is 1. */ int vill_set_p () { __UINT64_TYPE__ vtype; asm volatile ("csrr %0, vtype" : "=r"(vtype)); return (vtype >> VILL_BIT) & 1; } /* Return true if vill is 0. */ int vill_clear_p () { return !vill_set_p (); } int main () { int vl; assert (vill_clear_p ()); /* Valid: vl = VLMAX. */ asm volatile ("vsetvli %0,zero,e64,m8,ta,ma\n" : "=r"(vl)); assert (vill_clear_p ()); /* Valid: vl and VLMAX not changed. */ asm volatile ("vsetvli zero,zero,e64,m8,ta,ma\n"); assert (vill_clear_p ()); /* Reserved: Reduce VLMAX. */ asm volatile ("vsetvli zero,zero,e64,m1,ta,ma\n"); assert (vill_set_p ()); return 0; } ``` 2. Build `test.c` with `riscv32-unknown-elf-gcc test.c -o test -march=rv64gcv -mabi=lp64d` 3. Run qemu with `qemu-riscv64 -cpu rv64,v=true test` 4. The final assertion fails because executing the reserved `vsetvli` did not set `vill` ``` assertion "vill_set_p ()" failed: file "test.c", line 40, function: main ```