On Sat, Sep 26, 2026 at 2:23 PM Brian Cain <[email protected]> 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/hex_common.py b/target/hexagon/hex_common.py
> index 02c54506145..55b8a40fe8c 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);
> +            """))
>

gen_clear_ext() and gen_clear_ext_pair() currently update the
destination vector’s
extension field even when the instruction predicate is false. The following test
demonstrates the issue:

static void test_ext_bits_preserved_on_false_predicate(void)
{
    asm volatile(
        "r0 = #0x11111111\n"
        "v3 = vsplat(r0)\n"
        "v0.x = vsetqfext(v3, r0)\n"
        "r2 = #1\n"
        "v1 = vsplat(r2)\n"
        "r1 = #0\n"
        "p0 = cmp.eq(r1, r2)\n"
        "{\n"
        "    if (p0) v0 = v1\n"
        "}\n"
        "v2 = vgetqfext(v0.x, r0)\n"
        "vmemu(%[out]) = v2\n"
        :
        : [out] "r"(output)
        : "r0", "r1", "r2", "v0", "v1", "v2", "v3", "p0", "memory");

    for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) {
        expect[0].uw[i] = 0x11111111;
    }

    check_output_w(__LINE__, 1);
}

The extension reset needs to be predicated as well. For example:

def gen_clear_ext(self, f, tag):
    predicate = None
    guard = ""
    if is_predicated(tag):
        for regtype, regid in compute_tag_regs(tag, False):
            if regtype == "P":
                predicate = get_register(tag, regtype, regid).reg_tcg()
                break
        assert predicate is not None
        cond = "TCG_COND_NE" if "fLSBOLDNOT" in semdict[tag] else "TCG_COND_EQ"
        guard = f"""
            TCGv {self.reg_tcg()}_ext_pred = tcg_temp_new();
            TCGLabel *{self.reg_tcg()}_ext_skip = gen_new_label();
            tcg_gen_andi_tl({self.reg_tcg()}_ext_pred, {predicate}, 1);
            tcg_gen_brcondi_tl({cond}, {self.reg_tcg()}_ext_pred, 0,
                                {self.reg_tcg()}_ext_skip);
        """
        end_guard = f"""
            gen_set_label({self.reg_tcg()}_ext_skip);
        """
    else:
        end_guard = ""
    f.write(code_fmt(f"""\
            {guard}
            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);
            {end_guard}
        """))

def gen_clear_ext_pair(self, f, tag):
    predicate = None
    guard = ""
    if is_predicated(tag):
        for regtype, regid in compute_tag_regs(tag, False):
            if regtype == "P":
                predicate = get_register(tag, regtype, regid).reg_tcg()
                break
        assert predicate is not None
        cond = "TCG_COND_NE" if "fLSBOLDNOT" in semdict[tag] else "TCG_COND_EQ"
        guard = f"""
            TCGv {self.reg_tcg()}_ext_pred = tcg_temp_new();
            TCGLabel *{self.reg_tcg()}_ext_skip = gen_new_label();
            tcg_gen_andi_tl({self.reg_tcg()}_ext_pred, {predicate}, 1);
            tcg_gen_brcondi_tl({cond}, {self.reg_tcg()}_ext_pred, 0,
                                {self.reg_tcg()}_ext_skip);
        """
        end_guard = f"""
            gen_set_label({self.reg_tcg()}_ext_skip);
        """
    else:
        end_guard = ""
    f.write(code_fmt(f"""\
            {guard}
            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);
            {end_guard}
        """))

Reply via email to