diff options
author | Andreas Krebbel <Andreas.Krebbel@de.ibm.com> | 2015-02-27 10:15:36 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2015-02-27 10:15:36 +0000 |
commit | 35bc11c3590f04250f150a4ab4d3b6e26979c9e8 (patch) | |
tree | 7ac1ee3f156eed9b51a85aa2d2fb4fa2d2961ec9 | |
parent | 004f64e1b05a568d974669c41a5c0f1af77914de (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 77 |
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" |