See links:
-*
-<http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-November/001366.html>
+* <http://lists.libre-soc.org/pipermail/libre-soc-dev/2020-November/001366.html>
* <https://bugs.libre-soc.org/show_bug.cgi?id=535>
+* <https://bugs.libre-soc.org/show_bug.cgi?id=568> TODO
+* <https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vsetvlivsetvl-instructions>
+
+Use of setvl results in changes to the MVL, VL and STATE SPRs. see [[sv/sprs]]♧
+
+# Format
+
+*(Allocation of opcode TBD pending OPF ISA WG approval)*
+
+| 0.5|6.10|11.15|16.20| 21..24.25 | 26...30 |31| name |
+| -- | -- | --- | --- | ----------- | ------- |--| ------- |
+| 19 | RT | RA | | XO[0:4] | XO[5:9] |Rc| XL-Form |
+| 19 | RT | RA | imm | i // vs ms | NNNNN |Rc| setvl |
+
+Note that imm spans 7 bits (16 to 22), and that bit 22 is reserved and must be zero. Setting bit 22 causes an illegal exception.
+
+Note that in immediate setting mode VL and MVL start from **one** i.e. that an immediate value of zero will result in VL/MVL being set to 1. 0b111111 results in VL/MVL being set to 64. This is because setting VL/MVL to 1 results in "scalar identity" behaviour, where setting VL/MVL to 0 would result in all Vector operations becoming `nop`. If this is truly desired (nop behaviour) then setting VL and MVL to zero is to be done via the [[SV SPRs|sv/sprs]]
+
+Note that setmvli is a pseudo-op, based on RA/RT=0, and setvli likewise
+
+* setvli VL=8 : setvl r5, r0, VL=8
+* setmvli MVL=8 : setvl r0, r0, MVL=8
+
+# Pseudocode
+
+ // instruction fields:
+ rd = get_rt_field(); // bits 6..10
+ ra = get_ra_field(); // bits 11..15
+ vs = get_vs_field(); // bit 24
+ ms = get_ms_field(); // bit 25
+ Rc = get_Rc_field(); // bit 31
+ // add one. MVL/VL=1..64 not 0..63
+ vlimmed = get_immed_field()+1; // 16..22
+
+ // set VL (or not).
+ // 3 options: from SPR, from immed, from ra
+ if vs {
+ // VL to be sourced from fields/regs
+ if ra != 0 {
+ VL = GPR[ra]
+ } else {
+ VL = vlimmed
+ }
+ } else {
+ // VL not to change (except if MVL is reduced)
+ // read from SPRs
+ VL = SPR[SV_VL]
+ }
+
+ // set MVL (or not).
+ // 2 options: from SPR, from immed
+ if ms {
+ MVL = vlimmed
+ } else {
+ // MVL not to change, read from SPRs
+ MVL = SPR[SV_MVL]
+ }
+
+ // calculate (limit) VL
+ VL = min(VL, MVL)
+
+ // store VL, MVL
+ SPR[SV_VL] = VL
+ SPR[SV_MVL] = MVL
+
+ // write rd
+ if rt != 0 {
+ // rt is not zero
+ regs[rt] = VL;
+ }
+ // write CR?
+ if Rc {
+ // update CR from VL (not rt)
+ CR0.eq = (VL == 0)
+ ...
+ ...
+ }
+
+# Examples
+
+## Core concept loop
+
+ loop:
+ setvl a3, a0, MVL=8 # update a3 with vl
+ # (# of elements this iteration)
+ # set MVL to 8
+ # do vector operations at up to 8 length (MVL=8)
+ # ...
+ sub a0, a0, a3 # Decrement count by vl
+ bnez a0, loop # Any more?
+
+## Loop using Rc=1
+
+ my_fn:
+ li r3, 1000
+ b test
+ loop:
+ sub r3, r3, r4
+ ...
+ test:
+ setvli. r4, r3, VL=64, MVL=64
+ bne cr0, loop
+ end:
+ blr