summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/ppc/fpu_helper.c58
-rw-r--r--target/ppc/int_helper.c28
-rw-r--r--target/ppc/translate/vmx-impl.c.inc42
-rw-r--r--target/ppc/translate/vsx-impl.c.inc71
4 files changed, 95 insertions, 104 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 8f970288f5..bd12db960a 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2156,9 +2156,8 @@ VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
* maddflgs - flags for the float*muladd routine that control the
* various forms (madd, msub, nmadd, nmsub)
* sfprf - set FPRF
- * r2sp - round intermediate double precision result to single precision
*/
-#define VSX_MADD(op, nels, tp, fld, maddflgs, sfprf, r2sp) \
+#define VSX_MADD(op, nels, tp, fld, maddflgs, sfprf) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
ppc_vsr_t *s1, ppc_vsr_t *s2, ppc_vsr_t *s3) \
{ \
@@ -2170,20 +2169,7 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
- if (r2sp && (tstat.float_rounding_mode == float_round_nearest_even)) {\
- /* \
- * Avoid double rounding errors by rounding the intermediate \
- * result to odd. \
- */ \
- set_float_rounding_mode(float_round_to_zero, &tstat); \
- t.fld = tp##_muladd(s1->fld, s3->fld, s2->fld, \
- maddflgs, &tstat); \
- t.fld |= (get_float_exception_flags(&tstat) & \
- float_flag_inexact) != 0; \
- } else { \
- t.fld = tp##_muladd(s1->fld, s3->fld, s2->fld, \
- maddflgs, &tstat); \
- } \
+ t.fld = tp##_muladd(s1->fld, s3->fld, s2->fld, maddflgs, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
@@ -2191,10 +2177,6 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
sfprf, GETPC()); \
} \
\
- if (r2sp) { \
- t.fld = do_frsp(env, t.fld, GETPC()); \
- } \
- \
if (sfprf) { \
helper_compute_fprf_float64(env, t.fld); \
} \
@@ -2203,24 +2185,24 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
do_float_check_status(env, GETPC()); \
}
-VSX_MADD(XSMADDDP, 1, float64, VsrD(0), MADD_FLGS, 1, 0)
-VSX_MADD(XSMSUBDP, 1, float64, VsrD(0), MSUB_FLGS, 1, 0)
-VSX_MADD(XSNMADDDP, 1, float64, VsrD(0), NMADD_FLGS, 1, 0)
-VSX_MADD(XSNMSUBDP, 1, float64, VsrD(0), NMSUB_FLGS, 1, 0)
-VSX_MADD(XSMADDSP, 1, float64, VsrD(0), MADD_FLGS, 1, 1)
-VSX_MADD(XSMSUBSP, 1, float64, VsrD(0), MSUB_FLGS, 1, 1)
-VSX_MADD(XSNMADDSP, 1, float64, VsrD(0), NMADD_FLGS, 1, 1)
-VSX_MADD(XSNMSUBSP, 1, float64, VsrD(0), NMSUB_FLGS, 1, 1)
+VSX_MADD(XSMADDDP, 1, float64, VsrD(0), MADD_FLGS, 1)
+VSX_MADD(XSMSUBDP, 1, float64, VsrD(0), MSUB_FLGS, 1)
+VSX_MADD(XSNMADDDP, 1, float64, VsrD(0), NMADD_FLGS, 1)
+VSX_MADD(XSNMSUBDP, 1, float64, VsrD(0), NMSUB_FLGS, 1)
+VSX_MADD(XSMADDSP, 1, float64r32, VsrD(0), MADD_FLGS, 1)
+VSX_MADD(XSMSUBSP, 1, float64r32, VsrD(0), MSUB_FLGS, 1)
+VSX_MADD(XSNMADDSP, 1, float64r32, VsrD(0), NMADD_FLGS, 1)
+VSX_MADD(XSNMSUBSP, 1, float64r32, VsrD(0), NMSUB_FLGS, 1)
-VSX_MADD(xvmadddp, 2, float64, VsrD(i), MADD_FLGS, 0, 0)
-VSX_MADD(xvmsubdp, 2, float64, VsrD(i), MSUB_FLGS, 0, 0)
-VSX_MADD(xvnmadddp, 2, float64, VsrD(i), NMADD_FLGS, 0, 0)
-VSX_MADD(xvnmsubdp, 2, float64, VsrD(i), NMSUB_FLGS, 0, 0)
+VSX_MADD(xvmadddp, 2, float64, VsrD(i), MADD_FLGS, 0)
+VSX_MADD(xvmsubdp, 2, float64, VsrD(i), MSUB_FLGS, 0)
+VSX_MADD(xvnmadddp, 2, float64, VsrD(i), NMADD_FLGS, 0)
+VSX_MADD(xvnmsubdp, 2, float64, VsrD(i), NMSUB_FLGS, 0)
-VSX_MADD(xvmaddsp, 4, float32, VsrW(i), MADD_FLGS, 0, 0)
-VSX_MADD(xvmsubsp, 4, float32, VsrW(i), MSUB_FLGS, 0, 0)
-VSX_MADD(xvnmaddsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0)
-VSX_MADD(xvnmsubsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0)
+VSX_MADD(xvmaddsp, 4, float32, VsrW(i), MADD_FLGS, 0)
+VSX_MADD(xvmsubsp, 4, float32, VsrW(i), MSUB_FLGS, 0)
+VSX_MADD(xvnmaddsp, 4, float32, VsrW(i), NMADD_FLGS, 0)
+VSX_MADD(xvnmsubsp, 4, float32, VsrW(i), NMSUB_FLGS, 0)
/*
* VSX_MADDQ - VSX floating point quad-precision muliply/add
@@ -2540,6 +2522,8 @@ void helper_##name(CPUPPCState *env, \
ppc_vsr_t t = { }; \
bool first; \
\
+ helper_reset_fpstatus(env); \
+ \
if (max) { \
first = tp##_le_quiet(xb->fld, xa->fld, &env->fp_status); \
} else { \
@@ -2790,6 +2774,8 @@ void helper_XVCVSPBF16(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)
ppc_vsr_t t = { };
int i, status;
+ helper_reset_fpstatus(env);
+
for (i = 0; i < 4; i++) {
t.VsrH(2 * i + 1) = float32_to_bfloat16(xb->VsrW(i), &env->fp_status);
}
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index b2b17bb1ca..492f34c499 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -1072,7 +1072,7 @@ void helper_VPERMR(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
*r = result;
}
-#define XXGENPCV(NAME, SZ) \
+#define XXGENPCV_BE_EXP(NAME, SZ) \
void glue(helper_, glue(NAME, _be_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
{ \
ppc_vsr_t tmp; \
@@ -1093,8 +1093,9 @@ void glue(helper_, glue(NAME, _be_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
} \
\
*t = tmp; \
-} \
- \
+}
+
+#define XXGENPCV_BE_COMP(NAME, SZ) \
void glue(helper_, glue(NAME, _be_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
{ \
ppc_vsr_t tmp = { .u64 = { 0, 0 } }; \
@@ -1111,8 +1112,9 @@ void glue(helper_, glue(NAME, _be_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
} \
\
*t = tmp; \
-} \
- \
+}
+
+#define XXGENPCV_LE_EXP(NAME, SZ) \
void glue(helper_, glue(NAME, _le_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
{ \
ppc_vsr_t tmp; \
@@ -1135,8 +1137,9 @@ void glue(helper_, glue(NAME, _le_exp))(ppc_vsr_t *t, ppc_vsr_t *b) \
} \
\
*t = tmp; \
-} \
- \
+}
+
+#define XXGENPCV_LE_COMP(NAME, SZ) \
void glue(helper_, glue(NAME, _le_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
{ \
ppc_vsr_t tmp = { .u64 = { 0, 0 } }; \
@@ -1157,10 +1160,21 @@ void glue(helper_, glue(NAME, _le_comp))(ppc_vsr_t *t, ppc_vsr_t *b)\
*t = tmp; \
}
+#define XXGENPCV(NAME, SZ) \
+ XXGENPCV_BE_EXP(NAME, SZ) \
+ XXGENPCV_BE_COMP(NAME, SZ) \
+ XXGENPCV_LE_EXP(NAME, SZ) \
+ XXGENPCV_LE_COMP(NAME, SZ) \
+
XXGENPCV(XXGENPCVBM, 1)
XXGENPCV(XXGENPCVHM, 2)
XXGENPCV(XXGENPCVWM, 4)
XXGENPCV(XXGENPCVDM, 8)
+
+#undef XXGENPCV_BE_EXP
+#undef XXGENPCV_BE_COMP
+#undef XXGENPCV_LE_EXP
+#undef XXGENPCV_LE_COMP
#undef XXGENPCV
#if defined(HOST_WORDS_BIGENDIAN)
diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc
index f91bee839d..6101bca3fd 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -1088,10 +1088,8 @@ static void do_vrlq_mask(TCGv_i64 mh, TCGv_i64 ml, TCGv_i64 b, TCGv_i64 e)
tcg_gen_or_i64(tl, t1, tl);
/* t = t >> 1 */
- tcg_gen_shli_i64(t0, th, 63);
- tcg_gen_shri_i64(tl, tl, 1);
+ tcg_gen_extract2_i64(tl, tl, th, 1);
tcg_gen_shri_i64(th, th, 1);
- tcg_gen_or_i64(tl, t0, tl);
/* m = m ^ t */
tcg_gen_xor_i64(mh, mh, th);
@@ -1148,10 +1146,8 @@ static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask,
tcg_gen_or_i64(t1, ah, t1);
if (mask || insert) {
- tcg_gen_shri_i64(n, vrb, 8);
- tcg_gen_shri_i64(vrb, vrb, 16);
- tcg_gen_andi_i64(n, n, 0x7f);
- tcg_gen_andi_i64(vrb, vrb, 0x7f);
+ tcg_gen_extract_i64(n, vrb, 8, 7);
+ tcg_gen_extract_i64(vrb, vrb, 16, 7);
do_vrlq_mask(ah, al, vrb, n);
@@ -1161,10 +1157,8 @@ static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask,
if (insert) {
get_avr64(n, a->vrt, true);
get_avr64(vrb, a->vrt, false);
- tcg_gen_not_i64(ah, ah);
- tcg_gen_not_i64(al, al);
- tcg_gen_and_i64(n, n, ah);
- tcg_gen_and_i64(vrb, vrb, al);
+ tcg_gen_andc_i64(n, n, ah);
+ tcg_gen_andc_i64(vrb, vrb, al);
tcg_gen_or_i64(t0, t0, n);
tcg_gen_or_i64(t1, t1, vrb);
}
@@ -3141,14 +3135,14 @@ static bool trans_VMULLD(DisasContext *ctx, arg_VX *a)
return true;
}
-TRANS_FLAGS2(ALTIVEC_207, VMULESB, do_vx_helper, gen_helper_VMULESB)
-TRANS_FLAGS2(ALTIVEC_207, VMULOSB, do_vx_helper, gen_helper_VMULOSB)
-TRANS_FLAGS2(ALTIVEC_207, VMULEUB, do_vx_helper, gen_helper_VMULEUB)
-TRANS_FLAGS2(ALTIVEC_207, VMULOUB, do_vx_helper, gen_helper_VMULOUB)
-TRANS_FLAGS2(ALTIVEC_207, VMULESH, do_vx_helper, gen_helper_VMULESH)
-TRANS_FLAGS2(ALTIVEC_207, VMULOSH, do_vx_helper, gen_helper_VMULOSH)
-TRANS_FLAGS2(ALTIVEC_207, VMULEUH, do_vx_helper, gen_helper_VMULEUH)
-TRANS_FLAGS2(ALTIVEC_207, VMULOUH, do_vx_helper, gen_helper_VMULOUH)
+TRANS_FLAGS(ALTIVEC, VMULESB, do_vx_helper, gen_helper_VMULESB)
+TRANS_FLAGS(ALTIVEC, VMULOSB, do_vx_helper, gen_helper_VMULOSB)
+TRANS_FLAGS(ALTIVEC, VMULEUB, do_vx_helper, gen_helper_VMULEUB)
+TRANS_FLAGS(ALTIVEC, VMULOUB, do_vx_helper, gen_helper_VMULOUB)
+TRANS_FLAGS(ALTIVEC, VMULESH, do_vx_helper, gen_helper_VMULESH)
+TRANS_FLAGS(ALTIVEC, VMULOSH, do_vx_helper, gen_helper_VMULOSH)
+TRANS_FLAGS(ALTIVEC, VMULEUH, do_vx_helper, gen_helper_VMULEUH)
+TRANS_FLAGS(ALTIVEC, VMULOUH, do_vx_helper, gen_helper_VMULOUH)
TRANS_FLAGS2(ALTIVEC_207, VMULESW, do_vx_helper, gen_helper_VMULESW)
TRANS_FLAGS2(ALTIVEC_207, VMULOSW, do_vx_helper, gen_helper_VMULOSW)
TRANS_FLAGS2(ALTIVEC_207, VMULEUW, do_vx_helper, gen_helper_VMULEUW)
@@ -3162,19 +3156,16 @@ static void do_vx_vmulhw_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
{
TCGv_i64 hh, lh, temp;
- uint64_t c;
hh = tcg_temp_new_i64();
lh = tcg_temp_new_i64();
temp = tcg_temp_new_i64();
- c = 0xFFFFFFFF;
-
if (sign) {
tcg_gen_ext32s_i64(lh, a);
tcg_gen_ext32s_i64(temp, b);
} else {
- tcg_gen_andi_i64(lh, a, c);
- tcg_gen_andi_i64(temp, b, c);
+ tcg_gen_ext32u_i64(lh, a);
+ tcg_gen_ext32u_i64(temp, b);
}
tcg_gen_mul_i64(lh, lh, temp);
@@ -3188,8 +3179,7 @@ static void do_vx_vmulhw_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
tcg_gen_mul_i64(hh, hh, temp);
tcg_gen_shri_i64(lh, lh, 32);
- tcg_gen_andi_i64(hh, hh, c << 32);
- tcg_gen_or_i64(t, hh, lh);
+ tcg_gen_deposit_i64(t, hh, lh, 0, 32);
tcg_temp_free_i64(hh);
tcg_temp_free_i64(lh);
diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
index 2ffeab5287..48a97b2d7e 100644
--- a/target/ppc/translate/vsx-impl.c.inc
+++ b/target/ppc/translate/vsx-impl.c.inc
@@ -1204,43 +1204,44 @@ static bool trans_XXPERMX(DisasContext *ctx, arg_8RR_XX4_uim3 *a)
return true;
}
-#define XXGENPCV(NAME) \
-static bool trans_##NAME(DisasContext *ctx, arg_X_imm5 *a) \
-{ \
- TCGv_ptr xt, vrb; \
- \
- REQUIRE_INSNS_FLAGS2(ctx, ISA310); \
- REQUIRE_VSX(ctx); \
- \
- if (a->imm & ~0x3) { \
- gen_invalid(ctx); \
- return true; \
- } \
- \
- xt = gen_vsr_ptr(a->xt); \
- vrb = gen_avr_ptr(a->vrb); \
- \
- switch (a->imm) { \
- case 0b00000: /* Big-Endian expansion */ \
- glue(gen_helper_, glue(NAME, _be_exp))(xt, vrb); \
- break; \
- case 0b00001: /* Big-Endian compression */ \
- glue(gen_helper_, glue(NAME, _be_comp))(xt, vrb); \
- break; \
- case 0b00010: /* Little-Endian expansion */ \
- glue(gen_helper_, glue(NAME, _le_exp))(xt, vrb); \
- break; \
- case 0b00011: /* Little-Endian compression */ \
- glue(gen_helper_, glue(NAME, _le_comp))(xt, vrb); \
- break; \
- } \
- \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(vrb); \
- \
- return true; \
+typedef void (*xxgenpcv_genfn)(TCGv_ptr, TCGv_ptr);
+
+static bool do_xxgenpcv(DisasContext *ctx, arg_X_imm5 *a,
+ const xxgenpcv_genfn fn[4])
+{
+ TCGv_ptr xt, vrb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ if (a->imm & ~0x3) {
+ gen_invalid(ctx);
+ return true;
+ }
+
+ xt = gen_vsr_ptr(a->xt);
+ vrb = gen_avr_ptr(a->vrb);
+
+ fn[a->imm](xt, vrb);
+
+ tcg_temp_free_ptr(xt);
+ tcg_temp_free_ptr(vrb);
+
+ return true;
}
+#define XXGENPCV(NAME) \
+ static bool trans_##NAME(DisasContext *ctx, arg_X_imm5 *a) \
+ { \
+ static const xxgenpcv_genfn fn[4] = { \
+ gen_helper_##NAME##_be_exp, \
+ gen_helper_##NAME##_be_comp, \
+ gen_helper_##NAME##_le_exp, \
+ gen_helper_##NAME##_le_comp, \
+ }; \
+ return do_xxgenpcv(ctx, a, fn); \
+ }
+
XXGENPCV(XXGENPCVBM)
XXGENPCV(XXGENPCVHM)
XXGENPCV(XXGENPCVWM)