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