(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, 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.
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 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.
19
20 Basic concept:
21
22 * CR-based instructions that perform simple AND/OR/XOR from all four bits
23 of a CR to create a single bit value (0/1) in an integer register
24 * Inverse of the same, taking a single bit value (0/1) from an integer
25 register to selectively target all four bits of a given CR
26 * CR-to-CR version of the same, allowing multiple bits to be AND/OR/XORed
27 in one hit.
28 * Vectorisation of the same
29
30 Purpose:
31
32 * To provide a merged version of what is currently a multi-sequence of
33 CR operations (crand, cror, crxor) with mfcr and mtcrf, reducing
34 instruction count.
35 * To provide a vectorised version of the same, suitable for advanced
36 predication
37
38 Side-effects:
39
40 * mtcrweird when RA=0 is a means to set or clear arbitrary CR bits
41 using immediates embedded within the instruction.
42
43 (Twin) Predication interactions:
44
45 * 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
46 * CR twin predication with zeroing is likewise a way to interact with the incoming integer
47
48 this gets particularly powerful if data-dependent predication is also enabled.
49
50 # Bit ordering.
51
52 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.
53 In [[isa/sprset]] we see the pseudocode for `mtcrf` for example:
54
55 mtcrf FXM,RS
56
57 do n = 0 to 7
58 if FXM[n] = 1 then
59 CR[4*n+32:4*n+35] <- (RS)[4*n+32:4*n+35]
60
61 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:
62
63 for i in range(VL):
64 if INTpredmode:
65 predbit = (r3)[63-i] # IBM MSB0 spec sigh
66 else:
67 # completely incomprehensible vertical numbering
68 n = (7-(i%8)) | (i & ~0x7) # total mess
69 CRpredicate = CR{n} # select CR0, CR1, ....
70 predbit = CRpredicate[offs] # select eq..ov bit
71
72 Which is nowhere close to matching the straightforward obvious case:
73
74 for i in range(VL):
75 if INTpredmode:
76 predbit = (r3)[63-i] # IBM MSB0 spec sigh
77 else:
78 CRpredicate = CR{i} # start at CR0, work up
79 predbit = CRpredicate[offs]
80
81 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.
82
83 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).
84
85 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:
86
87 do n = 0 to 7
88 CR[4*n+32+offs] <- (RS)[63-n]
89
90 Assuming that `offs` is set to `CR.eq` this results in:
91
92 * Arithmetic bit 0 (the LSB, numbered 63 in IBM MSB0 terminology)
93 of RS being inserted into CR0.eq
94 * Arithmetic bit 1 of RS being inserted into CR1.eq
95 * ...
96 * Arithmetic bit 7 of RS being inserted into CR7.eq
97
98 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
99 (`CR.eq` for example) continue to follow the v3.0B definition and convention.
100
101
102 # Instruction form and pseudocode
103
104 Note that `CR{n}` refers to `CR0` when `n=0` and consequently, for CR0-7, is defined, in v3.0B pseudocode, as:
105
106 CR{7-n} = CR[32+n*4:35+n*4]
107
108 Instruction format:
109
110 | 0-5 | 6-10 | 11 | 12-15 | 16-18 | 19-20 | 21-25 | 26-30 | 31 |
111 | --- | ---- | -- | ----- | ----- | ----- | ----- | ----- | -- |
112 | 19 | RT | | mask | BB | | XO[0:4] | XO[5:9] | / |
113 | 19 | RT | 0 | mask | BB | 0 M | XO[0:4] | 0 mode | Rc |
114 | 19 | RA | 1 | mask | BB | 0 / | XO[0:4] | 0 mode | / |
115 | 19 | BT // | 0 | mask | BB | 1 / | XO[0:4] | 0 mode | / |
116 | 19 | BFT | 1 | mask | BB | 1 M | XO[0:4] | 0 mode | / |
117
118 mode is encoded in XO and is 4 bits
119
120 bit 11=0, bit 19=0
121
122 crrweird: RT, BB, mask.mode
123
124 creg = CR{BB}
125 n0 = mask[0] & (mode[0] == creg[0])
126 n1 = mask[1] & (mode[1] == creg[1])
127 n2 = mask[2] & (mode[2] == creg[2])
128 n3 = mask[3] & (mode[3] == creg[3])
129 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
130 RT[63] = result # MSB0 numbering, 63 is LSB
131 If Rc:
132 CR1 = analyse(RT)
133
134 bit 11=1, bit 19=0
135
136 mtcrweird: RA, BB, mask.mode
137
138 reg = (RA|0)
139 lsb = reg[63] # MSB0 numbering
140 n0 = mask[0] & (mode[0] == lsb)
141 n1 = mask[1] & (mode[1] == lsb)
142 n2 = mask[2] & (mode[2] == lsb)
143 n3 = mask[3] & (mode[3] == lsb)
144 CR{BB} = n0 || n1 || n2 || n3
145
146 bit 11=0, bit 19=1
147
148 crweird: BT, BB, mask.mode
149
150 creg = CR{BB}
151 n0 = mask[0] & (mode[0] == creg[0])
152 n1 = mask[1] & (mode[1] == creg[1])
153 n2 = mask[2] & (mode[2] == creg[2])
154 n3 = mask[3] & (mode[3] == creg[3])
155 CR{BT} = n0 || n1 || n2 || n3
156
157 bit 11=1, bit 19=1
158
159 crweirder: BFT, BB, mask.mode
160
161 creg = CR{BB}
162 n0 = mask[0] & (mode[0] == creg[0])
163 n1 = mask[1] & (mode[1] == creg[1])
164 n2 = mask[2] & (mode[2] == creg[2])
165 n3 = mask[3] & (mode[3] == creg[3])
166 BF = BFT[2:4] # select CR
167 bit = BFT[0:1] # select bit of CR
168 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
169 CR{BF}[bit] = result
170
171 Pseudo-op:
172
173 mtcri BB, mode mtcrweird r0, BB, 0b1111.~mode
174 mtcrset BB, mask mtcrweird r0, BB, mask.0b0000
175 mtcrclr BB, mask mtcrweird r0, BB, mask.0b1111
176
177 # Vectorised versions
178
179 The name "weird" refers to a minor violation of SV rules when it comes to deriving the Vectorised versions of these instructions.
180
181 Normally the progression of the SV for-loop would move on to the next register.
182 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.
183
184 crrweird: RT, BB, mask.mode
185
186 for i in range(VL):
187 if BB.isvec:
188 creg = CR{BB+i}
189 else:
190 creg = CR{BB}
191 n0 = mask[0] & (mode[0] == creg[0])
192 n1 = mask[1] & (mode[1] == creg[1])
193 n2 = mask[2] & (mode[2] == creg[2])
194 n3 = mask[3] & (mode[3] == creg[3])
195 # OR or AND to a single bit
196 result = n0|n1|n2|n3 if M else n0&n1&n2&n3
197 if RT.isvec:
198 if RT.elwidth == 0b00:
199 # pack 1 result into 64-bit registers
200 iregs[RT+i][0..62] = 0
201 iregs[RT+i][63] = result # sets LSB to result
202 if RT.elwidth == 0b01:
203 # pack 2 results sequentially into INT registers
204 iregs[RT+i//2][0..61] = 0
205 iregs[RT+i//2][63-(i%2)] = result
206 if RT.elwidth == 0b10:
207 # pack 4 results sequentially into INT registers
208 iregs[RT+i//4][0..59] = 0
209 iregs[RT+i//4][63-(i%4)] = result
210 if RT.elwidth == 0b11:
211 # pack 8 results sequentially into INT registers
212 iregs[RT+i//8][0..55] = 0
213 iregs[RT+i//8][63-(i%8)] = result
214 else:
215 iregs[RT][63-i] = result # results also in scalar INT
216
217 Note that:
218
219 * in the scalar case the CR-Vector assessment
220 is stored bit-wise starting at the LSB of the
221 destination scalar INT
222 * in the INT-vector case the result is stored in the
223 LSB of each element in the result vector
224
225 Note that element width overrides are respected on the INT src or destination register (but that elwidth overrides on CRs are meaningless)
226
227 # v3.1 setbc instructions
228
229 there are additional setb conditional instructions in v3.1 (p129)
230
231 RT = (CR[BI] == 1) ? 1 : 0
232
233 which also negate that, and also return -1 / 0. these are similar yo crweird but not the same purpose. most notable is that crweird acts on CR fields rather than the entire 32 bit CR.
234
235