1#!/usr/bin/env python3
2
3##
4##  Copyright(c) 2019-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##     Generate data for printing each instruction (format string + operands)
28##
29def regprinter(m):
30    str = m.group(1)
31    str += ":".join(["%d"] * len(m.group(2)))
32    str += m.group(3)
33    if ("S" in m.group(1)) and (len(m.group(2)) == 1):
34        str += "/%s"
35    elif ("C" in m.group(1)) and (len(m.group(2)) == 1):
36        str += "/%s"
37    return str
38
39
40def spacify(s):
41    # Regular expression that matches any operator that contains '=' character:
42    opswithequal_re = "[-+^&|!<>=]?="
43    # Regular expression that matches any assignment operator.
44    assignment_re = "[-+^&|]?="
45
46    # Out of the operators that contain the = sign, if the operator is also an
47    # assignment, spaces will be added around it, unless it's enclosed within
48    # parentheses, or spaces are already present.
49
50    equals = re.compile(opswithequal_re)
51    assign = re.compile(assignment_re)
52
53    slen = len(s)
54    paren_count = {}
55    i = 0
56    pc = 0
57    while i < slen:
58        c = s[i]
59        if c == "(":
60            pc += 1
61        elif c == ")":
62            pc -= 1
63        paren_count[i] = pc
64        i += 1
65
66    # Iterate over all operators that contain the equal sign. If any
67    # match is also an assignment operator, add spaces around it if
68    # the parenthesis count is 0.
69    pos = 0
70    out = []
71    for m in equals.finditer(s):
72        ms = m.start()
73        me = m.end()
74        # t is the string that matched opswithequal_re.
75        t = m.string[ms:me]
76        out += s[pos:ms]
77        pos = me
78        if paren_count[ms] == 0:
79            # Check if the entire string t is an assignment.
80            am = assign.match(t)
81            if am and len(am.group(0)) == me - ms:
82                # Don't add spaces if they are already there.
83                if ms > 0 and s[ms - 1] != " ":
84                    out.append(" ")
85                out += t
86                if me < slen and s[me] != " ":
87                    out.append(" ")
88                continue
89        # If this is not an assignment, just append it to the output
90        # string.
91        out += t
92
93    # Append the remaining part of the string.
94    out += s[pos : len(s)]
95    return "".join(out)
96
97
98def main():
99    hex_common.read_semantics_file(sys.argv[1])
100    hex_common.read_attribs_file(sys.argv[2])
101
102    immext_casere = re.compile(r"IMMEXT\(([A-Za-z])")
103
104    with open(sys.argv[3], "w") as f:
105        for tag in hex_common.tags:
106            if not hex_common.behdict[tag]:
107                continue
108            extendable_upper_imm = False
109            extendable_lower_imm = False
110            m = immext_casere.search(hex_common.semdict[tag])
111            if m:
112                if m.group(1).isupper():
113                    extendable_upper_imm = True
114                else:
115                    extendable_lower_imm = True
116            beh = hex_common.behdict[tag]
117            beh = hex_common.regre.sub(regprinter, beh)
118            beh = hex_common.absimmre.sub(r"#%s0x%x", beh)
119            beh = hex_common.relimmre.sub(r"PC+%s%d", beh)
120            beh = spacify(beh)
121            # Print out a literal "%s" at the end, used to match empty string
122            # so C won't complain at us
123            if "A_VECX" in hex_common.attribdict[tag]:
124                macname = "DEF_VECX_PRINTINFO"
125            else:
126                macname = "DEF_PRINTINFO"
127            f.write(f'{macname}({tag},"{beh}%s"')
128            regs_or_imms = hex_common.reg_or_immre.findall(hex_common.behdict[tag])
129            ri = 0
130            seenregs = {}
131            for allregs, a, b, c, d, allimm, immlett, bits, immshift in regs_or_imms:
132                if a:
133                    # register
134                    if b in seenregs:
135                        regno = seenregs[b]
136                    else:
137                        regno = ri
138                    if len(b) == 1:
139                        f.write(f", insn->regno[{regno}]")
140                        if "S" in a:
141                            f.write(f", sreg2str(insn->regno[{regno}])")
142                        elif "C" in a:
143                            f.write(f", creg2str(insn->regno[{regno}])")
144                    elif len(b) == 2:
145                        f.write(f", insn->regno[{regno}] + 1" f", insn->regno[{regno}]")
146                    else:
147                        print("Put some stuff to handle quads here")
148                    if b not in seenregs:
149                        seenregs[b] = ri
150                        ri += 1
151                else:
152                    # immediate
153                    if immlett.isupper():
154                        if extendable_upper_imm:
155                            if immlett in "rR":
156                                f.write(',insn->extension_valid?"##":""')
157                            else:
158                                f.write(',insn->extension_valid?"#":""')
159                        else:
160                            f.write(',""')
161                        ii = 1
162                    else:
163                        if extendable_lower_imm:
164                            if immlett in "rR":
165                                f.write(',insn->extension_valid?"##":""')
166                            else:
167                                f.write(',insn->extension_valid?"#":""')
168                        else:
169                            f.write(',""')
170                        ii = 0
171                    f.write(f", insn->immed[{ii}]")
172            # append empty string so there is at least one more arg
173            f.write(',"")\n')
174
175
176if __name__ == "__main__":
177    main()
178