Hi Kyrill,

On 11/12/2019 09:55 AM, Kyrill Tkachov wrote:
Hi Mihail,

On 10/23/19 10:26 AM, Mihail Ionescu wrote:
[PATCH, GCC/ARM, 4/10] Clear GPR with CLRM

Hi,

=== Context ===

This patch is part of a patch series to add support for Armv8.1-M
Mainline Security Extensions architecture. Its purpose is to improve
code density of functions with the cmse_nonsecure_entry attribute and
when calling function with the cmse_nonsecure_call attribute by using
CLRM to do all the general purpose registers clearing as well as
clearing the APSR register.

=== Patch description ===

This patch adds a new pattern for the CLRM instruction and guards the
current clearing code in output_return_instruction() and thumb_exit()
on Armv8.1-M Mainline instructions not being present.
cmse_clear_registers () is then modified to use the new CLRM instruction
when targeting Armv8.1-M Mainline while keeping Armv8-M register
clearing code for VFP registers.

For the CLRM instruction, which does not mandated APSR in the register
list, checking whether it is the right volatile unspec or a clearing
register is done in clear_operation_p.

Note that load/store multiple were deemed sufficiently different in
terms of RTX structure compared to the CLRM pattern for a different
function to be used to validate the match_parallel.

ChangeLog entries are as follows:

*** gcc/ChangeLog ***

2019-10-23  Mihail-Calin Ionescu <mihail.ione...@arm.com>
2019-10-23  Thomas Preud'homme <thomas.preudho...@arm.com>

        * config/arm/arm-protos.h (clear_operation_p): Declare.
        * config/arm/arm.c (clear_operation_p): New function.
        (cmse_clear_registers): Generate clear_multiple instruction pattern if
        targeting Armv8.1-M Mainline or successor.
        (output_return_instruction): Only output APSR register clearing if
        Armv8.1-M Mainline instructions not available.
        (thumb_exit): Likewise.
        * config/arm/predicates.md (clear_multiple_operation): New predicate.
        * config/arm/thumb2.md (clear_apsr): New define_insn.
        (clear_multiple): Likewise.
        * config/arm/unspecs.md (VUNSPEC_CLRM_APSR): New volatile unspec.

*** gcc/testsuite/ChangeLog ***

2019-10-23  Mihail-Calin Ionescu <mihail.ione...@arm.com>
2019-10-23  Thomas Preud'homme <thomas.preudho...@arm.com>

        * gcc.target/arm/cmse/bitfield-1.c: Add check for CLRM.
        * gcc.target/arm/cmse/bitfield-2.c: Likewise.
        * gcc.target/arm/cmse/bitfield-3.c: Likewise.
        * gcc.target/arm/cmse/struct-1.c: Likewise.
        * gcc.target/arm/cmse/cmse-14.c: Likewise.
        * gcc.target/arm/cmse/cmse-1.c: Likewise.  Restrict checks for Armv8-M
        GPR clearing when CLRM is not available.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c: likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c: likewise.
        * gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c: likewise.
        * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/union-1.c: Likewise.
        * gcc.target/arm/cmse/mainline/8_1m/union-2.c: Likewise.

Testing: bootstrapped on arm-linux-gnueabihf and testsuite shows no
regression.

Is this ok for trunk?

Best regards,

Mihail


###############     Attachment also inlined for ease of reply ###############


diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index f995974f9bb89ab3c7ff0888c394b0dfaf7da60c..1a948d2c97526ad7e67e8d4a610ac74cfdb13882 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -77,6 +77,7 @@ extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
 extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
 extern bool ldm_stm_operation_p (rtx, bool, machine_mode mode,
                                  bool, bool);
+extern bool clear_operation_p (rtx);
 extern int arm_const_double_rtx (rtx);
 extern int vfp3_const_double_rtx (rtx);
 extern int neon_immediate_valid_for_move (rtx, machine_mode, rtx *, int *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d485e80096c9d2eef2172d211a0a5ab63cdbb3c7..3a373cea33c3d0b966cbe700d26f66fe069e1efb 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13499,6 +13499,66 @@ ldm_stm_operation_p (rtx op, bool load, machine_mode mode,
   return true;
 }

+/* Checks whether OP is a valid parallel pattern for a CLRM insn.  To be a
+   valid CLRM pattern, OP must have the following form:
+
+   [(set (reg:SI <N>) (const_int 0))
+    (set (reg:SI <M>) (const_int 0))
+    ...
+    (unspec_volatile [(const_int 0)]
+                    VUNSPEC_CLRM_APSR)
+   ]


If this clears the whole APSR than it also clobbers the condition flags, right?

Then it should also have a  (clobber (reg:CC CC_REGNUM)) in there.
Yes -- it should also clobber the condition flags, thanks for catching
this. I've updated the patch to include the CC clobbering.

Regards,
Mihail

+
+   Any number (including 0) of set expressions is valid, the volatile unspec is +   optional.  All registers but SP and PC are allowed and registers must be in
+   strict increasing order.  */
+
+bool
+clear_operation_p (rtx op)
+{
+  HOST_WIDE_INT i;
+  unsigned regno, last_regno;
+  rtx elt, reg, zero;
+  machine_mode mode;
+  HOST_WIDE_INT count = XVECLEN (op, 0);
+
+  for (i = 0; i < count; i++)
+    {
+      elt = XVECEXP (op, 0, i);
+
+      if (GET_CODE (elt) == UNSPEC_VOLATILE)
+       {
+         if (XINT (elt, 1) != VUNSPEC_CLRM_APSR
+             || XVECLEN (elt, 0) != 1
+             || XVECEXP (elt, 0, 0) != CONST0_RTX (SImode)
+             || i != count - 1)
+           return false;
+
+         continue;
+       }
+
+      if (GET_CODE (elt) != SET)
+       return false;
+
+      reg = SET_DEST (elt);
+      regno = REGNO (reg);
+      mode = GET_MODE (reg);
+      zero = SET_SRC (elt);
+
+      if (!REG_P (reg)
+         || GET_MODE (reg) != SImode
+         || regno == SP_REGNUM
+         || regno == PC_REGNUM
+         || (i != 0 && regno <= last_regno)
+         || zero != CONST0_RTX (SImode))
+       return false;
+
+      last_regno = REGNO (reg);
+    }
+
+  return true;
+}
+
 /* Return true iff it would be profitable to turn a sequence of NOPS loads     or stores (depending on IS_STORE) into a load-multiple or store-multiple     instruction.  ADD_OFFSET is nonzero if the base address register needs @@ -17596,6 +17656,56 @@ cmse_clear_registers (sbitmap to_clear_bitmap, uint32_t *padding_bits_to_clear,

   /* Clear full registers.  */

+  if (TARGET_HAVE_FPCXT_CMSE)
+    {
+      rtvec vunspec_vec;
+      int i, j, k, nb_regs;
+      rtx use_seq, par, reg, set, vunspec;
+      int to_clear_bitmap_size = SBITMAP_SIZE (to_clear_bitmap);
+      auto_sbitmap core_regs_bitmap (to_clear_bitmap_size);
+      auto_sbitmap to_clear_core_bitmap (to_clear_bitmap_size);
+
+      /* Get set of core registers to clear.  */
+      bitmap_clear (core_regs_bitmap);
+      bitmap_set_range (core_regs_bitmap, R0_REGNUM,
+                       IP_REGNUM - R0_REGNUM + 1);
+      bitmap_and (to_clear_core_bitmap, to_clear_bitmap,
+                 core_regs_bitmap);
+      gcc_assert (!bitmap_empty_p (to_clear_core_bitmap));
+
+      if (bitmap_empty_p (to_clear_core_bitmap))
+       return;
+
+      /* Create clrm RTX pattern.  */
+      nb_regs = bitmap_count_bits (to_clear_core_bitmap);
+      par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nb_regs + 1));
+
+      /* Insert core register clearing RTX in the pattern. */
+      start_sequence ();
+      for (j = 0, i = minregno; j < nb_regs; i++)
+       {
+         if (!bitmap_bit_p (to_clear_core_bitmap, i))
+           continue;
+
+         reg = gen_rtx_REG (SImode, i);
+         set = gen_rtx_SET (reg, const0_rtx);
+         XVECEXP (par, 0, j++) = set;
+         emit_use (reg);
+       }
+
+      /* Insert APSR register clearing RTX in the pattern. */
+      vunspec_vec = gen_rtvec (1, gen_int_mode (0, SImode));
+      vunspec = gen_rtx_UNSPEC_VOLATILE (SImode, vunspec_vec,
+                                        VUNSPEC_CLRM_APSR);
+      XVECEXP (par, 0, j) = vunspec;
+
+      use_seq = get_insns ();
+      end_sequence ();
+
+      emit_insn_after (use_seq, emit_insn (par));
+      minregno = FIRST_VFP_REGNUM;
+    }
+
   /* If not marked for clearing, clearing_reg already does not contain
      any secret.  */
   if (clearing_regno <= maxregno
@@ -20259,40 +20369,50 @@ output_return_instruction (rtx operand, bool really_return, bool reverse,
         default:
           if (IS_CMSE_ENTRY (func_type))
             {
-             /* Check if we have to clear the 'GE bits' which is only used if -                parallel add and subtraction instructions are available.  */
-             if (TARGET_INT_SIMD)
-               snprintf (instr, sizeof (instr),
-                         "msr%s\tAPSR_nzcvqg, %%|lr", conditional);
-             else
-               snprintf (instr, sizeof (instr),
-                         "msr%s\tAPSR_nzcvq, %%|lr", conditional);
-
-             output_asm_insn (instr, & operand);
-             /* Do not clear FPSCR if targeting Armv8.1-M Mainline, VLDR takes
-                care of it.  */
-             if (TARGET_HARD_FLOAT && ! TARGET_HAVE_FPCXT_CMSE)
+             /* For Armv8.1-M, this is cleared as part of the CLRM instruction +                emitted by cmse_nonsecure_entry_clear_before_return () and the
+                VSTR/VLDR instructions in the prologue and epilogue.  */
+             if (!TARGET_HAVE_FPCXT_CMSE)
                 {
-                 /* Clear the cumulative exception-status bits (0-4,7) and the -                    condition code bits (28-31) of the FPSCR.  We need to -                    remember to clear the first scratch register used (IP) and
-                    save and restore the second (r4).  */
-                 snprintf (instr, sizeof (instr), "push\t{%%|r4}");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "vmrs\t%%|ip, fpscr");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "movw\t%%|r4, #65376");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "movt\t%%|r4, #4095");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "and\t%%|ip, %%|r4");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "vmsr\tfpscr, %%|ip");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "pop\t{%%|r4}");
-                 output_asm_insn (instr, & operand);
-                 snprintf (instr, sizeof (instr), "mov\t%%|ip, %%|lr");
+                 /* Check if we have to clear the 'GE bits' which is only used if +                    parallel add and subtraction instructions are available.  */
+                 if (TARGET_INT_SIMD)
+                   snprintf (instr, sizeof (instr),
+                             "msr%s\tAPSR_nzcvqg, %%|lr", conditional);
+                 else
+                   snprintf (instr, sizeof (instr),
+                             "msr%s\tAPSR_nzcvq, %%|lr", conditional);
+
                   output_asm_insn (instr, & operand);
+                 /* Do not clear FPSCR if targeting Armv8.1-M Mainline, VLDR takes
+                    care of it.  */
+                 if (TARGET_HARD_FLOAT)
+                   {
+                     /* Clear the cumulative exception-status bits (0-4,7) and +                        the condition code bits (28-31) of the FPSCR.  We need +                        to remember to clear the first scratch register used
+                        (IP) and save and restore the second (r4).
+
+                        Important note: the length of the
+                        thumb2_cmse_entry_return insn pattern must account for
+                        the size of the below instructions.  */
+                     snprintf (instr, sizeof (instr), "push\t{%%|r4}");
+                     output_asm_insn (instr, & operand);


I know this is pre-existing in this function, but I think we should just use output_asm_insn directly here:
output_asm_insn ("push\t{%%|r4}", & operand);

and avoid all the snprintfs.


+                     snprintf (instr, sizeof (instr), "vmrs\t%%|ip, fpscr");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "movw\t%%|r4, #65376");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "movt\t%%|r4, #4095");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "and\t%%|ip, %%|r4");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "vmsr\tfpscr, %%|ip");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "pop\t{%%|r4}");
+                     output_asm_insn (instr, & operand);
+                     snprintf (instr, sizeof (instr), "mov\t%%|ip, %%|lr");
+                     output_asm_insn (instr, & operand);
+                   }
                 }
               snprintf (instr, sizeof (instr), "bxns\t%%|lr");
             }
@@ -24690,8 +24810,11 @@ thumb_exit (FILE *f, int reg_containing_return_addr)

       if (IS_CMSE_ENTRY (arm_current_func_type ()))
         {
-         asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n",
-                      reg_containing_return_addr);
+         /* For Armv8.1-M, this is cleared as part of the CLRM instruction
+            emitted by cmse_nonsecure_entry_clear_before_return ().  */
+         if (!TARGET_HAVE_FPCXT_CMSE)
+           asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n",
+                        reg_containing_return_addr);
           asm_fprintf (f, "\tbxns\t%r\n", reg_containing_return_addr);
         }
       else
@@ -24931,11 +25054,14 @@ thumb_exit (FILE *f, int reg_containing_return_addr)           address.  It may therefore contain information that we might not want           to leak, hence it must be cleared.  The value in R0 will never be a           secret at this point, so it is safe to use it, see the clearing code
-        in 'cmse_nonsecure_entry_clear_before_return'.  */
+        in cmse_nonsecure_entry_clear_before_return ().  */
       if (reg_containing_return_addr != LR_REGNUM)
         asm_fprintf (f, "\tmov\tlr, r0\n");

-      asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n", reg_containing_return_addr); +      /* For Armv8.1-M, this is cleared as part of the CLRM instruction emitted
+        by cmse_nonsecure_entry_clear_before_return ().  */
+      if (!TARGET_HAVE_FPCXT_CMSE)
+       asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n", reg_containing_return_addr);
       asm_fprintf (f, "\tbxns\t%r\n", reg_containing_return_addr);
     }
   else
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 8b36e7ee462235ad26e132f1ccf98d28c2487d67..e5c583ef3d167194e7a061d7c3e98d3b4bb5269c 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -510,6 +510,12 @@
             (match_test "satisfies_constraint_Dy (op)")
             (match_test "satisfies_constraint_G (op)"))))

+(define_special_predicate "clear_multiple_operation"
+  (match_code "parallel")
+{
+ return clear_operation_p (op);
+})
+
 (define_special_predicate "load_multiple_operation"
   (match_code "parallel")
 {
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 6ccc875e2b4e7b8ce256e52da966dfe220c6f5d6..9994c0d59f741ef47d0ec43dd53a2324b031d048 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -1599,3 +1599,39 @@
       FAIL;
  }")

+(define_insn "*clear_apsr"
+  [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)]
+  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
+  "clrm%?\\t{APSR}"
+  [(set_attr "predicable" "yes")]
+)


Similar to earlier, if this clears the whole APSR then it should also represent a clobber of the CC reg.


+
+;; The operands are validated through the clear_multiple_operation
+;; match_parallel predicate rather than through constraints so enable it only
+;; after reload.
+(define_insn "*clear_multiple"
+  [(match_parallel 0 "clear_multiple_operation"
+     [(set (match_operand:SI 1 "register_operand" "")
+          (const_int 0))])]
+  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
+  {
+    char pattern[100];
+    int i, num_saves = XVECLEN (operands[0], 0);
+
+    strcpy (pattern, \"clrm%?\\t{\");
+    for (i = 0; i < num_saves; i++)
+      {
+       if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
+         strcat (pattern, \"APSR\");
+       else
+         strcat (pattern,
+                 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
+       if (i < num_saves - 1)
+         strcat (pattern, \", %|\");
+      }
+    strcat (pattern, \"}\");
+    output_asm_insn (pattern, operands);
+    return \"\";
+  }
+  [(set_attr "predicable" "yes")]
+)
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 324359be7127f04a80ebc0079ad0a9964dfd82a7..498bc0798dbaaa3ee73815ba27864ae92a2fd08e 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -174,6 +174,7 @@
   VUNSPEC_MRRC2                ; Represent the coprocessor mrrc2 instruction.    VUNSPEC_SPECULATION_BARRIER ; Represents an unconditional speculation barrier.
   VUNSPEC_VSTR_VLDR    ; Represent the vstr/vldr instruction.
+  VUNSPEC_CLRM_APSR    ; Represent the clearing of APSR with clrm instruction.
 ])

 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c index 6d611e130b6f3b544807b767927d99b89071343b..7036cb9508c27d56c4b2c01a81c44bf6f1f9c781 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c
@@ -36,6 +36,7 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #1855" } } */
 /* { dg-final { scan-assembler "movt\tr1, 65535" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */

diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c index b7ec0a040319545b50590261278f1517bcb22796..50d4979470dd21738453e0d70c7a69ee0752ac41 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c
@@ -33,6 +33,7 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #1919" } } */
 /* { dg-final { scan-assembler "movt\tr1, 2047" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */

diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c index 7b9c3f0fe061317f71d3122dea7a55ab5311f234..2b7507c900ab18705083ba1d86359e1ae36a50a2 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c
@@ -34,5 +34,6 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #65535" } } */
 /* { dg-final { scan-assembler "movt\tr1, 63" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c index aa0ec8e0b0f0953a5a5cbc2db58413176c2505f3..35cab1f3233daac9fba50d25dac23364c798fb9c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
@@ -105,8 +105,10 @@ qux (int_nsfunc_t * callback)
 /* { dg-final { scan-assembler "bic" } } */
 /* { dg-final { scan-assembler "push\t\{r4, r5, r6" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" { target arm_cmse_clear_ok } } } */ +/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq" } } */
+/* { dg-final { scan-assembler "msr\tAPSR_nzcvq" { target { ! arm_cmse_clear_ok } } } } */ +/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, APSR\}" { target arm_cmse_clear_ok } } } */

 int call_callback (void)
 {
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c index df1ea52bec533c36a738d7d3b2b2ff749b0f3713..1f5af7c2dba7747f6058d12af8ef80b4dd1b1431 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
@@ -9,5 +9,6 @@ int foo (void)
   return bar ();
 }

+/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
 /* { dg-final { scan-assembler-not "^(.*\\s)?bl?\[^\\s]*\\s+bar" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c index 62c63b888ab49e99fba0a08b69941e73c9a8d33b..c52e1c14d9956743625e3b8a200e823f163924e3 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c
@@ -12,5 +12,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c index b718a70522b86e2bc58900681a781129543f8869..fdba955a32fc5ad492b74974185f98470bc49a7e 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c index 16536ab4f9ec5782463ab90f404a2e9f6f938850..85068ceaac6a5c0c60af4a54c0af0d20326fc18d 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c
@@ -13,5 +13,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c index 0b3cc1e2b2b26e185a9d5d4855d3bea8c70289b5..af69d38acf47d9d1d55480edba2b66f07e2d06ad 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c index 914ea39626f2f72eac8c9c1cb495b0855e58f5e1..62201595549f07b046c7c5972d612ab155c4c38c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c
@@ -13,5 +13,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c index 32435d255805331c7c56a096675b7a2af3286e5e..287f0d6faad113fbc8c30051280668baa58ab130 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c
@@ -7,7 +7,5 @@
 /* { 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 "clrm\t\{r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c index eb655b5504e58dc842853c8cb874c5cef3b82aa6..7b2df1faff5ea6ce6e7a58a37cd23eaf9616ee97 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c index ab266af7092afbce868792446124c291188e8a90..638643d0a6772d43f440df3942c6c723f1eff3ef 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c
@@ -6,10 +6,6 @@
 #include "../../../cmse-5.x"

 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
@@ -26,7 +22,6 @@
 /* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */ -/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */ +/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c index fd1a24b3258e8403394dac98ff7c4712b0eb7a1b..9ec14d1a707839e4858bac72bc292fd0984bf86c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c index d8f9b7758d50f74f777fcda22f3f6714ff28bb96..d375879ed02483c05d7853c95f9b9e15383ff321 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c index 4878c6ef9157abff003780fbf6401db8eb3ef2f3..e5cb0fabd4ce20ef8e57f25778b81a3ed3908af0 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c index 82aad2d13d6b170c92fd2c2345ab76f41e383013..7e3b7609dfa5c8c1df77e413fa1bb85aa80ea9f6 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c
@@ -6,10 +6,6 @@
 #include "../../../cmse-5.x"

 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
@@ -19,7 +15,6 @@
 /* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */ -/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */ +/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c index 8e054c2aeebac4bd3f164b00ad867bc2d72cb674..d998b43a148250a15eb4aae9fb0ef6e4bf51203b 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c index e74cea7697ba1c12ebeef21636d1b8fd60b42677..e416bef2cb9fabd9cb33e3c1c87057ebdd3d6daf 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c index 4c4a0c956fa574f8fa25e4222ce9274bfbc5e32d..d43a9f85a199ecdf7e018852b3af9b4cf36af81f 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c
@@ -8,9 +8,9 @@
 /* { 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 "clrm\t\{r1, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */

diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c index c684d79fae00feb8e15e9f142735f005473b6011..157bccb9ff3256056d496a0d0770374315b04d87 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c
@@ -5,13 +5,8 @@
 #include "../../../cmse-5.x"

 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
-/* { dg-final { scan-assembler "mov\tip, lr" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */ -/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c index 4cb6a54a0a5b02954519e64503d7c2c4c0e4750d..02e48157a2c61b0a8bee77e949944acc2a4bee37 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c
@@ -7,10 +7,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */

diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c index 4764b2fadfb38661764b909cdb2c9cd109e24df0..c7a22a2ba464dce26b289635dd8dcc8213ae33d8 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c
@@ -9,8 +9,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */

diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c index 9b2e7565d24ff52138b0fb90a1e6268aa4c515a0..2522a17a6316d76a21d8d241d4c44cdddf1981e0 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c
@@ -8,9 +8,6 @@
 /* { dg-final { scan-assembler "__acle_se_foo:" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
 /* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
@@ -27,7 +24,6 @@
 /* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */ -/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c index 9e93d75c35de5e3dde1074fb99da94edc2648319..d34ca383236fdd31723966e6218ea918cf8c9122 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */

 /* 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/8_1m/softfp-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c index 566889e66c8cea6ca32348f48742d2c325336995..ff8e9816cff1569bbfc1c5213c1f8ed2e49ba250 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c
@@ -10,8 +10,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */

 /* 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/8_1m/softfp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c index 0ee28de4123c5e09df7c5d1046e0bd555af6f0fa..ff9a7dfa5e696e3a6c4132343d0ee94c3068c208 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c
@@ -9,8 +9,9 @@
 /* { 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" } } */
+/* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, APSR\}" } } */

 /* 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/8_1m/softfp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c index 5af1fdb934ce5aa5afd8d096122b6e9b55591bd9..eb7561f2a2629f3c153afe3a1a5c58d8abb9d07b 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c
@@ -7,10 +7,6 @@

 /* { dg-final { scan-assembler "__acle_se_foo:" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
@@ -19,7 +15,6 @@
 /* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */ -/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c index 1c38290e79d18a8f94e44b974c54220e553a9a49..03d36aa650986b6069e2fe1c1f3f98fa9664d88a 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */

 /* 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/8_1m/softfp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c index 39c2e72f968ce9f30d36bd347544ca26b3dfad8a..ce45e10688f855ca7b2a63777d2b3d3418815589 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c
@@ -10,8 +10,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */

 /* 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/8_1m/union-1.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c index d51db020c7707fa714364b10dd3ec5896a9dad17..dbd1d34413ef36f2b03716c0d9cf46b024af0835 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c index 131afbbf4289b238438c53ab9ea55d13b8567513..3edc7f1e259779a24e722d67ed544c0a673090c7 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c
@@ -14,5 +14,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c index 0ee28de4123c5e09df7c5d1046e0bd555af6f0fa..3a72406df2492206c2cb8ac7b63e4242ec0ba598 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c
@@ -9,8 +9,9 @@
 /* { 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" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler-not "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/struct-1.c b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c index 5f6891a26d9be6edbb81c6c9e71897d1b49c8c60..90fdac18e30424edca60b6f884227adbf716899d 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/struct-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c
@@ -29,5 +29,6 @@ main (void)
 /* { dg-final { scan-assembler "movs\tr1, #255" } } */
 /* { dg-final { scan-assembler "movt\tr1, 65535" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index c685bcbf99c81210a34192cc31db055fa7b2d605..1db1ff001a5b9d4d7796f0de9355d2b46030c96e 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -78,6 +78,7 @@ extern int thumb_legitimate_offset_p (machine_mode, HOST_WIDE_INT);
 extern int thumb1_legitimate_address_p (machine_mode, rtx, int);
 extern bool ldm_stm_operation_p (rtx, bool, machine_mode mode,
                                  bool, bool);
+extern bool clear_operation_p (rtx);
 extern int arm_const_double_rtx (rtx);
 extern int vfp3_const_double_rtx (rtx);
 extern int neon_immediate_valid_for_move (rtx, machine_mode, rtx *, int *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 68c8779245e56be0c8e808a8c98d631eee3f325c..d10ff0736fed4baa92fab0ff978db62c05c6dc7f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13634,6 +13634,70 @@ ldm_stm_operation_p (rtx op, bool load, machine_mode mode,
   return true;
 }
 
+/* Checks whether OP is a valid parallel pattern for a CLRM insn.  To be a
+   valid CLRM pattern, OP must have the following form:
+
+   [(set (reg:SI <N>) (const_int 0))
+    (set (reg:SI <M>) (const_int 0))
+    ...
+    (unspec_volatile [(const_int 0)]
+		     VUNSPEC_CLRM_APSR)
+    (clobber (reg:CC CC_REGNUM))
+   ]
+
+   Any number (including 0) of set expressions is valid, the volatile unspec is
+   optional.  All registers but SP and PC are allowed and registers must be in
+   strict increasing order.  */
+
+bool
+clear_operation_p (rtx op)
+{
+  HOST_WIDE_INT i;
+  unsigned regno, last_regno;
+  rtx elt, reg, zero;
+  machine_mode mode;
+  HOST_WIDE_INT count = XVECLEN (op, 0);
+
+  for (i = 0; i < count; i++)
+    {
+      elt = XVECEXP (op, 0, i);
+
+      if (GET_CODE (elt) == UNSPEC_VOLATILE)
+	{
+	  if (XINT (elt, 1) != VUNSPEC_CLRM_APSR
+	      || XVECLEN (elt, 0) != 1
+	      || XVECEXP (elt, 0, 0) != CONST0_RTX (SImode)
+	      || i != count - 2)
+	    return false;
+
+	  continue;
+	}
+
+      if (GET_CODE (elt) == CLOBBER)
+	continue;
+
+      if (GET_CODE (elt) != SET)
+	return false;
+
+      reg = SET_DEST (elt);
+      regno = REGNO (reg);
+      mode = GET_MODE (reg);
+      zero = SET_SRC (elt);
+
+      if (!REG_P (reg)
+	  || GET_MODE (reg) != SImode
+	  || regno == SP_REGNUM
+	  || regno == PC_REGNUM
+	  || (i != 0 && regno <= last_regno)
+	  || zero != CONST0_RTX (SImode))
+	return false;
+
+      last_regno = REGNO (reg);
+    }
+
+  return true;
+}
+
 /* Return true iff it would be profitable to turn a sequence of NOPS loads
    or stores (depending on IS_STORE) into a load-multiple or store-multiple
    instruction.  ADD_OFFSET is nonzero if the base address register needs
@@ -17964,6 +18028,62 @@ cmse_clear_registers (sbitmap to_clear_bitmap, uint32_t *padding_bits_to_clear,
 
   /* Clear full registers.  */
 
+  if (TARGET_HAVE_FPCXT_CMSE)
+    {
+      rtvec vunspec_vec;
+      int i, j, k, nb_regs;
+      rtx use_seq, par, reg, set, vunspec;
+      int to_clear_bitmap_size = SBITMAP_SIZE (to_clear_bitmap);
+      auto_sbitmap core_regs_bitmap (to_clear_bitmap_size);
+      auto_sbitmap to_clear_core_bitmap (to_clear_bitmap_size);
+
+      /* Get set of core registers to clear.  */
+      bitmap_clear (core_regs_bitmap);
+      bitmap_set_range (core_regs_bitmap, R0_REGNUM,
+			IP_REGNUM - R0_REGNUM + 1);
+      bitmap_and (to_clear_core_bitmap, to_clear_bitmap,
+		  core_regs_bitmap);
+      gcc_assert (!bitmap_empty_p (to_clear_core_bitmap));
+
+      if (bitmap_empty_p (to_clear_core_bitmap))
+	return;
+
+      /* Create clrm RTX pattern.  */
+      nb_regs = bitmap_count_bits (to_clear_core_bitmap);
+      par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nb_regs + 2));
+
+      /* Insert core register clearing RTX in the pattern.  */
+      start_sequence ();
+      for (j = 0, i = minregno; j < nb_regs; i++)
+	{
+	  if (!bitmap_bit_p (to_clear_core_bitmap, i))
+	    continue;
+
+	  reg = gen_rtx_REG (SImode, i);
+	  set = gen_rtx_SET (reg, const0_rtx);
+	  XVECEXP (par, 0, j++) = set;
+	  emit_use (reg);
+	}
+
+      /* Insert APSR register clearing RTX in the pattern
+       * along with clobbering CC.  */
+      vunspec_vec = gen_rtvec (1, gen_int_mode (0, SImode));
+      vunspec = gen_rtx_UNSPEC_VOLATILE (SImode, vunspec_vec,
+					 VUNSPEC_CLRM_APSR);
+
+      XVECEXP (par, 0, j++) = vunspec;
+
+      rtx ccreg = gen_rtx_REG (CCmode, CC_REGNUM);
+      rtx clobber = gen_rtx_CLOBBER (VOIDmode, ccreg);
+      XVECEXP (par, 0, j) = clobber;
+
+      use_seq = get_insns ();
+      end_sequence ();
+
+      emit_insn_after (use_seq, emit_insn (par));
+      minregno = FIRST_VFP_REGNUM;
+    }
+
   /* If not marked for clearing, clearing_reg already does not contain
      any secret.  */
   if (clearing_regno <= maxregno
@@ -20627,40 +20747,42 @@ output_return_instruction (rtx operand, bool really_return, bool reverse,
 	default:
 	  if (IS_CMSE_ENTRY (func_type))
 	    {
-	      /* Check if we have to clear the 'GE bits' which is only used if
-		 parallel add and subtraction instructions are available.  */
-	      if (TARGET_INT_SIMD)
-		snprintf (instr, sizeof (instr),
-			  "msr%s\tAPSR_nzcvqg, %%|lr", conditional);
-	      else
-		snprintf (instr, sizeof (instr),
-			  "msr%s\tAPSR_nzcvq, %%|lr", conditional);
-
-	      output_asm_insn (instr, & operand);
-	      /* Do not clear FPSCR if targeting Armv8.1-M Mainline, VLDR takes
-		 care of it.  */
-	      if (TARGET_HARD_FLOAT && ! TARGET_HAVE_FPCXT_CMSE)
+	      /* For Armv8.1-M, this is cleared as part of the CLRM instruction
+		 emitted by cmse_nonsecure_entry_clear_before_return () and the
+		 VSTR/VLDR instructions in the prologue and epilogue.  */
+	      if (!TARGET_HAVE_FPCXT_CMSE)
 		{
-		  /* Clear the cumulative exception-status bits (0-4,7) and the
-		     condition code bits (28-31) of the FPSCR.  We need to
-		     remember to clear the first scratch register used (IP) and
-		     save and restore the second (r4).  */
-		  snprintf (instr, sizeof (instr), "push\t{%%|r4}");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "vmrs\t%%|ip, fpscr");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "movw\t%%|r4, #65376");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "movt\t%%|r4, #4095");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "and\t%%|ip, %%|r4");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "vmsr\tfpscr, %%|ip");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "pop\t{%%|r4}");
-		  output_asm_insn (instr, & operand);
-		  snprintf (instr, sizeof (instr), "mov\t%%|ip, %%|lr");
+		  /* Check if we have to clear the 'GE bits' which is only used if
+		     parallel add and subtraction instructions are available.  */
+		  if (TARGET_INT_SIMD)
+		    snprintf (instr, sizeof (instr),
+			      "msr%s\tAPSR_nzcvqg, %%|lr", conditional);
+		  else
+		    snprintf (instr, sizeof (instr),
+			      "msr%s\tAPSR_nzcvq, %%|lr", conditional);
+
 		  output_asm_insn (instr, & operand);
+		  /* Do not clear FPSCR if targeting Armv8.1-M Mainline, VLDR takes
+		     care of it.  */
+		  if (TARGET_HARD_FLOAT)
+		    {
+		      /* Clear the cumulative exception-status bits (0-4,7) and
+			 the condition code bits (28-31) of the FPSCR.  We need
+			 to remember to clear the first scratch register used
+			 (IP) and save and restore the second (r4).
+
+			 Important note: the length of the
+			 thumb2_cmse_entry_return insn pattern must account for
+			 the size of the below instructions.  */
+		      output_asm_insn ("push\t{%|r4}", & operand);
+		      output_asm_insn ("vmrs\t%|ip, fpscr", & operand);
+		      output_asm_insn ("movw\t%|r4, #65376", & operand);
+		      output_asm_insn ("movt\t%|r4, #4095", & operand);
+		      output_asm_insn ("and\t%|ip, %|r4", & operand);
+		      output_asm_insn ("vmsr\tfpscr, %|ip", & operand);
+		      output_asm_insn ("pop\t{%|r4}", & operand);
+		      output_asm_insn ("mov\t%|ip, %|lr", & operand);
+		    }
 		}
 	      snprintf (instr, sizeof (instr), "bxns\t%%|lr");
 	    }
@@ -22643,6 +22765,9 @@ arm_expand_prologue (void)
       saved_regs += 4;
       insn = emit_insn (gen_push_fpsysreg_insn (stack_pointer_rtx,
 						GEN_INT (FPCXTNS_ENUM)));
+      rtx dwarf = gen_rtx_SET (stack_pointer_rtx,
+			  plus_constant (Pmode, stack_pointer_rtx, -4));
+      add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
       RTX_FRAME_RELATED_P (insn) = 1;
     }
 
@@ -25059,8 +25184,11 @@ thumb_exit (FILE *f, int reg_containing_return_addr)
 
       if (IS_CMSE_ENTRY (arm_current_func_type ()))
 	{
-	  asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n",
-		       reg_containing_return_addr);
+	  /* For Armv8.1-M, this is cleared as part of the CLRM instruction
+	     emitted by cmse_nonsecure_entry_clear_before_return ().  */
+	  if (!TARGET_HAVE_FPCXT_CMSE)
+	    asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n",
+			 reg_containing_return_addr);
 	  asm_fprintf (f, "\tbxns\t%r\n", reg_containing_return_addr);
 	}
       else
@@ -25300,11 +25428,14 @@ thumb_exit (FILE *f, int reg_containing_return_addr)
          address.  It may therefore contain information that we might not want
 	 to leak, hence it must be cleared.  The value in R0 will never be a
 	 secret at this point, so it is safe to use it, see the clearing code
-	 in 'cmse_nonsecure_entry_clear_before_return'.  */
+	 in cmse_nonsecure_entry_clear_before_return ().  */
       if (reg_containing_return_addr != LR_REGNUM)
 	asm_fprintf (f, "\tmov\tlr, r0\n");
 
-      asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n", reg_containing_return_addr);
+      /* For Armv8.1-M, this is cleared as part of the CLRM instruction emitted
+	 by cmse_nonsecure_entry_clear_before_return ().  */
+      if (!TARGET_HAVE_FPCXT_CMSE)
+	asm_fprintf (f, "\tmsr\tAPSR_nzcvq, %r\n", reg_containing_return_addr);
       asm_fprintf (f, "\tbxns\t%r\n", reg_containing_return_addr);
     }
   else
@@ -26842,6 +26973,9 @@ arm_expand_epilogue (bool really_return)
 
 	  insn = emit_insn (gen_pop_fpsysreg_insn (stack_pointer_rtx,
 						   GEN_INT (FPCXTNS_ENUM)));
+	  rtx dwarf = gen_rtx_SET (stack_pointer_rtx,
+				  plus_constant (Pmode, stack_pointer_rtx, 4));
+	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
 	  RTX_FRAME_RELATED_P (insn) = 1;
 	}
       }
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 267c446c03e8903c21a0d74e43ae589ffcf689f4..3668c45081f116d1648ba08bab87aed9eab971c3 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -537,6 +537,12 @@
 	    (match_test "satisfies_constraint_Dy (op)")
 	    (match_test "satisfies_constraint_G (op)"))))
 
+(define_special_predicate "clear_multiple_operation"
+  (match_code "parallel")
+{
+ return clear_operation_p (op);
+})
+
 (define_special_predicate "load_multiple_operation"
   (match_code "parallel")
 {
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 7fce50b045b40f0d29ba792dce05e43072dad3b0..ea60005db0409058b1611d399d6a6cc96a933b41 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -1576,3 +1576,44 @@
       FAIL;
  }")
 
+(define_insn "*clear_apsr"
+  [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
+  (clobber (reg:CC CC_REGNUM))]
+  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
+  "clrm%?\\t{APSR}"
+  [(set_attr "predicable" "yes")]
+)
+
+;; The operands are validated through the clear_multiple_operation
+;; match_parallel predicate rather than through constraints so enable it only
+;; after reload.
+(define_insn "*clear_multiple"
+  [(match_parallel 0 "clear_multiple_operation"
+     [(set (match_operand:SI 1 "register_operand" "")
+	   (const_int 0))])]
+  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
+  {
+    char pattern[100];
+    int i, num_saves = XVECLEN (operands[0], 0);
+
+    strcpy (pattern, \"clrm%?\\t{\");
+    for (i = 0; i < num_saves; i++)
+      {
+	if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
+	  {
+	    strcat (pattern, \"APSR\");
+	    // Skip clobber
+	    ++i;
+	  }
+	else
+	  strcat (pattern,
+		  reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
+	if (i < num_saves - 1)
+	  strcat (pattern, \", %|\");
+      }
+    strcat (pattern, \"}\");
+    output_asm_insn (pattern, operands);
+    return \"\";
+  }
+  [(set_attr "predicable" "yes")]
+)
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 59d354e9a918187ab2f747d5e5f8f7edd9ad7082..4dcdcc6fc3fd3ea396e1d5479c8ce0b37db065f1 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -212,6 +212,7 @@
   VUNSPEC_MRRC2		; Represent the coprocessor mrrc2 instruction.
   VUNSPEC_SPECULATION_BARRIER ; Represents an unconditional speculation barrier.
   VUNSPEC_VSTR_VLDR	; Represent the vstr/vldr instruction.
+  VUNSPEC_CLRM_APSR	; Represent the clearing of APSR with clrm instruction.
 ])
 
 ;; Enumerators for NEON unspecs.
diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c
index 6d611e130b6f3b544807b767927d99b89071343b..7036cb9508c27d56c4b2c01a81c44bf6f1f9c781 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-1.c
@@ -36,6 +36,7 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #1855" } } */
 /* { dg-final { scan-assembler "movt\tr1, 65535" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c
index b7ec0a040319545b50590261278f1517bcb22796..50d4979470dd21738453e0d70c7a69ee0752ac41 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-2.c
@@ -33,6 +33,7 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #1919" } } */
 /* { dg-final { scan-assembler "movt\tr1, 2047" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c
index 7b9c3f0fe061317f71d3122dea7a55ab5311f234..2b7507c900ab18705083ba1d86359e1ae36a50a2 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/bitfield-3.c
@@ -34,5 +34,6 @@ main (void)
 /* { dg-final { scan-assembler "movw\tr1, #65535" } } */
 /* { dg-final { scan-assembler "movt\tr1, 63" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
index aa0ec8e0b0f0953a5a5cbc2db58413176c2505f3..35cab1f3233daac9fba50d25dac23364c798fb9c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
@@ -105,8 +105,10 @@ qux (int_nsfunc_t * callback)
 /* { dg-final { scan-assembler "bic" } } */
 /* { dg-final { scan-assembler "push\t\{r4, r5, r6" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" { target arm_cmse_clear_ok } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq" } } */
+/* { dg-final { scan-assembler "msr\tAPSR_nzcvq" { target { ! arm_cmse_clear_ok } } } } */
+/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, APSR\}" { target arm_cmse_clear_ok } } } */
 
 int call_callback (void)
 {
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
index df1ea52bec533c36a738d7d3b2b2ff749b0f3713..1f5af7c2dba7747f6058d12af8ef80b4dd1b1431 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
@@ -9,5 +9,6 @@ int foo (void)
   return bar ();
 }
 
+/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
 /* { dg-final { scan-assembler-not "^(.*\\s)?bl?\[^\\s]*\\s+bar" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c
index 62c63b888ab49e99fba0a08b69941e73c9a8d33b..c52e1c14d9956743625e3b8a200e823f163924e3 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c
@@ -12,5 +12,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c
index b718a70522b86e2bc58900681a781129543f8869..fdba955a32fc5ad492b74974185f98470bc49a7e 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-5.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c
index 16536ab4f9ec5782463ab90f404a2e9f6f938850..85068ceaac6a5c0c60af4a54c0af0d20326fc18d 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-6.c
@@ -13,5 +13,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c
index 0b3cc1e2b2b26e185a9d5d4855d3bea8c70289b5..af69d38acf47d9d1d55480edba2b66f07e2d06ad 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-7.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c
index 914ea39626f2f72eac8c9c1cb495b0855e58f5e1..62201595549f07b046c7c5972d612ab155c4c38c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-8.c
@@ -13,5 +13,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c
index 32435d255805331c7c56a096675b7a2af3286e5e..287f0d6faad113fbc8c30051280668baa58ab130 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-9.c
@@ -7,7 +7,5 @@
 /* { 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 "clrm\t\{r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c
index eb655b5504e58dc842853c8cb874c5cef3b82aa6..7b2df1faff5ea6ce6e7a58a37cd23eaf9616ee97 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c
index ab266af7092afbce868792446124c291188e8a90..638643d0a6772d43f440df3942c6c723f1eff3ef 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-5.c
@@ -6,10 +6,6 @@
 #include "../../../cmse-5.x"
 
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
@@ -26,7 +22,6 @@
 /* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c
index fd1a24b3258e8403394dac98ff7c4712b0eb7a1b..9ec14d1a707839e4858bac72bc292fd0984bf86c 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c
index d8f9b7758d50f74f777fcda22f3f6714ff28bb96..d375879ed02483c05d7853c95f9b9e15383ff321 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-8.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c
index 4878c6ef9157abff003780fbf6401db8eb3ef2f3..e5cb0fabd4ce20ef8e57f25778b81a3ed3908af0 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-13.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c
index 82aad2d13d6b170c92fd2c2345ab76f41e383013..7e3b7609dfa5c8c1df77e413fa1bb85aa80ea9f6 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-5.c
@@ -6,10 +6,6 @@
 #include "../../../cmse-5.x"
 
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
@@ -19,7 +15,6 @@
 /* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c
index 8e054c2aeebac4bd3f164b00ad867bc2d72cb674..d998b43a148250a15eb4aae9fb0ef6e4bf51203b 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c
index e74cea7697ba1c12ebeef21636d1b8fd60b42677..e416bef2cb9fabd9cb33e3c1c87057ebdd3d6daf 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/hard/cmse-8.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c
index 4c4a0c956fa574f8fa25e4222ce9274bfbc5e32d..d43a9f85a199ecdf7e018852b3af9b4cf36af81f 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13.c
@@ -8,9 +8,9 @@
 /* { 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 "clrm\t\{r1, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c
index c684d79fae00feb8e15e9f142735f005473b6011..157bccb9ff3256056d496a0d0770374315b04d87 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-5.c
@@ -5,13 +5,8 @@
 #include "../../../cmse-5.x"
 
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
-/* { dg-final { scan-assembler "mov\tip, lr" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c
index 4cb6a54a0a5b02954519e64503d7c2c4c0e4750d..02e48157a2c61b0a8bee77e949944acc2a4bee37 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7.c
@@ -7,10 +7,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c
index 4764b2fadfb38661764b909cdb2c9cd109e24df0..c7a22a2ba464dce26b289635dd8dcc8213ae33d8 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8.c
@@ -9,8 +9,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler-not "vmov" } } */
 /* { dg-final { scan-assembler-not "vmsr" } } */
 
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c
index 9b2e7565d24ff52138b0fb90a1e6268aa4c515a0..2522a17a6316d76a21d8d241d4c44cdddf1981e0 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-5.c
@@ -8,9 +8,6 @@
 /* { dg-final { scan-assembler "__acle_se_foo:" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
 /* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts2, #1\.0" } } */
@@ -27,7 +24,6 @@
 /* { dg-final { scan-assembler "vmov\.f32\ts13, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts14, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f32\ts15, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c
index 9e93d75c35de5e3dde1074fb99da94edc2648319..d34ca383236fdd31723966e6218ea918cf8c9122 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 
 /* 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/8_1m/softfp-sp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c
index 566889e66c8cea6ca32348f48742d2c325336995..ff8e9816cff1569bbfc1c5213c1f8ed2e49ba250 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8.c
@@ -10,8 +10,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 
 /* 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/8_1m/softfp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c
index 0ee28de4123c5e09df7c5d1046e0bd555af6f0fa..ff9a7dfa5e696e3a6c4132343d0ee94c3068c208 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13.c
@@ -9,8 +9,9 @@
 /* { 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" } } */
+/* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr3, r4" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, APSR\}" } } */
 
 /* 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/8_1m/softfp/cmse-5.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c
index 5af1fdb934ce5aa5afd8d096122b6e9b55591bd9..eb7561f2a2629f3c153afe3a1a5c58d8abb9d07b 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-5.c
@@ -7,10 +7,6 @@
 
 /* { dg-final { scan-assembler "__acle_se_foo:" } } */
 /* { dg-final { scan-assembler "vstr\tFPCXTNS, \\\[sp, #-4\\\]!" } } */
-/* { dg-final { scan-assembler-not "mov\tr0, lr" } } */
-/* { dg-final { scan-assembler "mov\tr1, lr" } } */
-/* { dg-final { scan-assembler "mov\tr2, lr" } } */
-/* { dg-final { scan-assembler "mov\tr3, lr" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td0, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td1, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td2, #1\.0" } } */
@@ -19,7 +15,6 @@
 /* { dg-final { scan-assembler "vmov\.f64\td5, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td6, #1\.0" } } */
 /* { dg-final { scan-assembler "vmov\.f64\td7, #1\.0" } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvq, lr" { target { ! arm_dsp } } } } */
-/* { dg-final { scan-assembler "msr\tAPSR_nzcvqg, lr" { target arm_dsp } } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" } } */
 /* { dg-final { scan-assembler "bxns" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c
index 1c38290e79d18a8f94e44b974c54220e553a9a49..03d36aa650986b6069e2fe1c1f3f98fa9664d88a 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7.c
@@ -8,10 +8,7 @@
 /* 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 "clrm\t\{r0, r1, r2, r3, APSR\}" } } */
 
 /* 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/8_1m/softfp/cmse-8.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c
index 39c2e72f968ce9f30d36bd347544ca26b3dfad8a..ce45e10688f855ca7b2a63777d2b3d3418815589 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8.c
@@ -10,8 +10,7 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 
 /* 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/8_1m/union-1.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c
index d51db020c7707fa714364b10dd3ec5896a9dad17..dbd1d34413ef36f2b03716c0d9cf46b024af0835 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-1.c
@@ -10,6 +10,5 @@
 /* { 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 "clrm\t\{r2, r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c
index 131afbbf4289b238438c53ab9ea55d13b8567513..3edc7f1e259779a24e722d67ed544c0a673090c7 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/union-2.c
@@ -14,5 +14,5 @@
 /* { 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 "clrm\t\{r3, APSR\}" } } */
 /* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c b/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c
index 0ee28de4123c5e09df7c5d1046e0bd555af6f0fa..3a72406df2492206c2cb8ac7b63e4242ec0ba598 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/mainline/8m/softfp/cmse-13.c
@@ -9,8 +9,9 @@
 /* { 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" } } */
+/* { dg-final { scan-assembler "mov\tr1, r4" } } */
+/* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
+/* { dg-final { scan-assembler-not "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/struct-1.c b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c
index 5f6891a26d9be6edbb81c6c9e71897d1b49c8c60..90fdac18e30424edca60b6f884227adbf716899d 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/struct-1.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/struct-1.c
@@ -29,5 +29,6 @@ main (void)
 /* { dg-final { scan-assembler "movs\tr1, #255" } } */
 /* { dg-final { scan-assembler "movt\tr1, 65535" } } */
 /* { dg-final { scan-assembler "ands\tr0(, r0)?, r1" } } */
+/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, ip, APSR\}" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { target arm_cmse_clear_ok } } } */
 /* { dg-final { scan-assembler "bxns" } } */

Reply via email to