1#!/usr/bin/env python3 2 3## 4## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. 5## 6## This program is free software; you can redistribute it and/or modify 7## it under the terms of the GNU General Public License as published by 8## the Free Software Foundation; either version 2 of the License, or 9## (at your option) any later version. 10## 11## This program is distributed in the hope that it will be useful, 12## but WITHOUT ANY WARRANTY; without even the implied warranty of 13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14## GNU General Public License for more details. 15## 16## You should have received a copy of the GNU General Public License 17## along with this program; if not, see <http://www.gnu.org/licenses/>. 18## 19 20import sys 21import re 22import string 23import textwrap 24 25behdict = {} # tag ->behavior 26semdict = {} # tag -> semantics 27attribdict = {} # tag -> attributes 28macros = {} # macro -> macro information... 29attribinfo = {} # Register information and misc 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 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_slot(tag): 201 if ( 202 "A_CVI_SCATTER" not in attribdict[tag] 203 and "A_CVI_GATHER" not in attribdict[tag] 204 and ("A_STORE" in attribdict[tag] 205 or "A_LOAD" in attribdict[tag]) 206 ): 207 return 1 208 else: 209 return 0 210 211 212def need_part1(tag): 213 return re.compile(r"fPART1").search(semdict[tag]) 214 215 216def need_ea(tag): 217 return re.compile(r"\bEA\b").search(semdict[tag]) 218 219 220def need_PC(tag): 221 return "A_IMPLICIT_READS_PC" in attribdict[tag] 222 223 224def need_next_PC(tag): 225 return "A_CALL" in attribdict[tag] 226 227 228def need_pkt_has_multi_cof(tag): 229 return "A_COF" in attribdict[tag] 230 231 232def need_pkt_need_commit(tag): 233 return 'A_IMPLICIT_WRITES_USR' in attribdict[tag] 234 235 236def skip_qemu_helper(tag): 237 return tag in overrides.keys() 238 239 240def is_idef_parser_enabled(tag): 241 return tag in idef_parser_enabled 242 243 244def imm_name(immlett): 245 return f"{immlett}iV" 246 247 248def read_semantics_file(name): 249 eval_line = "" 250 for line in open(name, "rt").readlines(): 251 if not line.startswith("#"): 252 eval_line += line 253 if line.endswith("\\\n"): 254 eval_line.rstrip("\\\n") 255 else: 256 eval(eval_line.strip()) 257 eval_line = "" 258 259 260def read_attribs_file(name): 261 attribre = re.compile( 262 r"DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), " 263 + r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)' 264 ) 265 for line in open(name, "rt").readlines(): 266 if not attribre.match(line): 267 continue 268 (attrib_base, descr, rreg, wreg) = attribre.findall(line)[0] 269 attrib_base = "A_" + attrib_base 270 attribinfo[attrib_base] = {"rreg": rreg, "wreg": wreg, "descr": descr} 271 272 273def read_overrides_file(name): 274 overridere = re.compile(r"#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") 275 for line in open(name, "rt").readlines(): 276 if not overridere.match(line): 277 continue 278 tag = overridere.findall(line)[0] 279 overrides[tag] = True 280 281 282def read_idef_parser_enabled_file(name): 283 global idef_parser_enabled 284 with open(name, "r") as idef_parser_enabled_file: 285 lines = idef_parser_enabled_file.read().strip().split("\n") 286 idef_parser_enabled = set(lines) 287 288 289def is_predicated(tag): 290 return "A_CONDEXEC" in attribdict[tag] 291 292 293def code_fmt(txt): 294 return textwrap.indent(textwrap.dedent(txt), " ") 295 296 297def hvx_newv(tag): 298 if "A_CVI_NEW" in attribdict[tag]: 299 return "EXT_NEW" 300 elif "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]: 301 return "EXT_TMP" 302 else: 303 return "EXT_DFL" 304 305def vreg_offset_func(tag): 306 if "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]: 307 return "ctx_tmp_vreg_off" 308 else: 309 return "ctx_future_vreg_off" 310 311class HelperArg: 312 def __init__(self, proto_arg, call_arg, func_arg): 313 self.proto_arg = proto_arg 314 self.call_arg = call_arg 315 self.func_arg = func_arg 316 317class Register: 318 def __init__(self, regtype, regid): 319 self.regtype = regtype 320 self.regid = regid 321 self.reg_num = f"{regtype}{regid}N" 322 def decl_reg_num(self, f, regno): 323 f.write(code_fmt(f"""\ 324 const int {self.reg_num} = insn->regno[{regno}]; 325 """)) 326 def idef_arg(self, declared): 327 declared.append(self.reg_tcg()) 328 def helper_arg(self): 329 return HelperArg( 330 self.helper_proto_type(), 331 self.reg_tcg(), 332 f"{self.helper_arg_type()} {self.helper_arg_name()}" 333 ) 334 335# 336# Every register is either Single or Pair or Hvx 337# 338class Scalar: 339 def is_scalar_reg(self): 340 return True 341 def is_hvx_reg(self): 342 return False 343 def helper_arg_name(self): 344 return self.reg_tcg() 345 346class Single(Scalar): 347 def helper_proto_type(self): 348 return "s32" 349 def helper_arg_type(self): 350 return "int32_t" 351 352class Pair(Scalar): 353 def helper_proto_type(self): 354 return "s64" 355 def helper_arg_type(self): 356 return "int64_t" 357 358class Hvx: 359 def is_scalar_reg(self): 360 return False 361 def is_hvx_reg(self): 362 return True 363 def hvx_off(self): 364 return f"{self.reg_tcg()}_off" 365 def helper_proto_type(self): 366 return "ptr" 367 def helper_arg_type(self): 368 return "void *" 369 def helper_arg_name(self): 370 return f"{self.reg_tcg()}_void" 371 372# 373# Every register is either Dest or OldSource or NewSource or ReadWrite 374# 375class Dest: 376 def reg_tcg(self): 377 return f"{self.regtype}{self.regid}V" 378 def is_written(self): 379 return True 380 def is_writeonly(self): 381 return True 382 def is_read(self): 383 return False 384 def is_readwrite(self): 385 return False 386 387class Source: 388 def is_written(self): 389 return False 390 def is_writeonly(self): 391 return False 392 def is_read(self): 393 return True 394 def is_readwrite(self): 395 return False 396 397class OldSource(Source): 398 def reg_tcg(self): 399 return f"{self.regtype}{self.regid}V" 400 401class NewSource(Source): 402 def reg_tcg(self): 403 return f"{self.regtype}{self.regid}N" 404 405class ReadWrite: 406 def reg_tcg(self): 407 return f"{self.regtype}{self.regid}V" 408 def is_written(self): 409 return True 410 def is_writeonly(self): 411 return False 412 def is_read(self): 413 return True 414 def is_readwrite(self): 415 return True 416 417class GprDest(Register, Single, Dest): 418 def decl_tcg(self, f, tag, regno): 419 self.decl_reg_num(f, regno) 420 f.write(code_fmt(f"""\ 421 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 422 """)) 423 def log_write(self, f, tag): 424 f.write(code_fmt(f"""\ 425 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 426 """)) 427 def analyze_write(self, f, tag, regno): 428 self.decl_reg_num(f, regno) 429 predicated = "true" if is_predicated(tag) else "false" 430 f.write(code_fmt(f"""\ 431 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 432 """)) 433 434class GprSource(Register, Single, OldSource): 435 def decl_tcg(self, f, tag, regno): 436 self.decl_reg_num(f, regno) 437 f.write(code_fmt(f"""\ 438 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 439 """)) 440 def analyze_read(self, f, regno): 441 self.decl_reg_num(f, regno) 442 f.write(code_fmt(f"""\ 443 ctx_log_reg_read(ctx, {self.reg_num}); 444 """)) 445 446class GprNewSource(Register, Single, NewSource): 447 def decl_tcg(self, f, tag, regno): 448 f.write(code_fmt(f"""\ 449 TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]); 450 """)) 451 def analyze_read(self, f, regno): 452 self.decl_reg_num(f, regno) 453 f.write(code_fmt(f"""\ 454 ctx_log_reg_read(ctx, {self.reg_num}); 455 """)) 456 457class GprReadWrite(Register, Single, ReadWrite): 458 def decl_tcg(self, f, tag, regno): 459 self.decl_reg_num(f, regno) 460 f.write(code_fmt(f"""\ 461 TCGv {self.reg_tcg()} = get_result_gpr(ctx, {self.reg_num}); 462 """)) 463 ## For read/write registers, we need to get the original value into 464 ## the result TCGv. For predicated instructions, this is done in 465 ## gen_start_packet. For un-predicated instructions, we do it here. 466 if not is_predicated(tag): 467 f.write(code_fmt(f"""\ 468 tcg_gen_mov_tl({self.reg_tcg()}, hex_gpr[{self.reg_num}]); 469 """)) 470 def log_write(self, f, tag): 471 f.write(code_fmt(f"""\ 472 gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); 473 """)) 474 def analyze_write(self, f, tag, regno): 475 self.decl_reg_num(f, regno) 476 predicated = "true" if is_predicated(tag) else "false" 477 f.write(code_fmt(f"""\ 478 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 479 """)) 480 481class ControlDest(Register, Single, Dest): 482 def decl_reg_num(self, f, regno): 483 f.write(code_fmt(f"""\ 484 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 485 """)) 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 def log_write(self, f, tag): 492 f.write(code_fmt(f"""\ 493 gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 494 """)) 495 def analyze_write(self, f, tag, regno): 496 self.decl_reg_num(f, regno) 497 predicated = "true" if is_predicated(tag) else "false" 498 f.write(code_fmt(f"""\ 499 ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); 500 """)) 501 502class ControlSource(Register, Single, OldSource): 503 def decl_reg_num(self, f, regno): 504 f.write(code_fmt(f"""\ 505 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 506 """)) 507 def decl_tcg(self, f, tag, regno): 508 self.decl_reg_num(f, regno); 509 f.write(code_fmt(f"""\ 510 TCGv {self.reg_tcg()} = tcg_temp_new(); 511 gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); 512 """)) 513 def analyze_read(self, f, regno): 514 self.decl_reg_num(f, regno) 515 f.write(code_fmt(f"""\ 516 ctx_log_reg_read(ctx, {self.reg_num}); 517 """)) 518 519class ModifierSource(Register, Single, OldSource): 520 def decl_reg_num(self, f, regno): 521 f.write(code_fmt(f"""\ 522 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_M0; 523 """)) 524 def decl_tcg(self, f, tag, regno): 525 self.decl_reg_num(f, regno) 526 f.write(code_fmt(f"""\ 527 TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; 528 TCGv CS G_GNUC_UNUSED = 529 hex_gpr[{self.reg_num} - HEX_REG_M0 + HEX_REG_CS0]; 530 """)) 531 def idef_arg(self, declared): 532 declared.append(self.reg_tcg()) 533 declared.append("CS") 534 def analyze_read(self, f, regno): 535 self.decl_reg_num(f, regno) 536 f.write(code_fmt(f"""\ 537 ctx_log_reg_read(ctx, {self.reg_num}); 538 """)) 539 540class PredDest(Register, Single, Dest): 541 def decl_tcg(self, f, tag, regno): 542 self.decl_reg_num(f, regno) 543 f.write(code_fmt(f"""\ 544 TCGv {self.reg_tcg()} = tcg_temp_new(); 545 """)) 546 def log_write(self, f, tag): 547 f.write(code_fmt(f"""\ 548 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 549 """)) 550 def analyze_write(self, f, tag, regno): 551 self.decl_reg_num(f, regno) 552 f.write(code_fmt(f"""\ 553 ctx_log_pred_write(ctx, {self.reg_num}); 554 """)) 555 556class PredSource(Register, Single, OldSource): 557 def decl_tcg(self, f, tag, regno): 558 self.decl_reg_num(f, regno) 559 f.write(code_fmt(f"""\ 560 TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}]; 561 """)) 562 def analyze_read(self, f, regno): 563 self.decl_reg_num(f, regno) 564 f.write(code_fmt(f"""\ 565 ctx_log_pred_read(ctx, {self.reg_num}); 566 """)) 567 568class PredNewSource(Register, Single, NewSource): 569 def decl_tcg(self, f, tag, regno): 570 f.write(code_fmt(f"""\ 571 TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]); 572 """)) 573 def analyze_read(self, f, regno): 574 self.decl_reg_num(f, regno) 575 f.write(code_fmt(f"""\ 576 ctx_log_pred_read(ctx, {self.reg_num}); 577 """)) 578 579class PredReadWrite(Register, Single, ReadWrite): 580 def decl_tcg(self, f, tag, regno): 581 self.decl_reg_num(f, regno) 582 f.write(code_fmt(f"""\ 583 TCGv {self.reg_tcg()} = tcg_temp_new(); 584 tcg_gen_mov_tl({self.reg_tcg()}, hex_pred[{self.reg_num}]); 585 """)) 586 def log_write(self, f, tag): 587 f.write(code_fmt(f"""\ 588 gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); 589 """)) 590 def analyze_write(self, f, tag, regno): 591 self.decl_reg_num(f, regno) 592 f.write(code_fmt(f"""\ 593 ctx_log_pred_write(ctx, {self.reg_num}); 594 """)) 595 596class PairDest(Register, Pair, Dest): 597 def decl_tcg(self, f, tag, regno): 598 self.decl_reg_num(f, regno) 599 f.write(code_fmt(f"""\ 600 TCGv_i64 {self.reg_tcg()} = 601 get_result_gpr_pair(ctx, {self.reg_num}); 602 """)) 603 def log_write(self, f, tag): 604 f.write(code_fmt(f"""\ 605 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 606 """)) 607 def analyze_write(self, f, tag, regno): 608 self.decl_reg_num(f, regno) 609 predicated = "true" if is_predicated(tag) else "false" 610 f.write(code_fmt(f"""\ 611 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 612 """)) 613 614class PairSource(Register, Pair, OldSource): 615 def decl_tcg(self, f, tag, regno): 616 self.decl_reg_num(f, regno) 617 f.write(code_fmt(f"""\ 618 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 619 tcg_gen_concat_i32_i64({self.reg_tcg()}, 620 hex_gpr[{self.reg_num}], 621 hex_gpr[{self.reg_num} + 1]); 622 """)) 623 def analyze_read(self, f, regno): 624 self.decl_reg_num(f, regno) 625 f.write(code_fmt(f"""\ 626 ctx_log_reg_read_pair(ctx, {self.reg_num}); 627 """)) 628 629class PairReadWrite(Register, Pair, ReadWrite): 630 def decl_tcg(self, f, tag, regno): 631 self.decl_reg_num(f, regno) 632 f.write(code_fmt(f"""\ 633 TCGv_i64 {self.reg_tcg()} = 634 get_result_gpr_pair(ctx, {self.reg_num}); 635 tcg_gen_concat_i32_i64({self.reg_tcg()}, 636 hex_gpr[{self.reg_num}], 637 hex_gpr[{self.reg_num} + 1]); 638 """)) 639 def log_write(self, f, tag): 640 f.write(code_fmt(f"""\ 641 gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 642 """)) 643 def analyze_write(self, f, tag, regno): 644 self.decl_reg_num(f, regno) 645 predicated = "true" if is_predicated(tag) else "false" 646 f.write(code_fmt(f"""\ 647 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 648 """)) 649 650class ControlPairDest(Register, Pair, Dest): 651 def decl_reg_num(self, f, regno): 652 f.write(code_fmt(f"""\ 653 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 654 """)) 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 """)) 661 def log_write(self, f, tag): 662 f.write(code_fmt(f"""\ 663 gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 664 """)) 665 def analyze_write(self, f, tag, regno): 666 self.decl_reg_num(f, regno) 667 predicated = "true" if is_predicated(tag) else "false" 668 f.write(code_fmt(f"""\ 669 ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); 670 """)) 671 672class ControlPairSource(Register, Pair, OldSource): 673 def decl_reg_num(self, f, regno): 674 f.write(code_fmt(f"""\ 675 const int {self.reg_num} = insn->regno[{regno}] + HEX_REG_SA0; 676 """)) 677 def decl_tcg(self, f, tag, regno): 678 self.decl_reg_num(f, regno) 679 f.write(code_fmt(f"""\ 680 TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64(); 681 gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); 682 """)) 683 def analyze_read(self, f, regno): 684 self.decl_reg_num(f, regno) 685 f.write(code_fmt(f"""\ 686 ctx_log_reg_read_pair(ctx, {self.reg_num}); 687 """)) 688 689class VRegDest(Register, Hvx, Dest): 690 def decl_tcg(self, f, tag, regno): 691 self.decl_reg_num(f, regno) 692 f.write(code_fmt(f"""\ 693 const intptr_t {self.hvx_off()} = 694 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 695 """)) 696 if not skip_qemu_helper(tag): 697 f.write(code_fmt(f"""\ 698 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 699 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 700 """)) 701 def log_write(self, f, tag): 702 pass 703 def helper_hvx_desc(self, f): 704 f.write(code_fmt(f"""\ 705 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 706 """)) 707 def analyze_write(self, f, tag, regno): 708 self.decl_reg_num(f, regno) 709 newv = hvx_newv(tag) 710 predicated = "true" if is_predicated(tag) else "false" 711 f.write(code_fmt(f"""\ 712 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); 713 """)) 714 715class VRegSource(Register, Hvx, OldSource): 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()} = vreg_src_off(ctx, {self.reg_num}); 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 helper_hvx_desc(self, f): 727 f.write(code_fmt(f"""\ 728 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 729 """)) 730 def analyze_read(self, f, regno): 731 self.decl_reg_num(f, regno) 732 f.write(code_fmt(f"""\ 733 ctx_log_vreg_read(ctx, {self.reg_num}); 734 """)) 735 736class VRegNewSource(Register, Hvx, NewSource): 737 def decl_tcg(self, f, tag, regno): 738 self.decl_reg_num(f, regno) 739 if skip_qemu_helper(tag): 740 f.write(code_fmt(f"""\ 741 const intptr_t {self.hvx_off()} = 742 ctx_future_vreg_off(ctx, {self.reg_num}, 1, true); 743 """)) 744 def helper_hvx_desc(self, f): 745 f.write(code_fmt(f"""\ 746 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 747 """)) 748 def analyze_read(self, f, regno): 749 self.decl_reg_num(f, regno) 750 f.write(code_fmt(f"""\ 751 ctx_log_vreg_read(ctx, {self.reg_num}); 752 """)) 753 754class VRegReadWrite(Register, Hvx, ReadWrite): 755 def decl_tcg(self, f, tag, regno): 756 self.decl_reg_num(f, regno) 757 f.write(code_fmt(f"""\ 758 const intptr_t {self.hvx_off()} = 759 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true); 760 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 761 vreg_src_off(ctx, {self.reg_num}), 762 sizeof(MMVector), sizeof(MMVector)); 763 """)) 764 if not skip_qemu_helper(tag): 765 f.write(code_fmt(f"""\ 766 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 767 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 768 """)) 769 def log_write(self, f, tag): 770 pass 771 def helper_hvx_desc(self, f): 772 f.write(code_fmt(f"""\ 773 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 774 """)) 775 def analyze_write(self, f, tag, regno): 776 self.decl_reg_num(f, regno) 777 newv = hvx_newv(tag) 778 predicated = "true" if is_predicated(tag) else "false" 779 f.write(code_fmt(f"""\ 780 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); 781 """)) 782 783class VRegTmp(Register, Hvx, ReadWrite): 784 def decl_tcg(self, f, tag, regno): 785 self.decl_reg_num(f, regno) 786 f.write(code_fmt(f"""\ 787 const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp); 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 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 794 vreg_src_off(ctx, {self.reg_num}), 795 sizeof(MMVector), sizeof(MMVector)); 796 """)) 797 def log_write(self, f, tag): 798 f.write(code_fmt(f"""\ 799 gen_log_vreg_write(ctx, {self.hvx_off()}, {self.reg_num}, 800 {hvx_newv(tag)}); 801 """)) 802 def helper_hvx_desc(self, f): 803 f.write(code_fmt(f"""\ 804 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ 805 """)) 806 def analyze_write(self, f, tag, regno): 807 self.decl_reg_num(f, regno) 808 newv = hvx_newv(tag) 809 predicated = "true" if is_predicated(tag) else "false" 810 f.write(code_fmt(f"""\ 811 ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); 812 """)) 813 814class VRegPairDest(Register, Hvx, Dest): 815 def decl_tcg(self, f, tag, regno): 816 self.decl_reg_num(f, regno) 817 f.write(code_fmt(f"""\ 818 const intptr_t {self.hvx_off()} = 819 {vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true); 820 """)) 821 if not skip_qemu_helper(tag): 822 f.write(code_fmt(f"""\ 823 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 824 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 825 """)) 826 def log_write(self, f, tag): 827 pass 828 def helper_hvx_desc(self, f): 829 f.write(code_fmt(f"""\ 830 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 831 """)) 832 def analyze_write(self, f, tag, regno): 833 self.decl_reg_num(f, regno) 834 newv = hvx_newv(tag) 835 predicated = "true" if is_predicated(tag) else "false" 836 f.write(code_fmt(f"""\ 837 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}); 838 """)) 839 840class VRegPairSource(Register, Hvx, OldSource): 841 def decl_tcg(self, f, tag, regno): 842 self.decl_reg_num(f, regno) 843 f.write(code_fmt(f"""\ 844 const intptr_t {self.hvx_off()} = 845 offsetof(CPUHexagonState, {self.reg_tcg()}); 846 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 847 vreg_src_off(ctx, {self.reg_num}), 848 sizeof(MMVector), sizeof(MMVector)); 849 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 850 vreg_src_off(ctx, {self.reg_num} ^ 1), 851 sizeof(MMVector), sizeof(MMVector)); 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 helper_hvx_desc(self, f): 859 f.write(code_fmt(f"""\ 860 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ 861 """)) 862 def analyze_read(self, f, regno): 863 self.decl_reg_num(f, regno) 864 f.write(code_fmt(f"""\ 865 ctx_log_vreg_read_pair(ctx, {self.reg_num}); 866 """)) 867 868class VRegPairReadWrite(Register, Hvx, ReadWrite): 869 def decl_tcg(self, f, tag, regno): 870 self.decl_reg_num(f, regno) 871 f.write(code_fmt(f"""\ 872 const intptr_t {self.hvx_off()} = 873 offsetof(CPUHexagonState, {self.reg_tcg()}); 874 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 875 vreg_src_off(ctx, {self.reg_num}), 876 sizeof(MMVector), sizeof(MMVector)); 877 tcg_gen_gvec_mov(MO_64, {self.hvx_off()} + sizeof(MMVector), 878 vreg_src_off(ctx, {self.reg_num} ^ 1), 879 sizeof(MMVector), sizeof(MMVector)); 880 """)) 881 if not skip_qemu_helper(tag): 882 f.write(code_fmt(f"""\ 883 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 884 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 885 """)) 886 def log_write(self, f, tag): 887 f.write(code_fmt(f"""\ 888 gen_log_vreg_write_pair(ctx, {self.hvx_off()}, {self.reg_num}, 889 {hvx_newv(tag)}); 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_write(self, f, tag, regno): 896 self.decl_reg_num(f, regno) 897 newv = hvx_newv(tag) 898 predicated = "true" if is_predicated(tag) else "false" 899 f.write(code_fmt(f"""\ 900 ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}); 901 """)) 902 903class QRegDest(Register, Hvx, Dest): 904 def decl_tcg(self, f, tag, regno): 905 self.decl_reg_num(f, regno) 906 f.write(code_fmt(f"""\ 907 const intptr_t {self.hvx_off()} = 908 get_result_qreg(ctx, {self.reg_num}); 909 """)) 910 if not skip_qemu_helper(tag): 911 f.write(code_fmt(f"""\ 912 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 913 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 914 """)) 915 def log_write(self, f, tag): 916 pass 917 def helper_hvx_desc(self, f): 918 f.write(code_fmt(f"""\ 919 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 920 """)) 921 def analyze_write(self, f, tag, regno): 922 self.decl_reg_num(f, regno) 923 f.write(code_fmt(f"""\ 924 ctx_log_qreg_write(ctx, {self.reg_num}); 925 """)) 926 927class QRegSource(Register, Hvx, OldSource): 928 def decl_tcg(self, f, tag, regno): 929 self.decl_reg_num(f, regno) 930 f.write(code_fmt(f"""\ 931 const intptr_t {self.hvx_off()} = 932 offsetof(CPUHexagonState, QRegs[{self.reg_num}]); 933 """)) 934 if not skip_qemu_helper(tag): 935 f.write(code_fmt(f"""\ 936 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 937 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 938 """)) 939 def helper_hvx_desc(self, f): 940 f.write(code_fmt(f"""\ 941 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 942 """)) 943 def analyze_read(self, f, regno): 944 self.decl_reg_num(f, regno) 945 f.write(code_fmt(f"""\ 946 ctx_log_qreg_read(ctx, {self.reg_num}); 947 """)) 948 949class QRegReadWrite(Register, Hvx, ReadWrite): 950 def decl_tcg(self, f, tag, regno): 951 self.decl_reg_num(f, regno) 952 f.write(code_fmt(f"""\ 953 const intptr_t {self.hvx_off()} = 954 get_result_qreg(ctx, {self.reg_num}); 955 tcg_gen_gvec_mov(MO_64, {self.hvx_off()}, 956 offsetof(CPUHexagonState, QRegs[{self.reg_num}]), 957 sizeof(MMQReg), sizeof(MMQReg)); 958 """)) 959 if not skip_qemu_helper(tag): 960 f.write(code_fmt(f"""\ 961 TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr(); 962 tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()}); 963 """)) 964 def log_write(self, f, tag): 965 pass 966 def helper_hvx_desc(self, f): 967 f.write(code_fmt(f"""\ 968 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ 969 """)) 970 def analyze_write(self, f, tag, regno): 971 self.decl_reg_num(f, regno) 972 f.write(code_fmt(f"""\ 973 ctx_log_qreg_write(ctx, {self.reg_num}); 974 """)) 975 976def init_registers(): 977 regs = { 978 GprDest("R", "d"), 979 GprDest("R", "e"), 980 GprSource("R", "s"), 981 GprSource("R", "t"), 982 GprSource("R", "u"), 983 GprSource("R", "v"), 984 GprReadWrite("R", "x"), 985 GprReadWrite("R", "y"), 986 ControlDest("C", "d"), 987 ControlSource("C", "s"), 988 ModifierSource("M", "u"), 989 PredDest("P", "d"), 990 PredDest("P", "e"), 991 PredSource("P", "s"), 992 PredSource("P", "t"), 993 PredSource("P", "u"), 994 PredSource("P", "v"), 995 PredReadWrite("P", "x"), 996 PairDest("R", "dd"), 997 PairDest("R", "ee"), 998 PairSource("R", "ss"), 999 PairSource("R", "tt"), 1000 PairReadWrite("R", "xx"), 1001 PairReadWrite("R", "yy"), 1002 ControlPairDest("C", "dd"), 1003 ControlPairSource("C", "ss"), 1004 VRegDest("V", "d"), 1005 VRegSource("V", "s"), 1006 VRegSource("V", "u"), 1007 VRegSource("V", "v"), 1008 VRegSource("V", "w"), 1009 VRegReadWrite("V", "x"), 1010 VRegTmp("V", "y"), 1011 VRegPairDest("V", "dd"), 1012 VRegPairSource("V", "uu"), 1013 VRegPairSource("V", "vv"), 1014 VRegPairReadWrite("V", "xx"), 1015 QRegDest("Q", "d"), 1016 QRegDest("Q", "e"), 1017 QRegSource("Q", "s"), 1018 QRegSource("Q", "t"), 1019 QRegSource("Q", "u"), 1020 QRegSource("Q", "v"), 1021 QRegReadWrite("Q", "x"), 1022 } 1023 for reg in regs: 1024 registers[f"{reg.regtype}{reg.regid}"] = reg 1025 1026 new_regs = { 1027 GprNewSource("N", "s"), 1028 GprNewSource("N", "t"), 1029 PredNewSource("P", "t"), 1030 PredNewSource("P", "u"), 1031 PredNewSource("P", "v"), 1032 VRegNewSource("O", "s"), 1033 } 1034 for reg in new_regs: 1035 new_registers[f"{reg.regtype}{reg.regid}"] = reg 1036 1037def get_register(tag, regtype, regid): 1038 if f"{regtype}{regid}V" in semdict[tag]: 1039 return registers[f"{regtype}{regid}"] 1040 else: 1041 return new_registers[f"{regtype}{regid}"] 1042 1043def helper_ret_type(tag, regs): 1044 ## If there is a scalar result, it is the return type 1045 return_type = HelperArg( "void", "void", "void") 1046 numscalarresults = 0 1047 for regtype, regid in regs: 1048 reg = get_register(tag, regtype, regid) 1049 if reg.is_written() and reg.is_scalar_reg(): 1050 return_type = HelperArg( 1051 reg.helper_proto_type(), 1052 reg.reg_tcg(), 1053 reg.helper_arg_type() 1054 ) 1055 if numscalarresults > 1: 1056 raise Exception("numscalarresults > 1") 1057 return return_type 1058 1059def helper_args(tag, regs, imms): 1060 args = [] 1061 1062 ## First argument is the CPU state 1063 args.append(HelperArg( 1064 "env", 1065 "tcg_env", 1066 "CPUHexagonState *env" 1067 )) 1068 1069 ## For predicated instructions, we pass in the destination register 1070 if is_predicated(tag): 1071 for regtype, regid in regs: 1072 reg = get_register(tag, regtype, regid) 1073 if reg.is_writeonly() and not reg.is_hvx_reg(): 1074 args.append(reg.helper_arg()) 1075 1076 ## Pass the HVX destination registers 1077 for regtype, regid in regs: 1078 reg = get_register(tag, regtype, regid) 1079 if reg.is_written() and reg.is_hvx_reg(): 1080 args.append(reg.helper_arg()) 1081 1082 ## Pass the source registers 1083 for regtype, regid in regs: 1084 reg = get_register(tag, regtype, regid) 1085 if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()): 1086 args.append(reg.helper_arg()) 1087 1088 ## Pass the immediates 1089 for immlett, bits, immshift in imms: 1090 args.append(HelperArg( 1091 "s32", 1092 f"tcg_constant_tl({imm_name(immlett)})", 1093 f"int32_t {imm_name(immlett)}" 1094 )) 1095 1096 ## Other stuff the helper might need 1097 if need_pkt_has_multi_cof(tag): 1098 args.append(HelperArg( 1099 "i32", 1100 "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)", 1101 "uint32_t pkt_has_multi_cof" 1102 )) 1103 if need_pkt_need_commit(tag): 1104 args.append(HelperArg( 1105 "i32", 1106 "tcg_constant_tl(ctx->need_commit)", 1107 "uint32_t pkt_need_commit" 1108 )) 1109 if need_PC(tag): 1110 args.append(HelperArg( 1111 "i32", 1112 "tcg_constant_tl(ctx->pkt->pc)", 1113 "target_ulong PC" 1114 )) 1115 if need_next_PC(tag): 1116 args.append(HelperArg( 1117 "i32", 1118 "tcg_constant_tl(ctx->next_PC)", 1119 "target_ulong next_PC" 1120 )) 1121 if need_slot(tag): 1122 args.append(HelperArg( 1123 "i32", 1124 "gen_slotval(ctx)", 1125 "uint32_t slotval" 1126 )) 1127 if need_part1(tag): 1128 args.append(HelperArg( 1129 "i32", 1130 "tcg_constant_tl(insn->part1)" 1131 "uint32_t part1" 1132 )) 1133 return args 1134