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