diff --git a/target/hexagon/README b/target/hexagon/README index 746ebec378..7ffd517d70 100644 --- a/target/hexagon/README +++ b/target/hexagon/README @@ -43,11 +43,9 @@ target/hexagon/gen_semantics.c. This step produces That file is consumed by the following python scripts to produce the indicated header files in /target/hexagon gen_opcodes_def.py -> opcodes_def_generated.h.inc - gen_op_regs.py -> op_regs_generated.h.inc gen_printinsn.py -> printinsn_generated.h.inc gen_op_attribs.py -> op_attribs_generated.h.inc gen_helper_protos.py -> helper_protos_generated.h.inc - gen_shortcode.py -> shortcode_generated.h.inc gen_tcg_funcs.py -> tcg_funcs_generated.c.inc gen_tcg_func_table.py -> tcg_func_table_generated.c.inc gen_helper_funcs.py -> helper_funcs_generated.c.inc @@ -183,10 +181,11 @@ when the override is present. } We also generate an analyze_ function for each instruction. Currently, -these functions record the writes to registers by calling ctx_log_*. During -gen_start_packet, we invoke the analyze_ function for each instruction in -the packet, and we mark the implicit writes. After the analysis is performed, -we initialize the result register for each of the predicated assignments. +these functions record the reads and writes to registers by calling ctx_log_*. +During gen_start_packet, we invoke the analyze_ function for each instruction in +the packet, and we mark the implicit writes. The analysis determines if the packet +semantics can be short-circuited. If not, we initialize the result register for each +of the predicated assignments. In addition to instruction semantics, we use a generator to create the decode tree. This generation is a four step process. diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc index 87942d46f4..9e3a05f882 100644 --- a/target/hexagon/attribs_def.h.inc +++ b/target/hexagon/attribs_def.h.inc @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -117,6 +117,7 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", "") DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "") DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "") DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "") +DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "") DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "") DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "") DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "") diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c index a40210ca1e..23deba2426 100644 --- a/target/hexagon/decode.c +++ b/target/hexagon/decode.c @@ -115,22 +115,13 @@ static void decode_fill_newvalue_regno(Packet *packet) { int i, use_regidx, offset, def_idx, dst_idx; - uint16_t def_opcode, use_opcode; - char *dststr; for (i = 1; i < packet->num_insns; i++) { if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) && !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) { - use_opcode = packet->insn[i].opcode; - /* It's a store, so we're adjusting the Nt field */ - if (GET_ATTRIB(use_opcode, A_STORE)) { - use_regidx = strchr(opcode_reginfo[use_opcode], 't') - - opcode_reginfo[use_opcode]; - } else { /* It's a Jump, so we're adjusting the Ns field */ - use_regidx = strchr(opcode_reginfo[use_opcode], 's') - - opcode_reginfo[use_opcode]; - } + g_assert(packet->insn[i].new_read_idx != -1); + use_regidx = packet->insn[i].new_read_idx; /* * What's encoded at the N-field is the offset to who's producing @@ -151,37 +142,9 @@ decode_fill_newvalue_regno(Packet *packet) */ g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1)))); - /* - * packet->insn[def_idx] is the producer - * Figure out which type of destination it produces - * and the corresponding index in the reginfo - */ - def_opcode = packet->insn[def_idx].opcode; - dststr = strstr(opcode_wregs[def_opcode], "Rd"); - if (dststr) { - dststr = strchr(opcode_reginfo[def_opcode], 'd'); - } else { - dststr = strstr(opcode_wregs[def_opcode], "Rx"); - if (dststr) { - dststr = strchr(opcode_reginfo[def_opcode], 'x'); - } else { - dststr = strstr(opcode_wregs[def_opcode], "Re"); - if (dststr) { - dststr = strchr(opcode_reginfo[def_opcode], 'e'); - } else { - dststr = strstr(opcode_wregs[def_opcode], "Ry"); - if (dststr) { - dststr = strchr(opcode_reginfo[def_opcode], 'y'); - } else { - g_assert_not_reached(); - } - } - } - } - g_assert(dststr != NULL); - /* Now patch up the consumer with the register number */ - dst_idx = dststr - opcode_reginfo[def_opcode]; + g_assert(packet->insn[def_idx].dest_idx != -1); + dst_idx = packet->insn[def_idx].dest_idx; packet->insn[i].regno[use_regidx] = packet->insn[def_idx].regno[dst_idx]; /* @@ -362,8 +325,7 @@ static void decode_shuffle_for_execution(Packet *packet) for (flag = false, i = 0; i < last_insn + 1; i++) { int opcode = packet->insn[i].opcode; - if ((strstr(opcode_wregs[opcode], "Pd4") || - strstr(opcode_wregs[opcode], "Pe4")) && + if (packet->insn[i].has_pred_dest && GET_ATTRIB(opcode, A_STORE) == 0) { /* This should be a compare (not a store conditional) */ if (flag) { diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py index a9af666cef..54bac19724 100755 --- a/target/hexagon/gen_analyze_funcs.py +++ b/target/hexagon/gen_analyze_funcs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2022-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -43,59 +43,53 @@ def gen_analyze_func(f, tag, regs, imms): f.write("{\n") f.write(" Insn *insn G_GNUC_UNUSED = ctx->insn;\n") - - i = 0 - ## Analyze all the registers - for regtype, regid in regs: - reg = hex_common.get_register(tag, regtype, regid) - if reg.is_written(): - reg.analyze_write(f, tag, i) + if (hex_common.is_hvx_insn(tag)): + if hex_common.has_hvx_helper(tag): + f.write( + " const bool G_GNUC_UNUSED insn_has_hvx_helper = true;\n" + ) + f.write(" ctx_start_hvx_insn(ctx);\n") else: - reg.analyze_read(f, i) - i += 1 + f.write( + " const bool G_GNUC_UNUSED insn_has_hvx_helper = false;\n" + ) - has_generated_helper = not hex_common.skip_qemu_helper( - tag - ) and not hex_common.is_idef_parser_enabled(tag) + ## Declare all the registers + for regno, register in enumerate(regs): + reg_type, reg_id = register + reg = hex_common.get_register(tag, reg_type, reg_id) + reg.decl_reg_num(f, regno) - ## Mark HVX instructions with generated helpers - if (has_generated_helper and - "A_CVI" in hex_common.attribdict[tag]): - f.write(" ctx->has_hvx_helper = true;\n") + ## Analyze the register reads + for regno, register in enumerate(regs): + reg_type, reg_id = register + reg = hex_common.get_register(tag, reg_type, reg_id) + if reg.is_read(): + reg.analyze_read(f, regno) + + ## Analyze the register writes + for regno, register in enumerate(regs): + reg_type, reg_id = register + reg = hex_common.get_register(tag, reg_type, reg_id) + if reg.is_written(): + reg.analyze_write(f, tag, regno) f.write("}\n\n") def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.read_overrides_file(sys.argv[3]) - hex_common.read_overrides_file(sys.argv[4]) - ## Whether or not idef-parser is enabled is - ## determined by the number of arguments to - ## this script: - ## - ## 5 args. -> not enabled, - ## 6 args. -> idef-parser enabled. - ## - ## The 6:th arg. then holds a list of the successfully - ## parsed instructions. - is_idef_parser_enabled = len(sys.argv) > 6 - if is_idef_parser_enabled: - hex_common.read_idef_parser_enabled_file(sys.argv[5]) - hex_common.calculate_attribs() - hex_common.init_registers() + hex_common.read_common_files() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() with open(sys.argv[-1], "w") as f: - f.write("#ifndef HEXAGON_TCG_FUNCS_H\n") - f.write("#define HEXAGON_TCG_FUNCS_H\n\n") + f.write("#ifndef HEXAGON_ANALYZE_FUNCS_C_INC\n") + f.write("#define HEXAGON_ANALYZE_FUNCS_C_INC\n\n") for tag in hex_common.tags: gen_analyze_func(f, tag, tagregs[tag], tagimms[tag]) - f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n") + f.write("#endif /* HEXAGON_ANALYZE_FUNCS_C_INC */\n") if __name__ == "__main__": diff --git a/target/hexagon/gen_helper_funcs.py b/target/hexagon/gen_helper_funcs.py index 9cc3d69c49..e9685bff2f 100755 --- a/target/hexagon/gen_helper_funcs.py +++ b/target/hexagon/gen_helper_funcs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -102,24 +102,7 @@ def gen_helper_function(f, tag, tagregs, tagimms): def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.read_overrides_file(sys.argv[3]) - hex_common.read_overrides_file(sys.argv[4]) - ## Whether or not idef-parser is enabled is - ## determined by the number of arguments to - ## this script: - ## - ## 5 args. -> not enabled, - ## 6 args. -> idef-parser enabled. - ## - ## The 6:th arg. then holds a list of the successfully - ## parsed instructions. - is_idef_parser_enabled = len(sys.argv) > 6 - if is_idef_parser_enabled: - hex_common.read_idef_parser_enabled_file(sys.argv[5]) - hex_common.calculate_attribs() - hex_common.init_registers() + hex_common.read_common_files() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() diff --git a/target/hexagon/gen_helper_protos.py b/target/hexagon/gen_helper_protos.py index c82b0f54e4..fd2bfd0f36 100755 --- a/target/hexagon/gen_helper_protos.py +++ b/target/hexagon/gen_helper_protos.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -40,28 +40,19 @@ def gen_helper_prototype(f, tag, tagregs, tagimms): declared.append(arg.proto_arg) arguments = ", ".join(declared) - f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n") + + ## Add the TCG_CALL_NO_RWG_SE flag to helpers that don't take the env + ## argument and aren't HVX instructions. Since HVX instructions take + ## pointers to their arguments, they will have side effects. + if hex_common.need_env(tag) or hex_common.is_hvx_insn(tag): + f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n") + else: + f.write(f"DEF_HELPER_FLAGS_{len(declared) - 1}({tag}, " + f"TCG_CALL_NO_RWG_SE, {arguments})\n") def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.read_overrides_file(sys.argv[3]) - hex_common.read_overrides_file(sys.argv[4]) - ## Whether or not idef-parser is enabled is - ## determined by the number of arguments to - ## this script: - ## - ## 5 args. -> not enabled, - ## 6 args. -> idef-parser enabled. - ## - ## The 6:th arg. then holds a list of the successfully - ## parsed instructions. - is_idef_parser_enabled = len(sys.argv) > 6 - if is_idef_parser_enabled: - hex_common.read_idef_parser_enabled_file(sys.argv[5]) - hex_common.calculate_attribs() - hex_common.init_registers() + hex_common.read_common_files() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_idef_parser_funcs.py index 550a48cb7b..eb494abba8 100644 --- a/target/hexagon/gen_idef_parser_funcs.py +++ b/target/hexagon/gen_idef_parser_funcs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved. +## Copyright(c) 2019-2024 rev.ng Labs Srl. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -44,13 +44,12 @@ import hex_common ## def main(): hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) hex_common.calculate_attribs() hex_common.init_registers() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() - with open(sys.argv[3], "w") as f: + with open(sys.argv[-1], "w") as f: f.write('#include "macros.inc"\n\n') for tag in hex_common.tags: diff --git a/target/hexagon/gen_op_attribs.py b/target/hexagon/gen_op_attribs.py index 41074b8573..99448220da 100755 --- a/target/hexagon/gen_op_attribs.py +++ b/target/hexagon/gen_op_attribs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -25,13 +25,12 @@ import hex_common def main(): hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) hex_common.calculate_attribs() ## ## Generate all the attributes associated with each instruction ## - with open(sys.argv[3], "w") as f: + with open(sys.argv[-1], "w") as f: for tag in hex_common.tags: f.write( f"OP_ATTRIB({tag},ATTRIBS(" diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py deleted file mode 100755 index 7b7b33895a..0000000000 --- a/target/hexagon/gen_op_regs.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 - -## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, see . -## - -import sys -import re -import string -import hex_common - - -## -## Generate the register and immediate operands for each instruction -## -def calculate_regid_reg(tag): - def letter_inc(x): - return chr(ord(x) + 1) - - ordered_implregs = ["SP", "FP", "LR"] - srcdst_lett = "X" - src_lett = "S" - dst_lett = "D" - retstr = "" - mapdict = {} - for reg in ordered_implregs: - reg_rd = 0 - reg_wr = 0 - if ("A_IMPLICIT_WRITES_" + reg) in hex_common.attribdict[tag]: - reg_wr = 1 - if reg_rd and reg_wr: - retstr += srcdst_lett - mapdict[srcdst_lett] = reg - srcdst_lett = letter_inc(srcdst_lett) - elif reg_rd: - retstr += src_lett - mapdict[src_lett] = reg - src_lett = letter_inc(src_lett) - elif reg_wr: - retstr += dst_lett - mapdict[dst_lett] = reg - dst_lett = letter_inc(dst_lett) - return retstr, mapdict - - -def calculate_regid_letters(tag): - retstr, mapdict = calculate_regid_reg(tag) - return retstr - - -def strip_reg_prefix(x): - y = x.replace("UREG.", "") - y = y.replace("MREG.", "") - return y.replace("GREG.", "") - - -def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.init_registers() - tagregs = hex_common.get_tagregs(full=True) - tagimms = hex_common.get_tagimms() - - with open(sys.argv[3], "w") as f: - for tag in hex_common.tags: - regs = tagregs[tag] - rregs = [] - wregs = [] - regids = "" - for regtype, regid, _, numregs in regs: - reg = hex_common.get_register(tag, regtype, regid) - if reg.is_read(): - if regid[0] not in regids: - regids += regid[0] - rregs.append(regtype + regid + numregs) - if reg.is_written(): - wregs.append(regtype + regid + numregs) - if regid[0] not in regids: - regids += regid[0] - for attrib in hex_common.attribdict[tag]: - if hex_common.attribinfo[attrib]["rreg"]: - rregs.append(strip_reg_prefix(attribinfo[attrib]["rreg"])) - if hex_common.attribinfo[attrib]["wreg"]: - wregs.append(strip_reg_prefix(attribinfo[attrib]["wreg"])) - regids += calculate_regid_letters(tag) - f.write( - f'REGINFO({tag},"{regids}",\t/*RD:*/\t"{",".join(rregs)}",' - f'\t/*WR:*/\t"{",".join(wregs)}")\n' - ) - - for tag in hex_common.tags: - imms = tagimms[tag] - f.write(f"IMMINFO({tag}") - if not imms: - f.write(""",'u',0,0,'U',0,0""") - for sign, size, shamt in imms: - if sign == "r": - sign = "s" - if not shamt: - shamt = "0" - f.write(f""",'{sign}',{size},{shamt}""") - if len(imms) == 1: - if sign.isupper(): - myu = "u" - else: - myu = "U" - f.write(f""",'{myu}',0,0""") - f.write(")\n") - - -if __name__ == "__main__": - main() diff --git a/target/hexagon/gen_opcodes_def.py b/target/hexagon/gen_opcodes_def.py index cddd868fe3..536f0eb68a 100755 --- a/target/hexagon/gen_opcodes_def.py +++ b/target/hexagon/gen_opcodes_def.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ def main(): ## ## Generate a list of all the opcodes ## - with open(sys.argv[3], "w") as f: + with open(sys.argv[-1], "w") as f: for tag in hex_common.tags: f.write(f"OPCODE({tag}),\n") diff --git a/target/hexagon/gen_printinsn.py b/target/hexagon/gen_printinsn.py index e570bd7c6a..8bf4d0985c 100755 --- a/target/hexagon/gen_printinsn.py +++ b/target/hexagon/gen_printinsn.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -97,11 +97,10 @@ def spacify(s): def main(): hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) immext_casere = re.compile(r"IMMEXT\(([A-Za-z])") - with open(sys.argv[3], "w") as f: + with open(sys.argv[-1], "w") as f: for tag in hex_common.tags: if not hex_common.behdict[tag]: continue diff --git a/target/hexagon/gen_shortcode.py b/target/hexagon/gen_shortcode.py deleted file mode 100755 index deb94446c4..0000000000 --- a/target/hexagon/gen_shortcode.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 - -## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, see . -## - -import sys -import re -import string -import hex_common - - -def gen_shortcode(f, tag): - f.write(f"DEF_SHORTCODE({tag}, {hex_common.semdict[tag]})\n") - - -def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.calculate_attribs() - tagregs = hex_common.get_tagregs() - tagimms = hex_common.get_tagimms() - - with open(sys.argv[3], "w") as f: - f.write("#ifndef DEF_SHORTCODE\n") - f.write("#define DEF_SHORTCODE(TAG,SHORTCODE) /* Nothing */\n") - f.write("#endif\n") - - for tag in hex_common.tags: - ## Skip the priv instructions - if "A_PRIV" in hex_common.attribdict[tag]: - continue - ## Skip the guest instructions - if "A_GUEST" in hex_common.attribdict[tag]: - continue - ## Skip the diag instructions - if tag == "Y6_diag": - continue - if tag == "Y6_diag0": - continue - if tag == "Y6_diag1": - continue - - gen_shortcode(f, tag) - - f.write("#undef DEF_SHORTCODE\n") - - -if __name__ == "__main__": - main() diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h index 1c4391b415..3fc1f4e281 100644 --- a/target/hexagon/gen_tcg.h +++ b/target/hexagon/gen_tcg.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1369,3 +1369,6 @@ gen_helper_raise_exception(tcg_env, excp); \ } while (0) #endif + +#define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0) +#define fGEN_TCG_SA1_setin1(SHORTCODE) tcg_gen_movi_tl(RdV, -1) diff --git a/target/hexagon/gen_tcg_func_table.py b/target/hexagon/gen_tcg_func_table.py index f998ef0992..978ac1819b 100755 --- a/target/hexagon/gen_tcg_func_table.py +++ b/target/hexagon/gen_tcg_func_table.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -25,12 +25,11 @@ import hex_common def main(): hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) hex_common.calculate_attribs() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() - with open(sys.argv[3], "w") as f: + with open(sys.argv[-1], "w") as f: f.write("#ifndef HEXAGON_FUNC_TABLE_H\n") f.write("#define HEXAGON_FUNC_TABLE_H\n\n") diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py index 3d8e3cb6a2..05aa0a7855 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -108,24 +108,7 @@ def gen_def_tcg_func(f, tag, tagregs, tagimms): def main(): - hex_common.read_semantics_file(sys.argv[1]) - hex_common.read_attribs_file(sys.argv[2]) - hex_common.read_overrides_file(sys.argv[3]) - hex_common.read_overrides_file(sys.argv[4]) - hex_common.calculate_attribs() - hex_common.init_registers() - ## Whether or not idef-parser is enabled is - ## determined by the number of arguments to - ## this script: - ## - ## 5 args. -> not enabled, - ## 6 args. -> idef-parser enabled. - ## - ## The 6:th arg. then holds a list of the successfully - ## parsed instructions. - is_idef_parser_enabled = len(sys.argv) > 6 - if is_idef_parser_enabled: - hex_common.read_idef_parser_enabled_file(sys.argv[5]) + is_idef_parser_enabled = hex_common.read_common_files() tagregs = hex_common.get_tagregs() tagimms = hex_common.get_tagimms() diff --git a/target/hexagon/gen_trans_funcs.py b/target/hexagon/gen_trans_funcs.py index 53e844a44b..9f86b4edbd 100755 --- a/target/hexagon/gen_trans_funcs.py +++ b/target/hexagon/gen_trans_funcs.py @@ -68,6 +68,9 @@ def mark_which_imm_extended(f, tag): ## insn->regno[0] = args->Rd; ## insn->regno[1] = args->Rs; ## insn->regno[2] = args->Rt; +## insn->new_read_idx = -1; +## insn->dest_idx = 0; +## insn->has_pred_dest = false; ## return true; ## } ## @@ -84,14 +87,21 @@ def gen_trans_funcs(f): insn->opcode = {tag}; """)) - regno = 0 - for reg in regs: - reg_type = reg[0] - reg_id = reg[1] + new_read_idx = -1 + dest_idx = -1 + has_pred_dest = "false" + for regno, (reg_type, reg_id, *_) in enumerate(regs): + reg = hex_common.get_register(tag, reg_type, reg_id) f.write(code_fmt(f"""\ insn->regno[{regno}] = args->{reg_type}{reg_id}; """)) - regno += 1 + if reg.is_read() and reg.is_new(): + new_read_idx = regno + # dest_idx should be the first destination, so check for -1 + if reg.is_written() and dest_idx == -1: + dest_idx = regno + if reg_type == "P" and reg.is_written() and not reg.is_read(): + has_pred_dest = "true" if len(imms) != 0: mark_which_imm_extended(f, tag) @@ -112,6 +122,11 @@ def gen_trans_funcs(f): insn->immed[{immno}] = args->{imm_type}{imm_letter}; """)) + f.write(code_fmt(f"""\ + insn->new_read_idx = {new_read_idx}; + insn->dest_idx = {dest_idx}; + insn->has_pred_dest = {has_pred_dest}; + """)) f.write(textwrap.dedent(f"""\ return true; {close_curly} @@ -120,5 +135,6 @@ def gen_trans_funcs(f): if __name__ == "__main__": hex_common.read_semantics_file(sys.argv[1]) + hex_common.init_registers() with open(sys.argv[2], "w") as f: gen_trans_funcs(f) diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py index 195620c7ec..15ed4980e4 100755 --- a/target/hexagon/hex_common.py +++ b/target/hexagon/hex_common.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -26,7 +26,6 @@ behdict = {} # tag ->behavior semdict = {} # tag -> semantics attribdict = {} # tag -> attributes macros = {} # macro -> macro information... -attribinfo = {} # Register information and misc registers = {} # register -> register functions new_registers = {} tags = [] # list of all tags @@ -101,6 +100,7 @@ def calculate_attribs(): add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1') add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1') add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3') + add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP') # Recurse down macros, find attributes from sub-macros macroValues = list(macros.values()) @@ -197,6 +197,26 @@ def get_tagimms(): return dict(zip(tags, list(map(compute_tag_immediates, tags)))) +def need_p0(tag): + return "A_IMPLICIT_READS_P0" in attribdict[tag] + + +def need_sp(tag): + return "A_IMPLICIT_READS_SP" in attribdict[tag] + + +def is_hvx_insn(tag): + return "A_CVI" in attribdict[tag] + + +def need_env(tag): + return ("A_STORE" in attribdict[tag] or + "A_LOAD" in attribdict[tag] or + "A_CVI_GATHER" in attribdict[tag] or + "A_CVI_SCATTER" in attribdict[tag] or + "A_IMPLICIT_WRITES_USR" in attribdict[tag]) + + def need_slot(tag): if ( "A_CVI_SCATTER" not in attribdict[tag] @@ -241,6 +261,16 @@ def is_idef_parser_enabled(tag): return tag in idef_parser_enabled +def is_hvx_insn(tag): + return "A_CVI" in attribdict[tag] + + +def has_hvx_helper(tag): + return (is_hvx_insn(tag) and + not skip_qemu_helper(tag) and + not is_idef_parser_enabled(tag)) + + def imm_name(immlett): return f"{immlett}iV" @@ -257,19 +287,6 @@ def read_semantics_file(name): eval_line = "" -def read_attribs_file(name): - attribre = re.compile( - r"DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), " - + r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)' - ) - for line in open(name, "rt").readlines(): - if not attribre.match(line): - continue - (attrib_base, descr, rreg, wreg) = attribre.findall(line)[0] - attrib_base = "A_" + attrib_base - attribinfo[attrib_base] = {"rreg": rreg, "wreg": wreg, "descr": descr} - - def read_overrides_file(name): overridere = re.compile(r"#define fGEN_TCG_([A-Za-z0-9_]+)\(.*") for line in open(name, "rt").readlines(): @@ -397,10 +414,18 @@ class Source: class OldSource(Source): def reg_tcg(self): return f"{self.regtype}{self.regid}V" + def is_old(self): + return True + def is_new(self): + return False class NewSource(Source): def reg_tcg(self): return f"{self.regtype}{self.regid}N" + def is_old(self): + return False + def is_new(self): + return True class ReadWrite: def reg_tcg(self): @@ -413,6 +438,10 @@ class ReadWrite: return True def is_readwrite(self): return True + def is_old(self): + return True + def is_new(self): + return False class GprDest(Register, Single, Dest): def decl_tcg(self, f, tag, regno): @@ -425,7 +454,6 @@ class GprDest(Register, Single, Dest): gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); @@ -438,7 +466,6 @@ class GprSource(Register, Single, OldSource): TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}]; """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_reg_read(ctx, {self.reg_num}); """)) @@ -449,9 +476,8 @@ class GprNewSource(Register, Single, NewSource): TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]); """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_reg_read(ctx, {self.reg_num}); + ctx_log_reg_read_new(ctx, {self.reg_num}); """)) class GprReadWrite(Register, Single, ReadWrite): @@ -471,8 +497,11 @@ class GprReadWrite(Register, Single, ReadWrite): f.write(code_fmt(f"""\ gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()}); """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_reg_read(ctx, {self.reg_num}); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); @@ -493,7 +522,6 @@ class ControlDest(Register, Single, Dest): gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write(ctx, {self.reg_num}, {predicated}); @@ -511,7 +539,6 @@ class ControlSource(Register, Single, OldSource): gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_reg_read(ctx, {self.reg_num}); """)) @@ -532,7 +559,6 @@ class ModifierSource(Register, Single, OldSource): declared.append(self.reg_tcg()) declared.append("CS") def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_reg_read(ctx, {self.reg_num}); """)) @@ -548,7 +574,6 @@ class PredDest(Register, Single, Dest): gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_pred_write(ctx, {self.reg_num}); """)) @@ -560,7 +585,6 @@ class PredSource(Register, Single, OldSource): TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}]; """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_pred_read(ctx, {self.reg_num}); """)) @@ -571,9 +595,8 @@ class PredNewSource(Register, Single, NewSource): TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]); """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_pred_read(ctx, {self.reg_num}); + ctx_log_pred_read_new(ctx, {self.reg_num}); """)) class PredReadWrite(Register, Single, ReadWrite): @@ -587,8 +610,11 @@ class PredReadWrite(Register, Single, ReadWrite): f.write(code_fmt(f"""\ gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()}); """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_pred_read(ctx, {self.reg_num}); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_pred_write(ctx, {self.reg_num}); """)) @@ -605,7 +631,6 @@ class PairDest(Register, Pair, Dest): gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); @@ -621,7 +646,6 @@ class PairSource(Register, Pair, OldSource): hex_gpr[{self.reg_num} + 1]); """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_reg_read_pair(ctx, {self.reg_num}); """)) @@ -640,8 +664,11 @@ class PairReadWrite(Register, Pair, ReadWrite): f.write(code_fmt(f"""\ gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()}); """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_reg_read_pair(ctx, {self.reg_num}); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); @@ -663,7 +690,6 @@ class ControlPairDest(Register, Pair, Dest): gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated}); @@ -681,7 +707,6 @@ class ControlPairSource(Register, Pair, OldSource): gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()}); """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ ctx_log_reg_read_pair(ctx, {self.reg_num}); """)) @@ -705,11 +730,11 @@ class VRegDest(Register, Hvx, Dest): /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) newv = hvx_newv(tag) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ - ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); + ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, + insn_has_hvx_helper); """)) class VRegSource(Register, Hvx, OldSource): @@ -728,9 +753,8 @@ class VRegSource(Register, Hvx, OldSource): /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_vreg_read(ctx, {self.reg_num}); + ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); """)) class VRegNewSource(Register, Hvx, NewSource): @@ -746,9 +770,8 @@ class VRegNewSource(Register, Hvx, NewSource): /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_vreg_read(ctx, {self.reg_num}); + ctx_log_vreg_read_new(ctx, {self.reg_num}, insn_has_hvx_helper); """)) class VRegReadWrite(Register, Hvx, ReadWrite): @@ -772,12 +795,16 @@ class VRegReadWrite(Register, Hvx, ReadWrite): f.write(code_fmt(f"""\ /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) newv = hvx_newv(tag) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ - ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); + ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, + insn_has_hvx_helper); """)) class VRegTmp(Register, Hvx, ReadWrite): @@ -803,12 +830,16 @@ class VRegTmp(Register, Hvx, ReadWrite): f.write(code_fmt(f"""\ /* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */ """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_vreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) newv = hvx_newv(tag) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ - ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}); + ctx_log_vreg_write(ctx, {self.reg_num}, {newv}, {predicated}, + insn_has_hvx_helper); """)) class VRegPairDest(Register, Hvx, Dest): @@ -830,11 +861,11 @@ class VRegPairDest(Register, Hvx, Dest): /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) newv = hvx_newv(tag) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ - ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}); + ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, + insn_has_hvx_helper); """)) class VRegPairSource(Register, Hvx, OldSource): @@ -860,9 +891,8 @@ class VRegPairSource(Register, Hvx, OldSource): /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_vreg_read_pair(ctx, {self.reg_num}); + ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); """)) class VRegPairReadWrite(Register, Hvx, ReadWrite): @@ -892,12 +922,16 @@ class VRegPairReadWrite(Register, Hvx, ReadWrite): f.write(code_fmt(f"""\ /* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */ """)) + def analyze_read(self, f, regno): + f.write(code_fmt(f"""\ + ctx_log_vreg_read_pair(ctx, {self.reg_num}, insn_has_hvx_helper); + """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) newv = hvx_newv(tag) predicated = "true" if is_predicated(tag) else "false" f.write(code_fmt(f"""\ - ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}); + ctx_log_vreg_write_pair(ctx, {self.reg_num}, {newv}, {predicated}, + insn_has_hvx_helper); """)) class QRegDest(Register, Hvx, Dest): @@ -919,9 +953,8 @@ class QRegDest(Register, Hvx, Dest): /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ """)) def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_qreg_write(ctx, {self.reg_num}); + ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); """)) class QRegSource(Register, Hvx, OldSource): @@ -941,9 +974,8 @@ class QRegSource(Register, Hvx, OldSource): /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ """)) def analyze_read(self, f, regno): - self.decl_reg_num(f, regno) f.write(code_fmt(f"""\ - ctx_log_qreg_read(ctx, {self.reg_num}); + ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); """)) class QRegReadWrite(Register, Hvx, ReadWrite): @@ -967,10 +999,13 @@ class QRegReadWrite(Register, Hvx, ReadWrite): f.write(code_fmt(f"""\ /* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */ """)) - def analyze_write(self, f, tag, regno): - self.decl_reg_num(f, regno) + def analyze_read(self, f, regno): f.write(code_fmt(f"""\ - ctx_log_qreg_write(ctx, {self.reg_num}); + ctx_log_qreg_read(ctx, {self.reg_num}, insn_has_hvx_helper); + """)) + def analyze_write(self, f, tag, regno): + f.write(code_fmt(f"""\ + ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper); """)) def init_registers(): @@ -1060,11 +1095,12 @@ def helper_args(tag, regs, imms): args = [] ## First argument is the CPU state - args.append(HelperArg( - "env", - "tcg_env", - "CPUHexagonState *env" - )) + if need_env(tag): + args.append(HelperArg( + "env", + "tcg_env", + "CPUHexagonState *env" + )) ## For predicated instructions, we pass in the destination register if is_predicated(tag): @@ -1118,6 +1154,18 @@ def helper_args(tag, regs, imms): "tcg_constant_tl(ctx->next_PC)", "target_ulong next_PC" )) + if need_p0(tag): + args.append(HelperArg( + "i32", + "hex_pred[0]", + "uint32_t P0" + )) + if need_sp(tag): + args.append(HelperArg( + "i32", + "hex_gpr[HEX_REG_SP]", + "uint32_t SP" + )) if need_slot(tag): args.append(HelperArg( "i32", @@ -1131,3 +1179,24 @@ def helper_args(tag, regs, imms): "uint32_t part1" )) return args + + +def read_common_files(): + read_semantics_file(sys.argv[1]) + read_overrides_file(sys.argv[2]) + read_overrides_file(sys.argv[3]) + ## Whether or not idef-parser is enabled is + ## determined by the number of arguments to + ## this script: + ## + ## 4 args. -> not enabled, + ## 5 args. -> idef-parser enabled. + ## + ## The 5:th arg. then holds a list of the successfully + ## parsed instructions. + is_idef_parser_enabled = len(sys.argv) > 5 + if is_idef_parser_enabled: + read_idef_parser_enabled_file(sys.argv[4]) + calculate_attribs() + init_registers() + return is_idef_parser_enabled diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h index 3e7a22c91e..24dcf7fe9f 100644 --- a/target/hexagon/insn.h +++ b/target/hexagon/insn.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,6 +39,9 @@ struct Instruction { uint32_t slot:3; uint32_t which_extended:1; /* If has an extender, which immediate */ uint32_t new_value_producer_slot:4; + int32_t new_read_idx; + int32_t dest_idx; + bool has_pred_dest; bool part1; /* * cmp-jumps are split into two insns. diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index 1376d6ccc1..feb798c6c0 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -343,7 +343,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift) #define fREAD_LR() (env->gpr[HEX_REG_LR]) -#define fREAD_SP() (env->gpr[HEX_REG_SP]) +#define fREAD_SP() (SP) #define fREAD_LC0 (env->gpr[HEX_REG_LC0]) #define fREAD_LC1 (env->gpr[HEX_REG_LC1]) #define fREAD_SA0 (env->gpr[HEX_REG_SA0]) @@ -358,7 +358,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift) #endif #define fREAD_PC() (PC) -#define fREAD_P0() (env->pred[0]) +#define fREAD_P0() (P0) #define fCHECK_PCALIGN(A) diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index fb480afc03..b0b253aa6b 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -1,5 +1,5 @@ ## -## Copyright(c) 2020-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2020-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -18,7 +18,6 @@ hexagon_ss = ss.source_set() hex_common_py = 'hex_common.py' -attribs_def = meson.current_source_dir() / 'attribs_def.h.inc' gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h' gen_tcg_hvx_h = meson.current_source_dir() / 'gen_tcg_hvx.h' idef_parser_dir = meson.current_source_dir() / 'idef-parser' @@ -42,28 +41,17 @@ hexagon_ss.add(semantics_generated) # # Step 2 # We use Python scripts to generate the following files -# shortcode_generated.h.inc # tcg_func_table_generated.c.inc # printinsn_generated.h.inc -# op_regs_generated.h.inc # op_attribs_generated.h.inc # opcodes_def_generated.h.inc # -shortcode_generated = custom_target( - 'shortcode_generated.h.inc', - output: 'shortcode_generated.h.inc', - depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_shortcode.py'), semantics_generated, attribs_def, '@OUTPUT@'], -) -hexagon_ss.add(shortcode_generated) - tcg_func_table_generated = custom_target( 'tcg_func_table_generated.c.inc', output: 'tcg_func_table_generated.c.inc', depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_tcg_func_table.py'), semantics_generated, attribs_def, '@OUTPUT@'], + depend_files: [hex_common_py], + command: [python, files('gen_tcg_func_table.py'), semantics_generated, '@OUTPUT@'], ) hexagon_ss.add(tcg_func_table_generated) @@ -71,26 +59,17 @@ printinsn_generated = custom_target( 'printinsn_generated.h.inc', output: 'printinsn_generated.h.inc', depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_printinsn.py'), semantics_generated, attribs_def, '@OUTPUT@'], + depend_files: [hex_common_py], + command: [python, files('gen_printinsn.py'), semantics_generated, '@OUTPUT@'], ) hexagon_ss.add(printinsn_generated) -op_regs_generated = custom_target( - 'op_regs_generated.h.inc', - output: 'op_regs_generated.h.inc', - depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_op_regs.py'), semantics_generated, attribs_def, '@OUTPUT@'], -) -hexagon_ss.add(op_regs_generated) - op_attribs_generated = custom_target( 'op_attribs_generated.h.inc', output: 'op_attribs_generated.h.inc', depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_op_attribs.py'), semantics_generated, attribs_def, '@OUTPUT@'], + depend_files: [hex_common_py], + command: [python, files('gen_op_attribs.py'), semantics_generated, '@OUTPUT@'], ) hexagon_ss.add(op_attribs_generated) @@ -98,8 +77,8 @@ opcodes_def_generated = custom_target( 'opcodes_def_generated.h.inc', output: 'opcodes_def_generated.h.inc', depends: [semantics_generated], - depend_files: [hex_common_py, attribs_def], - command: [python, files('gen_opcodes_def.py'), semantics_generated, attribs_def, '@OUTPUT@'], + depend_files: [hex_common_py], + command: [python, files('gen_opcodes_def.py'), semantics_generated, '@OUTPUT@'], ) hexagon_ss.add(opcodes_def_generated) @@ -110,7 +89,7 @@ hexagon_ss.add(opcodes_def_generated) # gen_dectree_import = executable( 'gen_dectree_import', - 'gen_dectree_import.c', opcodes_def_generated, op_regs_generated, + 'gen_dectree_import.c', opcodes_def_generated, native: true, build_by_default: false) iset_py = custom_target( @@ -298,7 +277,7 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs output: 'idef_parser_input.h.inc', depends: [semantics_generated], depend_files: [hex_common_py], - command: [python, files('gen_idef_parser_funcs.py'), semantics_generated, attribs_def, '@OUTPUT@'], + command: [python, files('gen_idef_parser_funcs.py'), semantics_generated, '@OUTPUT@'], ) preprocessed_idef_parser_input_generated = custom_target( @@ -367,12 +346,12 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs # Setup input and dependencies for the next step, this depends on whether or # not idef-parser is enabled helper_dep = [semantics_generated, idef_generated_tcg_c, idef_generated_tcg] - helper_in = [semantics_generated, attribs_def, gen_tcg_h, gen_tcg_hvx_h, idef_generated_list] + helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, idef_generated_list] else # Setup input and dependencies for the next step, this depends on whether or # not idef-parser is enabled helper_dep = [semantics_generated] - helper_in = [semantics_generated, attribs_def, gen_tcg_h, gen_tcg_hvx_h] + helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h] endif # @@ -386,7 +365,7 @@ helper_protos_generated = custom_target( 'helper_protos_generated.h.inc', output: 'helper_protos_generated.h.inc', depends: helper_dep, - depend_files: [hex_common_py, attribs_def, gen_tcg_h, gen_tcg_hvx_h], + depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h], command: [python, files('gen_helper_protos.py'), helper_in, '@OUTPUT@'], ) hexagon_ss.add(helper_protos_generated) @@ -395,7 +374,7 @@ helper_funcs_generated = custom_target( 'helper_funcs_generated.c.inc', output: 'helper_funcs_generated.c.inc', depends: helper_dep, - depend_files: [hex_common_py, attribs_def, gen_tcg_h, gen_tcg_hvx_h], + depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h], command: [python, files('gen_helper_funcs.py'), helper_in, '@OUTPUT@'], ) hexagon_ss.add(helper_funcs_generated) @@ -404,7 +383,7 @@ tcg_funcs_generated = custom_target( 'tcg_funcs_generated.c.inc', output: 'tcg_funcs_generated.c.inc', depends: helper_dep, - depend_files: [hex_common_py, attribs_def, gen_tcg_h, gen_tcg_hvx_h], + depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h], command: [python, files('gen_tcg_funcs.py'), helper_in, '@OUTPUT@'], ) hexagon_ss.add(tcg_funcs_generated) @@ -413,7 +392,7 @@ analyze_funcs_generated = custom_target( 'analyze_funcs_generated.c.inc', output: 'analyze_funcs_generated.c.inc', depends: helper_dep, - depend_files: [hex_common_py, attribs_def, gen_tcg_h, gen_tcg_hvx_h], + depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h], command: [python, files('gen_analyze_funcs.py'), helper_in, '@OUTPUT@'], ) hexagon_ss.add(analyze_funcs_generated) diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c b/target/hexagon/mmvec/decode_ext_mmvec.c index 202d84c7c0..f850d0154d 100644 --- a/target/hexagon/mmvec/decode_ext_mmvec.c +++ b/target/hexagon/mmvec/decode_ext_mmvec.c @@ -28,19 +28,15 @@ check_new_value(Packet *pkt) { /* .new value for a MMVector store */ int i, j; - const char *reginfo; - const char *destletters; - const char *dststr = NULL; uint16_t def_opcode; - char letter; for (i = 1; i < pkt->num_insns; i++) { uint16_t use_opcode = pkt->insn[i].opcode; if (GET_ATTRIB(use_opcode, A_DOTNEWVALUE) && GET_ATTRIB(use_opcode, A_CVI) && GET_ATTRIB(use_opcode, A_STORE)) { - int use_regidx = strchr(opcode_reginfo[use_opcode], 's') - - opcode_reginfo[use_opcode]; + int use_regidx = pkt->insn[i].new_read_idx; + g_assert(pkt->insn[i].new_read_idx != -1); /* * What's encoded at the N-field is the offset to who's producing * the value. @@ -68,31 +64,19 @@ check_new_value(Packet *pkt) /* def_idx is the index of the producer */ def_opcode = pkt->insn[def_idx].opcode; - reginfo = opcode_reginfo[def_opcode]; - destletters = "dexy"; - for (j = 0; (letter = destletters[j]) != 0; j++) { - dststr = strchr(reginfo, letter); - if (dststr != NULL) { - break; - } - } - if ((dststr == NULL) && GET_ATTRIB(def_opcode, A_CVI_GATHER)) { + if ((pkt->insn[def_idx].dest_idx == -1) && + GET_ATTRIB(def_opcode, A_CVI_GATHER)) { pkt->insn[i].regno[use_regidx] = def_oreg; pkt->insn[i].new_value_producer_slot = pkt->insn[def_idx].slot; } else { - if (dststr == NULL) { + if (pkt->insn[def_idx].dest_idx == -1) { /* still not there, we have a bad packet */ g_assert_not_reached(); } - int def_regnum = pkt->insn[def_idx].regno[dststr - reginfo]; + int def_regnum = + pkt->insn[def_idx].regno[pkt->insn[def_idx].dest_idx]; /* Now patch up the consumer with the register number */ pkt->insn[i].regno[use_regidx] = def_regnum ^ def_oreg; - /* special case for (Vx,Vy) */ - dststr = strchr(reginfo, 'y'); - if (def_oreg && strchr(reginfo, 'x') && dststr) { - def_regnum = pkt->insn[def_idx].regno[dststr - reginfo]; - pkt->insn[i].regno[use_regidx] = def_regnum; - } /* * We need to remember who produces this value to later * check if it was dynamically cancelled diff --git a/target/hexagon/opcodes.c b/target/hexagon/opcodes.c index 1f7f3def38..c8bde2f9e9 100644 --- a/target/hexagon/opcodes.c +++ b/target/hexagon/opcodes.c @@ -36,41 +36,6 @@ const char * const opcode_names[] = { #undef OPCODE }; -const char * const opcode_reginfo[] = { -#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ -#define REGINFO(TAG, REGINFO, RREGS, WREGS) REGINFO, -#include "op_regs_generated.h.inc" - NULL -#undef REGINFO -#undef IMMINFO -}; - - -const char * const opcode_rregs[] = { -#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ -#define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS, -#include "op_regs_generated.h.inc" - NULL -#undef REGINFO -#undef IMMINFO -}; - - -const char * const opcode_wregs[] = { -#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */ -#define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS, -#include "op_regs_generated.h.inc" - NULL -#undef REGINFO -#undef IMMINFO -}; - -const char * const opcode_short_semantics[] = { -#define DEF_SHORTCODE(TAG, SHORTCODE) [TAG] = #SHORTCODE, -#include "shortcode_generated.h.inc" -#undef DEF_SHORTCODE - NULL -}; DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB); diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h index fa7e321950..0ee11bd445 100644 --- a/target/hexagon/opcodes.h +++ b/target/hexagon/opcodes.h @@ -40,10 +40,6 @@ typedef enum { extern const char * const opcode_names[]; -extern const char * const opcode_reginfo[]; -extern const char * const opcode_rregs[]; -extern const char * const opcode_wregs[]; - typedef struct { const char * const encoding; const EncClass enc_class; diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 47a870f42d..0904dc2d38 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -380,70 +380,8 @@ static bool need_commit(DisasContext *ctx) return true; } - if (pkt->num_insns == 1) { - if (pkt->pkt_has_hvx) { - /* - * The HVX instructions with generated helpers use - * pass-by-reference, so they need the read/write overlap - * check below. - * The HVX instructions with overrides are OK. - */ - if (!ctx->has_hvx_helper) { - return false; - } - } else { - return false; - } - } - - /* Check for overlap between register reads and writes */ - for (int i = 0; i < ctx->reg_log_idx; i++) { - int rnum = ctx->reg_log[i]; - if (test_bit(rnum, ctx->regs_read)) { - return true; - } - } - - /* Check for overlap between predicate reads and writes */ - for (int i = 0; i < ctx->preg_log_idx; i++) { - int pnum = ctx->preg_log[i]; - if (test_bit(pnum, ctx->pregs_read)) { - return true; - } - } - - /* Check for overlap between HVX reads and writes */ - for (int i = 0; i < ctx->vreg_log_idx; i++) { - int vnum = ctx->vreg_log[i]; - if (test_bit(vnum, ctx->vregs_read)) { - return true; - } - } - if (!bitmap_empty(ctx->vregs_updated_tmp, NUM_VREGS)) { - int i = find_first_bit(ctx->vregs_updated_tmp, NUM_VREGS); - while (i < NUM_VREGS) { - if (test_bit(i, ctx->vregs_read)) { - return true; - } - i = find_next_bit(ctx->vregs_updated_tmp, NUM_VREGS, i + 1); - } - } - if (!bitmap_empty(ctx->vregs_select, NUM_VREGS)) { - int i = find_first_bit(ctx->vregs_select, NUM_VREGS); - while (i < NUM_VREGS) { - if (test_bit(i, ctx->vregs_read)) { - return true; - } - i = find_next_bit(ctx->vregs_select, NUM_VREGS, i + 1); - } - } - - /* Check for overlap between HVX predicate reads and writes */ - for (int i = 0; i < ctx->qreg_log_idx; i++) { - int qnum = ctx->qreg_log[i]; - if (test_bit(qnum, ctx->qregs_read)) { - return true; - } + if (ctx->read_after_write || ctx->has_hvx_overlap) { + return true; } return false; @@ -467,7 +405,8 @@ static void mark_implicit_pred_reads(DisasContext *ctx) static void analyze_packet(DisasContext *ctx) { Packet *pkt = ctx->pkt; - ctx->has_hvx_helper = false; + ctx->read_after_write = false; + ctx->has_hvx_overlap = false; for (int i = 0; i < pkt->num_insns; i++) { Insn *insn = &pkt->insn[i]; ctx->insn = insn; @@ -492,21 +431,19 @@ static void gen_start_packet(DisasContext *ctx) ctx->next_PC = next_PC; ctx->reg_log_idx = 0; bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS); - bitmap_zero(ctx->regs_read, TOTAL_PER_THREAD_REGS); bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS); ctx->preg_log_idx = 0; bitmap_zero(ctx->pregs_written, NUM_PREGS); - bitmap_zero(ctx->pregs_read, NUM_PREGS); ctx->future_vregs_idx = 0; ctx->tmp_vregs_idx = 0; ctx->vreg_log_idx = 0; + bitmap_zero(ctx->vregs_written, NUM_VREGS); bitmap_zero(ctx->vregs_updated_tmp, NUM_VREGS); bitmap_zero(ctx->vregs_updated, NUM_VREGS); bitmap_zero(ctx->vregs_select, NUM_VREGS); bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS); bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS); - bitmap_zero(ctx->vregs_read, NUM_VREGS); - bitmap_zero(ctx->qregs_read, NUM_QREGS); + bitmap_zero(ctx->qregs_written, NUM_QREGS); ctx->qreg_log_idx = 0; for (i = 0; i < STORES_MAX; i++) { ctx->store_width[i] = 0; diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h index 4dd59c6726..00cc2bcd63 100644 --- a/target/hexagon/translate.h +++ b/target/hexagon/translate.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,12 +38,10 @@ typedef struct DisasContext { int reg_log[REG_WRITES_MAX]; int reg_log_idx; DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS); - DECLARE_BITMAP(regs_read, TOTAL_PER_THREAD_REGS); DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS); int preg_log[PRED_WRITES_MAX]; int preg_log_idx; DECLARE_BITMAP(pregs_written, NUM_PREGS); - DECLARE_BITMAP(pregs_read, NUM_PREGS); uint8_t store_width[STORES_MAX]; bool s1_store_processed; int future_vregs_idx; @@ -52,22 +50,27 @@ typedef struct DisasContext { int tmp_vregs_num[VECTOR_TEMPS_MAX]; int vreg_log[NUM_VREGS]; int vreg_log_idx; + DECLARE_BITMAP(vregs_written, NUM_VREGS); + DECLARE_BITMAP(insn_vregs_written, NUM_VREGS); DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS); DECLARE_BITMAP(vregs_updated, NUM_VREGS); DECLARE_BITMAP(vregs_select, NUM_VREGS); DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS); DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS); - DECLARE_BITMAP(vregs_read, NUM_VREGS); + DECLARE_BITMAP(insn_vregs_read, NUM_VREGS); int qreg_log[NUM_QREGS]; int qreg_log_idx; - DECLARE_BITMAP(qregs_read, NUM_QREGS); + DECLARE_BITMAP(qregs_written, NUM_QREGS); + DECLARE_BITMAP(insn_qregs_written, NUM_QREGS); + DECLARE_BITMAP(insn_qregs_read, NUM_QREGS); bool pre_commit; bool need_commit; TCGCond branch_cond; target_ulong branch_dest; bool is_tight_loop; bool short_circuit; - bool has_hvx_helper; + bool read_after_write; + bool has_hvx_overlap; TCGv new_value[TOTAL_PER_THREAD_REGS]; TCGv new_pred_value[NUM_PREGS]; TCGv pred_written; @@ -75,6 +78,8 @@ typedef struct DisasContext { TCGv dczero_addr; } DisasContext; +bool is_gather_store_insn(DisasContext *ctx); + static inline void ctx_log_pred_write(DisasContext *ctx, int pnum) { if (!test_bit(pnum, ctx->pregs_written)) { @@ -86,7 +91,14 @@ static inline void ctx_log_pred_write(DisasContext *ctx, int pnum) static inline void ctx_log_pred_read(DisasContext *ctx, int pnum) { - set_bit(pnum, ctx->pregs_read); + if (test_bit(pnum, ctx->pregs_written)) { + ctx->read_after_write = true; + } +} + +static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum) +{ + g_assert(test_bit(pnum, ctx->pregs_written)); } static inline void ctx_log_reg_write(DisasContext *ctx, int rnum, @@ -117,7 +129,14 @@ static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum, static inline void ctx_log_reg_read(DisasContext *ctx, int rnum) { - set_bit(rnum, ctx->regs_read); + if (test_bit(rnum, ctx->regs_written)) { + ctx->read_after_write = true; + } +} + +static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum) +{ + g_assert(test_bit(rnum, ctx->regs_written)); } static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum) @@ -131,10 +150,25 @@ intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum, intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum, int num, bool alloc_ok); +static inline void ctx_start_hvx_insn(DisasContext *ctx) +{ + bitmap_zero(ctx->insn_vregs_written, NUM_VREGS); + bitmap_zero(ctx->insn_vregs_read, NUM_VREGS); + bitmap_zero(ctx->insn_qregs_written, NUM_QREGS); + bitmap_zero(ctx->insn_qregs_read, NUM_QREGS); +} + static inline void ctx_log_vreg_write(DisasContext *ctx, int rnum, VRegWriteType type, - bool is_predicated) + bool is_predicated, bool has_helper) { + if (has_helper) { + set_bit(rnum, ctx->insn_vregs_written); + if (test_bit(rnum, ctx->insn_vregs_read)) { + ctx->has_hvx_overlap = true; + } + } + set_bit(rnum, ctx->vregs_written); if (type != EXT_TMP) { if (!test_bit(rnum, ctx->vregs_updated)) { ctx->vreg_log[ctx->vreg_log_idx] = rnum; @@ -160,33 +194,77 @@ static inline void ctx_log_vreg_write(DisasContext *ctx, static inline void ctx_log_vreg_write_pair(DisasContext *ctx, int rnum, VRegWriteType type, - bool is_predicated) + bool is_predicated, bool has_helper) { - ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated); - ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated); + ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated, has_helper); + ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated, has_helper); } -static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum) +static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum, + bool has_helper) { - set_bit(rnum, ctx->vregs_read); + if (has_helper) { + set_bit(rnum, ctx->insn_vregs_read); + if (test_bit(rnum, ctx->insn_vregs_written)) { + ctx->has_hvx_overlap = true; + } + } + if (test_bit(rnum, ctx->vregs_written)) { + ctx->read_after_write = true; + } } -static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum) +static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum, + bool has_helper) { - ctx_log_vreg_read(ctx, rnum ^ 0); - ctx_log_vreg_read(ctx, rnum ^ 1); + g_assert(is_gather_store_insn(ctx) || + test_bit(rnum, ctx->vregs_updated) || + test_bit(rnum, ctx->vregs_select) || + test_bit(rnum, ctx->vregs_updated_tmp)); + if (has_helper) { + set_bit(rnum, ctx->insn_vregs_read); + if (test_bit(rnum, ctx->insn_vregs_written)) { + ctx->has_hvx_overlap = true; + } + } + if (is_gather_store_insn(ctx)) { + ctx->read_after_write = true; + } +} + +static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum, + bool has_helper) +{ + ctx_log_vreg_read(ctx, rnum ^ 0, has_helper); + ctx_log_vreg_read(ctx, rnum ^ 1, has_helper); } static inline void ctx_log_qreg_write(DisasContext *ctx, - int rnum) + int rnum, bool has_helper) { + if (has_helper) { + set_bit(rnum, ctx->insn_qregs_written); + if (test_bit(rnum, ctx->insn_qregs_read)) { + ctx->has_hvx_overlap = true; + } + } + set_bit(rnum, ctx->qregs_written); ctx->qreg_log[ctx->qreg_log_idx] = rnum; ctx->qreg_log_idx++; } -static inline void ctx_log_qreg_read(DisasContext *ctx, int qnum) +static inline void ctx_log_qreg_read(DisasContext *ctx, + int qnum, bool has_helper) { - set_bit(qnum, ctx->qregs_read); + if (has_helper) { + set_bit(qnum, ctx->insn_qregs_read); + if (test_bit(qnum, ctx->insn_qregs_written)) { + ctx->has_hvx_overlap = true; + } + } + if (test_bit(qnum, ctx->qregs_written)) { + ctx->read_after_write = true; + } } extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS]; @@ -205,7 +283,6 @@ extern TCGv hex_vstore_addr[VSTORES_MAX]; extern TCGv hex_vstore_size[VSTORES_MAX]; extern TCGv hex_vstore_pending[VSTORES_MAX]; -bool is_gather_store_insn(DisasContext *ctx); void process_store(DisasContext *ctx, int slot_num); FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, 0, 2) diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c index b45170acd1..1fe14b5158 100644 --- a/tests/tcg/hexagon/hvx_misc.c +++ b/tests/tcg/hexagon/hvx_misc.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2021-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -231,6 +231,7 @@ static void test_masked_store(bool invert) static void test_new_value_store(void) { void *p0 = buffer0; + void *p1 = buffer1; void *pout = output; asm("{\n\t" @@ -242,6 +243,19 @@ static void test_new_value_store(void) expect[0] = buffer0[0]; check_output_w(__LINE__, 1); + + /* Test the .new read from the high half of a pair */ + asm("v7 = vmem(%0 + #0)\n\t" + "v12 = vmem(%1 + #0)\n\t" + "{\n\t" + " v5:4 = vcombine(v12, v7)\n\t" + " vmem(%2 + #0) = v5.new\n\t" + "}\n\t" + : : "r"(p0), "r"(p1), "r"(pout) : "v4", "v5", "v7", "v12", "memory"); + + expect[0] = buffer1[0]; + + check_output_w(__LINE__, 1); } static void test_max_temps()