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