add links, add bitmanip logic ops
[libreriscv.git] / simple_v_extension / specification / bitmanip.mdwn
1 [[!tag standards]]
2
3 # Bitmanip opcodes
4
5 These are bit manipulation opcodes that, if provided, augment SimpleV for
6 the purposes of efficiently accelerating Vector Processing, 3D Graphics
7 and Video Processing.
8
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)
12
13 See
14 <https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#vector-mask-instructions>
15 for details.
16
17 # Predicate Masks
18
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.
22
23 ## logical bit-wise instructions
24
25 These are the available bitwise instructions in RVV:
26
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)
35
36 The ones that exist in scalar RISC-V are:
37
38 AND rd, rs1, rs2 # rd = rs1 & rs2
39 OR rd, rs1, rs2 # rd = rs1 | rs2
40 XOR rd, rs1, rs2 # rd = rs1 ^ rs2
41
42 The ones in Bitmanip are:
43
44 ANDN rd, rs1, rs2 # rd = rs1 & ~rs2
45 ORN rd, rs1, rs2 # rd = rs1 | ~rs2
46 XORN rd, rs1, rs2 # rd = rs1 ^ ~rs2
47
48 This leaves:
49
50 NOR
51 NAND
52
53 These are currently listed as "pseudo-ops" in BitManip-Draft (0.91)
54 They need to be actual opcodes.
55
56
57 TODO: there is an extensive table in RVV of bit-level operations:
58
59 output instruction pseudoinstruction
60
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 |
78
79 ## pcnt - population count
80
81 population-count
82
83 ## ffirst - find first bit
84
85 finds the first bit set as an index.
86
87 ## sbf - set before first bit
88
89 Sets all LSBs leading up to where an LSB in the src is set. If the second
90 operand is non-zero, this process begins each time from where 1s are set in the
91 second operand.
92
93 # Example
94
95 7 6 5 4 3 2 1 0 Bit number
96
97 1 0 0 1 0 1 0 0 a3 contents
98 sbf a2, a3, x0
99 0 0 0 0 0 0 1 1 a2 contents
100
101 1 0 0 1 0 1 0 1 a3 contents
102 sbf a2, a3, x0
103 0 0 0 0 0 0 0 0 a2
104
105 0 0 0 0 0 0 0 0 a3 contents
106 sbf a2, a3, x0
107 1 1 1 1 1 1 1 1 a2
108
109 1 1 0 0 0 0 1 1 a0 vcontents
110 1 0 0 1 0 1 0 0 a3 contents
111 sbf a2, a3, a0
112 0 1 0 0 0 0 1 1 a2 contents
113
114 Pseudo-code:
115
116 def sbf(rd, rs1, rs2):
117 rd = 0
118 setting_mode = rs2 == x0 or (regs[rs2] & 1)
119 while i < XLEN:
120 bit = 1<<i
121 if setting_mode:
122 if regs[rs1] & bit: # found a bit in rs1: stop setting rd
123 setting_mode = False
124 else:
125 regs[rd] |= bit
126 else if rs2 != x0: # searching mode
127 if (regs[rs2] & bit):
128 setting_mode = True # back into "setting" mode
129 i += 1