2014-07-16 Yvan Roux <yvan.roux@linaro.org>
authoryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Jul 2014 15:39:57 +0000 (15:39 +0000)
committeryroux <yroux@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Jul 2014 15:39:57 +0000 (15:39 +0000)
Backport from trunk r210828, r211103.
2014-05-31  Kugan Vivekanandarajah  <kuganv@linaro.org>

* config/arm/arm.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New define.
(arm_builtins) : Add ARM_BUILTIN_GET_FPSCR and ARM_BUILTIN_SET_FPSCR.
(bdesc_2arg) : Add description for builtins __builtins_arm_set_fpscr
and __builtins_arm_get_fpscr.
(arm_init_builtins) : Initialize builtins __builtins_arm_set_fpscr and
__builtins_arm_get_fpscr.
(arm_expand_builtin) : Expand builtins __builtins_arm_set_fpscr and
__builtins_arm_ldfpscr.
(arm_atomic_assign_expand_fenv): New function.
* config/arm/vfp.md (set_fpscr): New pattern.
(get_fpscr) : Likewise.
* config/arm/unspecs.md (unspecv): Add VUNSPEC_GET_FPSCR and
VUNSPEC_SET_FPSCR.
* doc/extend.texi (AARCH64 Built-in Functions) : Document
__builtins_arm_set_fpscr, __builtins_arm_get_fpscr.

2014-05-23  Kugan Vivekanandarajah  <kuganv@linaro.org>

* config/aarch64/aarch64.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New
define.
* config/aarch64/aarch64-protos.h (aarch64_atomic_assign_expand_fenv):
New function declaration.
* config/aarch64/aarch64-builtins.c (aarch64_builtins) : Add
AARCH64_BUILTIN_GET_FPCR, AARCH64_BUILTIN_SET_FPCR.
AARCH64_BUILTIN_GET_FPSR and AARCH64_BUILTIN_SET_FPSR.
(aarch64_init_builtins) : Initialize builtins
__builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
__builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.
(aarch64_expand_builtin) : Expand builtins __builtins_aarch64_set_fpcr
__builtins_aarch64_get_fpcr, __builtins_aarch64_get_fpsr,
and __builtins_aarch64_set_fpsr.
(aarch64_atomic_assign_expand_fenv): New function.
* config/aarch64/aarch64.md (set_fpcr): New pattern.
(get_fpcr) : Likewise.
(set_fpsr) : Likewise.
(get_fpsr) : Likewise.
(unspecv): Add UNSPECV_GET_FPCR and UNSPECV_SET_FPCR, UNSPECV_GET_FPSR
 and UNSPECV_SET_FPSR.
* doc/extend.texi (AARCH64 Built-in Functions) : Document
__builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
__builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@212672 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog.linaro
gcc/config/aarch64/aarch64-builtins.c
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/arm/arm.c
gcc/config/arm/unspecs.md
gcc/config/arm/vfp.md
gcc/doc/extend.texi

index 76113bc..c0a979a 100644 (file)
@@ -1,5 +1,52 @@
 2014-07-16  Yvan Roux  <yvan.roux@linaro.org>
 
+       Backport from trunk r210828, r211103.
+       2014-05-31  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       * config/arm/arm.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New define.
+       (arm_builtins) : Add ARM_BUILTIN_GET_FPSCR and ARM_BUILTIN_SET_FPSCR.
+       (bdesc_2arg) : Add description for builtins __builtins_arm_set_fpscr
+       and __builtins_arm_get_fpscr.
+       (arm_init_builtins) : Initialize builtins __builtins_arm_set_fpscr and
+       __builtins_arm_get_fpscr.
+       (arm_expand_builtin) : Expand builtins __builtins_arm_set_fpscr and
+       __builtins_arm_ldfpscr.
+       (arm_atomic_assign_expand_fenv): New function.
+       * config/arm/vfp.md (set_fpscr): New pattern.
+       (get_fpscr) : Likewise.
+       * config/arm/unspecs.md (unspecv): Add VUNSPEC_GET_FPSCR and
+       VUNSPEC_SET_FPSCR.
+       * doc/extend.texi (AARCH64 Built-in Functions) : Document
+       __builtins_arm_set_fpscr, __builtins_arm_get_fpscr.
+
+       2014-05-23  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       * config/aarch64/aarch64.c (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New
+       define.
+       * config/aarch64/aarch64-protos.h (aarch64_atomic_assign_expand_fenv):
+       New function declaration.
+       * config/aarch64/aarch64-builtins.c (aarch64_builtins) : Add
+       AARCH64_BUILTIN_GET_FPCR, AARCH64_BUILTIN_SET_FPCR.
+       AARCH64_BUILTIN_GET_FPSR and AARCH64_BUILTIN_SET_FPSR.
+       (aarch64_init_builtins) : Initialize builtins
+       __builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
+       __builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.
+       (aarch64_expand_builtin) : Expand builtins __builtins_aarch64_set_fpcr
+       __builtins_aarch64_get_fpcr, __builtins_aarch64_get_fpsr,
+       and __builtins_aarch64_set_fpsr.
+       (aarch64_atomic_assign_expand_fenv): New function.
+       * config/aarch64/aarch64.md (set_fpcr): New pattern.
+       (get_fpcr) : Likewise.
+       (set_fpsr) : Likewise.
+       (get_fpsr) : Likewise.
+       (unspecv): Add UNSPECV_GET_FPCR and UNSPECV_SET_FPCR, UNSPECV_GET_FPSR
+        and UNSPECV_SET_FPSR.
+       * doc/extend.texi (AARCH64 Built-in Functions) : Document
+       __builtins_aarch64_set_fpcr, __builtins_aarch64_get_fpcr.
+       __builtins_aarch64_set_fpsr and __builtins_aarch64_get_fpsr.
+
+2014-07-16  Yvan Roux  <yvan.roux@linaro.org>
+
        Backport from trunk r210355.
        2014-05-13  Ian Bolton  <ian.bolton@arm.com>
 
index a301982..afd568e 100644 (file)
@@ -394,6 +394,12 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
 enum aarch64_builtins
 {
   AARCH64_BUILTIN_MIN,
+
+  AARCH64_BUILTIN_GET_FPCR,
+  AARCH64_BUILTIN_SET_FPCR,
+  AARCH64_BUILTIN_GET_FPSR,
+  AARCH64_BUILTIN_SET_FPSR,
+
   AARCH64_SIMD_BUILTIN_BASE,
 #include "aarch64-simd-builtins.def"
   AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE
@@ -775,6 +781,24 @@ aarch64_init_simd_builtins (void)
 void
 aarch64_init_builtins (void)
 {
+  tree ftype_set_fpr
+    = build_function_type_list (void_type_node, unsigned_type_node, NULL);
+  tree ftype_get_fpr
+    = build_function_type_list (unsigned_type_node, NULL);
+
+  aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
+    = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr,
+                           AARCH64_BUILTIN_GET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
+  aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
+    = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr,
+                           AARCH64_BUILTIN_SET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
+  aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
+    = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr,
+                           AARCH64_BUILTIN_GET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
+  aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
+    = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr,
+                           AARCH64_BUILTIN_SET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
+
   if (TARGET_SIMD)
     aarch64_init_simd_builtins ();
 }
@@ -987,6 +1011,36 @@ aarch64_expand_builtin (tree exp,
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   int fcode = DECL_FUNCTION_CODE (fndecl);
+  int icode;
+  rtx pat, op0;
+  tree arg0;
+
+  switch (fcode)
+    {
+    case AARCH64_BUILTIN_GET_FPCR:
+    case AARCH64_BUILTIN_SET_FPCR:
+    case AARCH64_BUILTIN_GET_FPSR:
+    case AARCH64_BUILTIN_SET_FPSR:
+      if ((fcode == AARCH64_BUILTIN_GET_FPCR)
+         || (fcode == AARCH64_BUILTIN_GET_FPSR))
+       {
+         icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?
+           CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
+         target = gen_reg_rtx (SImode);
+         pat = GEN_FCN (icode) (target);
+       }
+      else
+       {
+         target = NULL_RTX;
+         icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?
+           CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
+         arg0 = CALL_EXPR_ARG (exp, 0);
+         op0 = expand_normal (arg0);
+         pat = GEN_FCN (icode) (op0);
+       }
+      emit_insn (pat);
+      return target;
+    }
 
   if (fcode >= AARCH64_SIMD_BUILTIN_BASE)
     return aarch64_simd_expand_builtin (fcode, exp, target);
@@ -1260,6 +1314,106 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
   return changed;
 }
 
+void
+aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+  const unsigned AARCH64_FE_INVALID = 1;
+  const unsigned AARCH64_FE_DIVBYZERO = 2;
+  const unsigned AARCH64_FE_OVERFLOW = 4;
+  const unsigned AARCH64_FE_UNDERFLOW = 8;
+  const unsigned AARCH64_FE_INEXACT = 16;
+  const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
+                                                       | AARCH64_FE_DIVBYZERO
+                                                       | AARCH64_FE_OVERFLOW
+                                                       | AARCH64_FE_UNDERFLOW
+                                                       | AARCH64_FE_INEXACT);
+  const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
+  tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
+  tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
+  tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
+  tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
+
+  /* Generate the equivalence of :
+       unsigned int fenv_cr;
+       fenv_cr = __builtin_aarch64_get_fpcr ();
+
+       unsigned int fenv_sr;
+       fenv_sr = __builtin_aarch64_get_fpsr ();
+
+       Now set all exceptions to non-stop
+       unsigned int mask_cr
+               = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
+       unsigned int masked_cr;
+       masked_cr = fenv_cr & mask_cr;
+
+       And clear all exception flags
+       unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
+       unsigned int masked_cr;
+       masked_sr = fenv_sr & mask_sr;
+
+       __builtin_aarch64_set_cr (masked_cr);
+       __builtin_aarch64_set_sr (masked_sr);  */
+
+  fenv_cr = create_tmp_var (unsigned_type_node, NULL);
+  fenv_sr = create_tmp_var (unsigned_type_node, NULL);
+
+  get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
+  set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
+  get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
+  set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
+
+  mask_cr = build_int_cst (unsigned_type_node,
+                          ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
+  mask_sr = build_int_cst (unsigned_type_node,
+                          ~(AARCH64_FE_ALL_EXCEPT));
+
+  ld_fenv_cr = build2 (MODIFY_EXPR, unsigned_type_node,
+                   fenv_cr, build_call_expr (get_fpcr, 0));
+  ld_fenv_sr = build2 (MODIFY_EXPR, unsigned_type_node,
+                   fenv_sr, build_call_expr (get_fpsr, 0));
+
+  masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
+  masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
+
+  hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
+  hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
+
+  hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
+                       hold_fnclex_sr);
+  masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
+                       masked_fenv_sr);
+  ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
+
+  *hold = build2 (COMPOUND_EXPR, void_type_node,
+                 build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
+                 hold_fnclex);
+
+  /* Store the value of masked_fenv to clear the exceptions:
+     __builtin_aarch64_set_fpsr (masked_fenv_sr);  */
+
+  *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
+
+  /* Generate the equivalent of :
+       unsigned int new_fenv_var;
+       new_fenv_var = __builtin_aarch64_get_fpsr ();
+
+       __builtin_aarch64_set_fpsr (fenv_sr);
+
+       __atomic_feraiseexcept (new_fenv_var);  */
+
+  new_fenv_var = create_tmp_var (unsigned_type_node, NULL);
+  reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
+                       new_fenv_var, build_call_expr (get_fpsr, 0));
+  restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
+  atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+  update_call = build_call_expr (atomic_feraiseexcept, 1,
+                                fold_convert (integer_type_node, new_fenv_var));
+  *update = build2 (COMPOUND_EXPR, void_type_node,
+                   build2 (COMPOUND_EXPR, void_type_node,
+                           reload_fenv, restore_fnenv), update_call);
+}
+
+
 #undef AARCH64_CHECK_BUILTIN_MODE
 #undef AARCH64_FIND_FRINT_VARIANT
 #undef BUILTIN_DX
index a05605b..68d488d 100644 (file)
@@ -306,4 +306,5 @@ extern void aarch64_split_combinev16qi (rtx operands[3]);
 extern void aarch64_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
 extern bool
 aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
+void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *);
 #endif /* GCC_AARCH64_PROTOS_H */
index 2f792d3..8936560 100644 (file)
@@ -9507,6 +9507,10 @@ aarch64_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \
   aarch64_autovectorize_vector_sizes
 
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV \
+  aarch64_atomic_assign_expand_fenv
+
 /* Section anchor support.  */
 
 #undef TARGET_MIN_ANCHOR_OFFSET
index 71c8309..c86dd5f 100644 (file)
 
 (define_c_enum "unspecv" [
     UNSPECV_EH_RETURN          ; Represent EH_RETURN
+    UNSPECV_GET_FPCR           ; Represent fetch of FPCR content.
+    UNSPECV_SET_FPCR           ; Represent assign of FPCR content.
+    UNSPECV_GET_FPSR           ; Represent fetch of FPSR content.
+    UNSPECV_SET_FPSR           ; Represent assign of FPSR content.
   ]
 )
 
   [(set_attr "length" "12")
    (set_attr "type" "multiple")])
 
+;; Write Floating-point Control Register.
+(define_insn "set_fpcr"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
+  ""
+  "msr\\tfpcr, %0\;isb"
+  [(set_attr "type" "mrs")])
+
+;; Read Floating-point Control Register.
+(define_insn "get_fpcr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
+  ""
+  "mrs\\t%0, fpcr"
+  [(set_attr "type" "mrs")])
+
+;; Write Floating-point Status Register.
+(define_insn "set_fpsr"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
+  ""
+  "msr\\tfpsr, %0"
+  [(set_attr "type" "mrs")])
+
+;; Read Floating-point Status Register.
+(define_insn "get_fpsr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
+  ""
+  "mrs\\t%0, fpsr"
+  [(set_attr "type" "mrs")])
+
+
 ;; AdvSIMD Stuff
 (include "aarch64-simd.md")
 
index 55780d4..e3b6cd4 100644 (file)
@@ -59,6 +59,7 @@
 #include "params.h"
 #include "opts.h"
 #include "dumpfile.h"
+#include "gimple-expr.h"
 
 /* Forward definitions of types.  */
 typedef struct minipool_node    Mnode;
@@ -94,6 +95,7 @@ static int thumb_far_jump_used_p (void);
 static bool thumb_force_lr_save (void);
 static unsigned arm_size_return_regs (void);
 static bool arm_assemble_integer (rtx, unsigned int, int);
+static void arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update);
 static void arm_print_operand (FILE *, rtx, int);
 static void arm_print_operand_address (FILE *, rtx);
 static bool arm_print_operand_punct_valid_p (unsigned char code);
@@ -585,6 +587,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE arm_mangle_type
 
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV arm_atomic_assign_expand_fenv
+
 #undef TARGET_BUILD_BUILTIN_VA_LIST
 #define TARGET_BUILD_BUILTIN_VA_LIST arm_build_builtin_va_list
 #undef TARGET_EXPAND_BUILTIN_VA_START
@@ -23462,6 +23467,9 @@ enum arm_builtins
   ARM_BUILTIN_CRC32CH,
   ARM_BUILTIN_CRC32CW,
 
+  ARM_BUILTIN_GET_FPSCR,
+  ARM_BUILTIN_SET_FPSCR,
+
 #undef CRYPTO1
 #undef CRYPTO2
 #undef CRYPTO3
@@ -24260,6 +24268,15 @@ static const struct builtin_description bdesc_2arg[] =
   IWMMXT_BUILTIN2 (iwmmxt_wmacuz, WMACUZ)
   IWMMXT_BUILTIN2 (iwmmxt_wmacsz, WMACSZ)
 
+
+#define FP_BUILTIN(L, U) \
+  {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
+   UNKNOWN, 0},
+
+  FP_BUILTIN (set_fpscr, GET_FPSCR)
+  FP_BUILTIN (get_fpscr, SET_FPSCR)
+#undef FP_BUILTIN
+
 #define CRC32_BUILTIN(L, U) \
   {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \
    UNKNOWN, 0},
@@ -24774,6 +24791,21 @@ arm_init_builtins (void)
 
   if (TARGET_CRC32)
     arm_init_crc32_builtins ();
+
+  if (TARGET_VFP)
+    {
+      tree ftype_set_fpscr
+       = build_function_type_list (void_type_node, unsigned_type_node, NULL);
+      tree ftype_get_fpscr
+       = build_function_type_list (unsigned_type_node, NULL);
+
+      arm_builtin_decls[ARM_BUILTIN_GET_FPSCR]
+       = add_builtin_function ("__builtin_arm_ldfscr", ftype_get_fpscr,
+                               ARM_BUILTIN_GET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
+      arm_builtin_decls[ARM_BUILTIN_SET_FPSCR]
+       = add_builtin_function ("__builtin_arm_stfscr", ftype_set_fpscr,
+                               ARM_BUILTIN_SET_FPSCR, BUILT_IN_MD, NULL, NULL_TREE);
+    }
 }
 
 /* Return the ARM builtin for CODE.  */
@@ -25501,6 +25533,25 @@ arm_expand_builtin (tree exp,
 
   switch (fcode)
     {
+    case ARM_BUILTIN_GET_FPSCR:
+    case ARM_BUILTIN_SET_FPSCR:
+      if (fcode == ARM_BUILTIN_GET_FPSCR)
+       {
+         icode = CODE_FOR_get_fpscr;
+         target = gen_reg_rtx (SImode);
+         pat = GEN_FCN (icode) (target);
+       }
+      else
+       {
+         target = NULL_RTX;
+         icode = CODE_FOR_set_fpscr;
+         arg0 = CALL_EXPR_ARG (exp, 0);
+         op0 = expand_normal (arg0);
+         pat = GEN_FCN (icode) (op0);
+       }
+      emit_insn (pat);
+      return target;
+
     case ARM_BUILTIN_TEXTRMSB:
     case ARM_BUILTIN_TEXTRMUB:
     case ARM_BUILTIN_TEXTRMSH:
@@ -31412,4 +31463,73 @@ arm_const_not_ok_for_debug_p (rtx p)
   return false;
 }
 
+static void
+arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+  const unsigned ARM_FE_INVALID = 1;
+  const unsigned ARM_FE_DIVBYZERO = 2;
+  const unsigned ARM_FE_OVERFLOW = 4;
+  const unsigned ARM_FE_UNDERFLOW = 8;
+  const unsigned ARM_FE_INEXACT = 16;
+  const unsigned HOST_WIDE_INT ARM_FE_ALL_EXCEPT = (ARM_FE_INVALID
+                                                   | ARM_FE_DIVBYZERO
+                                                   | ARM_FE_OVERFLOW
+                                                   | ARM_FE_UNDERFLOW
+                                                   | ARM_FE_INEXACT);
+  const unsigned HOST_WIDE_INT ARM_FE_EXCEPT_SHIFT = 8;
+  tree fenv_var, get_fpscr, set_fpscr, mask, ld_fenv, masked_fenv;
+  tree new_fenv_var, reload_fenv, restore_fnenv;
+  tree update_call, atomic_feraiseexcept, hold_fnclex;
+
+  if (!TARGET_VFP)
+    return;
+
+  /* Generate the equivalent of :
+       unsigned int fenv_var;
+       fenv_var = __builtin_arm_get_fpscr ();
+
+       unsigned int masked_fenv;
+       masked_fenv = fenv_var & mask;
+
+       __builtin_arm_set_fpscr (masked_fenv);  */
+
+  fenv_var = create_tmp_var (unsigned_type_node, NULL);
+  get_fpscr = arm_builtin_decls[ARM_BUILTIN_GET_FPSCR];
+  set_fpscr = arm_builtin_decls[ARM_BUILTIN_SET_FPSCR];
+  mask = build_int_cst (unsigned_type_node,
+                       ~((ARM_FE_ALL_EXCEPT << ARM_FE_EXCEPT_SHIFT)
+                         | ARM_FE_ALL_EXCEPT));
+  ld_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
+                   fenv_var, build_call_expr (get_fpscr, 0));
+  masked_fenv = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, mask);
+  hold_fnclex = build_call_expr (set_fpscr, 1, masked_fenv);
+  *hold = build2 (COMPOUND_EXPR, void_type_node,
+                 build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
+                 hold_fnclex);
+
+  /* Store the value of masked_fenv to clear the exceptions:
+     __builtin_arm_set_fpscr (masked_fenv);  */
+
+  *clear = build_call_expr (set_fpscr, 1, masked_fenv);
+
+  /* Generate the equivalent of :
+       unsigned int new_fenv_var;
+       new_fenv_var = __builtin_arm_get_fpscr ();
+
+       __builtin_arm_set_fpscr (fenv_var);
+
+       __atomic_feraiseexcept (new_fenv_var);  */
+
+  new_fenv_var = create_tmp_var (unsigned_type_node, NULL);
+  reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node, new_fenv_var,
+                       build_call_expr (get_fpscr, 0));
+  restore_fnenv = build_call_expr (set_fpscr, 1, fenv_var);
+  atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+  update_call = build_call_expr (atomic_feraiseexcept, 1,
+                                fold_convert (integer_type_node, new_fenv_var));
+  *update = build2 (COMPOUND_EXPR, void_type_node,
+                   build2 (COMPOUND_EXPR, void_type_node,
+                           reload_fenv, restore_fnenv), update_call);
+}
+
 #include "gt-arm.h"
index 8caa953..147cb80 100644 (file)
   VUNSPEC_SLX          ; Represent a store-register-release-exclusive.
   VUNSPEC_LDA          ; Represent a store-register-acquire.
   VUNSPEC_STL          ; Represent a store-register-release.
+  VUNSPEC_GET_FPSCR    ; Represent fetch of FPSCR content.
+  VUNSPEC_SET_FPSCR    ; Represent assign of FPSCR content.
 ])
 
 ;; Enumerators for NEON unspecs.
index e1a48ee..3c7744f 100644 (file)
    (set_attr "conds" "unconditional")]
 )
 
+;; Write Floating-point Status and Control Register.
+(define_insn "set_fpscr"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_SET_FPSCR)]
+  "TARGET_VFP"
+  "mcr\\tp10, 7, %0, cr1, cr0, 0\\t @SET_FPSCR"
+  [(set_attr "type" "mrs")])
+
+;; Read Floating-point Status and Control Register.
+(define_insn "get_fpscr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(const_int 0)] VUNSPEC_GET_FPSCR))]
+  "TARGET_VFP"
+  "mrc\\tp10, 7, %0, cr1, cr0, 0\\t @GET_FPSCR"
+  [(set_attr "type" "mrs")])
+
+
 ;; Unimplemented insns:
 ;; fldm*
 ;; fstm*
index 10ad6e4..b6e660a 100644 (file)
@@ -9109,6 +9109,7 @@ to those machines.  Generally these generate calls to specific machine
 instructions, but allow the compiler to schedule those calls.
 
 @menu
+* AArch64 Built-in Functions::
 * Alpha Built-in Functions::
 * Altera Nios II Built-in Functions::
 * ARC Built-in Functions::
@@ -9116,6 +9117,7 @@ instructions, but allow the compiler to schedule those calls.
 * ARM iWMMXt Built-in Functions::
 * ARM NEON Intrinsics::
 * ARM ACLE Intrinsics::
+* ARM Floating Point Status and Control Intrinsics::
 * AVR Built-in Functions::
 * Blackfin Built-in Functions::
 * FR-V Built-in Functions::
@@ -9141,6 +9143,18 @@ instructions, but allow the compiler to schedule those calls.
 * TILEPro Built-in Functions::
 @end menu
 
+@node AArch64 Built-in Functions
+@subsection AArch64 Built-in Functions
+
+These built-in functions are available for the AArch64 family of
+processors.
+@smallexample
+unsigned int __builtin_aarch64_get_fpcr ()
+void __builtin_aarch64_set_fpcr (unsigned int)
+unsigned int __builtin_aarch64_get_fpsr ()
+void __builtin_aarch64_set_fpsr (unsigned int)
+@end smallexample
+
 @node Alpha Built-in Functions
 @subsection Alpha Built-in Functions
 
@@ -9917,6 +9931,17 @@ when the @option{-mfpu=neon} switch is used:
 
 @include arm-acle-intrinsics.texi
 
+@node ARM Floating Point Status and Control Intrinsics
+@subsection ARM Floating Point Status and Control Intrinsics
+
+These built-in functions are available for the ARM family of
+processors with floating-point unit.
+
+@smallexample
+unsigned int __builtin_arm_get_fpscr ()
+void __builtin_arm_set_fpscr (unsigned int)
+@end smallexample
+
 @node AVR Built-in Functions
 @subsection AVR Built-in Functions