have to now add LD/ST-update instructions to list of explicit-allowed
[openpower-isa.git] / src / openpower / fpscr.py
1 # SPDX-License-Identifier: LGPLv3+
2 # Funded by NLnet https://nlnet.nl/
3
4 # XXX TODO: get this into openpower/consts.py instead.
5 # create the layout from an auto-created Enum FPSCRb
6 """ Record for FPSCR as defined in
7 Power ISA v3.1B Book I section 4.2.2 page 136(162)
8
9 FPSCR fields in MSB0:
10
11 |Bits |Mnemonic | Description |
12 |-----|---------|-------------------------------------------------------------|
13 |0:28 |   | Reserved |
14 |29:31| DRN | Decimal Rounding Mode |
15 |32 | FX | FP Exception Summary |
16 |33 | FEX | FP Enabled Exception Summary |
17 |34 | VX | FP Invalid Operation Exception Summary |
18 |35 | OX | FP Overflow Exception |
19 |36 | UX | FP Underflow Exception |
20 |37 | ZX | FP Zero Divide Exception |
21 |38 | XX | FP Inexact Exception |
22 |39 | VXSNAN | FP Invalid Operation Exception (SNaN) |
23 |40 | VXISI | FP Invalid Operation Exception (∞ - ∞) |
24 |41 | VXIDI | FP Invalid Operation Exception (∞ ÷ ∞) |
25 |42 | VXZDZ | FP Invalid Operation Exception (0 ÷ 0) |
26 |43 | VXIMZ | FP Invalid Operation Exception (∞ × 0) |
27 |44 | VXVC | FP Invalid Operation Exception (Invalid Compare) |
28 |45 | FR | FP Fraction Rounded |
29 |46 | FI | FP Fraction Inexact |
30 |47:51| FPRF | FP Result Flags |
31 |47 | C | FP Result Class Descriptor |
32 |48:51| FPCC | FP Condition Code |
33 |48 | FL | FP Less Than or Negative |
34 |49 | FG | FP Greater Than or Positive |
35 |50 | FE | FP Equal or Zero |
36 |51 | FU | FP Unordered or NaN |
37 |52 |   | Reserved |
38 |53 | VXSOFT | FP Invalid Operation Exception (Software-Defined Condition) |
39 |54 | VXSQRT | FP Invalid Operation Exception (Invalid Square Root) |
40 |55 | VXCVI | FP Invalid Operation Exception (Invalid Integer Convert) |
41 |56 | VE | FP Invalid Operation Exception Enable |
42 |57 | OE | FP Overflow Exception Enable |
43 |58 | UE | FP Underflow Exception Enable |
44 |59 | ZE | FP Zero Divide Exception Enable |
45 |60 | XE | FP Inexact Exception Enable |
46 |61 | NI | FP Non-IEEE Mode |
47 |62:63| RN | FP Rounding Control |
48 """
49
50 from nmigen import Record
51 from copy import deepcopy
52 from openpower.util import log
53 from openpower.decoder.selectable_int import (
54 FieldSelectableInt, SelectableInt)
55
56
57 class FPSCRRecord(Record):
58 layout = [("RN", 2),
59 ("NI", 1),
60 ("XE", 1),
61 ("ZE", 1),
62 ("UE", 1),
63 ("OE", 1),
64 ("VE", 1),
65 ("VXCVI", 1),
66 ("VXSQRT", 1),
67 ("VXSOFT", 1),
68 ("rsvd1", 1),
69 ("FPRF", [
70 ("FPCC", [
71 ("FU", 1),
72 ("FE", 1),
73 ("FG", 1),
74 ("FL", 1),
75 ]),
76 ("C", 1),
77 ]),
78 ("FI", 1),
79 ("FR", 1),
80 ("VXVC", 1),
81 ("VXIMZ", 1),
82 ("VXZDZ", 1),
83 ("VXIDI", 1),
84 ("VXISI", 1),
85 ("VXSNAN", 1),
86 ("XX", 1),
87 ("ZX", 1),
88 ("UX", 1),
89 ("OX", 1),
90 ("VX", 1),
91 ("FEX", 1),
92 ("FX", 1),
93 ("DRN", 3),
94 ("rsvd2", 29),
95 ]
96
97 def __init__(self, name=None):
98 super().__init__(name=name, layout=FPSCRRecord.layout)
99
100
101 class FPSCR_FPRF(FieldSelectableInt):
102 """ special FieldSelectableInt instance to handle assigning strings to
103 FPSCR.FPRF
104
105 Translation Table from:
106 PowerISA v3.1B Book I Section 4.2.2 Page 139(165)
107 Figure 47 Floating-Point Result Flags
108 """
109 TRANSLATION_TABLE = (
110 ("Quiet NaN", 0b10001),
111 ("QNaN", 0b10001),
112 ("- Infinity", 0b01001),
113 ("- Normalized Number", 0b01000),
114 ("- Normal Number", 0b01000),
115 ("- Denormalized Number", 0b11000),
116 ("- Zero", 0b10010),
117 ("+ Zero", 0b00010),
118 ("+ Denormalized Number", 0b10100),
119 ("+ Normalized Number", 0b00100),
120 ("+ Normal Number", 0b00100),
121 ("+ Infinity", 0b00101),
122 )
123 TRANSLATION_TABLE_DICT = {k.casefold(): v for k, v in TRANSLATION_TABLE}
124
125 def eq(self, b):
126 if isinstance(b, str):
127 b = FPSCR_FPRF.TRANSLATION_TABLE_DICT[b.casefold()]
128 super().eq(b)
129
130
131 class FPSCRState(SelectableInt):
132 def __init__(self, value=0):
133 SelectableInt.__init__(self, value, 64)
134 self.fsi = {}
135 offs = 0
136 # set up sub-fields from Record layout
137 self.fsi = {}
138 l = deepcopy(FPSCRRecord.layout)
139 l.reverse()
140 for field, width in l:
141 if field == "FPRF":
142 v = FPSCR_FPRF(self, tuple(range(47, 52)))
143 end = 52
144 else:
145 end = offs + width
146 fs = tuple(range(offs, end))
147 v = FieldSelectableInt(self, fs)
148 self.fsi[field] = v
149 offs = end
150 # extra fields, temporarily explicitly added. TODO nested layout above
151 extras = [
152 (47, "C"),
153 (range(48, 52), "FPCC"),
154 (48, "FL"),
155 (49, "FG"),
156 (50, "FE"),
157 (51, "FU"),
158 ]
159 for offs, field in extras:
160 if isinstance(offs, int):
161 fs = (offs,)
162 else:
163 fs = tuple(offs)
164 v = FieldSelectableInt(self, fs)
165 self.fsi[field] = v
166
167 @property
168 def DRN(self):
169 return self.fsi['DRN'].asint(msb0=True)
170
171 @DRN.setter
172 def DRN(self, value):
173 self.fsi['DRN'].eq(value)
174
175 @property
176 def FX(self):
177 return self.fsi['FX'].asint(msb0=True)
178
179 @FX.setter
180 def FX(self, value):
181 self.fsi['FX'].eq(value)
182
183 @property
184 def FEX(self):
185 return self.fsi['FEX'].asint(msb0=True)
186
187 @FEX.setter
188 def FEX(self, value):
189 self.fsi['FEX'].eq(value)
190
191 @property
192 def VX(self):
193 return self.fsi['VX'].asint(msb0=True)
194
195 @VX.setter
196 def VX(self, value):
197 self.fsi['VX'].eq(value)
198
199 @property
200 def OX(self):
201 return self.fsi['OX'].asint(msb0=True)
202
203 @OX.setter
204 def OX(self, value):
205 self.fsi['OX'].eq(value)
206
207 @property
208 def UX(self):
209 return self.fsi['UX'].asint(msb0=True)
210
211 @UX.setter
212 def UX(self, value):
213 self.fsi['UX'].eq(value)
214
215 @property
216 def ZX(self):
217 return self.fsi['ZX'].asint(msb0=True)
218
219 @ZX.setter
220 def ZX(self, value):
221 self.fsi['ZX'].eq(value)
222
223 @property
224 def XX(self):
225 return self.fsi['XX'].asint(msb0=True)
226
227 @XX.setter
228 def XX(self, value):
229 self.fsi['XX'].eq(value)
230
231 @property
232 def VXSNAN(self):
233 return self.fsi['VXSNAN'].asint(msb0=True)
234
235 @VXSNAN.setter
236 def VXSNAN(self, value):
237 self.fsi['VXSNAN'].eq(value)
238
239 @property
240 def VXISI(self):
241 return self.fsi['VXISI'].asint(msb0=True)
242
243 @VXISI.setter
244 def VXISI(self, value):
245 self.fsi['VXISI'].eq(value)
246
247 @property
248 def VXIDI(self):
249 return self.fsi['VXIDI'].asint(msb0=True)
250
251 @VXIDI.setter
252 def VXIDI(self, value):
253 self.fsi['VXIDI'].eq(value)
254
255 @property
256 def VXZDZ(self):
257 return self.fsi['VXZDZ'].asint(msb0=True)
258
259 @VXZDZ.setter
260 def VXZDZ(self, value):
261 self.fsi['VXZDZ'].eq(value)
262
263 @property
264 def VXIMZ(self):
265 return self.fsi['VXIMZ'].asint(msb0=True)
266
267 @VXIMZ.setter
268 def VXIMZ(self, value):
269 self.fsi['VXIMZ'].eq(value)
270
271 @property
272 def VXVC(self):
273 return self.fsi['VXVC'].asint(msb0=True)
274
275 @VXVC.setter
276 def VXVC(self, value):
277 self.fsi['VXVC'].eq(value)
278
279 @property
280 def FR(self):
281 return self.fsi['FR'].asint(msb0=True)
282
283 @FR.setter
284 def FR(self, value):
285 self.fsi['FR'].eq(value)
286
287 @property
288 def FI(self):
289 return self.fsi['FI'].asint(msb0=True)
290
291 @FI.setter
292 def FI(self, value):
293 self.fsi['FI'].eq(value)
294
295 @property
296 def FPRF(self):
297 return self.fsi['FPRF'].asint(msb0=True)
298
299 @FPRF.setter
300 def FPRF(self, value):
301 self.fsi['FPRF'].eq(value)
302
303 @property
304 def C(self):
305 return self.fsi['C'].asint(msb0=True)
306
307 @C.setter
308 def C(self, value):
309 self.fsi['C'].eq(value)
310
311 @property
312 def FPCC(self):
313 return self.fsi['FPCC'].asint(msb0=True)
314
315 @FPCC.setter
316 def FPCC(self, value):
317 self.fsi['FPCC'].eq(value)
318
319 @property
320 def FL(self):
321 return self.fsi['FL'].asint(msb0=True)
322
323 @FL.setter
324 def FL(self, value):
325 self.fsi['FL'].eq(value)
326
327 @property
328 def FG(self):
329 return self.fsi['FG'].asint(msb0=True)
330
331 @FG.setter
332 def FG(self, value):
333 self.fsi['FG'].eq(value)
334
335 @property
336 def FE(self):
337 return self.fsi['FE'].asint(msb0=True)
338
339 @FE.setter
340 def FE(self, value):
341 self.fsi['FE'].eq(value)
342
343 @property
344 def FU(self):
345 return self.fsi['FU'].asint(msb0=True)
346
347 @FU.setter
348 def FU(self, value):
349 self.fsi['FU'].eq(value)
350
351 @property
352 def VXSOFT(self):
353 return self.fsi['VXSOFT'].asint(msb0=True)
354
355 @VXSOFT.setter
356 def VXSOFT(self, value):
357 self.fsi['VXSOFT'].eq(value)
358
359 @property
360 def VXSQRT(self):
361 return self.fsi['VXSQRT'].asint(msb0=True)
362
363 @VXSQRT.setter
364 def VXSQRT(self, value):
365 self.fsi['VXSQRT'].eq(value)
366
367 @property
368 def VXCVI(self):
369 return self.fsi['VXCVI'].asint(msb0=True)
370
371 @VXCVI.setter
372 def VXCVI(self, value):
373 self.fsi['VXCVI'].eq(value)
374
375 @property
376 def VE(self):
377 return self.fsi['VE'].asint(msb0=True)
378
379 @VE.setter
380 def VE(self, value):
381 self.fsi['VE'].eq(value)
382
383 @property
384 def OE(self):
385 return self.fsi['OE'].asint(msb0=True)
386
387 @OE.setter
388 def OE(self, value):
389 self.fsi['OE'].eq(value)
390
391 @property
392 def UE(self):
393 return self.fsi['UE'].asint(msb0=True)
394
395 @UE.setter
396 def UE(self, value):
397 self.fsi['UE'].eq(value)
398
399 @property
400 def ZE(self):
401 return self.fsi['ZE'].asint(msb0=True)
402
403 @ZE.setter
404 def ZE(self, value):
405 self.fsi['ZE'].eq(value)
406
407 @property
408 def XE(self):
409 return self.fsi['XE'].asint(msb0=True)
410
411 @XE.setter
412 def XE(self, value):
413 self.fsi['XE'].eq(value)
414
415 @property
416 def NI(self):
417 return self.fsi['NI'].asint(msb0=True)
418
419 @NI.setter
420 def NI(self, value):
421 self.fsi['NI'].eq(value)
422
423 @property
424 def RN(self):
425 return self.fsi['RN'].asint(msb0=True)
426
427 @RN.setter
428 def RN(self, value):
429 self.fsi['RN'].eq(value)
430
431
432 if __name__ == "__main__":
433 from pprint import pprint
434 print("FPSCRRecord.layout:")
435 pprint(FPSCRRecord.layout)
436 print("FPSCRState.fsi:")
437 pprint(FPSCRState().fsi)
438
439 # quick test of setter/getters
440 fpscr = FPSCRState()
441 fpscr.FPCC = 0b0001
442 print(fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
443 fpscr.FG = 0b1
444 print(fpscr.FPCC, fpscr.FL, fpscr.FG, fpscr.FE, fpscr.FU)
445 fpscr.FPRF = 0b00011
446 print(fpscr.FPRF, fpscr.C)
447 fpscr[63] = 1
448 print(fpscr.RN)