1 **OBSOLETE SPEC** see [[openpower/sv/bitmanip]]
5 These are bit manipulation opcodes that, if provided, augment SimpleV for
6 the purposes of efficiently accelerating Vector Processing, 3D Graphics
9 The justification for their inclusion in BitManip is identical to the
10 significant justification that went into their inclusion in the
11 RISC-V Vector Extension (under the "Predicate Mask" opcodes section)
14 <https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vector-mask-instructions>
19 SV uses standard integer scalar registers as a predicate bitmask. Therefore,
20 the majority of RISC-V RV32I / RV64I bit-level instructions are perfectly
21 adequate. Some exceptions however present themselves from RVV.
23 ## logical bit-wise instructions
25 These are the available bitwise instructions in RVV:
27 vmand.mm vd, vs2, vs1 # vd[i] = vs2[i].LSB && vs1[i].LSB
28 vmnand.mm vd, vs2, vs1 # vd[i] = !(vs2[i].LSB && vs1[i].LSB)
29 vmandnot.mm vd, vs2, vs1 # vd[i] = vs2[i].LSB && !vs1[i].LSB
30 vmxor.mm vd, vs2, vs1 # vd[i] = vs2[i].LSB ^^ vs1[i].LSB
31 vmor.mm vd, vs2, vs1 # vd[i] = vs2[i].LSB || vs1[i].LSB
32 vmnor.mm vd, vs2, vs1 # vd[i] = !(vs2[i[.LSB || vs1[i].LSB)
33 vmornot.mm vd, vs2, vs1 # vd[i] = vs2[i].LSB || !vs1[i].LSB
34 vmxnor.mm vd, vs2, vs1 # vd[i] = !(vs2[i].LSB ^^ vs1[i].LSB)
36 The ones that exist in scalar RISC-V are:
38 AND rd, rs1, rs2 # rd = rs1 & rs2
39 OR rd, rs1, rs2 # rd = rs1 | rs2
40 XOR rd, rs1, rs2 # rd = rs1 ^ rs2
42 The ones in Bitmanip are:
44 ANDN rd, rs1, rs2 # rd = rs1 & ~rs2
45 ORN rd, rs1, rs2 # rd = rs1 | ~rs2
46 XORN rd, rs1, rs2 # rd = rs1 ^ ~rs2
53 These are currently listed as "pseudo-ops" in BitManip-Draft (0.91)
54 They need to be actual opcodes.
57 TODO: there is an extensive table in RVV of bit-level operations:
59 output instruction pseudoinstruction
61 | 0 | 1 | 2 | 3 | instruction | pseudoinstruction |
62 | - | - | - | - | -------------------------- | ----------------- |
63 | 0 | 0 | 0 | 0 | vmxor.mm vd, vd, vd | vmclr.m vd |
64 | 1 | 0 | 0 | 0 | vmnor.mm vd, src1, src2 | |
65 | 0 | 1 | 0 | 0 | vmandnot.mm vd, src2, src1 | |
66 | 1 | 1 | 0 | 0 | vmnand.mm vd, src1, src1 | vmnot.m vd, src1 |
67 | 0 | 0 | 1 | 0 | vmandnot.mm vd, src1, src2 | |
68 | 1 | 0 | 1 | 0 | vmnand.mm vd, src2, src2 | vmnot.m vd, src2 |
69 | 0 | 1 | 1 | 0 | vmxor.mm vd, src1, src2 | |
70 | 1 | 1 | 1 | 0 | vmnand.mm vd, src1, src2 | |
71 | 0 | 0 | 0 | 1 | vmand.mm vd, src1, src2 | |
72 | 1 | 0 | 0 | 1 | vmxnor.mm vd, src1, src2 | |
73 | 0 | 1 | 0 | 1 | vmand.mm vd, src2, src2 | vmcpy.m vd, src2 |
74 | 1 | 1 | 0 | 1 | vmornot.mm vd, src2, src1 | |
75 | 0 | 0 | 1 | 1 | vmand.mm vd, src1, src1 | vmcpy.m vd, src1 |
76 | 1 | 0 | 1 | 1 | vmornot.mm vd, src1, src2 | |
77 | 1 | 1 | 1 | 1 | vmxnor.mm vd, vd, vd | vmset.m vd |
79 ## pcnt - population count
85 unsigned int v; // count the number of bits set in v
86 unsigned int c; // c accumulates the total bits set in v
89 v &= v - 1; // clear the least significant bit set
92 This instruction is present in BitManip.
94 ## ffirst - find first bit
96 finds the first bit set as an index.
101 uint_xlen_t clz(uint_xlen_t rs1)
103 for (int count = 0; count < XLEN; count++)
104 if ((rs1 << count) >> (XLEN - 1))
109 This is similar but not identical to BitManip "CLZ". CLZ returns XLEN when no bits are set, whereas RVV returns -1.
111 ## sbf - set before first bit
113 Sets all LSBs leading up to (excluding) where an LSB in the src is set,
114 and sets zeros including and following the src bit found.
115 If the second operand is non-zero, this process continues the search
116 (in the same LSB to MSB order) beginning each time (including the first time)
117 from where 1s are set in the second operand.
119 A side-effect of the search is that when src is zero, the output is all ones.
120 If the second operand is non-zero and the src is zero, the output is a
121 copy of the second operand.
125 7 6 5 4 3 2 1 0 Bit number
127 1 0 0 1 0 1 0 0 a3 contents
129 0 0 0 0 0 0 1 1 a2 contents
131 1 0 0 1 0 1 0 1 a3 contents
135 0 0 0 0 0 0 0 0 a3 contents
139 1 1 0 0 0 0 1 1 a0 vcontents
140 1 0 0 1 0 1 0 0 a3 contents
142 0 1 0 0 0 0 1 1 a2 contents
146 def sof(rd, rs1, rs2):
148 setting_mode = rs2 == x0 or (regs[rs2] & 1)
153 # only reenable when predicate in use, and bit valid
154 if !setting_mode && rs2 != x0:
155 if (regs[rs2] & bit):
156 # back into "setting" mode
162 if regs[rs1] & bit == 1:
166 # setting mode, search for 1
167 if regs[rs1] & bit: # found a bit in rs1:
169 # next loop starts skipping
171 regs[rd] |= bit # always set except when search succeeds
175 def sbf(rd, rs1, rs2):
177 # start setting if no predicate or if 1st predicate bit set
178 setting_mode = rs2 == x0 or (regs[rs2] & 1)
181 if rs2 != x0 and (regs[rs2] & bit):
185 if regs[rs1] & bit: # found a bit in rs1: stop setting rd
189 else if rs2 != x0: # searching mode
190 if (regs[rs2] & bit):
191 setting_mode = True # back into "setting" mode
194 ## sif - set including first bit
196 Similar to sbf except including the bit which ends a run. i.e:
197 Sets all LSBs leading up to *and including* where an LSB in the src is set,
198 and sets zeros following the point where the src bit is found.
200 The side-effect of when the src is zero is also the same as for sbf:
201 output is all 1s if src2 is zero, and output is equal to src2 if src2
207 7 6 5 4 3 2 1 0 Element number
209 1 0 0 1 0 1 0 0 a3 contents
211 0 0 0 0 0 1 1 1 a2 contents
213 1 0 0 1 0 1 0 1 a3 contents
217 1 1 0 0 0 0 1 1 a0 vcontents
218 1 0 0 1 0 1 0 0 a3 contents
220 1 1 x x x x 1 1 a2 contents
224 def sif(rd, rs1, rs2):
226 setting_mode = rs2 == x0 or (regs[rs2] & 1)
231 # only reenable when predicate in use, and bit valid
232 if !setting_mode && rs2 != x0:
233 if (regs[rs2] & bit):
234 # back into "setting" mode
240 if regs[rs1] & bit == 1:
244 # setting mode, search for 1
245 regs[rd] |= bit # always set during search
246 if regs[rs1] & bit: # found a bit in rs1:
248 # next loop starts skipping
252 ## sof - set only first bit
254 Similar to sbf and sif except *only* set the bit which ends a run.
256 Unlike sbf and sif however, if the src is zero then the output is
257 also guaranteed to be zero, irrespective of src2's contents.
261 7 6 5 4 3 2 1 0 Element number
263 1 0 0 1 0 1 0 0 a3 contents
265 0 0 0 0 0 1 0 0 a2 contents
267 1 0 0 1 0 1 0 1 a3 contents
271 1 1 0 0 0 0 1 1 a0 vcontents
272 1 1 0 1 0 1 0 0 a3 contents
274 0 1 x x x x 0 0 a2 contents
278 def sof(rd, rs1, rs2):
280 setting_mode = rs2 == x0 or (regs[rs2] & 1)
285 # only reenable when predicate in use, and bit valid
286 if !setting_mode && rs2 != x0:
287 if (regs[rs2] & bit):
288 # back into "setting" mode
294 if regs[rs1] & bit == 1:
298 # setting mode, search for 1
299 if regs[rs1] & bit: # found a bit in rs1:
300 regs[rd] |= bit # only set when search succeeds
302 # next loop starts skipping