ppc-7.0 queue :
* Clang fixes * Vector/VSX instruction batch fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmIjHL4ACgkQUaNDx8/7 7KH+sg/+JZW/X+U7uZRT9vK6vS4jqFG7gn55ouZKSvAQtPUMtUFdkEL/jeA3IuHh kRvmjGwWjtjgM9TIiJsVBo8yJeMqUO8f6AKUtaQU/3vT4CPO2Jbd8X0A58OOoe4I M3fzWf/18bAYPPEZAxmlJ8f8LEPsBOLM0tQ2py7JkVpUQU3WcP7/YgXbYRH1l+9k m1lMyXGZ/dQDxkFel9TGcfuHXVecBngyx4O1pJ1JkHduo+bLAi6h5HJgdj1wEVfr 5vyqn7OULm6bPXWRb1j+CnCj0QO0VAky4hC4HDGajMlcnG8l/X8Dzs2bD+ua/VbE 1aNkVpuNtuu0ljKfarqMED2no8lPJg4MpKOZvi8O128/bU+IkmJUYI2g73Gr6URL V6/Awh0syy9mi04gsXMD5kCwFLuBNQ5jC3z1aAZNy7Be/l37vzAoN0i53eYAGK3D rBTuMictAKRXKyXQ63VLiYqSdUB6zVoOIM6w3HJxQTQ8YkJ/Hx5cfOGv+lnTIdsK cX4e7s1p8YPSnDOEfEKTk+gnVcTn57FAhNJhelRuC1s2/OI8Gz4n+3eUGmcl04Bq +gcD1UEGMEsQpjMz+ikPuGMZvmF5gPr+9S3DPyMfUOoQJFUI8GOxq9SmUVKC9fki 6oHTHpOvZg8MSJz8gzETq18hwHRKoRb95KzVHWGj1EG0ekjHG2U= =C+wh -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/legoater/tags/pull-ppc-20220305' into staging ppc-7.0 queue : * Clang fixes * Vector/VSX instruction batch fixes # gpg: Signature made Sat 05 Mar 2022 08:18:06 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-ppc-20220305: target/ppc: Add missing helper_reset_fpstatus to helper_XVCVSPBF16 target/ppc: Add missing helper_reset_fpstatus to VSX_MAX_MINC target/ppc: split XXGENPCV macros for readability target/ppc: use andc in vrlqmi target/ppc: use extract/extract2 to create vrlqnm mask target/ppc: use ext32u and deposit in do_vx_vmulhw_i64 target/ppc: Fix vmul[eo]* instructions marked 2.07 tests/tcg/ppc64le: Use Altivec register names in clobber list tests/tcg/ppc64le: emit bcdsub with .long when needed tests/tcg/ppc64le: drop __int128 usage in bcdsub target/ppc: change xs[n]madd[am]sp to use float64r32_muladd tests/tcg/ppc64le: use inline asm instead of __builtin_mtfsf Use long endian options for ppc64 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9d662a6b22
4
configure
vendored
4
configure
vendored
@ -630,10 +630,10 @@ case "$cpu" in
|
||||
ppc)
|
||||
CPU_CFLAGS="-m32" ;;
|
||||
ppc64)
|
||||
CPU_CFLAGS="-m64 -mbig" ;;
|
||||
CPU_CFLAGS="-m64 -mbig-endian" ;;
|
||||
ppc64le)
|
||||
cpu="ppc64"
|
||||
CPU_CFLAGS="-m64 -mlittle" ;;
|
||||
CPU_CFLAGS="-m64 -mlittle-endian" ;;
|
||||
|
||||
s390)
|
||||
CPU_CFLAGS="-m31" ;;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -64,9 +64,9 @@ fi
|
||||
: ${cross_cc_ppc="powerpc-linux-gnu-gcc"}
|
||||
: ${cross_cc_cflags_ppc="-m32"}
|
||||
: ${cross_cc_ppc64="powerpc64-linux-gnu-gcc"}
|
||||
: ${cross_cc_cflags_ppc64="-m64 -mbig"}
|
||||
: ${cross_cc_cflags_ppc64="-m64 -mbig-endian"}
|
||||
: ${cross_cc_ppc64le="$cross_cc_ppc64"}
|
||||
: ${cross_cc_cflags_ppc64le="-m64 -mlittle"}
|
||||
: ${cross_cc_cflags_ppc64le="-m64 -mlittle-endian"}
|
||||
: ${cross_cc_riscv64="riscv64-linux-gnu-gcc"}
|
||||
: ${cross_cc_s390x="s390x-linux-gnu-gcc"}
|
||||
: ${cross_cc_sh4="sh4-linux-gnu-gcc"}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define CRF_LT (1 << 3)
|
||||
#define CRF_GT (1 << 2)
|
||||
@ -8,24 +9,50 @@
|
||||
#define CRF_SO (1 << 0)
|
||||
#define UNDEF 0
|
||||
|
||||
#define BCDSUB(vra, vrb, ps) \
|
||||
asm ("bcdsub. %1,%2,%3,%4;" \
|
||||
"mfocrf %0,0b10;" \
|
||||
: "=r" (cr), "=v" (vrt) \
|
||||
: "v" (vra), "v" (vrb), "i" (ps) \
|
||||
: );
|
||||
#ifdef __has_builtin
|
||||
#if !__has_builtin(__builtin_bcdsub)
|
||||
#define NO_BUILTIN_BCDSUB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TEST(vra, vrb, ps, exp_res, exp_cr6) \
|
||||
do { \
|
||||
__int128 vrt = 0; \
|
||||
int cr = 0; \
|
||||
BCDSUB(vra, vrb, ps); \
|
||||
if (exp_res) \
|
||||
assert(vrt == exp_res); \
|
||||
assert((cr >> 4) == exp_cr6); \
|
||||
#ifdef NO_BUILTIN_BCDSUB
|
||||
#define BCDSUB(T, A, B, PS) \
|
||||
".long 4 << 26 | (" #T ") << 21 | (" #A ") << 16 | (" #B ") << 11" \
|
||||
" | 1 << 10 | (" #PS ") << 9 | 65\n\t"
|
||||
#else
|
||||
#define BCDSUB(T, A, B, PS) "bcdsub. " #T ", " #A ", " #B ", " #PS "\n\t"
|
||||
#endif
|
||||
|
||||
#define TEST(AH, AL, BH, BL, PS, TH, TL, CR6) \
|
||||
do { \
|
||||
int cr = 0; \
|
||||
uint64_t th, tl; \
|
||||
/* \
|
||||
* Use GPR pairs to load the VSR values and place the resulting VSR and\
|
||||
* CR6 in th, tl, and cr. Note that we avoid newer instructions (e.g., \
|
||||
* mtvsrdd/mfvsrld) so we can run this test on POWER8 machines. \
|
||||
*/ \
|
||||
asm ("mtvsrd 32, %3\n\t" \
|
||||
"mtvsrd 33, %4\n\t" \
|
||||
"xxmrghd 32, 32, 33\n\t" \
|
||||
"mtvsrd 33, %5\n\t" \
|
||||
"mtvsrd 34, %6\n\t" \
|
||||
"xxmrghd 33, 33, 34\n\t" \
|
||||
BCDSUB(0, 0, 1, PS) \
|
||||
"mfocrf %0, 0b10\n\t" \
|
||||
"mfvsrd %1, 32\n\t" \
|
||||
"xxswapd 32, 32\n\t" \
|
||||
"mfvsrd %2, 32\n\t" \
|
||||
: "=r" (cr), "=r" (th), "=r" (tl) \
|
||||
: "r" (AH), "r" (AL), "r" (BH), "r" (BL) \
|
||||
: "v0", "v1", "v2"); \
|
||||
if (TH != UNDEF || TL != UNDEF) { \
|
||||
assert(tl == TL); \
|
||||
assert(th == TH); \
|
||||
} \
|
||||
assert((cr >> 4) == CR6); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Unbounded result is equal to zero:
|
||||
* sign = (PS) ? 0b1111 : 0b1100
|
||||
@ -33,13 +60,13 @@
|
||||
*/
|
||||
void test_bcdsub_eq(void)
|
||||
{
|
||||
__int128 a, b;
|
||||
|
||||
/* maximum positive BCD value */
|
||||
a = b = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c);
|
||||
|
||||
TEST(a, b, 0, 0xc, CRF_EQ);
|
||||
TEST(a, b, 1, 0xf, CRF_EQ);
|
||||
TEST(0x9999999999999999, 0x999999999999999c,
|
||||
0x9999999999999999, 0x999999999999999c,
|
||||
0, 0x0, 0xc, CRF_EQ);
|
||||
TEST(0x9999999999999999, 0x999999999999999c,
|
||||
0x9999999999999999, 0x999999999999999c,
|
||||
1, 0x0, 0xf, CRF_EQ);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -49,21 +76,16 @@ void test_bcdsub_eq(void)
|
||||
*/
|
||||
void test_bcdsub_gt(void)
|
||||
{
|
||||
__int128 a, b, c;
|
||||
/* maximum positive and negative one BCD values */
|
||||
TEST(0x9999999999999999, 0x999999999999999c, 0x0, 0x1d, 0,
|
||||
0x0, 0xc, (CRF_GT | CRF_SO));
|
||||
TEST(0x9999999999999999, 0x999999999999999c, 0x0, 0x1d, 1,
|
||||
0x0, 0xf, (CRF_GT | CRF_SO));
|
||||
|
||||
/* maximum positive BCD value */
|
||||
a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999c);
|
||||
|
||||
/* negative one BCD value */
|
||||
b = (__int128) 0x1d;
|
||||
|
||||
TEST(a, b, 0, 0xc, (CRF_GT | CRF_SO));
|
||||
TEST(a, b, 1, 0xf, (CRF_GT | CRF_SO));
|
||||
|
||||
c = (((__int128) 0x9999999999999999) << 64 | 0x999999999999998c);
|
||||
|
||||
TEST(c, b, 0, a, CRF_GT);
|
||||
TEST(c, b, 1, (a | 0x3), CRF_GT);
|
||||
TEST(0x9999999999999999, 0x999999999999998c, 0x0, 0x1d, 0,
|
||||
0x9999999999999999, 0x999999999999999c, CRF_GT);
|
||||
TEST(0x9999999999999999, 0x999999999999998c, 0x0, 0x1d, 1,
|
||||
0x9999999999999999, 0x999999999999999f, CRF_GT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -73,45 +95,27 @@ void test_bcdsub_gt(void)
|
||||
*/
|
||||
void test_bcdsub_lt(void)
|
||||
{
|
||||
__int128 a, b;
|
||||
/* positive zero and positive one BCD values */
|
||||
TEST(0x0, 0xc, 0x0, 0x1c, 0, 0x0, 0x1d, CRF_LT);
|
||||
TEST(0x0, 0xc, 0x0, 0x1c, 1, 0x0, 0x1d, CRF_LT);
|
||||
|
||||
/* positive zero BCD value */
|
||||
a = (__int128) 0xc;
|
||||
|
||||
/* positive one BCD value */
|
||||
b = (__int128) 0x1c;
|
||||
|
||||
TEST(a, b, 0, 0x1d, CRF_LT);
|
||||
TEST(a, b, 1, 0x1d, CRF_LT);
|
||||
|
||||
/* maximum negative BCD value */
|
||||
a = (((__int128) 0x9999999999999999) << 64 | 0x999999999999999d);
|
||||
|
||||
/* positive one BCD value */
|
||||
b = (__int128) 0x1c;
|
||||
|
||||
TEST(a, b, 0, 0xd, (CRF_LT | CRF_SO));
|
||||
TEST(a, b, 1, 0xd, (CRF_LT | CRF_SO));
|
||||
/* maximum negative and positive one BCD values */
|
||||
TEST(0x9999999999999999, 0x999999999999999d, 0x0, 0x1c, 0,
|
||||
0x0, 0xd, (CRF_LT | CRF_SO));
|
||||
TEST(0x9999999999999999, 0x999999999999999d, 0x0, 0x1c, 1,
|
||||
0x0, 0xd, (CRF_LT | CRF_SO));
|
||||
}
|
||||
|
||||
void test_bcdsub_invalid(void)
|
||||
{
|
||||
__int128 a, b;
|
||||
TEST(0x0, 0x1c, 0x0, 0xf00, 0, UNDEF, UNDEF, CRF_SO);
|
||||
TEST(0x0, 0x1c, 0x0, 0xf00, 1, UNDEF, UNDEF, CRF_SO);
|
||||
|
||||
/* positive one BCD value */
|
||||
a = (__int128) 0x1c;
|
||||
b = 0xf00;
|
||||
TEST(0x0, 0xf00, 0x0, 0x1c, 0, UNDEF, UNDEF, CRF_SO);
|
||||
TEST(0x0, 0xf00, 0x0, 0x1c, 1, UNDEF, UNDEF, CRF_SO);
|
||||
|
||||
TEST(a, b, 0, UNDEF, CRF_SO);
|
||||
TEST(a, b, 1, UNDEF, CRF_SO);
|
||||
|
||||
TEST(b, a, 0, UNDEF, CRF_SO);
|
||||
TEST(b, a, 1, UNDEF, CRF_SO);
|
||||
|
||||
a = 0xbad;
|
||||
|
||||
TEST(a, b, 0, UNDEF, CRF_SO);
|
||||
TEST(a, b, 1, UNDEF, CRF_SO);
|
||||
TEST(0x0, 0xbad, 0x0, 0xf00, 0, UNDEF, UNDEF, CRF_SO);
|
||||
TEST(0x0, 0xbad, 0x0, 0xf00, 1, UNDEF, UNDEF, CRF_SO);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#define MTFSF(FLM, FRB) asm volatile ("mtfsf %0, %1" :: "i" (FLM), "f" (FRB))
|
||||
#define MFFS(FRT) asm("mffs %0" : "=f" (FRT))
|
||||
|
||||
#define FPSCR_VE 7 /* Floating-point invalid operation exception enable */
|
||||
#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
|
||||
#define FPSCR_FI 17 /* Floating-point fraction inexact */
|
||||
@ -21,10 +25,7 @@ void sigfpe_handler(int sig, siginfo_t *si, void *ucontext)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
long long ll;
|
||||
} fpscr;
|
||||
uint64_t fpscr;
|
||||
|
||||
struct sigaction sa = {
|
||||
.sa_sigaction = sigfpe_handler,
|
||||
@ -40,10 +41,9 @@ int main(void)
|
||||
prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE);
|
||||
|
||||
/* First test if the FI bit is being set correctly */
|
||||
fpscr.ll = FP_FI;
|
||||
__builtin_mtfsf(0b11111111, fpscr.d);
|
||||
fpscr.d = __builtin_mffs();
|
||||
assert((fpscr.ll & FP_FI) != 0);
|
||||
MTFSF(0b11111111, FP_FI);
|
||||
MFFS(fpscr);
|
||||
assert((fpscr & FP_FI) != 0);
|
||||
|
||||
/* Then test if the deferred exception is being called correctly */
|
||||
sigaction(SIGFPE, &sa, NULL);
|
||||
@ -54,8 +54,7 @@ int main(void)
|
||||
* But if a different exception is chosen si_code check should
|
||||
* change accordingly.
|
||||
*/
|
||||
fpscr.ll = FP_VE | FP_VXSOFT;
|
||||
__builtin_mtfsf(0b11111111, fpscr.d);
|
||||
MTFSF(0b11111111, FP_VE | FP_VXSOFT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -6,16 +6,16 @@
|
||||
#define TEST(INSN, B_HI, B_LO, T_HI, T_LO) \
|
||||
do { \
|
||||
uint64_t th, tl, bh = B_HI, bl = B_LO; \
|
||||
asm("mtvsrd 0, %2\n\t" \
|
||||
"mtvsrd 1, %3\n\t" \
|
||||
"xxmrghd 0, 0, 1\n\t" \
|
||||
INSN " 0, 0\n\t" \
|
||||
"mfvsrd %0, 0\n\t" \
|
||||
"xxswapd 0, 0\n\t" \
|
||||
"mfvsrd %1, 0\n\t" \
|
||||
asm("mtvsrd 32, %2\n\t" \
|
||||
"mtvsrd 33, %3\n\t" \
|
||||
"xxmrghd 32, 32, 33\n\t" \
|
||||
INSN " 32, 32\n\t" \
|
||||
"mfvsrd %0, 32\n\t" \
|
||||
"xxswapd 32, 32\n\t" \
|
||||
"mfvsrd %1, 32\n\t" \
|
||||
: "=r" (th), "=r" (tl) \
|
||||
: "r" (bh), "r" (bl) \
|
||||
: "vs0", "vs1"); \
|
||||
: "v0", "v1"); \
|
||||
printf(INSN "(0x%016" PRIx64 "%016" PRIx64 ") = 0x%016" PRIx64 \
|
||||
"%016" PRIx64 "\n", bh, bl, th, tl); \
|
||||
assert(th == T_HI && tl == T_LO); \
|
||||
|
Loading…
Reference in New Issue
Block a user