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