3 # New instructions for CR/INT predication
7 * main bugreport for crweirds
8 <https://bugs.libre-soc.org/show_bug.cgi?id=533>
9 * <https://bugs.libre-soc.org/show_bug.cgi?id=527>
10 * <https://bugs.libre-soc.org/show_bug.cgi?id=569>
11 * <https://bugs.libre-soc.org/show_bug.cgi?id=558#c47>
15 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, consequently the entire Vector ISA is available for use in creating masks. This is not practical for SV given the premise to minimise adding of instructions.
17 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.
19 The opportunity is therefore taken to also augment CR logical arithmetic as well, using a mask-based paradigm that takes into consideration multiple bits of each CR (eq/lt/gt/ov). v3.0B Scalar CR instructions (crand, crxor) only allow a single bit calculation.
23 * CR-based instructions that perform simple AND/OR/XOR from all four bits
24 of a CR to create a single bit value (0/1) in an integer register
25 * Inverse of the same, taking a single bit value (0/1) from an integer
26 register to selectively target all four bits of a given CR
27 * CR-to-CR version of the same, allowing multiple bits to be AND/OR/XORed
29 * Vectorisation of the same
33 * To provide a merged version of what is currently a multi-sequence of
34 CR operations (crand, cror, crxor) with mfcr and mtcrf, reducing
36 * To provide a vectorised version of the same, suitable for advanced
41 * mtcrweird when RA=0 is a means to set or clear arbitrary CR bits
42 using immediates embedded within the instruction.
44 (Twin) Predication interactions:
46 * 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
47 * CR twin predication with zeroing is likewise a way to interact with the incoming integer
49 this gets particularly powerful if data-dependent predication is also enabled. further explanation is below.
53 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.
54 In [[isa/sprset]] we see the pseudocode for `mtcrf` for example:
60 CR[4*n+32:4*n+35] <- (RS)[4*n+32:4*n+35]
62 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:
66 predbit = (r3)[63-i] # IBM MSB0 spec sigh
68 # completely incomprehensible vertical numbering
69 n = (7-(i%8)) | (i & ~0x7) # total mess
70 CRpredicate = CR{n} # select CR0, CR1, ....
71 predbit = CRpredicate[offs] # select eq..ov bit
73 Which is nowhere close to matching the straightforward obvious case:
77 predbit = (r3)[63-i] # IBM MSB0 spec sigh
79 CRpredicate = CR{i} # start at CR0, work up
80 predbit = CRpredicate[offs]
82 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.
84 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).
86 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:
89 CR[4*n+32+offs] <- (RS)[63-n]
91 Assuming that `offs` is set to `CR.eq` this results in:
93 * Arithmetic bit 0 (the LSB, numbered 63 in IBM MSB0 terminology)
94 of RS being inserted into CR0.eq
95 * Arithmetic bit 1 of RS being inserted into CR1.eq
97 * Arithmetic bit 7 of RS being inserted into CR7.eq
99 To clarify, then: all instructions below do **NOT** follow the IBM convention, they follow the natural sequence CR0 CR1 instead, using `CR{fieldnum}` to refer to the individual CR Fields. However it is critically important to note that the offsets **in** a CR field
100 (`CR.eq` for example) continue to follow the v3.0B definition and convention.
103 # Instruction form and pseudocode
105 Note that `CR{n}` refers to `CR0` when `n=0` and consequently, for CR0-7, is defined, in v3.0B pseudocode, as:
107 CR{7-n} = CR[32+n*4:35+n*4]
111 |0-5|6-10 |11|12-15|16-18|19-20|21-25 |26-30 |31|name |
112 |---|---- |--|-----|-----|-----|----- |----- |--|---- |
113 |19 |RT | |mask |BB | |XO[0:4]|XO[5:9]|/ | |
114 |19 |RT |0 |mask |BB | 0 M |XO[0:4]|0 mode |Rc|crrweird |
115 |19 |RA |1 |mask |BT | 0 / |XO[0:4]|0 mode |/ |mtcrweird |
116 |19 |BT //|0 |mask |BB | 1 / |XO[0:4]|0 mode |/ |crweird |
117 |19 |BFT |1 |mask |BB | 1 M |XO[0:4]|0 mode |/ |crweirder |
121 mode is encoded in XO and is 4 bits
125 crrweird: RT, BB, mask.mode
128 n0 = mask[0] & (mode[0] == creg[0])
129 n1 = mask[1] & (mode[1] == creg[1])
130 n2 = mask[2] & (mode[2] == creg[2])
131 n3 = mask[3] & (mode[3] == creg[3])
132 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
133 RT[63] = result # MSB0 numbering, 63 is LSB
137 This is a [[openpower/sv/normal]] SVP64 type operation and as
138 such can use Rc=1 and RC1 Data-dependent Mode capability
144 mtcrweird: BT, RA, mask.mode
147 lsb = reg[63] # MSB0 numbering
148 n0 = mask[0] & (mode[0] == lsb)
149 n1 = mask[1] & (mode[1] == lsb)
150 n2 = mask[2] & (mode[2] == lsb)
151 n3 = mask[3] & (mode[3] == lsb)
152 CR{BT} = n0 || n1 || n2 || n3
154 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
155 3-bit Data-dependent and 3-bit Predicate-result capability
162 crweird: BT, BB, mask.mode
165 n0 = mask[0] & (mode[0] == creg[0])
166 n1 = mask[1] & (mode[1] == creg[1])
167 n2 = mask[2] & (mode[2] == creg[2])
168 n3 = mask[3] & (mode[3] == creg[3])
169 CR{BT} = n0 || n1 || n2 || n3
171 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
172 3-bit Data-dependent and 3-bit Predicate-result capability
179 crweirder: BFT, BB, mask.mode
182 n0 = mask[0] & (mode[0] == creg[0])
183 n1 = mask[1] & (mode[1] == creg[1])
184 n2 = mask[2] & (mode[2] == creg[2])
185 n3 = mask[3] & (mode[3] == creg[3])
186 BF = BFT[2:4] # select CR
187 bit = BFT[0:1] # select bit of CR
188 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
191 This is a [[openpower/sv/cr_ops]] SVP64 type operation that has
192 5-bit Data-dependent and 5-bit Predicate-result capability
195 **Example Pseudo-ops:**
197 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
198 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
199 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
201 # Vectorised versions
203 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
205 Normally the progression of the SV for-loop would move on to the next register.
206 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.
208 crrweird: RT, BB, mask.mode
215 n0 = mask[0] & (mode[0] == creg[0])
216 n1 = mask[1] & (mode[1] == creg[1])
217 n2 = mask[2] & (mode[2] == creg[2])
218 n3 = mask[3] & (mode[3] == creg[3])
219 # OR or AND to a single bit
220 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
222 # TODO: RT.elwidth override to be also added here
223 # note, yes, really, the CR's elwidth field determines
224 # the bit-packing into the INT!
225 if BB.elwidth == 0b00:
226 # pack 1 result into 64-bit registers
227 iregs[RT+i][0..62] = 0
228 iregs[RT+i][63] = result # sets LSB to result
229 if BB.elwidth == 0b01:
230 # pack 2 results sequentially into INT registers
231 iregs[RT+i//2][0..61] = 0
232 iregs[RT+i//2][63-(i%2)] = result
233 if BB.elwidth == 0b10:
234 # pack 4 results sequentially into INT registers
235 iregs[RT+i//4][0..59] = 0
236 iregs[RT+i//4][63-(i%4)] = result
237 if BB.elwidth == 0b11:
238 # pack 8 results sequentially into INT registers
239 iregs[RT+i//8][0..55] = 0
240 iregs[RT+i//8][63-(i%8)] = result
242 iregs[RT][63-i] = result # results also in scalar INT
246 * in the scalar case the CR-Vector assessment
247 is stored bit-wise starting at the LSB of the
248 destination scalar INT
249 * in the INT-vector case the result is stored in the
250 LSB of each element in the result vector
252 Note that element width overrides are respected on the INT src or destination register, however that it is the CR element-width
253 override that is used to indicate how many bits of CR results
254 are packed/extracted into/from each INT register
256 # v3.1 setbc instructions
258 there are additional setb conditional instructions in v3.1 (p129)
260 RT = (CR[BI] == 1) ? 1 : 0
262 which also negate that, and also return -1 / 0. these are similar to crweird but not the same purpose. most notable is that crweird acts on CR fields rather than the entire 32 bit CR.
264 # Predication Examples
266 Take the following example:
269 sv.mtcrweird/dm=r10/dz cr8.v, 0, 0b0011.0000
271 Here, RA is zero, so the source input is zero. The destination
272 is CR Field 8, and the destination predicate mask indicates
273 to target the first two elements. Destination predicate zeroing is
274 enabled, and the destination predicate is only set in the 2nd bit.
275 mask is 0b0011, mode is all zeros.
277 Let us first consider what should go into element 0 (CR Field 8):
279 * The destination predicate bit is zero, and zeroing is enabled.
280 * Therefore, what is in the source is irrelevant: the result must
282 * Therefore all four bits of CR Field 8 are therefore set to zero.
284 Now the second element, CR Field 9 (CR9):
286 * Bit 2 of the destination predicate, r10, is 1. Therefore the computation
287 of the result is relevant.
288 * RA is zero therefore bit 2 is zero. mask is 0b0011 and mode is 0b0000
289 * When calculating n0 thru n3 we get n0=1, n1=2, n2=0, n3=0
290 * Therefore, CR9 is set (using LSB0 ordering) to 0b0011, i.e. to mask.
292 It should be clear that this instruction uses bits of the integer
293 predicate to decide whether to set CR Fields to `(mask & ~mode)`
294 or to zero. Thus, in effect, it is the integer predicate that has
295 been copied into the CR Fields.
297 By using twin predication, zeroing, and inversion (sm=~r3, dm=r10) for example, it becomes possible to combine two Integers together in
298 order to set bits in CR Fields.
299 Likewise there are dozens of ways that CR Predicates can be used, on the
300 same sv.mtcrweird instruction.