aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>2015-02-27 10:15:36 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2015-02-27 10:15:36 +0000
commit35bc11c3590f04250f150a4ab4d3b6e26979c9e8 (patch)
tree7ac1ee3f156eed9b51a85aa2d2fb4fa2d2961ec9
parent004f64e1b05a568d974669c41a5c0f1af77914de (diff)
downloadgcc-35bc11c3590f04250f150a4ab4d3b6e26979c9e8.zip
gcc-35bc11c3590f04250f150a4ab4d3b6e26979c9e8.tar.gz
gcc-35bc11c3590f04250f150a4ab4d3b6e26979c9e8.tar.bz2
S/390: Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV.
gcc/ChangeLog: * config/s390/s390.c: (s390_atomic_assign_expand_fenv): New function. (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): Define macro. From-SVN: r221048
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/s390/s390.c77
2 files changed, 83 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e2e095..39d6d3e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2015-02-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+ * config/s390/s390.c: (s390_atomic_assign_expand_fenv): New
+ function.
+ (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): Define macro.
+
+2015-02-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
* config/s390/s390.c (enum s390_builtin):
Add S390_BUILTIN_S390_SFPC and S390_BUILTIN_S390_EFPC.
(code_for_builtin): Add CODE_FOR_s390_sfpc and CODE_FOR_s390_efpc.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index f4709da..1924f2a 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -12139,6 +12139,80 @@ s390_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
|| size == 4 || (TARGET_ZARCH && size == 8));
}
+/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV hook. */
+
+static void
+s390_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+ tree sfpc = s390_builtin_decls[S390_BUILTIN_S390_SFPC];
+ tree efpc = s390_builtin_decls[S390_BUILTIN_S390_EFPC];
+ tree call_efpc = build_call_expr (efpc, 0);
+ tree fenv_var = create_tmp_var (unsigned_type_node);
+
+#define FPC_EXCEPTION_MASK HOST_WIDE_INT_UC (0xf8000000)
+#define FPC_FLAGS_MASK HOST_WIDE_INT_UC (0x00f80000)
+#define FPC_DXC_MASK HOST_WIDE_INT_UC (0x0000ff00)
+#define FPC_EXCEPTION_MASK_SHIFT HOST_WIDE_INT_UC (24)
+#define FPC_FLAGS_SHIFT HOST_WIDE_INT_UC (16)
+#define FPC_DXC_SHIFT HOST_WIDE_INT_UC (8)
+
+ /* Generates the equivalent of feholdexcept (&fenv_var)
+
+ fenv_var = __builtin_s390_efpc ();
+ __builtin_s390_sfpc (fenv_var & mask) */
+ tree old_fpc = build2 (MODIFY_EXPR, unsigned_type_node, fenv_var, call_efpc);
+ tree new_fpc =
+ build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var,
+ build_int_cst (unsigned_type_node,
+ ~(FPC_DXC_MASK | FPC_FLAGS_MASK |
+ FPC_EXCEPTION_MASK)));
+ tree set_new_fpc = build_call_expr (sfpc, 1, new_fpc);
+ *hold = build2 (COMPOUND_EXPR, void_type_node, old_fpc, set_new_fpc);
+
+ /* Generates the equivalent of feclearexcept (FE_ALL_EXCEPT)
+
+ __builtin_s390_sfpc (__builtin_s390_efpc () & mask) */
+ new_fpc = build2 (BIT_AND_EXPR, unsigned_type_node, call_efpc,
+ build_int_cst (unsigned_type_node,
+ ~(FPC_DXC_MASK | FPC_FLAGS_MASK)));
+ *clear = build_call_expr (sfpc, 1, new_fpc);
+
+ /* Generates the equivalent of feupdateenv (fenv_var)
+
+ old_fpc = __builtin_s390_efpc ();
+ __builtin_s390_sfpc (fenv_var);
+ __atomic_feraiseexcept ((old_fpc & FPC_FLAGS_MASK) >> FPC_FLAGS_SHIFT); */
+
+ old_fpc = create_tmp_var (unsigned_type_node);
+ tree store_old_fpc = build2 (MODIFY_EXPR, void_type_node,
+ old_fpc, call_efpc);
+
+ set_new_fpc = build_call_expr (sfpc, 1, fenv_var);
+
+ tree raise_old_except = build2 (BIT_AND_EXPR, unsigned_type_node, old_fpc,
+ build_int_cst (unsigned_type_node,
+ FPC_FLAGS_MASK));
+ raise_old_except = build2 (RSHIFT_EXPR, unsigned_type_node, raise_old_except,
+ build_int_cst (unsigned_type_node,
+ FPC_FLAGS_SHIFT));
+ tree atomic_feraiseexcept
+ = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+ raise_old_except = build_call_expr (atomic_feraiseexcept,
+ 1, raise_old_except);
+
+ *update = build2 (COMPOUND_EXPR, void_type_node,
+ build2 (COMPOUND_EXPR, void_type_node,
+ store_old_fpc, set_new_fpc),
+ raise_old_except);
+
+#undef FPC_EXCEPTION_MASK
+#undef FPC_FLAGS_MASK
+#undef FPC_DXC_MASK
+#undef FPC_EXCEPTION_MASK_SHIFT
+#undef FPC_FLAGS_SHIFT
+#undef FPC_DXC_SHIFT
+}
+
/* Initialize GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -12330,6 +12404,9 @@ s390_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
s390_use_by_pieces_infrastructure_p
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV s390_atomic_assign_expand_fenv
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"