xref: /qemu/target/hexagon/gen_analyze_funcs.py (revision cd6c4edff69ce6ba0aa8e6ed702f43a042a456bc)
1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
5##
6##  This program is free software; you can redistribute it and/or modify
7##  it under the terms of the GNU General Public License as published by
8##  the Free Software Foundation; either version 2 of the License, or
9##  (at your option) any later version.
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 hex_common
24
25##
26## Helpers for gen_analyze_func
27##
28def is_predicated(tag):
29    return 'A_CONDEXEC' in hex_common.attribdict[tag]
30
31def analyze_opn_old(f, tag, regtype, regid, regno):
32    regN = f"{regtype}{regid}N"
33    predicated = "true" if is_predicated(tag) else "false"
34    if (regtype == "R"):
35        if (regid in {"ss", "tt"}):
36            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
37        elif (regid in {"dd", "ee", "xx", "yy"}):
38            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
39            f.write(f"    ctx_log_reg_write_pair(ctx, {regN}, {predicated});\n")
40        elif (regid in {"s", "t", "u", "v"}):
41            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
42        elif (regid in {"d", "e", "x", "y"}):
43            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
44            f.write(f"    ctx_log_reg_write(ctx, {regN}, {predicated});\n")
45        else:
46            print("Bad register parse: ", regtype, regid)
47    elif (regtype == "P"):
48        if (regid in {"s", "t", "u", "v"}):
49            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
50        elif (regid in {"d", "e", "x"}):
51            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
52            f.write(f"    ctx_log_pred_write(ctx, {regN});\n")
53        else:
54            print("Bad register parse: ", regtype, regid)
55    elif (regtype == "C"):
56        if (regid == "ss"):
57            f.write(f"//    const int {regN} = insn->regno[{regno}] "
58                     "+ HEX_REG_SA0;\n")
59        elif (regid == "dd"):
60            f.write(f"    const int {regN} = insn->regno[{regno}] "
61                     "+ HEX_REG_SA0;\n")
62            f.write(f"    ctx_log_reg_write_pair(ctx, {regN}, {predicated});\n")
63        elif (regid == "s"):
64            f.write(f"//    const int {regN} = insn->regno[{regno}] "
65                     "+ HEX_REG_SA0;\n")
66        elif (regid == "d"):
67            f.write(f"    const int {regN} = insn->regno[{regno}] "
68                     "+ HEX_REG_SA0;\n")
69            f.write(f"    ctx_log_reg_write(ctx, {regN}, {predicated});\n")
70        else:
71            print("Bad register parse: ", regtype, regid)
72    elif (regtype == "M"):
73        if (regid == "u"):
74            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
75        else:
76            print("Bad register parse: ", regtype, regid)
77    elif (regtype == "V"):
78        newv = "EXT_DFL"
79        if (hex_common.is_new_result(tag)):
80            newv = "EXT_NEW"
81        elif (hex_common.is_tmp_result(tag)):
82            newv = "EXT_TMP"
83        if (regid in {"dd", "xx"}):
84            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
85            f.write(f"    ctx_log_vreg_write_pair(ctx, {regN}, {newv}, "
86                    f"{predicated});\n")
87        elif (regid in {"uu", "vv"}):
88            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
89        elif (regid in {"s", "u", "v", "w"}):
90            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
91        elif (regid in {"d", "x", "y"}):
92            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
93            f.write(f"    ctx_log_vreg_write(ctx, {regN}, {newv}, "
94                    f"{predicated});\n")
95        else:
96            print("Bad register parse: ", regtype, regid)
97    elif (regtype == "Q"):
98        if (regid in {"d", "e", "x"}):
99            f.write(f"    const int {regN} = insn->regno[{regno}];\n")
100            f.write(f"    ctx_log_qreg_write(ctx, {regN});\n")
101        elif (regid in {"s", "t", "u", "v"}):
102            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
103        else:
104            print("Bad register parse: ", regtype, regid)
105    elif (regtype == "G"):
106        if (regid in {"dd"}):
107            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
108        elif (regid in {"d"}):
109            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
110        elif (regid in {"ss"}):
111            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
112        elif (regid in {"s"}):
113            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
114        else:
115            print("Bad register parse: ", regtype, regid)
116    elif (regtype == "S"):
117        if (regid in {"dd"}):
118            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
119        elif (regid in {"d"}):
120            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
121        elif (regid in {"ss"}):
122            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
123        elif (regid in {"s"}):
124            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
125        else:
126            print("Bad register parse: ", regtype, regid)
127    else:
128        print("Bad register parse: ", regtype, regid)
129
130def analyze_opn_new(f, tag, regtype, regid, regno):
131    regN = f"{regtype}{regid}N"
132    if (regtype == "N"):
133        if (regid in {"s", "t"}):
134            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
135        else:
136            print("Bad register parse: ", regtype, regid)
137    elif (regtype == "P"):
138        if (regid in {"t", "u", "v"}):
139            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
140        else:
141            print("Bad register parse: ", regtype, regid)
142    elif (regtype == "O"):
143        if (regid == "s"):
144            f.write(f"//    const int {regN} = insn->regno[{regno}];\n")
145        else:
146            print("Bad register parse: ", regtype, regid)
147    else:
148        print("Bad register parse: ", regtype, regid)
149
150def analyze_opn(f, tag, regtype, regid, toss, numregs, i):
151    if (hex_common.is_pair(regid)):
152        analyze_opn_old(f, tag, regtype, regid, i)
153    elif (hex_common.is_single(regid)):
154        if hex_common.is_old_val(regtype, regid, tag):
155            analyze_opn_old(f,tag, regtype, regid, i)
156        elif hex_common.is_new_val(regtype, regid, tag):
157            analyze_opn_new(f, tag, regtype, regid, i)
158        else:
159            print("Bad register parse: ", regtype, regid, toss, numregs)
160    else:
161        print("Bad register parse: ", regtype, regid, toss, numregs)
162
163##
164## Generate the code to analyze the instruction
165##     For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
166##     We produce:
167##     static void analyze_A2_add(DisasContext *ctx)
168##     {
169##         Insn *insn G_GNUC_UNUSED = ctx->insn;
170##         const int RdN = insn->regno[0];
171##         ctx_log_reg_write(ctx, RdN, false);
172##     //    const int RsN = insn->regno[1];
173##     //    const int RtN = insn->regno[2];
174##     }
175##
176def gen_analyze_func(f, tag, regs, imms):
177    f.write(f"static void analyze_{tag}(DisasContext *ctx)\n")
178    f.write('{\n')
179
180    f.write("    Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
181
182    i=0
183    ## Analyze all the registers
184    for regtype, regid, toss, numregs in regs:
185        analyze_opn(f, tag, regtype, regid, toss, numregs, i)
186        i += 1
187
188    has_generated_helper = (not hex_common.skip_qemu_helper(tag) and
189                            not hex_common.is_idef_parser_enabled(tag))
190    if (has_generated_helper and
191        'A_SCALAR_LOAD' in hex_common.attribdict[tag]):
192        f.write("    ctx->need_pkt_has_store_s1 = true;\n")
193
194    f.write("}\n\n")
195
196def main():
197    hex_common.read_semantics_file(sys.argv[1])
198    hex_common.read_attribs_file(sys.argv[2])
199    hex_common.read_overrides_file(sys.argv[3])
200    hex_common.read_overrides_file(sys.argv[4])
201    ## Whether or not idef-parser is enabled is
202    ## determined by the number of arguments to
203    ## this script:
204    ##
205    ##   5 args. -> not enabled,
206    ##   6 args. -> idef-parser enabled.
207    ##
208    ## The 6:th arg. then holds a list of the successfully
209    ## parsed instructions.
210    is_idef_parser_enabled = len(sys.argv) > 6
211    if is_idef_parser_enabled:
212        hex_common.read_idef_parser_enabled_file(sys.argv[5])
213    hex_common.calculate_attribs()
214    tagregs = hex_common.get_tagregs()
215    tagimms = hex_common.get_tagimms()
216
217    with open(sys.argv[-1], 'w') as f:
218        f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
219        f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
220
221        for tag in hex_common.tags:
222            gen_analyze_func(f, tag, tagregs[tag], tagimms[tag])
223
224        f.write("#endif    /* HEXAGON_TCG_FUNCS_H */\n")
225
226if __name__ == "__main__":
227    main()
228