(no commit message)
[libreriscv.git] / openpower / sv / setvl.mdwn
index ed5840932bc141a14baed99953ccbf6ceca5c9f7..b40aa46e46daad98a6e0807315aeb775b3878530 100644 (file)
@@ -2,6 +2,109 @@
 
 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