Richard Henderson <richard.hender...@linaro.org> writes: > Reviewed-by: Peter Maydell <peter.mayd...@linaro.org> > Signed-off-by: Richard Henderson <richard.hender...@linaro.org>
Reviewed-by: Alex Bennée <alex.ben...@linaro.org> > --- > target/arm/translate-a64.c | 93 > +++++++++++++++++++++++++++++----------------- > 1 file changed, 59 insertions(+), 34 deletions(-) > > diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c > index 38400560db..c928c4787c 100644 > --- a/target/arm/translate-a64.c > +++ b/target/arm/translate-a64.c > @@ -7209,6 +7209,28 @@ static void > disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn) > } > } > > +/* CMTST : test is "if (X & Y != 0)". */ > +static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b) > +{ > + tcg_gen_and_i32(d, a, b); > + tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0); > + tcg_gen_neg_i32(d, d); > +} > + > +static void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b) > +{ > + tcg_gen_and_i64(d, a, b); > + tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0); > + tcg_gen_neg_i64(d, d); > +} > + > +static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b) > +{ > + tcg_gen_and_vec(vece, d, a, b); > + tcg_gen_dupi_vec(vece, a, 0); > + tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a); > +} > + > static void handle_3same_64(DisasContext *s, int opcode, bool u, > TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 > tcg_rm) > { > @@ -7252,10 +7274,7 @@ static void handle_3same_64(DisasContext *s, int > opcode, bool u, > cond = TCG_COND_EQ; > goto do_cmop; > } > - /* CMTST : test is "if (X & Y != 0)". */ > - tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm); > - tcg_gen_setcondi_i64(TCG_COND_NE, tcg_rd, tcg_rd, 0); > - tcg_gen_neg_i64(tcg_rd, tcg_rd); > + gen_cmtst_i64(tcg_rd, tcg_rn, tcg_rm); > break; > case 0x8: /* SSHL, USHL */ > if (u) { > @@ -9737,6 +9756,22 @@ static void disas_simd_3same_float(DisasContext *s, > uint32_t insn) > /* Integer op subgroup of C3.6.16. */ > static void disas_simd_3same_int(DisasContext *s, uint32_t insn) > { > + static const GVecGen3 cmtst_op[4] = { > + { .fni4 = gen_helper_neon_tst_u8, > + .fniv = gen_cmtst_vec, > + .vece = MO_8 }, > + { .fni4 = gen_helper_neon_tst_u16, > + .fniv = gen_cmtst_vec, > + .vece = MO_16 }, > + { .fni4 = gen_cmtst_i32, > + .fniv = gen_cmtst_vec, > + .vece = MO_32 }, > + { .fni8 = gen_cmtst_i64, > + .fniv = gen_cmtst_vec, > + .prefer_i64 = TCG_TARGET_REG_BITS == 64, > + .vece = MO_64 }, > + }; > + > int is_q = extract32(insn, 30, 1); > int u = extract32(insn, 29, 1); > int size = extract32(insn, 22, 2); > @@ -9745,6 +9780,7 @@ static void disas_simd_3same_int(DisasContext *s, > uint32_t insn) > int rn = extract32(insn, 5, 5); > int rd = extract32(insn, 0, 5); > int pass; > + TCGCond cond; > > switch (opcode) { > case 0x13: /* MUL, PMUL */ > @@ -9792,6 +9828,25 @@ static void disas_simd_3same_int(DisasContext *s, > uint32_t insn) > gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_add, size); > } > return; > + case 0x11: > + if (!u) { /* CMTST */ > + gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]); > + return; > + } > + /* else CMEQ */ > + cond = TCG_COND_EQ; > + goto do_gvec_cmp; > + case 0x06: /* CMGT, CMHI */ > + cond = u ? TCG_COND_GTU : TCG_COND_GT; > + goto do_gvec_cmp; > + case 0x07: /* CMGE, CMHS */ > + cond = u ? TCG_COND_GEU : TCG_COND_GE; > + do_gvec_cmp: > + tcg_gen_gvec_cmp(cond, size, vec_full_reg_offset(s, rd), > + vec_full_reg_offset(s, rn), > + vec_full_reg_offset(s, rm), > + is_q ? 16 : 8, vec_full_reg_size(s)); > + return; > } > > if (size == 3) { > @@ -9874,26 +9929,6 @@ static void disas_simd_3same_int(DisasContext *s, > uint32_t insn) > genenvfn = fns[size][u]; > break; > } > - case 0x6: /* CMGT, CMHI */ > - { > - static NeonGenTwoOpFn * const fns[3][2] = { > - { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_u8 }, > - { gen_helper_neon_cgt_s16, gen_helper_neon_cgt_u16 }, > - { gen_helper_neon_cgt_s32, gen_helper_neon_cgt_u32 }, > - }; > - genfn = fns[size][u]; > - break; > - } > - case 0x7: /* CMGE, CMHS */ > - { > - static NeonGenTwoOpFn * const fns[3][2] = { > - { gen_helper_neon_cge_s8, gen_helper_neon_cge_u8 }, > - { gen_helper_neon_cge_s16, gen_helper_neon_cge_u16 }, > - { gen_helper_neon_cge_s32, gen_helper_neon_cge_u32 }, > - }; > - genfn = fns[size][u]; > - break; > - } > case 0x8: /* SSHL, USHL */ > { > static NeonGenTwoOpFn * const fns[3][2] = { > @@ -9966,16 +10001,6 @@ static void disas_simd_3same_int(DisasContext *s, > uint32_t insn) > genfn = fns[size][u]; > break; > } > - case 0x11: /* CMTST, CMEQ */ > - { > - static NeonGenTwoOpFn * const fns[3][2] = { > - { gen_helper_neon_tst_u8, gen_helper_neon_ceq_u8 }, > - { gen_helper_neon_tst_u16, gen_helper_neon_ceq_u16 }, > - { gen_helper_neon_tst_u32, gen_helper_neon_ceq_u32 }, > - }; > - genfn = fns[size][u]; > - break; > - } > case 0x13: /* MUL, PMUL */ > if (u) { > /* PMUL */ -- Alex Bennée