xref: /qemu/target/hexagon/gen_idef_parser_funcs.py (revision 513823e7521a09ed7ad1e32e6454bac3b2cbf52d)
1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-2024 rev.ng Labs Srl. 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 argparse
24from io import StringIO
25
26import hex_common
27
28
29##
30## Generate code to be fed to the idef_parser
31##
32## Consider A2_add:
33##
34##     Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
35##
36## We produce:
37##
38##     A2_add(RdV, in RsV, in RtV) {
39##       { RdV=RsV+RtV;}
40##     }
41##
42## A2_add represents the instruction tag. Then we have a list of TCGv
43## that the code generated by the parser can expect in input. Some of
44## them are inputs ("in" prefix), while some others are outputs.
45##
46def main():
47    parser = argparse.ArgumentParser(
48        "Emit instruction implementations that can be fed to idef-parser"
49    )
50    parser.add_argument("semantics", help="semantics file")
51    parser.add_argument("out", help="output file")
52    args = parser.parse_args()
53    hex_common.read_semantics_file(args.semantics)
54    hex_common.calculate_attribs()
55    hex_common.init_registers()
56    tagregs = hex_common.get_tagregs()
57    tagimms = hex_common.get_tagimms()
58
59    with open(args.out, "w") as f:
60        f.write('#include "macros.h.inc"\n\n')
61
62        for tag in hex_common.tags:
63            ## Skip the priv instructions
64            if "A_PRIV" in hex_common.attribdict[tag]:
65                continue
66            ## Skip the guest instructions
67            if "A_GUEST" in hex_common.attribdict[tag]:
68                continue
69            ## Skip instructions that saturate in a ternary expression
70            if tag in {"S2_asr_r_r_sat", "S2_asl_r_r_sat"}:
71                continue
72            ## Skip instructions using switch
73            if tag in {"S4_vrcrotate_acc", "S4_vrcrotate"}:
74                continue
75            ## Skip trap instructions
76            if tag in {"J2_trap0", "J2_trap1"}:
77                continue
78            ## Skip 128-bit instructions
79            if tag in {"A7_croundd_ri", "A7_croundd_rr"}:
80                continue
81            if tag in {
82                "M7_wcmpyrw",
83                "M7_wcmpyrwc",
84                "M7_wcmpyiw",
85                "M7_wcmpyiwc",
86                "M7_wcmpyrw_rnd",
87                "M7_wcmpyrwc_rnd",
88                "M7_wcmpyiw_rnd",
89                "M7_wcmpyiwc_rnd",
90            }:
91                continue
92            ## Skip interleave/deinterleave instructions
93            if tag in {"S2_interleave", "S2_deinterleave"}:
94                continue
95            ## Skip instructions using bit reverse
96            if tag in {
97                "S2_brev",
98                "S2_brevp",
99                "S2_ct0",
100                "S2_ct1",
101                "S2_ct0p",
102                "S2_ct1p",
103                "A4_tlbmatch",
104            }:
105                continue
106            ## Skip other unsupported instructions
107            if tag == "S2_cabacdecbin" or tag == "A5_ACS":
108                continue
109            if tag.startswith("Y"):
110                continue
111            if tag.startswith("V6_"):
112                continue
113            if ( tag.startswith("F") and
114                 tag not in {
115                     "F2_sfimm_p",
116                     "F2_sfimm_n",
117                     "F2_dfimm_p",
118                     "F2_dfimm_n",
119                     "F2_dfmpyll",
120                     "F2_dfmpylh"
121                 }):
122                continue
123            if tag.endswith("_locked"):
124                continue
125            if "A_COF" in hex_common.attribdict[tag]:
126                continue
127            if ( tag.startswith('R6_release_') ):
128                continue
129            ## Skip instructions that are incompatible with short-circuit
130            ## packet register writes
131            if ( tag == 'S2_insert' or
132                 tag == 'S2_insert_rp' or
133                 tag == 'S2_asr_r_svw_trun' or
134                 tag == 'A2_swiz' ):
135                continue
136
137            regs = tagregs[tag]
138            imms = tagimms[tag]
139
140            arguments = []
141            for regtype, regid in regs:
142                reg = hex_common.get_register(tag, regtype, regid)
143                prefix = "in " if reg.is_read() else ""
144                arguments.append(f"{prefix}{reg.reg_tcg()}")
145
146            for immlett, bits, immshift in imms:
147                arguments.append(hex_common.imm_name(immlett))
148
149            f.write(f"{tag}({', '.join(arguments)}) {{\n")
150            f.write("    ")
151            if hex_common.need_ea(tag):
152                f.write("size4u_t EA; ")
153            f.write(f"{hex_common.semdict[tag]}\n")
154            f.write("}\n\n")
155
156
157if __name__ == "__main__":
158    main()
159