@@ -22,6 +22,7 @@
#include "exec/exec-all.h"
#include "internal.h"
#include "fpu/softfloat.h"
+#include "tcg/tcg-gvec-desc.h"
static inline float128 float128_snan_to_qnan(float128 x)
{
@@ -3263,17 +3264,19 @@ VSX_TSTDC(float64)
VSX_TSTDC(float128)
#undef VSX_TSTDC
-void helper_XVTSTDCDP(ppc_vsr_t *t, ppc_vsr_t *b, uint64_t dcmx, uint32_t v)
+void helper_XVTSTDCDP(ppc_vsr_t *t, ppc_vsr_t *b, uint32_t dcmx)
{
int i;
+ dcmx = simd_data(dcmx);
for (i = 0; i < 2; i++) {
t->s64[i] = (int64_t)-float64_tstdc(b->f64[i], dcmx);
}
}
-void helper_XVTSTDCSP(ppc_vsr_t *t, ppc_vsr_t *b, uint64_t dcmx, uint32_t v)
+void helper_XVTSTDCSP(ppc_vsr_t *t, ppc_vsr_t *b, uint32_t dcmx)
{
int i;
+ dcmx = simd_data(dcmx);
for (i = 0; i < 4; i++) {
t->s32[i] = (int32_t)-float32_tstdc(b->f32[i], dcmx);
}
@@ -517,8 +517,8 @@ DEF_HELPER_3(xvcvsxdsp, void, env, vsr, vsr)
DEF_HELPER_3(xvcvuxdsp, void, env, vsr, vsr)
DEF_HELPER_3(xvcvsxwsp, void, env, vsr, vsr)
DEF_HELPER_3(xvcvuxwsp, void, env, vsr, vsr)
-DEF_HELPER_FLAGS_4(XVTSTDCSP, TCG_CALL_NO_RWG, void, vsr, vsr, i64, i32)
-DEF_HELPER_FLAGS_4(XVTSTDCDP, TCG_CALL_NO_RWG, void, vsr, vsr, i64, i32)
+DEF_HELPER_FLAGS_3(XVTSTDCSP, TCG_CALL_NO_RWG, void, vsr, vsr, i32)
+DEF_HELPER_FLAGS_3(XVTSTDCDP, TCG_CALL_NO_RWG, void, vsr, vsr, i32)
DEF_HELPER_3(xvrspi, void, env, vsr, vsr)
DEF_HELPER_3(xvrspic, void, env, vsr, vsr)
DEF_HELPER_3(xvrspim, void, env, vsr, vsr)
@@ -632,6 +632,8 @@ static void gen_mtvsrws(DisasContext *ctx)
#define SGN_MASK_SP 0x8000000080000000ull
#define EXP_MASK_DP 0x7FF0000000000000ull
#define EXP_MASK_SP 0x7F8000007F800000ull
+#define FRC_MASK_DP (~(SGN_MASK_DP | EXP_MASK_DP))
+#define FRC_MASK_SP (~(SGN_MASK_SP | EXP_MASK_SP))
#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -1113,23 +1115,187 @@ GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
+/* test if +Inf */
+static void gen_is_pos_inf(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, exp_msk));
+}
+
+/* test if -Inf */
+static void gen_is_neg_inf(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk | exp_msk));
+}
+
+/* test if +Inf or -Inf */
+static void gen_is_any_inf(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, exp_msk));
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk));
+}
+
+/* test if +0 */
+static void gen_is_pos_zero(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, 0));
+}
+
+/* test if -0 */
+static void gen_is_neg_zero(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk));
+}
+
+/* test if +0 or -0 */
+static void gen_is_any_zero(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, 0));
+}
+
+/* test if +Denormal */
+static void gen_is_pos_denormal(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
+ tcg_constant_vec_matching(t, vece, frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
+ tcg_constant_vec_matching(t, vece, 0));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if -Denormal */
+static void gen_is_neg_denormal(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk | frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_GTU, vece, b, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if +Denormal or -Denormal */
+static void gen_is_any_denormal(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_LE, vece, t, b,
+ tcg_constant_vec_matching(t, vece, frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
+ tcg_constant_vec_matching(t, vece, 0));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if NaN */
+static void gen_is_nan(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, t, b,
+ tcg_constant_vec_matching(t, vece, exp_msk));
+}
+
static bool do_xvtstdc(DisasContext *ctx, arg_XX2_uim *a, unsigned vece)
{
- static const GVecGen2i op[] = {
- {
- .fnoi = gen_helper_XVTSTDCSP,
- .vece = MO_32
- },
- {
- .fnoi = gen_helper_XVTSTDCDP,
- .vece = MO_64
- },
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, 0
+ };
+
+ GVecGen2 op = {
+ .fno = (vece == MO_32) ? gen_helper_XVTSTDCSP : gen_helper_XVTSTDCDP,
+ .vece = vece,
+ .opt_opc = vecop_list
};
REQUIRE_VSX(ctx);
- tcg_gen_gvec_2i(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
- 16, 16, (int32_t)(a->uim), &op[vece - MO_32]);
+ switch (a->uim) {
+ case 0:
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
+ break;
+ case ((1 << 0) | (1 << 1)):
+ /* test if +Denormal or -Denormal */
+ op.fniv = gen_is_any_denormal,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 0):
+ /* test if -Denormal */
+ op.fniv = gen_is_neg_denormal,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 1):
+ /* test if +Denormal */
+ op.fniv = gen_is_pos_denormal,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case ((1 << 2) | (1 << 3)):
+ /* test if +0 or -0 */
+ op.fniv = gen_is_any_zero,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 2):
+ /* test if -0 */
+ op.fniv = gen_is_neg_zero,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 3):
+ /* test if +0 */
+ op.fniv = gen_is_pos_zero,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case ((1 << 4) | (1 << 5)):
+ /* test if +Inf or -Inf */
+ op.fniv = gen_is_any_inf,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 4):
+ /* test if -Inf */
+ op.fniv = gen_is_neg_inf,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 5):
+ /* test if +Inf */
+ op.fniv = gen_is_pos_inf,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ case (1 << 6):
+ /* test if NaN */
+ op.fniv = gen_is_nan,
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16, 16,
+ &op);
+ break;
+ default:
+ tcg_gen_gvec_2_ool(vsr_full_offset(a->xt), vsr_full_offset(a->xb), 16,
+ 16, (int32_t)(a->uim), op.fno);
+ break;
+ }
return true;
}