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