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 |
119 mode is encoded in XO and is 4 bits
123 crrweird: RT, BB, mask.mode
126 n0 = mask[0] & (mode[0] == creg[0])
127 n1 = mask[1] & (mode[1] == creg[1])
128 n2 = mask[2] & (mode[2] == creg[2])
129 n3 = mask[3] & (mode[3] == creg[3])
130 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
131 RT[63] = result # MSB0 numbering, 63 is LSB
137 mtcrweird: BT, RA, mask.mode
140 lsb = reg[63] # MSB0 numbering
141 n0 = mask[0] & (mode[0] == lsb)
142 n1 = mask[1] & (mode[1] == lsb)
143 n2 = mask[2] & (mode[2] == lsb)
144 n3 = mask[3] & (mode[3] == lsb)
145 CR{BT} = n0 || n1 || n2 || n3
149 crweird: BT, BB, mask.mode
152 n0 = mask[0] & (mode[0] == creg[0])
153 n1 = mask[1] & (mode[1] == creg[1])
154 n2 = mask[2] & (mode[2] == creg[2])
155 n3 = mask[3] & (mode[3] == creg[3])
156 CR{BT} = n0 || n1 || n2 || n3
160 crweirder: BFT, BB, mask.mode
163 n0 = mask[0] & (mode[0] == creg[0])
164 n1 = mask[1] & (mode[1] == creg[1])
165 n2 = mask[2] & (mode[2] == creg[2])
166 n3 = mask[3] & (mode[3] == creg[3])
167 BF = BFT[2:4] # select CR
168 bit = BFT[0:1] # select bit of CR
169 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
174 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
175 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
176 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
178 # Vectorised versions
180 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
182 Normally the progression of the SV for-loop would move on to the next register.
183 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.
185 crrweird: RT, BB, mask.mode
192 n0 = mask[0] & (mode[0] == creg[0])
193 n1 = mask[1] & (mode[1] == creg[1])
194 n2 = mask[2] & (mode[2] == creg[2])
195 n3 = mask[3] & (mode[3] == creg[3])
196 # OR or AND to a single bit
197 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
199 # TODO: RT.elwidth override to be also added here
200 # note, yes, really, the CR's elwidth field determines
201 # the bit-packing into the INT!
202 if BB.elwidth == 0b00:
203 # pack 1 result into 64-bit registers
204 iregs[RT+i][0..62] = 0
205 iregs[RT+i][63] = result # sets LSB to result
206 if BB.elwidth == 0b01:
207 # pack 2 results sequentially into INT registers
208 iregs[RT+i//2][0..61] = 0
209 iregs[RT+i//2][63-(i%2)] = result
210 if BB.elwidth == 0b10:
211 # pack 4 results sequentially into INT registers
212 iregs[RT+i//4][0..59] = 0
213 iregs[RT+i//4][63-(i%4)] = result
214 if BB.elwidth == 0b11:
215 # pack 8 results sequentially into INT registers
216 iregs[RT+i//8][0..55] = 0
217 iregs[RT+i//8][63-(i%8)] = result
219 iregs[RT][63-i] = result # results also in scalar INT
223 * in the scalar case the CR-Vector assessment
224 is stored bit-wise starting at the LSB of the
225 destination scalar INT
226 * in the INT-vector case the result is stored in the
227 LSB of each element in the result vector
229 Note that element width overrides are respected on the INT src or destination register, however that it is the CR element-width
230 override that is used to indicate how many bits of CR results
231 are packed/extracted into/from each INT register
233 # v3.1 setbc instructions
235 there are additional setb conditional instructions in v3.1 (p129)
237 RT = (CR[BI] == 1) ? 1 : 0
239 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.
241 # Predication Examples
243 Take the following example:
246 sv.mtcrweird/dm=r10/dz cr8.v, 0, 0b0011.0000
248 Here, RA is zero, so the source input is zero. The destination
249 is CR Field 8, and the destination predicate mask indicates
250 to target the first two elements. Destination predicate zeroing is
251 enabled, and the destination predicate is only set in the 2nd bit.
252 mask is 0b0011, mode is all zeros.
254 Let us first consider what should go into element 0 (CR Field 8):
256 * The destination predicate bit is zero, and zeroing is enabled.
257 * Therefore, what is in the source is irrelevant: the result must
259 * Therefore all four bits of CR Field 8 are therefore set to zero.
261 Now the second element, CR Field 9 (CR9):
263 * Bit 2 of the destination predicate, r10, is 1. Therefore the computation
264 of the result is relevant.
265 * RA is zero therefore bit 2 is zero. mask is 0b0011 and mode is 0b0000
266 * When calculating n0 thru n3 we get n0=1, n1=2, n2=0, n3=0
267 * Therefore, CR9 is set (using LSB0 ordering) to 0b0011, i.e. to mask.
269 It should be clear that this instruction uses bits of the integer
270 predicate to decide whether to set CR Fields to `(mask & ~mode)`
271 or to zero. Thus, in effect, it is the integer predicate that has
272 been copied into the CR Fields.
274 By using twin predication, zeroing, and inversion (sm=~r3, dm=r10) for example, it becomes possible to combine two Integers together in
275 order to set bits in CR Fields.
276 Likewise there are dozens of ways that CR Predicates can be used, on the
277 same sv.mtcrweird instruction.