4 ## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
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.
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.
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/>.
25 behdict
= {} # tag ->behavior
26 semdict
= {} # tag -> semantics
27 attribdict
= {} # tag -> attributes
28 macros
= {} # macro -> macro information...
29 attribinfo
= {} # Register information and misc
30 registers
= {} # register -> register functions
32 tags
= [] # list of all tags
33 overrides
= {} # tags with helper overrides
34 idef_parser_enabled
= {} # tags enabled for idef-parser
36 # We should do this as a hash for performance,
37 # but to keep order let's keep it as a list.
41 return [x
for x
in seq
if x
not in seen
and not seen_add(x
)]
44 regre
= re
.compile(r
"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
45 immre
= re
.compile(r
"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
46 reg_or_immre
= re
.compile(
47 r
"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)"
48 r
"([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)"
50 relimmre
= re
.compile(r
"[#]([rR])(\d+)(?:[:](\d+))?")
51 absimmre
= re
.compile(r
"[#]([sSuUm])(\d+)(?:[:](\d+))?")
53 finished_macros
= set()
56 def 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
)
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
)
70 # When qemu needs an attribute that isn't in the imported files,
72 def add_qemu_macro_attrib(name
, attrib
):
73 macros
[name
].attribs
.add(attrib
)
76 immextre
= re
.compile(r
"f(MUST_)?IMMEXT[(]([UuSsRr])")
79 def is_cond_jump(tag
):
82 if "A_HWLOOP0_END" in attribdict
[tag
] or "A_HWLOOP1_END" in attribdict
[tag
]:
84 return re
.compile(r
"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict
[tag
]) != None
87 def is_cond_call(tag
):
88 return re
.compile(r
"(if.*fCALL)").search(semdict
[tag
]) != None
91 def 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')
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
113 for macname
in allmacros_re
.findall(semdict
[tag
]):
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
121 if is_cond_jump(tag
) or is_cond_call(tag
):
122 attribdict
[tag
].add("A_CONDEXEC")
125 def SEMANTICS(tag
, beh
, sem
):
129 attribdict
[tag
] = set()
130 tags
.append(tag
) # dicts have no order, this is for order
133 def ATTRIBUTES(tag
, attribstring
):
134 attribstring
= attribstring
.replace("ATTRIBS", "").replace("(", "").replace(")", "")
137 attribs
= attribstring
.split(",")
138 for attrib
in attribs
:
139 attribdict
[tag
].add(attrib
.strip())
143 __slots__
= ["key", "name", "beh", "attribs", "re"]
145 def __init__(self
, name
, beh
, attribs
):
149 self
.attribs
= set(attribs
)
150 self
.re
= re
.compile("\\b" + name
+ "\\b")
153 def MACROATTRIB(macname
, beh
, attribstring
):
154 attribstring
= attribstring
.replace("(", "").replace(")", "")
156 attribs
= attribstring
.split(",")
159 macros
[macname
] = Macro(macname
, beh
, attribs
)
161 def compute_tag_regs(tag
, full
):
162 tagregs
= regre
.findall(behdict
[tag
])
164 tagregs
= map(lambda reg
: reg
[:2], tagregs
)
165 return uniquify(tagregs
)
167 def compute_tag_immediates(tag
):
168 return uniquify(immre
.findall(behdict
[tag
]))
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
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
192 def get_tagregs(full
=False):
193 compute_func
= lambda tag
: compute_tag_regs(tag
, full
)
194 return dict(zip(tags
, list(map(compute_func
, tags
))))
197 return dict(zip(tags
, list(map(compute_tag_immediates
, tags
))))
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
])
213 return re
.compile(r
"fPART1").search(semdict
[tag
])
217 return re
.compile(r
"\bEA\b").search(semdict
[tag
])
221 return "A_IMPLICIT_READS_PC" in attribdict
[tag
]
224 def need_next_PC(tag
):
225 return "A_CALL" in attribdict
[tag
]
228 def need_pkt_has_multi_cof(tag
):
229 return "A_COF" in attribdict
[tag
]
232 def need_pkt_need_commit(tag
):
233 return 'A_IMPLICIT_WRITES_USR' in attribdict
[tag
]
236 def skip_qemu_helper(tag
):
237 return tag
in overrides
.keys()
240 def is_idef_parser_enabled(tag
):
241 return tag
in idef_parser_enabled
244 def imm_name(immlett
):
245 return f
"{immlett}iV"
248 def read_semantics_file(name
):
250 for line
in open(name
, "rt").readlines():
251 if not line
.startswith("#"):
253 if line
.endswith("\\\n"):
254 eval_line
.rstrip("\\\n")
256 eval(eval_line
.strip())
260 def 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_\.]*)"\)'
265 for line
in open(name
, "rt").readlines():
266 if not attribre
.match(line
):
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
}
273 def 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
):
278 tag
= overridere
.findall(line
)[0]
279 overrides
[tag
] = True
282 def 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
)
289 def is_predicated(tag
):
290 return "A_CONDEXEC" in attribdict
[tag
]
294 return textwrap
.indent(textwrap
.dedent(txt
), " ")
298 if "A_CVI_NEW" in attribdict
[tag
]:
300 elif "A_CVI_TMP" in attribdict
[tag
] or "A_CVI_TMP_DST" in attribdict
[tag
]:
305 def 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"
309 return "ctx_future_vreg_off"
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
318 def __init__(self
, regtype
, regid
):
319 self
.regtype
= regtype
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}];
326 def idef_arg(self
, declared
):
327 declared
.append(self
.reg_tcg())
328 def helper_arg(self
):
330 self
.helper_proto_type(),
332 f
"{self.helper_arg_type()} {self.helper_arg_name()}"
336 # Every register is either Single or Pair or Hvx
339 def is_scalar_reg(self
):
341 def is_hvx_reg(self
):
343 def helper_arg_name(self
):
344 return self
.reg_tcg()
346 class Single(Scalar
):
347 def helper_proto_type(self
):
349 def helper_arg_type(self
):
353 def helper_proto_type(self
):
355 def helper_arg_type(self
):
359 def is_scalar_reg(self
):
361 def is_hvx_reg(self
):
364 return f
"{self.reg_tcg()}_off"
365 def helper_proto_type(self
):
367 def helper_arg_type(self
):
369 def helper_arg_name(self
):
370 return f
"{self.reg_tcg()}_void"
373 # Every register is either Dest or OldSource or NewSource or ReadWrite
377 return f
"{self.regtype}{self.regid}V"
378 def is_written(self
):
380 def is_writeonly(self
):
384 def is_readwrite(self
):
388 def is_written(self
):
390 def is_writeonly(self
):
394 def is_readwrite(self
):
397 class OldSource(Source
):
399 return f
"{self.regtype}{self.regid}V"
401 class NewSource(Source
):
403 return f
"{self.regtype}{self.regid}N"
407 return f
"{self.regtype}{self.regid}V"
408 def is_written(self
):
410 def is_writeonly(self
):
414 def is_readwrite(self
):
417 class 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});
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()});
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});
434 class 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}];
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});
446 class 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}]);
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});
457 class 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});
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}]);
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()});
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});
481 class 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;
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});
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()});
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});
502 class 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;
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()});
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});
519 class 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;
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];
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});
540 class 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();
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()});
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});
556 class 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}];
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});
568 class 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}]);
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});
579 class 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}]);
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()});
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});
596 class 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});
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()});
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});
614 class 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]);
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});
629 class 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]);
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()});
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});
650 class 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;
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});
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()});
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});
672 class 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;
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()});
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});
689 class 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);
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()});
701 def log_write(self
, f
, tag
):
703 def helper_hvx_desc(self
, f
):
704 f
.write(code_fmt(f
"""\
705 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
707 def analyze_write(self
, f
, tag
, regno
):
708 self
.decl_reg_num(f
, regno
)
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});
715 class 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});
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()});
726 def helper_hvx_desc(self
, f
):
727 f
.write(code_fmt(f
"""\
728 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
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});
736 class 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);
744 def helper_hvx_desc(self
, f
):
745 f
.write(code_fmt(f
"""\
746 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
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});
754 class 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));
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()});
769 def log_write(self
, f
, tag
):
771 def helper_hvx_desc(self
, f
):
772 f
.write(code_fmt(f
"""\
773 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
775 def analyze_write(self
, f
, tag
, regno
):
776 self
.decl_reg_num(f
, regno
)
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});
783 class 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);
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));
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},
802 def helper_hvx_desc(self
, f
):
803 f
.write(code_fmt(f
"""\
804 /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
806 def analyze_write(self
, f
, tag
, regno
):
807 self
.decl_reg_num(f
, regno
)
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});
814 class 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);
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()});
826 def log_write(self
, f
, tag
):
828 def helper_hvx_desc(self
, f
):
829 f
.write(code_fmt(f
"""\
830 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
832 def analyze_write(self
, f
, tag
, regno
):
833 self
.decl_reg_num(f
, regno
)
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});
840 class 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));
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()});
858 def helper_hvx_desc(self
, f
):
859 f
.write(code_fmt(f
"""\
860 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
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});
868 class 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));
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()});
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},
891 def helper_hvx_desc(self
, f
):
892 f
.write(code_fmt(f
"""\
893 /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
895 def analyze_write(self
, f
, tag
, regno
):
896 self
.decl_reg_num(f
, regno
)
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});
903 class 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});
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()});
915 def log_write(self
, f
, tag
):
917 def helper_hvx_desc(self
, f
):
918 f
.write(code_fmt(f
"""\
919 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
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});
927 class 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}]);
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()});
939 def helper_hvx_desc(self
, f
):
940 f
.write(code_fmt(f
"""\
941 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
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});
949 class 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));
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()});
964 def log_write(self
, f
, tag
):
966 def helper_hvx_desc(self
, f
):
967 f
.write(code_fmt(f
"""\
968 /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
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});
976 def init_registers():
984 GprReadWrite("R", "x"),
985 GprReadWrite("R", "y"),
986 ControlDest("C", "d"),
987 ControlSource("C", "s"),
988 ModifierSource("M", "u"),
991 PredSource("P", "s"),
992 PredSource("P", "t"),
993 PredSource("P", "u"),
994 PredSource("P", "v"),
995 PredReadWrite("P", "x"),
998 PairSource("R", "ss"),
999 PairSource("R", "tt"),
1000 PairReadWrite("R", "xx"),
1001 PairReadWrite("R", "yy"),
1002 ControlPairDest("C", "dd"),
1003 ControlPairSource("C", "ss"),
1005 VRegSource("V", "s"),
1006 VRegSource("V", "u"),
1007 VRegSource("V", "v"),
1008 VRegSource("V", "w"),
1009 VRegReadWrite("V", "x"),
1011 VRegPairDest("V", "dd"),
1012 VRegPairSource("V", "uu"),
1013 VRegPairSource("V", "vv"),
1014 VRegPairReadWrite("V", "xx"),
1017 QRegSource("Q", "s"),
1018 QRegSource("Q", "t"),
1019 QRegSource("Q", "u"),
1020 QRegSource("Q", "v"),
1021 QRegReadWrite("Q", "x"),
1024 registers
[f
"{reg.regtype}{reg.regid}"] = reg
1027 GprNewSource("N", "s"),
1028 GprNewSource("N", "t"),
1029 PredNewSource("P", "t"),
1030 PredNewSource("P", "u"),
1031 PredNewSource("P", "v"),
1032 VRegNewSource("O", "s"),
1034 for reg
in new_regs
:
1035 new_registers
[f
"{reg.regtype}{reg.regid}"] = reg
1037 def get_register(tag
, regtype
, regid
):
1038 if f
"{regtype}{regid}V" in semdict
[tag
]:
1039 return registers
[f
"{regtype}{regid}"]
1041 return new_registers
[f
"{regtype}{regid}"]
1043 def 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(),
1053 reg
.helper_arg_type()
1055 if numscalarresults
> 1:
1056 raise Exception("numscalarresults > 1")
1059 def helper_args(tag
, regs
, imms
):
1062 ## First argument is the CPU state
1063 args
.append(HelperArg(
1066 "CPUHexagonState *env"
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())
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())
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())
1088 ## Pass the immediates
1089 for immlett
, bits
, immshift
in imms
:
1090 args
.append(HelperArg(
1092 f
"tcg_constant_tl({imm_name(immlett)})",
1093 f
"int32_t {imm_name(immlett)}"
1096 ## Other stuff the helper might need
1097 if need_pkt_has_multi_cof(tag
):
1098 args
.append(HelperArg(
1100 "tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
1101 "uint32_t pkt_has_multi_cof"
1103 if need_pkt_need_commit(tag
):
1104 args
.append(HelperArg(
1106 "tcg_constant_tl(ctx->need_commit)",
1107 "uint32_t pkt_need_commit"
1110 args
.append(HelperArg(
1112 "tcg_constant_tl(ctx->pkt->pc)",
1115 if need_next_PC(tag
):
1116 args
.append(HelperArg(
1118 "tcg_constant_tl(ctx->next_PC)",
1119 "target_ulong next_PC"
1122 args
.append(HelperArg(
1128 args
.append(HelperArg(
1130 "tcg_constant_tl(insn->part1)"