1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
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 <assert.h>
/* 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
```
|