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# Every register is either Single or Pair or Hvx 355# 356class Scalar: 357 def is_scalar_reg(self): 358 return True 359 def is_hvx_reg(self): 360 return False 361 def helper_arg_name(self): 362 return self.reg_tcg() 363 364class Single(Scalar): 365 def helper_proto_type(self): 366 return "s32" 367 def helper_arg_type(self): 368 return "int32_t" 369 370class Pair(Scalar): 371 def helper_proto_type(self): 372 return "s64" 373 def helper_arg_type(self): 374 return "int64_t" 375 376class Hvx: 377 def is_scalar_reg(self): 378 return False 379 def is_hvx_reg(self): 380 return True 381 def hvx_off(self): 382 return f"{self.reg_tcg()}_off" 383 def helper_proto_type(self): 384 return "ptr" 385 def helper_arg_type(self): 386 return "void *" 387 def helper_arg_name(self): 388 return f"{self.reg_tcg()}_void" 389 390# 391# Every register is either Dest or OldSource or NewSource or ReadWrite 392# 393class Dest: 394 def reg_tcg(self): 395 return f"{self.regtype}{self.regid}V" 396 def is_written(self): 397 return True 398 def is_writeonly(self): 399 return True 400 def is_read(self): 401 return False 402 def is_readwrite(self): 403 return False 404 405class Source: 406 def is_written(self): 407 return False 408 def is_writeonly(self): 409 return False 410 def is_read(self): 411 return True 412 def is_readwrite(self): 413 return False 414 415class OldSource(Source): 416 def reg_tcg(self): 417 return f"{self.regtype}{self.regid}V" 418 def is_old(self): 419 return True 420 def is_new(self): 421 return False 422 423class NewSource(Source): 424 def reg_tcg(self): 425 return f"{self.regtype}{self.regid}N" 426 def is_old(self): 427 return False 428 def is_new(self): 429 return True 430 431class ReadWrite: 432 def reg_tcg(self): 433 return f"{self.regtype}{self.regid}V" 434 def is_written(self): 435 return True 436 def is_writeonly(self): 437 return False 438 def is_read(self): 439 return True 440 def is_readwrite(self): 441 return True 442 def is_old(self): 443 return True 444 def is_new(self): 445 return False 446 447class GprDest(Register, Single, Dest): 448 def decl_tcg(self, f, tag, regno): 449 self.decl_reg_num(f, regno) 450 f.write(code_fmt(f"""\ 451 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 452 """)) 453 def log_write(self, f, tag): 454 f.write(code_fmt(f"""\ 455 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 456 """)) 457 def analyze_write(self, f, tag, regno): 458 predicated = "true" if is_predicated(tag) else "false" 459 f.write(code_fmt(f"""\ 460 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 461 """)) 462 463class GprSource(Register, Single, OldSource): 464 def decl_tcg(self, f, tag, regno): 465 self.decl_reg_num(f, regno) 466 f.write(code_fmt(f"""\ 467 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 468 """)) 469 def analyze_read(self, f, regno): 470 f.write(code_fmt(f"""\ 471 ctx_log_reg_read(ctx, {self.reg_num}); 472 """)) 473 474class GprNewSource(Register, Single, NewSource): 475 def decl_tcg(self, f, tag, regno): 476 f.write(code_fmt(f"""\ 477 TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]); 478 """)) 479 def analyze_read(self, f, regno): 480 f.write(code_fmt(f"""\ 481 ctx_log_reg_read_new(ctx, {self.reg_num}); 482 """)) 483 484class GprReadWrite(Register, Single, ReadWrite): 485 def decl_tcg(self, f, tag, regno): 486 self.decl_reg_num(f, regno) 487 f.write(code_fmt(f"""\ 488 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 489 """)) 490 ## For read/write registers, we need to get the original value into 491 ## the result TCGv. For predicated instructions, this is done in 492 ## gen_start_packet. For un-predicated instructions, we do it here. 493 if not is_predicated(tag): 494 f.write(code_fmt(f"""\ 495 tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]); 496 """)) 497 def log_write(self, f, tag): 498 f.write(code_fmt(f"""\ 499 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 500 """)) 501 def analyze_read(self, f, regno): 502 f.write(code_fmt(f"""\ 503 ctx_log_reg_read(ctx, {self.reg_num}); 504 """)) 505 def analyze_write(self, f, tag, regno): 506 predicated = "true" if is_predicated(tag) else "false" 507 f.write(code_fmt(f"""\ 508 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 509 """)) 510 511class ControlDest(Register, Single, Dest): 512 def decl_reg_num(self, f, regno): 513 f.write(code_fmt(f"""\ 514 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 515 """)) 516 def decl_tcg(self, f, tag, regno): 517 self.decl_reg_num(f, regno) 518 f.write(code_fmt(f"""\ 519 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 520 """)) 521 def log_write(self, f, tag): 522 f.write(code_fmt(f"""\ 523 gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 524 """)) 525 def analyze_write(self, f, tag, regno): 526 predicated = "true" if is_predicated(tag) else "false" 527 f.write(code_fmt(f"""\ 528 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 529 """)) 530 531class ControlSource(Register, Single, OldSource): 532 def decl_reg_num(self, f, regno): 533 f.write(code_fmt(f"""\ 534 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 535 """)) 536 def decl_tcg(self, f, tag, regno): 537 self.decl_reg_num(f, regno); 538 f.write(code_fmt(f"""\ 539 TCGv {self.reg_tcg()} = tcg_temp_new(); 540 gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 541 """)) 542 def analyze_read(self, f, regno): 543 f.write(code_fmt(f"""\ 544 ctx_log_reg_read(ctx, {self.reg_num}); 545 """)) 546 547class ModifierSource(Register, Single, OldSource): 548 def decl_reg_num(self, f, regno): 549 f.write(code_fmt(f"""\ 550 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0; 551 """)) 552 def decl_tcg(self, f, tag, regno): 553 self.decl_reg_num(f, regno) 554 f.write(code_fmt(f"""\ 555 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 556 TCGv CS G_GNUC_UNUSED = 557 hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0]; 558 """)) 559 def idef_arg(self, declared): 560 declared.append(self.reg_tcg()) 561 declared.append("CS") 562 def analyze_read(self, f, regno): 563 f.write(code_fmt(f"""\ 564 ctx_log_reg_read(ctx, {self.reg_num}); 565 """)) 566 567class PredDest(Register, Single, Dest): 568 def decl_tcg(self, f, tag, regno): 569 self.decl_reg_num(f, regno) 570 f.write(code_fmt(f"""\ 571 TCGv {self.reg_tcg()} = tcg_temp_new(); 572 """)) 573 def log_write(self, f, tag): 574 f.write(code_fmt(f"""\ 575 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 576 """)) 577 def analyze_write(self, f, tag, regno): 578 f.write(code_fmt(f"""\ 579 ctx_log_pred_write(ctx, {self.reg_num}); 580 """)) 581 582class PredSource(Register, Single, OldSource): 583 def decl_tcg(self, f, tag, regno): 584 self.decl_reg_num(f, regno) 585 f.write(code_fmt(f"""\ 586 TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}]; 587 """)) 588 def analyze_read(self, f, regno): 589 f.write(code_fmt(f"""\ 590 ctx_log_pred_read(ctx, {self.reg_num}); 591 """)) 592 593class PredNewSource(Register, Single, NewSource): 594 def decl_tcg(self, f, tag, regno): 595 f.write(code_fmt(f"""\ 596 TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]); 597 """)) 598 def analyze_read(self, f, regno): 599 f.write(code_fmt(f"""\ 600 ctx_log_pred_read_new(ctx, {self.reg_num}); 601 """)) 602 603class PredReadWrite(Register, Single, ReadWrite): 604 def decl_tcg(self, f, tag, regno): 605 self.decl_reg_num(f, regno) 606 f.write(code_fmt(f"""\ 607 TCGv {self.reg_tcg()} = tcg_temp_new(); 608 tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]); 609 """)) 610 def log_write(self, f, tag): 611 f.write(code_fmt(f"""\ 612 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 613 """)) 614 def analyze_read(self, f, regno): 615 f.write(code_fmt(f"""\ 616 ctx_log_pred_read(ctx, {self.reg_num}); 617 """)) 618 def analyze_write(self, f, tag, regno): 619 f.write(code_fmt(f"""\ 620 ctx_log_pred_write(ctx, {self.reg_num}); 621 """)) 622 623class PairDest(Register, Pair, Dest): 624 def decl_tcg(self, f, tag, regno): 625 self.decl_reg_num(f, regno) 626 f.write(code_fmt(f"""\ 627 TCGv_i64 {self.reg_tcg()} = 628 get_result_gpr_pair(ctx, {self.reg_num}); 629 """)) 630 def log_write(self, f, tag): 631 f.write(code_fmt(f"""\ 632 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 633 """)) 634 def analyze_write(self, f, tag, regno): 635 predicated = "true" if is_predicated(tag) else "false" 636 f.write(code_fmt(f"""\ 637 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 638 """)) 639 640class PairSource(Register, Pair, OldSource): 641 def decl_tcg(self, f, tag, regno): 642 self.decl_reg_num(f, regno) 643 f.write(code_fmt(f"""\ 644 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 645 tcg_gen_concat_i32_i64({self.reg_tcg()}, 646 hex_gpr[{self.reg_num}], 647 hex_gpr[{self.reg_num} + 1]); 648 """)) 649 def analyze_read(self, f, regno): 650 f.write(code_fmt(f"""\ 651 ctx_log_reg_read_pair(ctx, {self.reg_num}); 652 """)) 653 654class PairReadWrite(Register, Pair, ReadWrite): 655 def decl_tcg(self, f, tag, regno): 656 self.decl_reg_num(f, regno) 657 f.write(code_fmt(f"""\ 658 TCGv_i64 {self.reg_tcg()} = 659 get_result_gpr_pair(ctx, {self.reg_num}); 660 tcg_gen_concat_i32_i64({self.reg_tcg()}, 661 hex_gpr[{self.reg_num}], 662 hex_gpr[{self.reg_num} + 1]); 663 """)) 664 def log_write(self, f, tag): 665 f.write(code_fmt(f"""\ 666 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 667 """)) 668 def analyze_read(self, f, regno): 669 f.write(code_fmt(f"""\ 670 ctx_log_reg_read_pair(ctx, {self.reg_num}); 671 """)) 672 def analyze_write(self, f, tag, regno): 673 predicated = "true" if is_predicated(tag) else "false" 674 f.write(code_fmt(f"""\ 675 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 676 """)) 677 678class ControlPairDest(Register, Pair, Dest): 679 def decl_reg_num(self, f, regno): 680 f.write(code_fmt(f"""\ 681 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 682 """)) 683 def decl_tcg(self, f, tag, regno): 684 self.decl_reg_num(f, regno) 685 f.write(code_fmt(f"""\ 686 TCGv_i64 {self.reg_tcg()} = 687 get_result_gpr_pair(ctx, {self.reg_num}); 688 """)) 689 def log_write(self, f, tag): 690 f.write(code_fmt(f"""\ 691 gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 692 """)) 693 def analyze_write(self, f, tag, regno): 694 predicated = "true" if is_predicated(tag) else "false" 695 f.write(code_fmt(f"""\ 696 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 697 """)) 698 699class ControlPairSource(Register, Pair, OldSource): 700 def decl_reg_num(self, f, regno): 701 f.write(code_fmt(f"""\ 702 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 703 """)) 704 def decl_tcg(self, f, tag, regno): 705 self.decl_reg_num(f, regno) 706 f.write(code_fmt(f"""\ 707 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 708 gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 709 """)) 710 def analyze_read(self, f, regno): 711 f.write(code_fmt(f"""\ 712 ctx_log_reg_read_pair(ctx, {self.reg_num}); 713 """)) 714 715class VRegDest(Register, Hvx, Dest): 716 def decl_tcg(self, f, tag, regno): 717 self.decl_reg_num(f, regno) 718 f.write(code_fmt(f"""\ 719 const intptr_t {self.hvx_off()} = 720 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 721 """)) 722 if not skip_qemu_helper(tag): 723 f.write(code_fmt(f"""\ 724 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 725 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 726 """)) 727 def log_write(self, f, tag): 728 pass 729 def helper_hvx_desc(self, f): 730 f.write(code_fmt(f"""\ 731 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 732 """)) 733 def analyze_write(self, f, tag, regno): 734 newv = hvx_newv(tag) 735 predicated = "true" if is_predicated(tag) else "false" 736 f.write(code_fmt(f"""\ 737 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 738 insn_has_hvx_helper); 739 """)) 740 741class VRegSource(Register, Hvx, OldSource): 742 def decl_tcg(self, f, tag, regno): 743 self.decl_reg_num(f, regno) 744 f.write(code_fmt(f"""\ 745 const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num}); 746 """)) 747 if not skip_qemu_helper(tag): 748 f.write(code_fmt(f"""\ 749 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 750 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 751 """)) 752 def helper_hvx_desc(self, f): 753 f.write(code_fmt(f"""\ 754 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 755 """)) 756 def analyze_read(self, f, regno): 757 f.write(code_fmt(f"""\ 758 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 759 """)) 760 761class VRegNewSource(Register, Hvx, NewSource): 762 def decl_tcg(self, f, tag, regno): 763 self.decl_reg_num(f, regno) 764 if skip_qemu_helper(tag): 765 f.write(code_fmt(f"""\ 766 const intptr_t {self.hvx_off()} = 767 ctx_future_vreg_off(ctx, {self.reg_num}, 1, true); 768 """)) 769 def helper_hvx_desc(self, f): 770 f.write(code_fmt(f"""\ 771 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 772 """)) 773 def analyze_read(self, f, regno): 774 f.write(code_fmt(f"""\ 775 ctx_log_vreg_read_new(ctx, {self.reg_num}, insn_has_hvx_helper); 776 """)) 777 778class VRegReadWrite(Register, Hvx, ReadWrite): 779 def decl_tcg(self, f, tag, regno): 780 self.decl_reg_num(f, regno) 781 f.write(code_fmt(f"""\ 782 const intptr_t {self.hvx_off()} = 783 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 784 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 785 vreg_src_off(ctx, {self.reg_num}), 786 sizeof(MMVector), sizeof(MMVector)); 787 """)) 788 if not skip_qemu_helper(tag): 789 f.write(code_fmt(f"""\ 790 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 791 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 792 """)) 793 def log_write(self, f, tag): 794 pass 795 def helper_hvx_desc(self, f): 796 f.write(code_fmt(f"""\ 797 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 798 """)) 799 def analyze_read(self, f, regno): 800 f.write(code_fmt(f"""\ 801 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 802 """)) 803 def analyze_write(self, f, tag, regno): 804 newv = hvx_newv(tag) 805 predicated = "true" if is_predicated(tag) else "false" 806 f.write(code_fmt(f"""\ 807 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 808 insn_has_hvx_helper); 809 """)) 810 811class VRegTmp(Register, Hvx, ReadWrite): 812 def decl_tcg(self, f, tag, regno): 813 self.decl_reg_num(f, regno) 814 f.write(code_fmt(f"""\ 815 const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp); 816 """)) 817 if not skip_qemu_helper(tag): 818 f.write(code_fmt(f"""\ 819 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 820 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 821 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 822 vreg_src_off(ctx, {self.reg_num}), 823 sizeof(MMVector), sizeof(MMVector)); 824 """)) 825 def log_write(self, f, tag): 826 f.write(code_fmt(f"""\ 827 gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num}, 828 {hvx_newv(tag)}); 829 """)) 830 def helper_hvx_desc(self, f): 831 f.write(code_fmt(f"""\ 832 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 833 """)) 834 def analyze_read(self, f, regno): 835 f.write(code_fmt(f"""\ 836 ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 837 """)) 838 def analyze_write(self, f, tag, regno): 839 newv = hvx_newv(tag) 840 predicated = "true" if is_predicated(tag) else "false" 841 f.write(code_fmt(f"""\ 842 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, 843 insn_has_hvx_helper); 844 """)) 845 846class VRegPairDest(Register, Hvx, Dest): 847 def decl_tcg(self, f, tag, regno): 848 self.decl_reg_num(f, regno) 849 f.write(code_fmt(f"""\ 850 const intptr_t {self.hvx_off()} = 851 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true); 852 """)) 853 if not skip_qemu_helper(tag): 854 f.write(code_fmt(f"""\ 855 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 856 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 857 """)) 858 def log_write(self, f, tag): 859 pass 860 def helper_hvx_desc(self, f): 861 f.write(code_fmt(f"""\ 862 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 863 """)) 864 def analyze_write(self, f, tag, regno): 865 newv = hvx_newv(tag) 866 predicated = "true" if is_predicated(tag) else "false" 867 f.write(code_fmt(f"""\ 868 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, 869 insn_has_hvx_helper); 870 """)) 871 872class VRegPairSource(Register, Hvx, OldSource): 873 def decl_tcg(self, f, tag, regno): 874 self.decl_reg_num(f, regno) 875 f.write(code_fmt(f"""\ 876 const intptr_t {self.hvx_off()} = 877 offsetof(CPUHexagonState, {self.reg_tcg()}); 878 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 879 vreg_src_off(ctx, {self.reg_num}), 880 sizeof(MMVector), sizeof(MMVector)); 881 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 882 vreg_src_off(ctx, {self.reg_num} ^ 1), 883 sizeof(MMVector), sizeof(MMVector)); 884 """)) 885 if not skip_qemu_helper(tag): 886 f.write(code_fmt(f"""\ 887 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 888 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 889 """)) 890 def helper_hvx_desc(self, f): 891 f.write(code_fmt(f"""\ 892 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 893 """)) 894 def analyze_read(self, f, regno): 895 f.write(code_fmt(f"""\ 896 ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); 897 """)) 898 899class VRegPairReadWrite(Register, Hvx, ReadWrite): 900 def decl_tcg(self, f, tag, regno): 901 self.decl_reg_num(f, regno) 902 f.write(code_fmt(f"""\ 903 const intptr_t {self.hvx_off()} = 904 offsetof(CPUHexagonState, {self.reg_tcg()}); 905 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 906 vreg_src_off(ctx, {self.reg_num}), 907 sizeof(MMVector), sizeof(MMVector)); 908 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 909 vreg_src_off(ctx, {self.reg_num} ^ 1), 910 sizeof(MMVector), sizeof(MMVector)); 911 """)) 912 if not skip_qemu_helper(tag): 913 f.write(code_fmt(f"""\ 914 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 915 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 916 """)) 917 def log_write(self, f, tag): 918 f.write(code_fmt(f"""\ 919 gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num}, 920 {hvx_newv(tag)}); 921 """)) 922 def helper_hvx_desc(self, f): 923 f.write(code_fmt(f"""\ 924 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 925 """)) 926 def analyze_read(self, f, regno): 927 f.write(code_fmt(f"""\ 928 ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); 929 """)) 930 def analyze_write(self, f, tag, regno): 931 newv = hvx_newv(tag) 932 predicated = "true" if is_predicated(tag) else "false" 933 f.write(code_fmt(f"""\ 934 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, 935 insn_has_hvx_helper); 936 """)) 937 938class QRegDest(Register, Hvx, Dest): 939 def decl_tcg(self, f, tag, regno): 940 self.decl_reg_num(f, regno) 941 f.write(code_fmt(f"""\ 942 const intptr_t {self.hvx_off()} = 943 get_result_qreg(ctx, {self.reg_num}); 944 """)) 945 if not skip_qemu_helper(tag): 946 f.write(code_fmt(f"""\ 947 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 948 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 949 """)) 950 def log_write(self, f, tag): 951 pass 952 def helper_hvx_desc(self, f): 953 f.write(code_fmt(f"""\ 954 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 955 """)) 956 def analyze_write(self, f, tag, regno): 957 f.write(code_fmt(f"""\ 958 ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); 959 """)) 960 961class QRegSource(Register, Hvx, OldSource): 962 def decl_tcg(self, f, tag, regno): 963 self.decl_reg_num(f, regno) 964 f.write(code_fmt(f"""\ 965 const intptr_t {self.hvx_off()} = 966 offsetof(CPUHexagonState, QRegs[{self.reg_num}]); 967 """)) 968 if not skip_qemu_helper(tag): 969 f.write(code_fmt(f"""\ 970 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 971 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 972 """)) 973 def helper_hvx_desc(self, f): 974 f.write(code_fmt(f"""\ 975 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 976 """)) 977 def analyze_read(self, f, regno): 978 f.write(code_fmt(f"""\ 979 ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 980 """)) 981 982class QRegReadWrite(Register, Hvx, ReadWrite): 983 def decl_tcg(self, f, tag, regno): 984 self.decl_reg_num(f, regno) 985 f.write(code_fmt(f"""\ 986 const intptr_t {self.hvx_off()} = 987 get_result_qreg(ctx, {self.reg_num}); 988 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 989 offsetof(CPUHexagonState, QRegs[{self.reg_num}]), 990 sizeof(MMQReg), sizeof(MMQReg)); 991 """)) 992 if not skip_qemu_helper(tag): 993 f.write(code_fmt(f"""\ 994 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 995 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 996 """)) 997 def log_write(self, f, tag): 998 pass 999 def helper_hvx_desc(self, f): 1000 f.write(code_fmt(f"""\ 1001 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 1002 """)) 1003 def analyze_read(self, f, regno): 1004 f.write(code_fmt(f"""\ 1005 ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); 1006 """)) 1007 def analyze_write(self, f, tag, regno): 1008 f.write(code_fmt(f"""\ 1009 ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); 1010 """)) 1011 1012def init_registers(): 1013 regs = { 1014 GprDest("R", "d"), 1015 GprDest("R", "e"), 1016 GprSource("R", "s"), 1017 GprSource("R", "t"), 1018 GprSource("R", "u"), 1019 GprSource("R", "v"), 1020 GprReadWrite("R", "x"), 1021 GprReadWrite("R", "y"), 1022 ControlDest("C", "d"), 1023 ControlSource("C", "s"), 1024 ModifierSource("M", "u"), 1025 PredDest("P", "d"), 1026 PredDest("P", "e"), 1027 PredSource("P", "s"), 1028 PredSource("P", "t"), 1029 PredSource("P", "u"), 1030 PredSource("P", "v"), 1031 PredReadWrite("P", "x"), 1032 PairDest("R", "dd"), 1033 PairDest("R", "ee"), 1034 PairSource("R", "ss"), 1035 PairSource("R", "tt"), 1036 PairReadWrite("R", "xx"), 1037 PairReadWrite("R", "yy"), 1038 ControlPairDest("C", "dd"), 1039 ControlPairSource("C", "ss"), 1040 VRegDest("V", "d"), 1041 VRegSource("V", "s"), 1042 VRegSource("V", "u"), 1043 VRegSource("V", "v"), 1044 VRegSource("V", "w"), 1045 VRegReadWrite("V", "x"), 1046 VRegTmp("V", "y"), 1047 VRegPairDest("V", "dd"), 1048 VRegPairSource("V", "uu"), 1049 VRegPairSource("V", "vv"), 1050 VRegPairReadWrite("V", "xx"), 1051 QRegDest("Q", "d"), 1052 QRegDest("Q", "e"), 1053 QRegSource("Q", "s"), 1054 QRegSource("Q", "t"), 1055 QRegSource("Q", "u"), 1056 QRegSource("Q", "v"), 1057 QRegReadWrite("Q", "x"), 1058 } 1059 for reg in regs: 1060 registers[f"{reg.regtype}{reg.regid}"] = reg 1061 1062 new_regs = { 1063 GprNewSource("N", "s"), 1064 GprNewSource("N", "t"), 1065 PredNewSource("P", "t"), 1066 PredNewSource("P", "u"), 1067 PredNewSource("P", "v"), 1068 VRegNewSource("O", "s"), 1069 } 1070 for reg in new_regs: 1071 new_registers[f"{reg.regtype}{reg.regid}"] = reg 1072 1073def get_register(tag, regtype, regid): 1074 if f"{regtype}{regid}V" in semdict[tag]: 1075 return registers[f"{regtype}{regid}"] 1076 else: 1077 return new_registers[f"{regtype}{regid}"] 1078 1079def helper_ret_type(tag, regs): 1080 ## If there is a scalar result, it is the return type 1081 return_type = HelperArg( "void", "void", "void") 1082 numscalarresults = 0 1083 for regtype, regid in regs: 1084 reg = get_register(tag, regtype, regid) 1085 if reg.is_written() and reg.is_scalar_reg(): 1086 return_type = HelperArg( 1087 reg.helper_proto_type(), 1088 reg.reg_tcg(), 1089 reg.helper_arg_type() 1090 ) 1091 if numscalarresults > 1: 1092 raise Exception("numscalarresults > 1") 1093 return return_type 1094 1095def helper_args(tag, regs, imms): 1096 args = [] 1097 1098 ## First argument is the CPU state 1099 if need_env(tag): 1100 args.append(HelperArg( 1101 "env", 1102 "tcg_env", 1103 "CPUHexagonState *env" 1104 )) 1105 1106 ## For predicated instructions, we pass in the destination register 1107 if is_predicated(tag): 1108 for regtype, regid in regs: 1109 reg = get_register(tag, regtype, regid) 1110 if reg.is_writeonly() and not reg.is_hvx_reg(): 1111 args.append(reg.helper_arg()) 1112 1113 ## Pass the HVX destination registers 1114 for regtype, regid in regs: 1115 reg = get_register(tag, regtype, regid) 1116 if reg.is_written() and reg.is_hvx_reg(): 1117 args.append(reg.helper_arg()) 1118 1119 ## Pass the source registers 1120 for regtype, regid in regs: 1121 reg = get_register(tag, regtype, regid) 1122 if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()): 1123 args.append(reg.helper_arg()) 1124 1125 ## Pass the immediates 1126 for immlett, bits, immshift in imms: 1127 args.append(HelperArg( 1128 "s32", 1129 f"tcg_constant_tl({imm_name(immlett)})", 1130 f"int32_t {imm_name(immlett)}" 1131 )) 1132 1133 ## Other stuff the helper might need 1134 if need_pkt_has_multi_cof(tag): 1135 args.append(HelperArg( 1136 "i32", 1137 "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)", 1138 "uint32_t pkt_has_multi_cof" 1139 )) 1140 if need_pkt_need_commit(tag): 1141 args.append(HelperArg( 1142 "i32", 1143 "tcg_constant_tl(ctx->need_commit)", 1144 "uint32_t pkt_need_commit" 1145 )) 1146 if need_PC(tag): 1147 args.append(HelperArg( 1148 "i32", 1149 "tcg_constant_tl(ctx->pkt->pc)", 1150 "target_ulong PC" 1151 )) 1152 if need_next_PC(tag): 1153 args.append(HelperArg( 1154 "i32", 1155 "tcg_constant_tl(ctx->next_PC)", 1156 "target_ulong next_PC" 1157 )) 1158 if need_p0(tag): 1159 args.append(HelperArg( 1160 "i32", 1161 "hex_pred[0]", 1162 "uint32_t P0" 1163 )) 1164 if need_sp(tag): 1165 args.append(HelperArg( 1166 "i32", 1167 "hex_gpr[HEX_REG_SP]", 1168 "uint32_t SP" 1169 )) 1170 if need_slot(tag): 1171 args.append(HelperArg( 1172 "i32", 1173 "gen_slotval(ctx)", 1174 "uint32_t slotval" 1175 )) 1176 if need_part1(tag): 1177 args.append(HelperArg( 1178 "i32", 1179 "tcg_constant_tl(insn->part1)" 1180 "uint32_t part1" 1181 )) 1182 return args 1183 1184 1185def parse_common_args(desc): 1186 parser = argparse.ArgumentParser(desc) 1187 parser.add_argument("semantics", help="semantics file") 1188 parser.add_argument("overrides", help="overrides file") 1189 parser.add_argument("overrides_vec", help="vector overrides file") 1190 parser.add_argument("out", help="output file") 1191 parser.add_argument("--idef-parser", 1192 help="file of instructions translated by idef-parser") 1193 args = parser.parse_args() 1194 read_semantics_file(args.semantics) 1195 read_overrides_file(args.overrides) 1196 read_overrides_file(args.overrides_vec) 1197 if args.idef_parser: 1198 read_idef_parser_enabled_file(args.idef_parser) 1199 calculate_attribs() 1200 init_registers() 1201 return args 1202