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## Helpers for gen_helper_function 27## 28def gen_decl_ea(f): 29 f.write(" uint32_t EA;\n") 30 31def gen_helper_return_type(f,regtype,regid,regno): 32 if regno > 1 : f.write(", ") 33 f.write("int32_t") 34 35def gen_helper_return_type_pair(f,regtype,regid,regno): 36 if regno > 1 : f.write(", ") 37 f.write("int64_t") 38 39def gen_helper_arg(f,regtype,regid,regno): 40 if regno > 0 : f.write(", " ) 41 f.write("int32_t %s%sV" % (regtype,regid)) 42 43def gen_helper_arg_new(f,regtype,regid,regno): 44 if regno >= 0 : f.write(", " ) 45 f.write("int32_t %s%sN" % (regtype,regid)) 46 47def gen_helper_arg_pair(f,regtype,regid,regno): 48 if regno >= 0 : f.write(", ") 49 f.write("int64_t %s%sV" % (regtype,regid)) 50 51def gen_helper_arg_ext(f,regtype,regid,regno): 52 if regno > 0 : f.write(", ") 53 f.write("void *%s%sV_void" % (regtype,regid)) 54 55def gen_helper_arg_ext_pair(f,regtype,regid,regno): 56 if regno > 0 : f.write(", ") 57 f.write("void *%s%sV_void" % (regtype,regid)) 58 59def gen_helper_arg_opn(f,regtype,regid,i,tag): 60 if (hex_common.is_pair(regid)): 61 if (hex_common.is_hvx_reg(regtype)): 62 gen_helper_arg_ext_pair(f,regtype,regid,i) 63 else: 64 gen_helper_arg_pair(f,regtype,regid,i) 65 elif (hex_common.is_single(regid)): 66 if hex_common.is_old_val(regtype, regid, tag): 67 if (hex_common.is_hvx_reg(regtype)): 68 gen_helper_arg_ext(f,regtype,regid,i) 69 else: 70 gen_helper_arg(f,regtype,regid,i) 71 elif hex_common.is_new_val(regtype, regid, tag): 72 gen_helper_arg_new(f,regtype,regid,i) 73 else: 74 print("Bad register parse: ",regtype,regid,toss,numregs) 75 else: 76 print("Bad register parse: ",regtype,regid,toss,numregs) 77 78def gen_helper_arg_imm(f,immlett): 79 f.write(", int32_t %s" % (hex_common.imm_name(immlett))) 80 81def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""): 82 f.write(" int32_t %s%sV%s = 0;\n" % \ 83 (regtype,regid,subfield)) 84 85def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""): 86 f.write(" int64_t %s%sV%s = 0;\n" % \ 87 (regtype,regid,subfield)) 88 89def gen_helper_dest_decl_ext(f,regtype,regid): 90 if (regtype == "Q"): 91 f.write(" /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \ 92 (regtype,regid,regtype,regid)) 93 else: 94 f.write(" /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \ 95 (regtype,regid,regtype,regid)) 96 97def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno): 98 f.write(" /* %s%sV is *(MMVectorPair *))%s%sV_void) */\n" % \ 99 (regtype,regid,regtype, regid)) 100 101def gen_helper_dest_decl_opn(f,regtype,regid,i): 102 if (hex_common.is_pair(regid)): 103 if (hex_common.is_hvx_reg(regtype)): 104 gen_helper_dest_decl_ext_pair(f,regtype,regid, i) 105 else: 106 gen_helper_dest_decl_pair(f,regtype,regid,i) 107 elif (hex_common.is_single(regid)): 108 if (hex_common.is_hvx_reg(regtype)): 109 gen_helper_dest_decl_ext(f,regtype,regid) 110 else: 111 gen_helper_dest_decl(f,regtype,regid,i) 112 else: 113 print("Bad register parse: ",regtype,regid,toss,numregs) 114 115def gen_helper_src_var_ext(f,regtype,regid): 116 if (regtype == "Q"): 117 f.write(" /* %s%sV is *(MMQReg *)(%s%sV_void) */\n" % \ 118 (regtype,regid,regtype,regid)) 119 else: 120 f.write(" /* %s%sV is *(MMVector *)(%s%sV_void) */\n" % \ 121 (regtype,regid,regtype,regid)) 122 123def gen_helper_src_var_ext_pair(f,regtype,regid,regno): 124 f.write(" /* %s%sV%s is *(MMVectorPair *)(%s%sV%s_void) */\n" % \ 125 (regtype,regid,regno,regtype,regid,regno)) 126 127def gen_helper_return(f,regtype,regid,regno): 128 f.write(" return %s%sV;\n" % (regtype,regid)) 129 130def gen_helper_return_pair(f,regtype,regid,regno): 131 f.write(" return %s%sV;\n" % (regtype,regid)) 132 133def gen_helper_dst_write_ext(f,regtype,regid): 134 return 135 136def gen_helper_dst_write_ext_pair(f,regtype,regid): 137 return 138 139def gen_helper_return_opn(f, regtype, regid, i): 140 if (hex_common.is_pair(regid)): 141 if (hex_common.is_hvx_reg(regtype)): 142 gen_helper_dst_write_ext_pair(f,regtype,regid) 143 else: 144 gen_helper_return_pair(f,regtype,regid,i) 145 elif (hex_common.is_single(regid)): 146 if (hex_common.is_hvx_reg(regtype)): 147 gen_helper_dst_write_ext(f,regtype,regid) 148 else: 149 gen_helper_return(f,regtype,regid,i) 150 else: 151 print("Bad register parse: ",regtype,regid,toss,numregs) 152 153## 154## Generate the TCG code to call the helper 155## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;} 156## We produce: 157## int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV) 158## { 159## uint32_t slot __attribute__(unused)) = 4; 160## int32_t RdV = 0; 161## { RdV=RsV+RtV;} 162## COUNT_HELPER(A2_add); 163## return RdV; 164## } 165## 166def gen_helper_function(f, tag, tagregs, tagimms): 167 regs = tagregs[tag] 168 imms = tagimms[tag] 169 170 numresults = 0 171 numscalarresults = 0 172 numscalarreadwrite = 0 173 for regtype,regid,toss,numregs in regs: 174 if (hex_common.is_written(regid)): 175 numresults += 1 176 if (hex_common.is_scalar_reg(regtype)): 177 numscalarresults += 1 178 if (hex_common.is_readwrite(regid)): 179 if (hex_common.is_scalar_reg(regtype)): 180 numscalarreadwrite += 1 181 182 if (numscalarresults > 1): 183 ## The helper is bogus when there is more than one result 184 f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n" 185 % (tag, tag)) 186 else: 187 ## The return type of the function is the type of the destination 188 ## register (if scalar) 189 i=0 190 for regtype,regid,toss,numregs in regs: 191 if (hex_common.is_written(regid)): 192 if (hex_common.is_pair(regid)): 193 if (hex_common.is_hvx_reg(regtype)): 194 continue 195 else: 196 gen_helper_return_type_pair(f,regtype,regid,i) 197 elif (hex_common.is_single(regid)): 198 if (hex_common.is_hvx_reg(regtype)): 199 continue 200 else: 201 gen_helper_return_type(f,regtype,regid,i) 202 else: 203 print("Bad register parse: ",regtype,regid,toss,numregs) 204 i += 1 205 206 if (numscalarresults == 0): 207 f.write("void") 208 f.write(" HELPER(%s)(CPUHexagonState *env" % tag) 209 210 ## Arguments include the vector destination operands 211 i = 1 212 for regtype,regid,toss,numregs in regs: 213 if (hex_common.is_written(regid)): 214 if (hex_common.is_pair(regid)): 215 if (hex_common.is_hvx_reg(regtype)): 216 gen_helper_arg_ext_pair(f,regtype,regid,i) 217 else: 218 continue 219 elif (hex_common.is_single(regid)): 220 if (hex_common.is_hvx_reg(regtype)): 221 gen_helper_arg_ext(f,regtype,regid,i) 222 else: 223 # This is the return value of the function 224 continue 225 else: 226 print("Bad register parse: ",regtype,regid,toss,numregs) 227 i += 1 228 229 ## For conditional instructions, we pass in the destination register 230 if 'A_CONDEXEC' in hex_common.attribdict[tag]: 231 for regtype, regid, toss, numregs in regs: 232 if (hex_common.is_writeonly(regid) and 233 not hex_common.is_hvx_reg(regtype)): 234 gen_helper_arg_opn(f, regtype, regid, i, tag) 235 i += 1 236 237 ## Arguments to the helper function are the source regs and immediates 238 for regtype,regid,toss,numregs in regs: 239 if (hex_common.is_read(regid)): 240 if (hex_common.is_hvx_reg(regtype) and 241 hex_common.is_readwrite(regid)): 242 continue 243 gen_helper_arg_opn(f,regtype,regid,i,tag) 244 i += 1 245 for immlett,bits,immshift in imms: 246 gen_helper_arg_imm(f,immlett) 247 i += 1 248 249 if (hex_common.need_pkt_has_multi_cof(tag)): 250 f.write(", uint32_t pkt_has_multi_cof") 251 252 if hex_common.need_PC(tag): 253 if i > 0: f.write(", ") 254 f.write("target_ulong PC") 255 i += 1 256 if hex_common.helper_needs_next_PC(tag): 257 if i > 0: f.write(", ") 258 f.write("target_ulong next_PC") 259 i += 1 260 if hex_common.need_slot(tag): 261 if i > 0: f.write(", ") 262 f.write("uint32_t slot") 263 i += 1 264 if hex_common.need_part1(tag): 265 if i > 0: f.write(", ") 266 f.write("uint32_t part1") 267 f.write(")\n{\n") 268 if (not hex_common.need_slot(tag)): 269 f.write(" uint32_t slot __attribute__((unused)) = 4;\n" ) 270 if hex_common.need_ea(tag): gen_decl_ea(f) 271 ## Declare the return variable 272 i=0 273 if 'A_CONDEXEC' not in hex_common.attribdict[tag]: 274 for regtype,regid,toss,numregs in regs: 275 if (hex_common.is_writeonly(regid)): 276 gen_helper_dest_decl_opn(f,regtype,regid,i) 277 i += 1 278 279 for regtype,regid,toss,numregs in regs: 280 if (hex_common.is_read(regid)): 281 if (hex_common.is_pair(regid)): 282 if (hex_common.is_hvx_reg(regtype)): 283 gen_helper_src_var_ext_pair(f,regtype,regid,i) 284 elif (hex_common.is_single(regid)): 285 if (hex_common.is_hvx_reg(regtype)): 286 gen_helper_src_var_ext(f,regtype,regid) 287 else: 288 print("Bad register parse: ",regtype,regid,toss,numregs) 289 290 if 'A_FPOP' in hex_common.attribdict[tag]: 291 f.write(' arch_fpop_start(env);\n'); 292 293 f.write(" %s\n" % hex_common.semdict[tag]) 294 295 if 'A_FPOP' in hex_common.attribdict[tag]: 296 f.write(' arch_fpop_end(env);\n'); 297 298 ## Save/return the return variable 299 for regtype,regid,toss,numregs in regs: 300 if (hex_common.is_written(regid)): 301 gen_helper_return_opn(f, regtype, regid, i) 302 f.write("}\n\n") 303 ## End of the helper definition 304 305def main(): 306 hex_common.read_semantics_file(sys.argv[1]) 307 hex_common.read_attribs_file(sys.argv[2]) 308 hex_common.read_overrides_file(sys.argv[3]) 309 hex_common.read_overrides_file(sys.argv[4]) 310 ## Whether or not idef-parser is enabled is 311 ## determined by the number of arguments to 312 ## this script: 313 ## 314 ## 5 args. -> not enabled, 315 ## 6 args. -> idef-parser enabled. 316 ## 317 ## The 6:th arg. then holds a list of the successfully 318 ## parsed instructions. 319 is_idef_parser_enabled = len(sys.argv) > 6 320 if is_idef_parser_enabled: 321 hex_common.read_idef_parser_enabled_file(sys.argv[5]) 322 hex_common.calculate_attribs() 323 tagregs = hex_common.get_tagregs() 324 tagimms = hex_common.get_tagimms() 325 326 output_file = sys.argv[-1] 327 with open(output_file, 'w') as f: 328 for tag in hex_common.tags: 329 ## Skip the priv instructions 330 if ( "A_PRIV" in hex_common.attribdict[tag] ) : 331 continue 332 ## Skip the guest instructions 333 if ( "A_GUEST" in hex_common.attribdict[tag] ) : 334 continue 335 ## Skip the diag instructions 336 if ( tag == "Y6_diag" ) : 337 continue 338 if ( tag == "Y6_diag0" ) : 339 continue 340 if ( tag == "Y6_diag1" ) : 341 continue 342 if ( hex_common.skip_qemu_helper(tag) ): 343 continue 344 if ( hex_common.is_idef_parser_enabled(tag) ): 345 continue 346 347 gen_helper_function(f, tag, tagregs, tagimms) 348 349if __name__ == "__main__": 350 main() 351