diff options
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 256 |
1 files changed, 220 insertions, 36 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index 9f9f4e19e0..d4ad2028f1 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -3917,6 +3917,205 @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn, return 1; } +static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a) +{ + tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0); + tcg_gen_neg_i32(d, d); +} + +static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a) +{ + tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0); + tcg_gen_neg_i64(d, d); +} + +static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +{ + TCGv_vec zero = tcg_const_zeros_vec_matching(d); + tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero); + tcg_temp_free_vec(zero); +} + +static const TCGOpcode vecop_list_cmp[] = { + INDEX_op_cmp_vec, 0 +}; + +const GVecGen2 ceq0_op[4] = { + { .fno = gen_helper_gvec_ceq0_b, + .fniv = gen_ceq0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_8 }, + { .fno = gen_helper_gvec_ceq0_h, + .fniv = gen_ceq0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_16 }, + { .fni4 = gen_ceq0_i32, + .fniv = gen_ceq0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_32 }, + { .fni8 = gen_ceq0_i64, + .fniv = gen_ceq0_vec, + .opt_opc = vecop_list_cmp, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, +}; + +static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a) +{ + tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0); + tcg_gen_neg_i32(d, d); +} + +static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a) +{ + tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0); + tcg_gen_neg_i64(d, d); +} + +static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +{ + TCGv_vec zero = tcg_const_zeros_vec_matching(d); + tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero); + tcg_temp_free_vec(zero); +} + +const GVecGen2 cle0_op[4] = { + { .fno = gen_helper_gvec_cle0_b, + .fniv = gen_cle0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_8 }, + { .fno = gen_helper_gvec_cle0_h, + .fniv = gen_cle0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_16 }, + { .fni4 = gen_cle0_i32, + .fniv = gen_cle0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_32 }, + { .fni8 = gen_cle0_i64, + .fniv = gen_cle0_vec, + .opt_opc = vecop_list_cmp, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, +}; + +static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a) +{ + tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0); + tcg_gen_neg_i32(d, d); +} + +static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a) +{ + tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0); + tcg_gen_neg_i64(d, d); +} + +static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +{ + TCGv_vec zero = tcg_const_zeros_vec_matching(d); + tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero); + tcg_temp_free_vec(zero); +} + +const GVecGen2 cge0_op[4] = { + { .fno = gen_helper_gvec_cge0_b, + .fniv = gen_cge0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_8 }, + { .fno = gen_helper_gvec_cge0_h, + .fniv = gen_cge0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_16 }, + { .fni4 = gen_cge0_i32, + .fniv = gen_cge0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_32 }, + { .fni8 = gen_cge0_i64, + .fniv = gen_cge0_vec, + .opt_opc = vecop_list_cmp, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, +}; + +static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a) +{ + tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0); + tcg_gen_neg_i32(d, d); +} + +static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a) +{ + tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0); + tcg_gen_neg_i64(d, d); +} + +static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +{ + TCGv_vec zero = tcg_const_zeros_vec_matching(d); + tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero); + tcg_temp_free_vec(zero); +} + +const GVecGen2 clt0_op[4] = { + { .fno = gen_helper_gvec_clt0_b, + .fniv = gen_clt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_8 }, + { .fno = gen_helper_gvec_clt0_h, + .fniv = gen_clt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_16 }, + { .fni4 = gen_clt0_i32, + .fniv = gen_clt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_32 }, + { .fni8 = gen_clt0_i64, + .fniv = gen_clt0_vec, + .opt_opc = vecop_list_cmp, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, +}; + +static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a) +{ + tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0); + tcg_gen_neg_i32(d, d); +} + +static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a) +{ + tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0); + tcg_gen_neg_i64(d, d); +} + +static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) +{ + TCGv_vec zero = tcg_const_zeros_vec_matching(d); + tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero); + tcg_temp_free_vec(zero); +} + +const GVecGen2 cgt0_op[4] = { + { .fno = gen_helper_gvec_cgt0_b, + .fniv = gen_cgt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_8 }, + { .fno = gen_helper_gvec_cgt0_h, + .fniv = gen_cgt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_16 }, + { .fni4 = gen_cgt0_i32, + .fniv = gen_cgt0_vec, + .opt_opc = vecop_list_cmp, + .vece = MO_32 }, + { .fni8 = gen_cgt0_i64, + .fniv = gen_cgt0_vec, + .opt_opc = vecop_list_cmp, + .prefer_i64 = TCG_TARGET_REG_BITS == 64, + .vece = MO_64 }, +}; + static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift) { tcg_gen_vec_sar8i_i64(a, a, shift); @@ -6481,6 +6680,27 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size); break; + case NEON_2RM_VCEQ0: + tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, + vec_size, &ceq0_op[size]); + break; + case NEON_2RM_VCGT0: + tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, + vec_size, &cgt0_op[size]); + break; + case NEON_2RM_VCLE0: + tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, + vec_size, &cle0_op[size]); + break; + case NEON_2RM_VCGE0: + tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, + vec_size, &cge0_op[size]); + break; + case NEON_2RM_VCLT0: + tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size, + vec_size, &clt0_op[size]); + break; + default: elementwise: for (pass = 0; pass < (q ? 4 : 2); pass++) { @@ -6543,42 +6763,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) default: abort(); } break; - case NEON_2RM_VCGT0: case NEON_2RM_VCLE0: - tmp2 = tcg_const_i32(0); - switch(size) { - case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; - case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; - case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; - default: abort(); - } - tcg_temp_free_i32(tmp2); - if (op == NEON_2RM_VCLE0) { - tcg_gen_not_i32(tmp, tmp); - } - break; - case NEON_2RM_VCGE0: case NEON_2RM_VCLT0: - tmp2 = tcg_const_i32(0); - switch(size) { - case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; - case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; - case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; - default: abort(); - } - tcg_temp_free_i32(tmp2); - if (op == NEON_2RM_VCLT0) { - tcg_gen_not_i32(tmp, tmp); - } - break; - case NEON_2RM_VCEQ0: - tmp2 = tcg_const_i32(0); - switch(size) { - case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; - case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; - case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; - default: abort(); - } - tcg_temp_free_i32(tmp2); - break; case NEON_2RM_VCGT0_F: { TCGv_ptr fpstatus = get_fpstatus_ptr(1); |