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