Short-circuit for packets with r/w and no overlap

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPWaq5HRZSCTIjOD4GlSvuOVkbDIFAmY4FR8ACgkQGlSvuOVk
 bDLEfxAAup6v9J4n2/q88FXfLGgx1EfZrT01gOM/48mwngNNQJGJQySe2GLl0G8S
 1hx/Ym3jbikic8HL80v8FyCr4gNRshEY7xKpCfvY9lsgnCRbhEvoV/hZqucmLQAt
 1SIhFSsi5h8gyZDTvXhH75v3qGvYjQ7fQBhy2JbRsPjthdHBh9xi6Na60wlqfNZq
 oGsVtY7sv1uHsvDKBi3JoXWckSK99R38BHY6zPoStarRZACkkLdX6KHxeX88TUt1
 whIUYUS/K0nRVxzekdq/+m8UJYrXnW/0cliM5mLFHDGlsV+qjdcIRrfaPWBO0eFN
 kXeZU2BWLCdP2M52FHI4FllnIRpX5OGkxjR6x8Pc9r+EGciwGRU7xeAlqBxKQSZP
 e3oXtV6oKxg69xBgHE5HcKbt6bX5EZR/sUcbAoGA41UssaiMyj3wbg1cy2UxXu2J
 7oJyywJUggWGSoCIIJJ95YgpUrIg73Yg6pOjfhKW1w/V2SuQPGG0XTXrwe7J6uGi
 VAqyu55p2oiW8Gk4Lvl1SfWgxkVeZa/NcxTmXNEWFnT7vatqwez0O5pxIkxdSCFE
 lRv7PuFT5nhQ/gg12zGqqRiOrMOMQitHFzJ9sUNu7J4Y7W5R4gzRW19ucojLt0lH
 fT83Ra+Eex1Cu3DsuvWkokxFikxXP1Ll297Jr1JhOPewTtvlxvI=
 =Q8/k
 -----END PGP SIGNATURE-----

Merge tag 'pull-hex-20240505' of https://github.com/quic/qemu into staging

Short-circuit for packets with r/w and no overlap

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEPWaq5HRZSCTIjOD4GlSvuOVkbDIFAmY4FR8ACgkQGlSvuOVk
# bDLEfxAAup6v9J4n2/q88FXfLGgx1EfZrT01gOM/48mwngNNQJGJQySe2GLl0G8S
# 1hx/Ym3jbikic8HL80v8FyCr4gNRshEY7xKpCfvY9lsgnCRbhEvoV/hZqucmLQAt
# 1SIhFSsi5h8gyZDTvXhH75v3qGvYjQ7fQBhy2JbRsPjthdHBh9xi6Na60wlqfNZq
# oGsVtY7sv1uHsvDKBi3JoXWckSK99R38BHY6zPoStarRZACkkLdX6KHxeX88TUt1
# whIUYUS/K0nRVxzekdq/+m8UJYrXnW/0cliM5mLFHDGlsV+qjdcIRrfaPWBO0eFN
# kXeZU2BWLCdP2M52FHI4FllnIRpX5OGkxjR6x8Pc9r+EGciwGRU7xeAlqBxKQSZP
# e3oXtV6oKxg69xBgHE5HcKbt6bX5EZR/sUcbAoGA41UssaiMyj3wbg1cy2UxXu2J
# 7oJyywJUggWGSoCIIJJ95YgpUrIg73Yg6pOjfhKW1w/V2SuQPGG0XTXrwe7J6uGi
# VAqyu55p2oiW8Gk4Lvl1SfWgxkVeZa/NcxTmXNEWFnT7vatqwez0O5pxIkxdSCFE
# lRv7PuFT5nhQ/gg12zGqqRiOrMOMQitHFzJ9sUNu7J4Y7W5R4gzRW19ucojLt0lH
# fT83Ra+Eex1Cu3DsuvWkokxFikxXP1Ll297Jr1JhOPewTtvlxvI=
# =Q8/k
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 05 May 2024 04:24:15 PM PDT
# gpg:                using RSA key 3D66AAE474594824C88CE0F81A54AFB8E5646C32
# gpg: Good signature from "Brian Cain (QUIC) <quic_bcain@quicinc.com>" [unknown]
# gpg:                 aka "Brian Cain <bcain@kernel.org>" [unknown]
# gpg:                 aka "Brian Cain (QuIC) <bcain@quicinc.com>" [unknown]
# gpg:                 aka "Brian Cain (CAF) <bcain@codeaurora.org>" [unknown]
# gpg:                 aka "bcain" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6350 20F9 67A7 7164 79EF  49E0 175C 464E 541B 6D47
#      Subkey fingerprint: 3D66 AAE4 7459 4824 C88C  E0F8 1A54 AFB8 E564 6C32

* tag 'pull-hex-20240505' of https://github.com/quic/qemu:
  Hexagon (target/hexagon) Remove hex_common.read_attribs_file
  Hexagon (target/hexagon) Remove gen_shortcode.py
  Hexagon (target/hexagon) Remove gen_op_regs.py
  Hexagon (target/hexagon) Remove uses of op_regs_generated.h.inc
  Hexagon (tests/tcg/hexagon) Test HVX .new read from high half of pair
  Hexagon (target/hexagon) Mark has_pred_dest in trans functions
  Hexagon (target/hexagon) Mark dest_idx in trans functions
  Hexagon (target/hexagon) Mark new_read_idx in trans functions
  Hexagon (target/hexagon) Add is_old/is_new to Register class
  Hexagon (target/hexagon) Only pass env to generated helper when needed
  Hexagon (target/hexagon) Pass SP explicitly to helpers that need it
  Hexagon (target/hexagon) Pass P0 explicitly to helpers that need it
  Hexagon (target/hexagon) Enable more short-circuit packets (HVX)
  Hexagon (target/hexagon) Enable more short-circuit packets (scalar core)
  Hexagon (target/hexagon) Analyze reads before writes

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-05-06 08:33:43 -07:00
commit 28188253dc
26 changed files with 375 additions and 611 deletions

View File

@ -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 <BUILD_DIR>/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_<tag> function for each instruction. Currently,
these functions record the writes to registers by calling ctx_log_*. During
gen_start_packet, we invoke the analyze_<tag> 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_<tag> 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.

View File

@ -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", "", "")

View File

@ -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) {

View File

@ -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__":

View File

@ -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()

View File

@ -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()

View File

@ -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:

View File

@ -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("

View File

@ -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 <http://www.gnu.org/licenses/>.
##
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()

View File

@ -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")

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
##
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()

View File

@ -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)

View File

@ -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")

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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()