Commit 53229a77 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg: Specify optional vector requirements with a list



Replace the single opcode in .opc with a null-terminated
array in .opt_opc.  We still require that all opcodes be
used with the same .vece.

Validate the contents of this list with CONFIG_DEBUG_TCG.
All tcg_gen_*_vec functions will check any list active
during .fniv expansion.  Swap the active list in and out
as we expand other opcodes, or take control away from the
front-end function.

Convert all existing vector aware front ends.

Reviewed-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent ce27c5d1
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -3302,29 +3302,30 @@ static bool trans_SUB_zzi(DisasContext *s, arg_rri_esz *a)

static bool trans_SUBR_zzi(DisasContext *s, arg_rri_esz *a)
{
    static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 };
    static const GVecGen2s op[4] = {
        { .fni8 = tcg_gen_vec_sub8_i64,
          .fniv = tcg_gen_sub_vec,
          .fno = gen_helper_sve_subri_b,
          .opc = INDEX_op_sub_vec,
          .opt_opc = vecop_list,
          .vece = MO_8,
          .scalar_first = true },
        { .fni8 = tcg_gen_vec_sub16_i64,
          .fniv = tcg_gen_sub_vec,
          .fno = gen_helper_sve_subri_h,
          .opc = INDEX_op_sub_vec,
          .opt_opc = vecop_list,
          .vece = MO_16,
          .scalar_first = true },
        { .fni4 = tcg_gen_sub_i32,
          .fniv = tcg_gen_sub_vec,
          .fno = gen_helper_sve_subri_s,
          .opc = INDEX_op_sub_vec,
          .opt_opc = vecop_list,
          .vece = MO_32,
          .scalar_first = true },
        { .fni8 = tcg_gen_sub_i64,
          .fniv = tcg_gen_sub_vec,
          .fno = gen_helper_sve_subri_d,
          .opc = INDEX_op_sub_vec,
          .opt_opc = vecop_list,
          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
          .vece = MO_64,
          .scalar_first = true }
+83 −40
Original line number Diff line number Diff line
@@ -5861,27 +5861,31 @@ static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
    tcg_gen_add_vec(vece, d, d, a);
}

static const TCGOpcode vecop_list_ssra[] = {
    INDEX_op_sari_vec, INDEX_op_add_vec, 0
};

const GVecGen2i ssra_op[4] = {
    { .fni8 = gen_ssra8_i64,
      .fniv = gen_ssra_vec,
      .load_dest = true,
      .opc = INDEX_op_sari_vec,
      .opt_opc = vecop_list_ssra,
      .vece = MO_8 },
    { .fni8 = gen_ssra16_i64,
      .fniv = gen_ssra_vec,
      .load_dest = true,
      .opc = INDEX_op_sari_vec,
      .opt_opc = vecop_list_ssra,
      .vece = MO_16 },
    { .fni4 = gen_ssra32_i32,
      .fniv = gen_ssra_vec,
      .load_dest = true,
      .opc = INDEX_op_sari_vec,
      .opt_opc = vecop_list_ssra,
      .vece = MO_32 },
    { .fni8 = gen_ssra64_i64,
      .fniv = gen_ssra_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .opt_opc = vecop_list_ssra,
      .load_dest = true,
      .opc = INDEX_op_sari_vec,
      .vece = MO_64 },
};

@@ -5915,27 +5919,31 @@ static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
    tcg_gen_add_vec(vece, d, d, a);
}

static const TCGOpcode vecop_list_usra[] = {
    INDEX_op_shri_vec, INDEX_op_add_vec, 0
};

const GVecGen2i usra_op[4] = {
    { .fni8 = gen_usra8_i64,
      .fniv = gen_usra_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_usra,
      .vece = MO_8, },
    { .fni8 = gen_usra16_i64,
      .fniv = gen_usra_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_usra,
      .vece = MO_16, },
    { .fni4 = gen_usra32_i32,
      .fniv = gen_usra_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_usra,
      .vece = MO_32, },
    { .fni8 = gen_usra64_i64,
      .fniv = gen_usra_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_usra,
      .vece = MO_64, },
};

@@ -5993,27 +6001,29 @@ static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
    }
}

static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };

const GVecGen2i sri_op[4] = {
    { .fni8 = gen_shr8_ins_i64,
      .fniv = gen_shr_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_sri,
      .vece = MO_8 },
    { .fni8 = gen_shr16_ins_i64,
      .fniv = gen_shr_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_sri,
      .vece = MO_16 },
    { .fni4 = gen_shr32_ins_i32,
      .fniv = gen_shr_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_sri,
      .vece = MO_32 },
    { .fni8 = gen_shr64_ins_i64,
      .fniv = gen_shr_ins_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .load_dest = true,
      .opc = INDEX_op_shri_vec,
      .opt_opc = vecop_list_sri,
      .vece = MO_64 },
};

@@ -6069,27 +6079,29 @@ static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
    }
}

static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };

const GVecGen2i sli_op[4] = {
    { .fni8 = gen_shl8_ins_i64,
      .fniv = gen_shl_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shli_vec,
      .opt_opc = vecop_list_sli,
      .vece = MO_8 },
    { .fni8 = gen_shl16_ins_i64,
      .fniv = gen_shl_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shli_vec,
      .opt_opc = vecop_list_sli,
      .vece = MO_16 },
    { .fni4 = gen_shl32_ins_i32,
      .fniv = gen_shl_ins_vec,
      .load_dest = true,
      .opc = INDEX_op_shli_vec,
      .opt_opc = vecop_list_sli,
      .vece = MO_32 },
    { .fni8 = gen_shl64_ins_i64,
      .fniv = gen_shl_ins_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .load_dest = true,
      .opc = INDEX_op_shli_vec,
      .opt_opc = vecop_list_sli,
      .vece = MO_64 },
};

@@ -6156,51 +6168,60 @@ static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
 * these tables are shared with AArch64 which does support them.
 */

static const TCGOpcode vecop_list_mla[] = {
    INDEX_op_mul_vec, INDEX_op_add_vec, 0
};

static const TCGOpcode vecop_list_mls[] = {
    INDEX_op_mul_vec, INDEX_op_sub_vec, 0
};

const GVecGen3 mla_op[4] = {
    { .fni4 = gen_mla8_i32,
      .fniv = gen_mla_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mla,
      .vece = MO_8 },
    { .fni4 = gen_mla16_i32,
      .fniv = gen_mla_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mla,
      .vece = MO_16 },
    { .fni4 = gen_mla32_i32,
      .fniv = gen_mla_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mla,
      .vece = MO_32 },
    { .fni8 = gen_mla64_i64,
      .fniv = gen_mla_vec,
      .opc = INDEX_op_mul_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .load_dest = true,
      .opt_opc = vecop_list_mla,
      .vece = MO_64 },
};

const GVecGen3 mls_op[4] = {
    { .fni4 = gen_mls8_i32,
      .fniv = gen_mls_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mls,
      .vece = MO_8 },
    { .fni4 = gen_mls16_i32,
      .fniv = gen_mls_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mls,
      .vece = MO_16 },
    { .fni4 = gen_mls32_i32,
      .fniv = gen_mls_vec,
      .opc = INDEX_op_mul_vec,
      .load_dest = true,
      .opt_opc = vecop_list_mls,
      .vece = MO_32 },
    { .fni8 = gen_mls64_i64,
      .fniv = gen_mls_vec,
      .opc = INDEX_op_mul_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .load_dest = true,
      .opt_opc = vecop_list_mls,
      .vece = MO_64 },
};

@@ -6226,19 +6247,25 @@ static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
    tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
}

static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };

const GVecGen3 cmtst_op[4] = {
    { .fni4 = gen_helper_neon_tst_u8,
      .fniv = gen_cmtst_vec,
      .opt_opc = vecop_list_cmtst,
      .vece = MO_8 },
    { .fni4 = gen_helper_neon_tst_u16,
      .fniv = gen_cmtst_vec,
      .opt_opc = vecop_list_cmtst,
      .vece = MO_16 },
    { .fni4 = gen_cmtst_i32,
      .fniv = gen_cmtst_vec,
      .opt_opc = vecop_list_cmtst,
      .vece = MO_32 },
    { .fni8 = gen_cmtst_i64,
      .fniv = gen_cmtst_vec,
      .prefer_i64 = TCG_TARGET_REG_BITS == 64,
      .opt_opc = vecop_list_cmtst,
      .vece = MO_64 },
};

@@ -6253,26 +6280,30 @@ static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
    tcg_temp_free_vec(x);
}

static const TCGOpcode vecop_list_uqadd[] = {
    INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
};

const GVecGen4 uqadd_op[4] = {
    { .fniv = gen_uqadd_vec,
      .fno = gen_helper_gvec_uqadd_b,
      .opc = INDEX_op_usadd_vec,
      .write_aofs = true,
      .opt_opc = vecop_list_uqadd,
      .vece = MO_8 },
    { .fniv = gen_uqadd_vec,
      .fno = gen_helper_gvec_uqadd_h,
      .opc = INDEX_op_usadd_vec,
      .write_aofs = true,
      .opt_opc = vecop_list_uqadd,
      .vece = MO_16 },
    { .fniv = gen_uqadd_vec,
      .fno = gen_helper_gvec_uqadd_s,
      .opc = INDEX_op_usadd_vec,
      .write_aofs = true,
      .opt_opc = vecop_list_uqadd,
      .vece = MO_32 },
    { .fniv = gen_uqadd_vec,
      .fno = gen_helper_gvec_uqadd_d,
      .opc = INDEX_op_usadd_vec,
      .write_aofs = true,
      .opt_opc = vecop_list_uqadd,
      .vece = MO_64 },
};

@@ -6287,25 +6318,29 @@ static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
    tcg_temp_free_vec(x);
}

static const TCGOpcode vecop_list_sqadd[] = {
    INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
};

const GVecGen4 sqadd_op[4] = {
    { .fniv = gen_sqadd_vec,
      .fno = gen_helper_gvec_sqadd_b,
      .opc = INDEX_op_ssadd_vec,
      .opt_opc = vecop_list_sqadd,
      .write_aofs = true,
      .vece = MO_8 },
    { .fniv = gen_sqadd_vec,
      .fno = gen_helper_gvec_sqadd_h,
      .opc = INDEX_op_ssadd_vec,
      .opt_opc = vecop_list_sqadd,
      .write_aofs = true,
      .vece = MO_16 },
    { .fniv = gen_sqadd_vec,
      .fno = gen_helper_gvec_sqadd_s,
      .opc = INDEX_op_ssadd_vec,
      .opt_opc = vecop_list_sqadd,
      .write_aofs = true,
      .vece = MO_32 },
    { .fniv = gen_sqadd_vec,
      .fno = gen_helper_gvec_sqadd_d,
      .opc = INDEX_op_ssadd_vec,
      .opt_opc = vecop_list_sqadd,
      .write_aofs = true,
      .vece = MO_64 },
};
@@ -6321,25 +6356,29 @@ static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
    tcg_temp_free_vec(x);
}

static const TCGOpcode vecop_list_uqsub[] = {
    INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
};

const GVecGen4 uqsub_op[4] = {
    { .fniv = gen_uqsub_vec,
      .fno = gen_helper_gvec_uqsub_b,
      .opc = INDEX_op_ussub_vec,
      .opt_opc = vecop_list_uqsub,
      .write_aofs = true,
      .vece = MO_8 },
    { .fniv = gen_uqsub_vec,
      .fno = gen_helper_gvec_uqsub_h,
      .opc = INDEX_op_ussub_vec,
      .opt_opc = vecop_list_uqsub,
      .write_aofs = true,
      .vece = MO_16 },
    { .fniv = gen_uqsub_vec,
      .fno = gen_helper_gvec_uqsub_s,
      .opc = INDEX_op_ussub_vec,
      .opt_opc = vecop_list_uqsub,
      .write_aofs = true,
      .vece = MO_32 },
    { .fniv = gen_uqsub_vec,
      .fno = gen_helper_gvec_uqsub_d,
      .opc = INDEX_op_ussub_vec,
      .opt_opc = vecop_list_uqsub,
      .write_aofs = true,
      .vece = MO_64 },
};
@@ -6355,25 +6394,29 @@ static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
    tcg_temp_free_vec(x);
}

static const TCGOpcode vecop_list_sqsub[] = {
    INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
};

const GVecGen4 sqsub_op[4] = {
    { .fniv = gen_sqsub_vec,
      .fno = gen_helper_gvec_sqsub_b,
      .opc = INDEX_op_sssub_vec,
      .opt_opc = vecop_list_sqsub,
      .write_aofs = true,
      .vece = MO_8 },
    { .fniv = gen_sqsub_vec,
      .fno = gen_helper_gvec_sqsub_h,
      .opc = INDEX_op_sssub_vec,
      .opt_opc = vecop_list_sqsub,
      .write_aofs = true,
      .vece = MO_16 },
    { .fniv = gen_sqsub_vec,
      .fno = gen_helper_gvec_sqsub_s,
      .opc = INDEX_op_sssub_vec,
      .opt_opc = vecop_list_sqsub,
      .write_aofs = true,
      .vece = MO_32 },
    { .fniv = gen_sqsub_vec,
      .fno = gen_helper_gvec_sqsub_d,
      .opc = INDEX_op_sssub_vec,
      .opt_opc = vecop_list_sqsub,
      .write_aofs = true,
      .vece = MO_64 },
};
+6 −1
Original line number Diff line number Diff line
@@ -566,10 +566,15 @@ static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
}                                                                       \
static void glue(gen_, NAME)(DisasContext *ctx)                         \
{                                                                       \
    static const TCGOpcode vecop_list[] = {                             \
        glue(glue(INDEX_op_, NORM), _vec),                              \
        glue(glue(INDEX_op_, SAT), _vec),                               \
        INDEX_op_cmp_vec, 0                                             \
    };                                                                  \
    static const GVecGen4 g = {                                         \
        .fniv = glue(glue(gen_, NAME), _vec),                           \
        .fno = glue(gen_helper_, NAME),                                 \
        .opc = glue(glue(INDEX_op_, SAT), _vec),                        \
        .opt_opc = vecop_list,                                          \
        .write_aofs = true,                                             \
        .vece = VECE,                                                   \
    };                                                                  \
+144 −105

File changed.

Preview size limit exceeded, changes collapsed.

+12 −12
Original line number Diff line number Diff line
@@ -91,8 +91,8 @@ typedef struct {
    void (*fniv)(unsigned, TCGv_vec, TCGv_vec);
    /* Expand out-of-line helper w/descriptor.  */
    gen_helper_gvec_2 *fno;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The data argument to the out-of-line helper.  */
    int32_t data;
    /* The vector element size, if applicable.  */
@@ -112,8 +112,8 @@ typedef struct {
    gen_helper_gvec_2 *fno;
    /* Expand out-of-line helper w/descriptor, data as argument.  */
    gen_helper_gvec_2i *fnoi;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The vector element size, if applicable.  */
    uint8_t vece;
    /* Prefer i64 to v64.  */
@@ -131,8 +131,8 @@ typedef struct {
    void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
    /* Expand out-of-line helper w/descriptor.  */
    gen_helper_gvec_2i *fno;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The data argument to the out-of-line helper.  */
    uint32_t data;
    /* The vector element size, if applicable.  */
@@ -152,8 +152,8 @@ typedef struct {
    void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
    /* Expand out-of-line helper w/descriptor.  */
    gen_helper_gvec_3 *fno;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The data argument to the out-of-line helper.  */
    int32_t data;
    /* The vector element size, if applicable.  */
@@ -175,8 +175,8 @@ typedef struct {
    void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, int64_t);
    /* Expand out-of-line helper w/descriptor, data in descriptor.  */
    gen_helper_gvec_3 *fno;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The vector element size, if applicable.  */
    uint8_t vece;
    /* Prefer i64 to v64.  */
@@ -194,8 +194,8 @@ typedef struct {
    void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec);
    /* Expand out-of-line helper w/descriptor.  */
    gen_helper_gvec_4 *fno;
    /* The opcode, if any, to which this corresponds.  */
    TCGOpcode opc;
    /* The optional opcodes, if any, utilized by .fniv.  */
    const TCGOpcode *opt_opc;
    /* The data argument to the out-of-line helper.  */
    int32_t data;
    /* The vector element size, if applicable.  */
Loading