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