[PATCH, GCC/ARM, 9/10] Call nscall function with blxns

Kyrill Tkachov kyrylo.tkachov@foss.arm.com
Wed Dec 18 17:00:00 GMT 2019


On 12/18/19 1:38 PM, Mihail Ionescu wrote:
> Hi,
>
> On 11/12/2019 10:23 AM, Kyrill Tkachov wrote:
>>
>> On 10/23/19 10:26 AM, Mihail Ionescu wrote:
>>> [PATCH, GCC/ARM, 9/10] Call nscall function with blxns
>>>
>>> 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 call
>>> functions with the cmse_nonsecure_call attribute directly using blxns
>>> with no undue restriction on the register used for that.
>>>
>>> === Patch description ===
>>>
>>> This change to use BLXNS to call a nonsecure function from secure
>>> directly (not using a libcall) is made in 2 steps:
>>> - change nonsecure_call patterns to use blxns instead of calling
>>>   __gnu_cmse_nonsecure_call
>>> - loosen requirement for function address to allow any register when
>>>   doing BLXNS.
>>>
>>> The former is a straightforward check over whether instructions 
>>> added in
>>> Armv8.1-M Mainline are available while the latter consist in making the
>>> nonsecure call pattern accept any register by using match_operand and
>>> changing the nonsecure_call_internal expander to no force r4 when
>>> targeting Armv8.1-M Mainline.
>>>
>>> The tricky bit is actually in the test update, specifically how to 
>>> check
>>> that register lists for CLRM have all registers except for the one
>>> holding parameters (already done) and the one holding the address used
>>> by BLXNS. This is achieved with 3 scan-assembler directives.
>>>
>>> 1) The first one lists all registers that can appear in CLRM but make
>>>    each of them optional.
>>>    Property guaranteed: no wrong register is cleared and none appears
>>>    twice in the register list.
>>> 2) The second directive check that the CLRM is made of a fixed number
>>>    of the right registers to be cleared. The number used is the number
>>>    of registers that could contain a secret minus one (used to hold the
>>>    address of the function to call.
>>>    Property guaranteed: register list has the right number of registers
>>>    Cumulated property guaranteed: only registers with a potential 
>>> secret
>>>    are cleared and they are all listed but ont
>>> 3) The last directive checks that we cannot find a CLRM with a register
>>>    in it that also appears in BLXNS. This is check via the use of a
>>>    back-reference on any of the allowed register in CLRM, the
>>>    back-reference enforcing that whatever register match in CLRM 
>>> must be
>>>    the same in the BLXNS.
>>>    Property guaranteed: register used for BLXNS is different from
>>>    registers cleared in CLRM.
>>>
>>> Some more care needs to happen for the gcc.target/arm/cmse/cmse-1.c
>>> testcase due to there being two CLRM generated. To ensure the third
>>> directive match the right CLRM to the BLXNS, a negative lookahead is
>>> used between the CLRM register list and the BLXNS. The way negative
>>> lookahead work is by matching the *position* where a given regular
>>> expression does not match. In this case, since it comes after the CLRM
>>> register list it is requesting that what comes after the register list
>>> does not have a CLRM again followed by BLXNS. This guarantees that the
>>> .*blxns after only matches a blxns without another CLRM before.
>>>
>>> ChangeLog entries are as follows:
>>>
>>> *** gcc/ChangeLog ***
>>>
>>> 2019-10-23  Mihail-Calin Ionescu <mihail.ionescu@arm.com>
>>> 2019-10-23  Thomas Preud'homme <thomas.preudhomme@arm.com>
>>>
>>>         * config/arm/arm.md (nonsecure_call_internal): Do not force 
>>> memory
>>>         address in r4 when targeting Armv8.1-M Mainline.
>>>         (nonsecure_call_value_internal): Likewise.
>>>         * config/arm/thumb2.md (nonsecure_call_reg_thumb2): Make 
>>> memory address
>>>         a register match_operand again.  Emit BLXNS when targeting
>>>         Armv8.1-M Mainline.
>>>         (nonsecure_call_value_reg_thumb2): Likewise.
>>>
>>> *** gcc/testsuite/ChangeLog ***
>>>
>>> 2019-10-23  Mihail-Calin Ionescu <mihail.ionescu@arm.com>
>>> 2019-10-23  Thomas Preud'homme <thomas.preudhomme@arm.com>
>>>
>>>         * gcc.target/arm/cmse/cmse-1.c: Add check for BLXNS when 
>>> instructions
>>>         introduced in Armv8.1-M Mainline Security Extensions are 
>>> available and
>>>         restrict checks for libcall to __gnu_cmse_nonsecure_call to 
>>> Armv8-M
>>>         targets only.  Adapt CLRM check to verify register used for 
>>> BLXNS is
>>>         not in the CLRM register list.
>>>         * gcc.target/arm/cmse/cmse-14.c: Likewise.
>>>         * gcc.target/arm/cmse/mainline/8_1m/bitfield-4.c: Likewise 
>>> and adapt
>>>         check for LSB clearing bit to be using the same register as 
>>> BLXNS when
>>>         targeting Armv8.1-M Mainline.
>>>         * 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/bitfield-and-union.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-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-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-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-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-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.
>>>         * gcc.target/arm/cmse/cmse-15.c: Count BLXNS when targeting 
>>> Armv8.1-M
>>>         Mainline and restrict libcall count to Armv8-M.
>>>
>>> Testing: bootstrapped on arm-linux-gnueabihf and arm-none-eabi; 
>>> testsuite shows no
>>> regression.
>>>
>>> Is this ok for trunk?
>>>
>> Ok.
>>
>> Thanks,
>>
>> Kyrill
>>
>>
>
>
> I found a small issue with this one. The constraint for the first 
> operand of nonsecure_call_reg_thumb2 was wrong as it allowed it to 
> pick and overwrite the ip register which can hold the address for the 
> non secure call. The constraint has now been changed to pick one of 
> the low registers.


Ok.

Thanks,

Kyrill


>
>
> Regards,
> Mihail
>
>>> Best regards,
>>>
>>> Mihail
>>>
>>>
>>> ###############     Attachment also inlined for ease of reply 
>>> ###############
>>>
>>>
>>> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
>>> index 
>>> d607f88cb05ffa9cd8a47b8c8e0c53ea3a5ca411..b7af3c060427d972e3cd1c7a8055aec20335c02b 
>>> 100644
>>> --- a/gcc/config/arm/arm.md
>>> +++ b/gcc/config/arm/arm.md
>>> @@ -7561,12 +7561,15 @@
>>>    "use_cmse"
>>>    "
>>>    {
>>> -    rtx tmp;
>>> -    tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
>>> +    if (!TARGET_HAVE_FPCTX_CMSE)
>>> +      {
>>> +       rtx tmp =
>>> +         copy_to_suggested_reg (XEXP (operands[0], 0),
>>>                                   gen_rtx_REG (SImode, R4_REGNUM),
>>>                                   SImode);
>>>
>>> -    operands[0] = replace_equiv_address (operands[0], tmp);
>>> +       operands[0] = replace_equiv_address (operands[0], tmp);
>>> +      }
>>>    }")
>>>
>>>  (define_insn "*call_reg_armv5"
>>> @@ -7669,12 +7672,15 @@
>>>    "use_cmse"
>>>    "
>>>    {
>>> -    rtx tmp;
>>> -    tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
>>> +    if (!TARGET_HAVE_FPCTX_CMSE)
>>> +      {
>>> +       rtx tmp =
>>> +         copy_to_suggested_reg (XEXP (operands[1], 0),
>>>                                   gen_rtx_REG (SImode, R4_REGNUM),
>>>                                   SImode);
>>>
>>> -    operands[1] = replace_equiv_address (operands[1], tmp);
>>> +       operands[1] = replace_equiv_address (operands[1], tmp);
>>> +      }
>>>    }")
>>>
>>>  (define_insn "*call_value_reg_armv5"
>>> diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
>>> index 
>>> 19d25cfe9b97b9428e3a6daebbf8dfb5648f29ef..964b3e2afcd524bb342373b400e35d0a72c4bd7f 
>>> 100644
>>> --- a/gcc/config/arm/thumb2.md
>>> +++ b/gcc/config/arm/thumb2.md
>>> @@ -560,13 +560,18 @@
>>>  )
>>>
>>>  (define_insn "*nonsecure_call_reg_thumb2"
>>> -  [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
>>> +  [(call (unspec:SI [(mem:SI (match_operand:SI 0 
>>> "s_register_operand" "r"))]
>>>                      UNSPEC_NONSECURE_MEM)
>>> -        (match_operand 0 "" ""))
>>> -   (use (match_operand 1 "" ""))
>>> +        (match_operand 1 "" ""))
>>> +   (use (match_operand 2 "" ""))
>>>     (clobber (reg:SI LR_REGNUM))]
>>>    "TARGET_THUMB2 && use_cmse"
>>> -  "bl\\t__gnu_cmse_nonsecure_call"
>>> +  {
>>> +    if (TARGET_HAVE_FPCTX_CMSE)
>>> +      return "blxns\\t%0";
>>> +    else
>>> +      return "bl\\t__gnu_cmse_nonsecure_call";
>>> +  }
>>>    [(set_attr "length" "4")
>>>     (set_attr "type" "call")]
>>>  )
>>> @@ -585,13 +590,18 @@
>>>  (define_insn "*nonsecure_call_value_reg_thumb2"
>>>    [(set (match_operand 0 "" "")
>>>          (call
>>> -        (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
>>> +        (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" 
>>> "l*r"))]
>>>                      UNSPEC_NONSECURE_MEM)
>>> -        (match_operand 1 "" "")))
>>> -   (use (match_operand 2 "" ""))
>>> +        (match_operand 2 "" "")))
>>> +   (use (match_operand 3 "" ""))
>>>     (clobber (reg:SI LR_REGNUM))]
>>>    "TARGET_THUMB2 && use_cmse"
>>> -  "bl\t__gnu_cmse_nonsecure_call"
>>> +  {
>>> +    if (TARGET_HAVE_FPCTX_CMSE)
>>> +      return "blxns\\t%1";
>>> +    else
>>> +      return "bl\\t__gnu_cmse_nonsecure_call";
>>> +  }
>>>    [(set_attr "length" "4")
>>>     (set_attr "type" "call")]
>>>  )
>>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c 
>>> b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
>>> index 
>>> 9f36fa3b1d8b86b4e1827909fca4fee181ba1c61..ddfcfacab5f601a729319a9d2dab03e61ee56bca 
>>> 100644
>>> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
>>> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-1.c
>>> @@ -110,7 +110,13 @@ qux (int_nsfunc_t * callback)
>>>  /* { dg-final { scan-assembler "vldr\tFPCXTNS, \\\[sp\\\], #4" { 
>>> target arm_cmse_clear_ok } } } */
>>>  /* { dg-final { scan-assembler "msr\tAPSR_nzcvq" { target { ! 
>>> arm_cmse_clear_ok } } } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" { target arm_cmse_clear_ok } } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}(?!.*clrm.*blxns).*blxns\t\\1" 
>>> { target arm_cmse_clear_ok } } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" { target arm_cmse_clear_ok } } } */
>>>
>>>  int call_callback (void)
>>> @@ -120,4 +126,5 @@ int call_callback (void)
>>>    else
>>>      return default_callback ();
>>>  }
>>> -/* { dg-final { scan-assembler-times 
>>> "bl\\s+__gnu_cmse_nonsecure_call" 1 } } */
>>> +/* { dg-final { scan-assembler-times 
>>> "bl\\s+__gnu_cmse_nonsecure_call" 1 { target { ! arm_cmse_clear_ok } 
>>> } } } */
>>> +/* { dg-final { scan-assembler "blxns" { target arm_cmse_clear_ok } 
>>> } } */
>>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c 
>>> b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
>>> index 
>>> 6d39afab44329e78a8ff2f693fd94fe6a501af5a..5ab97856066e14c0005b56210e62f2b7a59fd911 
>>> 100644
>>> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
>>> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-14.c
>>> @@ -10,7 +10,15 @@ int foo (void)
>>>  }
>>>
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" { target arm_cmse_clear_ok } } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" { target arm_cmse_clear_ok } } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" { 
>>> target arm_cmse_clear_ok } } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" { 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" } 
>>> } */
>>> +/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" { 
>>> target { ! arm_cmse_clear_ok } } } } */
>>> +/* { dg-final { scan-assembler-not "^(.*\\s)?bl?\[^\\s]*\\s+bar" { 
>>> target { ! arm_cmse_clear_ok } } } } */
>>> +/* { dg-final { scan-assembler "blxns" { target arm_cmse_clear_ok } 
>>> } } */
>>> +/* { dg-final { scan-assembler-not 
>>> "^(.*\\s)?bl?(?!xns)\[^\\s]*\\s+bar" { target arm_cmse_clear_ok } } 
>>> } */
>>> diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c 
>>> b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c
>>> index 
>>> 4e9ace1f3f33b8a8653797e29ca62eb3dd7ae918..0e37b50e004d74dc81f5a8bdc0c9ba21ceaca67d 
>>> 100644
>>> --- a/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c
>>> +++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-15.c
>>> @@ -69,4 +69,9 @@ int secure5 (void)
>>>  {
>>>    return (*s_bar2) ();
>>>  }
>>> -/* { dg-final { scan-assembler-times 
>>> "bl\\s+__gnu_cmse_nonsecure_call" 6 } } */
>>> +
>>> +/* ARMv8-M expectation.  */
>>> +/* { dg-final { scan-assembler-times 
>>> "bl\\s+__gnu_cmse_nonsecure_call" 6 { target { ! arm_cmse_clear_ok } 
>>> } } } */
>>> +
>>> +/* ARMv8.1-M expectation.  */
>>> +/* { dg-final { scan-assembler-times "blxns" 6 { target 
>>> arm_cmse_clear_ok } } } */
>>> 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 
>>> d4caf513ed2153370369bddbfcf6d2568d9f2f1e..ff34edb21c36c9f114aa934fa86ea962d932f273 
>>> 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
>>> @@ -10,9 +10,16 @@
>>>  /* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
>>>  /* { dg-final { scan-assembler "mov\tip, #3" } } */
>>>  /* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r3, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[3-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[3-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 2b7655a2c9971fb0aad4e6c8a1fee72e21028fad..4d1407aba4418006463fdca59cbe90e768e78391 
>>> 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
>>> @@ -8,9 +8,16 @@
>>>  /* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
>>>  /* { dg-final { scan-assembler "movw\tip, #2047" } } */
>>>  /* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 1a62076df9d6831d06f5ac6bdcb7deed0ecd23f8..9b1227adfdc03457266573447c7996245a114110 
>>> 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
>>> @@ -11,9 +11,16 @@
>>>  /* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
>>>  /* { dg-final { scan-assembler "mov\tip, #255" } } */
>>>  /* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r3, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[3-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[3-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 1319ac9766bcd330f6d8f0f7754a64a1dcc105b1..aec958fc9b9d125c54022911ee34affa9dd81797 
>>> 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
>>> @@ -8,9 +8,16 @@
>>>  /* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
>>>  /* { dg-final { scan-assembler "movw\tip, #2047" } } */
>>>  /* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 9bb60175529d77a3b1868f62a5a4d5355f00b76b..ae039e292d55423b1dc1b19551278418224bbe5e 
>>> 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
>>> @@ -11,9 +11,16 @@
>>>  /* { dg-final { scan-assembler "movw\tip, #65535" } } */
>>>  /* { dg-final { scan-assembler "movt\tip, 31" } } */
>>>  /* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r3, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[3-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[3-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 11ca78bfdaf1ebe09f9699c278dc3db4fd20768c..f455f8cf19b1d8f32bd6ca208d33c144da644c29 
>>> 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
>>> @@ -5,9 +5,16 @@
>>>
>>>  /* { dg-final { scan-assembler "movw\tip, #1799" } } */
>>>  /* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[1-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[1-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r1, r2, r3, r5, r6, r7, r8, 
>>> r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r1, )?(r2, )?(r3, )?(r4, 
>>> )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } 
>>> } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[1-9\]|r10|fp|ip), 
>>> ){11}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[1-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> diff --git 
>>> a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-and-union.c 
>>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-and-union.c
>>> index 
>>> 2f14c52715e0ad6e6ab69b01713ee13985a22653..3e76364c40452a7946e3b97e2321fd6e6d204355 
>>> 100644
>>> --- 
>>> a/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-and-union.c
>>> +++ 
>>> b/gcc/testsuite/gcc.target/arm/cmse/mainline/8_1m/bitfield-and-union.c
>>> @@ -15,9 +15,16 @@
>>>  /* { dg-final { scan-assembler "movw\tip, #65535" } } */
>>>  /* { dg-final { scan-assembler "movt\tip, 31" } } */
>>>  /* { dg-final { scan-assembler "and\tr3, r3, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r5, r6, r7, r8, r9, r10, 
>>> fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r4, )?(r5, )?(r6, )?(r7, 
>>> )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[4-9\]|r10|fp|ip), 
>>> ){8}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[4-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> e759db24fac27be2de664ad4faced7bb5d3be84a..0c49277389271321c7fd7faa6ae6aaee2c299def 
>>> 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
>>> @@ -6,11 +6,18 @@
>>>  #include "../../../cmse-13.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts2, #1\.0" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts3, #1\.0" } } */
>>> @@ -20,4 +27,4 @@
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 9df7b5de3ad64e719fc97d7a67a4893398e87b32..3c66b0a8c6f1c7be6c8cf77b2c71916a08c7b357 
>>> 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
>>> @@ -6,14 +6,21 @@
>>>  #include "../../../cmse-7.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vscclrm\t\{s0-s31, VPR\}" } } */
>>>  /* { dg-final { scan-assembler "vldm\tsp!, \{d8-d15\}" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> b36ff73cb9b46d4d3a91f854c022787dc000d9c3..7d456c39705b15fa5b55270ac6b4ed57f5c7e465 
>>> 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
>>> @@ -6,11 +6,18 @@
>>>  #include "../../../cmse-8.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts1, #1\.0" } } */
>>>  /* { dg-final { scan-assembler "vscclrm\t\{s2-s31, VPR\}" } } */
>>> @@ -18,4 +25,4 @@
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 72493f032355828bdf48b84dc98d8102becd1b36..ab95c83a1167aff9fd4c0e24fe5580895cfbf0bb 
>>> 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
>>> @@ -6,11 +6,18 @@
>>>  #include "../../../cmse-13.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f64\td1, #1\.0" } } */
>>> @@ -22,4 +29,4 @@
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 112ed78d6f172be31d4a4f06840d32a90cdf3dd4..cf58d547972e21e0816a1bdf74968d0b50d2bd08 
>>> 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
>>> @@ -6,14 +6,21 @@
>>>  #include "../../../cmse-7.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vscclrm\t\{s0-s31, VPR\}" } } */
>>>  /* { dg-final { scan-assembler "vldm\tsp!, \{d8-d15\}" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> f48e8a0a020cebed8c9fa124d352f047442979d6..1854d03d0814c90f8014a28fb1c81c6866f0071d 
>>> 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
>>> @@ -6,15 +6,22 @@
>>>  #include "../../../cmse-8.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vpush.64\t\{d8, d9, d10, d11, d12, 
>>> d13, d14, d15\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
>>>  /* { dg-final { scan-assembler "vscclrm\t\{s2-s31, VPR\}" } } */
>>>  /* { dg-final { scan-assembler "vldm\tsp!, \{d8-d15\}" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 52d22427de79c6a76fbe32b8df7f76b4b286249c..1b207c394081e6ec9bf569961a4a059d5b47fe20 
>>> 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
>>> @@ -5,18 +5,25 @@
>>>  #include "../../../cmse-13.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[1,4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[1,4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr3, r4" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r1, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r1, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[1,4-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[1,4-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } 
>>> } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>  /* { dg-final { scan-assembler-not "vmov" } } */
>>>  /* { dg-final { scan-assembler-not "vmsr" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 40026d5ee1cc62b4acf48be9619ccd69ef4ead7b..3ec639480868944ed29065936c1fab10aa9e0fed 
>>> 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
>>> @@ -5,15 +5,22 @@
>>>  #include "../../../cmse-7.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>  /* { dg-final { scan-assembler-not "vmov" } } */
>>>  /* { dg-final { scan-assembler-not "vmsr" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 6edc1f6ed7e6bc27024056375db4a2d30c3ea3c4..5c1d245d4aa966812e52f327c7ceba5dabba2e18 
>>> 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
>>> @@ -5,17 +5,24 @@
>>>  #include "../../../cmse-8.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>  /* { dg-final { scan-assembler-not "vmov" } } */
>>>  /* { dg-final { scan-assembler-not "vmsr" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 8d05576add940c277e5a13f7aab99e6807c1553d..3228692c2686fcae8e1369f984aaa6c375ad6418 
>>> 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
>>> @@ -6,13 +6,20 @@
>>>  #include "../../../cmse-7.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 1f0a14742781b7340685338901dbfab9b700b779..1c60d97dabd99136533a61fef5ae099eae4bbc93 
>>> 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
>>> @@ -6,15 +6,22 @@
>>>  #include "../../../cmse-8.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 842794181087ddbd5ce59680035a0cb61ce5682e..c366f6ae4ccc65d943dbbf045925ca9c6e8921ca 
>>> 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
>>> @@ -6,16 +6,23 @@
>>>  #include "../../../cmse-13.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[1,4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[1,4-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr2, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr3, r4" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r1, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r1, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[1,4-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[1,4-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } 
>>> } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 38c9d5457034d2427413bcce7e7be6bad80f7a67..186a4480f4e816bdb2413ecbc690470e1c2480e6 
>>> 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
>>> @@ -6,13 +6,20 @@
>>>  #include "../../../cmse-7.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[0-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r0, r1, r2, r3, r5, r6, r7, 
>>> r8, r9, r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r0, )?(r1, )?(r2, )?(r3, 
>>> )?(r4, )?(r5, )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, 
>>> )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[0-9\]|r10|fp|ip), 
>>> ){12}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[0-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 6a17bd322fcc4e7e00ea289ee7373db9d8c37a87..f0f74f06bbd1eed2f71b46bc8947c99ce1de0765 
>>> 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
>>> @@ -6,15 +6,22 @@
>>>  #include "../../../cmse-8.x"
>>>
>>>  /* 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" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr0, r4" } } */
>>>  /* { dg-final { scan-assembler-not "mov\tr1, r4" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>>  /* { dg-final { scan-assembler "vlstm\tsp" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "vlldm\tsp" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>>
>>>  /* Now we check that we use the correct intrinsic to call. */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 43e58ebde56ceb229edca2db25b720c42207c100..4d58eed1ac21e32dfa893397736be45129af53b8 
>>> 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
>>> @@ -8,9 +8,16 @@
>>>  /* { dg-final { scan-assembler "and\tr0, r0, ip" } } */
>>>  /* { dg-final { scan-assembler "movw\tip, #511" } } */
>>>  /* { dg-final { scan-assembler "and\tr1, r1, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[2-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r2, r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r2, )?(r3, )?(r4, )?(r5, 
>>> )?(r6, )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[2-9\]|r10|fp|ip), 
>>> ){10}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[2-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>> 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 
>>> 6adf8fae5c3a56a6e50278919a2edbd2fda58f42..95de458b50172f6e84ffc2625fc35eca8f65108a 
>>> 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
>>> @@ -12,9 +12,16 @@
>>>  /* { dg-final { scan-assembler "movw\tip, #65535" } } */
>>>  /* { dg-final { scan-assembler "movt\tip, 31" } } */
>>>  /* { dg-final { scan-assembler "and\tr2, r2, ip" } } */
>>> -/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
>>> -/* { dg-final { scan-assembler "lsls\tr4, r4, #1" } } */
>>> +/* Shift on the same register as blxns.  */
>>> +/* { dg-final { scan-assembler "lsrs\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>> +/* { dg-final { scan-assembler "lsls\t(r\[3-9\]|r10|fp|ip), \\1, 
>>> #1.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "push\t\{r4, r5, r6, r7, r8, r9, 
>>> r10, fp\}" } } */
>>> -/* { dg-final { scan-assembler "clrm\t\{r3, r5, r6, r7, r8, r9, 
>>> r10, fp, ip, APSR\}" } } */
>>> +/* Check the right registers are cleared and none appears twice.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{(r3, )?(r4, )?(r5, )?(r6, 
>>> )?(r7, )?(r8, )?(r9, )?(r10, )?(fp, )?(ip, )?APSR\}" } } */
>>> +/* Check that the right number of registers is cleared and thus 
>>> only one
>>> +   register is missing.  */
>>> +/* { dg-final { scan-assembler "clrm\t\{((r\[3-9\]|r10|fp|ip), 
>>> ){9}APSR\}" } } */
>>> +/* Check that no cleared register is used for blxns.  */
>>> +/* { dg-final { scan-assembler-not 
>>> "clrm\t\{\[^\}\]\+(r\[3-9\]|r10|fp|ip),\[^\}\]\+\}.*blxns\t\\1" } } */
>>>  /* { dg-final { scan-assembler "pop\t\{r4, r5, r6, r7, r8, r9, r10, 
>>> fp\}" } } */
>>> -/* { dg-final { scan-assembler "bl\t__gnu_cmse_nonsecure_call" } } */
>>> +/* { dg-final { scan-assembler "blxns" } } */
>>>



More information about the Gcc-patches mailing list