ARMv8-M Security Extension's cmse_nonsecure_call: use __gnu_cmse_nonsecure_call
authorAndre Vieira <andre.simoesdiasvieira@arm.com>
Fri, 2 Dec 2016 15:33:26 +0000 (15:33 +0000)
committerAndre Vieira <avieira@gcc.gnu.org>
Fri, 2 Dec 2016 15:33:26 +0000 (15:33 +0000)
    gcc/ChangeLog:
    2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme  <thomas.preudhomme@arm.com>

* config/arm/arm.c (detect_cmse_nonsecure_call): New.
(cmse_nonsecure_call_clear_caller_saved): New.
(arm_reorg): Use cmse_nonsecure_call_clear_caller_saved.
(arm_function_ok_for_sibcall): Disable sibcalls for
cmse_nonsecure_call.
* config/arm/arm-protos.h (detect_cmse_nonsecure_call): New.
* config/arm/arm.md (call): Handle cmse_nonsecure_entry.
(call_value): Likewise.
(nonsecure_call_internal): New.
(nonsecure_call_value_internal): New.
* config/arm/thumb1.md (*nonsecure_call_reg_thumb1_v5): New.
(*nonsecure_call_value_reg_thumb1_v5): New.
* config/arm/thumb2.md (*nonsecure_call_reg_thumb2): New.
(*nonsecure_call_value_reg_thumb2): New.
* config/arm/unspecs.md (UNSPEC_NONSECURE_MEM): New.

    libgcc/ChangeLog:
    2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
       Thomas Preud'homme  <thomas.preudhomme@arm.com>

* config/arm/cmse_nonsecure_call.S: New.
* config/arm/t-arm: Compile cmse_nonsecure_call.S

    gcc/testsuite/ChangeLog:
    2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme  <thomas.preudhomme@arm.com>

* gcc.target/arm/cmse/cmse.exp: Run tests in mainline dir.
* gcc.target/arm/cmse/cmse-9.c: Added some extra tests.
* gcc.target/arm/cmse/cmse-14.c: New.
* gcc.target/arm/cmse/baseline/bitfield-4.c: New.
* gcc.target/arm/cmse/baseline/bitfield-5.c: New.
* gcc.target/arm/cmse/baseline/bitfield-6.c: New.
* gcc.target/arm/cmse/baseline/bitfield-7.c: New.
* gcc.target/arm/cmse/baseline/bitfield-8.c: New.
* gcc.target/arm/cmse/baseline/bitfield-9.c: New.
* gcc.target/arm/cmse/baseline/bitfield-and-union-1.c: New.
* gcc.target/arm/cmse/baseline/cmse-11.c: New.
* gcc.target/arm/cmse/baseline/cmse-13.c: New.
* gcc.target/arm/cmse/baseline/cmse-6.c: New.
* gcc.target/arm/cmse/baseline/union-1.c: New.
* gcc.target/arm/cmse/baseline/union-2.c: New.
* gcc.target/arm/cmse/mainline/bitfield-4.c: New.
* gcc.target/arm/cmse/mainline/bitfield-5.c: New.
* gcc.target/arm/cmse/mainline/bitfield-6.c: New.
* gcc.target/arm/cmse/mainline/bitfield-7.c: New.
* gcc.target/arm/cmse/mainline/bitfield-8.c: New.
* gcc.target/arm/cmse/mainline/bitfield-9.c: New.
* gcc.target/arm/cmse/mainline/bitfield-and-union-1.c: New.
* gcc.target/arm/cmse/mainline/union-1.c: New.
* gcc.target/arm/cmse/mainline/union-2.c: New.
* gcc.target/arm/cmse/mainline/hard-sp/cmse-13.c: New.
* gcc.target/arm/cmse/mainline/hard-sp/cmse-7.c: New.
* gcc.target/arm/cmse/mainline/hard-sp/cmse-8.c: New.
* gcc.target/arm/cmse/mainline/hard/cmse-13.c: New.
* gcc.target/arm/cmse/mainline/hard/cmse-7.c: New.
* gcc.target/arm/cmse/mainline/hard/cmse-8.c: New.
* gcc.target/arm/cmse/mainline/soft/cmse-13.c: New.
* gcc.target/arm/cmse/mainline/soft/cmse-7.c: New.
* gcc.target/arm/cmse/mainline/soft/cmse-8.c: New.
* gcc.target/arm/cmse/mainline/softfp-sp/cmse-7.c: New.
* gcc.target/arm/cmse/mainline/softfp-sp/cmse-8.c: New.
* gcc.target/arm/cmse/mainline/softfp/cmse-13.c: New.
* gcc.target/arm/cmse/mainline/softfp/cmse-7.c: New.
* gcc.target/arm/cmse/mainline/softfp/cmse-8.c: New.

Co-Authored-By: Thomas Preud'homme <thomas.preudhomme@arm.com>
From-SVN: r243192

49 files changed:
gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/thumb1.md
gcc/config/arm/thumb2.md
gcc/config/arm/unspecs.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-and-union-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/union-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/baseline/union-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/cmse-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/cmse-9.c
gcc/testsuite/gcc.target/arm/cmse/cmse.exp
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-and-union-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/union-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/cmse/mainline/union-2.c [new file with mode: 0644]
libgcc/ChangeLog
libgcc/config/arm/cmse_nonsecure_call.S [new file with mode: 0644]
libgcc/config/arm/t-arm

index ce79fdd107725b529f7d83aaa6dd95d935e849f5..807d40686499c8101c1e032ac5fb473a254c40df 100644 (file)
@@ -1,3 +1,22 @@
+2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+           Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * config/arm/arm.c (detect_cmse_nonsecure_call): New.
+       (cmse_nonsecure_call_clear_caller_saved): New.
+       (arm_reorg): Use cmse_nonsecure_call_clear_caller_saved.
+       (arm_function_ok_for_sibcall): Disable sibcalls for
+       cmse_nonsecure_call.
+       * config/arm/arm-protos.h (detect_cmse_nonsecure_call): New.
+       * config/arm/arm.md (call): Handle cmse_nonsecure_entry.
+       (call_value): Likewise.
+       (nonsecure_call_internal): New.
+       (nonsecure_call_value_internal): New.
+       * config/arm/thumb1.md (*nonsecure_call_reg_thumb1_v5): New.
+       (*nonsecure_call_value_reg_thumb1_v5): New.
+       * config/arm/thumb2.md (*nonsecure_call_reg_thumb2): New.
+       (*nonsecure_call_value_reg_thumb2): New.
+       * config/arm/unspecs.md (UNSPEC_NONSECURE_MEM): New.
+
 2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
index 634a5de05472d562972d9ad84b5858691715714c..05d73ab2271d28ce8d6d49199341d4365f0a2bcb 100644 (file)
@@ -137,6 +137,7 @@ extern int arm_const_double_inline_cost (rtx);
 extern bool arm_const_double_by_parts (rtx);
 extern bool arm_const_double_by_immediates (rtx);
 extern void arm_emit_call_insn (rtx, rtx, bool);
+bool detect_cmse_nonsecure_call (tree);
 extern const char *output_call (rtx *);
 void arm_emit_movpair (rtx, rtx);
 extern const char *output_mov_long_double_arm_from_arm (rtx *);
index a6b07b295e3ca6679b1edd988fcf01929b0e06f3..f1df3a0971010375c116041e38153f96b24e7aae 100644 (file)
@@ -7000,6 +7000,15 @@ arm_function_ok_for_sibcall (tree decl, tree exp)
   if (IS_CMSE_ENTRY (arm_current_func_type ()))
     return false;
 
+  /* We do not allow ARMv8-M non-secure calls to be turned into sibling calls,
+     this would complicate matters for later code generation.  */
+  if (TREE_CODE (exp) == CALL_EXPR)
+    {
+      tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
+      if (lookup_attribute ("cmse_nonsecure_call", TYPE_ATTRIBUTES (fntype)))
+       return false;
+    }
+
   if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (cfun->decl))))
     {
       /* Check that the return value locations are the same.  For
@@ -16654,6 +16663,197 @@ compute_not_to_clear_mask (tree arg_type, rtx arg_rtx, int regno,
   return not_to_clear_mask;
 }
 
+/* Saves callee saved registers, clears callee saved registers and caller saved
+   registers not used to pass arguments before a cmse_nonsecure_call.  And
+   restores the callee saved registers after.  */
+
+static void
+cmse_nonsecure_call_clear_caller_saved (void)
+{
+  basic_block bb;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      rtx_insn *insn;
+
+      FOR_BB_INSNS (bb, insn)
+       {
+         uint64_t to_clear_mask, float_mask;
+         rtx_insn *seq;
+         rtx pat, call, unspec, reg, cleared_reg, tmp;
+         unsigned int regno, maxregno;
+         rtx address;
+         CUMULATIVE_ARGS args_so_far_v;
+         cumulative_args_t args_so_far;
+         tree arg_type, fntype;
+         bool using_r4, first_param = true;
+         function_args_iterator args_iter;
+         uint32_t padding_bits_to_clear[4] = {0U, 0U, 0U, 0U};
+         uint32_t * padding_bits_to_clear_ptr = &padding_bits_to_clear[0];
+
+         if (!NONDEBUG_INSN_P (insn))
+           continue;
+
+         if (!CALL_P (insn))
+           continue;
+
+         pat = PATTERN (insn);
+         gcc_assert (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 0);
+         call = XVECEXP (pat, 0, 0);
+
+         /* Get the real call RTX if the insn sets a value, ie. returns.  */
+         if (GET_CODE (call) == SET)
+             call = SET_SRC (call);
+
+         /* Check if it is a cmse_nonsecure_call.  */
+         unspec = XEXP (call, 0);
+         if (GET_CODE (unspec) != UNSPEC
+             || XINT (unspec, 1) != UNSPEC_NONSECURE_MEM)
+           continue;
+
+         /* Determine the caller-saved registers we need to clear.  */
+         to_clear_mask = (1LL << (NUM_ARG_REGS)) - 1;
+         maxregno = NUM_ARG_REGS - 1;
+         /* Only look at the caller-saved floating point registers in case of
+            -mfloat-abi=hard.  For -mfloat-abi=softfp we will be using the
+            lazy store and loads which clear both caller- and callee-saved
+            registers.  */
+         if (TARGET_HARD_FLOAT_ABI)
+           {
+             float_mask = (1LL << (D7_VFP_REGNUM + 1)) - 1;
+             float_mask &= ~((1LL << FIRST_VFP_REGNUM) - 1);
+             to_clear_mask |= float_mask;
+             maxregno = D7_VFP_REGNUM;
+           }
+
+         /* Make sure the register used to hold the function address is not
+            cleared.  */
+         address = RTVEC_ELT (XVEC (unspec, 0), 0);
+         gcc_assert (MEM_P (address));
+         gcc_assert (REG_P (XEXP (address, 0)));
+         to_clear_mask &= ~(1LL << REGNO (XEXP (address, 0)));
+
+         /* Set basic block of call insn so that df rescan is performed on
+            insns inserted here.  */
+         set_block_for_insn (insn, bb);
+         df_set_flags (DF_DEFER_INSN_RESCAN);
+         start_sequence ();
+
+         /* Make sure the scheduler doesn't schedule other insns beyond
+            here.  */
+         emit_insn (gen_blockage ());
+
+         /* Walk through all arguments and clear registers appropriately.
+         */
+         fntype = TREE_TYPE (MEM_EXPR (address));
+         arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX,
+                                   NULL_TREE);
+         args_so_far = pack_cumulative_args (&args_so_far_v);
+         FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
+           {
+             rtx arg_rtx;
+             machine_mode arg_mode = TYPE_MODE (arg_type);
+
+             if (VOID_TYPE_P (arg_type))
+               continue;
+
+             if (!first_param)
+               arm_function_arg_advance (args_so_far, arg_mode, arg_type,
+                                         true);
+
+             arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type,
+                                         true);
+             gcc_assert (REG_P (arg_rtx));
+             to_clear_mask
+               &= ~compute_not_to_clear_mask (arg_type, arg_rtx,
+                                              REGNO (arg_rtx),
+                                              padding_bits_to_clear_ptr);
+
+             first_param = false;
+           }
+
+         /* Clear padding bits where needed.  */
+         cleared_reg = XEXP (address, 0);
+         reg = gen_rtx_REG (SImode, IP_REGNUM);
+         using_r4 = false;
+         for (regno = R0_REGNUM; regno < NUM_ARG_REGS; regno++)
+           {
+             if (padding_bits_to_clear[regno] == 0)
+               continue;
+
+             /* If this is a Thumb-1 target copy the address of the function
+                we are calling from 'r4' into 'ip' such that we can use r4 to
+                clear the unused bits in the arguments.  */
+             if (TARGET_THUMB1 && !using_r4)
+               {
+                 using_r4 =  true;
+                 reg = cleared_reg;
+                 emit_move_insn (gen_rtx_REG (SImode, IP_REGNUM),
+                                         reg);
+               }
+
+             tmp = GEN_INT ((((~padding_bits_to_clear[regno]) << 16u) >> 16u));
+             emit_move_insn (reg, tmp);
+             /* Also fill the top half of the negated
+                padding_bits_to_clear.  */
+             if (((~padding_bits_to_clear[regno]) >> 16) > 0)
+               {
+                 tmp = GEN_INT ((~padding_bits_to_clear[regno]) >> 16);
+                 emit_insn (gen_rtx_SET (gen_rtx_ZERO_EXTRACT (SImode, reg,
+                                                               GEN_INT (16),
+                                                               GEN_INT (16)),
+                                         tmp));
+               }
+
+             emit_insn (gen_andsi3 (gen_rtx_REG (SImode, regno),
+                                    gen_rtx_REG (SImode, regno),
+                                    reg));
+
+           }
+         if (using_r4)
+           emit_move_insn (cleared_reg,
+                           gen_rtx_REG (SImode, IP_REGNUM));
+
+         /* We use right shift and left shift to clear the LSB of the address
+            we jump to instead of using bic, to avoid having to use an extra
+            register on Thumb-1.  */
+         tmp = gen_rtx_LSHIFTRT (SImode, cleared_reg, const1_rtx);
+         emit_insn (gen_rtx_SET (cleared_reg, tmp));
+         tmp = gen_rtx_ASHIFT (SImode, cleared_reg, const1_rtx);
+         emit_insn (gen_rtx_SET (cleared_reg, tmp));
+
+         /* Clearing all registers that leak before doing a non-secure
+            call.  */
+         for (regno = R0_REGNUM; regno <= maxregno; regno++)
+           {
+             if (!(to_clear_mask & (1LL << regno)))
+               continue;
+
+             /* If regno is an even vfp register and its successor is also to
+                be cleared, use vmov.  */
+             if (IS_VFP_REGNUM (regno))
+               {
+                 if (TARGET_VFP_DOUBLE
+                     && VFP_REGNO_OK_FOR_DOUBLE (regno)
+                     && to_clear_mask & (1LL << (regno + 1)))
+                   emit_move_insn (gen_rtx_REG (DFmode, regno++),
+                                   CONST0_RTX (DFmode));
+                 else
+                   emit_move_insn (gen_rtx_REG (SFmode, regno),
+                                   CONST0_RTX (SFmode));
+               }
+             else
+               emit_move_insn (gen_rtx_REG (SImode, regno), cleared_reg);
+           }
+
+         seq = get_insns ();
+         end_sequence ();
+         emit_insn_before (seq, insn);
+
+       }
+    }
+}
+
 /* Rewrite move insn into subtract of 0 if the condition codes will
    be useful in next conditional jump insn.  */
 
@@ -16954,6 +17154,8 @@ arm_reorg (void)
   HOST_WIDE_INT address = 0;
   Mfix * fix;
 
+  if (use_cmse)
+    cmse_nonsecure_call_clear_caller_saved ();
   if (TARGET_THUMB1)
     thumb1_reorg ();
   else if (TARGET_THUMB2)
@@ -17326,6 +17528,23 @@ vfp_emit_fstmd (int base_reg, int count)
   return count * 8;
 }
 
+/* Returns true if -mcmse has been passed and the function pointed to by 'addr'
+   has the cmse_nonsecure_call attribute and returns false otherwise.  */
+
+bool
+detect_cmse_nonsecure_call (tree addr)
+{
+  if (!addr)
+    return FALSE;
+
+  tree fntype = TREE_TYPE (addr);
+  if (use_cmse && lookup_attribute ("cmse_nonsecure_call",
+                                   TYPE_ATTRIBUTES (fntype)))
+    return TRUE;
+  return FALSE;
+}
+
+
 /* Emit a call instruction with pattern PAT.  ADDR is the address of
    the call target.  */
 
index 5523baf5099cb7c35a6ad3c8a39e5c31efd32f17..d561a4b5d1be9a7bd159f51b50ec736bd89f8fd1 100644 (file)
   "
   {
     rtx callee, pat;
+    tree addr = MEM_EXPR (operands[0]);
     
     /* In an untyped call, we can get NULL for operand 2.  */
     if (operands[2] == NULL_RTX)
        : !REG_P (callee))
       XEXP (operands[0], 0) = force_reg (Pmode, callee);
 
-    pat = gen_call_internal (operands[0], operands[1], operands[2]);
-    arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
+    if (detect_cmse_nonsecure_call (addr))
+      {
+       pat = gen_nonsecure_call_internal (operands[0], operands[1],
+                                          operands[2]);
+       emit_call_insn (pat);
+      }
+    else
+      {
+       pat = gen_call_internal (operands[0], operands[1], operands[2]);
+       arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
+      }
     DONE;
   }"
 )
              (use (match_operand 2 "" ""))
              (clobber (reg:SI LR_REGNUM))])])
 
+(define_expand "nonsecure_call_internal"
+  [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
+                              UNSPEC_NONSECURE_MEM)
+                   (match_operand 1 "general_operand" ""))
+             (use (match_operand 2 "" ""))
+             (clobber (reg:SI LR_REGNUM))
+             (clobber (reg:SI 4))])]
+  "use_cmse"
+  "
+  {
+    rtx tmp;
+    tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
+                                gen_rtx_REG (SImode, 4),
+                                SImode);
+
+    operands[0] = replace_equiv_address (operands[0], tmp);
+  }")
+
 (define_insn "*call_reg_armv5"
   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
          (match_operand 1 "" ""))
   "
   {
     rtx pat, callee;
+    tree addr = MEM_EXPR (operands[1]);
     
     /* In an untyped call, we can get NULL for operand 2.  */
     if (operands[3] == 0)
        : !REG_P (callee))
       XEXP (operands[1], 0) = force_reg (Pmode, callee);
 
-    pat = gen_call_value_internal (operands[0], operands[1],
-                                  operands[2], operands[3]);
-    arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
+    if (detect_cmse_nonsecure_call (addr))
+      {
+       pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
+                                                operands[2], operands[3]);
+       emit_call_insn (pat);
+      }
+    else
+      {
+       pat = gen_call_value_internal (operands[0], operands[1],
+                                      operands[2], operands[3]);
+       arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
+      }
     DONE;
   }"
 )
              (use (match_operand 3 "" ""))
              (clobber (reg:SI LR_REGNUM))])])
 
+(define_expand "nonsecure_call_value_internal"
+  [(parallel [(set (match_operand       0 "" "")
+                  (call (unspec:SI [(match_operand 1 "memory_operand" "")]
+                                   UNSPEC_NONSECURE_MEM)
+                        (match_operand 2 "general_operand" "")))
+             (use (match_operand 3 "" ""))
+             (clobber (reg:SI LR_REGNUM))
+             (clobber (reg:SI 4))])]
+  "use_cmse"
+  "
+  {
+    rtx tmp;
+    tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
+                                gen_rtx_REG (SImode, 4),
+                                SImode);
+
+    operands[1] = replace_equiv_address (operands[1], tmp);
+  }")
+
 (define_insn "*call_value_reg_armv5"
   [(set (match_operand 0 "" "")
         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
index 73a738195d5b35fe9b2a153d1270c26cbaad12e4..f9e934fab015c5b8bda344a5a2ca0341912080a8 100644 (file)
    (set_attr "type" "call")]
 )
 
+(define_insn "*nonsecure_call_reg_thumb1_v5"
+  [(call (unspec:SI [(mem:SI (match_operand:SI 0 "register_operand" "l*r"))]
+                   UNSPEC_NONSECURE_MEM)
+        (match_operand 1 "" ""))
+   (use (match_operand 2 "" ""))
+   (clobber (reg:SI LR_REGNUM))
+   (clobber (match_dup 0))]
+  "TARGET_THUMB1 && use_cmse && !SIBLING_CALL_P (insn)"
+  "bl\\t__gnu_cmse_nonsecure_call"
+  [(set_attr "length" "4")
+   (set_attr "type" "call")]
+)
+
 (define_insn "*call_reg_thumb1"
   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
         (match_operand 1 "" ""))
    (set_attr "type" "call")]
 )
 
+(define_insn "*nonsecure_call_value_reg_thumb1_v5"
+  [(set (match_operand 0 "" "")
+       (call (unspec:SI
+              [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
+              UNSPEC_NONSECURE_MEM)
+             (match_operand 2 "" "")))
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI LR_REGNUM))
+   (clobber (match_dup 1))]
+  "TARGET_THUMB1 && use_cmse"
+  "bl\\t__gnu_cmse_nonsecure_call"
+  [(set_attr "length" "4")
+   (set_attr "type" "call")]
+)
+
 (define_insn "*call_value_reg_thumb1"
   [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
index 9029a2fcfa8c865df9473eab7f807589a5a244e5..9b078a5c6a7ebd2ea7d1c39d9b6a80ce7b69a7dc 100644 (file)
   [(set_attr "type" "call")]
 )
 
+(define_insn "*nonsecure_call_reg_thumb2"
+  [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "r"))]
+                   UNSPEC_NONSECURE_MEM)
+        (match_operand 1 "" ""))
+   (use (match_operand 2 "" ""))
+   (clobber (reg:SI LR_REGNUM))
+   (clobber (match_dup 0))]
+  "TARGET_THUMB2 && use_cmse"
+  "bl\\t__gnu_cmse_nonsecure_call"
+  [(set_attr "length" "4")
+   (set_attr "type" "call")]
+)
+
 (define_insn "*call_value_reg_thumb2"
   [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
   [(set_attr "type" "call")]
 )
 
+(define_insn "*nonsecure_call_value_reg_thumb2"
+  [(set (match_operand 0 "" "")
+       (call
+        (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
+                   UNSPEC_NONSECURE_MEM)
+        (match_operand 2 "" "")))
+   (use (match_operand 3 "" ""))
+   (clobber (reg:SI LR_REGNUM))
+   (clobber (match_dup 1))]
+  "TARGET_THUMB2 && use_cmse"
+  "bl\t__gnu_cmse_nonsecure_call"
+  [(set_attr "length" "4")
+   (set_attr "type" "call")]
+)
+
 (define_insn "*thumb2_indirect_jump"
   [(set (pc)
        (match_operand:SI 0 "register_operand" "l*r"))]
index bee8795f007accc623c82b73c41a8619ebc29209..1aa39e8e0b9ddf17bb535c4d82959e569d3c9fd5 100644 (file)
@@ -84,6 +84,8 @@
   UNSPEC_VRINTA         ; Represent a float to integral float rounding
                         ; towards nearest, ties away from zero.
   UNSPEC_PROBE_STACK    ; Probe stack memory reference
+  UNSPEC_NONSECURE_MEM ; Represent non-secure memory in ARMv8-M with
+                       ; security extension
 ])
 
 (define_c_enum "unspec" [
index ca431e4a548c5dbf2d2c8ebb86b526a23c18279c..e9786b70e1b4be9fd38253c9415b68f2339bc991 100644 (file)
@@ -1,3 +1,45 @@
+2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+           Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * gcc.target/arm/cmse/cmse.exp: Run tests in mainline dir.
+       * gcc.target/arm/cmse/cmse-9.c: Added some extra tests.
+       * gcc.target/arm/cmse/cmse-14.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-4.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-5.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-6.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-7.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-8.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-9.c: New.
+       * gcc.target/arm/cmse/baseline/bitfield-and-union-1.c: New.
+       * gcc.target/arm/cmse/baseline/cmse-11.c: New.
+       * gcc.target/arm/cmse/baseline/cmse-13.c: New.
+       * gcc.target/arm/cmse/baseline/cmse-6.c: New.
+       * gcc.target/arm/cmse/baseline/union-1.c: New.
+       * gcc.target/arm/cmse/baseline/union-2.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-4.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-5.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-6.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-7.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-8.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-9.c: New.
+       * gcc.target/arm/cmse/mainline/bitfield-and-union-1.c: New.
+       * gcc.target/arm/cmse/mainline/union-1.c: New.
+       * gcc.target/arm/cmse/mainline/union-2.c: New.
+       * gcc.target/arm/cmse/mainline/hard-sp/cmse-13.c: New.
+       * gcc.target/arm/cmse/mainline/hard-sp/cmse-7.c: New.
+       * gcc.target/arm/cmse/mainline/hard-sp/cmse-8.c: New.
+       * gcc.target/arm/cmse/mainline/hard/cmse-13.c: New.
+       * gcc.target/arm/cmse/mainline/hard/cmse-7.c: New.
+       * gcc.target/arm/cmse/mainline/hard/cmse-8.c: New.
+       * gcc.target/arm/cmse/mainline/soft/cmse-13.c: New.
+       * gcc.target/arm/cmse/mainline/soft/cmse-7.c: New.
+       * gcc.target/arm/cmse/mainline/soft/cmse-8.c: New.
+       * gcc.target/arm/cmse/mainline/softfp-sp/cmse-7.c: New.
+       * gcc.target/arm/cmse/mainline/softfp-sp/cmse-8.c: New.
+       * gcc.target/arm/cmse/mainline/softfp/cmse-13.c: New.
+       * gcc.target/arm/cmse/mainline/softfp/cmse-7.c: New.
+       * gcc.target/arm/cmse/mainline/softfp/cmse-8.c: New.
+
 2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-4.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-4.c
new file mode 100644 (file)
index 0000000..a6c1386
--- /dev/null
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char a;
+  unsigned int b:5;
+  unsigned int c:11, :0, d:8;
+  struct { unsigned int ee:2; } e;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+extern void foo (test_st st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 255" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #255" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #3" } } */
+/* { dg-final { scan-assembler "ands\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-5.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-5.c
new file mode 100644 (file)
index 0000000..d51ce2d
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned short  b :5;
+  unsigned char          c;
+  unsigned short  d :11;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #8191" } } */
+/* { dg-final { scan-assembler "movt\tr4, 255" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #2047" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-6.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-6.c
new file mode 100644 (file)
index 0000000..77e9104
--- /dev/null
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char a;
+  unsigned int b : 3;
+  unsigned int c : 14;
+  unsigned int d : 1;
+  struct {
+      unsigned int    ee  : 2;
+      unsigned short  ff  : 15;
+  } e;
+  unsigned char        g : 1;
+  unsigned char          : 4;
+  unsigned char        h : 3;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 1023" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #3" } } */
+/* { dg-final { scan-assembler "movt\tr4, 32767" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #255" } } */
+/* { dg-final { scan-assembler "ands\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-7.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-7.c
new file mode 100644 (file)
index 0000000..3d8941b
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned short  b :5;
+  unsigned char          c;
+  unsigned short  d :11;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #8191" } } */
+/* { dg-final { scan-assembler "movt\tr4, 255" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #2047" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-8.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-8.c
new file mode 100644 (file)
index 0000000..9ffbb71
--- /dev/null
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #255" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #1" } } */
+/* { dg-final { scan-assembler "movt\tr4, 65535" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 31" } } */
+/* { dg-final { scan-assembler "ands\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-9.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-9.c
new file mode 100644 (file)
index 0000000..8a61418
--- /dev/null
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  char a:3;
+} test_st3;
+
+typedef struct
+{
+  char a:3;
+} test_st2;
+
+typedef struct
+{
+  test_st2 st2;
+  test_st3 st3;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #1799" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr1, r4" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-and-union-1.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/bitfield-and-union-1.c
new file mode 100644 (file)
index 0000000..642f4e0
--- /dev/null
@@ -0,0 +1,96 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned short a :11;
+} test_st_4;
+
+typedef union
+{
+  char       a;
+  test_st_4 st4;
+}test_un_2;
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st_3;
+
+typedef struct
+{
+  unsigned char          a :3;
+  unsigned int   b :13;
+  test_un_2      un2;
+} test_st_2;
+
+typedef union
+{
+  test_st_2 st2;
+  test_st_3 st3;
+}test_un_1;
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned char          c :4;
+  test_un_1      un1;
+} test_st_1;
+
+typedef union
+{
+  test_st_1 st1;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st_1;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st_1);
+
+int
+main (void)
+{
+  read_st_1 r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st1);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #7939" } } */
+/* { dg-final { scan-assembler "movt\tr4, 15" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 2047" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "movs\tr4, #1" } } */
+/* { dg-final { scan-assembler "movt\tr4, 65535" } } */
+/* { dg-final { scan-assembler "ands\tr2, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 31" } } */
+/* { dg-final { scan-assembler "ands\tr3, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-11.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-11.c
new file mode 100644 (file)
index 0000000..3007409
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_base_ok } */
+/* { dg-add-options arm_arch_v8m_base } */
+/* { dg-options "-mcmse" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (int);
+
+int
+foo (int a)
+{
+  return bar (bar (a + 1));
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr1, r4" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-13.c
new file mode 100644 (file)
index 0000000..f2b931b
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_base_ok } */
+/* { dg-add-options arm_arch_v8m_base } */
+/* { dg-options "-mcmse" } */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (float, double);
+
+int
+foo (int a)
+{
+  return bar (1.0f, 2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "movs\tr0, r4" } } */
+/* { dg-final { scan-assembler "\n\tmovs\tr1, r4" } } */
+/* { dg-final { scan-assembler-not "\n\tmovs\tr2, r4\n\tmovs\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vmov" } } */
+/* { dg-final { scan-assembler-not "vmsr" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-6.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/cmse-6.c
new file mode 100644 (file)
index 0000000..95da045
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_base_ok } */
+/* { dg-add-options arm_arch_v8m_base } */
+/* { dg-options "-mcmse" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Remember dont clear r0 and r1, because we are passing the double parameter
+ * for bar in them.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/union-1.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/union-1.c
new file mode 100644 (file)
index 0000000..ff18e83
--- /dev/null
@@ -0,0 +1,71 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned short  c :3;
+  unsigned char            :0;
+  unsigned int   d :9;
+} test_st_1;
+
+typedef struct
+{
+  unsigned short  a :7;
+  unsigned char            :0;
+  unsigned char          b :1;
+  unsigned char            :0;
+  unsigned short  c :6;
+} test_st_2;
+
+typedef union
+{
+  test_st_1 st_1;
+  test_st_2 st_2;
+}test_un;
+
+typedef union
+{
+  test_un un;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_un;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_un);
+
+int
+main (void)
+{
+  read_un r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.un);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #8063" } } */
+/* { dg-final { scan-assembler "movt\tr4, 63" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #511" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr2, r4" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/baseline/union-2.c b/gcc/testsuite/gcc.target/arm/cmse/baseline/union-2.c
new file mode 100644 (file)
index 0000000..b2e024b
--- /dev/null
@@ -0,0 +1,86 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned short  c :3;
+  unsigned char            :0;
+  unsigned int   d :9;
+} test_st_1;
+
+typedef struct
+{
+  unsigned short  a :7;
+  unsigned char            :0;
+  unsigned char          b :1;
+  unsigned char            :0;
+  unsigned short  c :6;
+} test_st_2;
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st_3;
+
+typedef union
+{
+  test_st_1 st_1;
+  test_st_2 st_2;
+  test_st_3 st_3;
+}test_un;
+
+typedef union
+{
+  test_un un;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_un;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_un);
+
+int
+main (void)
+{
+  read_un r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+
+  f (r.un);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #8191" } } */
+/* { dg-final { scan-assembler "movt\tr4, 63" } } */
+/* { dg-final { scan-assembler "ands\tr0, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #511" } } */
+/* { dg-final { scan-assembler "movt\tr4, 65535" } } */
+/* { dg-final { scan-assembler "ands\tr1, r4" } } */
+/* { dg-final { scan-assembler "movw\tr4, #65535" } } */
+/* { dg-final { scan-assembler "movt\tr4, 31" } } */
+/* { dg-final { scan-assembler "ands\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr4, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "movs\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
new file mode 100644 (file)
index 0000000..701e9ee
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int foo (void)
+{
+  return bar ();
+}
+
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+/* { dg-final { scan-assembler-not "b\[^ y\n\]*\\s+bar" } } */
index 1d97f0e1a37209bd129ffe96ce92a86bc2e0d5d1..9e81e30c891bbc1f9d2d1d68d03bacad9ce65fe1 100644 (file)
@@ -2,11 +2,19 @@
 /* { dg-skip-if "Testing exclusion of -mcmse" { arm-*-* } { "-mcmse" } { "" } }  */
 
 
+void __attribute__ ((cmse_nonsecure_call)) (*bar) (int); /* { dg-warning "attribute ignored without -mcmse option" } */
+typedef void __attribute__ ((cmse_nonsecure_call)) baz (int); /* { dg-warning "attribute ignored without -mcmse option" } */
+
 int __attribute__ ((cmse_nonsecure_entry))
-foo (int a)
+foo (int a, baz b)
 { /* { dg-warning "attribute ignored without -mcmse option" } */
+  bar (a);
+  b (a);
   return a + 1;
 }
 
+/* { dg-final { scan-assembler-not "bxns" } } */
+/* { dg-final { scan-assembler-not "blxns" } } */
+/* { dg-final { scan-assembler-not "bl\t__gnu_cmse_nonsecure_call" } } */
 /* { dg-final { scan-assembler "foo:" } } */
 /* { dg-final { scan-assembler-not "__acle_se_foo:" } } */
index 38f18414c2fefec56161e6ac3f7291b03a3b29a3..66a8b7da005f7dfeffbded61b02fd6a7473a1dcf 100644 (file)
@@ -50,6 +50,8 @@ if {[check_effective_target_arm_arch_v8m_base_ok]} then {
 }
 
 if {[check_effective_target_arm_arch_v8m_main_ok]} then {
+    gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/*.c]] \
+           "" $DEFAULT_CFLAGS
     # Mainline -mfloat-abi=soft
     gcc-dg-runtest [lsort [glob $srcdir/$subdir/mainline/soft/*.c]] \
            "-mfloat-abi=soft" $DEFAULT_CFLAGS
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-4.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-4.c
new file mode 100644 (file)
index 0000000..c3b1396
--- /dev/null
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char a;
+  unsigned int b:5;
+  unsigned int c:11, :0, d:8;
+  struct { unsigned int ee:2; } e;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+extern void foo (test_st st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 255" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #255" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #3" } } */
+/* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-5.c
new file mode 100644 (file)
index 0000000..0d02904
--- /dev/null
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned short  b :5;
+  unsigned char          c;
+  unsigned short  d :11;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #8191" } } */
+/* { dg-final { scan-assembler "movt\tip, 255" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #2047" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-6.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-6.c
new file mode 100644 (file)
index 0000000..005515a
--- /dev/null
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char a;
+  unsigned int b : 3;
+  unsigned int c : 14;
+  unsigned int d : 1;
+  struct {
+      unsigned int    ee  : 2;
+      unsigned short  ff  : 15;
+  } e;
+  unsigned char        g : 1;
+  unsigned char          : 4;
+  unsigned char        h : 3;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 1023" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #3" } } */
+/* { dg-final { scan-assembler "movt\tip, 32767" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #255" } } */
+/* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-7.c
new file mode 100644 (file)
index 0000000..6dd218e
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned short  b :5;
+  unsigned char          c;
+  unsigned short  d :11;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+
+/* { dg-final { scan-assembler "movw\tip, #8191" } } */
+/* { dg-final { scan-assembler "movt\tip, 255" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #2047" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-8.c
new file mode 100644 (file)
index 0000000..c833bcb
--- /dev/null
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "mov\tip, #255" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #1" } } */
+/* { dg-final { scan-assembler "movt\tip, 65535" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 31" } } */
+/* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-9.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-9.c
new file mode 100644 (file)
index 0000000..d6e4cdb
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  char a:3;
+} test_st3;
+
+typedef struct
+{
+  char a:3;
+} test_st2;
+
+typedef struct
+{
+  test_st2 st2;
+  test_st3 st3;
+} test_st;
+
+typedef union
+{
+  test_st st;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st;
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st);
+
+int
+main (void)
+{
+  read_st r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+
+  f (r.st);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #1799" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-and-union-1.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/bitfield-and-union-1.c
new file mode 100644 (file)
index 0000000..e139ba6
--- /dev/null
@@ -0,0 +1,94 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned short a :11;
+} test_st_4;
+
+typedef union
+{
+  char       a;
+  test_st_4 st4;
+}test_un_2;
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st_3;
+
+typedef struct
+{
+  unsigned char          a :3;
+  unsigned int   b :13;
+  test_un_2      un2;
+} test_st_2;
+
+typedef union
+{
+  test_st_2 st2;
+  test_st_3 st3;
+}test_un_1;
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned char          c :4;
+  test_un_1      un1;
+} test_st_1;
+
+typedef union
+{
+  test_st_1 st1;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_st_1;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_st_1);
+
+int
+main (void)
+{
+  read_st_1 r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+  r.values.v4 = 0xFFFFFFFF;
+
+  f (r.st1);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #7939" } } */
+/* { dg-final { scan-assembler "movt\tip, 15" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 2047" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "mov\tip, #1" } } */
+/* { dg-final { scan-assembler "movt\tip, 65535" } } */
+/* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 31" } } */
+/* { dg-final { scan-assembler "and\tr3, r3, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-13.c
new file mode 100644 (file)
index 0000000..d90ad81
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing double precision" {*-*-*} {"-mfpu=fpv[4-5]-d16"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-sp-d16" }  */
+
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (float, double);
+
+int
+foo (int a)
+{
+  return bar (3.0f, 2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts0, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts1, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts2, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts7, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts8, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts9, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts10, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts11, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts12, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts13, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts14, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts15, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-7.c
new file mode 100644 (file)
index 0000000..c047cd5
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing double precision" {*-*-*} {"-mfpu=fpv[4-5]-d16"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-sp-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int
+foo (int a)
+{
+  return bar () + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts0, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts1, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts2, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts7, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts8, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts9, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts10, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts11, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts12, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts13, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts14, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts15, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard-sp/cmse-8.c
new file mode 100644 (file)
index 0000000..20d2d4a
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing double precision" {*-*-*} {"-mfpu=fpv[4-5]-d16"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-sp-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts0, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts1, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts2, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts7, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts8, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts9, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts10, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts11, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts12, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts13, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts14, .L" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts15, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-13.c
new file mode 100644 (file)
index 0000000..0af586a
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-d16" }  */
+
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (float, double);
+
+int
+foo (int a)
+{
+  return bar (3.0f, 2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "vldr\.32\ts1, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.64\td0, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts0, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.64\td1, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts2, .L" } } */
+/* { dg-final { scan-assembler-not "vldr\.32\ts3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td2, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td7, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-7.c
new file mode 100644 (file)
index 0000000..a5c64fb
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int
+foo (int a)
+{
+  return bar () + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "vldr\.64\td0, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td1, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td2, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td7, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/hard/cmse-8.c
new file mode 100644 (file)
index 0000000..5e041b1
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=softfp } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=hard -mfpu=fpv5-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vldr\.64\td0, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td1, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td2, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td3, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td4, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td5, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td6, .L" } } */
+/* { dg-final { scan-assembler "vldr\.64\td7, .L" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-13.c
new file mode 100644 (file)
index 0000000..dbbd262
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=hard" -mfloat-abi=softfp } {""} } */
+/* { dg-options "-mcmse -mfloat-abi=soft" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (float, double);
+
+int
+foo (int a)
+{
+  return bar (1.0f, 2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vmov" } } */
+/* { dg-final { scan-assembler-not "vmsr" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-7.c
new file mode 100644 (file)
index 0000000..e335684
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=hard" -mfloat-abi=softfp } {""} } */
+/* { dg-options "-mcmse -mfloat-abi=soft" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int
+foo (int a)
+{
+  return bar () + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vmov" } } */
+/* { dg-final { scan-assembler-not "vmsr" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/soft/cmse-8.c
new file mode 100644 (file)
index 0000000..024a12e
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=hard" -mfloat-abi=softfp } {""} } */
+/* { dg-options "-mcmse -mfloat-abi=soft" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler-not "vmov" } } */
+/* { dg-final { scan-assembler-not "vmsr" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-7.c
new file mode 100644 (file)
index 0000000..fb195eb
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
+/* { dg-skip-if "Skip these if testing double precision" {*-*-*} {"-mfpu=fpv[4-5]-d16"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-sp-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int
+foo (int a)
+{
+  return bar () + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp-sp/cmse-8.c
new file mode 100644 (file)
index 0000000..22ed3f8
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
+/* { dg-skip-if "Skip these if testing double precision" {*-*-*} {"-mfpu=fpv[4-5]-d16"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-sp-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-13.c
new file mode 100644 (file)
index 0000000..9634065
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (float, double);
+
+int
+foo (int a)
+{
+  return bar (1.0f, 2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "\n\tmov\tr1, r4" } } */
+/* { dg-final { scan-assembler-not "\n\tmov\tr2, r4\n\tmov\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-7.c
new file mode 100644 (file)
index 0000000..04f8466
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (void);
+
+int
+foo (int a)
+{
+  return bar () + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/softfp/cmse-8.c
new file mode 100644 (file)
index 0000000..ffe94de
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_main_ok } */
+/* { dg-add-options arm_arch_v8m_main } */
+/* { dg-skip-if "Do not combine float-abi= hard | soft | softfp" {*-*-*} {"-mfloat-abi=soft" -mfloat-abi=hard } {""} } */
+/* { dg-skip-if "Skip these if testing single precision" {*-*-*} {"-mfpu=*-sp-*"} {""} } */
+/* { dg-options "-mcmse -mfloat-abi=softfp -mfpu=fpv5-d16" }  */
+
+int __attribute__ ((cmse_nonsecure_call)) (*bar) (double);
+
+int
+foo (int a)
+{
+  return bar (2.0) + a + 1;
+}
+
+/* Checks for saving and clearing prior to function call.  */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+
+/* Now we check that we use the correct intrinsic to call.  */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/union-1.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/union-1.c
new file mode 100644 (file)
index 0000000..1fc846c
--- /dev/null
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned short  c :3;
+  unsigned char            :0;
+  unsigned int   d :9;
+} test_st_1;
+
+typedef struct
+{
+  unsigned short  a :7;
+  unsigned char            :0;
+  unsigned char          b :1;
+  unsigned char            :0;
+  unsigned short  c :6;
+} test_st_2;
+
+typedef union
+{
+  test_st_1 st_1;
+  test_st_2 st_2;
+}test_un;
+
+typedef union
+{
+  test_un un;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_un;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_un);
+
+int
+main (void)
+{
+  read_un r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+
+  f (r.un);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #8063" } } */
+/* { dg-final { scan-assembler "movt\tip, 63" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #511" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
+
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/union-2.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/union-2.c
new file mode 100644 (file)
index 0000000..420d0f1
--- /dev/null
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-options "-mcmse" } */
+
+typedef struct
+{
+  unsigned char          a :2;
+  unsigned char            :0;
+  unsigned short  b :5;
+  unsigned char            :0;
+  unsigned short  c :3;
+  unsigned char            :0;
+  unsigned int   d :9;
+} test_st_1;
+
+typedef struct
+{
+  unsigned short  a :7;
+  unsigned char            :0;
+  unsigned char          b :1;
+  unsigned char            :0;
+  unsigned short  c :6;
+} test_st_2;
+
+typedef struct
+{
+  unsigned char          a;
+  unsigned int     :0;
+  unsigned int   b :1;
+  unsigned short    :0;
+  unsigned short  c;
+  unsigned int     :0;
+  unsigned int   d :21;
+} test_st_3;
+
+typedef union
+{
+  test_st_1 st_1;
+  test_st_2 st_2;
+  test_st_3 st_3;
+}test_un;
+
+typedef union
+{
+  test_un un;
+  struct
+    {
+      unsigned int v1;
+      unsigned int v2;
+      unsigned int v3;
+      unsigned int v4;
+    }values;
+} read_un;
+
+
+typedef void __attribute__ ((cmse_nonsecure_call)) (*foo_ns) (test_un);
+
+int
+main (void)
+{
+  read_un r;
+  foo_ns f;
+
+  f = (foo_ns) 0x200000;
+  r.values.v1 = 0xFFFFFFFF;
+  r.values.v2 = 0xFFFFFFFF;
+  r.values.v3 = 0xFFFFFFFF;
+
+  f (r.un);
+  return 0;
+}
+
+/* { dg-final { scan-assembler "movw\tip, #8191" } } */
+/* { dg-final { scan-assembler "movt\tip, 63" } } */
+/* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #511" } } */
+/* { dg-final { scan-assembler "movt\tip, 65535" } } */
+/* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
+/* { dg-final { scan-assembler "movw\tip, #65535" } } */
+/* { dg-final { scan-assembler "movt\tip, 31" } } */
+/* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
+/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
+/* { dg-final { scan-assembler "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
index f323f4384afcf6a8d5c5bc745f9c981d6abfc2bb..6627d266e23809a4edebced3e9c571cf051e670f 100644 (file)
@@ -1,3 +1,9 @@
+2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
+           Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * config/arm/cmse_nonsecure_call.S: New.
+       * config/arm/t-arm: Compile cmse_nonsecure_call.S
+
 2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
            Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
diff --git a/libgcc/config/arm/cmse_nonsecure_call.S b/libgcc/config/arm/cmse_nonsecure_call.S
new file mode 100644 (file)
index 0000000..68b6a1c
--- /dev/null
@@ -0,0 +1,131 @@
+/* CMSE wrapper function used to save, clear and restore callee saved registers
+   for cmse_nonsecure_call's.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 3, or (at your option) any
+   later version.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+.syntax unified
+.thumb
+.global __gnu_cmse_nonsecure_call
+__gnu_cmse_nonsecure_call:
+#if defined(__ARM_ARCH_8M_MAIN__)
+push       {r5-r11,lr}
+mov        r7, r4
+mov        r8, r4
+mov        r9, r4
+mov        r10, r4
+mov        r11, r4
+mov        ip, r4
+
+/* Save and clear callee-saved registers only if we are dealing with hard float
+   ABI.  The unused caller-saved registers have already been cleared by GCC
+   generated code.  */
+#ifdef __ARM_PCS_VFP
+vpush.f64   {d8-d15}
+mov        r5, #0
+vmov       d8, r5, r5
+#if __ARM_FP & 0x04
+vmov       s18, s19, r5, r5
+vmov       s20, s21, r5, r5
+vmov       s22, s23, r5, r5
+vmov       s24, s25, r5, r5
+vmov       s26, s27, r5, r5
+vmov       s28, s29, r5, r5
+vmov       s30, s31, r5, r5
+#elif __ARM_FP & 0x08
+vmov.f64    d9, d8
+vmov.f64    d10, d8
+vmov.f64    d11, d8
+vmov.f64    d12, d8
+vmov.f64    d13, d8
+vmov.f64    d14, d8
+vmov.f64    d15, d8
+#else
+#error "Half precision implementation not supported."
+#endif
+/* Clear the cumulative exception-status bits (0-4,7) and the
+   condition code bits (28-31) of the FPSCR.  */
+vmrs       r5, fpscr
+movw       r6, #65376
+movt       r6, #4095
+ands       r5, r6
+vmsr       fpscr, r5
+
+/* We are not dealing with hard float ABI, so we can safely use the vlstm and
+   vlldm instructions without needing to preserve the registers used for
+   argument passing.  */
+#else
+sub        sp, sp, #0x88 /* Reserve stack space to save all floating point
+                            registers, including FPSCR.  */
+vlstm      sp            /* Lazy store and clearance of d0-d16 and FPSCR.  */
+#endif /* __ARM_PCS_VFP */
+
+/* Make sure to clear the 'GE' bits of the APSR register if 32-bit SIMD
+   instructions are available.  */
+#if defined(__ARM_FEATURE_SIMD32)
+msr        APSR_nzcvqg, r4
+#else
+msr        APSR_nzcvq, r4
+#endif
+
+mov        r5, r4
+mov        r6, r4
+blxns      r4
+
+#ifdef __ARM_PCS_VFP
+vpop.f64    {d8-d15}
+#else
+vlldm      sp            /* Lazy restore of d0-d16 and FPSCR.  */
+add        sp, sp, #0x88 /* Free space used to save floating point registers.  */
+#endif /* __ARM_PCS_VFP */
+
+pop        {r5-r11, pc}
+
+#elif defined (__ARM_ARCH_8M_BASE__)
+push       {r5-r7, lr}
+mov        r5, r8
+mov        r6, r9
+mov        r7, r10
+push       {r5-r7}
+mov        r5, r11
+push       {r5}
+mov        r5, r4
+mov        r6, r4
+mov        r7, r4
+mov        r8, r4
+mov        r9, r4
+mov        r10, r4
+mov        r11, r4
+mov        ip, r4
+msr        APSR_nzcvq, r4
+blxns      r4
+pop        {r5}
+mov        r11, r5
+pop        {r5-r7}
+mov        r10, r7
+mov        r9, r6
+mov        r8, r5
+pop        {r5-r7, pc}
+
+#else
+#error "This should only be used for armv8-m base- and mainline."
+#endif
index 5618143bfd0f02b170db3f9e4c0a15cecb403cec..9e85ac06b146feaa14ab83374a0156737b870310 100644 (file)
@@ -12,4 +12,6 @@ libgcc-objects += cmse.o cmse_nonsecure_call.o
 
 cmse.o: $(srcdir)/config/arm/cmse.c
        $(gcc_compile) -c $(CMSE_OPTS) $<
+cmse_nonsecure_call.o: $(srcdir)/config/arm/cmse_nonsecure_call.S
+                      $(gcc_compile) -c $<
 endif