1 import collections
as _collections
2 import contextlib
as _contextlib
4 import dataclasses
as _dataclasses
6 import functools
as _functools
7 import inspect
as _inspect
9 import operator
as _operator
10 import pathlib
as _pathlib
12 import types
as _types
13 import typing
as _typing
16 from functools
import cached_property
18 from cached_property
import cached_property
20 from openpower
.decoder
.power_enums
import (
21 Function
as _Function
,
28 CRIn2Sel
as _CRIn2Sel
,
29 CROutSel
as _CROutSel
,
31 LDSTMode
as _LDSTMode
,
36 SVMaskSrc
as _SVMaskSrc
,
43 SVP64SubVL
as _SVP64SubVL
,
44 SVP64Pred
as _SVP64Pred
,
45 SVP64PredMode
as _SVP64PredMode
,
46 SVP64Width
as _SVP64Width
,
48 from openpower
.decoder
.selectable_int
import (
49 SelectableInt
as _SelectableInt
,
50 selectconcat
as _selectconcat
,
52 from openpower
.decoder
.power_fields
import (
55 DecodeFields
as _DecodeFields
,
57 from openpower
.decoder
.pseudo
.pagereader
import ISA
as _ISA
61 def __init__(self
, walk
):
63 return super().__init
__()
65 def __get__(self
, instance
, owner
):
69 return _functools
.partial(self
.__walk
, entity
)
74 def walk(clsself
, match
=None):
78 class DataclassMeta(type):
79 def __new__(metacls
, name
, bases
, ns
):
80 cls
= super().__new
__(metacls
, name
, bases
, ns
)
81 return _dataclasses
.dataclass(cls
, eq
=True, frozen
=True)
84 class Dataclass(Node
, metaclass
=DataclassMeta
):
86 def walk(clsself
, match
=None):
88 match
= lambda subnode
: True
90 def field_type(field
):
93 def field_value(field
):
94 return getattr(clsself
, field
.name
)
96 field_node
= (field_type
if isinstance(clsself
, type) else field_value
)
98 for field
in _dataclasses
.fields(clsself
):
100 node
= field_node(field
)
104 class Tuple(Node
, tuple):
105 def __init_subclass__(cls
, datatype
):
106 cls
.__datatype
= datatype
107 return super().__init
_subclass
__()
110 def walk(clsself
, match
=None):
112 match
= lambda subnode
: True
114 if isinstance(clsself
, type):
115 yield ("[]", clsself
.__datatype
)
117 for (index
, item
) in enumerate(filter(match
, clsself
)):
118 yield (str(index
), item
)
121 class Dict(Node
, dict):
122 def __init_subclass__(cls
, datatype
):
123 cls
.__datatype
= datatype
124 return super().__init
_subclass
__()
127 return hash(tuple(sorted(self
.items())))
130 raise NotImplementedError()
132 def __delitem__(self
, key
):
133 raise NotImplementedError()
135 def __setitem__(self
, key
, value
):
136 raise NotImplementedError()
138 def popitem(self
) -> tuple:
139 raise NotImplementedError()
141 def pop(self
, key
, default
=None):
142 raise NotImplementedError()
144 def update(self
, entry
, **kwargs
):
145 raise NotImplementedError()
148 def walk(clsself
, match
=None):
150 match
= lambda subnode
: True
152 if isinstance(clsself
, type):
153 yield ("{}", clsself
.__datatype
)
155 yield from filter(lambda kv
: match(kv
[0]), clsself
.items())
159 def __init__(self
, nodecls
, method
):
160 self
.__nodecls
= nodecls
161 self
.__method
= method
162 return super().__init
__()
166 return self
.__nodecls
168 @_contextlib.contextmanager
169 def __call__(self
, path
, node
):
170 return self
.__method
(self
=self
, path
=path
, node
=node
)
173 class VisitorMeta(type):
174 def __init__(cls
, name
, bases
, ns
):
176 for (key
, value
) in ns
.items():
177 if isinstance(value
, VisitorMethod
):
178 if value
.type in cls
.__registry
:
179 raise AttributeError(f
"overriding visitor method: {key!r}")
180 cls
.__registry
[value
.type] = value
181 return super().__init
__(name
, bases
, ns
)
183 def __contains__(self
, nodecls
):
184 return self
.__registry
.__contains
__(nodecls
)
186 def __getitem__(self
, nodecls
):
187 return self
.__registry
.__getitem
__(nodecls
)
189 def __setitem__(self
, nodecls
, call
):
190 return self
.__registry
.__setitem
__(nodecls
, call
)
193 yield from self
.__registry
.items()
196 class Visitor(metaclass
=VisitorMeta
):
197 @_contextlib.contextmanager
198 def __call__(self
, path
, node
):
199 (visitorcls
, nodecls
) = map(type, (self
, node
))
200 if nodecls
in visitorcls
:
201 handler
= visitorcls
[nodecls
]
202 with
handler(path
=path
, node
=node
) as ctx
:
209 def __init__(self
, nodecls
):
210 if not isinstance(nodecls
, type):
211 raise ValueError(nodecls
)
212 self
.__nodecls
= nodecls
213 return super().__init
__()
215 def __call__(self
, method
):
216 if not callable(method
):
217 raise ValueError(method
)
218 return VisitorMethod(nodecls
=self
.__nodecls
, method
=method
)
221 def walk(root
, match
=None):
222 pairs
= _collections
.deque([root
])
224 (path
, node
) = pairs
.popleft()
225 pairs
.extend(node
.walk(match
=match
))
229 def visit(visitor
, node
, path
="/"):
230 with
visitor(path
=path
, node
=node
):
231 if isinstance(node
, Node
):
232 for (subpath
, subnode
) in node
.walk():
233 visit(visitor
=visitor
, path
=subpath
, node
=subnode
)
236 @_functools.total_ordering
237 class Style(_enum
.Enum
):
238 LEGACY
= _enum
.auto()
240 NORMAL
= _enum
.auto()
241 VERBOSE
= _enum
.auto()
243 def __lt__(self
, other
):
244 if not isinstance(other
, self
.__class
__):
245 return NotImplemented
246 return (self
.value
< other
.value
)
249 @_functools.total_ordering
250 class Priority(_enum
.Enum
):
256 def _missing_(cls
, value
):
257 if isinstance(value
, str):
258 value
= value
.upper()
262 return super()._missing
_(value
)
264 def __lt__(self
, other
):
265 if not isinstance(other
, self
.__class
__):
266 return NotImplemented
268 # NOTE: the order is inversed, LOW < NORMAL < HIGH
269 return (self
.value
> other
.value
)
272 def dataclass(cls
, record
, keymap
=None, typemap
=None):
276 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
278 def transform(key_value
):
279 (key
, value
) = key_value
280 key
= keymap
.get(key
, key
)
281 hook
= typemap
.get(key
, lambda value
: value
)
282 if hook
is bool and value
in ("", "0"):
288 record
= dict(map(transform
, record
.items()))
289 for key
in frozenset(record
.keys()):
290 if record
[key
] == "":
296 @_functools.total_ordering
297 class Opcode(Dataclass
):
299 def __new__(cls
, value
):
300 if isinstance(value
, str):
301 value
= int(value
, 0)
302 if not isinstance(value
, int):
303 raise ValueError(value
)
305 if value
.bit_length() > 64:
306 raise ValueError(value
)
308 return super().__new
__(cls
, value
)
311 return self
.__repr
__()
314 return f
"{self:0{self.bit_length()}b}"
316 def bit_length(self
):
317 if super().bit_length() > 32:
321 class Value(Integer
):
330 def __lt__(self
, other
):
331 if not isinstance(other
, Opcode
):
332 return NotImplemented
333 return ((self
.value
, self
.mask
) < (other
.value
, other
.mask
))
336 return (self
.value
& self
.mask
)
339 return int(self
).__index
__()
342 def pattern(value
, mask
, bit_length
):
343 for bit
in range(bit_length
):
344 if ((mask
& (1 << (bit_length
- bit
- 1))) == 0):
346 elif (value
& (1 << (bit_length
- bit
- 1))):
351 return "".join(pattern(self
.value
, self
.mask
, self
.value
.bit_length()))
353 def match(self
, key
):
354 return ((self
.value
& self
.mask
) == (key
& self
.mask
))
357 @_functools.total_ordering
358 class IntegerOpcode(Opcode
):
359 def __init__(self
, value
):
360 if value
.startswith("0b"):
361 mask
= int(("1" * len(value
[2:])), 2)
365 value
= Opcode
.Value(value
)
366 mask
= Opcode
.Mask(mask
)
368 return super().__init
__(value
=value
, mask
=mask
)
371 @_functools.total_ordering
372 class PatternOpcode(Opcode
):
373 def __init__(self
, pattern
):
374 if not isinstance(pattern
, str):
375 raise ValueError(pattern
)
377 (value
, mask
) = (0, 0)
378 for symbol
in pattern
:
379 if symbol
not in {"0", "1", "-"}:
380 raise ValueError(pattern
)
381 value |
= (symbol
== "1")
382 mask |
= (symbol
!= "-")
388 value
= Opcode
.Value(value
)
389 mask
= Opcode
.Mask(mask
)
391 return super().__init
__(value
=value
, mask
=mask
)
394 class PPCRecord(Dataclass
):
395 class FlagsMeta(type):
410 class Flags(Tuple
, datatype
=str, metaclass
=FlagsMeta
):
411 def __new__(cls
, flags
=frozenset()):
412 flags
= frozenset(flags
)
413 diff
= (flags
- frozenset(cls
))
415 raise ValueError(flags
)
416 return super().__new
__(cls
, sorted(flags
))
420 flags
: Flags
= Flags()
422 function
: _Function
= _Function
.NONE
423 intop
: _MicrOp
= _MicrOp
.OP_ILLEGAL
424 in1
: _In1Sel
= _In1Sel
.NONE
425 in2
: _In2Sel
= _In2Sel
.NONE
426 in3
: _In3Sel
= _In3Sel
.NONE
427 out
: _OutSel
= _OutSel
.NONE
428 cr_in
: _CRInSel
= _CRInSel
.NONE
429 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
430 cr_out
: _CROutSel
= _CROutSel
.NONE
431 cry_in
: _CryIn
= _CryIn
.ZERO
432 ldst_len
: _LDSTLen
= _LDSTLen
.NONE
433 upd
: _LDSTMode
= _LDSTMode
.NONE
434 Rc
: _RCOE
= _RCOE
.NONE
435 form
: _Form
= _Form
.NONE
437 unofficial
: bool = False
441 "internal op": "intop",
445 "ldst len": "ldst_len",
447 "CONDITIONS": "conditions",
450 def __lt__(self
, other
):
451 if not isinstance(other
, self
.__class
__):
452 return NotImplemented
453 lhs
= (self
.opcode
, self
.comment
)
454 rhs
= (other
.opcode
, other
.comment
)
458 def CSV(cls
, record
, opcode_cls
):
459 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
460 typemap
["opcode"] = opcode_cls
462 if record
["CR in"] == "BA_BB":
463 record
["cr_in"] = "BA"
464 record
["cr_in2"] = "BB"
468 for flag
in frozenset(PPCRecord
.Flags
):
469 if bool(record
.pop(flag
, "")):
471 record
["flags"] = PPCRecord
.Flags(flags
)
473 return dataclass(cls
, record
,
474 keymap
=PPCRecord
.__KEYMAP
,
479 return frozenset(self
.comment
.split("=")[-1].split("/"))
482 class PPCMultiRecord(Tuple
, datatype
=PPCRecord
):
483 def __getattr__(self
, attr
):
486 raise AttributeError(attr
)
487 return getattr(self
[0], attr
)
490 class SVP64Record(Dataclass
):
491 class ExtraMap(tuple):
493 @_dataclasses.dataclass(eq
=True, frozen
=True)
495 seltype
: _SelType
= _SelType
.NONE
496 reg
: _Reg
= _Reg
.NONE
499 return f
"{self.seltype.value}:{self.reg.name}"
501 def __new__(cls
, value
="0"):
502 if isinstance(value
, str):
503 def transform(value
):
504 (seltype
, reg
) = value
.split(":")
505 seltype
= _SelType(seltype
)
507 return cls
.Entry(seltype
=seltype
, reg
=reg
)
512 value
= map(transform
, value
.split(";"))
514 return super().__new
__(cls
, value
)
517 return repr(list(self
))
519 def __new__(cls
, value
=tuple()):
523 return super().__new
__(cls
, map(cls
.Extra
, value
))
526 return repr({index
:self
[index
] for index
in range(0, 4)})
529 ptype
: _SVPType
= _SVPType
.NONE
530 etype
: _SVEType
= _SVEType
.NONE
531 msrc
: _SVMaskSrc
= _SVMaskSrc
.NO
# MASK_SRC is active
532 in1
: _In1Sel
= _In1Sel
.NONE
533 in2
: _In2Sel
= _In2Sel
.NONE
534 in3
: _In3Sel
= _In3Sel
.NONE
535 out
: _OutSel
= _OutSel
.NONE
536 out2
: _OutSel
= _OutSel
.NONE
537 cr_in
: _CRInSel
= _CRInSel
.NONE
538 cr_in2
: _CRIn2Sel
= _CRIn2Sel
.NONE
539 cr_out
: _CROutSel
= _CROutSel
.NONE
540 extra
: ExtraMap
= ExtraMap()
542 mode
: _SVMode
= _SVMode
.NORMAL
546 "CONDITIONS": "conditions",
555 def CSV(cls
, record
):
556 record
["insn"] = record
["insn"].split("=")[-1]
558 for key
in frozenset({
559 "in1", "in2", "in3", "CR in",
560 "out", "out2", "CR out",
566 if record
["CR in"] == "BA_BB":
567 record
["cr_in"] = "BA"
568 record
["cr_in2"] = "BB"
572 for idx
in range(0, 4):
573 extra
.append(record
.pop(f
"{idx}"))
575 record
["extra"] = cls
.ExtraMap(extra
)
577 return dataclass(cls
, record
, keymap
=cls
.__KEYMAP
)
582 "in1", "in2", "in3", "cr_in", "cr_in2",
583 "out", "out2", "cr_out",
598 for index
in range(0, 4):
599 for entry
in self
.extra
[index
]:
600 extras
[entry
.seltype
][entry
.reg
] = idxmap
[index
]
602 for (seltype
, regs
) in extras
.items():
603 idx
= regs
.get(reg
, _SVExtra
.NONE
)
604 if idx
is not _SVExtra
.NONE
:
605 yield (reg
, seltype
, idx
)
612 # has the word "in", it is a SelType.SRC "out" -> DST
613 # in1/2/3 and CR in are SRC, and must match only against "s:NN"
614 # out/out1 and CR out are DST, and must match only against "d:NN"
615 keytype
= _SelType
.SRC
if ("in" in key
) else _SelType
.DST
616 sel
= sels
[key
] = getattr(self
, key
)
617 reg
= regs
[key
] = _Reg(sel
)
618 seltypes
[key
] = _SelType
.NONE
619 idxs
[key
] = _SVExtra
.NONE
620 for (reg
, seltype
, idx
) in extra(reg
.alias
):
621 if keytype
!= seltype
: # only check SRC-to-SRC and DST-to-DST
623 if idx
!= idxs
[key
] and idxs
[key
] is not _SVExtra
.NONE
:
624 raise ValueError(idx
)
627 seltypes
[key
] = seltype
629 if sels
["cr_in"] is _CRInSel
.BA_BB
:
630 sels
["cr_in"] = _CRIn2Sel
.BA
631 sels
["cr_in2"] = _CRIn2Sel
.BB
632 idxs
["cr_in2"] = idxs
["cr_in"]
633 for key
in ("cr_in", "cr_in2"):
634 regs
[key
] = _Reg(sels
[key
])
635 seltype
[key
] = _SelType
.SRC
642 "seltype": seltypes
[key
],
646 return _types
.MappingProxyType(records
)
648 extra_idx_in1
= property(lambda self
: self
.extras
["in1"]["idx"])
649 extra_idx_in2
= property(lambda self
: self
.extras
["in2"]["idx"])
650 extra_idx_in3
= property(lambda self
: self
.extras
["in3"]["idx"])
651 extra_idx_out
= property(lambda self
: self
.extras
["out"]["idx"])
652 extra_idx_out2
= property(lambda self
: self
.extras
["out2"]["idx"])
653 extra_idx_cr_in
= property(lambda self
: self
.extras
["cr_in"]["idx"])
654 extra_idx_cr_in2
= property(lambda self
: self
.extras
["cr_in2"]["idx"])
655 extra_idx_cr_out
= property(lambda self
: self
.extras
["cr_out"]["idx"])
660 for idx
in range(0, 4):
661 for entry
in self
.extra
[idx
]:
662 if entry
.seltype
is _SelType
.DST
:
663 if extra
is not None:
664 raise ValueError(self
.svp64
)
668 if _RegType(extra
.reg
) not in (_RegType
.CR_3BIT
, _RegType
.CR_5BIT
):
669 raise ValueError(self
.svp64
)
674 def extra_CR_3bit(self
):
675 return (_RegType(self
.extra_CR
.reg
) is _RegType
.CR_3BIT
)
679 def __init__(self
, value
=(0, 32)):
680 if isinstance(value
, str):
681 (start
, end
) = map(int, value
.split(":"))
684 if start
< 0 or end
< 0 or start
>= end
:
685 raise ValueError(value
)
690 return super().__init
__()
693 return (self
.__end
- self
.__start
+ 1)
696 return f
"[{self.__start}:{self.__end}]"
699 yield from range(self
.start
, (self
.end
+ 1))
701 def __reversed__(self
):
702 return tuple(reversed(tuple(self
)))
713 class Section(Dataclass
):
714 class Mode(_enum
.Enum
):
715 INTEGER
= _enum
.auto()
716 PATTERN
= _enum
.auto()
719 def _missing_(cls
, value
):
720 if isinstance(value
, str):
721 return cls
[value
.upper()]
722 return super()._missing
_(value
)
725 def __new__(cls
, value
=None):
726 if isinstance(value
, str):
727 if value
.upper() == "NONE":
730 value
= int(value
, 0)
734 return super().__new
__(cls
, value
)
740 return (bin(self
) if self
else "None")
746 opcode
: IntegerOpcode
= None
747 priority
: Priority
= Priority
.NORMAL
749 def __lt__(self
, other
):
750 if not isinstance(other
, self
.__class
__):
751 return NotImplemented
752 return (self
.priority
< other
.priority
)
755 def CSV(cls
, record
):
756 keymap
= {"path": "csv"}
757 typemap
= {field
.name
:field
.type for field
in _dataclasses
.fields(cls
)}
758 if record
["opcode"] == "NONE":
759 typemap
["opcode"] = lambda _
: None
761 return dataclass(cls
, record
, typemap
=typemap
, keymap
=keymap
)
764 class Fields(Dict
, datatype
=type("Bits", (Tuple
,), {}, datatype
=int)):
765 def __init__(self
, items
):
766 if isinstance(items
, dict):
767 items
= items
.items()
770 (name
, bitrange
) = item
771 return (name
, tuple(bitrange
.values()))
773 mapping
= dict(map(transform
, items
))
775 return super().__init
__(mapping
)
778 yield from self
.__mapping
.items()
793 def __init__(self
, insn
, operands
):
795 "b": {"target_addr": TargetAddrOperandLI
},
796 "ba": {"target_addr": TargetAddrOperandLI
},
797 "bl": {"target_addr": TargetAddrOperandLI
},
798 "bla": {"target_addr": TargetAddrOperandLI
},
799 "bc": {"target_addr": TargetAddrOperandBD
},
800 "bca": {"target_addr": TargetAddrOperandBD
},
801 "bcl": {"target_addr": TargetAddrOperandBD
},
802 "bcla": {"target_addr": TargetAddrOperandBD
},
803 "addpcis": {"D": DOperandDX
},
804 "fishmv": {"D": DOperandDX
},
805 "fmvis": {"D": DOperandDX
},
808 "SVi": NonZeroOperand
,
809 "SVd": NonZeroOperand
,
810 "SVxd": NonZeroOperand
,
811 "SVyd": NonZeroOperand
,
812 "SVzd": NonZeroOperand
,
814 "D": SignedImmediateOperand
,
818 "SIM": SignedOperand
,
819 "SVD": SignedOperand
,
820 "SVDS": SignedOperand
,
821 "RSp": GPRPairOperand
,
822 "RTp": GPRPairOperand
,
823 "FRAp": FPRPairOperand
,
824 "FRBp": FPRPairOperand
,
825 "FRSp": FPRPairOperand
,
826 "FRTp": FPRPairOperand
,
828 custom_immediates
= {
834 for operand
in operands
:
838 (name
, value
) = operand
.split("=")
839 mapping
[name
] = (StaticOperand
, {
845 if name
.endswith(")"):
846 name
= name
.replace("(", " ").replace(")", "")
847 (imm_name
, _
, name
) = name
.partition(" ")
851 if imm_name
is not None:
852 imm_cls
= custom_immediates
.get(imm_name
, ImmediateOperand
)
854 if insn
in custom_insns
and name
in custom_insns
[insn
]:
855 cls
= custom_insns
[insn
][name
]
856 elif name
in custom_fields
:
857 cls
= custom_fields
[name
]
858 elif name
in _Reg
.__members
__:
860 if reg
in self
.__class
__.__GPR
_PAIRS
:
862 elif reg
in self
.__class
__.__FPR
_PAIRS
:
865 regtype
= _RegType
[name
]
866 if regtype
is _RegType
.GPR
:
868 elif regtype
is _RegType
.FPR
:
870 elif regtype
is _RegType
.CR_3BIT
:
872 elif regtype
is _RegType
.CR_5BIT
:
875 if imm_name
is not None:
876 mapping
[imm_name
] = (imm_cls
, {"name": imm_name
})
877 mapping
[name
] = (cls
, {"name": name
})
881 for (name
, (cls
, kwargs
)) in mapping
.items():
882 kwargs
= dict(kwargs
)
883 kwargs
["name"] = name
884 if issubclass(cls
, StaticOperand
):
885 static
.append((cls
, kwargs
))
886 elif issubclass(cls
, DynamicOperand
):
887 dynamic
.append((cls
, kwargs
))
889 raise ValueError(name
)
891 self
.__mapping
= mapping
892 self
.__static
= tuple(static
)
893 self
.__dynamic
= tuple(dynamic
)
895 return super().__init
__()
898 for (_
, items
) in self
.__mapping
.items():
899 (cls
, kwargs
) = items
903 return self
.__mapping
.__repr
__()
905 def __contains__(self
, key
):
906 return self
.__mapping
.__contains
__(key
)
908 def __getitem__(self
, key
):
909 return self
.__mapping
.__getitem
__(key
)
917 return self
.__dynamic
920 class Arguments(tuple):
921 def __new__(cls
, record
, arguments
, operands
):
922 operands
= iter(tuple(operands
))
923 arguments
= iter(tuple(arguments
))
928 operand
= next(operands
)
929 except StopIteration:
933 argument
= next(arguments
)
934 except StopIteration:
935 raise ValueError("operands count mismatch")
937 if isinstance(operand
, ImmediateOperand
):
938 argument
= argument
.replace("(", " ").replace(")", "")
939 (imm_argument
, _
, argument
) = argument
.partition(" ")
941 (imm_operand
, operand
) = (operand
, next(operands
))
942 except StopIteration:
943 raise ValueError("operands count mismatch")
944 items
.append((imm_argument
, imm_operand
))
945 items
.append((argument
, operand
))
949 except StopIteration:
952 raise ValueError("operands count mismatch")
954 return super().__new
__(cls
, items
)
957 class PCode(Tuple
, datatype
=str):
961 class MarkdownRecord(Dataclass
):
966 @_functools.total_ordering
967 class Record(Dataclass
):
973 svp64
: SVP64Record
= None
977 if self
.svp64
is not None:
978 return self
.svp64
.extras
980 return _types
.MappingProxyType({})
984 return self
.mdwn
.pcode
986 def __lt__(self
, other
):
987 if not isinstance(other
, Record
):
988 return NotImplemented
989 lhs
= (min(self
.opcodes
), self
.name
)
990 rhs
= (min(other
.opcodes
), other
.name
)
995 return (self
.static_operands
+ self
.dynamic_operands
)
998 def static_operands(self
):
1000 operands
.append(POStaticOperand(record
=self
, value
=self
.PO
))
1001 for ppc
in self
.ppc
:
1002 operands
.append(XOStaticOperand(
1004 value
=ppc
.opcode
.value
,
1005 span
=self
.section
.bitsel
,
1007 for (cls
, kwargs
) in self
.mdwn
.operands
.static
:
1008 operands
.append(cls(record
=self
, **kwargs
))
1009 return tuple(operands
)
1012 def dynamic_operands(self
):
1014 for (cls
, kwargs
) in self
.mdwn
.operands
.dynamic
:
1015 operands
.append(cls(record
=self
, **kwargs
))
1016 return tuple(operands
)
1020 def binary(mapping
):
1021 return int("".join(str(int(mapping
[bit
])) \
1022 for bit
in sorted(mapping
)), 2)
1024 def PO_XO(value
, mask
, opcode
, bits
):
1027 for (src
, dst
) in enumerate(reversed(bits
)):
1028 value
[dst
] = ((opcode
.value
& (1 << src
)) != 0)
1029 mask
[dst
] = ((opcode
.mask
& (1 << src
)) != 0)
1030 return (value
, mask
)
1032 def PO(value
, mask
, opcode
, bits
):
1033 return PO_XO(value
=value
, mask
=mask
, opcode
=opcode
, bits
=bits
)
1035 def XO(value
, mask
, opcode
, bits
):
1036 (value
, mask
) = PO_XO(value
=value
, mask
=mask
,
1037 opcode
=opcode
, bits
=bits
)
1038 for (op_cls
, op_kwargs
) in self
.mdwn
.operands
.static
:
1039 operand
= op_cls(record
=self
, **op_kwargs
)
1040 for (src
, dst
) in enumerate(reversed(operand
.span
)):
1041 value
[dst
] = ((operand
.value
& (1 << src
)) != 0)
1043 return (value
, mask
)
1046 value
= {bit
:False for bit
in range(32)}
1047 mask
= {bit
:False for bit
in range(32)}
1048 if self
.section
.opcode
is not None:
1049 (value
, mask
) = PO(value
=value
, mask
=mask
,
1050 opcode
=self
.section
.opcode
, bits
=range(0, 6))
1051 for ppc
in self
.ppc
:
1052 pairs
.append(XO(value
=value
, mask
=mask
,
1053 opcode
=ppc
.opcode
, bits
=self
.section
.bitsel
))
1056 for (value
, mask
) in pairs
:
1057 value
= Opcode
.Value(binary(value
))
1058 mask
= Opcode
.Mask(binary(mask
))
1059 result
.append(Opcode(value
=value
, mask
=mask
))
1061 return tuple(result
)
1065 opcode
= self
.section
.opcode
1067 opcode
= self
.ppc
[0].opcode
1068 if isinstance(opcode
, PatternOpcode
):
1069 value
= int(opcode
.value
)
1070 bits
= opcode
.value
.bit_length()
1071 return int(_SelectableInt(value
=value
, bits
=bits
)[0:6])
1073 return int(opcode
.value
)
1077 return tuple(ppc
.opcode
for ppc
in self
.ppc
)
1079 def match(self
, key
):
1080 for opcode
in self
.opcodes
:
1081 if opcode
.match(key
):
1088 return self
.svp64
.mode
1108 if self
.svp64
is None:
1114 return self
.ppc
.cr_in
1118 return self
.ppc
.cr_in2
1122 return self
.ppc
.cr_out
1124 ptype
= property(lambda self
: self
.svp64
.ptype
)
1125 etype
= property(lambda self
: self
.svp64
.etype
)
1127 extra_idx_in1
= property(lambda self
: self
.svp64
.extra_idx_in1
)
1128 extra_idx_in2
= property(lambda self
: self
.svp64
.extra_idx_in2
)
1129 extra_idx_in3
= property(lambda self
: self
.svp64
.extra_idx_in3
)
1130 extra_idx_out
= property(lambda self
: self
.svp64
.extra_idx_out
)
1131 extra_idx_out2
= property(lambda self
: self
.svp64
.extra_idx_out2
)
1132 extra_idx_cr_in
= property(lambda self
: self
.svp64
.extra_idx_cr_in
)
1133 extra_idx_cr_in2
= property(lambda self
: self
.svp64
.extra_idx_cr_in2
)
1134 extra_idx_cr_out
= property(lambda self
: self
.svp64
.extra_idx_cr_out
)
1136 def __contains__(self
, key
):
1137 return self
.mdwn
.operands
.__contains
__(key
)
1139 def __getitem__(self
, key
):
1140 (cls
, kwargs
) = self
.mdwn
.operands
.__getitem
__(key
)
1141 return cls(record
=self
, **kwargs
)
1145 if "Rc" not in self
:
1147 return self
["Rc"].value
1151 def __init__(self
, record
, name
):
1152 self
.__record
= record
1156 yield ("record", self
.record
)
1157 yield ("name", self
.__name
)
1160 return f
"{self.__class__.__name__}({self.name})"
1168 return self
.__record
1172 return self
.record
.fields
[self
.name
]
1174 def assemble(self
, insn
):
1175 raise NotImplementedError()
1177 def disassemble(self
, insn
,
1178 style
=Style
.NORMAL
, indent
=""):
1179 raise NotImplementedError()
1182 class DynamicOperand(Operand
):
1183 def assemble(self
, insn
, value
):
1185 if isinstance(value
, str):
1186 value
= int(value
, 0)
1188 raise ValueError("signed operands not allowed")
1191 def disassemble(self
, insn
,
1192 style
=Style
.NORMAL
, indent
=""):
1196 if style
>= Style
.VERBOSE
:
1197 span
= map(str, span
)
1198 yield f
"{indent}{self.name}"
1199 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1200 yield f
"{indent}{indent}{', '.join(span)}"
1202 yield str(int(value
))
1205 class SignedOperand(DynamicOperand
):
1206 def assemble(self
, insn
, value
):
1207 if isinstance(value
, str):
1208 value
= int(value
, 0)
1209 return super().assemble(value
=value
, insn
=insn
)
1211 def assemble(self
, insn
, value
):
1213 if isinstance(value
, str):
1214 value
= int(value
, 0)
1217 def disassemble(self
, insn
,
1218 style
=Style
.NORMAL
, indent
=""):
1220 value
= insn
[span
].to_signed_int()
1221 sign
= "-" if (value
< 0) else ""
1224 if style
>= Style
.VERBOSE
:
1225 span
= map(str, span
)
1226 yield f
"{indent}{self.name}"
1227 yield f
"{indent}{indent}{sign}{value}"
1228 yield f
"{indent}{indent}{', '.join(span)}"
1230 yield f
"{sign}{value}"
1233 class StaticOperand(Operand
):
1234 def __init__(self
, record
, name
, value
):
1235 self
.__value
= value
1236 return super().__init
__(record
=record
, name
=name
)
1239 yield ("value", self
.__value
)
1240 yield from super().__iter
__()
1243 return f
"{self.__class__.__name__}({self.name}, value={self.value})"
1249 def assemble(self
, insn
):
1250 insn
[self
.span
] = self
.value
1252 def disassemble(self
, insn
,
1253 style
=Style
.NORMAL
, indent
=""):
1257 if style
>= Style
.VERBOSE
:
1258 span
= map(str, span
)
1259 yield f
"{indent}{self.name}"
1260 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1261 yield f
"{indent}{indent}{', '.join(span)}"
1263 yield str(int(value
))
1266 class SpanStaticOperand(StaticOperand
):
1267 def __init__(self
, record
, name
, value
, span
):
1268 self
.__span
= tuple(span
)
1269 return super().__init
__(record
=record
, name
=name
, value
=value
)
1272 yield ("span", self
.__span
)
1273 yield from super().__iter
__()
1280 class POStaticOperand(SpanStaticOperand
):
1281 def __init__(self
, record
, value
):
1282 return super().__init
__(record
=record
, name
="PO",
1283 value
=value
, span
=range(0, 6))
1286 for (key
, value
) in super().__iter
__():
1287 if key
not in {"name", "span"}:
1291 class XOStaticOperand(SpanStaticOperand
):
1292 def __init__(self
, record
, value
, span
):
1293 bits
= record
.section
.bitsel
1294 value
= _SelectableInt(value
=value
, bits
=len(bits
))
1295 span
= dict(zip(bits
, range(len(bits
))))
1296 span_rev
= {value
:key
for (key
, value
) in span
.items()}
1298 # This part is tricky: we cannot use record.operands,
1299 # as this code is called by record.static_operands method.
1300 for (cls
, kwargs
) in record
.mdwn
.operands
:
1301 operand
= cls(record
=record
, **kwargs
)
1302 for idx
in operand
.span
:
1303 rev
= span
.pop(idx
, None)
1305 span_rev
.pop(rev
, None)
1307 value
= int(_selectconcat(*(value
[bit
] for bit
in span
.values())))
1308 span
= tuple(span
.keys())
1310 return super().__init
__(record
=record
, name
="XO",
1311 value
=value
, span
=span
)
1314 for (key
, value
) in super().__iter
__():
1315 if key
not in {"name"}:
1319 class ImmediateOperand(DynamicOperand
):
1323 class SignedImmediateOperand(SignedOperand
, ImmediateOperand
):
1327 class NonZeroOperand(DynamicOperand
):
1328 def assemble(self
, insn
, value
):
1329 if isinstance(value
, str):
1330 value
= int(value
, 0)
1331 if not isinstance(value
, int):
1332 raise ValueError("non-integer operand")
1334 raise ValueError("non-zero operand")
1336 return super().assemble(value
=value
, insn
=insn
)
1338 def disassemble(self
, insn
,
1339 style
=Style
.NORMAL
, indent
=""):
1343 if style
>= Style
.VERBOSE
:
1344 span
= map(str, span
)
1345 yield f
"{indent}{self.name}"
1346 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1347 yield f
"{indent}{indent}{', '.join(span)}"
1349 yield str(int(value
) + 1)
1352 class ExtendableOperand(DynamicOperand
):
1353 def sv_spec_enter(self
, value
, span
):
1354 return (value
, span
)
1356 def sv_spec(self
, insn
):
1360 span
= tuple(map(str, span
))
1362 if isinstance(insn
, SVP64Instruction
):
1363 (origin_value
, origin_span
) = (value
, span
)
1364 (value
, span
) = self
.sv_spec_enter(value
=value
, span
=span
)
1366 for extra_idx
in self
.extra_idx
:
1367 if self
.record
.etype
is _SVEType
.EXTRA3
:
1368 spec
= insn
.prefix
.rm
.extra3
[extra_idx
]
1369 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1370 spec
= insn
.prefix
.rm
.extra2
[extra_idx
]
1372 raise ValueError(self
.record
.etype
)
1375 vector
= bool(spec
[0])
1376 spec_span
= spec
.__class
__
1377 if self
.record
.etype
is _SVEType
.EXTRA3
:
1378 spec_span
= tuple(map(str, spec_span
[1, 2]))
1380 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1381 spec_span
= tuple(map(str, spec_span
[1,]))
1382 spec
= _SelectableInt(value
=spec
[1].value
, bits
=2)
1385 spec_span
= (spec_span
+ ("{0}",))
1387 spec_span
= (("{0}",) + spec_span
)
1389 raise ValueError(self
.record
.etype
)
1391 vector_shift
= (2 + (5 - value
.bits
))
1392 scalar_shift
= value
.bits
1393 spec_shift
= (5 - value
.bits
)
1395 bits
= (len(span
) + len(spec_span
))
1396 value
= _SelectableInt(value
=value
.value
, bits
=bits
)
1397 spec
= _SelectableInt(value
=spec
.value
, bits
=bits
)
1399 value
= ((value
<< vector_shift
) |
(spec
<< spec_shift
))
1400 span
= (span
+ spec_span
+ ((spec_shift
* ("{0}",))))
1402 value
= ((spec
<< scalar_shift
) | value
)
1403 span
= ((spec_shift
* ("{0}",)) + spec_span
+ span
)
1405 (value
, span
) = self
.sv_spec_leave(value
=value
, span
=span
,
1406 origin_value
=origin_value
, origin_span
=origin_span
)
1408 return (vector
, value
, span
)
1410 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1411 return (value
, span
)
1414 def extra_idx(self
):
1415 for (key
, record
) in self
.record
.svp64
.extras
.items():
1416 if record
["reg"].alias
is self
.extra_reg
.alias
:
1420 def extra_reg(self
):
1421 return _Reg(self
.name
)
1423 def remap(self
, value
, vector
):
1424 raise NotImplementedError()
1426 def assemble(self
, value
, insn
, prefix
):
1429 if isinstance(value
, str):
1430 value
= value
.lower()
1431 if value
.startswith("%"):
1433 if value
.startswith("*"):
1434 if not isinstance(insn
, SVP64Instruction
):
1435 raise ValueError(value
)
1438 if value
.startswith(prefix
):
1439 if (self
.extra_reg
.or_zero
and (value
== f
"{prefix}0")):
1440 raise ValueError(value
)
1441 value
= value
[len(prefix
):]
1442 value
= int(value
, 0)
1444 if isinstance(insn
, SVP64Instruction
):
1445 (value
, extra
) = self
.remap(value
=value
, vector
=vector
)
1447 for extra_idx
in self
.extra_idx
:
1448 if self
.record
.etype
is _SVEType
.EXTRA3
:
1449 insn
.prefix
.rm
.extra3
[extra_idx
] = extra
1450 elif self
.record
.etype
is _SVEType
.EXTRA2
:
1451 insn
.prefix
.rm
.extra2
[extra_idx
] = extra
1453 raise ValueError(self
.record
.etype
)
1455 return super().assemble(value
=value
, insn
=insn
)
1457 def disassemble(self
, insn
,
1458 style
=Style
.NORMAL
, prefix
="", indent
=""):
1459 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1461 if (self
.extra_reg
.or_zero
and (value
== 0)):
1464 if style
>= Style
.VERBOSE
:
1465 mode
= "vector" if vector
else "scalar"
1466 yield f
"{indent}{self.name} ({mode})"
1467 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1468 yield f
"{indent}{indent}{', '.join(span)}"
1469 if isinstance(insn
, SVP64Instruction
):
1470 for extra_idx
in frozenset(self
.extra_idx
):
1471 if self
.record
.etype
is _SVEType
.NONE
:
1472 yield f
"{indent}{indent}extra[none]"
1474 etype
= repr(self
.record
.etype
).lower()
1475 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1477 vector
= "*" if vector
else ""
1478 yield f
"{vector}{prefix}{int(value)}"
1481 class SimpleRegisterOperand(ExtendableOperand
):
1482 def remap(self
, value
, vector
):
1484 extra
= (value
& 0b11)
1485 value
= (value
>> 2)
1487 extra
= (value
>> 5)
1488 value
= (value
& 0b11111)
1490 # now sanity-check. EXTRA3 is ok, EXTRA2 has limits
1491 # (and shrink to a single bit if ok)
1492 if self
.record
.etype
is _SVEType
.EXTRA2
:
1494 # range is r0-r127 in increments of 2 (r0 r2 ... r126)
1495 assert (extra
& 0b01) == 0, \
1496 ("vector field %s cannot fit into EXTRA2" % value
)
1497 extra
= (0b10 |
(extra
>> 1))
1499 # range is r0-r63 in increments of 1
1500 assert (extra
>> 1) == 0, \
1501 ("scalar GPR %d cannot fit into EXTRA2" % value
)
1503 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1505 # EXTRA3 vector bit needs marking
1508 raise ValueError(self
.record
.etype
)
1510 return (value
, extra
)
1513 class GPROperand(SimpleRegisterOperand
):
1514 def assemble(self
, insn
, value
):
1515 return super().assemble(value
=value
, insn
=insn
, prefix
="r")
1517 def disassemble(self
, insn
,
1518 style
=Style
.NORMAL
, indent
=""):
1519 prefix
= "" if (style
<= Style
.SHORT
) else "r"
1520 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1521 style
=style
, indent
=indent
)
1524 class GPRPairOperand(GPROperand
):
1528 class FPROperand(SimpleRegisterOperand
):
1529 def assemble(self
, insn
, value
):
1530 return super().assemble(value
=value
, insn
=insn
, prefix
="f")
1532 def disassemble(self
, insn
,
1533 style
=Style
.NORMAL
, indent
=""):
1534 prefix
= "" if (style
<= Style
.SHORT
) else "f"
1535 yield from super().disassemble(prefix
=prefix
, insn
=insn
,
1536 style
=style
, indent
=indent
)
1539 class FPRPairOperand(FPROperand
):
1543 class ConditionRegisterFieldOperand(ExtendableOperand
):
1544 def pattern(name_pattern
):
1545 (name
, pattern
) = name_pattern
1546 return (name
, _re
.compile(f
"^{pattern}$", _re
.S
))
1555 CR
= r
"(?:CR|cr)([0-9]+)"
1557 BIT
= rf
"({'|'.join(CONDS.keys())})"
1558 LBIT
= fr
"{BIT}\s*\+\s*" # BIT+
1559 RBIT
= fr
"\s*\+\s*{BIT}" # +BIT
1560 CRN
= fr
"{CR}\s*\*\s*{N}" # CR*N
1561 NCR
= fr
"{N}\s*\*\s*{CR}" # N*CR
1562 XCR
= fr
"{CR}\.{BIT}"
1563 PATTERNS
= tuple(map(pattern
, (
1568 ("BIT+CR", (LBIT
+ CR
)),
1569 ("CR+BIT", (CR
+ RBIT
)),
1570 ("BIT+CR*N", (LBIT
+ CRN
)),
1571 ("CR*N+BIT", (CRN
+ RBIT
)),
1572 ("BIT+N*CR", (LBIT
+ NCR
)),
1573 ("N*CR+BIT", (NCR
+ RBIT
)),
1576 def remap(self
, value
, vector
, regtype
):
1577 if regtype
is _RegType
.CR_5BIT
:
1578 subvalue
= (value
& 0b11)
1582 extra
= (value
& 0b1111)
1585 extra
= (value
>> 3)
1588 if self
.record
.etype
is _SVEType
.EXTRA2
:
1590 assert (extra
& 0b111) == 0, \
1591 "vector CR cannot fit into EXTRA2"
1592 extra
= (0b10 |
(extra
>> 3))
1594 assert (extra
>> 1) == 0, \
1595 "scalar CR cannot fit into EXTRA2"
1597 elif self
.record
.etype
is _SVEType
.EXTRA3
:
1599 assert (extra
& 0b11) == 0, \
1600 "vector CR cannot fit into EXTRA3"
1601 extra
= (0b100 |
(extra
>> 2))
1603 assert (extra
>> 2) == 0, \
1604 "scalar CR cannot fit into EXTRA3"
1607 if regtype
is _RegType
.CR_5BIT
:
1608 value
= ((value
<< 2) | subvalue
)
1610 return (value
, extra
)
1612 def assemble(self
, insn
, value
):
1613 if isinstance(value
, str):
1616 if value
.startswith("*"):
1617 if not isinstance(insn
, SVP64Instruction
):
1618 raise ValueError(value
)
1622 for (name
, pattern
) in reversed(self
.__class
__.PATTERNS
):
1623 match
= pattern
.match(value
)
1624 if match
is not None:
1625 keys
= name
.replace("+", "_").replace("*", "_").split("_")
1626 values
= match
.groups()
1627 match
= dict(zip(keys
, values
))
1628 CR
= int(match
["CR"])
1632 N
= int(match
.get("N", "1"))
1633 BIT
= self
.__class
__.CONDS
[match
.get("BIT", "lt")]
1634 value
= ((CR
* N
) + BIT
)
1641 return super().assemble(value
=value
, insn
=insn
, prefix
="cr")
1643 def disassemble(self
, insn
,
1644 style
=Style
.NORMAL
, prefix
="", indent
=""):
1645 (vector
, value
, span
) = self
.sv_spec(insn
=insn
)
1647 if style
>= Style
.VERBOSE
:
1648 mode
= "vector" if vector
else "scalar"
1649 yield f
"{indent}{self.name} ({mode})"
1650 yield f
"{indent}{indent}{int(value):0{value.bits}b}"
1651 yield f
"{indent}{indent}{', '.join(span)}"
1652 if isinstance(insn
, SVP64Instruction
):
1653 for extra_idx
in frozenset(self
.extra_idx
):
1654 if self
.record
.etype
is _SVEType
.NONE
:
1655 yield f
"{indent}{indent}extra[none]"
1657 etype
= repr(self
.record
.etype
).lower()
1658 yield f
"{indent}{indent}{etype}{extra_idx!r}"
1660 vector
= "*" if vector
else ""
1661 CR
= int(value
>> 2)
1663 cond
= ("lt", "gt", "eq", "so")[CC
]
1664 if style
>= Style
.NORMAL
:
1666 if isinstance(insn
, SVP64Instruction
):
1667 yield f
"{vector}cr{CR}.{cond}"
1669 yield f
"4*cr{CR}+{cond}"
1673 yield f
"{vector}{prefix}{int(value)}"
1676 class CR3Operand(ConditionRegisterFieldOperand
):
1677 def remap(self
, value
, vector
):
1678 return super().remap(value
=value
, vector
=vector
,
1679 regtype
=_RegType
.CR_3BIT
)
1682 class CR5Operand(ConditionRegisterFieldOperand
):
1683 def remap(self
, value
, vector
):
1684 return super().remap(value
=value
, vector
=vector
,
1685 regtype
=_RegType
.CR_5BIT
)
1687 def sv_spec_enter(self
, value
, span
):
1688 value
= _SelectableInt(value
=(value
.value
>> 2), bits
=3)
1689 return (value
, span
)
1691 def sv_spec_leave(self
, value
, span
, origin_value
, origin_span
):
1692 value
= _selectconcat(value
, origin_value
[3:5])
1694 return (value
, span
)
1697 class EXTSOperand(SignedOperand
):
1698 field
: str # real name to report
1699 nz
: int = 0 # number of zeros
1700 fmt
: str = "d" # integer formatter
1702 def __init__(self
, record
, name
, field
, nz
=0, fmt
="d"):
1703 self
.__field
= field
1706 return super().__init
__(record
=record
, name
=name
)
1722 return self
.record
.fields
[self
.field
]
1724 def assemble(self
, insn
, value
):
1726 if isinstance(value
, str):
1727 value
= int(value
, 0)
1728 insn
[span
] = (value
>> self
.nz
)
1730 def disassemble(self
, insn
,
1731 style
=Style
.NORMAL
, indent
=""):
1733 value
= insn
[span
].to_signed_int()
1734 sign
= "-" if (value
< 0) else ""
1735 value
= (abs(value
) << self
.nz
)
1737 if style
>= Style
.VERBOSE
:
1738 span
= (tuple(map(str, span
)) + (("{0}",) * self
.nz
))
1739 zeros
= ("0" * self
.nz
)
1740 hint
= f
"{self.name} = EXTS({self.field} || {zeros})"
1741 yield f
"{indent * 1}{hint}"
1742 yield f
"{indent * 2}{self.field}"
1743 yield f
"{indent * 3}{sign}{value:{self.fmt}}"
1744 yield f
"{indent * 3}{', '.join(span)}"
1746 yield f
"{sign}{value:{self.fmt}}"
1749 class TargetAddrOperand(EXTSOperand
):
1750 def __init__(self
, record
, name
, field
):
1751 return super().__init
__(record
=record
, name
=name
, field
=field
,
1755 class TargetAddrOperandLI(TargetAddrOperand
):
1756 def __init__(self
, record
, name
):
1757 return super().__init
__(record
=record
, name
=name
, field
="LI")
1760 class TargetAddrOperandBD(TargetAddrOperand
):
1761 def __init__(self
, record
, name
):
1762 return super().__init
__(record
=record
, name
=name
, field
="BD")
1765 class EXTSOperandDS(EXTSOperand
, ImmediateOperand
):
1766 def __init__(self
, record
, name
):
1767 return super().__init
__(record
=record
, name
=name
, field
="DS", nz
=2)
1770 class EXTSOperandDQ(EXTSOperand
, ImmediateOperand
):
1771 def __init__(self
, record
, name
):
1772 return super().__init
__(record
=record
, name
=name
, field
="DQ", nz
=4)
1775 class DOperandDX(SignedOperand
):
1778 cls
= lambda name
: DynamicOperand(record
=self
.record
, name
=name
)
1779 operands
= map(cls
, ("d0", "d1", "d2"))
1780 spans
= map(lambda operand
: operand
.span
, operands
)
1781 return sum(spans
, tuple())
1783 def disassemble(self
, insn
,
1784 style
=Style
.NORMAL
, indent
=""):
1786 value
= insn
[span
].to_signed_int()
1787 sign
= "-" if (value
< 0) else ""
1790 if style
>= Style
.VERBOSE
:
1797 for (subname
, subspan
) in mapping
.items():
1798 operand
= DynamicOperand(name
=subname
)
1800 span
= map(str, span
)
1801 yield f
"{indent}{indent}{operand.name} = D{subspan}"
1802 yield f
"{indent}{indent}{indent}{sign}{value}"
1803 yield f
"{indent}{indent}{indent}{', '.join(span)}"
1805 yield f
"{sign}{value}"
1808 class Instruction(_Mapping
):
1810 def integer(cls
, value
=0, bits
=None, byteorder
="little"):
1811 if isinstance(value
, (int, bytes
)) and not isinstance(bits
, int):
1812 raise ValueError(bits
)
1814 if isinstance(value
, bytes
):
1815 if ((len(value
) * 8) != bits
):
1816 raise ValueError(f
"bit length mismatch")
1817 value
= int.from_bytes(value
, byteorder
=byteorder
)
1819 if isinstance(value
, int):
1820 value
= _SelectableInt(value
=value
, bits
=bits
)
1821 elif isinstance(value
, Instruction
):
1822 value
= value
.storage
1824 if not isinstance(value
, _SelectableInt
):
1825 raise ValueError(value
)
1828 if len(value
) != bits
:
1829 raise ValueError(value
)
1831 value
= _SelectableInt(value
=value
, bits
=bits
)
1833 return cls(storage
=value
)
1836 return hash(int(self
))
1838 def __getitem__(self
, key
):
1839 return self
.storage
.__getitem
__(key
)
1841 def __setitem__(self
, key
, value
):
1842 return self
.storage
.__setitem
__(key
, value
)
1844 def bytes(self
, byteorder
="little"):
1845 nr_bytes
= (len(self
.__class
__) // 8)
1846 return int(self
).to_bytes(nr_bytes
, byteorder
=byteorder
)
1849 def record(cls
, db
, entry
):
1852 raise KeyError(entry
)
1856 def operands(cls
, record
):
1857 yield from record
.operands
1860 def static_operands(cls
, record
):
1861 return filter(lambda operand
: isinstance(operand
, StaticOperand
),
1862 cls
.operands(record
=record
))
1865 def dynamic_operands(cls
, record
):
1866 return filter(lambda operand
: isinstance(operand
, DynamicOperand
),
1867 cls
.operands(record
=record
))
1869 def spec(self
, record
, prefix
):
1870 dynamic_operands
= tuple(map(_operator
.itemgetter(0),
1871 self
.spec_dynamic_operands(record
=record
)))
1873 static_operands
= []
1874 for (name
, value
) in self
.spec_static_operands(record
=record
):
1875 static_operands
.append(f
"{name}={value}")
1878 if dynamic_operands
:
1880 operands
+= ",".join(dynamic_operands
)
1883 operands
+= " ".join(static_operands
)
1885 return f
"{prefix}{record.name}{operands}"
1887 def spec_static_operands(self
, record
):
1888 for operand
in self
.static_operands(record
=record
):
1889 if not isinstance(operand
, (POStaticOperand
, XOStaticOperand
)):
1890 yield (operand
.name
, operand
.value
)
1892 def spec_dynamic_operands(self
, record
, style
=Style
.NORMAL
):
1896 for operand
in self
.dynamic_operands(record
=record
):
1898 value
= " ".join(operand
.disassemble(insn
=self
,
1899 style
=min(style
, Style
.NORMAL
)))
1901 name
= f
"{imm_name}({name})"
1902 value
= f
"{imm_value}({value})"
1904 if isinstance(operand
, ImmediateOperand
):
1912 def assemble(cls
, record
, arguments
=None):
1913 if arguments
is None:
1916 insn
= cls
.integer(value
=0)
1918 for operand
in cls
.static_operands(record
=record
):
1919 operand
.assemble(insn
=insn
)
1921 arguments
= Arguments(record
=record
,
1922 arguments
=arguments
, operands
=cls
.dynamic_operands(record
=record
))
1923 for (value
, operand
) in arguments
:
1924 operand
.assemble(insn
=insn
, value
=value
)
1928 def disassemble(self
, record
,
1930 style
=Style
.NORMAL
):
1931 raise NotImplementedError()
1934 class WordInstruction(Instruction
):
1935 _
: _Field
= range(0, 32)
1936 PO
: _Field
= range(0, 6)
1939 def integer(cls
, value
, byteorder
="little"):
1940 return super().integer(bits
=32, value
=value
, byteorder
=byteorder
)
1945 for idx
in range(32):
1946 bit
= int(self
[idx
])
1948 return "".join(map(str, bits
))
1950 def disassemble(self
, record
,
1952 style
=Style
.NORMAL
):
1953 if style
<= Style
.SHORT
:
1956 blob
= self
.bytes(byteorder
=byteorder
)
1957 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
1961 yield f
"{blob}.long 0x{int(self):08x}"
1964 # awful temporary hack: workaround for ld-update
1965 # https://bugs.libre-soc.org/show_bug.cgi?id=1056#c2
1966 # XXX TODO must check that *EXTENDED* RA != extended-RT
1967 if (record
.svp64
is not None and
1968 record
.mode
== _SVMode
.LDST_IMM
and
1969 'u' in record
.name
):
1970 yield f
"{blob}.long 0x{int(self):08x}"
1974 if style
is Style
.LEGACY
:
1976 for operand
in self
.dynamic_operands(record
=record
):
1977 if isinstance(operand
, (GPRPairOperand
, FPRPairOperand
)):
1980 if style
is Style
.LEGACY
and (paired
or record
.ppc
.unofficial
):
1981 yield f
"{blob}.long 0x{int(self):08x}"
1983 operands
= tuple(map(_operator
.itemgetter(1),
1984 self
.spec_dynamic_operands(record
=record
, style
=style
)))
1986 operands
= ",".join(operands
)
1987 yield f
"{blob}{record.name} {operands}"
1989 yield f
"{blob}{record.name}"
1991 if style
>= Style
.VERBOSE
:
1993 binary
= self
.binary
1994 spec
= self
.spec(record
=record
, prefix
="")
1995 yield f
"{indent}spec"
1996 yield f
"{indent}{indent}{spec}"
1997 yield f
"{indent}pcode"
1998 for stmt
in record
.mdwn
.pcode
:
1999 yield f
"{indent}{indent}{stmt}"
2000 yield f
"{indent}binary"
2001 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
2002 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
2003 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
2004 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
2005 yield f
"{indent}opcodes"
2006 for opcode
in record
.opcodes
:
2007 yield f
"{indent}{indent}{opcode!r}"
2008 for operand
in self
.operands(record
=record
):
2009 yield from operand
.disassemble(insn
=self
,
2010 style
=style
, indent
=indent
)
2014 class PrefixedInstruction(Instruction
):
2015 class Prefix(WordInstruction
.remap(range(0, 32))):
2018 class Suffix(WordInstruction
.remap(range(32, 64))):
2021 _
: _Field
= range(64)
2027 def integer(cls
, value
, byteorder
="little"):
2028 return super().integer(bits
=64, value
=value
, byteorder
=byteorder
)
2031 def pair(cls
, prefix
=0, suffix
=0, byteorder
="little"):
2032 def transform(value
):
2033 return WordInstruction
.integer(value
=value
,
2034 byteorder
=byteorder
)[0:32]
2036 (prefix
, suffix
) = map(transform
, (prefix
, suffix
))
2037 value
= _selectconcat(prefix
, suffix
)
2039 return super().integer(bits
=64, value
=value
)
2042 class Mode(_Mapping
):
2043 _
: _Field
= range(0, 5)
2044 sel
: _Field
= (0, 1)
2047 class ExtraRM(_Mapping
):
2048 _
: _Field
= range(0, 9)
2051 class Extra2RM(ExtraRM
):
2052 idx0
: _Field
= range(0, 2)
2053 idx1
: _Field
= range(2, 4)
2054 idx2
: _Field
= range(4, 6)
2055 idx3
: _Field
= range(6, 8)
2057 def __getitem__(self
, key
):
2063 _SVExtra
.Idx0
: self
.idx0
,
2064 _SVExtra
.Idx1
: self
.idx1
,
2065 _SVExtra
.Idx2
: self
.idx2
,
2066 _SVExtra
.Idx3
: self
.idx3
,
2069 def __setitem__(self
, key
, value
):
2070 self
[key
].assign(value
)
2073 class Extra3RM(ExtraRM
):
2074 idx0
: _Field
= range(0, 3)
2075 idx1
: _Field
= range(3, 6)
2076 idx2
: _Field
= range(6, 9)
2078 def __getitem__(self
, key
):
2083 _SVExtra
.Idx0
: self
.idx0
,
2084 _SVExtra
.Idx1
: self
.idx1
,
2085 _SVExtra
.Idx2
: self
.idx2
,
2088 def __setitem__(self
, key
, value
):
2089 self
[key
].assign(value
)
2092 class BaseRM(_Mapping
):
2093 _
: _Field
= range(24)
2094 mmode
: _Field
= (0,)
2095 mask
: _Field
= range(1, 4)
2096 elwidth
: _Field
= range(4, 6)
2097 ewsrc
: _Field
= range(6, 8)
2098 subvl
: _Field
= range(8, 10)
2099 mode
: Mode
.remap(range(19, 24))
2100 smask_extra322
: _Field
= (6,7,18,) # LDST_IDX is EXTRA332
2101 smask
: _Field
= range(16, 19) # everything else use this
2102 extra
: ExtraRM
.remap(range(10, 19))
2103 extra2
: Extra2RM
.remap(range(10, 19))
2104 extra3
: Extra3RM
.remap(range(10, 19))
2105 # XXX extra332 = (extra3[0], extra3[1], extra2[3])
2107 def specifiers(self
, record
):
2108 subvl
= int(self
.subvl
)
2116 def disassemble(self
, style
=Style
.NORMAL
):
2117 if style
>= Style
.VERBOSE
:
2119 for (name
, span
) in self
.traverse(path
="RM"):
2120 value
= self
.storage
[span
]
2122 yield f
"{indent}{int(value):0{value.bits}b}"
2123 yield f
"{indent}{', '.join(map(str, span))}"
2126 class FFRc1BaseRM(BaseRM
):
2127 def specifiers(self
, record
, mode
):
2128 inv
= _SelectableInt(value
=int(self
.inv
), bits
=1)
2129 CR
= _SelectableInt(value
=int(self
.CR
), bits
=2)
2130 mask
= int(_selectconcat(CR
, inv
))
2131 predicate
= PredicateBaseRM
.predicate(True, mask
)
2132 yield f
"{mode}={predicate}"
2134 yield from super().specifiers(record
=record
)
2137 class FFRc0BaseRM(BaseRM
):
2138 def specifiers(self
, record
, mode
):
2140 inv
= "~" if self
.inv
else ""
2141 yield f
"{mode}={inv}RC1"
2143 yield from super().specifiers(record
=record
)
2146 class SatBaseRM(BaseRM
):
2147 def specifiers(self
, record
):
2153 yield from super().specifiers(record
=record
)
2156 class ZZBaseRM(BaseRM
):
2157 def specifiers(self
, record
):
2161 yield from super().specifiers(record
=record
)
2164 class ZZCombinedBaseRM(BaseRM
):
2165 def specifiers(self
, record
):
2166 if self
.sz
and self
.dz
:
2173 yield from super().specifiers(record
=record
)
2176 class DZBaseRM(BaseRM
):
2177 def specifiers(self
, record
):
2181 yield from super().specifiers(record
=record
)
2184 class SZBaseRM(BaseRM
):
2185 def specifiers(self
, record
):
2189 yield from super().specifiers(record
=record
)
2192 class MRBaseRM(BaseRM
):
2193 def specifiers(self
, record
):
2199 yield from super().specifiers(record
=record
)
2202 class ElsBaseRM(BaseRM
):
2203 def specifiers(self
, record
):
2207 yield from super().specifiers(record
=record
)
2210 class WidthBaseRM(BaseRM
):
2212 def width(FP
, width
):
2221 width
= ("fp" + width
)
2224 def specifiers(self
, record
):
2225 # elwidths: use "w=" if same otherwise dw/sw
2226 # FIXME this should consider FP instructions
2228 dw
= WidthBaseRM
.width(FP
, int(self
.elwidth
))
2229 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2230 if record
.svp64
.mode
is _SVMode
.CROP
:
2234 sw
= WidthBaseRM
.width(FP
, int(self
.ewsrc
))
2243 yield from super().specifiers(record
=record
)
2246 class PredicateBaseRM(BaseRM
):
2248 def predicate(CR
, mask
):
2251 (False, 0b001): "1<<r3",
2252 (False, 0b010): "r3",
2253 (False, 0b011): "~r3",
2254 (False, 0b100): "r10",
2255 (False, 0b101): "~r10",
2256 (False, 0b110): "r30",
2257 (False, 0b111): "~r30",
2259 (True, 0b000): "lt",
2260 (True, 0b001): "ge",
2261 (True, 0b010): "gt",
2262 (True, 0b011): "le",
2263 (True, 0b100): "eq",
2264 (True, 0b101): "ne",
2265 (True, 0b110): "so",
2266 (True, 0b111): "ns",
2269 def specifiers(self
, record
):
2270 # predication - single and twin
2271 # use "m=" if same otherwise sm/dm
2272 CR
= (int(self
.mmode
) == 1)
2273 mask
= int(self
.mask
)
2274 sm
= dm
= PredicateBaseRM
.predicate(CR
, mask
)
2275 if record
.svp64
.ptype
is _SVPType
.P2
:
2276 # LDST_IDX smask moving to extra322 but not straight away (False)
2277 if False and record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2278 smask
= int(self
.smask_extra332
)
2280 smask
= int(self
.smask
)
2281 sm
= PredicateBaseRM
.predicate(CR
, smask
)
2290 yield from super().specifiers(record
=record
)
2293 class PredicateWidthBaseRM(WidthBaseRM
, PredicateBaseRM
):
2297 class SEABaseRM(BaseRM
):
2298 def specifiers(self
, record
):
2302 yield from super().specifiers(record
=record
)
2305 class VLiBaseRM(BaseRM
):
2306 def specifiers(self
, record
):
2310 yield from super().specifiers(record
=record
)
2313 class NormalBaseRM(PredicateWidthBaseRM
):
2316 https://libre-soc.org/openpower/sv/normal/
2321 class NormalSimpleRM(ZZCombinedBaseRM
, NormalBaseRM
):
2322 """normal: simple mode"""
2326 def specifiers(self
, record
):
2327 yield from super().specifiers(record
=record
)
2330 class NormalMRRM(MRBaseRM
, NormalBaseRM
):
2331 """normal: scalar reduce mode (mapreduce), SUBVL=1"""
2335 class NormalFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, NormalBaseRM
):
2336 """normal: Rc=1: ffirst CR sel"""
2339 CR
: BaseRM
.mode
[3, 4]
2341 def specifiers(self
, record
):
2342 yield from super().specifiers(record
=record
, mode
="ff")
2345 class NormalFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, NormalBaseRM
):
2346 """normal: Rc=0: ffirst z/nonz"""
2351 def specifiers(self
, record
):
2352 yield from super().specifiers(record
=record
, mode
="ff")
2355 class NormalSatRM(SatBaseRM
, ZZCombinedBaseRM
, NormalBaseRM
):
2356 """normal: sat mode: N=0/1 u/s, SUBVL=1"""
2362 class NormalRM(NormalBaseRM
):
2363 simple
: NormalSimpleRM
2365 ffrc1
: NormalFFRc1RM
2366 ffrc0
: NormalFFRc0RM
2370 class LDSTImmBaseRM(PredicateWidthBaseRM
):
2372 LD/ST Immediate mode
2373 https://libre-soc.org/openpower/sv/ldst/
2378 class LDSTImmSimpleRM(ElsBaseRM
, ZZBaseRM
, LDSTImmBaseRM
):
2379 """ld/st immediate: simple mode"""
2380 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2381 lf
: BaseRM
.mode
[4] # Fault-First Mode (not *Data-Dependent* Fail-First)
2387 def specifiers(self
, record
):
2393 yield from super().specifiers(record
=record
)
2396 class LDSTFFRc1RM(FFRc1BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2397 """ld/st immediate&indexed: Rc=1: ffirst CR sel"""
2400 CR
: BaseRM
.mode
[3, 4]
2402 def specifiers(self
, record
):
2403 yield from super().specifiers(record
=record
, mode
="ff")
2406 class LDSTFFRc0RM(FFRc0BaseRM
, VLiBaseRM
, LDSTImmBaseRM
):
2407 """ld/st immediate&indexed: Rc=0: ffirst z/nonz"""
2412 def specifiers(self
, record
):
2413 yield from super().specifiers(record
=record
, mode
="ff")
2416 class LDSTImmRM(LDSTImmBaseRM
):
2417 simple
: LDSTImmSimpleRM
2422 class LDSTIdxBaseRM(PredicateWidthBaseRM
):
2425 https://libre-soc.org/openpower/sv/ldst/
2430 class LDSTIdxSimpleRM(SEABaseRM
, ZZBaseRM
, LDSTIdxBaseRM
):
2431 """ld/st index: simple mode (includes element-strided and Signed-EA)"""
2432 pi
: BaseRM
.mode
[2] # Post-Increment Mode
2439 def specifiers(self
, record
):
2445 yield from super().specifiers(record
=record
)
2448 class LDSTIdxRM(LDSTIdxBaseRM
):
2449 simple
: LDSTIdxSimpleRM
2455 class CROpBaseRM(BaseRM
):
2458 https://libre-soc.org/openpower/sv/cr_ops/
2463 class CROpSimpleRM(PredicateBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2464 """crop: simple mode"""
2469 def specifiers(self
, record
):
2471 yield "rg" # simple CR Mode reports /rg
2473 yield from super().specifiers(record
=record
)
2476 class CROpMRRM(MRBaseRM
, ZZCombinedBaseRM
, CROpBaseRM
):
2477 """crop: scalar reduce mode (mapreduce)"""
2483 class CROpFF5RM(FFRc0BaseRM
, PredicateBaseRM
, VLiBaseRM
, DZBaseRM
,
2484 SZBaseRM
, CROpBaseRM
):
2485 """crop: ffirst 5-bit mode"""
2492 def specifiers(self
, record
):
2493 yield from super().specifiers(record
=record
, mode
="ff")
2496 # FIXME: almost everything in this class contradicts the specs (it doesn't)
2497 # The modes however are swapped: 5-bit is 3-bit, 3-bit is 5-bit
2498 class CROpFF3RM(FFRc1BaseRM
, PredicateBaseRM
, VLiBaseRM
, ZZBaseRM
, CROpBaseRM
):
2499 """cr_op: ffirst 3-bit mode"""
2505 def specifiers(self
, record
):
2506 yield from super().specifiers(record
=record
, mode
="ff")
2509 class CROpRM(CROpBaseRM
):
2510 simple
: CROpSimpleRM
2516 # ********************
2518 # https://libre-soc.org/openpower/sv/branches/
2519 class BranchBaseRM(BaseRM
):
2529 def specifiers(self
, record
):
2541 raise ValueError(self
.sz
)
2553 # Branch modes lack source mask.
2554 # Therefore a custom code is needed.
2555 CR
= (int(self
.mmode
) == 1)
2556 mask
= int(self
.mask
)
2557 m
= PredicateBaseRM
.predicate(CR
, mask
)
2561 yield from super().specifiers(record
=record
)
2564 class BranchSimpleRM(BranchBaseRM
):
2565 """branch: simple mode"""
2569 class BranchVLSRM(BranchBaseRM
):
2570 """branch: VLSET mode"""
2574 def specifiers(self
, record
):
2580 }[int(self
.VSb
), int(self
.VLi
)]
2582 yield from super().specifiers(record
=record
)
2585 class BranchCTRRM(BranchBaseRM
):
2586 """branch: CTR-test mode"""
2589 def specifiers(self
, record
):
2595 yield from super().specifiers(record
=record
)
2598 class BranchCTRVLSRM(BranchVLSRM
, BranchCTRRM
):
2599 """branch: CTR-test+VLSET mode"""
2603 class BranchRM(BranchBaseRM
):
2604 simple
: BranchSimpleRM
2607 ctrvls
: BranchCTRVLSRM
2618 @_dataclasses.dataclass(eq
=True, frozen
=True)
2623 def match(cls
, desc
, record
):
2624 raise NotImplementedError()
2626 def validate(self
, others
):
2629 def assemble(self
, insn
):
2630 raise NotImplementedError()
2633 @_dataclasses.dataclass(eq
=True, frozen
=True)
2634 class SpecifierWidth(Specifier
):
2638 def match(cls
, desc
, record
, etalon
):
2639 (mode
, _
, value
) = desc
.partition("=")
2641 value
= value
.strip()
2644 width
= _SVP64Width(value
)
2646 return cls(record
=record
, width
=width
)
2649 @_dataclasses.dataclass(eq
=True, frozen
=True)
2650 class SpecifierW(SpecifierWidth
):
2652 def match(cls
, desc
, record
):
2653 return super().match(desc
=desc
, record
=record
, etalon
="w")
2655 def assemble(self
, insn
):
2656 selector
= insn
.select(record
=self
.record
)
2657 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2658 selector
.ewsrc
= self
.width
.value
2659 selector
.elwidth
= self
.width
.value
2662 @_dataclasses.dataclass(eq
=True, frozen
=True)
2663 class SpecifierSW(SpecifierWidth
):
2665 def match(cls
, desc
, record
):
2666 if record
.svp64
.mode
is _SVMode
.CROP
:
2668 return super().match(desc
=desc
, record
=record
, etalon
="sw")
2670 def assemble(self
, insn
):
2671 selector
= insn
.select(record
=self
.record
)
2672 selector
.ewsrc
= self
.width
.value
2675 @_dataclasses.dataclass(eq
=True, frozen
=True)
2676 class SpecifierDW(SpecifierWidth
):
2678 def match(cls
, desc
, record
):
2679 return super().match(desc
=desc
, record
=record
, etalon
="dw")
2681 def assemble(self
, insn
):
2682 selector
= insn
.select(record
=self
.record
)
2683 selector
.elwidth
= self
.width
.value
2686 @_dataclasses.dataclass(eq
=True, frozen
=True)
2687 class SpecifierSubVL(Specifier
):
2691 def match(cls
, desc
, record
):
2693 value
= _SVP64SubVL(desc
)
2697 return cls(record
=record
, value
=value
)
2699 def assemble(self
, insn
):
2700 selector
= insn
.select(record
=self
.record
)
2701 selector
.subvl
= int(self
.value
.value
)
2704 @_dataclasses.dataclass(eq
=True, frozen
=True)
2705 class SpecifierPredicate(Specifier
):
2710 def match(cls
, desc
, record
, mode_match
, pred_match
):
2711 (mode
, _
, pred
) = desc
.partition("=")
2714 if not mode_match(mode
):
2717 pred
= _SVP64Pred(pred
.strip())
2718 if not pred_match(pred
):
2719 raise ValueError(pred
)
2721 return cls(record
=record
, mode
=mode
, pred
=pred
)
2724 @_dataclasses.dataclass(eq
=True, frozen
=True)
2725 class SpecifierFF(SpecifierPredicate
):
2727 def match(cls
, desc
, record
):
2728 return super().match(desc
=desc
, record
=record
,
2729 mode_match
=lambda mode_arg
: mode_arg
== "ff",
2730 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2735 def assemble(self
, insn
):
2736 selector
= insn
.select(record
=self
.record
)
2737 if selector
.mode
.sel
!= 0:
2738 raise ValueError("cannot override mode")
2739 if self
.record
.svp64
.mode
is _SVMode
.CROP
:
2740 selector
.mode
.sel
= 0b01
2741 # HACK: please finally provide correct logic for CRs.
2742 if self
.pred
in (_SVP64Pred
.RC1
, _SVP64Pred
.RC1_N
):
2743 selector
.mode
[2] = (self
.pred
is _SVP64Pred
.RC1_N
)
2745 selector
.mode
[2] = self
.pred
.inv
2746 selector
.mode
[3, 4] = self
.pred
.state
2748 selector
.mode
.sel
= 0b01 if self
.mode
== "ff" else 0b11
2749 selector
.inv
= self
.pred
.inv
2751 selector
.CR
= self
.pred
.state
2753 selector
.RC1
= self
.pred
.state
2756 @_dataclasses.dataclass(eq
=True, frozen
=True)
2757 class SpecifierMask(SpecifierPredicate
):
2759 def match(cls
, desc
, record
, mode
):
2760 return super().match(desc
=desc
, record
=record
,
2761 mode_match
=lambda mode_arg
: mode_arg
== mode
,
2762 pred_match
=lambda pred_arg
: pred_arg
.mode
in (
2767 def assemble(self
, insn
):
2768 raise NotImplementedError()
2771 @_dataclasses.dataclass(eq
=True, frozen
=True)
2772 class SpecifierM(SpecifierMask
):
2774 def match(cls
, desc
, record
):
2775 return super().match(desc
=desc
, record
=record
, mode
="m")
2777 def validate(self
, others
):
2779 if isinstance(spec
, SpecifierSM
):
2780 raise ValueError("source-mask and predicate mask conflict")
2781 elif isinstance(spec
, SpecifierDM
):
2782 raise ValueError("dest-mask and predicate mask conflict")
2784 def assemble(self
, insn
):
2785 selector
= insn
.select(record
=self
.record
)
2786 selector
.mask
= int(self
.pred
)
2787 if ((self
.record
.ptype
is _SVPType
.P2
) and
2788 (self
.record
.svp64
.mode
is not _SVMode
.BRANCH
)):
2789 selector
.smask
= int(self
.pred
)
2790 # LDST_IDX smask moving to extra322 but not straight away (False)
2791 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2792 selector
.smask_extra332
= int(self
.pred
)
2794 selector
.smask
= int(self
.pred
)
2796 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2799 @_dataclasses.dataclass(eq
=True, frozen
=True)
2800 class SpecifierSM(SpecifierMask
):
2802 def match(cls
, desc
, record
):
2803 return super().match(desc
=desc
, record
=record
, mode
="sm")
2805 def validate(self
, others
):
2806 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2807 raise ValueError("source-mask on non-twin predicate")
2809 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2812 if isinstance(spec
, SpecifierDM
):
2816 raise ValueError("missing dest-mask in CR twin predication")
2817 if self
.pred
.mode
!= twin
.pred
.mode
:
2818 raise ValueError(f
"predicate masks mismatch: "
2819 f
"{self.pred!r} vs {twin.pred!r}")
2821 def assemble(self
, insn
):
2822 selector
= insn
.select(record
=self
.record
)
2823 # LDST_IDX smask moving to extra322 but not straight away (False)
2824 if False and self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
2825 selector
.smask_extra332
= int(self
.pred
)
2827 selector
.smask
= int(self
.pred
)
2828 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2831 @_dataclasses.dataclass(eq
=True, frozen
=True)
2832 class SpecifierDM(SpecifierMask
):
2834 def match(cls
, desc
, record
):
2835 return super().match(desc
=desc
, record
=record
, mode
="dm")
2837 def validate(self
, others
):
2838 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2839 raise ValueError("dest-mask on non-twin predicate")
2841 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2844 if isinstance(spec
, SpecifierSM
):
2848 raise ValueError("missing source-mask in CR twin predication")
2849 if self
.pred
.mode
!= twin
.pred
.mode
:
2850 raise ValueError(f
"predicate masks mismatch: "
2851 f
"{self.pred!r} vs {twin.pred!r}")
2853 def assemble(self
, insn
):
2854 selector
= insn
.select(record
=self
.record
)
2855 selector
.mask
= int(self
.pred
)
2856 selector
.mmode
= (self
.pred
.mode
is _SVP64PredMode
.CR
)
2859 @_dataclasses.dataclass(eq
=True, frozen
=True)
2860 class SpecifierZZ(Specifier
):
2862 def match(cls
, desc
, record
):
2866 return cls(record
=record
)
2868 def validate(self
, others
):
2870 # Since zz takes precedence (overrides) sz and dz,
2871 # treat them as mutually exclusive.
2872 if isinstance(spec
, (SpecifierSZ
, SpecifierDZ
)):
2873 raise ValueError("mutually exclusive predicate masks")
2875 def assemble(self
, insn
):
2876 selector
= insn
.select(record
=self
.record
)
2877 if hasattr(selector
, "zz"): # this should be done in a different way
2884 @_dataclasses.dataclass(eq
=True, frozen
=True)
2885 class SpecifierXZ(Specifier
):
2887 hint
: str = _dataclasses
.field(repr=False)
2890 def match(cls
, desc
, record
, etalon
, hint
):
2894 return cls(desc
=desc
, record
=record
, hint
=hint
)
2896 def validate(self
, others
):
2897 if self
.record
.svp64
.ptype
is _SVPType
.P1
:
2898 raise ValueError(f
"{self.hint} on non-twin predicate")
2900 if self
.pred
.mode
is _SVP64PredMode
.CR
:
2903 if isinstance(spec
, SpecifierXZ
):
2907 raise ValueError(f
"missing {self.hint} in CR twin predication")
2908 if self
.pred
!= twin
.pred
:
2909 raise ValueError(f
"predicate masks mismatch: "
2910 f
"{self.pred!r} vs {twin.pred!r}")
2912 def assemble(self
, insn
):
2913 selector
= insn
.select(record
=self
.record
)
2914 setattr(selector
, self
.desc
, 1)
2917 @_dataclasses.dataclass(eq
=True, frozen
=True)
2918 class SpecifierSZ(SpecifierXZ
):
2920 def match(cls
, desc
, record
):
2921 return super().match(desc
=desc
, record
=record
,
2922 etalon
="sz", hint
="source-mask")
2924 def validate(self
, others
):
2926 if self
.record
.svp64
.mode
is not _SVMode
.CROP
:
2927 if isinstance(spec
, SpecifierFF
):
2928 raise ValueError("source-zero not allowed in ff mode")
2931 @_dataclasses.dataclass(eq
=True, frozen
=True)
2932 class SpecifierDZ(SpecifierXZ
):
2934 def match(cls
, desc
, record
):
2935 return super().match(desc
=desc
, record
=record
,
2936 etalon
="dz", hint
="dest-mask")
2938 def validate(self
, others
):
2940 if ((self
.record
.svp64
.mode
is not _SVMode
.CROP
) and
2941 isinstance(spec
, SpecifierFF
) and
2942 (spec
.pred
.mode
is _SVP64PredMode
.RC1
)):
2943 raise ValueError(f
"dest-zero not allowed in ff mode BO")
2946 @_dataclasses.dataclass(eq
=True, frozen
=True)
2947 class SpecifierEls(Specifier
):
2949 def match(cls
, desc
, record
):
2953 if record
.svp64
.mode
not in (_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
):
2954 raise ValueError("els is only valid in ld/st modes, not "
2955 "%s" % str(self
.record
.svp64
.mode
))
2957 return cls(record
=record
)
2959 def assemble(self
, insn
):
2960 if self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
: # stride mode
2961 insn
.prefix
.rm
.mode
[1] = 0
2963 selector
= insn
.select(record
=self
.record
)
2968 @_dataclasses.dataclass(eq
=True, frozen
=True)
2969 class SpecifierSEA(Specifier
):
2971 def match(cls
, desc
, record
):
2975 return cls(record
=record
)
2977 def validate(self
, others
):
2978 if self
.record
.svp64
.mode
is not _SVMode
.LDST_IDX
:
2979 raise ValueError("sea is only valid in ld/st modes, not "
2980 "%s" % str(self
.record
.svp64
.mode
))
2983 if isinstance(spec
, SpecifierFF
):
2984 raise ValueError(f
"sea cannot be used in ff mode")
2986 def assemble(self
, insn
):
2987 selector
= insn
.select(record
=self
.record
)
2988 if selector
.mode
.sel
not in (0b10, 0b00):
2989 raise ValueError("sea is only valid for normal and els modes, "
2990 "not %d" % int(selector
.mode
.sel
))
2994 @_dataclasses.dataclass(eq
=True, frozen
=True)
2995 class SpecifierSat(Specifier
):
3000 def match(cls
, desc
, record
, etalon
, sign
):
3004 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.LDST_IMM
,
3006 raise ValueError("only normal, ld/st imm and "
3007 "ld/st idx modes supported")
3009 return cls(record
=record
, desc
=desc
, sign
=sign
)
3011 def assemble(self
, insn
):
3012 selector
= insn
.select(record
=self
.record
)
3013 selector
.mode
[0] = 0b1
3014 selector
.mode
[1] = 0b0
3015 selector
.N
= int(self
.sign
)
3018 @_dataclasses.dataclass(eq
=True, frozen
=True)
3019 class SpecifierSatS(SpecifierSat
):
3021 def match(cls
, desc
, record
):
3022 return super().match(desc
=desc
, record
=record
,
3023 etalon
="sats", sign
=True)
3026 @_dataclasses.dataclass(eq
=True, frozen
=True)
3027 class SpecifierSatU(SpecifierSat
):
3029 def match(cls
, desc
, record
):
3030 return super().match(desc
=desc
, record
=record
,
3031 etalon
="satu", sign
=False)
3034 @_dataclasses.dataclass(eq
=True, frozen
=True)
3035 class SpecifierMapReduce(Specifier
):
3039 def match(cls
, record
, RG
):
3040 if record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3041 raise ValueError("only normal and crop modes supported")
3043 return cls(record
=record
, RG
=RG
)
3045 def assemble(self
, insn
):
3046 selector
= insn
.select(record
=self
.record
)
3047 if self
.record
.svp64
.mode
not in (_SVMode
.NORMAL
, _SVMode
.CROP
):
3048 raise ValueError("only normal and crop modes supported")
3049 selector
.mode
[0] = 0
3050 selector
.mode
[1] = 0
3051 selector
.mode
[2] = 1
3052 selector
.RG
= self
.RG
3055 @_dataclasses.dataclass(eq
=True, frozen
=True)
3056 class SpecifierMR(SpecifierMapReduce
):
3058 def match(cls
, desc
, record
):
3062 return super().match(record
=record
, RG
=False)
3065 @_dataclasses.dataclass(eq
=True, frozen
=True)
3066 class SpecifierMRR(SpecifierMapReduce
):
3068 def match(cls
, desc
, record
):
3072 return super().match(record
=record
, RG
=True)
3075 @_dataclasses.dataclass(eq
=True, frozen
=True)
3076 class SpecifierBranch(Specifier
):
3078 def match(cls
, desc
, record
, etalon
):
3082 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3083 raise ValueError("only branch modes supported")
3085 return cls(record
=record
)
3088 @_dataclasses.dataclass(eq
=True, frozen
=True)
3089 class SpecifierAll(SpecifierBranch
):
3091 def match(cls
, desc
, record
):
3092 return super().match(desc
=desc
, record
=record
, etalon
="all")
3094 def assemble(self
, insn
):
3095 selector
= insn
.select(record
=self
.record
)
3099 @_dataclasses.dataclass(eq
=True, frozen
=True)
3100 class SpecifierSNZ(Specifier
):
3102 def match(cls
, desc
, record
):
3106 if record
.svp64
.mode
not in (_SVMode
.BRANCH
, _SVMode
.CROP
):
3107 raise ValueError("only branch and crop modes supported")
3109 return cls(record
=record
)
3111 def assemble(self
, insn
):
3112 selector
= insn
.select(record
=self
.record
)
3113 if self
.record
.svp64
.mode
in (_SVMode
.CROP
, _SVMode
.BRANCH
):
3115 if self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3118 raise ValueError("only branch and crop modes supported")
3121 @_dataclasses.dataclass(eq
=True, frozen
=True)
3122 class SpecifierSL(SpecifierBranch
):
3124 def match(cls
, desc
, record
):
3125 return super().match(desc
=desc
, record
=record
, etalon
="sl")
3127 def assemble(self
, insn
):
3128 selector
= insn
.select(record
=self
.record
)
3132 @_dataclasses.dataclass(eq
=True, frozen
=True)
3133 class SpecifierSLu(SpecifierBranch
):
3135 def match(cls
, desc
, record
):
3136 return super().match(desc
=desc
, record
=record
, etalon
="slu")
3138 def assemble(self
, insn
):
3139 selector
= insn
.select(record
=self
.record
)
3143 @_dataclasses.dataclass(eq
=True, frozen
=True)
3144 class SpecifierLRu(SpecifierBranch
):
3146 def match(cls
, desc
, record
):
3147 return super().match(desc
=desc
, record
=record
, etalon
="lru")
3149 def assemble(self
, insn
):
3150 selector
= insn
.select(record
=self
.record
)
3154 @_dataclasses.dataclass(eq
=True, frozen
=True)
3155 class SpecifierVSXX(SpecifierBranch
):
3160 def match(cls
, desc
, record
, etalon
, VSb
, VLi
):
3164 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3165 raise ValueError("only branch modes supported")
3167 return cls(record
=record
, VSb
=VSb
, VLi
=VLi
)
3169 def assemble(self
, insn
):
3170 selector
= insn
.select(record
=self
.record
)
3172 selector
.VSb
= int(self
.VSb
)
3173 selector
.VLi
= int(self
.VLi
)
3176 @_dataclasses.dataclass(eq
=True, frozen
=True)
3177 class SpecifierVS(SpecifierVSXX
):
3179 def match(cls
, desc
, record
):
3180 return super().match(desc
=desc
, record
=record
,
3181 etalon
="vs", VSb
=False, VLi
=False)
3184 @_dataclasses.dataclass(eq
=True, frozen
=True)
3185 class SpecifierVSi(SpecifierVSXX
):
3187 def match(cls
, desc
, record
):
3188 return super().match(desc
=desc
, record
=record
,
3189 etalon
="vsi", VSb
=False, VLi
=True)
3192 @_dataclasses.dataclass(eq
=True, frozen
=True)
3193 class SpecifierVSb(SpecifierVSXX
):
3195 def match(cls
, desc
, record
):
3196 return super().match(desc
=desc
, record
=record
,
3197 etalon
="vsb", VSb
=True, VLi
=False)
3200 @_dataclasses.dataclass(eq
=True, frozen
=True)
3201 class SpecifierVSbi(SpecifierVSXX
):
3203 def match(cls
, desc
, record
):
3204 return super().match(desc
=desc
, record
=record
,
3205 etalon
="vsbi", VSb
=True, VLi
=True)
3208 @_dataclasses.dataclass(eq
=True, frozen
=True)
3209 class SpecifierCTX(Specifier
):
3213 def match(cls
, desc
, record
, etalon
, CTi
):
3217 if record
.svp64
.mode
is not _SVMode
.BRANCH
:
3218 raise ValueError("only branch modes supported")
3220 return cls(record
=record
, CTi
=CTi
)
3222 def assemble(self
, insn
):
3223 selector
= insn
.select(record
=self
.record
)
3225 selector
.CTi
= int(self
.CTi
)
3228 @_dataclasses.dataclass(eq
=True, frozen
=True)
3229 class SpecifierCTR(SpecifierCTX
):
3231 def match(cls
, desc
, record
):
3232 return super().match(desc
=desc
, record
=record
,
3233 etalon
="ctr", CTi
=False)
3236 @_dataclasses.dataclass(eq
=True, frozen
=True)
3237 class SpecifierCTi(SpecifierCTX
):
3239 def match(cls
, desc
, record
):
3240 return super().match(desc
=desc
, record
=record
,
3241 etalon
="cti", CTi
=True)
3244 @_dataclasses.dataclass(eq
=True, frozen
=True)
3245 class SpecifierPI(Specifier
):
3247 def match(cls
, desc
, record
):
3251 if record
.svp64
.mode
not in [_SVMode
.LDST_IMM
, _SVMode
.LDST_IDX
]:
3252 raise ValueError("only ld/st imm/idx mode supported")
3254 return cls(record
=record
)
3256 def assemble(self
, insn
):
3257 selector
= insn
.select(record
=self
.record
)
3258 selector
.mode
[2] = 0b1
3262 @_dataclasses.dataclass(eq
=True, frozen
=True)
3263 class SpecifierLF(Specifier
):
3265 def match(cls
, desc
, record
):
3269 if record
.svp64
.mode
is not _SVMode
.LDST_IMM
:
3270 raise ValueError("only ld/st imm mode supported")
3272 return cls(record
=record
)
3274 def assemble(self
, insn
):
3275 selector
= insn
.select(record
=self
.record
)
3276 selector
.mode
[1] = 0
3280 @_dataclasses.dataclass(eq
=True, frozen
=True)
3281 class SpecifierVLi(Specifier
):
3283 def match(cls
, desc
, record
):
3287 return cls(record
=record
)
3289 def validate(self
, others
):
3291 if isinstance(spec
, SpecifierFF
):
3294 raise ValueError("VLi only allowed in failfirst")
3296 def assemble(self
, insn
):
3297 selector
= insn
.select(record
=self
.record
)
3298 selector
.mode
[1] = 1
3302 class Specifiers(tuple):
3337 def __new__(cls
, items
, record
):
3338 def transform(item
):
3339 for spec_cls
in cls
.SPECS
:
3340 spec
= spec_cls
.match(item
, record
=record
)
3341 if spec
is not None:
3343 raise ValueError(item
)
3345 # TODO: remove this hack
3346 items
= dict.fromkeys(items
)
3350 items
= tuple(items
)
3352 specs
= tuple(map(transform
, items
))
3353 for (index
, spec
) in enumerate(specs
):
3354 head
= specs
[:index
]
3355 tail
= specs
[index
+ 1:]
3356 spec
.validate(others
=(head
+ tail
))
3358 return super().__new
__(cls
, specs
)
3361 class SVP64OperandMeta(type):
3362 class SVP64NonZeroOperand(NonZeroOperand
):
3363 def assemble(self
, insn
, value
):
3364 if isinstance(value
, str):
3365 value
= int(value
, 0)
3366 if not isinstance(value
, int):
3367 raise ValueError("non-integer operand")
3369 # FIXME: this is really weird
3370 if self
.record
.name
in ("svstep", "svstep."):
3371 value
+= 1 # compensation
3373 return super().assemble(value
=value
, insn
=insn
)
3375 class SVP64XOStaticOperand(SpanStaticOperand
):
3376 def __init__(self
, record
, value
, span
):
3377 return super().__init
__(record
=record
, name
="XO",
3378 value
=value
, span
=span
)
3381 NonZeroOperand
: SVP64NonZeroOperand
,
3382 XOStaticOperand
: SVP64XOStaticOperand
,
3385 def __new__(metacls
, name
, bases
, ns
):
3387 for (index
, base_cls
) in enumerate(bases
):
3388 bases
[index
] = metacls
.__TRANSFORM
.get(base_cls
, base_cls
)
3390 bases
= tuple(bases
)
3392 return super().__new
__(metacls
, name
, bases
, ns
)
3395 class SVP64Operand(Operand
, metaclass
=SVP64OperandMeta
):
3398 return tuple(map(lambda bit
: (bit
+ 32), super().span
))
3402 def __init__(self
, insn
, record
):
3404 self
.__record
= record
3405 return super().__init
__()
3408 return self
.rm
.__doc
__
3411 return repr(self
.rm
)
3419 return self
.__record
3423 rm
= getattr(self
.insn
.prefix
.rm
, self
.record
.svp64
.mode
.name
.lower())
3425 # The idea behind these tables is that they are now literally
3426 # in identical format to insndb.csv and minor_xx.csv and can
3427 # be done precisely as that. The only thing to watch out for
3428 # is the insertion of Rc=1 as a "mask/value" bit and likewise
3429 # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
3432 if self
.record
.svp64
.mode
is _SVMode
.NORMAL
:
3433 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3434 # mode Rc mask Rc member
3436 (0b000000, 0b111000, "simple"), # simple (no Rc)
3437 (0b001000, 0b111100, "mr"), # mapreduce (no Rc)
3438 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3439 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3440 (0b100000, 0b110000, "sat"), # saturation (no Rc)
3441 (0b001100, 0b111100, "rsvd"), # reserved
3443 mode
= int(self
.insn
.prefix
.rm
.normal
.mode
)
3444 search
= ((mode
<< 1) | self
.record
.Rc
)
3446 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IMM
:
3447 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3448 # mode Rc mask Rc member
3449 # ironically/coincidentally this table is identical to NORMAL
3450 # mode except reserved in place of mr
3452 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3453 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3454 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3456 search
= ((int(self
.insn
.prefix
.rm
.ldst_imm
.mode
) << 1) |
3459 elif self
.record
.svp64
.mode
is _SVMode
.LDST_IDX
:
3460 # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
3461 # mode Rc mask Rc member
3463 (0b000000, 0b010000, "simple"), # simple (no Rc involved)
3464 (0b010001, 0b010001, "ffrc1"), # ffirst, Rc=1
3465 (0b010000, 0b010001, "ffrc0"), # ffirst, Rc=0
3467 search
= ((int(self
.insn
.prefix
.rm
.ldst_idx
.mode
) << 1) |
3470 elif self
.record
.svp64
.mode
is _SVMode
.CROP
:
3471 # concatenate mode 5-bit with regtype (LSB) then do mask/map search
3472 # mode 3b mask 3b member
3474 (0b000000, 0b111000, "simple"), # simple
3475 (0b001000, 0b111000, "mr"), # mapreduce
3476 (0b010001, 0b010001, "ff3"), # ffirst, 3-bit CR
3477 (0b010000, 0b010000, "ff5"), # ffirst, 5-bit CR
3479 search
= ((int(self
.insn
.prefix
.rm
.crop
.mode
) << 1) |
3480 int(self
.record
.svp64
.extra_CR_3bit
))
3482 elif self
.record
.svp64
.mode
is _SVMode
.BRANCH
:
3486 (0b00, 0b11, "simple"), # simple
3487 (0b01, 0b11, "vls"), # VLset
3488 (0b10, 0b11, "ctr"), # CTR mode
3489 (0b11, 0b11, "ctrvls"), # CTR+VLset mode
3491 # slightly weird: doesn't have a 5-bit "mode" field like others
3492 search
= int(self
.insn
.prefix
.rm
.branch
.mode
.sel
)
3495 if table
is not None:
3496 for (value
, mask
, field
) in table
:
3497 if field
.startswith("rsvd"):
3499 if ((value
& mask
) == (search
& mask
)):
3500 return getattr(rm
, field
)
3504 def __getattr__(self
, key
):
3505 if key
.startswith(f
"_{self.__class__.__name__}__"):
3506 return super().__getattribute
__(key
)
3508 return getattr(self
.rm
, key
)
3510 def __setattr__(self
, key
, value
):
3511 if key
.startswith(f
"_{self.__class__.__name__}__"):
3512 return super().__setattr
__(key
, value
)
3515 if not hasattr(rm
, key
):
3516 raise AttributeError(key
)
3518 return setattr(rm
, key
, value
)
3521 class SVP64Instruction(PrefixedInstruction
):
3522 """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
3523 class Prefix(PrefixedInstruction
.Prefix
):
3525 rm
: RM
.remap((6, 8) + tuple(range(10, 32)))
3529 def select(self
, record
):
3530 return RMSelector(insn
=self
, record
=record
)
3535 for idx
in range(64):
3536 bit
= int(self
[idx
])
3538 return "".join(map(str, bits
))
3541 def assemble(cls
, record
, arguments
=None, specifiers
=None):
3542 insn
= super().assemble(record
=record
, arguments
=arguments
)
3544 specifiers
= Specifiers(items
=specifiers
, record
=record
)
3545 for specifier
in specifiers
:
3546 specifier
.assemble(insn
=insn
)
3548 insn
.prefix
.PO
= 0x1
3549 insn
.prefix
.id = 0x3
3553 def disassemble(self
, record
,
3555 style
=Style
.NORMAL
):
3557 if style
<= Style
.SHORT
:
3560 blob
= insn
.bytes(byteorder
=byteorder
)
3561 blob
= " ".join(map(lambda byte
: f
"{byte:02x}", blob
))
3564 blob_prefix
= blob(self
.prefix
)
3565 blob_suffix
= blob(self
.suffix
)
3567 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3568 yield f
"{blob_suffix}.long 0x{int(self.suffix):08x}"
3571 assert record
.svp64
is not None
3573 name
= f
"sv.{record.name}"
3575 rm
= self
.select(record
=record
)
3577 # convert specifiers to /x/y/z (sorted lexicographically)
3578 specifiers
= sorted(rm
.specifiers(record
=record
))
3579 if specifiers
: # if any add one extra to get the extra "/"
3580 specifiers
= ([""] + specifiers
)
3581 specifiers
= "/".join(specifiers
)
3583 # convert operands to " ,x,y,z"
3584 operands
= tuple(map(_operator
.itemgetter(1),
3585 self
.spec_dynamic_operands(record
=record
, style
=style
)))
3586 operands
= ",".join(operands
)
3587 if len(operands
) > 0: # if any separate with a space
3588 operands
= (" " + operands
)
3590 if style
<= Style
.LEGACY
:
3591 yield f
"{blob_prefix}.long 0x{int(self.prefix):08x}"
3592 suffix
= WordInstruction
.integer(value
=int(self
.suffix
))
3593 yield from suffix
.disassemble(record
=record
,
3594 byteorder
=byteorder
, style
=style
)
3596 yield f
"{blob_prefix}{name}{specifiers}{operands}"
3598 yield f
"{blob_suffix}"
3600 if style
>= Style
.VERBOSE
:
3602 binary
= self
.binary
3603 spec
= self
.spec(record
=record
, prefix
="sv.")
3605 yield f
"{indent}spec"
3606 yield f
"{indent}{indent}{spec}"
3607 yield f
"{indent}pcode"
3608 for stmt
in record
.mdwn
.pcode
:
3609 yield f
"{indent}{indent}{stmt}"
3610 yield f
"{indent}binary"
3611 yield f
"{indent}{indent}[0:8] {binary[0:8]}"
3612 yield f
"{indent}{indent}[8:16] {binary[8:16]}"
3613 yield f
"{indent}{indent}[16:24] {binary[16:24]}"
3614 yield f
"{indent}{indent}[24:32] {binary[24:32]}"
3615 yield f
"{indent}{indent}[32:40] {binary[32:40]}"
3616 yield f
"{indent}{indent}[40:48] {binary[40:48]}"
3617 yield f
"{indent}{indent}[48:56] {binary[48:56]}"
3618 yield f
"{indent}{indent}[56:64] {binary[56:64]}"
3619 yield f
"{indent}opcodes"
3620 for opcode
in record
.opcodes
:
3621 yield f
"{indent}{indent}{opcode!r}"
3622 for operand
in self
.operands(record
=record
):
3623 yield from operand
.disassemble(insn
=self
,
3624 style
=style
, indent
=indent
)
3626 yield f
"{indent}{indent}{str(rm)}"
3627 for line
in rm
.disassemble(style
=style
):
3628 yield f
"{indent}{indent}{line}"
3632 def operands(cls
, record
):
3633 for operand
in super().operands(record
=record
):
3634 parent
= operand
.__class
__
3635 name
= f
"SVP64{parent.__name__}"
3636 bases
= (SVP64Operand
, parent
)
3637 child
= type(name
, bases
, {})
3638 yield child(**dict(operand
))
3641 def parse(stream
, factory
):
3643 return ("TODO" not in frozenset(entry
.values()))
3645 lines
= filter(lambda line
: not line
.strip().startswith("#"), stream
)
3646 entries
= _csv
.DictReader(lines
)
3647 entries
= filter(match
, entries
)
3648 return tuple(map(factory
, entries
))
3651 class MarkdownDatabase
:
3654 for (name
, desc
) in _ISA():
3657 (dynamic
, *static
) = desc
.regs
3658 operands
.extend(dynamic
)
3659 operands
.extend(static
)
3660 pcode
= PCode(iterable
=filter(str.strip
, desc
.pcode
))
3661 operands
= Operands(insn
=name
, operands
=operands
)
3662 db
[name
] = MarkdownRecord(pcode
=pcode
, operands
=operands
)
3664 self
.__db
= dict(sorted(db
.items()))
3666 return super().__init
__()
3669 yield from self
.__db
.items()
3671 def __contains__(self
, key
):
3672 return self
.__db
.__contains
__(key
)
3674 def __getitem__(self
, key
):
3675 return self
.__db
.__getitem
__(key
)
3678 class FieldsDatabase
:
3681 df
= _DecodeFields()
3683 for (form
, fields
) in df
.instrs
.items():
3684 if form
in {"DQE", "TX"}:
3688 db
[_Form
[form
]] = Fields(fields
)
3692 return super().__init
__()
3694 def __getitem__(self
, key
):
3695 return self
.__db
.__getitem
__(key
)
3699 def __init__(self
, root
, mdwndb
):
3700 # The code below groups the instructions by name:section.
3701 # There can be multiple names for the same instruction.
3702 # The point is to capture different opcodes for the same instruction.
3704 records
= _collections
.defaultdict(set)
3705 path
= (root
/ "insndb.csv")
3706 with
open(path
, "r", encoding
="UTF-8") as stream
:
3707 for section
in sorted(parse(stream
, Section
.CSV
)):
3708 path
= (root
/ section
.csv
)
3710 section
.Mode
.INTEGER
: IntegerOpcode
,
3711 section
.Mode
.PATTERN
: PatternOpcode
,
3713 factory
= _functools
.partial(
3714 PPCRecord
.CSV
, opcode_cls
=opcode_cls
)
3715 with
open(path
, "r", encoding
="UTF-8") as stream
:
3716 for insn
in parse(stream
, factory
):
3717 for name
in insn
.names
:
3718 records
[name
].add(insn
)
3719 sections
[name
] = section
3721 items
= sorted(records
.items())
3723 for (name
, multirecord
) in items
:
3724 records
[name
] = PPCMultiRecord(sorted(multirecord
))
3726 def exact_match(name
):
3727 record
= records
.get(name
)
3733 if not name
.endswith("l"):
3735 alias
= exact_match(name
[:-1])
3738 record
= records
[alias
]
3739 if "lk" not in record
.flags
:
3740 raise ValueError(record
)
3744 if not name
.endswith("a"):
3746 alias
= LK_match(name
[:-1])
3749 record
= records
[alias
]
3750 if record
.intop
not in {_MicrOp
.OP_B
, _MicrOp
.OP_BC
}:
3751 raise ValueError(record
)
3752 if "AA" not in mdwndb
[name
].operands
:
3753 raise ValueError(record
)
3757 if not name
.endswith("."):
3759 alias
= exact_match(name
[:-1])
3762 record
= records
[alias
]
3763 if record
.Rc
is _RCOE
.NONE
:
3764 raise ValueError(record
)
3768 matches
= (exact_match
, LK_match
, AA_match
, Rc_match
)
3769 for (name
, _
) in mdwndb
:
3770 if name
.startswith("sv."):
3773 for match
in matches
:
3775 if alias
is not None:
3779 section
= sections
[alias
]
3780 record
= records
[alias
]
3781 db
[name
] = (section
, record
)
3783 self
.__db
= dict(sorted(db
.items()))
3785 return super().__init
__()
3787 @_functools.lru_cache(maxsize
=512, typed
=False)
3788 def __getitem__(self
, key
):
3789 return self
.__db
.get(key
, (None, None))
3792 class SVP64Database
:
3793 def __init__(self
, root
, ppcdb
):
3795 pattern
= _re
.compile(r
"^(?:LDST)?RM-(1P|2P)-.*?\.csv$")
3796 for (prefix
, _
, names
) in _os
.walk(root
):
3797 prefix
= _pathlib
.Path(prefix
)
3798 for name
in filter(lambda name
: pattern
.match(name
), names
):
3799 path
= (prefix
/ _pathlib
.Path(name
))
3800 with
open(path
, "r", encoding
="UTF-8") as stream
:
3801 db
.update(parse(stream
, SVP64Record
.CSV
))
3802 db
= {record
.name
:record
for record
in db
}
3804 self
.__db
= dict(sorted(db
.items()))
3805 self
.__ppcdb
= ppcdb
3807 return super().__init
__()
3809 def __getitem__(self
, key
):
3810 (_
, record
) = self
.__ppcdb
[key
]
3814 for name
in record
.names
:
3815 record
= self
.__db
.get(name
, None)
3816 if record
is not None:
3822 class Records(Tuple
, datatype
=Record
):
3823 def __new__(cls
, records
):
3824 return super().__new
__(cls
, sorted(records
))
3827 class Database(Node
):
3828 def __init__(self
, root
):
3829 root
= _pathlib
.Path(root
)
3830 mdwndb
= MarkdownDatabase()
3831 fieldsdb
= FieldsDatabase()
3832 ppcdb
= PPCDatabase(root
=root
, mdwndb
=mdwndb
)
3833 svp64db
= SVP64Database(root
=root
, ppcdb
=ppcdb
)
3837 opcodes
= _collections
.defaultdict(
3838 lambda: _collections
.defaultdict(set))
3840 for (name
, mdwn
) in mdwndb
:
3841 if name
.startswith("sv."):
3843 (section
, ppc
) = ppcdb
[name
]
3846 svp64
= svp64db
[name
]
3847 fields
= fieldsdb
[ppc
.form
]
3848 record
= Record(name
=name
,
3849 section
=section
, ppc
=ppc
, svp64
=svp64
,
3850 mdwn
=mdwn
, fields
=fields
)
3852 names
[record
.name
] = record
3853 opcodes
[section
][record
.PO
].add(record
)
3855 self
.__db
= Records(db
)
3856 self
.__names
= dict(sorted(names
.items()))
3857 self
.__opcodes
= dict(sorted(opcodes
.items()))
3859 return super().__init
__()
3862 def walk(clsself
, match
=None):
3864 match
= lambda subnode
: True
3866 if isinstance(clsself
, type):
3867 yield ("records", Records
)
3869 if match(clsself
.__db
):
3870 yield ("records", clsself
.__db
)
3873 return repr(self
.__db
)
3876 yield from self
.__db
3878 @_functools.lru_cache(maxsize
=None)
3879 def __contains__(self
, key
):
3880 return self
.__getitem
__(key
) is not None
3882 @_functools.lru_cache(maxsize
=None)
3883 def __getitem__(self
, key
):
3884 if isinstance(key
, SVP64Instruction
):
3887 if isinstance(key
, Instruction
):
3890 sections
= sorted(self
.__opcodes
)
3891 for section
in sections
:
3892 group
= self
.__opcodes
[section
]
3893 for record
in group
[PO
]:
3894 if record
.match(key
=key
):
3899 elif isinstance(key
, str):
3900 return self
.__names
.get(key
)
3902 raise ValueError("instruction or name expected")