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