Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/mmvec/mmvec.h     | 55 ++++++++++++++++++++------------
 hw/hexagon/hexagon_hvx_context.c |  5 +++
 target/hexagon/hex_common.py     | 29 +++++++++++++++++
 3 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/target/hexagon/mmvec/mmvec.h b/target/hexagon/mmvec/mmvec.h
index 662f9d1597e..462d66b686b 100644
--- a/target/hexagon/mmvec/mmvec.h
+++ b/target/hexagon/mmvec/mmvec.h
@@ -33,29 +33,42 @@ typedef uint32_t QRegMask; /* at least NUM_QREGS bits */
 
 #define VECTOR_SIZE_BYTE    (fVECSIZE())
 
-typedef union {
-    uint64_t ud[MAX_VEC_SIZE_BYTES / 8];
-    int64_t   d[MAX_VEC_SIZE_BYTES / 8];
-    uint32_t uw[MAX_VEC_SIZE_BYTES / 4];
-    int32_t   w[MAX_VEC_SIZE_BYTES / 4];
-    uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
-    int16_t   h[MAX_VEC_SIZE_BYTES / 2];
-    uint8_t  ub[MAX_VEC_SIZE_BYTES / 1];
-    int8_t    b[MAX_VEC_SIZE_BYTES / 1];
-    float32  sf[MAX_VEC_SIZE_BYTES / 4];
-    float16  hf[MAX_VEC_SIZE_BYTES / 2];
-    bfloat16 bf[MAX_VEC_SIZE_BYTES / 2];
+/*
+ * Fill value for a vector's qfloat extended-precision bits (MMVector.ext,
+ * below) whenever an instruction that isn't qfloat-aware writes that
+ * vector: architecturally the ext bits are unspecified in that case, and
+ * this repeating, recognizably-not-zero byte pattern is used instead of an
+ * all-zero fill so stray reads of stale ext state show up distinctly
+ * rather than silently looking like a valid (all-zero) qfloat result.
+ */
+#define V_EXTENDED_BYTEVAL 0x0a
+
+typedef struct {
+    union {
+        uint64_t ud[MAX_VEC_SIZE_BYTES / 8];
+        int64_t   d[MAX_VEC_SIZE_BYTES / 8];
+        uint32_t uw[MAX_VEC_SIZE_BYTES / 4];
+        int32_t   w[MAX_VEC_SIZE_BYTES / 4];
+        uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
+        int16_t   h[MAX_VEC_SIZE_BYTES / 2];
+        uint8_t  ub[MAX_VEC_SIZE_BYTES / 1];
+        int8_t    b[MAX_VEC_SIZE_BYTES / 1];
+        float32  sf[MAX_VEC_SIZE_BYTES / 4];
+        float16  hf[MAX_VEC_SIZE_BYTES / 2];
+        bfloat16 bf[MAX_VEC_SIZE_BYTES / 2];
+    };
+    /*
+     * Extended precision bits for qfloat: one byte per qf32 element (only
+     * the low 4 bits, the LREQ nibble, are meaningful); two qf16 elements
+     * share a byte, 2 bits (LR) each.  Any instruction that overwrites this
+     * vector without itself being qfloat-aware fills these with
+     * V_EXTENDED_BYTEVAL, since they're only meaningful as the tail end of
+     * a qfloat computation.
+     */
+    uint8_t ext[MAX_VEC_SIZE_BYTES / 4];
 } MMVector;
 
-typedef union {
-    uint64_t ud[2 * MAX_VEC_SIZE_BYTES / 8];
-    int64_t   d[2 * MAX_VEC_SIZE_BYTES / 8];
-    uint32_t uw[2 * MAX_VEC_SIZE_BYTES / 4];
-    int32_t   w[2 * MAX_VEC_SIZE_BYTES / 4];
-    uint16_t uh[2 * MAX_VEC_SIZE_BYTES / 2];
-    int16_t   h[2 * MAX_VEC_SIZE_BYTES / 2];
-    uint8_t  ub[2 * MAX_VEC_SIZE_BYTES / 1];
-    int8_t    b[2 * MAX_VEC_SIZE_BYTES / 1];
+typedef struct {
     MMVector v[2];
 } MMVectorPair;
 
diff --git a/hw/hexagon/hexagon_hvx_context.c b/hw/hexagon/hexagon_hvx_context.c
index 3b73498298e..575ea74fc94 100644
--- a/hw/hexagon/hexagon_hvx_context.c
+++ b/hw/hexagon/hexagon_hvx_context.c
@@ -15,6 +15,10 @@ static void hexagon_hvx_context_reset_hold(Object *obj, 
ResetType type)
     HexagonHVXContextState *s = HEXAGON_HVX_CONTEXT(obj);
 
     memset(&s->regs, 0, sizeof(s->regs));
+    for (int i = 0; i < NUM_VREGS; i++) {
+        memset(s->regs.VRegs[i].ext, V_EXTENDED_BYTEVAL,
+               sizeof(s->regs.VRegs[i].ext));
+    }
 }
 
 /* gvec needs VRegs/QRegs 16-aligned within the struct. */
@@ -26,6 +30,7 @@ static const VMStateDescription vmstate_mmvector = {
     .minimum_version_id = 1,
     .fields = (const VMStateField[]){
         VMSTATE_UINT64_ARRAY(ud, MMVector, MAX_VEC_SIZE_BYTES / 8),
+        VMSTATE_UINT8_ARRAY(ext, MMVector, MAX_VEC_SIZE_BYTES / 4),
         VMSTATE_END_OF_LIST()
     }
 };
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index d344284e8a2..b418aa716b8 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -448,6 +448,25 @@ def helper_arg_type(self):
         return "void *"
     def helper_arg_name(self):
         return f"{self.reg_tcg()}_void"
+    def gen_clear_ext(self, f):
+        f.write(code_fmt(f"""\
+                tcg_gen_gvec_dup_imm_var(MO_8, {self.hvx_base()},
+                    {self.hvx_off()} + offsetof(MMVector, ext),
+                    MAX_VEC_SIZE_BYTES / 4, MAX_VEC_SIZE_BYTES / 4,
+                    V_EXTENDED_BYTEVAL);
+            """))
+    def gen_clear_ext_pair(self, f):
+        f.write(code_fmt(f"""\
+                tcg_gen_gvec_dup_imm_var(MO_8, {self.hvx_base()},
+                    {self.hvx_off()} + offsetof(MMVector, ext),
+                    MAX_VEC_SIZE_BYTES / 4, MAX_VEC_SIZE_BYTES / 4,
+                    V_EXTENDED_BYTEVAL);
+                tcg_gen_gvec_dup_imm_var(MO_8, {self.hvx_base()},
+                    {self.hvx_off()} + sizeof(MMVector)
+                        + offsetof(MMVector, ext),
+                    MAX_VEC_SIZE_BYTES / 4, MAX_VEC_SIZE_BYTES / 4,
+                    V_EXTENDED_BYTEVAL);
+            """))
 
 #
 # Every register is either Dest or OldSource or NewSource or ReadWrite
@@ -793,11 +812,13 @@ def decl_tcg(self, f, tag, regno):
         """))
         if not skip_qemu_helper(tag):
             self.decl_tcg_ptr(f)
+        self.gen_clear_ext(f)
     def gen_zero(self, f):
         f.write(code_fmt(f"""\
                 tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()},
                     {self.hvx_off()}, sizeof(MMVector), sizeof(MMVector), 0);
             """))
+        self.gen_clear_ext(f)
     def gen_write(self, f, tag):
         pass
     def helper_hvx_desc(self, f):
@@ -868,11 +889,13 @@ def decl_tcg(self, f, tag, regno):
         """))
         if not skip_qemu_helper(tag):
             self.decl_tcg_ptr(f)
+        self.gen_clear_ext(f)
     def gen_zero(self, f):
         f.write(code_fmt(f"""\
                 tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()},
                     {self.hvx_off()}, sizeof(MMVector), sizeof(MMVector), 0);
             """))
+        self.gen_clear_ext(f)
     def gen_write(self, f, tag):
         pass
     def helper_hvx_desc(self, f):
@@ -911,11 +934,13 @@ def decl_tcg(self, f, tag, regno):
                                      {self.reg_tcg()}_srcoff,
                                      sizeof(MMVector), sizeof(MMVector));
             """))
+        self.gen_clear_ext(f)
     def gen_zero(self, f):
         f.write(code_fmt(f"""\
                 tcg_gen_gvec_dup_imm(MO_64, {self.hvx_off()},
                     sizeof(MMVector), sizeof(MMVector), 0);
             """))
+        self.gen_clear_ext(f)
     def gen_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_vreg_write(ctx, {self.hvx_base()}, {self.hvx_off()},
@@ -948,11 +973,13 @@ def decl_tcg(self, f, tag, regno):
         """))
         if not skip_qemu_helper(tag):
             self.decl_tcg_ptr(f)
+        self.gen_clear_ext_pair(f)
     def gen_zero(self, f):
         f.write(code_fmt(f"""\
             tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()}, 
{self.hvx_off()},
                 sizeof(MMVectorPair), sizeof(MMVectorPair), 0);
         """))
+        self.gen_clear_ext_pair(f)
     def gen_write(self, f, tag):
         pass
     def helper_hvx_desc(self, f):
@@ -1026,11 +1053,13 @@ def decl_tcg(self, f, tag, regno):
         """))
         if not skip_qemu_helper(tag):
             self.decl_tcg_ptr(f)
+        self.gen_clear_ext_pair(f)
     def gen_zero(self, f):
         f.write(code_fmt(f"""\
             tcg_gen_gvec_dup_imm_var(MO_64, {self.hvx_base()}, 
{self.hvx_off()},
                 sizeof(MMVectorPair), sizeof(MMVectorPair), 0);
         """))
+        self.gen_clear_ext_pair(f)
     def gen_write(self, f, tag):
         f.write(code_fmt(f"""\
             gen_vreg_write_pair(ctx, {self.hvx_base()}, {self.hvx_off()},
-- 
2.34.1

Reply via email to