Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / target / hexagon / hex_common.py
blob195620c7ecd0769b5ebae352e0131704a80cb5e3
1 #!/usr/bin/env python3
3 ##
4 ## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
5 ##
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
20 import sys
21 import re
22 import string
23 import textwrap
25 behdict = {} # tag ->behavior
26 semdict = {} # tag -> semantics
27 attribdict = {} # tag -> attributes
28 macros = {} # macro -> macro information...
29 attribinfo = {} # Register information and misc
30 registers = {} # register -> register functions
31 new_registers = {}
32 tags = [] # list of all tags
33 overrides = {} # tags with helper overrides
34 idef_parser_enabled = {} # tags enabled for idef-parser
36 # We should do this as a hash for performance,
37 # but to keep order let's keep it as a list.
38 def uniquify(seq):
39 seen = set()
40 seen_add = seen.add
41 return [x for x in seq if x not in seen and not seen_add(x)]
44 regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
45 immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
46 reg_or_immre = re.compile(
47 r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)"
48 r"([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)"
50 relimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?")
51 absimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?")
53 finished_macros = set()
56 def expand_macro_attribs(macro, allmac_re):
57 if macro.key not in finished_macros:
58 # Get a list of all things that might be macros
59 l = allmac_re.findall(macro.beh)
60 for submacro in l:
61 if not submacro:
62 continue
63 if not macros[submacro]:
64 raise Exception(f"Couldn't find macro: <{l}>")
65 macro.attribs |= expand_macro_attribs(macros[submacro], allmac_re)
66 finished_macros.add(macro.key)
67 return macro.attribs
70 # When qemu needs an attribute that isn't in the imported files,
71 # we'll add it here.
72 def add_qemu_macro_attrib(name, attrib):
73 macros[name].attribs.add(attrib)
76 immextre = re.compile(r"f(MUST_)?IMMEXT[(]([UuSsRr])")
79 def is_cond_jump(tag):
80 if tag == "J2_rte":
81 return False
82 if "A_HWLOOP0_END" in attribdict[tag] or "A_HWLOOP1_END" in attribdict[tag]:
83 return False
84 return re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None
87 def is_cond_call(tag):
88 return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None
91 def calculate_attribs():
92 add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC")
93 add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
94 add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
95 add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
96 add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
97 add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE")
98 add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0')
99 add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0')
100 add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0')
101 add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
102 add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
103 add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
105 # Recurse down macros, find attributes from sub-macros
106 macroValues = list(macros.values())
107 allmacros_restr = "|".join(set([m.re.pattern for m in macroValues]))
108 allmacros_re = re.compile(allmacros_restr)
109 for macro in macroValues:
110 expand_macro_attribs(macro, allmacros_re)
111 # Append attributes to all instructions
112 for tag in tags:
113 for macname in allmacros_re.findall(semdict[tag]):
114 if not macname:
115 continue
116 macro = macros[macname]
117 attribdict[tag] |= set(macro.attribs)
118 # Mark conditional jumps and calls
119 # Not all instructions are properly marked with A_CONDEXEC
120 for tag in tags:
121 if is_cond_jump(tag) or is_cond_call(tag):
122 attribdict[tag].add("A_CONDEXEC")
125 def SEMANTICS(tag, beh, sem):
126 # print tag,beh,sem
127 behdict[tag] = beh
128 semdict[tag] = sem
129 attribdict[tag] = set()
130 tags.append(tag) # dicts have no order, this is for order
133 def ATTRIBUTES(tag, attribstring):
134 attribstring = attribstring.replace("ATTRIBS", "").replace("(", "").replace(")", "")
135 if not attribstring:
136 return
137 attribs = attribstring.split(",")
138 for attrib in attribs:
139 attribdict[tag].add(attrib.strip())
142 class Macro(object):
143 __slots__ = ["key", "name", "beh", "attribs", "re"]
145 def __init__(self, name, beh, attribs):
146 self.key = name
147 self.name = name
148 self.beh = beh
149 self.attribs = set(attribs)
150 self.re = re.compile("\\b" + name + "\\b")
153 def MACROATTRIB(macname, beh, attribstring):
154 attribstring = attribstring.replace("(", "").replace(")", "")
155 if attribstring:
156 attribs = attribstring.split(",")
157 else:
158 attribs = []
159 macros[macname] = Macro(macname, beh, attribs)
161 def compute_tag_regs(tag, full):
162 tagregs = regre.findall(behdict[tag])
163 if not full:
164 tagregs = map(lambda reg: reg[:2], tagregs)
165 return uniquify(tagregs)
167 def compute_tag_immediates(tag):
168 return uniquify(immre.findall(behdict[tag]))
172 ## tagregs is the main data structure we'll use
173 ## tagregs[tag] will contain the registers used by an instruction
174 ## Within each entry, we'll use the regtype and regid fields
175 ## regtype can be one of the following
176 ## C control register
177 ## N new register value
178 ## P predicate register
179 ## R GPR register
180 ## M modifier register
181 ## Q HVX predicate vector
182 ## V HVX vector register
183 ## O HVX new vector register
184 ## regid can be one of the following
185 ## d, e destination register
186 ## dd destination register pair
187 ## s, t, u, v, w source register
188 ## ss, tt, uu, vv source register pair
189 ## x, y read-write register
190 ## xx, yy read-write register pair
192 def get_tagregs(full=False):
193 compute_func = lambda tag: compute_tag_regs(tag, full)
194 return dict(zip(tags, list(map(compute_func, tags))))
196 def get_tagimms():
197 return dict(zip(tags, list(map(compute_tag_immediates, tags))))
200 def need_slot(tag):
201 if (
202 "A_CVI_SCATTER" not in attribdict[tag]
203 and "A_CVI_GATHER" not in attribdict[tag]
204 and ("A_STORE" in attribdict[tag]
205 or "A_LOAD" in attribdict[tag])
207 return 1
208 else:
209 return 0
212 def need_part1(tag):
213 return re.compile(r"fPART1").search(semdict[tag])
216 def need_ea(tag):
217 return re.compile(r"\bEA\b").search(semdict[tag])
220 def need_PC(tag):
221 return "A_IMPLICIT_READS_PC" in attribdict[tag]
224 def need_next_PC(tag):
225 return "A_CALL" in attribdict[tag]
228 def need_pkt_has_multi_cof(tag):
229 return "A_COF" in attribdict[tag]
232 def need_pkt_need_commit(tag):
233 return 'A_IMPLICIT_WRITES_USR' in attribdict[tag]
236 def skip_qemu_helper(tag):
237 return tag in overrides.keys()
240 def is_idef_parser_enabled(tag):
241 return tag in idef_parser_enabled
244 def imm_name(immlett):
245 return f"{immlett}iV"
248 def read_semantics_file(name):
249 eval_line = ""
250 for line in open(name, "rt").readlines():
251 if not line.startswith("#"):
252 eval_line += line
253 if line.endswith("\\\n"):
254 eval_line.rstrip("\\\n")
255 else:
256 eval(eval_line.strip())
257 eval_line = ""
260 def read_attribs_file(name):
261 attribre = re.compile(
262 r"DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), "
263 + r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)'
265 for line in open(name, "rt").readlines():
266 if not attribre.match(line):
267 continue
268 (attrib_base, descr, rreg, wreg) = attribre.findall(line)[0]
269 attrib_base = "A_" + attrib_base
270 attribinfo[attrib_base] = {"rreg": rreg, "wreg": wreg, "descr": descr}
273 def read_overrides_file(name):
274 overridere = re.compile(r"#define fGEN_TCG_([A-Za-z0-9_]+)\(.*")
275 for line in open(name, "rt").readlines():
276 if not overridere.match(line):
277 continue
278 tag = overridere.findall(line)[0]
279 overrides[tag] = True
282 def read_idef_parser_enabled_file(name):
283 global idef_parser_enabled
284 with open(name, "r") as idef_parser_enabled_file:
285 lines = idef_parser_enabled_file.read().strip().split("\n")
286 idef_parser_enabled = set(lines)
289 def is_predicated(tag):
290 return "A_CONDEXEC" in attribdict[tag]
293 def code_fmt(txt):
294 return textwrap.indent(textwrap.dedent(txt), " ")
297 def hvx_newv(tag):
298 if "A_CVI_NEW" in attribdict[tag]:
299 return "EXT_NEW"
300 elif "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
301 return "EXT_TMP"
302 else:
303 return "EXT_DFL"
305 def vreg_offset_func(tag):
306 if "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
307 return "ctx_tmp_vreg_off"
308 else:
309 return "ctx_future_vreg_off"
311 class HelperArg:
312 def __init__(self, proto_arg, call_arg, func_arg):
313 self.proto_arg = proto_arg
314 self.call_arg = call_arg
315 self.func_arg = func_arg
317 class Register:
318 def __init__(self, regtype, regid):
319 self.regtype = regtype
320 self.regid = regid
321 self.reg_num = f"{regtype}{regid}N"
322 def decl_reg_num(self, f, regno):
323 f.write(code_fmt(f"""\
324 const int {self.reg_num} = insn->regno[{regno}];
325 """))
326 def idef_arg(self, declared):
327 declared.append(self.reg_tcg())
328 def helper_arg(self):
329 return HelperArg(
330 self.helper_proto_type(),
331 self.reg_tcg(),
332 f"{self.helper_arg_type()} {self.helper_arg_name()}"
336 # Every register is either Single or Pair or Hvx
338 class Scalar:
339 def is_scalar_reg(self):
340 return True
341 def is_hvx_reg(self):
342 return False
343 def helper_arg_name(self):
344 return self.reg_tcg()
346 class Single(Scalar):
347 def helper_proto_type(self):
348 return "s32"
349 def helper_arg_type(self):
350 return "int32_t"
352 class Pair(Scalar):
353 def helper_proto_type(self):
354 return "s64"
355 def helper_arg_type(self):
356 return "int64_t"
358 class Hvx:
359 def is_scalar_reg(self):
360 return False
361 def is_hvx_reg(self):
362 return True
363 def hvx_off(self):
364 return f"{self.reg_tcg()}_off"
365 def helper_proto_type(self):
366 return "ptr"
367 def helper_arg_type(self):
368 return "void *"
369 def helper_arg_name(self):
370 return f"{self.reg_tcg()}_void"
373 # Every register is either Dest or OldSource or NewSource or ReadWrite
375 class Dest:
376 def reg_tcg(self):
377 return f"{self.regtype}{self.regid}V"
378 def is_written(self):
379 return True
380 def is_writeonly(self):
381 return True
382 def is_read(self):
383 return False
384 def is_readwrite(self):
385 return False
387 class Source:
388 def is_written(self):
389 return False
390 def is_writeonly(self):
391 return False
392 def is_read(self):
393 return True
394 def is_readwrite(self):
395 return False
397 class OldSource(Source):
398 def reg_tcg(self):
399 return f"{self.regtype}{self.regid}V"
401 class NewSource(Source):
402 def reg_tcg(self):
403 return f"{self.regtype}{self.regid}N"
405 class ReadWrite:
406 def reg_tcg(self):
407 return f"{self.regtype}{self.regid}V"
408 def is_written(self):
409 return True
410 def is_writeonly(self):
411 return False
412 def is_read(self):
413 return True
414 def is_readwrite(self):
415 return True
417 class GprDest(Register, Single, Dest):
418 def decl_tcg(self, f, tag, regno):
419 self.decl_reg_num(f, regno)
420 f.write(code_fmt(f"""\
421 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
422 """))
423 def log_write(self, f, tag):
424 f.write(code_fmt(f"""\
425 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
426 """))
427 def analyze_write(self, f, tag, regno):
428 self.decl_reg_num(f, regno)
429 predicated = "true" if is_predicated(tag) else "false"
430 f.write(code_fmt(f"""\
431 ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
432 """))
434 class GprSource(Register, Single, OldSource):
435 def decl_tcg(self, f, tag, regno):
436 self.decl_reg_num(f, regno)
437 f.write(code_fmt(f"""\
438 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
439 """))
440 def analyze_read(self, f, regno):
441 self.decl_reg_num(f, regno)
442 f.write(code_fmt(f"""\
443 ctx_log_reg_read(ctx, {self.reg_num});
444 """))
446 class GprNewSource(Register, Single, NewSource):
447 def decl_tcg(self, f, tag, regno):
448 f.write(code_fmt(f"""\
449 TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]);
450 """))
451 def analyze_read(self, f, regno):
452 self.decl_reg_num(f, regno)
453 f.write(code_fmt(f"""\
454 ctx_log_reg_read(ctx, {self.reg_num});
455 """))
457 class GprReadWrite(Register, Single, ReadWrite):
458 def decl_tcg(self, f, tag, regno):
459 self.decl_reg_num(f, regno)
460 f.write(code_fmt(f"""\
461 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
462 """))
463 ## For read/write registers, we need to get the original value into
464 ## the result TCGv. For predicated instructions, this is done in
465 ## gen_start_packet. For un-predicated instructions, we do it here.
466 if not is_predicated(tag):
467 f.write(code_fmt(f"""\
468 tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]);
469 """))
470 def log_write(self, f, tag):
471 f.write(code_fmt(f"""\
472 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
473 """))
474 def analyze_write(self, f, tag, regno):
475 self.decl_reg_num(f, regno)
476 predicated = "true" if is_predicated(tag) else "false"
477 f.write(code_fmt(f"""\
478 ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
479 """))
481 class ControlDest(Register, Single, Dest):
482 def decl_reg_num(self, f, regno):
483 f.write(code_fmt(f"""\
484 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
485 """))
486 def decl_tcg(self, f, tag, regno):
487 self.decl_reg_num(f, regno)
488 f.write(code_fmt(f"""\
489 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
490 """))
491 def log_write(self, f, tag):
492 f.write(code_fmt(f"""\
493 gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
494 """))
495 def analyze_write(self, f, tag, regno):
496 self.decl_reg_num(f, regno)
497 predicated = "true" if is_predicated(tag) else "false"
498 f.write(code_fmt(f"""\
499 ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
500 """))
502 class ControlSource(Register, Single, OldSource):
503 def decl_reg_num(self, f, regno):
504 f.write(code_fmt(f"""\
505 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
506 """))
507 def decl_tcg(self, f, tag, regno):
508 self.decl_reg_num(f, regno);
509 f.write(code_fmt(f"""\
510 TCGv {self.reg_tcg()} = tcg_temp_new();
511 gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
512 """))
513 def analyze_read(self, f, regno):
514 self.decl_reg_num(f, regno)
515 f.write(code_fmt(f"""\
516 ctx_log_reg_read(ctx, {self.reg_num});
517 """))
519 class ModifierSource(Register, Single, OldSource):
520 def decl_reg_num(self, f, regno):
521 f.write(code_fmt(f"""\
522 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0;
523 """))
524 def decl_tcg(self, f, tag, regno):
525 self.decl_reg_num(f, regno)
526 f.write(code_fmt(f"""\
527 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
528 TCGv CS G_GNUC_UNUSED =
529 hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0];
530 """))
531 def idef_arg(self, declared):
532 declared.append(self.reg_tcg())
533 declared.append("CS")
534 def analyze_read(self, f, regno):
535 self.decl_reg_num(f, regno)
536 f.write(code_fmt(f"""\
537 ctx_log_reg_read(ctx, {self.reg_num});
538 """))
540 class PredDest(Register, Single, Dest):
541 def decl_tcg(self, f, tag, regno):
542 self.decl_reg_num(f, regno)
543 f.write(code_fmt(f"""\
544 TCGv {self.reg_tcg()} = tcg_temp_new();
545 """))
546 def log_write(self, f, tag):
547 f.write(code_fmt(f"""\
548 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
549 """))
550 def analyze_write(self, f, tag, regno):
551 self.decl_reg_num(f, regno)
552 f.write(code_fmt(f"""\
553 ctx_log_pred_write(ctx, {self.reg_num});
554 """))
556 class PredSource(Register, Single, OldSource):
557 def decl_tcg(self, f, tag, regno):
558 self.decl_reg_num(f, regno)
559 f.write(code_fmt(f"""\
560 TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}];
561 """))
562 def analyze_read(self, f, regno):
563 self.decl_reg_num(f, regno)
564 f.write(code_fmt(f"""\
565 ctx_log_pred_read(ctx, {self.reg_num});
566 """))
568 class PredNewSource(Register, Single, NewSource):
569 def decl_tcg(self, f, tag, regno):
570 f.write(code_fmt(f"""\
571 TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]);
572 """))
573 def analyze_read(self, f, regno):
574 self.decl_reg_num(f, regno)
575 f.write(code_fmt(f"""\
576 ctx_log_pred_read(ctx, {self.reg_num});
577 """))
579 class PredReadWrite(Register, Single, ReadWrite):
580 def decl_tcg(self, f, tag, regno):
581 self.decl_reg_num(f, regno)
582 f.write(code_fmt(f"""\
583 TCGv {self.reg_tcg()} = tcg_temp_new();
584 tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]);
585 """))
586 def log_write(self, f, tag):
587 f.write(code_fmt(f"""\
588 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
589 """))
590 def analyze_write(self, f, tag, regno):
591 self.decl_reg_num(f, regno)
592 f.write(code_fmt(f"""\
593 ctx_log_pred_write(ctx, {self.reg_num});
594 """))
596 class PairDest(Register, Pair, Dest):
597 def decl_tcg(self, f, tag, regno):
598 self.decl_reg_num(f, regno)
599 f.write(code_fmt(f"""\
600 TCGv_i64 {self.reg_tcg()} =
601 get_result_gpr_pair(ctx, {self.reg_num});
602 """))
603 def log_write(self, f, tag):
604 f.write(code_fmt(f"""\
605 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
606 """))
607 def analyze_write(self, f, tag, regno):
608 self.decl_reg_num(f, regno)
609 predicated = "true" if is_predicated(tag) else "false"
610 f.write(code_fmt(f"""\
611 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
612 """))
614 class PairSource(Register, Pair, OldSource):
615 def decl_tcg(self, f, tag, regno):
616 self.decl_reg_num(f, regno)
617 f.write(code_fmt(f"""\
618 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
619 tcg_gen_concat_i32_i64({self.reg_tcg()},
620 hex_gpr[{self.reg_num}],
621 hex_gpr[{self.reg_num} + 1]);
622 """))
623 def analyze_read(self, f, regno):
624 self.decl_reg_num(f, regno)
625 f.write(code_fmt(f"""\
626 ctx_log_reg_read_pair(ctx, {self.reg_num});
627 """))
629 class PairReadWrite(Register, Pair, ReadWrite):
630 def decl_tcg(self, f, tag, regno):
631 self.decl_reg_num(f, regno)
632 f.write(code_fmt(f"""\
633 TCGv_i64 {self.reg_tcg()} =
634 get_result_gpr_pair(ctx, {self.reg_num});
635 tcg_gen_concat_i32_i64({self.reg_tcg()},
636 hex_gpr[{self.reg_num}],
637 hex_gpr[{self.reg_num} + 1]);
638 """))
639 def log_write(self, f, tag):
640 f.write(code_fmt(f"""\
641 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
642 """))
643 def analyze_write(self, f, tag, regno):
644 self.decl_reg_num(f, regno)
645 predicated = "true" if is_predicated(tag) else "false"
646 f.write(code_fmt(f"""\
647 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
648 """))
650 class ControlPairDest(Register, Pair, Dest):
651 def decl_reg_num(self, f, regno):
652 f.write(code_fmt(f"""\
653 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
654 """))
655 def decl_tcg(self, f, tag, regno):
656 self.decl_reg_num(f, regno)
657 f.write(code_fmt(f"""\
658 TCGv_i64 {self.reg_tcg()} =
659 get_result_gpr_pair(ctx, {self.reg_num});
660 """))
661 def log_write(self, f, tag):
662 f.write(code_fmt(f"""\
663 gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
664 """))
665 def analyze_write(self, f, tag, regno):
666 self.decl_reg_num(f, regno)
667 predicated = "true" if is_predicated(tag) else "false"
668 f.write(code_fmt(f"""\
669 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
670 """))
672 class ControlPairSource(Register, Pair, OldSource):
673 def decl_reg_num(self, f, regno):
674 f.write(code_fmt(f"""\
675 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
676 """))
677 def decl_tcg(self, f, tag, regno):
678 self.decl_reg_num(f, regno)
679 f.write(code_fmt(f"""\
680 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
681 gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
682 """))
683 def analyze_read(self, f, regno):
684 self.decl_reg_num(f, regno)
685 f.write(code_fmt(f"""\
686 ctx_log_reg_read_pair(ctx, {self.reg_num});
687 """))
689 class VRegDest(Register, Hvx, Dest):
690 def decl_tcg(self, f, tag, regno):
691 self.decl_reg_num(f, regno)
692 f.write(code_fmt(f"""\
693 const intptr_t {self.hvx_off()} =
694 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
695 """))
696 if not skip_qemu_helper(tag):
697 f.write(code_fmt(f"""\
698 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
699 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
700 """))
701 def log_write(self, f, tag):
702 pass
703 def helper_hvx_desc(self, f):
704 f.write(code_fmt(f"""\
705 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
706 """))
707 def analyze_write(self, f, tag, regno):
708 self.decl_reg_num(f, regno)
709 newv = hvx_newv(tag)
710 predicated = "true" if is_predicated(tag) else "false"
711 f.write(code_fmt(f"""\
712 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
713 """))
715 class VRegSource(Register, Hvx, OldSource):
716 def decl_tcg(self, f, tag, regno):
717 self.decl_reg_num(f, regno)
718 f.write(code_fmt(f"""\
719 const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num});
720 """))
721 if not skip_qemu_helper(tag):
722 f.write(code_fmt(f"""\
723 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
724 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
725 """))
726 def helper_hvx_desc(self, f):
727 f.write(code_fmt(f"""\
728 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
729 """))
730 def analyze_read(self, f, regno):
731 self.decl_reg_num(f, regno)
732 f.write(code_fmt(f"""\
733 ctx_log_vreg_read(ctx, {self.reg_num});
734 """))
736 class VRegNewSource(Register, Hvx, NewSource):
737 def decl_tcg(self, f, tag, regno):
738 self.decl_reg_num(f, regno)
739 if skip_qemu_helper(tag):
740 f.write(code_fmt(f"""\
741 const intptr_t {self.hvx_off()} =
742 ctx_future_vreg_off(ctx, {self.reg_num}, 1, true);
743 """))
744 def helper_hvx_desc(self, f):
745 f.write(code_fmt(f"""\
746 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
747 """))
748 def analyze_read(self, f, regno):
749 self.decl_reg_num(f, regno)
750 f.write(code_fmt(f"""\
751 ctx_log_vreg_read(ctx, {self.reg_num});
752 """))
754 class VRegReadWrite(Register, Hvx, ReadWrite):
755 def decl_tcg(self, f, tag, regno):
756 self.decl_reg_num(f, regno)
757 f.write(code_fmt(f"""\
758 const intptr_t {self.hvx_off()} =
759 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
760 tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
761 vreg_src_off(ctx, {self.reg_num}),
762 sizeof(MMVector), sizeof(MMVector));
763 """))
764 if not skip_qemu_helper(tag):
765 f.write(code_fmt(f"""\
766 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
767 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
768 """))
769 def log_write(self, f, tag):
770 pass
771 def helper_hvx_desc(self, f):
772 f.write(code_fmt(f"""\
773 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
774 """))
775 def analyze_write(self, f, tag, regno):
776 self.decl_reg_num(f, regno)
777 newv = hvx_newv(tag)
778 predicated = "true" if is_predicated(tag) else "false"
779 f.write(code_fmt(f"""\
780 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
781 """))
783 class VRegTmp(Register, Hvx, ReadWrite):
784 def decl_tcg(self, f, tag, regno):
785 self.decl_reg_num(f, regno)
786 f.write(code_fmt(f"""\
787 const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp);
788 """))
789 if not skip_qemu_helper(tag):
790 f.write(code_fmt(f"""\
791 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
792 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
793 tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
794 vreg_src_off(ctx, {self.reg_num}),
795 sizeof(MMVector), sizeof(MMVector));
796 """))
797 def log_write(self, f, tag):
798 f.write(code_fmt(f"""\
799 gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num},
800 {hvx_newv(tag)});
801 """))
802 def helper_hvx_desc(self, f):
803 f.write(code_fmt(f"""\
804 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
805 """))
806 def analyze_write(self, f, tag, regno):
807 self.decl_reg_num(f, regno)
808 newv = hvx_newv(tag)
809 predicated = "true" if is_predicated(tag) else "false"
810 f.write(code_fmt(f"""\
811 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated});
812 """))
814 class VRegPairDest(Register, Hvx, Dest):
815 def decl_tcg(self, f, tag, regno):
816 self.decl_reg_num(f, regno)
817 f.write(code_fmt(f"""\
818 const intptr_t {self.hvx_off()} =
819 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true);
820 """))
821 if not skip_qemu_helper(tag):
822 f.write(code_fmt(f"""\
823 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
824 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
825 """))
826 def log_write(self, f, tag):
827 pass
828 def helper_hvx_desc(self, f):
829 f.write(code_fmt(f"""\
830 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
831 """))
832 def analyze_write(self, f, tag, regno):
833 self.decl_reg_num(f, regno)
834 newv = hvx_newv(tag)
835 predicated = "true" if is_predicated(tag) else "false"
836 f.write(code_fmt(f"""\
837 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated});
838 """))
840 class VRegPairSource(Register, Hvx, OldSource):
841 def decl_tcg(self, f, tag, regno):
842 self.decl_reg_num(f, regno)
843 f.write(code_fmt(f"""\
844 const intptr_t {self.hvx_off()} =
845 offsetof(CPUHexagonState, {self.reg_tcg()});
846 tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
847 vreg_src_off(ctx, {self.reg_num}),
848 sizeof(MMVector), sizeof(MMVector));
849 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
850 vreg_src_off(ctx, {self.reg_num} ^ 1),
851 sizeof(MMVector), sizeof(MMVector));
852 """))
853 if not skip_qemu_helper(tag):
854 f.write(code_fmt(f"""\
855 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
856 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
857 """))
858 def helper_hvx_desc(self, f):
859 f.write(code_fmt(f"""\
860 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
861 """))
862 def analyze_read(self, f, regno):
863 self.decl_reg_num(f, regno)
864 f.write(code_fmt(f"""\
865 ctx_log_vreg_read_pair(ctx, {self.reg_num});
866 """))
868 class VRegPairReadWrite(Register, Hvx, ReadWrite):
869 def decl_tcg(self, f, tag, regno):
870 self.decl_reg_num(f, regno)
871 f.write(code_fmt(f"""\
872 const intptr_t {self.hvx_off()} =
873 offsetof(CPUHexagonState, {self.reg_tcg()});
874 tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
875 vreg_src_off(ctx, {self.reg_num}),
876 sizeof(MMVector), sizeof(MMVector));
877 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
878 vreg_src_off(ctx, {self.reg_num} ^ 1),
879 sizeof(MMVector), sizeof(MMVector));
880 """))
881 if not skip_qemu_helper(tag):
882 f.write(code_fmt(f"""\
883 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
884 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
885 """))
886 def log_write(self, f, tag):
887 f.write(code_fmt(f"""\
888 gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num},
889 {hvx_newv(tag)});
890 """))
891 def helper_hvx_desc(self, f):
892 f.write(code_fmt(f"""\
893 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
894 """))
895 def analyze_write(self, f, tag, regno):
896 self.decl_reg_num(f, regno)
897 newv = hvx_newv(tag)
898 predicated = "true" if is_predicated(tag) else "false"
899 f.write(code_fmt(f"""\
900 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated});
901 """))
903 class QRegDest(Register, Hvx, Dest):
904 def decl_tcg(self, f, tag, regno):
905 self.decl_reg_num(f, regno)
906 f.write(code_fmt(f"""\
907 const intptr_t {self.hvx_off()} =
908 get_result_qreg(ctx, {self.reg_num});
909 """))
910 if not skip_qemu_helper(tag):
911 f.write(code_fmt(f"""\
912 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
913 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
914 """))
915 def log_write(self, f, tag):
916 pass
917 def helper_hvx_desc(self, f):
918 f.write(code_fmt(f"""\
919 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
920 """))
921 def analyze_write(self, f, tag, regno):
922 self.decl_reg_num(f, regno)
923 f.write(code_fmt(f"""\
924 ctx_log_qreg_write(ctx, {self.reg_num});
925 """))
927 class QRegSource(Register, Hvx, OldSource):
928 def decl_tcg(self, f, tag, regno):
929 self.decl_reg_num(f, regno)
930 f.write(code_fmt(f"""\
931 const intptr_t {self.hvx_off()} =
932 offsetof(CPUHexagonState, QRegs[{self.reg_num}]);
933 """))
934 if not skip_qemu_helper(tag):
935 f.write(code_fmt(f"""\
936 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
937 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
938 """))
939 def helper_hvx_desc(self, f):
940 f.write(code_fmt(f"""\
941 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
942 """))
943 def analyze_read(self, f, regno):
944 self.decl_reg_num(f, regno)
945 f.write(code_fmt(f"""\
946 ctx_log_qreg_read(ctx, {self.reg_num});
947 """))
949 class QRegReadWrite(Register, Hvx, ReadWrite):
950 def decl_tcg(self, f, tag, regno):
951 self.decl_reg_num(f, regno)
952 f.write(code_fmt(f"""\
953 const intptr_t {self.hvx_off()} =
954 get_result_qreg(ctx, {self.reg_num});
955 tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
956 offsetof(CPUHexagonState, QRegs[{self.reg_num}]),
957 sizeof(MMQReg), sizeof(MMQReg));
958 """))
959 if not skip_qemu_helper(tag):
960 f.write(code_fmt(f"""\
961 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
962 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
963 """))
964 def log_write(self, f, tag):
965 pass
966 def helper_hvx_desc(self, f):
967 f.write(code_fmt(f"""\
968 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
969 """))
970 def analyze_write(self, f, tag, regno):
971 self.decl_reg_num(f, regno)
972 f.write(code_fmt(f"""\
973 ctx_log_qreg_write(ctx, {self.reg_num});
974 """))
976 def init_registers():
977 regs = {
978 GprDest("R", "d"),
979 GprDest("R", "e"),
980 GprSource("R", "s"),
981 GprSource("R", "t"),
982 GprSource("R", "u"),
983 GprSource("R", "v"),
984 GprReadWrite("R", "x"),
985 GprReadWrite("R", "y"),
986 ControlDest("C", "d"),
987 ControlSource("C", "s"),
988 ModifierSource("M", "u"),
989 PredDest("P", "d"),
990 PredDest("P", "e"),
991 PredSource("P", "s"),
992 PredSource("P", "t"),
993 PredSource("P", "u"),
994 PredSource("P", "v"),
995 PredReadWrite("P", "x"),
996 PairDest("R", "dd"),
997 PairDest("R", "ee"),
998 PairSource("R", "ss"),
999 PairSource("R", "tt"),
1000 PairReadWrite("R", "xx"),
1001 PairReadWrite("R", "yy"),
1002 ControlPairDest("C", "dd"),
1003 ControlPairSource("C", "ss"),
1004 VRegDest("V", "d"),
1005 VRegSource("V", "s"),
1006 VRegSource("V", "u"),
1007 VRegSource("V", "v"),
1008 VRegSource("V", "w"),
1009 VRegReadWrite("V", "x"),
1010 VRegTmp("V", "y"),
1011 VRegPairDest("V", "dd"),
1012 VRegPairSource("V", "uu"),
1013 VRegPairSource("V", "vv"),
1014 VRegPairReadWrite("V", "xx"),
1015 QRegDest("Q", "d"),
1016 QRegDest("Q", "e"),
1017 QRegSource("Q", "s"),
1018 QRegSource("Q", "t"),
1019 QRegSource("Q", "u"),
1020 QRegSource("Q", "v"),
1021 QRegReadWrite("Q", "x"),
1023 for reg in regs:
1024 registers[f"{reg.regtype}{reg.regid}"] = reg
1026 new_regs = {
1027 GprNewSource("N", "s"),
1028 GprNewSource("N", "t"),
1029 PredNewSource("P", "t"),
1030 PredNewSource("P", "u"),
1031 PredNewSource("P", "v"),
1032 VRegNewSource("O", "s"),
1034 for reg in new_regs:
1035 new_registers[f"{reg.regtype}{reg.regid}"] = reg
1037 def get_register(tag, regtype, regid):
1038 if f"{regtype}{regid}V" in semdict[tag]:
1039 return registers[f"{regtype}{regid}"]
1040 else:
1041 return new_registers[f"{regtype}{regid}"]
1043 def helper_ret_type(tag, regs):
1044 ## If there is a scalar result, it is the return type
1045 return_type = HelperArg( "void", "void", "void")
1046 numscalarresults = 0
1047 for regtype, regid in regs:
1048 reg = get_register(tag, regtype, regid)
1049 if reg.is_written() and reg.is_scalar_reg():
1050 return_type = HelperArg(
1051 reg.helper_proto_type(),
1052 reg.reg_tcg(),
1053 reg.helper_arg_type()
1055 if numscalarresults > 1:
1056 raise Exception("numscalarresults > 1")
1057 return return_type
1059 def helper_args(tag, regs, imms):
1060 args = []
1062 ## First argument is the CPU state
1063 args.append(HelperArg(
1064 "env",
1065 "tcg_env",
1066 "CPUHexagonState *env"
1069 ## For predicated instructions, we pass in the destination register
1070 if is_predicated(tag):
1071 for regtype, regid in regs:
1072 reg = get_register(tag, regtype, regid)
1073 if reg.is_writeonly() and not reg.is_hvx_reg():
1074 args.append(reg.helper_arg())
1076 ## Pass the HVX destination registers
1077 for regtype, regid in regs:
1078 reg = get_register(tag, regtype, regid)
1079 if reg.is_written() and reg.is_hvx_reg():
1080 args.append(reg.helper_arg())
1082 ## Pass the source registers
1083 for regtype, regid in regs:
1084 reg = get_register(tag, regtype, regid)
1085 if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
1086 args.append(reg.helper_arg())
1088 ## Pass the immediates
1089 for immlett, bits, immshift in imms:
1090 args.append(HelperArg(
1091 "s32",
1092 f"tcg_constant_tl({imm_name(immlett)})",
1093 f"int32_t {imm_name(immlett)}"
1096 ## Other stuff the helper might need
1097 if need_pkt_has_multi_cof(tag):
1098 args.append(HelperArg(
1099 "i32",
1100 "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
1101 "uint32_t pkt_has_multi_cof"
1103 if need_pkt_need_commit(tag):
1104 args.append(HelperArg(
1105 "i32",
1106 "tcg_constant_tl(ctx->need_commit)",
1107 "uint32_t pkt_need_commit"
1109 if need_PC(tag):
1110 args.append(HelperArg(
1111 "i32",
1112 "tcg_constant_tl(ctx->pkt->pc)",
1113 "target_ulong PC"
1115 if need_next_PC(tag):
1116 args.append(HelperArg(
1117 "i32",
1118 "tcg_constant_tl(ctx->next_PC)",
1119 "target_ulong next_PC"
1121 if need_slot(tag):
1122 args.append(HelperArg(
1123 "i32",
1124 "gen_slotval(ctx)",
1125 "uint32_t slotval"
1127 if need_part1(tag):
1128 args.append(HelperArg(
1129 "i32",
1130 "tcg_constant_tl(insn->part1)"
1131 "uint32_t part1"
1133 return args