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