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 textwrap 24 25behdict = {} # tag ->behavior 26semdict = {} # tag -> semantics 27attribdict = {} # tag -> attributes 28macros = {} # macro -> macro information... 29registers = {} # register -> register functions 30new_registers = {} 31tags = [] # list of all tags 32overrides = {} # tags with helper overrides 33idef_parser_enabled = {} # tags enabled for idef-parser 34 35# We should do this as a hash for performance, 36# but to keep order let's keep it as a list. 37def uniquify(seq): 38 seen = set() 39 seen_add = seen.add 40 return [x for x in seq if x not in seen and not seen_add(x)] 41 42 43regre = re.compile(r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)") 44immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?") 45reg_or_immre = re.compile( 46 r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)" 47 r"([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)" 48) 49relimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?") 50absimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?") 51 52finished_macros = set() 53 54 55def expand_macro_attribs(macro, allmac_re): 56 if macro.key not in finished_macros: 57 # Get a list of all things that might be macros 58 l = allmac_re.findall(macro.beh) 59 for submacro in l: 60 if not submacro: 61 continue 62 if not macros[submacro]: 63 raise Exception(f"Couldn't find macro: <{l}>") 64 macro.attribs |= expand_macro_attribs(macros[submacro], allmac_re) 65 finished_macros.add(macro.key) 66 return macro.attribs 67 68 69# When qemu needs an attribute that isn't in the imported files, 70# we'll add it here. 71def add_qemu_macro_attrib(name, attrib): 72 macros[name].attribs.add(attrib) 73 74 75immextre = re.compile(r"f(MUST_)?IMMEXT[(]([UuSsRr])") 76 77 78def is_cond_jump(tag): 79 if tag == "J2_rte": 80 return False 81 if "A_HWLOOP0_END" in attribdict[tag] or "A_HWLOOP1_END" in attribdict[tag]: 82 return False 83 return re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None 84 85 86def is_cond_call(tag): 87 return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None 88 89 90def calculate_attribs(): 91 add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC") 92 add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC") 93 add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR") 94 add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR") 95 add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD") 96 add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE") 97 add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0') 98 add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0') 99 add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0') 100 add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1') 101 add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1') 102 add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3') 103 add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP') 104 105 # Recurse down macros, find attributes from sub-macros 106 macroValues = list(macros.values()) 107 allmacros_restr = "|".join(set([m.re.pattern for m in macroValues])) 108 allmacros_re = re.compile(allmacros_restr) 109 for macro in macroValues: 110 expand_macro_attribs(macro, allmacros_re) 111 # Append attributes to all instructions 112 for tag in tags: 113 for macname in allmacros_re.findall(semdict[tag]): 114 if not macname: 115 continue 116 macro = macros[macname] 117 attribdict[tag] |= set(macro.attribs) 118 # Mark conditional jumps and calls 119 # Not all instructions are properly marked with A_CONDEXEC 120 for tag in tags: 121 if is_cond_jump(tag) or is_cond_call(tag): 122 attribdict[tag].add("A_CONDEXEC") 123 124 125def SEMANTICS(tag, beh, sem): 126 # print tag,beh,sem 127 behdict[tag] = beh 128 semdict[tag] = sem 129 attribdict[tag] = set() 130 tags.append(tag) # dicts have no order, this is for order 131 132 133def ATTRIBUTES(tag, attribstring): 134 attribstring = attribstring.replace("ATTRIBS", "").replace("(", "").replace(")", "") 135 if not attribstring: 136 return 137 attribs = attribstring.split(",") 138 for attrib in attribs: 139 attribdict[tag].add(attrib.strip()) 140 141 142class Macro(object): 143 __slots__ = ["key", "name", "beh", "attribs", "re"] 144 145 def __init__(self, name, beh, attribs): 146 self.key = name 147 self.name = name 148 self.beh = beh 149 self.attribs = set(attribs) 150 self.re = re.compile("\\b" + name + "\\b") 151 152 153def MACROATTRIB(macname, beh, attribstring): 154 attribstring = attribstring.replace("(", "").replace(")", "") 155 if attribstring: 156 attribs = attribstring.split(",") 157 else: 158 attribs = [] 159 macros[macname] = Macro(macname, beh, attribs) 160 161def compute_tag_regs(tag, full): 162 tagregs = regre.findall(behdict[tag]) 163 if not full: 164 tagregs = map(lambda reg: reg[:2], tagregs) 165 return uniquify(tagregs) 166 167def compute_tag_immediates(tag): 168 return uniquify(immre.findall(behdict[tag])) 169 170 171## 172## tagregs is the main data structure we'll use 173## tagregs[tag] will contain the registers used by an instruction 174## Within each entry, we'll use the regtype and regid fields 175## regtype can be one of the following 176## C control register 177## N new register value 178## P predicate register 179## R GPR register 180## M modifier register 181## Q HVX predicate vector 182## V HVX vector register 183## O HVX new vector register 184## regid can be one of the following 185## d, e destination register 186## dd destination register pair 187## s, t, u, v, w source register 188## ss, tt, uu, vv source register pair 189## x, y read-write register 190## xx, yy read-write register pair 191## 192def get_tagregs(full=False): 193 compute_func = lambda tag: compute_tag_regs(tag, full) 194 return dict(zip(tags, list(map(compute_func, tags)))) 195 196def get_tagimms(): 197 return dict(zip(tags, list(map(compute_tag_immediates, tags)))) 198 199 200def need_p0(tag): 201 return "A_IMPLICIT_READS_P0" in attribdict[tag] 202 203 204def need_sp(tag): 205 return "A_IMPLICIT_READS_SP" in attribdict[tag] 206 207 208def is_hvx_insn(tag): 209 return "A_CVI" in attribdict[tag] 210 211 212def need_env(tag): 213 return ("A_STORE" in attribdict[tag] or 214 "A_LOAD" in attribdict[tag] or 215 "A_CVI_GATHER" in attribdict[tag] or 216 "A_CVI_SCATTER" in attribdict[tag] or 217 "A_IMPLICIT_WRITES_USR" in attribdict[tag]) 218 219 220def need_slot(tag): 221 if ( 222 "A_CVI_SCATTER" not in attribdict[tag] 223 and "A_CVI_GATHER" not in attribdict[tag] 224 and ("A_STORE" in attribdict[tag] 225 or "A_LOAD" in attribdict[tag]) 226 ): 227 return 1 228 else: 229 return 0 230 231 232def need_part1(tag): 233 return re.compile(r"fPART1").search(semdict[tag]) 234 235 236def need_ea(tag): 237 return re.compile(r"\bEA\b").search(semdict[tag]) 238 239 240def need_PC(tag): 241 return "A_IMPLICIT_READS_PC" in attribdict[tag] 242 243 244def need_next_PC(tag): 245 return "A_CALL" in attribdict[tag] 246 247 248def need_pkt_has_multi_cof(tag): 249 return "A_COF" in attribdict[tag] 250 251 252def need_pkt_need_commit(tag): 253 return 'A_IMPLICIT_WRITES_USR' in attribdict[tag] 254 255 256def skip_qemu_helper(tag): 257 return tag in overrides.keys() 258 259 260def is_idef_parser_enabled(tag): 261 return tag in idef_parser_enabled 262 263 264def is_hvx_insn(tag): 265 return "A_CVI" in attribdict[tag] 266 267 268def has_hvx_helper(tag): 269 return (is_hvx_insn(tag) and 270 not skip_qemu_helper(tag) and 271 not is_idef_parser_enabled(tag)) 272 273 274def imm_name(immlett): 275 return f"{immlett}iV" 276 277 278def read_semantics_file(name): 279 eval_line = "" 280 for line in open(name, "rt").readlines(): 281 if not line.startswith("#"): 282 eval_line += line 283 if line.endswith("\\\n"): 284 eval_line.rstrip("\\\n") 285 else: 286 eval(eval_line.strip()) 287 eval_line = "" 288 289 290def read_overrides_file(name): 291 overridere = re.compile(r"#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") 292 for line in open(name, "rt").readlines(): 293 if not overridere.match(line): 294 continue 295 tag = overridere.findall(line)[0] 296 overrides[tag] = True 297 298 299def read_idef_parser_enabled_file(name): 300 global idef_parser_enabled 301 with open(name, "r") as idef_parser_enabled_file: 302 lines = idef_parser_enabled_file.read().strip().split("\n") 303 idef_parser_enabled = set(lines) 304 305 306def is_predicated(tag): 307 return "A_CONDEXEC" in attribdict[tag] 308 309 310def code_fmt(txt): 311 return textwrap.indent(textwrap.dedent(txt), " ") 312 313 314def hvx_newv(tag): 315 if "A_CVI_NEW" in attribdict[tag]: 316 return "EXT_NEW" 317 elif "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]: 318 return "EXT_TMP" 319 else: 320 return "EXT_DFL" 321 322def vreg_offset_func(tag): 323 if "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]: 324 return "ctx_tmp_vreg_off" 325 else: 326 return "ctx_future_vreg_off" 327 328class HelperArg: 329 def __init__(self, proto_arg, call_arg, func_arg): 330 self.proto_arg = proto_arg 331 self.call_arg = call_arg 332 self.func_arg = func_arg 333 334class Register: 335 def __init__(self, regtype, regid): 336 self.regtype = regtype 337 self.regid = regid 338 self.reg_num = f"{regtype}{regid}N" 339 def decl_reg_num(self, f, regno): 340 f.write(code_fmt(f"""\ 341 const int {self.reg_num} = insn->regno[{regno}]; 342 """)) 343 def idef_arg(self, declared): 344 declared.append(self.reg_tcg()) 345 def helper_arg(self): 346 return HelperArg( 347 self.helper_proto_type(), 348 self.reg_tcg(), 349 f"{self.helper_arg_type()} {self.helper_arg_name()}" 350 ) 351 352# 353# Every register is either Single or Pair or Hvx 354# 355class Scalar: 356 def is_scalar_reg(self): 357 return True 358 def is_hvx_reg(self): 359 return False 360 def helper_arg_name(self): 361 return self.reg_tcg() 362 363class Single(Scalar): 364 def helper_proto_type(self): 365 return "s32" 366 def helper_arg_type(self): 367 return "int32_t" 368 369class Pair(Scalar): 370 def helper_proto_type(self): 371 return "s64" 372 def helper_arg_type(self): 373 return "int64_t" 374 375class Hvx: 376 def is_scalar_reg(self): 377 return False 378 def is_hvx_reg(self): 379 return True 380 def hvx_off(self): 381 return f"{self.reg_tcg()}_off" 382 def helper_proto_type(self): 383 return "ptr" 384 def helper_arg_type(self): 385 return "void *" 386 def helper_arg_name(self): 387 return f"{self.reg_tcg()}_void" 388 389# 390# Every register is either Dest or OldSource or NewSource or ReadWrite 391# 392class Dest: 393 def reg_tcg(self): 394 return f"{self.regtype}{self.regid}V" 395 def is_written(self): 396 return True 397 def is_writeonly(self): 398 return True 399 def is_read(self): 400 return False 401 def is_readwrite(self): 402 return False 403 404class Source: 405 def is_written(self): 406 return False 407 def is_writeonly(self): 408 return False 409 def is_read(self): 410 return True 411 def is_readwrite(self): 412 return False 413 414class OldSource(Source): 415 def reg_tcg(self): 416 return f"{self.regtype}{self.regid}V" 417 def is_old(self): 418 return True 419 def is_new(self): 420 return False 421 422class NewSource(Source): 423 def reg_tcg(self): 424 return f"{self.regtype}{self.regid}N" 425 def is_old(self): 426 return False 427 def is_new(self): 428 return True 429 430class ReadWrite: 431 def reg_tcg(self): 432 return f"{self.regtype}{self.regid}V" 433 def is_written(self): 434 return True 435 def is_writeonly(self): 436 return False 437 def is_read(self): 438 return True 439 def is_readwrite(self): 440 return True 441 def is_old(self): 442 return True 443 def is_new(self): 444 return False 445 446class GprDest(Register, Single, Dest): 447 def decl_tcg(self, f, tag, regno): 448 self.decl_reg_num(f, regno) 449 f.write(code_fmt(f"""\ 450 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 451 """)) 452 def log_write(self, f, tag): 453 f.write(code_fmt(f"""\ 454 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 455 """)) 456 def analyze_write(self, f, tag, regno): 457 predicated = "true" if is_predicated(tag) else "false" 458 f.write(code_fmt(f"""\ 459 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 460 """)) 461 462class GprSource(Register, Single, OldSource): 463 def decl_tcg(self, f, tag, regno): 464 self.decl_reg_num(f, regno) 465 f.write(code_fmt(f"""\ 466 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 467 """)) 468 def analyze_read(self, f, regno): 469 f.write(code_fmt(f"""\ 470 ctx_log_reg_read(ctx, {self.reg_num}); 471 """)) 472 473class GprNewSource(Register, Single, NewSource): 474 def decl_tcg(self, f, tag, regno): 475 f.write(code_fmt(f"""\ 476 TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]); 477 """)) 478 def analyze_read(self, f, regno): 479 f.write(code_fmt(f"""\ 480 ctx_log_reg_read_new(ctx, {self.reg_num}); 481 """)) 482 483class GprReadWrite(Register, Single, ReadWrite): 484 def decl_tcg(self, f, tag, regno): 485 self.decl_reg_num(f, regno) 486 f.write(code_fmt(f"""\ 487 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 488 """)) 489 ## For read/write registers, we need to get the original value into 490 ## the result TCGv. For predicated instructions, this is done in 491 ## gen_start_packet. For un-predicated instructions, we do it here. 492 if not is_predicated(tag): 493 f.write(code_fmt(f"""\ 494 tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]); 495 """)) 496 def log_write(self, f, tag): 497 f.write(code_fmt(f"""\ 498 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 499 """)) 500 def analyze_read(self, f, regno): 501 f.write(code_fmt(f"""\ 502 ctx_log_reg_read(ctx, {self.reg_num}); 503 """)) 504 def analyze_write(self, f, tag, regno): 505 predicated = "true" if is_predicated(tag) else "false" 506 f.write(code_fmt(f"""\ 507 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 508 """)) 509 510class ControlDest(Register, Single, Dest): 511 def decl_reg_num(self, f, regno): 512 f.write(code_fmt(f"""\ 513 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 514 """)) 515 def decl_tcg(self, f, tag, regno): 516 self.decl_reg_num(f, regno) 517 f.write(code_fmt(f"""\ 518 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 519 """)) 520 def log_write(self, f, tag): 521 f.write(code_fmt(f"""\ 522 gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 523 """)) 524 def analyze_write(self, f, tag, regno): 525 predicated = "true" if is_predicated(tag) else "false" 526 f.write(code_fmt(f"""\ 527 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 528 """)) 529 530class ControlSource(Register, Single, OldSource): 531 def decl_reg_num(self, f, regno): 532 f.write(code_fmt(f"""\ 533 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 534 """)) 535 def decl_tcg(self, f, tag, regno): 536 self.decl_reg_num(f, regno); 537 f.write(code_fmt(f"""\ 538 TCGv {self.reg_tcg()} = tcg_temp_new(); 539 gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 540 """)) 541 def analyze_read(self, f, regno): 542 f.write(code_fmt(f"""\ 543 ctx_log_reg_read(ctx, {self.reg_num}); 544 """)) 545 546class ModifierSource(Register, Single, OldSource): 547 def decl_reg_num(self, f, regno): 548 f.write(code_fmt(f"""\ 549 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0; 550 """)) 551 def decl_tcg(self, f, tag, regno): 552 self.decl_reg_num(f, regno) 553 f.write(code_fmt(f"""\ 554 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 555 TCGv CS G_GNUC_UNUSED = 556 hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0]; 557 """)) 558 def idef_arg(self, declared): 559 declared.append(self.reg_tcg()) 560 declared.append("CS") 561 def analyze_read(self, f, regno): 562 f.write(code_fmt(f"""\ 563 ctx_log_reg_read(ctx, {self.reg_num}); 564 """)) 565 566class PredDest(Register, Single, Dest): 567 def decl_tcg(self, f, tag, regno): 568 self.decl_reg_num(f, regno) 569 f.write(code_fmt(f"""\ 570 TCGv {self.reg_tcg()} = tcg_temp_new(); 571 """)) 572 def log_write(self, f, tag): 573 f.write(code_fmt(f"""\ 574 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 575 """)) 576 def analyze_write(self, f, tag, regno): 577 f.write(code_fmt(f"""\ 578 ctx_log_pred_write(ctx, {self.reg_num}); 579 """)) 580 581class PredSource(Register, Single, OldSource): 582 def decl_tcg(self, f, tag, regno): 583 self.decl_reg_num(f, regno) 584 f.write(code_fmt(f"""\ 585 TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}]; 586 """)) 587 def analyze_read(self, f, regno): 588 f.write(code_fmt(f"""\ 589 ctx_log_pred_read(ctx, {self.reg_num}); 590 """)) 591 592class PredNewSource(Register, Single, NewSource): 593 def decl_tcg(self, f, tag, regno): 594 f.write(code_fmt(f"""\ 595 TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]); 596 """)) 597 def analyze_read(self, f, regno): 598 f.write(code_fmt(f"""\ 599 ctx_log_pred_read_new(ctx, {self.reg_num}); 600 """)) 601 602class PredReadWrite(Register, Single, ReadWrite): 603 def decl_tcg(self, f, tag, regno): 604 self.decl_reg_num(f, regno) 605 f.write(code_fmt(f"""\ 606 TCGv {self.reg_tcg()} = tcg_temp_new(); 607 tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]); 608 """)) 609 def log_write(self, f, tag): 610 f.write(code_fmt(f"""\ 611 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 612 """)) 613 def analyze_read(self, f, regno): 614 f.write(code_fmt(f"""\ 615 ctx_log_pred_read(ctx, {self.reg_num}); 616 """)) 617 def analyze_write(self, f, tag, regno): 618 f.write(code_fmt(f"""\ 619 ctx_log_pred_write(ctx, {self.reg_num}); 620 """)) 621 622class PairDest(Register, Pair, Dest): 623 def decl_tcg(self, f, tag, regno): 624 self.decl_reg_num(f, regno) 625 f.write(code_fmt(f"""\ 626 TCGv_i64 {self.reg_tcg()} = 627 get_result_gpr_pair(ctx, {self.reg_num}); 628 """)) 629 def log_write(self, f, tag): 630 f.write(code_fmt(f"""\ 631 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 632 """)) 633 def analyze_write(self, f, tag, regno): 634 predicated = "true" if is_predicated(tag) else "false" 635 f.write(code_fmt(f"""\ 636 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 637 """)) 638 639class PairSource(Register, Pair, OldSource): 640 def decl_tcg(self, f, tag, regno): 641 self.decl_reg_num(f, regno) 642 f.write(code_fmt(f"""\ 643 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 644 tcg_gen_concat_i32_i64({self.reg_tcg()}, 645 hex_gpr[{self.reg_num}], 646 hex_gpr[{self.reg_num} + 1]); 647 """)) 648 def analyze_read(self, f, regno): 649 f.write(code_fmt(f"""\ 650 ctx_log_reg_read_pair(ctx, {self.reg_num}); 651 """)) 652 653class PairReadWrite(Register, Pair, ReadWrite): 654 def decl_tcg(self, f, tag, regno): 655 self.decl_reg_num(f, regno) 656 f.write(code_fmt(f"""\ 657 TCGv_i64 {self.reg_tcg()} = 658 get_result_gpr_pair(ctx, {self.reg_num}); 659 tcg_gen_concat_i32_i64({self.reg_tcg()}, 660 hex_gpr[{self.reg_num}], 661 hex_gpr[{self.reg_num} + 1]); 662 """)) 663 def log_write(self, f, tag): 664 f.write(code_fmt(f"""\ 665 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 666 """)) 667 def analyze_read(self, f, regno): 668 f.write(code_fmt(f"""\ 669 ctx_log_reg_read_pair(ctx, {self.reg_num}); 670 """)) 671 def analyze_write(self, f, tag, regno): 672 predicated = "true" if is_predicated(tag) else "false" 673 f.write(code_fmt(f"""\ 674 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 675 """)) 676 677class ControlPairDest(Register, Pair, Dest): 678 def decl_reg_num(self, f, regno): 679 f.write(code_fmt(f"""\ 680 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 681 """)) 682 def decl_tcg(self, f, tag, regno): 683 self.decl_reg_num(f, regno) 684 f.write(code_fmt(f"""\ 685 TCGv_i64 {self.reg_tcg()} = 686 get_result_gpr_pair(ctx, {self.reg_num}); 687 """)) 688 def log_write(self, f, tag): 689 f.write(code_fmt(f"""\ 690 gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 691 """)) 692 def analyze_write(self, f, tag, regno): 693 predicated = "true" if is_predicated(tag) else "false" 694 f.write(code_fmt(f"""\ 695 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 696 """)) 697 698class ControlPairSource(Register, Pair, OldSource): 699 def decl_reg_num(self, f, regno): 700 f.write(code_fmt(f"""\ 701 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 702 """)) 703 def decl_tcg(self, f, tag, regno): 704 self.decl_reg_num(f, regno) 705 f.write(code_fmt(f"""\ 706 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 707 gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 708 """)) 709 def analyze_read(self, f, regno): 710 f.write(code_fmt(f"""\ 711 ctx_log_reg_read_pair(ctx, {self.reg_num}); 712 """)) 713 714class VRegDest(Register, Hvx, Dest): 715 def decl_tcg(self, f, tag, regno): 716 self.decl_reg_num(f, regno) 717 f.write(code_fmt(f"""\ 718 const intptr_t {self.hvx_off()} = 719 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 720 """)) 721 if not skip_qemu_helper(tag): 722 f.write(code_fmt(f"""\ 723 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 724 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 725 """)) 726 def log_write(self, f, tag): 727 pass 728 def helper_hvx_desc(self, f): 729 f.write(code_fmt(f"""\ 730 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 731 """)) 732 def analyze_write(self, f, tag, regno): 733 newv = hvx_newv(tag) 734 predicated = "true" if is_predicated(tag) else "false" 735 f.write(code_fmt(f"""\ 736 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 737 insn_has_hvx_helper); 738 """)) 739 740class VRegSource(Register, Hvx, OldSource): 741 def decl_tcg(self, f, tag, regno): 742 self.decl_reg_num(f, regno) 743 f.write(code_fmt(f"""\ 744 const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num}); 745 """)) 746 if not skip_qemu_helper(tag): 747 f.write(code_fmt(f"""\ 748 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 749 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 750 """)) 751 def helper_hvx_desc(self, f): 752 f.write(code_fmt(f"""\ 753 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 754 """)) 755 def analyze_read(self, f, regno): 756 f.write(code_fmt(f"""\ 757 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 758 """)) 759 760class VRegNewSource(Register, Hvx, NewSource): 761 def decl_tcg(self, f, tag, regno): 762 self.decl_reg_num(f, regno) 763 if skip_qemu_helper(tag): 764 f.write(code_fmt(f"""\ 765 const intptr_t {self.hvx_off()} = 766 ctx_future_vreg_off(ctx, {self.reg_num}, 1, true); 767 """)) 768 def helper_hvx_desc(self, f): 769 f.write(code_fmt(f"""\ 770 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 771 """)) 772 def analyze_read(self, f, regno): 773 f.write(code_fmt(f"""\ 774 ctx_log_vreg_read_new(ctx, {self.reg_num}, insn_has_hvx_helper); 775 """)) 776 777class VRegReadWrite(Register, Hvx, ReadWrite): 778 def decl_tcg(self, f, tag, regno): 779 self.decl_reg_num(f, regno) 780 f.write(code_fmt(f"""\ 781 const intptr_t {self.hvx_off()} = 782 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 783 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 784 vreg_src_off(ctx, {self.reg_num}), 785 sizeof(MMVector), sizeof(MMVector)); 786 """)) 787 if not skip_qemu_helper(tag): 788 f.write(code_fmt(f"""\ 789 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 790 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 791 """)) 792 def log_write(self, f, tag): 793 pass 794 def helper_hvx_desc(self, f): 795 f.write(code_fmt(f"""\ 796 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 797 """)) 798 def analyze_read(self, f, regno): 799 f.write(code_fmt(f"""\ 800 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 801 """)) 802 def analyze_write(self, f, tag, regno): 803 newv = hvx_newv(tag) 804 predicated = "true" if is_predicated(tag) else "false" 805 f.write(code_fmt(f"""\ 806 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 807 insn_has_hvx_helper); 808 """)) 809 810class VRegTmp(Register, Hvx, ReadWrite): 811 def decl_tcg(self, f, tag, regno): 812 self.decl_reg_num(f, regno) 813 f.write(code_fmt(f"""\ 814 const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp); 815 """)) 816 if not skip_qemu_helper(tag): 817 f.write(code_fmt(f"""\ 818 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 819 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 820 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 821 vreg_src_off(ctx, {self.reg_num}), 822 sizeof(MMVector), sizeof(MMVector)); 823 """)) 824 def log_write(self, f, tag): 825 f.write(code_fmt(f"""\ 826 gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num}, 827 {hvx_newv(tag)}); 828 """)) 829 def helper_hvx_desc(self, f): 830 f.write(code_fmt(f"""\ 831 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 832 """)) 833 def analyze_read(self, f, regno): 834 f.write(code_fmt(f"""\ 835 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 836 """)) 837 def analyze_write(self, f, tag, regno): 838 newv = hvx_newv(tag) 839 predicated = "true" if is_predicated(tag) else "false" 840 f.write(code_fmt(f"""\ 841 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 842 insn_has_hvx_helper); 843 """)) 844 845class VRegPairDest(Register, Hvx, Dest): 846 def decl_tcg(self, f, tag, regno): 847 self.decl_reg_num(f, regno) 848 f.write(code_fmt(f"""\ 849 const intptr_t {self.hvx_off()} = 850 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true); 851 """)) 852 if not skip_qemu_helper(tag): 853 f.write(code_fmt(f"""\ 854 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 855 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 856 """)) 857 def log_write(self, f, tag): 858 pass 859 def helper_hvx_desc(self, f): 860 f.write(code_fmt(f"""\ 861 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 862 """)) 863 def analyze_write(self, f, tag, regno): 864 newv = hvx_newv(tag) 865 predicated = "true" if is_predicated(tag) else "false" 866 f.write(code_fmt(f"""\ 867 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, 868 insn_has_hvx_helper); 869 """)) 870 871class VRegPairSource(Register, Hvx, OldSource): 872 def decl_tcg(self, f, tag, regno): 873 self.decl_reg_num(f, regno) 874 f.write(code_fmt(f"""\ 875 const intptr_t {self.hvx_off()} = 876 offsetof(CPUHexagonState, {self.reg_tcg()}); 877 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 878 vreg_src_off(ctx, {self.reg_num}), 879 sizeof(MMVector), sizeof(MMVector)); 880 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 881 vreg_src_off(ctx, {self.reg_num} ^ 1), 882 sizeof(MMVector), sizeof(MMVector)); 883 """)) 884 if not skip_qemu_helper(tag): 885 f.write(code_fmt(f"""\ 886 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 887 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 888 """)) 889 def helper_hvx_desc(self, f): 890 f.write(code_fmt(f"""\ 891 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 892 """)) 893 def analyze_read(self, f, regno): 894 f.write(code_fmt(f"""\ 895 ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); 896 """)) 897 898class VRegPairReadWrite(Register, Hvx, ReadWrite): 899 def decl_tcg(self, f, tag, regno): 900 self.decl_reg_num(f, regno) 901 f.write(code_fmt(f"""\ 902 const intptr_t {self.hvx_off()} = 903 offsetof(CPUHexagonState, {self.reg_tcg()}); 904 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 905 vreg_src_off(ctx, {self.reg_num}), 906 sizeof(MMVector), sizeof(MMVector)); 907 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 908 vreg_src_off(ctx, {self.reg_num} ^ 1), 909 sizeof(MMVector), sizeof(MMVector)); 910 """)) 911 if not skip_qemu_helper(tag): 912 f.write(code_fmt(f"""\ 913 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 914 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 915 """)) 916 def log_write(self, f, tag): 917 f.write(code_fmt(f"""\ 918 gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num}, 919 {hvx_newv(tag)}); 920 """)) 921 def helper_hvx_desc(self, f): 922 f.write(code_fmt(f"""\ 923 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 924 """)) 925 def analyze_read(self, f, regno): 926 f.write(code_fmt(f"""\ 927 ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); 928 """)) 929 def analyze_write(self, f, tag, regno): 930 newv = hvx_newv(tag) 931 predicated = "true" if is_predicated(tag) else "false" 932 f.write(code_fmt(f"""\ 933 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, 934 insn_has_hvx_helper); 935 """)) 936 937class QRegDest(Register, Hvx, Dest): 938 def decl_tcg(self, f, tag, regno): 939 self.decl_reg_num(f, regno) 940 f.write(code_fmt(f"""\ 941 const intptr_t {self.hvx_off()} = 942 get_result_qreg(ctx, {self.reg_num}); 943 """)) 944 if not skip_qemu_helper(tag): 945 f.write(code_fmt(f"""\ 946 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 947 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 948 """)) 949 def log_write(self, f, tag): 950 pass 951 def helper_hvx_desc(self, f): 952 f.write(code_fmt(f"""\ 953 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 954 """)) 955 def analyze_write(self, f, tag, regno): 956 f.write(code_fmt(f"""\ 957 ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); 958 """)) 959 960class QRegSource(Register, Hvx, OldSource): 961 def decl_tcg(self, f, tag, regno): 962 self.decl_reg_num(f, regno) 963 f.write(code_fmt(f"""\ 964 const intptr_t {self.hvx_off()} = 965 offsetof(CPUHexagonState, QRegs[{self.reg_num}]); 966 """)) 967 if not skip_qemu_helper(tag): 968 f.write(code_fmt(f"""\ 969 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 970 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 971 """)) 972 def helper_hvx_desc(self, f): 973 f.write(code_fmt(f"""\ 974 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 975 """)) 976 def analyze_read(self, f, regno): 977 f.write(code_fmt(f"""\ 978 ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 979 """)) 980 981class QRegReadWrite(Register, Hvx, ReadWrite): 982 def decl_tcg(self, f, tag, regno): 983 self.decl_reg_num(f, regno) 984 f.write(code_fmt(f"""\ 985 const intptr_t {self.hvx_off()} = 986 get_result_qreg(ctx, {self.reg_num}); 987 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 988 offsetof(CPUHexagonState, QRegs[{self.reg_num}]), 989 sizeof(MMQReg), sizeof(MMQReg)); 990 """)) 991 if not skip_qemu_helper(tag): 992 f.write(code_fmt(f"""\ 993 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 994 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 995 """)) 996 def log_write(self, f, tag): 997 pass 998 def helper_hvx_desc(self, f): 999 f.write(code_fmt(f"""\ 1000 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 1001 """)) 1002 def analyze_read(self, f, regno): 1003 f.write(code_fmt(f"""\ 1004 ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 1005 """)) 1006 def analyze_write(self, f, tag, regno): 1007 f.write(code_fmt(f"""\ 1008 ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); 1009 """)) 1010 1011def init_registers(): 1012 regs = { 1013 GprDest("R", "d"), 1014 GprDest("R", "e"), 1015 GprSource("R", "s"), 1016 GprSource("R", "t"), 1017 GprSource("R", "u"), 1018 GprSource("R", "v"), 1019 GprReadWrite("R", "x"), 1020 GprReadWrite("R", "y"), 1021 ControlDest("C", "d"), 1022 ControlSource("C", "s"), 1023 ModifierSource("M", "u"), 1024 PredDest("P", "d"), 1025 PredDest("P", "e"), 1026 PredSource("P", "s"), 1027 PredSource("P", "t"), 1028 PredSource("P", "u"), 1029 PredSource("P", "v"), 1030 PredReadWrite("P", "x"), 1031 PairDest("R", "dd"), 1032 PairDest("R", "ee"), 1033 PairSource("R", "ss"), 1034 PairSource("R", "tt"), 1035 PairReadWrite("R", "xx"), 1036 PairReadWrite("R", "yy"), 1037 ControlPairDest("C", "dd"), 1038 ControlPairSource("C", "ss"), 1039 VRegDest("V", "d"), 1040 VRegSource("V", "s"), 1041 VRegSource("V", "u"), 1042 VRegSource("V", "v"), 1043 VRegSource("V", "w"), 1044 VRegReadWrite("V", "x"), 1045 VRegTmp("V", "y"), 1046 VRegPairDest("V", "dd"), 1047 VRegPairSource("V", "uu"), 1048 VRegPairSource("V", "vv"), 1049 VRegPairReadWrite("V", "xx"), 1050 QRegDest("Q", "d"), 1051 QRegDest("Q", "e"), 1052 QRegSource("Q", "s"), 1053 QRegSource("Q", "t"), 1054 QRegSource("Q", "u"), 1055 QRegSource("Q", "v"), 1056 QRegReadWrite("Q", "x"), 1057 } 1058 for reg in regs: 1059 registers[f"{reg.regtype}{reg.regid}"] = reg 1060 1061 new_regs = { 1062 GprNewSource("N", "s"), 1063 GprNewSource("N", "t"), 1064 PredNewSource("P", "t"), 1065 PredNewSource("P", "u"), 1066 PredNewSource("P", "v"), 1067 VRegNewSource("O", "s"), 1068 } 1069 for reg in new_regs: 1070 new_registers[f"{reg.regtype}{reg.regid}"] = reg 1071 1072def get_register(tag, regtype, regid): 1073 if f"{regtype}{regid}V" in semdict[tag]: 1074 return registers[f"{regtype}{regid}"] 1075 else: 1076 return new_registers[f"{regtype}{regid}"] 1077 1078def helper_ret_type(tag, regs): 1079 ## If there is a scalar result, it is the return type 1080 return_type = HelperArg( "void", "void", "void") 1081 numscalarresults = 0 1082 for regtype, regid in regs: 1083 reg = get_register(tag, regtype, regid) 1084 if reg.is_written() and reg.is_scalar_reg(): 1085 return_type = HelperArg( 1086 reg.helper_proto_type(), 1087 reg.reg_tcg(), 1088 reg.helper_arg_type() 1089 ) 1090 if numscalarresults > 1: 1091 raise Exception("numscalarresults > 1") 1092 return return_type 1093 1094def helper_args(tag, regs, imms): 1095 args = [] 1096 1097 ## First argument is the CPU state 1098 if need_env(tag): 1099 args.append(HelperArg( 1100 "env", 1101 "tcg_env", 1102 "CPUHexagonState *env" 1103 )) 1104 1105 ## For predicated instructions, we pass in the destination register 1106 if is_predicated(tag): 1107 for regtype, regid in regs: 1108 reg = get_register(tag, regtype, regid) 1109 if reg.is_writeonly() and not reg.is_hvx_reg(): 1110 args.append(reg.helper_arg()) 1111 1112 ## Pass the HVX destination registers 1113 for regtype, regid in regs: 1114 reg = get_register(tag, regtype, regid) 1115 if reg.is_written() and reg.is_hvx_reg(): 1116 args.append(reg.helper_arg()) 1117 1118 ## Pass the source registers 1119 for regtype, regid in regs: 1120 reg = get_register(tag, regtype, regid) 1121 if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()): 1122 args.append(reg.helper_arg()) 1123 1124 ## Pass the immediates 1125 for immlett, bits, immshift in imms: 1126 args.append(HelperArg( 1127 "s32", 1128 f"tcg_constant_tl({imm_name(immlett)})", 1129 f"int32_t {imm_name(immlett)}" 1130 )) 1131 1132 ## Other stuff the helper might need 1133 if need_pkt_has_multi_cof(tag): 1134 args.append(HelperArg( 1135 "i32", 1136 "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)", 1137 "uint32_t pkt_has_multi_cof" 1138 )) 1139 if need_pkt_need_commit(tag): 1140 args.append(HelperArg( 1141 "i32", 1142 "tcg_constant_tl(ctx->need_commit)", 1143 "uint32_t pkt_need_commit" 1144 )) 1145 if need_PC(tag): 1146 args.append(HelperArg( 1147 "i32", 1148 "tcg_constant_tl(ctx->pkt->pc)", 1149 "target_ulong PC" 1150 )) 1151 if need_next_PC(tag): 1152 args.append(HelperArg( 1153 "i32", 1154 "tcg_constant_tl(ctx->next_PC)", 1155 "target_ulong next_PC" 1156 )) 1157 if need_p0(tag): 1158 args.append(HelperArg( 1159 "i32", 1160 "hex_pred[0]", 1161 "uint32_t P0" 1162 )) 1163 if need_sp(tag): 1164 args.append(HelperArg( 1165 "i32", 1166 "hex_gpr[HEX_REG_SP]", 1167 "uint32_t SP" 1168 )) 1169 if need_slot(tag): 1170 args.append(HelperArg( 1171 "i32", 1172 "gen_slotval(ctx)", 1173 "uint32_t slotval" 1174 )) 1175 if need_part1(tag): 1176 args.append(HelperArg( 1177 "i32", 1178 "tcg_constant_tl(insn->part1)" 1179 "uint32_t part1" 1180 )) 1181 return args 1182 1183 1184def read_common_files(): 1185 read_semantics_file(sys.argv[1]) 1186 read_overrides_file(sys.argv[2]) 1187 read_overrides_file(sys.argv[3]) 1188 ## Whether or not idef-parser is enabled is 1189 ## determined by the number of arguments to 1190 ## this script: 1191 ## 1192 ## 4 args. -> not enabled, 1193 ## 5 args. -> idef-parser enabled. 1194 ## 1195 ## The 5:th arg. then holds a list of the successfully 1196 ## parsed instructions. 1197 is_idef_parser_enabled = len(sys.argv) > 5 1198 if is_idef_parser_enabled: 1199 read_idef_parser_enabled_file(sys.argv[4]) 1200 calculate_attribs() 1201 init_registers() 1202 return is_idef_parser_enabled 1203