remove fcvttgs since it's redundant
[openpower-isa.git] / src / openpower / decoder / power_enums.py
1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright (C) 2020, 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
3 # Copyright (C) 2020, Michael Nolan
4
5 """Enums used in OpenPOWER ISA decoding
6
7 Note: for SV, from v3.1B p12:
8
9 The designated SPR sandbox consists of non-privileged SPRs 704-719 and
10 privileged SPRs 720-735.
11
12 Note: the option exists to select a much shorter list of SPRs, to reduce
13 regfile size in HDL. this is SPRreduced and the supported list is in
14 get_spr_enum
15 """
16
17 from enum import (
18 auto,
19 Enum as _Enum,
20 unique,
21 )
22 import csv
23 import os
24 from os.path import dirname, join
25 from collections import namedtuple
26 import functools
27
28
29 def find_wiki_dir():
30 filedir = os.path.dirname(os.path.abspath(__file__))
31 basedir = dirname(dirname(dirname(filedir)))
32 tabledir = join(basedir, 'openpower')
33 isatables = join(tabledir, 'isatables')
34 #print ("find_wiki_dir", isatables)
35 return isatables
36
37
38 def find_wiki_file(name):
39 return join(find_wiki_dir(), name)
40
41
42 def get_csv(name):
43 """gets a not-entirely-csv-file-formatted database, which allows comments
44 """
45 file_path = find_wiki_file(name)
46 with open(file_path, 'r') as csvfile:
47 csvfile = filter(lambda row: row[0] !='#', csvfile) # strip "#..."
48 reader = csv.DictReader(csvfile)
49 return list(reader)
50
51
52 # names of the fields in the tables that don't correspond to an enum
53 single_bit_flags = ['inv A', 'inv out',
54 'cry out', 'BR', 'sgn ext', 'rsrv', '32b',
55 'sgn', 'lk', 'sgl pipe']
56
57 # default values for fields in the table
58 default_values = {'unit': "NONE", 'internal op': "OP_ILLEGAL",
59 'in1': "RA", 'in2': 'NONE', 'in3': 'NONE', 'out': 'NONE',
60 'CR in': 'NONE',
61 'ldst len': 'NONE',
62 'upd': '0',
63 'rc': 'NONE', 'cry in': 'ZERO', 'form': 'NONE'}
64
65
66 def get_signal_name(name):
67 if name[0].isdigit():
68 name = "is_" + name
69 return name.lower().replace(' ', '_')
70
71
72 class Enum(_Enum):
73 @classmethod
74 def _missing_(cls, desc):
75 if isinstance(desc, str):
76 try:
77 if desc == "":
78 desc = 0
79 else:
80 desc = int(desc, 0)
81 except ValueError:
82 pass
83 keys = {item.name:item for item in cls}
84 descs = {item.value:item for item in cls}
85 return keys.get(desc, descs.get(desc))
86
87
88 # this corresponds to which Function Unit (pipeline-with-Reservation-Stations)
89 # is to process and guard the operation. they are roughly divided by having
90 # the same register input/output signature (X-Form, etc.)
91
92
93 @unique
94 class Function(Enum):
95 NONE = 0
96 ALU = 1 << 1
97 LDST = 1 << 2
98 SHIFT_ROT = 1 << 3
99 LOGICAL = 1 << 4
100 BRANCH = 1 << 5
101 CR = 1 << 6
102 TRAP = 1 << 7
103 MUL = 1 << 8
104 DIV = 1 << 9
105 SPR = 1 << 10
106 MMU = 1 << 11
107 SV = 1 << 12 # Simple-V https://libre-soc.org/openpower/sv
108 VL = 1 << 13 # setvl
109 FPU = 1 << 14 # FPU
110
111 @functools.lru_cache(maxsize=None)
112 def __repr__(self):
113 counter = 0
114 value = int(self.value)
115 if value != 0:
116 while value != 0:
117 counter += 1
118 value >>= 1
119 counter -= 1
120 desc = f"(1 << {counter})"
121 else:
122 desc = "0"
123 return f"<{self.__class__.__name__}.{self.name}: {desc}>"
124
125
126 @unique
127 class Form(Enum):
128 NONE = 0
129 I = 1
130 B = 2
131 SC = 3
132 D = 4
133 DS = 5
134 DQ = 6
135 DX = 7
136 X = 8
137 XL = 9
138 XFX = 10
139 XFL = 11
140 XX1 = 12
141 XX2 = 13
142 XX3 = 14
143 XX4 = 15
144 XS = 16
145 XO = 17
146 A = 18
147 M = 19
148 MD = 20
149 MDS = 21
150 VA = 22
151 VC = 23
152 VX = 24
153 EVX = 25
154 EVS = 26
155 Z22 = 27
156 Z23 = 28
157 SVL = 29 # Simple-V for setvl instruction
158 SVD = 30 # Simple-V for LD/ST bit-reverse, variant of D-Form
159 SVDS = 31 # Simple-V for LD/ST bit-reverse, variant of DS-Form
160 SVM = 32 # Simple-V SHAPE mode
161 SVM2 = 33 # Simple-V SHAPE2 mode - fits into SVM
162 SVRM = 34 # Simple-V REMAP mode
163 TLI = 35 # ternlogi
164 XB = 36
165 BM2 = 37 # bmask
166 SVI = 38 # Simple-V Index Mode
167 VA2 = 39
168 SVC = 40
169 SVR = 41
170 CRB = 42 # crternlogi / crbinlut
171 MM = 43 # [f]minmax[s][.]
172 CW = 44
173 CW2 = 45
174 DCT = 46 # fdmadds
175
176 # Simple-V svp64 fields https://libre-soc.org/openpower/sv/svp64/
177
178
179 class SVMode(Enum):
180 NONE = 0 # for non-SV instructions only
181 NORMAL = auto()
182 LDST_IDX = auto()
183 LDST_IMM = auto()
184 BRANCH = auto()
185 CROP = auto()
186
187
188 @unique
189 class SVPType(Enum):
190 NONE = 0
191 P1 = 1
192 P2 = 2
193 P2M = 3 # for mixed EXTRA3/3/2 where MASK_SRC is RM[6,7,18]
194
195 @classmethod
196 def _missing_(cls, desc):
197 return {"1P": SVPType.P1, "2P": SVPType.P2, "2PM": SVPType.P2M}.get(desc)
198
199 def __repr__(self):
200 return {
201 SVPType.NONE: "NONE",
202 SVPType.P1: "1P",
203 SVPType.P2: "2P",
204 SVPType.P2M: "2PM",
205 }[self]
206
207
208 @unique
209 class SVEType(Enum):
210 """SVEType
211 * EXTRA2 : 0: [10,11] 1: [12,13] 2: [14,15] 3: [16,17] unused: [18]
212 * EXTRA3 : 0: [10,11,12] 1: [13,14,15] mask: [16,17,18]
213 * EXTRA32: 0: [10,11,12] 1: [13,14,15] 2: [16,17] mask: [6,7,18]
214 """
215 NONE = 0
216 EXTRA2 = 1
217 EXTRA3 = 2
218 EXTRA32 = 3 # mixed EXTRA3 and EXTRA2 using RM bits 6&7 for MASK_SRC
219
220 def __str__(self):
221 return self.name
222
223
224 @unique
225 class SVMaskSrc(Enum):
226 NO = 0
227 EN = 1
228
229 def __str__(self):
230 return self.name
231
232
233 @unique
234 class SVExtra(Enum):
235 NONE = 0
236 Idx0 = 1
237 Idx1 = 2
238 Idx2 = 3
239 Idx3 = 4
240 Idx_1_2 = 5 # due to weird BA/BB for crops
241
242 def __str__(self):
243 return {
244 SVExtra.NONE: "NONE",
245 SVExtra.Idx0: "EXTRA0",
246 SVExtra.Idx1: "EXTRA1",
247 SVExtra.Idx2: "EXTRA2",
248 SVExtra.Idx3: "EXTRA3",
249 SVExtra.Idx_1_2: "EXTRA1/EXTRA2",
250 }[self]
251
252 # Backward compatibility
253 SVEXTRA = SVExtra
254
255
256 class Reg(Enum):
257 NONE = auto()
258 RA = auto()
259 RA_OR_ZERO = auto()
260 RB = auto()
261 RC = auto()
262 RS = auto()
263 RT = auto()
264 RT_OR_ZERO = auto()
265 FRA = auto()
266 FRB = auto()
267 FRC = auto()
268 FRS = auto()
269 FRT = auto()
270 CR = auto()
271 CR0 = auto()
272 CR1 = auto()
273 BF = auto()
274 BFA = auto()
275 BA = auto()
276 BB = auto()
277 BC = auto()
278 BI = auto()
279 BT = auto()
280 BFT = auto()
281 WHOLE_REG = auto()
282 SPR = auto()
283 RSp = auto()
284 RTp = auto()
285 FRAp = auto()
286 FRBp = auto()
287 FRSp = auto()
288 FRTp = auto()
289
290 def __str__(self):
291 return self.name
292
293 @classmethod
294 def _missing_(cls, desc):
295 selectors = (
296 In1Sel, In2Sel, In3Sel, CRInSel, CRIn2Sel,
297 OutSel, CROutSel,
298 )
299 if isinstance(desc, selectors):
300 return cls.__members__.get(desc.name)
301
302 return cls.__members__.get(desc)
303
304 @property
305 def alias(self):
306 alias = {
307 Reg.RSp: Reg.RS,
308 Reg.RTp: Reg.RT,
309 Reg.FRAp: Reg.FRA,
310 Reg.FRBp: Reg.FRB,
311 Reg.FRSp: Reg.FRS,
312 Reg.FRTp: Reg.FRT,
313 }.get(self)
314 if alias is not None:
315 return alias
316
317 alias = {
318 Reg.RA_OR_ZERO: Reg.RA,
319 Reg.RT_OR_ZERO: Reg.RT,
320 }.get(self)
321 if alias is not None:
322 return alias
323
324 return self
325
326 @property
327 def or_zero(self):
328 return (self in (
329 Reg.RA_OR_ZERO,
330 Reg.RT_OR_ZERO,
331 ))
332
333 @property
334 def pair(self):
335 return (self in (
336 Reg.RSp,
337 Reg.RTp,
338 Reg.FRAp,
339 Reg.FRBp,
340 Reg.FRSp,
341 Reg.FRTp,
342 ))
343
344
345 @unique
346 class SVP64PredMode(Enum):
347 ALWAYS = 0
348 INT = 1
349 CR = 2
350 RC1 = 3
351
352
353 @unique
354 class SVP64PredInt(Enum):
355 ALWAYS = 0b000
356 R3_UNARY = 0b001
357 R3 = 0b010
358 R3_N = 0b011
359 R10 = 0b100
360 R10_N = 0b101
361 R30 = 0b110
362 R30_N = 0b111
363
364 @classmethod
365 def _missing_(cls, desc):
366 if isinstance(desc, str):
367 value = desc
368 values = {
369 "^r3": cls.R3_UNARY,
370 "r3": cls.R3,
371 "~r3": cls.R3_N,
372 "r10": cls.R10,
373 "~r10": cls.R10_N,
374 "r30": cls.R30,
375 "~r30": cls.R30_N,
376 }
377 if value.startswith("~"):
378 value = f"~{value[1:].strip()}"
379 elif "<<" in value: # 1 << r3
380 (lhs, _, rhs) = value.partition("<<")
381 lhs = lhs.strip().lower()
382 rhs = rhs.strip().lower()
383 if (lhs == "1") and (rhs in ("r3", "%r3")):
384 value = "^r3"
385
386 return values.get(value)
387
388 return super()._missing_(desc)
389
390 def __str__(self):
391 return {
392 self.__class__.ALWAYS: "",
393 self.__class__.R3_UNARY: "^r3",
394 self.__class__.R3: "r3",
395 self.__class__.R3_N: "~r3",
396 self.__class__.R10: "r10",
397 self.__class__.R10_N: "~r10",
398 self.__class__.R30: "r30",
399 self.__class__.R30_N: "~r30",
400 }[self]
401
402 def __repr__(self):
403 return f"{self.__class__.__name__}({str(self)})"
404
405 def __int__(self):
406 return self.value
407
408 @property
409 def mode(self):
410 return SVP64PredMode.INT
411
412 @property
413 def inv(self):
414 return (self.value & 0b1)
415
416 @property
417 def state(self):
418 return (self.value >> 1)
419
420
421 class SVP64PredCR(Enum):
422 LT = 0
423 GE = 1
424 NL = GE
425 GT = 2
426 LE = 3
427 NG = LE
428 EQ = 4
429 NE = 5
430 SO = 6
431 UN = SO
432 NS = 7
433 NU = NS
434
435 @classmethod
436 def _missing_(cls, desc):
437 if isinstance(desc, str):
438 name = desc.upper()
439 return cls.__members__.get(name)
440
441 return super()._missing_(desc)
442
443 def __int__(self):
444 return self.value
445
446 @property
447 def mode(self):
448 return SVP64PredMode.CR
449
450 @property
451 def inv(self):
452 return (self.value & 0b1)
453
454 @property
455 def state(self):
456 return (self.value >> 1)
457
458
459 @unique
460 class SVP64PredRC1(Enum):
461 RC1 = 0
462 RC1_N = 1
463
464 @classmethod
465 def _missing_(cls, desc):
466 return {
467 "RC1": SVP64PredRC1.RC1,
468 "~RC1": SVP64PredRC1.RC1_N,
469 }.get(desc)
470
471 def __int__(self):
472 return 1
473
474 @property
475 def mode(self):
476 return SVP64PredMode.RC1
477
478 @property
479 def inv(self):
480 return (self is SVP64PredRC1.RC1_N)
481
482 @property
483 def state(self):
484 return 1
485
486
487 class SVP64Pred(Enum):
488 ALWAYS = SVP64PredInt.ALWAYS
489 R3_UNARY = SVP64PredInt.R3_UNARY
490 R3 = SVP64PredInt.R3
491 R3_N = SVP64PredInt.R3_N
492 R10 = SVP64PredInt.R10
493 R10_N = SVP64PredInt.R10_N
494 R30 = SVP64PredInt.R30
495 R30_N = SVP64PredInt.R30_N
496
497 LT = SVP64PredCR.LT
498 GE = SVP64PredCR.GE
499 GT = SVP64PredCR.GT
500 LE = SVP64PredCR.LE
501 EQ = SVP64PredCR.EQ
502 NE = SVP64PredCR.NE
503 SO = SVP64PredCR.SO
504 NS = SVP64PredCR.NS
505
506 RC1 = SVP64PredRC1.RC1
507 RC1_N = SVP64PredRC1.RC1_N
508
509 @classmethod
510 def _missing_(cls, desc):
511 if isinstance(desc, str):
512 values = {item.value:item for item in cls}
513 for subcls in (SVP64PredInt, SVP64PredCR, SVP64PredRC1):
514 try:
515 return values.get(subcls(desc))
516 except ValueError:
517 pass
518 return None
519
520 return super()._missing_(desc)
521
522 def __int__(self):
523 return int(self.value)
524
525 @property
526 def mode(self):
527 return self.value.mode
528
529 @property
530 def inv(self):
531 return self.value.inv
532
533 @property
534 def state(self):
535 return self.value.state
536
537
538 @unique
539 class SVP64RMMode(Enum):
540 NORMAL = 0
541 MAPREDUCE = 1
542 FFIRST = 2
543 SATURATE = 3
544 BRANCH = 5
545
546
547 @unique
548 class SVP64BCPredMode(Enum):
549 NONE = 0
550 MASKZERO = 1
551 MASKONE = 2
552
553
554 @unique
555 class SVP64BCVLSETMode(Enum):
556 NONE = 0
557 VL_INCL = 1
558 VL_EXCL = 2
559
560
561 # note that these are chosen to be exactly the same as
562 # SVP64 RM bit 4. ALL=1 => bit4=1
563 @unique
564 class SVP64BCGate(Enum):
565 ANY = 0
566 ALL = 1
567
568
569 class SVP64BCCTRMode(Enum):
570 NONE = 0
571 TEST = 1
572 TEST_INV = 2
573
574
575 @unique
576 class SVP64Width(Enum):
577 DEFAULT = 0
578 EW_32 = 1
579 EW_16 = 2
580 EW_8 = 3
581
582 @classmethod
583 def _missing_(cls, desc):
584 if isinstance(desc, str):
585 return {
586 "32": SVP64Width.EW_32,
587 "16": SVP64Width.EW_16,
588 "8": SVP64Width.EW_8,
589 }.get(desc)
590
591 return super()._missing_(desc)
592
593
594 @unique
595 class SVP64SubVL(Enum):
596 VEC1 = 0
597 VEC2 = 1
598 VEC3 = 2
599 VEC4 = 3
600
601 @classmethod
602 def _missing_(cls, desc):
603 if isinstance(desc, str):
604 name = desc.upper()
605 return cls.__members__.get(name)
606
607 return super()._missing_(desc)
608
609
610 @unique
611 class SVP64Sat(Enum):
612 NONE = 0
613 SIGNED = 1
614 UNSIGNED = 2
615
616
617 @unique
618 class SVP64LDSTmode(Enum):
619 NONE = 0
620 INDEXED = 1
621 ELSTRIDE = 2
622 UNITSTRIDE = 3
623
624
625 class RegType(Enum):
626 GPR = 0
627 RA = GPR
628 RB = GPR
629 RC = GPR
630 RS = GPR
631 RSp = RS
632 RT = GPR
633 RTp = RT
634
635 FPR = 1
636 FRA = FPR
637 FRAp = FRA
638 FRB = FPR
639 FRBp = FRB
640 FRC = FPR
641 FRS = FPR
642 FRSp = FRS
643 FRT = FPR
644 FRTp = FRT
645
646 CR_3BIT = 2 # CR field; the CR register is 32-bit
647 BF = CR_3BIT
648 BFA = CR_3BIT
649
650 CR_5BIT = 3 # bit of the 32-bit CR register
651 BA = CR_5BIT
652 BB = CR_5BIT
653 BC = CR_5BIT
654 BI = CR_5BIT
655 BT = CR_5BIT
656
657 XER_BIT = 4 # XER bits, includes OV, OV32, SO, CA, CA32
658 OV = XER_BIT
659 OV32 = XER_BIT
660 CA = XER_BIT
661 CA32 = XER_BIT
662 SO = XER_BIT
663
664 @classmethod
665 def _missing_(cls, value):
666 if isinstance(value, Reg):
667 return cls.__members__.get(value.name)
668
669 return super()._missing_(value)
670
671
672 FPTRANS_INSNS = (
673 "fatan2", "fatan2s",
674 "fatan2pi", "fatan2pis",
675 "fpow", "fpows",
676 "fpown", "fpowns",
677 "fpowr", "fpowrs",
678 "frootn", "frootns",
679 "fhypot", "fhypots",
680 "frsqrt", "frsqrts",
681 "fcbrt", "fcbrts",
682 "frecip", "frecips",
683 "fexp2m1", "fexp2m1s",
684 "flog2p1", "flog2p1s",
685 "fexp2", "fexp2s",
686 "flog2", "flog2s",
687 "fexpm1", "fexpm1s",
688 "flogp1", "flogp1s",
689 "fexp", "fexps",
690 "flog", "flogs",
691 "fexp10m1", "fexp10m1s",
692 "flog10p1", "flog10p1s",
693 "fexp10", "fexp10s",
694 "flog10", "flog10s",
695 "fsin", "fsins",
696 "fcos", "fcoss",
697 "ftan", "ftans",
698 "fasin", "fasins",
699 "facos", "facoss",
700 "fatan", "fatans",
701 "fsinpi", "fsinpis",
702 "fcospi", "fcospis",
703 "ftanpi", "ftanpis",
704 "fasinpi", "fasinpis",
705 "facospi", "facospis",
706 "fatanpi", "fatanpis",
707 "fsinh", "fsinhs",
708 "fcosh", "fcoshs",
709 "ftanh", "ftanhs",
710 "fasinh", "fasinhs",
711 "facosh", "facoshs",
712 "fatanh", "fatanhs",
713 # fmin*/fmax* need to be replaced with fminmax
714 # https://bugs.libre-soc.org/show_bug.cgi?id=1057
715 # commented for now to make space for fmv/cvt
716 # "fminnum08", "fminnum08s",
717 # "fmaxnum08", "fmaxnum08s",
718 # "fmin19", "fmin19s",
719 # "fmax19", "fmax19s",
720 # "fminnum19", "fminnum19s",
721 # "fmaxnum19", "fmaxnum19s",
722 # "fminc", "fmincs",
723 # "fmaxc", "fmaxcs",
724 # "fminmagnum08", "fminmagnum08s",
725 # "fmaxmagnum08", "fmaxmagnum08s",
726 # "fminmag19", "fminmag19s",
727 # "fmaxmag19", "fmaxmag19s",
728 # "fminmagnum19", "fminmagnum19s",
729 # "fmaxmagnum19", "fmaxmagnum19s",
730 # "fminmagc", "fminmagcs",
731 # "fmaxmagc", "fmaxmagcs",
732 "fmod", "fmods",
733 "fremainder", "fremainders",
734 )
735
736
737 # supported instructions: make sure to keep up-to-date with CSV files
738 # just like everything else
739 _insns = [
740 "NONE", "add", "addc", "addco", "adde", "addeo",
741 "addi", "addic", "addic.", "addis",
742 "addme", "addmeo", "addo", "addze", "addzeo",
743 "addex",
744 "addg6s",
745 "and", "andc", "andi.", "andis.",
746 "attn",
747 "absdu", "absds", # AV bitmanip
748 "absdacs", "absdacu", # AV bitmanip
749 "avgadd", # AV bitmanip
750 "b", "bc", "bcctr", "bclr", "bctar",
751 "bmask", # AV bitmanip
752 "bpermd",
753 "cbcdtd",
754 "cdtbcd",
755 "cmp", "cmpb", "cmpeqb", "cmpi", "cmpl", "cmpli", "cmprb",
756 "cntlzd", "cntlzw", "cnttzd", "cnttzw",
757 "cprop", # AV bitmanip
758 "crand", "crandc", "creqv",
759 "crnand", "crnor", "cror", "crorc", "crxor",
760 "darn",
761 "dcbf", "dcbst", "dcbt", "dcbtst", "dcbz",
762 "divd", "divde", "divdeo", "divdeu",
763 "divdeuo", "divdo", "divdu", "divduo",
764 "divmod2du",
765 "divw", "divwe", "divweo",
766 "divweu", "divweuo", "divwo", "divwu", "divwuo",
767 "dsld", "dsld.", "dsrd", "dsrd.",
768 "eieio", "eqv",
769 "extsb", "extsh", "extsw", "extswsli",
770 "fadd", "fadds", "fsub", "fsubs", # FP add / sub
771 "fcfids", "fcfidus", "fsqrts", "fres", "frsqrtes", # FP stuff
772 "fdmadds", # DCT FP 3-arg
773 "fmsubs", "fmadds", "fnmsubs", "fnmadds", # FP 3-arg
774 "ffadds", "ffsubs", "ffmuls", "ffdivs", # FFT FP 2-arg
775 "ffmsubs", "ffmadds", "ffnmsubs", "ffnmadds", # FFT FP 3-arg
776 "fmul", "fmuls", "fdiv", "fdivs", # FP mul / div
777 "fmr", "fabs", "fnabs", "fneg", "fcpsgn", # FP move/abs/neg
778 "fmvis", # FP load immediate
779 "fishmv", # Float Replace Lower-Half Single, Immediate
780 "fcvttg", "fcvttgo",
781 "fmvtg", "fmvtgs",
782 "fcvtfg", "fcvtfgs",
783 "fmvfg", "fmvfgs",
784 'grev', 'grev.', 'grevi', 'grevi.',
785 'grevw', 'grevw.', 'grevwi', 'grevwi.',
786 "hrfid", "icbi", "icbt", "isel", "isync",
787 "lbarx", "lbz", "lbzcix", "lbzu", "lbzux", "lbzx", # load byte
788 "ld", "ldarx", "ldbrx", "ldu", "ldux", "ldx", # load double
789 # "lbzbr", "lbzubr", # load byte SVP64 bit-reversed
790 # "ldbr", "ldubr", # load double SVP64 bit-reversed
791 "lfs", "lfsx", "lfsu", "lfsux", # FP load single
792 "lfd", "lfdx", "lfdu", "lfdux", "lfiwzx", "lfiwax", # FP load double
793 "lha", "lharx", "lhau", "lhaux", "lhax", # load half
794 "lhbrx", "lhz", "lhzu", "lhzux", "lhzx", # more load half
795 # "lhabr", "lhaubr", # load half SVP64 bit-reversed
796 # "lhzbr", "lhzubr", # more load half SVP64 bit-reversed
797 "lwa", "lwarx", "lwaux", "lwax", "lwbrx", # load word
798 "lwz", "lwzcix", "lwzu", "lwzux", "lwzx", # more load word
799 # "lwabr", # load word SVP64 bit-reversed
800 # "lwzbr", "lwzubr", # more load word SVP64 bit-reversed
801 "maddedu", "maddedus",
802 "maddhd", "maddhdu", "maddld", # INT multiply-and-add
803 "maddsubrs", # Integer DCT Butterfly Add Sub and Round Shift
804 "maddrs", # Integer DCT Butterfly Add and Accumulate and Round Shift
805 "mcrf", "mcrxr", "mcrxrx", "mfcr/mfocrf", # CR mvs
806 "mfmsr", "mfspr",
807 "minmax", # AV bitmanip
808 "modsd", "modsw", "modud", "moduw",
809 "mtcrf/mtocrf", "mtmsr", "mtmsrd", "mtspr",
810 "mulhd", "mulhdu", "mulhw", "mulhwu", "mulld", "mulldo",
811 "mulli", "mullw", "mullwo",
812 "nand", "neg", "nego",
813 "nop",
814 "nor", "or", "orc", "ori", "oris",
815 "pcdec",
816 "popcntb", "popcntd", "popcntw",
817 "prtyd", "prtyw",
818 "rfid",
819 "rldcl", "rldcr", "rldic", "rldicl", "rldicr", "rldimi",
820 "rlwimi", "rlwinm", "rlwnm",
821 "setb",
822 "setvl", # https://libre-soc.org/openpower/sv/setvl
823 "svindex", # https://libre-soc.org/openpower/sv/remap
824 "svremap", # https://libre-soc.org/openpower/sv/remap - TEMPORARY
825 "svshape", # https://libre-soc.org/openpower/sv/remap/#svshape
826 "svshape2", # https://libre-soc.org/openpower/sv/remap/discussion TODO
827 "svstep", # https://libre-soc.org/openpower/sv/setvl
828 "sim_cfg",
829 "sadd", "saddw", "sadduw",
830 "slbia", "sld", "slw", "srad", "sradi",
831 "sraw", "srawi", "srd", "srw",
832 "stb", "stbcix", "stbcx", "stbu", "stbux", "stbx",
833 "std", "stdbrx", "stdcx", "stdu", "stdux", "stdx",
834 "stfs", "stfsx", "stfsu", "stfux", "stfsux", # FP store single
835 "stfd", "stfdx", "stfdu", "stfdux", "stfiwx", # FP store double
836 "sth", "sthbrx", "sthcx", "sthu", "sthux", "sthx",
837 "stw", "stwbrx", "stwcx", "stwu", "stwux", "stwx",
838 "subf", "subfc", "subfco", "subfe", "subfeo", "subfic",
839 "subfme", "subfmeo", "subfo", "subfze", "subfzeo",
840 "sync",
841 "ternlogi",
842 "td", "tdi",
843 "tlbie", "tlbiel", "tlbsync",
844 "tw", "twi",
845 "wait",
846 "xor", "xori", "xoris",
847 *FPTRANS_INSNS,
848 ]
849
850 # two-way lookup of instruction-to-index and vice-versa
851 insns = {}
852 asmidx = {}
853 for i, insn in enumerate(_insns):
854 insns[i] = insn
855 asmidx[insn] = i
856
857 # must be long enough to cover all instructions
858 asmlen = len(_insns).bit_length()
859
860 # Internal Operation numbering. Add new opcodes here (FPADD, FPMUL etc.)
861
862
863 @unique
864 class MicrOp(Enum):
865 OP_ILLEGAL = 0 # important that this is zero (see power_decoder.py)
866 OP_NOP = 1
867 OP_ADD = 2
868 OP_ADDPCIS = 3
869 OP_AND = 4
870 OP_ATTN = 5
871 OP_B = 6
872 OP_BC = 7
873 OP_BCREG = 8
874 OP_BPERM = 9
875 OP_CMP = 10
876 OP_CMPB = 11
877 OP_CMPEQB = 12
878 OP_CMPRB = 13
879 OP_CNTZ = 14
880 OP_CRAND = 15
881 OP_CRANDC = 16
882 OP_CREQV = 17
883 OP_CRNAND = 18
884 OP_CRNOR = 19
885 OP_CROR = 20
886 OP_CRORC = 21
887 OP_CRXOR = 22
888 OP_DARN = 23
889 OP_DCBF = 24
890 OP_DCBST = 25
891 OP_DCBT = 26
892 OP_DCBTST = 27
893 OP_DCBZ = 28
894 OP_DIV = 29
895 OP_DIVE = 30
896 OP_EXTS = 31
897 OP_EXTSWSLI = 32
898 OP_ICBI = 33
899 OP_ICBT = 34
900 OP_ISEL = 35
901 OP_ISYNC = 36
902 OP_LOAD = 37
903 OP_STORE = 38
904 OP_MADDHD = 39
905 OP_MADDHDU = 40
906 OP_MADDLD = 41
907 OP_MCRF = 42
908 OP_MCRXR = 43
909 OP_MCRXRX = 44
910 OP_MFCR = 45
911 OP_MFSPR = 46
912 OP_MOD = 47
913 OP_MTCRF = 48
914 OP_MTSPR = 49
915 OP_MUL_L64 = 50
916 OP_MUL_H64 = 51
917 OP_MUL_H32 = 52
918 OP_OR = 53
919 OP_POPCNT = 54
920 OP_PRTY = 55
921 OP_RLC = 56
922 OP_RLCL = 57
923 OP_RLCR = 58
924 OP_SETB = 59
925 OP_SHL = 60
926 OP_SHR = 61
927 OP_SYNC = 62
928 OP_TRAP = 63
929 OP_XOR = 67
930 OP_SIM_CONFIG = 68
931 OP_CROP = 69
932 OP_RFID = 70
933 OP_MFMSR = 71
934 OP_MTMSRD = 72
935 OP_SC = 73
936 OP_MTMSR = 74
937 OP_TLBIE = 75
938 OP_SETVL = 76
939 OP_FPOP = 77 # temporary: replace with actual ops
940 OP_FPOP_I = 78 # temporary: replace with actual ops
941 OP_FP_MADD = 79
942 OP_SVREMAP = 80
943 OP_SVSHAPE = 81
944 OP_SVSTEP = 82
945 OP_ADDG6S = 83
946 OP_CDTBCD = 84
947 OP_CBCDTD = 85
948 OP_TERNLOG = 86
949 OP_FETCH_FAILED = 87
950 OP_GREV = 88
951 OP_MINMAX = 89
952 OP_AVGADD = 90
953 OP_ABSDIFF = 91
954 OP_ABSADD = 92
955 OP_CPROP = 93
956 OP_BMASK = 94
957 OP_SVINDEX = 95
958 OP_FMVIS = 96
959 OP_FISHMV = 97
960 OP_PCDEC = 98
961 OP_MADDEDU = 99
962 OP_DIVMOD2DU = 100
963 OP_DSHL = 101
964 OP_DSHR = 102
965 OP_SHADD = 103
966 OP_MADDSUBRS = 104
967 OP_MADDRS = 105
968
969
970 class SelType(Enum):
971 NONE = None
972 SRC = 's'
973 DST = 'd'
974
975 def __str__(self):
976 return {
977 SelType.NONE: "NONE",
978 SelType.SRC: "SRC",
979 SelType.DST: "DST",
980 }[self]
981
982
983 class In1Sel(Enum):
984 NONE = 0
985 RA = 1
986 RA_OR_ZERO = 2
987 SPR = 3
988 RS = 4 # for some ALU/Logical operations
989 RSp = RS
990 FRA = 5
991 FRAp = FRA
992 FRS = 6
993 FRSp = FRS
994 FRT = 7
995 CIA = 8 # for addpcis
996 RT = 9
997
998 def __str__(self):
999 if self is In1Sel.RA_OR_ZERO:
1000 return "RA0"
1001 return self.name
1002
1003 @property
1004 def type(self):
1005 if self is In1Sel.NONE:
1006 return SelType.NONE
1007 return SelType.SRC
1008
1009
1010 class In2Sel(Enum):
1011 NONE = 0
1012 RB = 1
1013 CONST_UI = 2
1014 CONST_SI = 3
1015 CONST_UI_HI = 4
1016 CONST_SI_HI = 5
1017 CONST_LI = 6
1018 CONST_BD = 7
1019 CONST_DS = 8
1020 CONST_M1 = 9
1021 CONST_SH = 10
1022 CONST_SH32 = 11
1023 SPR = 12
1024 RS = 13 # for shiftrot (M-Form)
1025 RSp = RS
1026 FRB = 14
1027 FRBp = FRB
1028 CONST_SVD = 15 # for SVD-Form
1029 CONST_SVDS = 16 # for SVDS-Form
1030 CONST_XBI = 17
1031 CONST_DXHI4 = 18 # for addpcis
1032 CONST_DQ = 19 # for ld/st-quad
1033
1034 def __str__(self):
1035 return self.name
1036
1037 @property
1038 def type(self):
1039 if self is In2Sel.NONE:
1040 return SelType.NONE
1041 return SelType.SRC
1042
1043
1044 class In3Sel(Enum):
1045 NONE = 0
1046 RS = 1
1047 RSp = RS
1048 RB = 2 # for shiftrot (M-Form)
1049 FRS = 3
1050 FRSp = FRS
1051 FRC = 4
1052 RC = 5 # for SVP64 bit-reverse LD/ST
1053 RT = 6 # for ternlog[i]
1054 RTp = RT
1055 FRA = 7
1056
1057 def __str__(self):
1058 return self.name
1059
1060 @property
1061 def type(self):
1062 if self is In3Sel.NONE:
1063 return SelType.NONE
1064 return SelType.SRC
1065
1066
1067 class OutSel(Enum):
1068 NONE = 0
1069 RT = 1
1070 RTp = RT
1071 RA = 2
1072 SPR = 3
1073 RT_OR_ZERO = 4
1074 FRT = 5
1075 FRTp = FRT
1076 FRS = 6
1077 FRSp = FRS
1078 RS = 7
1079 RSp = RS
1080 FRA = 8
1081
1082 def __str__(self):
1083 if self is OutSel.RT_OR_ZERO:
1084 return "RT0"
1085 return self.name
1086
1087 @property
1088 def type(self):
1089 if self is OutSel.NONE:
1090 return SelType.NONE
1091 return SelType.DST
1092
1093
1094 @unique
1095 class LDSTLen(Enum):
1096 NONE = 0
1097 is1B = 1
1098 is2B = 2
1099 is4B = 4
1100 is8B = 8
1101
1102 # Backward compatibility
1103 LdstLen = LDSTLen
1104
1105
1106 @unique
1107 class LDSTMode(Enum):
1108 NONE = 0
1109 update = 1
1110 cix = 2
1111 cx = 3
1112
1113
1114 @unique
1115 class RCOE(Enum):
1116 NONE = 0
1117 ONE = 1
1118 RC = 2 # includes OE
1119 RC_ONLY = 3 # does not include OE
1120
1121
1122 @unique
1123 class CryIn(Enum):
1124 ZERO = 0
1125 ONE = 1
1126 CA = 2
1127 OV = 3
1128
1129
1130 @unique
1131 class CRInSel(Enum):
1132 NONE = 0
1133 CR0 = 1
1134 BI = 2
1135 BFA = 3
1136 BA_BB = 4
1137 BC = 5
1138 WHOLE_REG = 6
1139 CR1 = 7
1140 BA = 8
1141
1142 def __str__(self):
1143 return self.name
1144
1145 @property
1146 def type(self):
1147 if self is CRInSel.NONE:
1148 return SelType.NONE
1149 return SelType.SRC
1150
1151
1152 @unique
1153 class CRIn2Sel(Enum):
1154 NONE = 0
1155 BB = 1
1156
1157 def __str__(self):
1158 return self.name
1159
1160 @property
1161 def type(self):
1162 if self is CRIn2Sel.NONE:
1163 return SelType.NONE
1164 return SelType.SRC
1165
1166
1167 @unique
1168 class CROutSel(Enum):
1169 NONE = 0
1170 CR0 = 1
1171 BF = 2
1172 BT = 3
1173 WHOLE_REG = 4
1174 CR1 = 5
1175
1176 def __str__(self):
1177 return self.name
1178
1179 @property
1180 def type(self):
1181 if self is CROutSel.NONE:
1182 return SelType.NONE
1183 return SelType.DST
1184
1185
1186 # SPRs - Special-Purpose Registers. See V3.0B Figure 18 p971 and
1187 # http://libre-riscv.org/openpower/isatables/sprs.csv
1188 # http://bugs.libre-riscv.org/show_bug.cgi?id=261
1189 # http://bugs.libre-riscv.org/show_bug.cgi?id=859 - KAIVB
1190
1191 def get_spr_enum(full_file):
1192 """get_spr_enum - creates an Enum of SPRs, dynamically
1193 has the option to reduce the enum to a much shorter list.
1194 this saves drastically on the size of the regfile
1195 """
1196 short_list = {'PIDR', 'DAR', 'PRTBL', 'DSISR', 'SVSRR0', 'SVSTATE',
1197 'SVSTATE0', 'SVSTATE1', 'SVSTATE2', 'SVSTATE3',
1198 'SPRG0_priv', 'SPRG1_priv', 'SPRG2_priv', 'SPRG3_priv',
1199 'SPRG0', 'SPRG1', 'SPRG2', 'SPRG3', 'KAIVB',
1200 # hmmm should not be including these, they are FAST regs
1201 'CTR', 'LR', 'TAR', 'SRR0', 'SRR1', 'XER', 'DEC', 'TB', 'TBU',
1202 'HSRR0', 'HSRR1', 'HSPRG0', 'HSPRG1',
1203 }
1204 spr_csv = []
1205 for row in get_csv("sprs.csv"):
1206 if full_file or row['SPR'] in short_list:
1207 spr_csv.append(row)
1208
1209 spr_info = namedtuple('spr_info', 'SPR priv_mtspr priv_mfspr length idx')
1210 spr_dict = {}
1211 spr_byname = {}
1212 for row in spr_csv:
1213 info = spr_info(SPR=row['SPR'], priv_mtspr=row['priv_mtspr'],
1214 priv_mfspr=row['priv_mfspr'], length=int(row['len']),
1215 idx=int(row['Idx']))
1216 spr_dict[int(row['Idx'])] = info
1217 spr_byname[row['SPR']] = info
1218 fields = [(row['SPR'], int(row['Idx'])) for row in spr_csv]
1219 SPR = Enum('SPR', fields)
1220 return SPR, spr_dict, spr_byname
1221
1222
1223 SPRfull, spr_dict, spr_byname = get_spr_enum(full_file=True)
1224 SPRreduced, _, _ = get_spr_enum(full_file=False)
1225
1226 XER_bits = {
1227 'SO': 32,
1228 'OV': 33,
1229 'CA': 34,
1230 'OV32': 44,
1231 'CA32': 45
1232 }
1233
1234 MSRSpec = namedtuple("MSRSpec", ["dr", "pr", "sf"])
1235
1236 # flags for bfp_* functions
1237 BFP_FLAG_NAMES = (
1238 'vxsnan_flag',
1239 'vximz_flag',
1240 'vxidi_flag',
1241 'vxisi_flag',
1242 'vxzdz_flag',
1243 'vxsqrt_flag',
1244 'vxcvi_flag',
1245 'vxvc_flag',
1246 'ox_flag',
1247 'ux_flag',
1248 'xx_flag',
1249 'zx_flag',
1250 'inc_flag',
1251 )
1252
1253 if __name__ == '__main__':
1254 # find out what the heck is in SPR enum :)
1255 print("sprs full", len(SPRfull))
1256 print(dir(SPRfull))
1257 print("sprs reduced", len(SPRreduced))
1258 print(dir(SPRreduced))
1259 print(dir(Enum))
1260 print(SPRfull.__members__['TAR'])
1261 for x in SPRfull:
1262 print("full", x, x.value, str(x), x.name)
1263 for x in SPRreduced:
1264 print("reduced", x, x.value, str(x), x.name)
1265
1266 print("function", Function.ALU.name)