Generate the HLX decoder and apply its packet rules. Add HLX loads and
stores, including .tmp load forwarding and .new store handling.

HLX .new fields name the forwarded L register. A store without a
producer writes zeroes.

Signed-off-by: Marco Liebel <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/attribs_def.h.inc           |   5 +
 target/hexagon/decode.c                    | 118 ++++++++++++++++-----
 target/hexagon/gen_dectree_import.c        |   9 +-
 target/hexagon/gen_hlx_ext.py              |  25 +++++
 target/hexagon/gen_idef_parser_funcs.py    |   3 +
 target/hexagon/gen_tcg_funcs.py            |   3 +
 target/hexagon/imported/allext.idef        |   6 ++
 target/hexagon/imported/allextenc.def      |   4 +
 target/hexagon/imported/hlx/encode_ext.def |  18 ++++
 target/hexagon/imported/hlx_ext.idef       |  45 ++++++++
 target/hexagon/insn.h                      |   1 +
 target/hexagon/meson.build                 |  39 +++++++
 target/hexagon/opcodes.h                   |   1 +
 target/hexagon/translate.c                 |  12 +++
 14 files changed, 259 insertions(+), 30 deletions(-)
 create mode 100755 target/hexagon/gen_hlx_ext.py
 create mode 100644 target/hexagon/imported/hlx/encode_ext.def
 create mode 100644 target/hexagon/imported/hlx_ext.idef

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


Reply via email to