qemu/target/hexagon/gen_printinsn.py

178 lines
6.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
##
## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, see <http://www.gnu.org/licenses/>.
##
import sys
import re
import string
import hex_common
##
## Generate data for printing each instruction (format string + operands)
##
def regprinter(m):
str = m.group(1)
str += ":".join(["%d"] * len(m.group(2)))
str += m.group(3)
if ("S" in m.group(1)) and (len(m.group(2)) == 1):
str += "/%s"
elif ("C" in m.group(1)) and (len(m.group(2)) == 1):
str += "/%s"
return str
def spacify(s):
# Regular expression that matches any operator that contains '=' character:
opswithequal_re = "[-+^&|!<>=]?="
# Regular expression that matches any assignment operator.
assignment_re = "[-+^&|]?="
# Out of the operators that contain the = sign, if the operator is also an
# assignment, spaces will be added around it, unless it's enclosed within
# parentheses, or spaces are already present.
equals = re.compile(opswithequal_re)
assign = re.compile(assignment_re)
slen = len(s)
paren_count = {}
i = 0
pc = 0
while i < slen:
c = s[i]
if c == "(":
pc += 1
elif c == ")":
pc -= 1
paren_count[i] = pc
i += 1
# Iterate over all operators that contain the equal sign. If any
# match is also an assignment operator, add spaces around it if
# the parenthesis count is 0.
pos = 0
out = []
for m in equals.finditer(s):
ms = m.start()
me = m.end()
# t is the string that matched opswithequal_re.
t = m.string[ms:me]
out += s[pos:ms]
pos = me
if paren_count[ms] == 0:
# Check if the entire string t is an assignment.
am = assign.match(t)
if am and len(am.group(0)) == me - ms:
# Don't add spaces if they are already there.
if ms > 0 and s[ms - 1] != " ":
out.append(" ")
out += t
if me < slen and s[me] != " ":
out.append(" ")
continue
# If this is not an assignment, just append it to the output
# string.
out += t
# Append the remaining part of the string.
out += s[pos : len(s)]
return "".join(out)
def main():
hex_common.read_semantics_file(sys.argv[1])
hex_common.read_attribs_file(sys.argv[2])
immext_casere = re.compile(r"IMMEXT\(([A-Za-z])")
with open(sys.argv[3], "w") as f:
for tag in hex_common.tags:
if not hex_common.behdict[tag]:
continue
extendable_upper_imm = False
extendable_lower_imm = False
m = immext_casere.search(hex_common.semdict[tag])
if m:
if m.group(1).isupper():
extendable_upper_imm = True
else:
extendable_lower_imm = True
beh = hex_common.behdict[tag]
beh = hex_common.regre.sub(regprinter, beh)
beh = hex_common.absimmre.sub(r"#%s0x%x", beh)
beh = hex_common.relimmre.sub(r"PC+%s%d", beh)
beh = spacify(beh)
# Print out a literal "%s" at the end, used to match empty string
# so C won't complain at us
if "A_VECX" in hex_common.attribdict[tag]:
macname = "DEF_VECX_PRINTINFO"
else:
macname = "DEF_PRINTINFO"
f.write(f'{macname}({tag},"{beh}%s"')
regs_or_imms = hex_common.reg_or_immre.findall(hex_common.behdict[tag])
ri = 0
seenregs = {}
for allregs, a, b, c, d, allimm, immlett, bits, immshift in regs_or_imms:
if a:
# register
if b in seenregs:
regno = seenregs[b]
else:
regno = ri
if len(b) == 1:
f.write(f", insn->regno[{regno}]")
if "S" in a:
f.write(f", sreg2str(insn->regno[{regno}])")
elif "C" in a:
f.write(f", creg2str(insn->regno[{regno}])")
elif len(b) == 2:
f.write(f", insn->regno[{regno}] + 1" f", insn->regno[{regno}]")
else:
print("Put some stuff to handle quads here")
if b not in seenregs:
seenregs[b] = ri
ri += 1
else:
# immediate
if immlett.isupper():
if extendable_upper_imm:
if immlett in "rR":
f.write(',insn->extension_valid?"##":""')
else:
f.write(',insn->extension_valid?"#":""')
else:
f.write(',""')
ii = 1
else:
if extendable_lower_imm:
if immlett in "rR":
f.write(',insn->extension_valid?"##":""')
else:
f.write(',insn->extension_valid?"#":""')
else:
f.write(',""')
ii = 0
f.write(f", insn->immed[{ii}]")
# append empty string so there is at least one more arg
f.write(',"")\n')
if __name__ == "__main__":
main()