diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index a02261ee5e..e9779a33ee 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -19,6 +19,9 @@
DEF_ATTRIB(AA_DUMMY, "Dummy Zeroth Attribute", "", "")
/* Misc */
+DEF_ATTRIB(FAKEINSN, "Not a real instruction", "", "")
+DEF_ATTRIB(MAPPING, "Not real -- asm mapped", "", "")
+DEF_ATTRIB(CONDMAPPING, "Not real -- mapped based on values", "", "")
DEF_ATTRIB(EXTENSION, "Extension instruction", "", "")
DEF_ATTRIB(NA_NT, "Non-Allocating Non-Temporal instruction", "", "")
@@ -228,5 +231,7 @@ DEF_ATTRIB(HVX_IEEE_FP_OUT_32, "HVX IEEE FP 32-bit output", "",
"")
DEF_ATTRIB(CVI_VX_NO_TMP_LD, "HVX multiply without tmp load", "", "")
DEF_ATTRIB(HVX_FLT, "This a floating point HVX instruction.", "", "")
+DEF_ATTRIB(NO_IDEF_PARSER, "Skip idef-parser for this instruction", "", "")
+
/* Keep this as the last attribute: */
DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "")
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 0ac87bbee0..0c3dc67e12 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -23,6 +23,7 @@
#include "insn.h"
#include "printinsn.h"
#include "mmvec/decode_ext_mmvec.h"
+#include "hlx/decode_ext_hlx.h"
#define fZXTN(N, M, VAL) ((VAL) & ((1LL << (N)) - 1))
@@ -69,6 +70,7 @@ static int shift_left(DisasContext *ctx, int x, int n, int immno)
/* Include the generated decoder for 32 bit insn */
#include "decode_normal_generated.c.inc"
#include "decode_hvx_generated.c.inc"
+#include "decode_hlx_generated.c.inc"
/* Include the generated decoder for 16 bit insn */
#include "decode_subinsn_a_generated.c.inc"
@@ -102,40 +104,77 @@ void decode_send_insn_to(Packet *packet, int start, int
newloc)
}
}
-/* Fill newvalue registers with the correct regno */
-static void
+/* An HLX .new N-field names its producer register. */
+static int hlx_find_new_value_producer(Packet *packet, int consumer,
+ int lreg)
+{
+ for (int i = 0; i < packet->num_insns; i++) {
+ Insn *insn = &packet->insn[i];
+
+ if (i != consumer && GET_ATTRIB(insn->opcode, A_HLX) &&
+ insn->dest_idx != -1 && insn->regno[insn->dest_idx] == lreg) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* Fill newvalue registers with the correct regno. */
+static bool
decode_fill_newvalue_regno(Packet *packet)
{
int i, use_regidx, offset, def_idx, dst_idx;
- for (i = 1; i < packet->num_insns; i++) {
+ for (i = 0; i < packet->num_insns; i++) {
if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
- !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
+ (!GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION) ||
+ GET_ATTRIB(packet->insn[i].opcode, A_HLX))) {
- g_assert(packet->insn[i].new_read_idx != -1);
+ if (i == 0 && !GET_ATTRIB(packet->insn[i].opcode, A_HLX)) {
+ continue;
+ }
+ if (packet->insn[i].new_read_idx == -1) {
+ return false;
+ }
use_regidx = packet->insn[i].new_read_idx;
- /*
- * What's encoded at the N-field is the offset to who's producing
- * the value. Shift off the LSB which indicates odd/even register,
- * then walk backwards and skip over the constant extenders.
- */
- offset = packet->insn[i].regno[use_regidx] >> 1;
- def_idx = i - offset;
- for (int j = 0; j < offset; j++) {
- if (GET_ATTRIB(packet->insn[i - j - 1].opcode, A_IT_EXTENDER))
{
- def_idx--;
+ if (GET_ATTRIB(packet->insn[i].opcode, A_HLX)) {
+ def_idx = hlx_find_new_value_producer(
+ packet, i, packet->insn[i].regno[use_regidx]);
+ if (def_idx < 0) {
+ /* No producer means a 2KB zero store. */
+ packet->insn[i].hlx_new_zero = true;
+ continue;
+ }
+ } else {
+ /*
+ * What's encoded at the N-field is the offset to who's
+ * producing the value. Shift off the LSB which indicates
+ * odd/even register, then walk backwards and skip over the
+ * constant extenders.
+ */
+ offset = packet->insn[i].regno[use_regidx] >> 1;
+ if (offset == 0 || offset > i) {
+ return false;
+ }
+ def_idx = i - offset;
+ for (int j = 0; j < offset; j++) {
+ if (GET_ATTRIB(packet->insn[i - j - 1].opcode,
+ A_IT_EXTENDER)) {
+ def_idx--;
+ }
}
- }
- /*
- * Check for a badly encoded N-field which points to an instruction
- * out-of-range
- */
- g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1))));
+ /*
+ * Check for a badly encoded N-field which points to an
+ * instruction out-of-range
+ */
+ if (def_idx < 0 || packet->insn[def_idx].dest_idx == -1) {
+ return false;
+ }
+ }
/* Now patch up the consumer with the register number */
- 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];
@@ -147,6 +186,7 @@ decode_fill_newvalue_regno(Packet *packet)
packet->insn[def_idx].slot;
}
}
+ return true;
}
/* Split CJ into a compare and a jump */
@@ -422,7 +462,12 @@ static void decode_remove_extenders(Packet *packet)
static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot)
{
if (GET_ATTRIB(pkt->insn[slot].opcode, A_EXTENSION)) {
- return mmvec_ext_decode_find_iclass_slots(pkt->insn[slot].opcode);
+ if (GET_ATTRIB(pkt->insn[slot].opcode, A_HLX)) {
+ return hlx_ext_decode_find_iclass_slots(
+ pkt->insn[slot].opcode);
+ }
+ return mmvec_ext_decode_find_iclass_slots(
+ pkt->insn[slot].opcode);
} else {
return find_iclass_slots(pkt->insn[slot].opcode,
pkt->insn[slot].iclass);
@@ -491,7 +536,8 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t
encoding)
{
if (parse_bits(encoding) != 0) {
if (decode_normal(ctx, encoding) ||
- decode_hvx(ctx, encoding)) {
+ decode_hvx(ctx, encoding) ||
+ decode_hlx(ctx, encoding)) {
insn->generate = opcode_genptr[insn->opcode];
insn->iclass = iclass_bits(encoding);
return 1;
@@ -614,8 +660,11 @@ decode_set_slot_number(Packet *pkt)
}
}
- /* Fix the exceptions - mem insns to slot 0,1 */
+ /* HLX instructions already have extension-assigned slots. */
for (i = pkt->num_insns - 1; i >= 0; i--) {
+ if (GET_ATTRIB(pkt->insn[i].opcode, A_HLX)) {
+ continue;
+ }
/* First memory instruction always goes to slot 0 */
if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
@@ -671,8 +720,9 @@ decode_set_slot_number(Packet *pkt)
}
}
/* Is slot0 empty and slot1 used? */
- if ((!slot0_found) && slot1_found) {
- /* Then push it to slot0 */
+ if ((!slot0_found) && slot1_found &&
+ !GET_ATTRIB(pkt->insn[slot1_iidx].opcode, A_HLX)) {
+ /* Push it to slot 0. HLX loads remain in slot 1. */
pkt->insn[slot1_iidx].slot = 0;
}
@@ -688,6 +738,10 @@ bool opcode_supported(uint16_t opcode, const HexagonCPUDef *hex_def)
if (hex_version == HEX_VER_ANY) {
return true;
}
+ /* HLX was added in V85. */
+ if (GET_ATTRIB(opcode, A_HLX) && hex_version < HEX_VER_V85) {
+ return false;
+ }
if ((info.introduced != HEX_VER_NONE && hex_version < info.introduced) ||
(info.removed != HEX_VER_NONE && hex_version >= info.removed)) {
return false;
@@ -773,9 +827,12 @@ int decode_packet(DisasContext *ctx, int max_words, const
uint32_t *words,
pkt->encod_pkt_size_in_bytes = words_read * 4;
pkt->pkt_has_hvx = false;
+ pkt->pkt_has_hlx = false;
for (i = 0; i < num_insns; i++) {
pkt->pkt_has_hvx |=
GET_ATTRIB(pkt->insn[i].opcode, A_CVI);
+ pkt->pkt_has_hlx |=
+ GET_ATTRIB(pkt->insn[i].opcode, A_HLX);
}
/*
@@ -808,11 +865,16 @@ int decode_packet(DisasContext *ctx, int max_words, const
uint32_t *words,
return 0;
}
}
- decode_fill_newvalue_regno(pkt);
+ if (!decode_fill_newvalue_regno(pkt)) {
+ return 0;
+ }
if (pkt->pkt_has_hvx) {
mmvec_ext_decode_checks(pkt, disas_only);
}
+ if (pkt->pkt_has_hlx && !hlx_ext_decode_checks(pkt, disas_only)) {
+ return 0;
+ }
if (!disas_only) {
decode_shuffle_for_execution(pkt);
diff --git a/target/hexagon/gen_dectree_import.c
b/target/hexagon/gen_dectree_import.c
index 87f20c14f1..8ed369f699 100644
--- a/target/hexagon/gen_dectree_import.c
+++ b/target/hexagon/gen_dectree_import.c
@@ -79,6 +79,7 @@ static const char * const
opcode_enc_class_names[XX_LAST_ENC_CLASS] = {
"SUBINSN_S2",
"EXT_noext",
"EXT_mmvec",
+ "EXT_hlx",
};
static const char *get_opcode_enc(int opcode)
@@ -94,11 +95,15 @@ static const char *get_opcode_enc_class(int opcode)
{
const char *tmp = opcode_encodings[opcode].encoding;
if (tmp == NULL) {
- const char *test = "V6_"; /* HVX */
+ const char *test_hvx = "V6_";
+ const char *test_hlx = "LX_";
const char *name = opcode_names[opcode];
- if (strncmp(name, test, strlen(test)) == 0) {
+ if (strncmp(name, test_hvx, strlen(test_hvx)) == 0) {
return "EXT_mmvec";
}
+ if (strncmp(name, test_hlx, strlen(test_hlx)) == 0) {
+ return "EXT_hlx";
+ }
}
return opcode_enc_class_names[opcode_encodings[opcode].enc_class];
}
diff --git a/target/hexagon/gen_hlx_ext.py b/target/hexagon/gen_hlx_ext.py
new file mode 100755
index 0000000000..d0385c3ac7
--- /dev/null
+++ b/target/hexagon/gen_hlx_ext.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+##
+## Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+## SPDX-License-Identifier: GPL-2.0-or-later
+##
+
+"""Process HLX extension instruction definitions."""
+
+import sys
+
+def main():
+ """Copy preprocessed HLX instruction definitions."""
+ input_file = sys.argv[1]
+ output_file = sys.argv[2]
+
+ with open(input_file, "rt") as infile:
+ with open(output_file, "w") as outfile:
+ for line in infile:
+ # Skip preprocessor directives.
+ if not line.startswith("#"):
+ outfile.write(line)
+
+if __name__ == "__main__":
+ main()
diff --git a/target/hexagon/gen_idef_parser_funcs.py
b/target/hexagon/gen_idef_parser_funcs.py
index 9293be4c39..3f5879ce19 100644
--- a/target/hexagon/gen_idef_parser_funcs.py
+++ b/target/hexagon/gen_idef_parser_funcs.py
@@ -62,6 +62,9 @@ def main():
for tag in hex_common.tags:
if hex_common.tag_ignore(tag):
continue
+ ## Skip instructions that explicitly request no idef-parser
+ if "A_NO_IDEF_PARSER" in hex_common.attribdict[tag]:
+ continue
## Skip the priv instructions
if "A_PRIV" in hex_common.attribdict[tag]:
continue
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 4305eda996..eb2e5f3a7e 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -118,6 +118,9 @@ def gen_tcg_func(f, tag, regs, imms):
arguments = ", ".join(["ctx", "ctx->insn", "&ctx->pkt"] + declared)
f.write(f" emit_{tag}({arguments});\n")
+ elif hex_common.is_hlx_inline_tag(tag):
+ hex_common.gen_hlx_inline(f, tag, regs)
+
elif hex_common.skip_qemu_helper(tag):
if "A_FPOP" in hex_common.attribdict[tag]:
f.write(" TCGv pkt_need_commit = ")
diff --git a/target/hexagon/imported/allext.idef
b/target/hexagon/imported/allext.idef
index 9d4b23e9de..fa17b0de5d 100644
--- a/target/hexagon/imported/allext.idef
+++ b/target/hexagon/imported/allext.idef
@@ -23,3 +23,9 @@
#include "mmvec/ext.idef"
#undef EXTNAME
#undef EXTSTR
+
+#define EXTNAME hlx
+#define EXTSTR "hlx"
+#include "generated_hlx_ext.idef"
+#undef EXTNAME
+#undef EXTSTR
diff --git a/target/hexagon/imported/allextenc.def
b/target/hexagon/imported/allextenc.def
index 39a3e93fad..c72807c4b1 100644
--- a/target/hexagon/imported/allextenc.def
+++ b/target/hexagon/imported/allextenc.def
@@ -18,3 +18,7 @@
#define EXTNAME mmvec
#include "mmvec/encode_ext.def"
#undef EXTNAME
+
+#define EXTNAME hlx
+#include "hlx/encode_ext.def"
+#undef EXTNAME
diff --git a/target/hexagon/imported/hlx/encode_ext.def
b/target/hexagon/imported/hlx/encode_ext.def
new file mode 100644
index 0000000000..10d13db376
--- /dev/null
+++ b/target/hexagon/imported/hlx/encode_ext.def
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define CONCAT(A,B) A##B
+#define EXTEXTNAME(X) CONCAT(EXT_,X)
+#define DEF_ENC(TAG,STR) DEF_EXT_ENC(TAG,EXTEXTNAME(EXTNAME),STR)
+
+DEF_ENC(LX_L16b_tmp,"1001100----sssssPP-10----000dddd")
+DEF_ENC(LX_L16b_p_tmp,"1001100----sssssPP-10vv--100dddd")
+
+DEF_ENC(LX_S16b_new,"1010-1001--sssssPP000----000uuuu")
+DEF_ENC(LX_S16b_p_new,"1010-1001--sssssPP000vv--100uuuu")
+
+#undef DEF_ENC
+#undef EXTEXTNAME
+#undef CONCAT
diff --git a/target/hexagon/imported/hlx_ext.idef
b/target/hexagon/imported/hlx_ext.idef
new file mode 100644
index 0000000000..3685596e5e
--- /dev/null
+++ b/target/hexagon/imported/hlx_ext.idef
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef EXTINSN
+#define EXTINSN Q6INSN
+#define __SELF_DEF_EXTINSN 1
+#endif
+
+#ifndef NO_HLX
+
+/* HLX vectors hold 1024 halfwords or 512 words. */
+#define HLX_FOR_EACH_CODE(CODE) \
+{ \
+ fHIDE(int i;) \
+ fLVFOREACH(1024, i) { \
+ CODE ; \
+ } \
+}
+
+EXTINSN(LX_L16b_tmp,"Ld16.tmp=mem(Rs32)",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_LOAD,A_RESTRICT_SLOT1ONLY,A_HLX_TMP),"Aligned
HLX load",
+{ fEA_REG(RsV); fLOADMML(EA,LdV,false,false);})
+
+EXTINSN(LX_L16b_p_tmp,"if (Pv4)
Ld16.tmp=mem(Rs32)",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_LOAD,A_RESTRICT_SLOT1ONLY,A_HLX_TMP,A_CONDEXEC),"Aligned
HLX load",
+{ fEA_REG(RsV); if(fLSBOLD(PvV)){fLOADMML(EA,LdV,false,false);} else
{LOAD_CANCEL(EA);};})
+
+EXTINSN(LX_S16b_new,"mem(Rs32)=Ku16.new",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_STORE,A_HLX_NEW,A_DOTNEWVALUE,A_RESTRICT_SLOT0ONLY),"Aligned
HLX new halfword store",
+{ fEA_REG(RsV); fSTOREMML(EA,fNEWLREG(KuN),false,false);})
+
+EXTINSN(LX_S16b_p_new,"if (Pv4)
mem(Rs32)=Ku16.new",ATTRIBS(A_HLX,A_EXTENSION,A_NO_IDEF_PARSER,A_NOTE_HLX_MEM,A_HLX_MEM,A_VTCM_ALLBANK_ACCESS,A_STORE,A_HLX_NEW,A_DOTNEWVALUE,A_RESTRICT_SLOT0ONLY,A_CONDEXEC),"Aligned
HLX new halfword store",
+{ fEA_REG(RsV); if(fLSBOLD(PvV)){fSTOREMML(EA,fNEWLREG(KuN),false,false);}
else {STORE_CANCEL(EA);};})
+
+Q6INSN(LX_LL16b_tmp,"Ldd16.tmp=mem(Rs32)",ATTRIBS(A_MAPPING,A_HLX,A_NO_IDEF_PARSER),"Mapping
from Ldd16.tmp=mem(Rs32) to LWd.tmp=mem(R)",
+fASM_MAP("Ldd16.tmp=mem(Rs32)","LWd.tmp=mem(R)"))
+
+Q6INSN(LX_SS16b_new,"mem(Rs32)=Kuu16.new",ATTRIBS(A_MAPPING,A_HLX,A_NO_IDEF_PARSER),"Mapping
from mem(Rs32)=Kuu16.new to mem(R)=KWnew",
+fASM_MAP("mem(Rs32)=Kuu16.new","mem(R)=KWnew"))
+
+#endif /* NO_HLX */
+
+#ifdef __SELF_DEF_EXTINSN
+#undef EXTINSN
+#undef __SELF_DEF_EXTINSN
+#endif
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 5751c9ced9..cfd4072669 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -49,6 +49,7 @@ struct Instruction {
*/
bool extension_valid; /* Has a constant extender attached */
bool is_endloop; /* This is an end of loop */
+ bool hlx_new_zero; /* HLX .new store without a producer. */
int32_t immed[IMMEDS_MAX]; /* immediate field */
};
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index f9e820286e..3bffbef6c1 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -22,6 +22,26 @@ gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h'
gen_tcg_hvx_h = meson.current_source_dir() / 'gen_tcg_hvx.h'
gen_tcg_sys_h = meson.current_source_dir() / 'gen_tcg_sys.h'
idef_parser_dir = meson.current_source_dir() / 'idef-parser'
+imported_dir = meson.current_source_dir() / 'imported'
+
+#
+# Create the HLX ext.idef.
+#
+preprocessed_hlx_ext = custom_target(
+ 'hlx_ext.preprocessed.idef',
+ output: 'hlx_ext.preprocessed.idef',
+ input: imported_dir / 'hlx_ext.idef',
+ command: meson.get_compiler('c').cmd_array() +
+ ['-x', 'c', '-E', '-o', '@OUTPUT@', '@INPUT@']
+)
+generated_hlx_ext = custom_target(
+ 'generated_hlx_ext.idef',
+ output: 'generated_hlx_ext.idef',
+ input: preprocessed_hlx_ext,
+ depend_files: [hex_common_py],
+ command: [python, files('gen_hlx_ext.py'), '@INPUT@', '@OUTPUT@'],
+)
+hexagon_ss.add(generated_hlx_ext)
#
# Step 1
@@ -30,6 +50,7 @@ idef_parser_dir = meson.current_source_dir() / 'idef-parser'
gen_semantics = executable(
'gen_semantics',
'gen_semantics.c',
+ sources: generated_hlx_ext,
native: true, build_by_default: false)
semantics_generated = custom_target(
@@ -123,6 +144,15 @@ hvx_decode_generated = custom_target(
)
hexagon_ss.add(hvx_decode_generated)
+hlx_decode_generated = custom_target(
+ 'hlx_decode_generated',
+ output: 'hlx_decode_generated',
+ depends: [iset_py, semantics_generated],
+ env: {'PYTHONPATH': meson.current_build_dir()},
+ command: [python, files('gen_decodetree.py'), semantics_generated,
'EXT_hlx', '@OUTPUT@'],
+)
+hexagon_ss.add(hlx_decode_generated)
+
subinsn_a_decode_generated = custom_target(
'subinsn_a_decode_generated',
output: 'subinsn_a_decode_generated',
@@ -190,6 +220,15 @@ decode_hvx_generated = custom_target(
)
hexagon_ss.add(decode_hvx_generated)
+decode_hlx_generated = custom_target(
+ 'decode_hlx_generated.c.inc',
+ output: 'decode_hlx_generated.c.inc',
+ input: hlx_decode_generated,
+ env: {'PYTHONPATH': meson.current_build_dir()},
+ command: [python, files(decodetree_py), hlx_decode_generated,
'--static-decode=decode_hlx', '-o', '@OUTPUT@'],
+)
+hexagon_ss.add(decode_hlx_generated)
+
decode_subinsn_a_generated = custom_target(
'decode_subinsn_a_generated.c.inc',
output: 'decode_subinsn_a_generated.c.inc',
diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index 0ee11bd445..d6bc2de21c 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -35,6 +35,7 @@ typedef enum {
SUBINSN_S2,
EXT_noext,
EXT_mmvec,
+ EXT_hlx,
XX_LAST_ENC_CLASS
} EncClass;
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 41b7d3b0fb..ce0f215230 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -1264,6 +1264,15 @@ static void gen_commit_hvx(DisasContext *ctx)
}
}
+/* A .new store without a producer reads zeroed future_LRegs. */
+static void gen_hlx_new_zero(Insn *insn)
+{
+ int rnum = insn->regno[insn->new_read_idx];
+
+ tcg_gen_gvec_dup_imm(MO_64, offsetof(CPUHexagonState, future_LRegs[rnum]),
+ sizeof(HLXVector), sizeof(HLXVector), 0);
+}
+
static void gen_commit_hlx(DisasContext *ctx)
{
int i;
@@ -1490,6 +1499,9 @@ static void decode_and_translate_packet(CPUHexagonState
*env, DisasContext *ctx)
continue;
}
ctx->insn = insn;
+ if (insn->hlx_new_zero) {
+ gen_hlx_new_zero(insn);
+ }
if (GET_ATTRIB(insn->opcode, A_HLX) &&
trace_event_get_state_backends(
TRACE_HEXAGON_HLX_OP)) {