xref: /openbmc/qemu/target/hexagon/hex_common.py (revision 05caa062)
1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-2024 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.
10##
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.
15##
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/>.
18##
19
20import sys
21import re
22import string
23import textwrap
24
25behdict = {}  # tag ->behavior
26semdict = {}  # tag -> semantics
27attribdict = {}  # tag -> attributes
28macros = {}  # macro -> macro information...
29registers = {}  # register -> register functions
30new_registers = {}
31tags = []  # list of all tags
32overrides = {}  # tags with helper overrides
33idef_parser_enabled = {}  # tags enabled for idef-parser
34
35# We should do this as a hash for performance,
36# but to keep order let's keep it as a list.
37def uniquify(seq):
38    seen = set()
39    seen_add = seen.add
40    return [x for x in seq if x not in seen and not seen_add(x)]
41
42
43regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
44immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
45reg_or_immre = re.compile(
46    r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)"
47    r"([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)"
48)
49relimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?")
50absimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?")
51
52finished_macros = set()
53
54
55def expand_macro_attribs(macro, allmac_re):
56    if macro.key not in finished_macros:
57        # Get a list of all things that might be macros
58        l = allmac_re.findall(macro.beh)
59        for submacro in l:
60            if not submacro:
61                continue
62            if not macros[submacro]:
63                raise Exception(f"Couldn't find macro: <{l}>")
64            macro.attribs |= expand_macro_attribs(macros[submacro], allmac_re)
65            finished_macros.add(macro.key)
66    return macro.attribs
67
68
69# When qemu needs an attribute that isn't in the imported files,
70# we'll add it here.
71def add_qemu_macro_attrib(name, attrib):
72    macros[name].attribs.add(attrib)
73
74
75immextre = re.compile(r"f(MUST_)?IMMEXT[(]([UuSsRr])")
76
77
78def is_cond_jump(tag):
79    if tag == "J2_rte":
80        return False
81    if "A_HWLOOP0_END" in attribdict[tag] or "A_HWLOOP1_END" in attribdict[tag]:
82        return False
83    return re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None
84
85
86def is_cond_call(tag):
87    return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None
88
89
90def calculate_attribs():
91    add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC")
92    add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
93    add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
94    add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
95    add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
96    add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE")
97    add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0')
98    add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0')
99    add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0')
100    add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
101    add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
102    add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
103    add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP')
104
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")
123
124
125def 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
131
132
133def 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())
140
141
142class Macro(object):
143    __slots__ = ["key", "name", "beh", "attribs", "re"]
144
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")
151
152
153def 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)
160
161def 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)
166
167def compute_tag_immediates(tag):
168    return uniquify(immre.findall(behdict[tag]))
169
170
171##
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
191##
192def get_tagregs(full=False):
193    compute_func = lambda tag: compute_tag_regs(tag, full)
194    return dict(zip(tags, list(map(compute_func, tags))))
195
196def get_tagimms():
197    return dict(zip(tags, list(map(compute_tag_immediates, tags))))
198
199
200def need_p0(tag):
201    return "A_IMPLICIT_READS_P0" in attribdict[tag]
202
203
204def need_sp(tag):
205    return "A_IMPLICIT_READS_SP" in attribdict[tag]
206
207
208def is_hvx_insn(tag):
209    return "A_CVI" in attribdict[tag]
210
211
212def need_env(tag):
213    return ("A_STORE" in attribdict[tag] or
214            "A_LOAD" in attribdict[tag] or
215            "A_CVI_GATHER" in attribdict[tag] or
216            "A_CVI_SCATTER" in attribdict[tag] or
217            "A_IMPLICIT_WRITES_USR" in attribdict[tag])
218
219
220def need_slot(tag):
221    if (
222        "A_CVI_SCATTER" not in attribdict[tag]
223        and "A_CVI_GATHER" not in attribdict[tag]
224        and ("A_STORE" in attribdict[tag]
225             or "A_LOAD" in attribdict[tag])
226    ):
227        return 1
228    else:
229        return 0
230
231
232def need_part1(tag):
233    return re.compile(r"fPART1").search(semdict[tag])
234
235
236def need_ea(tag):
237    return re.compile(r"\bEA\b").search(semdict[tag])
238
239
240def need_PC(tag):
241    return "A_IMPLICIT_READS_PC" in attribdict[tag]
242
243
244def need_next_PC(tag):
245    return "A_CALL" in attribdict[tag]
246
247
248def need_pkt_has_multi_cof(tag):
249    return "A_COF" in attribdict[tag]
250
251
252def need_pkt_need_commit(tag):
253    return 'A_IMPLICIT_WRITES_USR' in attribdict[tag]
254
255
256def skip_qemu_helper(tag):
257    return tag in overrides.keys()
258
259
260def is_idef_parser_enabled(tag):
261    return tag in idef_parser_enabled
262
263
264def is_hvx_insn(tag):
265    return "A_CVI" in attribdict[tag]
266
267
268def has_hvx_helper(tag):
269    return (is_hvx_insn(tag) and
270            not skip_qemu_helper(tag) and
271            not is_idef_parser_enabled(tag))
272
273
274def imm_name(immlett):
275    return f"{immlett}iV"
276
277
278def read_semantics_file(name):
279    eval_line = ""
280    for line in open(name, "rt").readlines():
281        if not line.startswith("#"):
282            eval_line += line
283            if line.endswith("\\\n"):
284                eval_line.rstrip("\\\n")
285            else:
286                eval(eval_line.strip())
287                eval_line = ""
288
289
290def read_overrides_file(name):
291    overridere = re.compile(r"#define fGEN_TCG_([A-Za-z0-9_]+)\(.*")
292    for line in open(name, "rt").readlines():
293        if not overridere.match(line):
294            continue
295        tag = overridere.findall(line)[0]
296        overrides[tag] = True
297
298
299def read_idef_parser_enabled_file(name):
300    global idef_parser_enabled
301    with open(name, "r") as idef_parser_enabled_file:
302        lines = idef_parser_enabled_file.read().strip().split("\n")
303        idef_parser_enabled = set(lines)
304
305
306def is_predicated(tag):
307    return "A_CONDEXEC" in attribdict[tag]
308
309
310def code_fmt(txt):
311    return textwrap.indent(textwrap.dedent(txt), "    ")
312
313
314def hvx_newv(tag):
315    if "A_CVI_NEW" in attribdict[tag]:
316        return "EXT_NEW"
317    elif "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
318        return "EXT_TMP"
319    else:
320        return "EXT_DFL"
321
322def vreg_offset_func(tag):
323    if "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]:
324        return "ctx_tmp_vreg_off"
325    else:
326        return "ctx_future_vreg_off"
327
328class HelperArg:
329    def __init__(self, proto_arg, call_arg, func_arg):
330        self.proto_arg = proto_arg
331        self.call_arg = call_arg
332        self.func_arg = func_arg
333
334class Register:
335    def __init__(self, regtype, regid):
336        self.regtype = regtype
337        self.regid = regid
338        self.reg_num = f"{regtype}{regid}N"
339    def decl_reg_num(self, f, regno):
340        f.write(code_fmt(f"""\
341            const int {self.reg_num} = insn->regno[{regno}];
342        """))
343    def idef_arg(self, declared):
344        declared.append(self.reg_tcg())
345    def helper_arg(self):
346        return HelperArg(
347            self.helper_proto_type(),
348            self.reg_tcg(),
349            f"{self.helper_arg_type()} {self.helper_arg_name()}"
350        )
351
352#
353# Every register is either Single or Pair or Hvx
354#
355class Scalar:
356    def is_scalar_reg(self):
357        return True
358    def is_hvx_reg(self):
359        return False
360    def helper_arg_name(self):
361        return self.reg_tcg()
362
363class Single(Scalar):
364    def helper_proto_type(self):
365        return "s32"
366    def helper_arg_type(self):
367        return "int32_t"
368
369class Pair(Scalar):
370    def helper_proto_type(self):
371        return "s64"
372    def helper_arg_type(self):
373        return "int64_t"
374
375class Hvx:
376    def is_scalar_reg(self):
377        return False
378    def is_hvx_reg(self):
379        return True
380    def hvx_off(self):
381        return f"{self.reg_tcg()}_off"
382    def helper_proto_type(self):
383        return "ptr"
384    def helper_arg_type(self):
385        return "void *"
386    def helper_arg_name(self):
387        return f"{self.reg_tcg()}_void"
388
389#
390# Every register is either Dest or OldSource or NewSource or ReadWrite
391#
392class Dest:
393    def reg_tcg(self):
394        return f"{self.regtype}{self.regid}V"
395    def is_written(self):
396        return True
397    def is_writeonly(self):
398        return True
399    def is_read(self):
400        return False
401    def is_readwrite(self):
402        return False
403
404class Source:
405    def is_written(self):
406        return False
407    def is_writeonly(self):
408        return False
409    def is_read(self):
410        return True
411    def is_readwrite(self):
412        return False
413
414class OldSource(Source):
415    def reg_tcg(self):
416        return f"{self.regtype}{self.regid}V"
417    def is_old(self):
418        return True
419    def is_new(self):
420        return False
421
422class NewSource(Source):
423    def reg_tcg(self):
424        return f"{self.regtype}{self.regid}N"
425    def is_old(self):
426        return False
427    def is_new(self):
428        return True
429
430class ReadWrite:
431    def reg_tcg(self):
432        return f"{self.regtype}{self.regid}V"
433    def is_written(self):
434        return True
435    def is_writeonly(self):
436        return False
437    def is_read(self):
438        return True
439    def is_readwrite(self):
440        return True
441    def is_old(self):
442        return True
443    def is_new(self):
444        return False
445
446class GprDest(Register, Single, Dest):
447    def decl_tcg(self, f, tag, regno):
448        self.decl_reg_num(f, regno)
449        f.write(code_fmt(f"""\
450            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
451        """))
452    def log_write(self, f, tag):
453        f.write(code_fmt(f"""\
454            gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
455        """))
456    def analyze_write(self, f, tag, regno):
457        predicated = "true" if is_predicated(tag) else "false"
458        f.write(code_fmt(f"""\
459            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
460        """))
461
462class GprSource(Register, Single, OldSource):
463    def decl_tcg(self, f, tag, regno):
464        self.decl_reg_num(f, regno)
465        f.write(code_fmt(f"""\
466            TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
467        """))
468    def analyze_read(self, f, regno):
469        f.write(code_fmt(f"""\
470            ctx_log_reg_read(ctx, {self.reg_num});
471        """))
472
473class GprNewSource(Register, Single, NewSource):
474    def decl_tcg(self, f, tag, regno):
475        f.write(code_fmt(f"""\
476            TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]);
477        """))
478    def analyze_read(self, f, regno):
479        f.write(code_fmt(f"""\
480            ctx_log_reg_read_new(ctx, {self.reg_num});
481        """))
482
483class GprReadWrite(Register, Single, ReadWrite):
484    def decl_tcg(self, f, tag, regno):
485        self.decl_reg_num(f, regno)
486        f.write(code_fmt(f"""\
487            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
488        """))
489        ## For read/write registers, we need to get the original value into
490        ## the result TCGv.  For predicated instructions, this is done in
491        ## gen_start_packet.  For un-predicated instructions, we do it here.
492        if not is_predicated(tag):
493            f.write(code_fmt(f"""\
494                tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]);
495            """))
496    def log_write(self, f, tag):
497        f.write(code_fmt(f"""\
498            gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
499        """))
500    def analyze_read(self, f, regno):
501        f.write(code_fmt(f"""\
502            ctx_log_reg_read(ctx, {self.reg_num});
503        """))
504    def analyze_write(self, f, tag, regno):
505        predicated = "true" if is_predicated(tag) else "false"
506        f.write(code_fmt(f"""\
507            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
508        """))
509
510class ControlDest(Register, Single, Dest):
511    def decl_reg_num(self, f, regno):
512        f.write(code_fmt(f"""\
513            const int {self.reg_num} = insn->regno[{regno}]  + HEX_REG_SA0;
514        """))
515    def decl_tcg(self, f, tag, regno):
516        self.decl_reg_num(f, regno)
517        f.write(code_fmt(f"""\
518            TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num});
519        """))
520    def log_write(self, f, tag):
521        f.write(code_fmt(f"""\
522            gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
523        """))
524    def analyze_write(self, f, tag, regno):
525        predicated = "true" if is_predicated(tag) else "false"
526        f.write(code_fmt(f"""\
527            ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
528        """))
529
530class ControlSource(Register, Single, OldSource):
531    def decl_reg_num(self, f, regno):
532        f.write(code_fmt(f"""\
533            const int {self.reg_num} = insn->regno[{regno}]  + HEX_REG_SA0;
534        """))
535    def decl_tcg(self, f, tag, regno):
536        self.decl_reg_num(f, regno);
537        f.write(code_fmt(f"""\
538            TCGv {self.reg_tcg()} = tcg_temp_new();
539            gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
540        """))
541    def analyze_read(self, f, regno):
542        f.write(code_fmt(f"""\
543            ctx_log_reg_read(ctx, {self.reg_num});
544        """))
545
546class ModifierSource(Register, Single, OldSource):
547    def decl_reg_num(self, f, regno):
548        f.write(code_fmt(f"""\
549            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0;
550        """))
551    def decl_tcg(self, f, tag, regno):
552        self.decl_reg_num(f, regno)
553        f.write(code_fmt(f"""\
554            TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
555            TCGv CS G_GNUC_UNUSED =
556                hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0];
557        """))
558    def idef_arg(self, declared):
559        declared.append(self.reg_tcg())
560        declared.append("CS")
561    def analyze_read(self, f, regno):
562        f.write(code_fmt(f"""\
563            ctx_log_reg_read(ctx, {self.reg_num});
564        """))
565
566class PredDest(Register, Single, Dest):
567    def decl_tcg(self, f, tag, regno):
568        self.decl_reg_num(f, regno)
569        f.write(code_fmt(f"""\
570            TCGv {self.reg_tcg()} = tcg_temp_new();
571        """))
572    def log_write(self, f, tag):
573        f.write(code_fmt(f"""\
574            gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
575        """))
576    def analyze_write(self, f, tag, regno):
577        f.write(code_fmt(f"""\
578            ctx_log_pred_write(ctx, {self.reg_num});
579        """))
580
581class PredSource(Register, Single, OldSource):
582    def decl_tcg(self, f, tag, regno):
583        self.decl_reg_num(f, regno)
584        f.write(code_fmt(f"""\
585            TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}];
586        """))
587    def analyze_read(self, f, regno):
588        f.write(code_fmt(f"""\
589            ctx_log_pred_read(ctx, {self.reg_num});
590        """))
591
592class PredNewSource(Register, Single, NewSource):
593    def decl_tcg(self, f, tag, regno):
594        f.write(code_fmt(f"""\
595            TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]);
596        """))
597    def analyze_read(self, f, regno):
598        f.write(code_fmt(f"""\
599            ctx_log_pred_read_new(ctx, {self.reg_num});
600        """))
601
602class PredReadWrite(Register, Single, ReadWrite):
603    def decl_tcg(self, f, tag, regno):
604        self.decl_reg_num(f, regno)
605        f.write(code_fmt(f"""\
606            TCGv {self.reg_tcg()} = tcg_temp_new();
607            tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]);
608        """))
609    def log_write(self, f, tag):
610        f.write(code_fmt(f"""\
611            gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
612        """))
613    def analyze_read(self, f, regno):
614        f.write(code_fmt(f"""\
615            ctx_log_pred_read(ctx, {self.reg_num});
616        """))
617    def analyze_write(self, f, tag, regno):
618        f.write(code_fmt(f"""\
619            ctx_log_pred_write(ctx, {self.reg_num});
620        """))
621
622class PairDest(Register, Pair, Dest):
623    def decl_tcg(self, f, tag, regno):
624        self.decl_reg_num(f, regno)
625        f.write(code_fmt(f"""\
626            TCGv_i64 {self.reg_tcg()} =
627                get_result_gpr_pair(ctx, {self.reg_num});
628        """))
629    def log_write(self, f, tag):
630        f.write(code_fmt(f"""\
631            gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
632        """))
633    def analyze_write(self, f, tag, regno):
634        predicated = "true" if is_predicated(tag) else "false"
635        f.write(code_fmt(f"""\
636            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
637        """))
638
639class PairSource(Register, Pair, OldSource):
640    def decl_tcg(self, f, tag, regno):
641        self.decl_reg_num(f, regno)
642        f.write(code_fmt(f"""\
643            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
644            tcg_gen_concat_i32_i64({self.reg_tcg()},
645                                    hex_gpr[{self.reg_num}],
646                                    hex_gpr[{self.reg_num} + 1]);
647        """))
648    def analyze_read(self, f, regno):
649        f.write(code_fmt(f"""\
650            ctx_log_reg_read_pair(ctx, {self.reg_num});
651        """))
652
653class PairReadWrite(Register, Pair, ReadWrite):
654    def decl_tcg(self, f, tag, regno):
655        self.decl_reg_num(f, regno)
656        f.write(code_fmt(f"""\
657            TCGv_i64 {self.reg_tcg()} =
658                get_result_gpr_pair(ctx, {self.reg_num});
659            tcg_gen_concat_i32_i64({self.reg_tcg()},
660                                   hex_gpr[{self.reg_num}],
661                                   hex_gpr[{self.reg_num} + 1]);
662        """))
663    def log_write(self, f, tag):
664        f.write(code_fmt(f"""\
665            gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
666        """))
667    def analyze_read(self, f, regno):
668        f.write(code_fmt(f"""\
669            ctx_log_reg_read_pair(ctx, {self.reg_num});
670        """))
671    def analyze_write(self, f, tag, regno):
672        predicated = "true" if is_predicated(tag) else "false"
673        f.write(code_fmt(f"""\
674            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
675        """))
676
677class ControlPairDest(Register, Pair, Dest):
678    def decl_reg_num(self, f, regno):
679        f.write(code_fmt(f"""\
680            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
681        """))
682    def decl_tcg(self, f, tag, regno):
683        self.decl_reg_num(f, regno)
684        f.write(code_fmt(f"""\
685            TCGv_i64 {self.reg_tcg()} =
686                get_result_gpr_pair(ctx, {self.reg_num});
687        """))
688    def log_write(self, f, tag):
689        f.write(code_fmt(f"""\
690            gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
691        """))
692    def analyze_write(self, f, tag, regno):
693        predicated = "true" if is_predicated(tag) else "false"
694        f.write(code_fmt(f"""\
695            ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
696        """))
697
698class ControlPairSource(Register, Pair, OldSource):
699    def decl_reg_num(self, f, regno):
700        f.write(code_fmt(f"""\
701            const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0;
702        """))
703    def decl_tcg(self, f, tag, regno):
704        self.decl_reg_num(f, regno)
705        f.write(code_fmt(f"""\
706            TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
707            gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
708        """))
709    def analyze_read(self, f, regno):
710        f.write(code_fmt(f"""\
711            ctx_log_reg_read_pair(ctx, {self.reg_num});
712        """))
713
714class VRegDest(Register, Hvx, Dest):
715    def decl_tcg(self, f, tag, regno):
716        self.decl_reg_num(f, regno)
717        f.write(code_fmt(f"""\
718            const intptr_t {self.hvx_off()} =
719                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
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 log_write(self, f, tag):
727        pass
728    def helper_hvx_desc(self, f):
729        f.write(code_fmt(f"""\
730            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
731        """))
732    def analyze_write(self, f, tag, regno):
733        newv = hvx_newv(tag)
734        predicated = "true" if is_predicated(tag) else "false"
735        f.write(code_fmt(f"""\
736            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated},
737                               insn_has_hvx_helper);
738        """))
739
740class VRegSource(Register, Hvx, OldSource):
741    def decl_tcg(self, f, tag, regno):
742        self.decl_reg_num(f, regno)
743        f.write(code_fmt(f"""\
744            const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num});
745        """))
746        if not skip_qemu_helper(tag):
747            f.write(code_fmt(f"""\
748                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
749                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
750            """))
751    def helper_hvx_desc(self, f):
752        f.write(code_fmt(f"""\
753            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
754        """))
755    def analyze_read(self, f, regno):
756        f.write(code_fmt(f"""\
757            ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
758        """))
759
760class VRegNewSource(Register, Hvx, NewSource):
761    def decl_tcg(self, f, tag, regno):
762        self.decl_reg_num(f, regno)
763        if skip_qemu_helper(tag):
764            f.write(code_fmt(f"""\
765                const intptr_t {self.hvx_off()} =
766                    ctx_future_vreg_off(ctx, {self.reg_num}, 1, true);
767            """))
768    def helper_hvx_desc(self, f):
769        f.write(code_fmt(f"""\
770            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
771        """))
772    def analyze_read(self, f, regno):
773        f.write(code_fmt(f"""\
774            ctx_log_vreg_read_new(ctx, {self.reg_num}, insn_has_hvx_helper);
775        """))
776
777class VRegReadWrite(Register, Hvx, ReadWrite):
778    def decl_tcg(self, f, tag, regno):
779        self.decl_reg_num(f, regno)
780        f.write(code_fmt(f"""\
781            const intptr_t {self.hvx_off()} =
782                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
783            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
784                             vreg_src_off(ctx, {self.reg_num}),
785                             sizeof(MMVector), sizeof(MMVector));
786        """))
787        if not skip_qemu_helper(tag):
788            f.write(code_fmt(f"""\
789                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
790                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
791            """))
792    def log_write(self, f, tag):
793        pass
794    def helper_hvx_desc(self, f):
795        f.write(code_fmt(f"""\
796            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
797        """))
798    def analyze_read(self, f, regno):
799        f.write(code_fmt(f"""\
800            ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
801        """))
802    def analyze_write(self, f, tag, regno):
803        newv = hvx_newv(tag)
804        predicated = "true" if is_predicated(tag) else "false"
805        f.write(code_fmt(f"""\
806            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated},
807                               insn_has_hvx_helper);
808        """))
809
810class VRegTmp(Register, Hvx, ReadWrite):
811    def decl_tcg(self, f, tag, regno):
812        self.decl_reg_num(f, regno)
813        f.write(code_fmt(f"""\
814            const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp);
815        """))
816        if not skip_qemu_helper(tag):
817            f.write(code_fmt(f"""\
818                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
819                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
820                tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
821                                 vreg_src_off(ctx, {self.reg_num}),
822                                 sizeof(MMVector), sizeof(MMVector));
823            """))
824    def log_write(self, f, tag):
825        f.write(code_fmt(f"""\
826            gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num},
827                               {hvx_newv(tag)});
828        """))
829    def helper_hvx_desc(self, f):
830        f.write(code_fmt(f"""\
831            /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
832        """))
833    def analyze_read(self, f, regno):
834        f.write(code_fmt(f"""\
835            ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
836        """))
837    def analyze_write(self, f, tag, regno):
838        newv = hvx_newv(tag)
839        predicated = "true" if is_predicated(tag) else "false"
840        f.write(code_fmt(f"""\
841            ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated},
842                               insn_has_hvx_helper);
843        """))
844
845class VRegPairDest(Register, Hvx, Dest):
846    def decl_tcg(self, f, tag, regno):
847        self.decl_reg_num(f, regno)
848        f.write(code_fmt(f"""\
849            const intptr_t {self.hvx_off()} =
850                {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true);
851        """))
852        if not skip_qemu_helper(tag):
853            f.write(code_fmt(f"""\
854                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
855                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
856            """))
857    def log_write(self, f, tag):
858        pass
859    def helper_hvx_desc(self, f):
860        f.write(code_fmt(f"""\
861            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
862        """))
863    def analyze_write(self, f, tag, regno):
864        newv = hvx_newv(tag)
865        predicated = "true" if is_predicated(tag) else "false"
866        f.write(code_fmt(f"""\
867            ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated},
868                                    insn_has_hvx_helper);
869        """))
870
871class VRegPairSource(Register, Hvx, OldSource):
872    def decl_tcg(self, f, tag, regno):
873        self.decl_reg_num(f, regno)
874        f.write(code_fmt(f"""\
875            const intptr_t {self.hvx_off()} =
876                offsetof(CPUHexagonState, {self.reg_tcg()});
877            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
878                             vreg_src_off(ctx, {self.reg_num}),
879                             sizeof(MMVector), sizeof(MMVector));
880            tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
881                             vreg_src_off(ctx, {self.reg_num} ^ 1),
882                             sizeof(MMVector), sizeof(MMVector));
883        """))
884        if not skip_qemu_helper(tag):
885            f.write(code_fmt(f"""\
886                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
887                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
888            """))
889    def helper_hvx_desc(self, f):
890        f.write(code_fmt(f"""\
891            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
892        """))
893    def analyze_read(self, f, regno):
894        f.write(code_fmt(f"""\
895            ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper);
896        """))
897
898class VRegPairReadWrite(Register, Hvx, ReadWrite):
899    def decl_tcg(self, f, tag, regno):
900        self.decl_reg_num(f, regno)
901        f.write(code_fmt(f"""\
902            const intptr_t {self.hvx_off()} =
903                offsetof(CPUHexagonState, {self.reg_tcg()});
904            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
905                             vreg_src_off(ctx, {self.reg_num}),
906                             sizeof(MMVector), sizeof(MMVector));
907            tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector),
908                             vreg_src_off(ctx, {self.reg_num} ^ 1),
909                             sizeof(MMVector), sizeof(MMVector));
910        """))
911        if not skip_qemu_helper(tag):
912            f.write(code_fmt(f"""\
913                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
914                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
915            """))
916    def log_write(self, f, tag):
917        f.write(code_fmt(f"""\
918            gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num},
919                                    {hvx_newv(tag)});
920        """))
921    def helper_hvx_desc(self, f):
922        f.write(code_fmt(f"""\
923            /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
924        """))
925    def analyze_read(self, f, regno):
926        f.write(code_fmt(f"""\
927            ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper);
928        """))
929    def analyze_write(self, f, tag, regno):
930        newv = hvx_newv(tag)
931        predicated = "true" if is_predicated(tag) else "false"
932        f.write(code_fmt(f"""\
933            ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated},
934                                    insn_has_hvx_helper);
935        """))
936
937class QRegDest(Register, Hvx, Dest):
938    def decl_tcg(self, f, tag, regno):
939        self.decl_reg_num(f, regno)
940        f.write(code_fmt(f"""\
941            const intptr_t {self.hvx_off()} =
942                get_result_qreg(ctx, {self.reg_num});
943        """))
944        if not skip_qemu_helper(tag):
945            f.write(code_fmt(f"""\
946                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
947                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
948            """))
949    def log_write(self, f, tag):
950        pass
951    def helper_hvx_desc(self, f):
952        f.write(code_fmt(f"""\
953            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
954        """))
955    def analyze_write(self, f, tag, regno):
956        f.write(code_fmt(f"""\
957            ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
958        """))
959
960class QRegSource(Register, Hvx, OldSource):
961    def decl_tcg(self, f, tag, regno):
962        self.decl_reg_num(f, regno)
963        f.write(code_fmt(f"""\
964            const intptr_t {self.hvx_off()} =
965                offsetof(CPUHexagonState, QRegs[{self.reg_num}]);
966        """))
967        if not skip_qemu_helper(tag):
968            f.write(code_fmt(f"""\
969                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
970                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
971            """))
972    def helper_hvx_desc(self, f):
973        f.write(code_fmt(f"""\
974            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
975        """))
976    def analyze_read(self, f, regno):
977        f.write(code_fmt(f"""\
978            ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
979        """))
980
981class QRegReadWrite(Register, Hvx, ReadWrite):
982    def decl_tcg(self, f, tag, regno):
983        self.decl_reg_num(f, regno)
984        f.write(code_fmt(f"""\
985            const intptr_t {self.hvx_off()} =
986                get_result_qreg(ctx, {self.reg_num});
987            tcg_gen_gvec_mov(MO_64, {self.hvx_off()},
988                             offsetof(CPUHexagonState, QRegs[{self.reg_num}]),
989                             sizeof(MMQReg), sizeof(MMQReg));
990        """))
991        if not skip_qemu_helper(tag):
992            f.write(code_fmt(f"""\
993                TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
994                tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
995            """))
996    def log_write(self, f, tag):
997        pass
998    def helper_hvx_desc(self, f):
999        f.write(code_fmt(f"""\
1000            /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
1001        """))
1002    def analyze_read(self, f, regno):
1003        f.write(code_fmt(f"""\
1004            ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper);
1005        """))
1006    def analyze_write(self, f, tag, regno):
1007        f.write(code_fmt(f"""\
1008            ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
1009        """))
1010
1011def init_registers():
1012    regs = {
1013        GprDest("R", "d"),
1014        GprDest("R", "e"),
1015        GprSource("R", "s"),
1016        GprSource("R", "t"),
1017        GprSource("R", "u"),
1018        GprSource("R", "v"),
1019        GprReadWrite("R", "x"),
1020        GprReadWrite("R", "y"),
1021        ControlDest("C", "d"),
1022        ControlSource("C", "s"),
1023        ModifierSource("M", "u"),
1024        PredDest("P", "d"),
1025        PredDest("P", "e"),
1026        PredSource("P", "s"),
1027        PredSource("P", "t"),
1028        PredSource("P", "u"),
1029        PredSource("P", "v"),
1030        PredReadWrite("P", "x"),
1031        PairDest("R", "dd"),
1032        PairDest("R", "ee"),
1033        PairSource("R", "ss"),
1034        PairSource("R", "tt"),
1035        PairReadWrite("R", "xx"),
1036        PairReadWrite("R", "yy"),
1037        ControlPairDest("C", "dd"),
1038        ControlPairSource("C", "ss"),
1039        VRegDest("V", "d"),
1040        VRegSource("V", "s"),
1041        VRegSource("V", "u"),
1042        VRegSource("V", "v"),
1043        VRegSource("V", "w"),
1044        VRegReadWrite("V", "x"),
1045        VRegTmp("V", "y"),
1046        VRegPairDest("V", "dd"),
1047        VRegPairSource("V", "uu"),
1048        VRegPairSource("V", "vv"),
1049        VRegPairReadWrite("V", "xx"),
1050        QRegDest("Q", "d"),
1051        QRegDest("Q", "e"),
1052        QRegSource("Q", "s"),
1053        QRegSource("Q", "t"),
1054        QRegSource("Q", "u"),
1055        QRegSource("Q", "v"),
1056        QRegReadWrite("Q", "x"),
1057    }
1058    for reg in regs:
1059        registers[f"{reg.regtype}{reg.regid}"] = reg
1060
1061    new_regs = {
1062        GprNewSource("N", "s"),
1063        GprNewSource("N", "t"),
1064        PredNewSource("P", "t"),
1065        PredNewSource("P", "u"),
1066        PredNewSource("P", "v"),
1067        VRegNewSource("O", "s"),
1068    }
1069    for reg in new_regs:
1070        new_registers[f"{reg.regtype}{reg.regid}"] = reg
1071
1072def get_register(tag, regtype, regid):
1073    if f"{regtype}{regid}V" in semdict[tag]:
1074        return registers[f"{regtype}{regid}"]
1075    else:
1076        return new_registers[f"{regtype}{regid}"]
1077
1078def helper_ret_type(tag, regs):
1079    ## If there is a scalar result, it is the return type
1080    return_type = HelperArg( "void", "void", "void")
1081    numscalarresults = 0
1082    for regtype, regid in regs:
1083        reg = get_register(tag, regtype, regid)
1084        if reg.is_written() and reg.is_scalar_reg():
1085            return_type = HelperArg(
1086                reg.helper_proto_type(),
1087                reg.reg_tcg(),
1088                reg.helper_arg_type()
1089            )
1090    if numscalarresults > 1:
1091        raise Exception("numscalarresults > 1")
1092    return return_type
1093
1094def helper_args(tag, regs, imms):
1095    args = []
1096
1097    ## First argument is the CPU state
1098    if need_env(tag):
1099        args.append(HelperArg(
1100            "env",
1101            "tcg_env",
1102            "CPUHexagonState *env"
1103        ))
1104
1105    ## For predicated instructions, we pass in the destination register
1106    if is_predicated(tag):
1107        for regtype, regid in regs:
1108            reg = get_register(tag, regtype, regid)
1109            if reg.is_writeonly() and not reg.is_hvx_reg():
1110                args.append(reg.helper_arg())
1111
1112    ## Pass the HVX destination registers
1113    for regtype, regid in regs:
1114        reg = get_register(tag, regtype, regid)
1115        if reg.is_written() and reg.is_hvx_reg():
1116            args.append(reg.helper_arg())
1117
1118    ## Pass the source registers
1119    for regtype, regid in regs:
1120        reg = get_register(tag, regtype, regid)
1121        if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
1122            args.append(reg.helper_arg())
1123
1124    ## Pass the immediates
1125    for immlett, bits, immshift in imms:
1126        args.append(HelperArg(
1127            "s32",
1128            f"tcg_constant_tl({imm_name(immlett)})",
1129            f"int32_t {imm_name(immlett)}"
1130        ))
1131
1132    ## Other stuff the helper might need
1133    if need_pkt_has_multi_cof(tag):
1134        args.append(HelperArg(
1135            "i32",
1136            "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
1137            "uint32_t pkt_has_multi_cof"
1138        ))
1139    if need_pkt_need_commit(tag):
1140        args.append(HelperArg(
1141            "i32",
1142            "tcg_constant_tl(ctx->need_commit)",
1143            "uint32_t pkt_need_commit"
1144        ))
1145    if need_PC(tag):
1146        args.append(HelperArg(
1147            "i32",
1148            "tcg_constant_tl(ctx->pkt->pc)",
1149            "target_ulong PC"
1150        ))
1151    if need_next_PC(tag):
1152        args.append(HelperArg(
1153            "i32",
1154            "tcg_constant_tl(ctx->next_PC)",
1155            "target_ulong next_PC"
1156        ))
1157    if need_p0(tag):
1158        args.append(HelperArg(
1159            "i32",
1160            "hex_pred[0]",
1161            "uint32_t P0"
1162        ))
1163    if need_sp(tag):
1164        args.append(HelperArg(
1165            "i32",
1166            "hex_gpr[HEX_REG_SP]",
1167            "uint32_t SP"
1168        ))
1169    if need_slot(tag):
1170        args.append(HelperArg(
1171            "i32",
1172            "gen_slotval(ctx)",
1173            "uint32_t slotval"
1174        ))
1175    if need_part1(tag):
1176        args.append(HelperArg(
1177            "i32",
1178            "tcg_constant_tl(insn->part1)"
1179            "uint32_t part1"
1180        ))
1181    return args
1182
1183
1184def read_common_files():
1185    read_semantics_file(sys.argv[1])
1186    read_overrides_file(sys.argv[2])
1187    read_overrides_file(sys.argv[3])
1188    ## Whether or not idef-parser is enabled is
1189    ## determined by the number of arguments to
1190    ## this script:
1191    ##
1192    ##   4 args. -> not enabled,
1193    ##   5 args. -> idef-parser enabled.
1194    ##
1195    ## The 5:th arg. then holds a list of the successfully
1196    ## parsed instructions.
1197    is_idef_parser_enabled = len(sys.argv) > 5
1198    if is_idef_parser_enabled:
1199        read_idef_parser_enabled_file(sys.argv[4])
1200    calculate_attribs()
1201    init_registers()
1202    return is_idef_parser_enabled
1203