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 where an LSB in the src is set. If the second
114 operand is non-zero, this process begins each time (including the first time) from where 1s are set in the
119 7 6 5 4 3 2 1 0 Bit number
121 1 0 0 1 0 1 0 0 a3 contents
123 0 0 0 0 0 0 1 1 a2 contents
125 1 0 0 1 0 1 0 1 a3 contents
129 0 0 0 0 0 0 0 0 a3 contents
133 1 1 0 0 0 0 1 1 a0 vcontents
134 1 0 0 1 0 1 0 0 a3 contents
136 0 1 0 0 0 0 1 1 a2 contents
140 def sbf(rd, rs1, rs2):
142 # start setting if no predicate or if 1st predicate bit set
143 setting_mode = rs2 == x0 or (regs[rs2] & 1)
146 if rs2 != x0 and (regs[rs2] & bit):
150 if regs[rs1] & bit: # found a bit in rs1: stop setting rd
154 else if rs2 != x0: # searching mode
155 if (regs[rs2] & bit):
156 setting_mode = True # back into "setting" mode
159 ## sif - set including first bit
161 Similar to sbf except including the bit which ends a run.
165 7 6 5 4 3 2 1 0 Element number
167 1 0 0 1 0 1 0 0 a3 contents
169 0 0 0 0 0 1 1 1 a2 contents
171 1 0 0 1 0 1 0 1 a3 contents
175 1 1 0 0 0 0 1 1 a0 vcontents
176 1 0 0 1 0 1 0 0 a3 contents
178 1 1 x x x x 1 1 a2 contents
182 def sif(rd, rs1, rs2):
184 # start setting if no predicate or if 1st predicate bit set
185 setting_mode = rs2 == x0 or (regs[rs2] & 1)
188 if rs2 != x0 and (regs[rs2] & bit):
193 if regs[rs1] & bit: # found a bit in rs1: stop setting rd
195 else if rs2 != x0: # searching mode
196 if (regs[rs2] & bit):
197 setting_mode = True # back into "setting" mode
200 ## sof - set only first bit
204 7 6 5 4 3 2 1 0 Element number
206 1 0 0 1 0 1 0 0 a3 contents
208 0 0 0 0 0 1 0 0 a2 contents
210 1 0 0 1 0 1 0 1 a3 contents
214 1 1 0 0 0 0 1 1 a0 vcontents
215 1 1 0 1 0 1 0 0 a3 contents
217 0 1 x x x x 0 0 a2 contents
221 def sof(rd, rs1, rs2):
223 setting_mode = rs2 == x0 or (regs[rs2] & 1)
227 if regs[rs1] & bit: # found a bit in rs1:
228 # set bit, exit setting mode immediately
231 # Now skip any more 1s
236 if regs[rs1] & bit == 0:
240 # only reenable when predicate in use, and bit valid
241 if (regs[rs2] & bit):
242 setting_mode = True # back into "setting" mode