(no commit message)
[libreriscv.git] / simple_v_extension / specification / bitmanip.mdwn
index 0e741c3c97764674ac81d48a2b7552acc6bf339a..02be45c7c69e8c56351e4debec4c93b124b288a1 100644 (file)
@@ -1,4 +1,3 @@
-[[!tag standards]]
 
 # Bitmanip opcodes
 
@@ -95,11 +94,30 @@ This instruction is present in BitManip.
 
 finds the first bit set as an index.
 
+Pseudocode:
+
+
+    uint_xlen_t clz(uint_xlen_t rs1)
+    {
+        for (int count = 0; count < XLEN; count++)
+            if ((rs1 << count) >> (XLEN - 1))
+                return count;
+        return XLEN; // -1
+    }
+
+This is similar but not identical to BitManip "CLZ". CLZ returns XLEN when no bits are set, whereas RVV returns -1.
+
 ## sbf - set before first bit
 
-Sets all LSBs leading up to where an LSB in the src is set.  If the second
-operand is non-zero, this process begins each time from where 1s are set in the
-second operand.
+Sets all LSBs leading up to (excluding) where an LSB in the src is set,
+and sets zeros including and following the src bit found.
+If the second operand is non-zero, this process continues the search
+(in the same LSB to MSB order) beginning each time (including the first time)
+from where 1s are set in the second operand.
+
+A side-effect of the search is that when src is zero, the output is all ones.
+If the second operand is non-zero and the src is zero, the output is a
+copy of the second operand.
 
      # Example
 
@@ -124,11 +142,44 @@ second operand.
 
 Pseudo-code:
 
+    def sof(rd, rs1, rs2):
+        rd = 0
+        setting_mode = rs2 == x0 or (regs[rs2] & 1)
+
+        while i < XLEN:
+            bit = 1<<i
+
+            # only reenable when predicate in use, and bit valid
+            if !setting_mode && rs2 != x0:
+                if (regs[rs2] & bit):
+                    # back into "setting" mode
+                    setting_mode = True
+
+            # skipping mode
+            if !setting_mode:
+                # skip any more 1s
+                if regs[rs1] & bit == 1:
+                    i += 1
+                    continue
+
+            # setting mode, search for 1
+            if regs[rs1] & bit: # found a bit in rs1:
+                setting_mode = False
+                # next loop starts skipping
+            else:
+                regs[rd] |= bit # always set except when search succeeds
+
+            i += 1
+
     def sbf(rd, rs1, rs2):
         rd = 0
+        # start setting if no predicate or if 1st predicate bit set
         setting_mode = rs2 == x0 or (regs[rs2] & 1)
         while i < XLEN:
             bit = 1<<i
+            if rs2 != x0 and (regs[rs2] & bit):
+                # reset searching
+                setting_mode = False
             if setting_mode:
                 if regs[rs1] & bit: # found a bit in rs1: stop setting rd
                     setting_mode = False
@@ -141,6 +192,15 @@ Pseudo-code:
 
 ## sif - set including first bit
 
+Similar to sbf except including the bit which ends a run.  i.e:
+Sets all LSBs leading up to *and including* where an LSB in the src is set,
+and sets zeros following the point where the src bit is found.
+
+The side-effect of when the src is zero is also the same as for sbf:
+output is all 1s if src2 is zero, and output is equal to src2 if src2
+is non-zero.
+
+
      # Example
 
      7 6 5 4 3 2 1 0   Element number
@@ -158,8 +218,43 @@ Pseudo-code:
                        sif a2, a3, a0
      1 1 x x x x 1 1   a2 contents
 
+Pseudo-code:
+
+    def sif(rd, rs1, rs2):
+        rd = 0
+        setting_mode = rs2 == x0 or (regs[rs2] & 1)
+
+        while i < XLEN:
+            bit = 1<<i
+
+            # only reenable when predicate in use, and bit valid
+            if !setting_mode && rs2 != x0:
+                if (regs[rs2] & bit):
+                    # back into "setting" mode
+                    setting_mode = True
+
+            # skipping mode
+            if !setting_mode:
+                # skip any more 1s
+                if regs[rs1] & bit == 1:
+                    i += 1
+                    continue
+
+            # setting mode, search for 1
+            regs[rd] |= bit # always set during search
+            if regs[rs1] & bit: # found a bit in rs1:
+                setting_mode = False
+                # next loop starts skipping
+
+            i += 1
+
 ## sof - set only first bit
 
+Similar to sbf and sif except *only* set the bit which ends a run.
+
+Unlike sbf and sif however, if the src is zero then the output is
+also guaranteed to be zero, irrespective of src2's contents.
+
      # Example
 
      7 6 5 4 3 2 1 0   Element number
@@ -176,3 +271,34 @@ Pseudo-code:
      1 1 0 1 0 1 0 0   a3 contents
                        sof a2, a3, a0
      0 1 x x x x 0 0   a2 contents
+
+Pseudo-code:
+
+    def sof(rd, rs1, rs2):
+        rd = 0
+        setting_mode = rs2 == x0 or (regs[rs2] & 1)
+
+        while i < XLEN:
+            bit = 1<<i
+
+            # only reenable when predicate in use, and bit valid
+            if !setting_mode && rs2 != x0:
+                if (regs[rs2] & bit):
+                    # back into "setting" mode
+                    setting_mode = True
+
+            # skipping mode
+            if !setting_mode:
+                # skip any more 1s
+                if regs[rs1] & bit == 1:
+                    i += 1
+                    continue
+
+            # setting mode, search for 1
+            if regs[rs1] & bit: # found a bit in rs1:
+                regs[rd] |= bit # only set when search succeeds
+                setting_mode = False
+                # next loop starts skipping
+
+            i += 1
+