On 10/4/2026 8:26 PM, Brian Cain wrote:
> 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);
> +            """))
> 

According to previous patch, do we want to use sizeof(MMVector) here?

Reply via email to