(no commit message)
[libreriscv.git] / openpower / sv / cr_int_predication.mdwn
1 [[!tag standards]]
2
3 # New instructions for CR/INT predication
4
5 See:
6
7 * <https://bugs.libre-soc.org/show_bug.cgi?id=533>
8 * <https://bugs.libre-soc.org/show_bug.cgi?id=527>
9 * <https://bugs.libre-soc.org/show_bug.cgi?id=569>
10 * <https://bugs.libre-soc.org/show_bug.cgi?id=558#c47>
11
12 Rationale:
13
14 Condition Registers are conceptually perfect for use as predicate masks, the only problem being that typical Vector ISAs have quite comprehensive mask-based instructions: set-before-first, popcount and much more. In fact many Vector ISAs can use Vectors *as* masks. This is not practical for SV given the premise to minimise adding of instructions.
15
16 With the scalar OpenPOWER v3.0B ISA having already popcnt, cntlz and others normally seen in Vector Mask operations it makes sense to allow *both* scalar integers *and* CR-Vectors to be predicate masks. That in turn means that much more comprehensive interaction between CRs and scalar Integers is required.
17
18 Basic concept:
19
20 * CR-based instructions that perform simple AND/OR/XOR from all four bits
21 of a CR to create a single bit value (0/1) in an integer register
22 * Inverse of the same, taking a single bit value (0/1) from an integer
23 register to selectively target all four bits of a given CR
24 * CR-to-CR version of the same, allowing multiple bits to be AND/OR/XORed
25 in one hit.
26 * Vectorisation of the same
27
28 Purpose:
29
30 * To provide a merged version of what is currently a multi-sequence of
31 CR operations (crand, cror, crxor) with mfcr and mtcrf, reducing
32 instruction count.
33 * To provide a vectorised version of the same, suitable for advanced
34 predication
35
36 Side-effects:
37
38 * mtcrweird when RA=0 is a means to set or clear arbitrary CR bits from immediates
39
40 (Twin) Predication interactions:
41
42 * INT twin predication with zeroing is a way to copy an integer into CRs without necessarily needing the INT register (RA). if it is, it is effectively ANDed (or negate-and-ANDed) with the INT Predicate
43 * CR twin predication with zeroing is likewise a way to interact with the incoming integer
44
45 this gets particularly powerful if data-dependent predication is also enabled.
46
47 # Bit ordering.
48
49 IBM chose MSB0 for the OpenPOWER v3.0B specification. This makes things slightly hair-raising. Our desire initially is therefore to follow the logical progression from the defined behaviour of `mtcr` and `mfcr` etc.
50 In [[isa/sprset]] we see the pseudocode for `mtcrf` for example:
51
52 mtcrf FXM,RS
53
54 do n = 0 to 7
55 if FXM[n] = 1 then
56 CR[4*n+32:4*n+35] <- (RS)[4*n+32:4*n+35]
57
58 This places (according to a mask schedule) `CR0` into MSB0-numbered bits 32-35 of the target Integer register `RS`, these bits of `RS` being the 31st down to the 28th. Unfortunately, even when not Vectorised, this inserts CR numbering inversions on each batch of 8 CRs, massively complicating matters. Predication when using CRs would have to be morphed to this (unacceptably complex) behaviour:
59
60 for i in range(VL):
61 if INTpredmode:
62 predbit = (r3)[63-i] # IBM MSB0 spec sigh
63 else:
64 # completely incomprehensible vertical numbering
65 n = (7-(i%8)) | (i & ~0x7) # total mess
66 CRpredicate = CR{n} # select CR0, CR1, ....
67 predbit = CRpredicate[offs] # select eq..ov bit
68
69 Which is nowhere close to matching the straightforward obvious case:
70
71 for i in range(VL):
72 if INTpredmode:
73 predbit = (r3)[63-i] # IBM MSB0 spec sigh
74 else:
75 CRpredicate = CR{i} # start at CR0, work up
76 predbit = CRpredicate[offs]
77
78 In other words unless we do something about this, when we transfer bits from an Integer Predicate into a Vector of CRs, our numbering of CRs, when enumerating them in a CR Vector, would be **CR7** CR6 CR5.... CR0 **CR15** CR14 CR13... CR8 **CR23** CR22 etc. **not** the more natural and obvious CR0 CR1 ... CR23.
79
80 Therefore the instructions below need to **redefine** the relationship so that CR numbers (CR0, CR1) sequentially match the arithmetically-ordered bits of Integer registers. By `arithmetic` this is deduced from the fact that the instruction `addi r3, r0, 1` will result in the **LSB** (numbered 63 in IBM MSB0 order) of r3 being set to 1 and all other bits set to zero. We therefore refer, below, to this LSB as "Arithmetic bit 0", and it is this bit which is used - defined - as being the first bit used in Integer predication (on element 0).
81
82 Below is some pseudocode that, given a CR offset `offs` to represent `CR.eq` thru to `CR.ov` respectively, will copy the INT predicate bits in the correct order into the first 8 CRs:
83
84 do n = 0 to 7
85 CR[4*n+32+offs] <- (RS)[63-n]
86
87 Assuming that `offs` is set to `CR.eq` this results in:
88
89 * Arithmetic bit 0 (the LSB, numbered 63 in IBM MSB0 terminology)
90 of RS being inserted into CR0.eq
91 * Arithmetic bit 1 of RS being inserted into CR1.eq
92 * ...
93 * Arithmetic bit 7 of RS being inserted into CR7.eq
94
95 To clarify, then: all instructions below do **NOT** follow the IBM convention, they follow the natural sequence CR0 CR1 instead. However it is critically important to note that the offsets **in** a CR (`CR.eq` for example) continue to follow the v3.0B definition and convention.
96
97
98 # Instruction form and pseudocode
99
100 Note that `CR{n}` refers to `CR0` when `n=0` and consequently, for CR0-7, is defined, in v3.0B pseudocode, as:
101
102 CR{7-n} = CR[32+n*4:35+n*4]
103
104 Instruction format:
105
106 | 0-5 | 6-10 | 11 | 12-15 | 16-18 | 19-20 | 21-25 | 26-30 | 31 |
107 | --- | ---- | -- | ----- | ----- | ----- | ----- | ----- | -- |
108 | 19 | RT | | mask | BB | / | XO[0:4] | XO[5:9] | / |
109 | 19 | RT | 0 | mask | BB | 0 / | XO[0:4] | 0 mode | / |
110 | 19 | RA | 1 | mask | BB | 0 / | XO[0:4] | 0 mode | / |
111 | 19 | BT // | 0 | mask | BB | 1 / | XO[0:4] | 0 mode | / |
112 | 19 | BFT | 1 | mask | BB | 1 / | XO[0:4] | 0 mode | / |
113
114 mode is encoded in XO and is 4 bits
115
116 bit 11=0, bit 19=0
117
118 crrweird: RT, BB, mask.mode
119
120 creg = CR{BB}
121 n0 = mask[0] & (mode[0] == creg[0])
122 n1 = mask[1] & (mode[1] == creg[1])
123 n2 = mask[2] & (mode[2] == creg[2])
124 n3 = mask[3] & (mode[3] == creg[3])
125 RT[63] = n0|n1|n2|n3 # MSB0 numbering, 63 is LSB
126
127 bit 11=1, bit 19=0
128
129 mtcrweird: RA, BB, mask.mode
130
131 reg = (RA|0)
132 lsb = reg[63] # MSB0 numbering
133 n0 = mask[0] & (mode[0] == lsb)
134 n1 = mask[1] & (mode[1] == lsb)
135 n2 = mask[2] & (mode[2] == lsb)
136 n3 = mask[3] & (mode[3] == lsb)
137 CR{BB} = n0 || n1 || n2 || n3
138
139 bit 11=0, bit 19=1
140
141 crweird: BT, BB, mask.mode
142
143 creg = CR{BB}
144 n0 = mask[0] & (mode[0] == creg[0])
145 n1 = mask[1] & (mode[1] == creg[1])
146 n2 = mask[2] & (mode[2] == creg[2])
147 n3 = mask[3] & (mode[3] == creg[3])
148 CR{BT} = n0 || n1 || n2 || n3
149
150 bit 11=1, bit 19=1
151
152 crweirder: BFT, BB, mask.mode
153
154 creg = CR{BB}
155 n0 = mask[0] & (mode[0] == creg[0])
156 n1 = mask[1] & (mode[1] == creg[1])
157 n2 = mask[2] & (mode[2] == creg[2])
158 n3 = mask[3] & (mode[3] == creg[3])
159 BF = BFT[2:4] # select CR
160 bit = BFT[0:1] # select bit of CR
161 CR{BF}[bit] = n0|n1|n2|n3
162
163 Pseudo-op:
164
165 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
166 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
167 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
168
169
170 # Vectorised versions
171
172 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
173
174 Normally the progression of the SV for-loop would move on to the next register.
175 Instead however in the scalar case these instructions **remain in the same register** and insert or transfer between **bits** of the scalar integer source or destination.
176
177 crrweird: RT, BB, mask.mode
178
179 for i in range(VL):
180 if BB.isvec:
181 creg = CR{BB+i}
182 else:
183 creg = CR{BB}
184 n0 = mask[0] & (mode[0] == creg[0])
185 n1 = mask[1] & (mode[1] == creg[1])
186 n2 = mask[2] & (mode[2] == creg[2])
187 n3 = mask[3] & (mode[3] == creg[3])
188 if RT.isvec:
189 iregs[RT+i][63] = n0|n1|n2|n3
190 else:
191 iregs[RT][63-i] = n0|n1|n2|n3
192
193 Note that:
194
195 * in the scalar case the CR-Vector assessment
196 is stored bit-wise starting at the LSB of the
197 destination scalar INT
198 * in the INT-vector case the result is stored in the
199 LSB of each element in the result vector
200
201 Note that element width overrides are respected on the INT src or destination register (but that elwidth overrides on CRs are meaningless)