2
0
Эх сурвалжийг харах

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>
Peter Maydell 3 жил өмнө
parent
commit
9d662a6b22

+ 2 - 2
configure

@@ -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" ;;

+ 22 - 36
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);
     }

+ 21 - 7
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)

+ 16 - 26
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);

+ 36 - 35
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)

+ 2 - 2
tests/tcg/configure.sh

@@ -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"}

+ 74 - 70
tests/tcg/ppc64le/bcdsub.c

@@ -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)       \
-         : );
-
-#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 __has_builtin
+#if !__has_builtin(__builtin_bcdsub)
+#define NO_BUILTIN_BCDSUB
+#endif
+#endif
+
+#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 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);
+    /* 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));
+
+    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 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));
+    /* 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);
+
+    /* 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;
-
-    /* positive one BCD value */
-    a = (__int128) 0x1c;
-    b = 0xf00;
-
-    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);
+    TEST(0x0, 0x1c, 0x0, 0xf00, 0, UNDEF, UNDEF, CRF_SO);
+    TEST(0x0, 0x1c, 0x0, 0xf00, 1, UNDEF, UNDEF, CRF_SO);
 
-    a = 0xbad;
+    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(0x0, 0xbad, 0x0, 0xf00, 0, UNDEF, UNDEF, CRF_SO);
+    TEST(0x0, 0xbad, 0x0, 0xf00, 1, UNDEF, UNDEF, CRF_SO);
 }
 
 int main(void)

+ 9 - 10
tests/tcg/ppc64le/mtfsf.c

@@ -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;
 }

+ 8 - 8
tests/tcg/ppc64le/non_signalling_xscv.c

@@ -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);                               \