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 hex_common.bad_register(regtype, regid) 91 else: 92 hex_common.bad_register(regtype, regid) 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 hex_common.bad_register(regtype, regid) 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 hex_common.bad_register(regtype, regid) 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 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 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 hex_common.bad_register(regtype, regid) 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 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 hex_common.bad_register(regtype, regid) 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 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 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 if (hex_common.need_pkt_need_commit(tag)): 291 f.write(", uint32_t pkt_need_commit") 292 293 if hex_common.need_PC(tag): 294 if i > 0: 295 f.write(", ") 296 f.write("target_ulong PC") 297 i += 1 298 if hex_common.helper_needs_next_PC(tag): 299 if i > 0: 300 f.write(", ") 301 f.write("target_ulong next_PC") 302 i += 1 303 if hex_common.need_slot(tag): 304 if i > 0: 305 f.write(", ") 306 f.write("uint32_t slotval") 307 i += 1 308 if hex_common.need_part1(tag): 309 if i > 0: 310 f.write(", ") 311 f.write("uint32_t part1") 312 f.write(")\n{\n") 313 if hex_common.need_ea(tag): 314 gen_decl_ea(f) 315 ## Declare the return variable 316 i = 0 317 if "A_CONDEXEC" not in hex_common.attribdict[tag]: 318 for regtype, regid in regs: 319 if hex_common.is_writeonly(regid): 320 gen_helper_dest_decl_opn(f, regtype, regid, i) 321 i += 1 322 323 for regtype, regid in regs: 324 if hex_common.is_read(regid): 325 if hex_common.is_pair(regid): 326 if hex_common.is_hvx_reg(regtype): 327 gen_helper_src_var_ext_pair(f, regtype, regid, i) 328 elif hex_common.is_single(regid): 329 if hex_common.is_hvx_reg(regtype): 330 gen_helper_src_var_ext(f, regtype, regid) 331 else: 332 hex_common.bad_register(regtype, regid) 333 334 if hex_common.need_slot(tag): 335 if "A_LOAD" in hex_common.attribdict[tag]: 336 f.write(" bool pkt_has_store_s1 = slotval & 0x1;\n") 337 f.write(" uint32_t slot = slotval >> 1;\n") 338 339 if "A_FPOP" in hex_common.attribdict[tag]: 340 f.write(" arch_fpop_start(env);\n") 341 342 f.write(f" {hex_common.semdict[tag]}\n") 343 344 if "A_FPOP" in hex_common.attribdict[tag]: 345 f.write(" arch_fpop_end(env);\n") 346 347 ## Save/return the return variable 348 for regtype, regid in regs: 349 if hex_common.is_written(regid): 350 gen_helper_return_opn(f, regtype, regid, i) 351 f.write("}\n\n") 352 ## End of the helper definition 353 354 355def main(): 356 hex_common.read_semantics_file(sys.argv[1]) 357 hex_common.read_attribs_file(sys.argv[2]) 358 hex_common.read_overrides_file(sys.argv[3]) 359 hex_common.read_overrides_file(sys.argv[4]) 360 ## Whether or not idef-parser is enabled is 361 ## determined by the number of arguments to 362 ## this script: 363 ## 364 ## 5 args. -> not enabled, 365 ## 6 args. -> idef-parser enabled. 366 ## 367 ## The 6:th arg. then holds a list of the successfully 368 ## parsed instructions. 369 is_idef_parser_enabled = len(sys.argv) > 6 370 if is_idef_parser_enabled: 371 hex_common.read_idef_parser_enabled_file(sys.argv[5]) 372 hex_common.calculate_attribs() 373 tagregs = hex_common.get_tagregs() 374 tagimms = hex_common.get_tagimms() 375 376 output_file = sys.argv[-1] 377 with open(output_file, "w") as f: 378 for tag in hex_common.tags: 379 ## Skip the priv instructions 380 if "A_PRIV" in hex_common.attribdict[tag]: 381 continue 382 ## Skip the guest instructions 383 if "A_GUEST" in hex_common.attribdict[tag]: 384 continue 385 ## Skip the diag instructions 386 if tag == "Y6_diag": 387 continue 388 if tag == "Y6_diag0": 389 continue 390 if tag == "Y6_diag1": 391 continue 392 if hex_common.skip_qemu_helper(tag): 393 continue 394 if hex_common.is_idef_parser_enabled(tag): 395 continue 396 397 gen_helper_function(f, tag, tagregs, tagimms) 398 399 400if __name__ == "__main__": 401 main() 402