sv_binutils: drop obsolete code
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
1 import abc as _abc
2 import argparse as _argparse
3 import dataclasses as _dataclasses
4 import enum as _enum
5
6 from openpower.decoder.power_enums import (
7 In1Sel as _In1Sel,
8 In2Sel as _In2Sel,
9 In3Sel as _In3Sel,
10 OutSel as _OutSel,
11 CRInSel as _CRInSel,
12 CROutSel as _CROutSel,
13 SVPtype as _SVPtype,
14 SVEtype as _SVEtype,
15 SVEXTRA as _SVEXTRA,
16 )
17 from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
18
19
20 DISCLAIMER = (
21 "/*",
22 " * this file is auto-generated, do not edit",
23 " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
24 " * part of Libre-SOC, sponsored by NLnet",
25 " */",
26 )
27
28
29 def indent(strings):
30 return map(lambda string: (" " + string), strings)
31
32
33 class CType:
34 @classmethod
35 @_abc.abstractmethod
36 def c_decl(self, name):
37 pass
38
39 @_abc.abstractmethod
40 def c_value(self, prefix="", suffix=""):
41 pass
42
43 @classmethod
44 @_abc.abstractmethod
45 def c_var(self, name):
46 pass
47
48
49 class Enum(CType, _enum.Enum):
50 @classmethod
51 def c_decl(cls):
52 c_tag = f"svp64_{cls.__name__.lower()}"
53 yield f"enum {c_tag} {{"
54 for item in cls:
55 yield from indent(item.c_value(suffix=","))
56 yield f"}};"
57
58 def c_value(self, prefix="", suffix=""):
59 c_tag = f"svp64_{self.__class__.__name__.lower()}"
60 yield f"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
61
62 @classmethod
63 def c_var(cls, name):
64 c_tag = f"svp64_{cls.__name__.lower()}"
65 yield f"enum {c_tag} {name}"
66
67
68 # Python forbids inheriting from enum unless it's empty.
69 In1Sel = Enum("In1Sel", {item.name:item.value for item in _In1Sel})
70 In2Sel = Enum("In2Sel", {item.name:item.value for item in _In2Sel})
71 In3Sel = Enum("In3Sel", {item.name:item.value for item in _In3Sel})
72 OutSel = Enum("OutSel", {item.name:item.value for item in _OutSel})
73 CRInSel = Enum("CRInSel", {item.name:item.value for item in _CRInSel})
74 CROutSel = Enum("CROutSel", {item.name:item.value for item in _CROutSel})
75 SVPType = Enum("SVPType", {item.name:item.value for item in _SVPtype})
76 SVEType = Enum("SVEType", {item.name:item.value for item in _SVEtype})
77 SVEXTRA = Enum("SVEXTRA", {item.name:item.value for item in _SVEXTRA})
78
79
80 class Opcode(CType):
81 def __init__(self, value, mask, bits):
82 self.__value = value
83 self.__mask = mask
84 self.__bits = bits
85
86 return super().__init__()
87
88 @property
89 def value(self):
90 return self.__value
91
92 @property
93 def mask(self):
94 return self.__mask
95
96 @property
97 def bits(self):
98 return self.__bits
99
100 def __repr__(self):
101 fmt = f"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
102 return fmt.format(value=self.value, mask=self.mask)
103
104 def __lt__(self, other):
105 if not isinstance(other, self.__class__):
106 return NotImplemented
107
108 return self.__value < other.__value
109
110 @classmethod
111 def c_decl(cls):
112 yield f"struct svp64_opcode {{"
113 yield from indent([
114 "uint32_t value;",
115 "uint32_t mask;",
116 ])
117 yield f"}};"
118
119 def c_value(self, prefix="", suffix=""):
120 yield f"{prefix}{{"
121 yield from indent([
122 f".value = UINT32_C(0x{self.value:08X}),",
123 f".mask = UINT32_C(0x{self.mask:08X}),",
124 ])
125 yield f"}}{suffix}"
126
127 @classmethod
128 def c_var(cls, name):
129 yield f"struct svp64_opcode {name}"
130
131
132 class IntegerOpcode(Opcode):
133 def __init__(self, integer):
134 value = int(integer, 0)
135 bits = max(1, value.bit_length())
136 mask = int(("1" * bits), 2)
137
138 return super().__init__(value=value, mask=mask, bits=bits)
139
140
141 class PatternOpcode(Opcode):
142 def __init__(self, pattern):
143 value = 0
144 mask = 0
145 bits = len(pattern)
146 for bit in pattern:
147 value |= (bit == "1")
148 mask |= (bit != "-")
149 value <<= 1
150 mask <<= 1
151 value >>= 1
152 mask >>= 1
153
154 return super().__init__(value=value, mask=mask, bits=bits)
155
156
157 class Name(CType, str):
158 def __repr__(self):
159 escaped = self.replace("\"", "\\\"")
160 return f"\"{escaped}\""
161
162 def c_value(self, prefix="", suffix=""):
163 yield f"{prefix}{self!r}{suffix}"
164
165 @classmethod
166 def c_var(cls, name):
167 yield f"const char *{name}"
168
169
170 @_dataclasses.dataclass(eq=True, frozen=True)
171 class Record(CType):
172 in1: In1Sel
173 in2: In2Sel
174 in3: In3Sel
175 out: OutSel
176 out2: OutSel
177 cr_in: CRInSel
178 cr_out: CROutSel
179 sv_ptype: SVPType
180 sv_etype: SVEType
181 sv_in1: SVEXTRA
182 sv_in2: SVEXTRA
183 sv_in3: SVEXTRA
184 sv_out: SVEXTRA
185 sv_out2: SVEXTRA
186 sv_cr_in: SVEXTRA
187 sv_cr_out: SVEXTRA
188
189 @classmethod
190 def c_decl(cls):
191 bits_all = 0
192 yield f"struct svp64_record {{"
193 for field in _dataclasses.fields(cls):
194 bits = len(field.type).bit_length()
195 yield from indent([f"uint64_t {field.name} : {bits};"])
196 bits_all += bits
197 bits_rsvd = (64 - (bits_all % 64))
198 if bits_rsvd:
199 yield from indent([f"uint64_t : {bits_rsvd};"])
200 yield f"}};"
201
202 def c_value(self, prefix="", suffix=""):
203 yield f"{prefix}{{"
204 for field in _dataclasses.fields(self):
205 name = field.name
206 attr = getattr(self, name)
207 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
208 yield f"}}{suffix}"
209
210 @classmethod
211 def c_var(cls, name):
212 yield f"struct svp64_record {name}"
213
214
215 @_dataclasses.dataclass(eq=True, frozen=True)
216 class Entry(CType):
217 name: Name
218 record: Record
219
220 def __lt__(self, other):
221 if not isinstance(other, self.__class__):
222 return NotImplemented
223
224 return self.name < other.name
225
226 @classmethod
227 def c_decl(cls):
228 yield f"struct svp64_entry {{"
229 for field in _dataclasses.fields(cls):
230 yield from indent(field.type.c_var(name=f"{field.name};"))
231 yield f"}};"
232
233 def c_value(self, prefix="", suffix=""):
234 yield f"{prefix}{{"
235 for field in _dataclasses.fields(self):
236 name = field.name
237 attr = getattr(self, name)
238 yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
239 yield f"}}{suffix}"
240
241 @classmethod
242 def c_var(cls, name):
243 yield f"struct svp64_entry {name}"
244
245
246 class Codegen(_enum.Enum):
247 PPC_SVP64_H = _enum.auto()
248 PPC_SVP64_OPC_C = _enum.auto()
249
250 @classmethod
251 def _missing_(cls, value):
252 return {
253 "ppc-svp64.h": Codegen.PPC_SVP64_H,
254 "ppc-svp64-opc.c": Codegen.PPC_SVP64_OPC_C,
255 }.get(value)
256
257 def __str__(self):
258 return {
259 Codegen.PPC_SVP64_H: "ppc-svp64.h",
260 Codegen.PPC_SVP64_OPC_C: "ppc-svp64-opc.c",
261 }[self]
262
263 def generate(self, entries):
264 def ppc_svp64_h(entries):
265 yield from DISCLAIMER
266 yield ""
267
268 yield f"#ifndef {self.name}"
269 yield f"#define {self.name}"
270 yield ""
271
272 yield "#include <stdint.h>"
273 yield ""
274
275 yield "#ifdef __cplusplus"
276 yield "extern \"C\" {"
277 yield "#endif"
278 yield ""
279
280 enums = (
281 In1Sel, In2Sel, In3Sel, OutSel,
282 CRInSel, CROutSel,
283 SVPType, SVEType, SVEXTRA,
284 )
285 for enum in enums:
286 yield from enum.c_decl()
287 yield ""
288
289 yield from Record.c_decl()
290 yield ""
291
292 yield from Entry.c_decl()
293 yield ""
294
295 yield "extern const struct svp64_entry svp64_entries[];"
296 yield "extern const unsigned int svp64_num_entries;"
297 yield ""
298
299 yield f"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
300 yield ""
301
302 yield "#ifdef __cplusplus"
303 yield "}"
304 yield "#endif"
305 yield ""
306
307 yield f"#endif /* {self.name} */"
308 yield ""
309
310 def ppc_svp64_opc_c(entries):
311 yield from DISCLAIMER
312 yield ""
313
314 yield "#include \"opcode/ppc-svp64.h\""
315 yield ""
316
317 yield "const struct svp64_entry svp64_entries[] = {"
318 for (index, entry) in enumerate(entries):
319 yield from indent(entry.c_value(prefix=f"[{index}] = ", suffix=","))
320 yield f"}};"
321 yield ""
322
323 yield "const unsigned int svp64_num_entries = \\"
324 yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
325 yield ""
326
327 return {
328 Codegen.PPC_SVP64_H: ppc_svp64_h,
329 Codegen.PPC_SVP64_OPC_C: ppc_svp64_opc_c,
330 }[self](entries)
331
332
333 ISA = _SVP64RM()
334 FIELDS = {field.name:field for field in _dataclasses.fields(Record)}
335 FIELDS.update({field.name:field for field in _dataclasses.fields(Entry)})
336 def parse(path, opcode_cls):
337 visited = set()
338 for record in ISA.get_svp64_csv(path):
339 opcode = opcode_cls(record.pop("opcode"))
340 names = record.pop("comment").split("=")[-1]
341 for name in map(Name, names.split("/")):
342 if name.startswith("l") and name.endswith("br"):
343 continue
344 if name in {"mcrxr", "mcrxrx", "darn"}:
345 continue
346 if name in {"bctar", "bcctr"}:
347 continue
348 if "rfid" in name:
349 continue
350 if name in {"setvl"}:
351 continue
352
353 record = {key.lower().replace(" ", "_"):value for (key, value) in record.items()}
354 for (key, value) in tuple(record.items()):
355 key = key.lower().replace(" ", "_")
356 if key not in FIELDS:
357 record.pop(key)
358 continue
359
360 field = FIELDS[key]
361 if not isinstance(value, field.type):
362 if issubclass(field.type, _enum.Enum):
363 value = {item.name:item for item in field.type}[value]
364 else:
365 value = field.type(value)
366
367 record[key] = value
368
369 if name not in visited:
370 yield Entry(name=name, record=Record(**record))
371
372 visited.add(name)
373
374
375 def main(codegen):
376 entries = []
377 table = {
378 "minor_19.csv": IntegerOpcode,
379 "minor_30.csv": IntegerOpcode,
380 "minor_31.csv": IntegerOpcode,
381 "minor_58.csv": IntegerOpcode,
382 "minor_62.csv": IntegerOpcode,
383 "minor_22.csv": IntegerOpcode,
384 "minor_5.csv": PatternOpcode,
385 "minor_63.csv": PatternOpcode,
386 "minor_59.csv": PatternOpcode,
387 "major.csv": IntegerOpcode,
388 "extra.csv": PatternOpcode,
389 }
390 for (path, opcode_cls) in table.items():
391 entries.extend(parse(path, opcode_cls))
392 entries = sorted(frozenset(entries))
393
394 for line in codegen.generate(entries):
395 print(line)
396
397
398 if __name__ == "__main__":
399 parser = _argparse.ArgumentParser()
400 parser.add_argument("codegen", type=Codegen, choices=Codegen, help="code generator")
401
402 args = vars(parser.parse_args())
403 main(**args)