Commit 1e4f3696 by Mihail Ionescu

[PATCH, GCC/ARM, 7/10] Clear all VFP regs inline in hardfloat nscall functions

The patch is fairly straightforward in its approach and consist of the
following 3 logical changes:
- abstract the number of floating-point register to clear in
  max_fp_regno
- use max_fp_regno to decide how many registers to clear so that the
  same code works for Armv8-M and Armv8.1-M Mainline
- emit vpush and vpop instruction respectively before and after a
  nonsecure call

Note that as in the patch to clear GPRs inline, debug information has to
be disabled for VPUSH and VPOP due to VPOP adding CFA adjustment note
for SP when R7 is sometimes used as CFA.

ChangeLog entries are as follows:

*** gcc/ChangeLog ***

2020-01-16  Mihail-Calin Ionescu  <mihail.ionescu@arm.com>
2020-01-16  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* config/arm/arm.c (vfp_emit_fstmd): Declare early.
	(arm_emit_vfp_multi_reg_pop): Likewise.
	(cmse_nonsecure_call_inline_register_clear): Abstract number of VFP
	registers to clear in max_fp_regno.  Emit VPUSH and VPOP to save and
	restore callee-saved VFP registers.

*** gcc/testsuite/ChangeLog ***

2020-01-16  Mihail-Calin Ionescu  <mihail.ionescu@arm.com>
2020-01-16  Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c: Add check for
	VPUSH and VPOP and update expectation for VSCCLRM.
	* 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.
parent 2d924ca6
2020-01-16 Mihail-Calin Ionescu <mihail.ionescu@arm.com>
2020-01-16 Thomas Preud'homme <thomas.preudhomme@arm.com>
* config/arm/arm.c (vfp_emit_fstmd): Declare early.
(arm_emit_vfp_multi_reg_pop): Likewise.
(cmse_nonsecure_call_inline_register_clear): Abstract number of VFP
registers to clear in max_fp_regno. Emit VPUSH and VPOP to save and
restore callee-saved VFP registers.
2020-01-16 Mihail-Calin Ionescu <mihail.ionescu@arm.com>
2020-01-16 Thomas Preud'homme <thomas.preudhomme@arm.com>
* config/arm/arm.c (arm_emit_multi_reg_pop): Declare early.
(cmse_nonsecure_call_clear_caller_saved): Rename into ...
(cmse_nonsecure_call_inline_register_clear): This. Save and clear
......
......@@ -188,6 +188,8 @@ static void emit_constant_insn (rtx cond, rtx pattern);
static rtx_insn *emit_set_insn (rtx, rtx);
static rtx emit_multi_reg_push (unsigned long, unsigned long);
static void arm_emit_multi_reg_pop (unsigned long);
static int vfp_emit_fstmd (int, int);
static void arm_emit_vfp_multi_reg_pop (int, int, rtx);
static int arm_arg_partial_bytes (cumulative_args_t,
const function_arg_info &);
static rtx arm_function_arg (cumulative_args_t, const function_arg_info &);
......@@ -18287,8 +18289,10 @@ cmse_nonsecure_call_inline_register_clear (void)
unsigned address_regnum, regno;
unsigned max_int_regno
= clear_callee_saved ? IP_REGNUM : LAST_ARG_REGNUM;
unsigned max_fp_regno
= TARGET_HAVE_FPCXT_CMSE ? LAST_VFP_REGNUM : D7_VFP_REGNUM;
unsigned maxregno
= TARGET_HARD_FLOAT_ABI ? D7_VFP_REGNUM : max_int_regno;
= TARGET_HARD_FLOAT_ABI ? max_fp_regno : max_int_regno;
auto_sbitmap to_clear_bitmap (maxregno + 1);
rtx_insn *seq;
rtx pat, call, unspec, clearing_reg, ip_reg, shift;
......@@ -18336,7 +18340,7 @@ cmse_nonsecure_call_inline_register_clear (void)
bitmap_clear (float_bitmap);
bitmap_set_range (float_bitmap, FIRST_VFP_REGNUM,
D7_VFP_REGNUM - FIRST_VFP_REGNUM + 1);
max_fp_regno - FIRST_VFP_REGNUM + 1);
bitmap_ior (to_clear_bitmap, to_clear_bitmap, float_bitmap);
}
......@@ -18413,6 +18417,16 @@ cmse_nonsecure_call_inline_register_clear (void)
/* Disable frame debug info in push because it needs to be
disabled for pop (see below). */
RTX_FRAME_RELATED_P (push_insn) = 0;
/* Save VFP callee-saved registers. */
if (TARGET_HARD_FLOAT_ABI)
{
vfp_emit_fstmd (D7_VFP_REGNUM + 1,
(max_fp_regno - D7_VFP_REGNUM) / 2);
/* Disable frame debug info in push because it needs to be
disabled for vpop (see below). */
RTX_FRAME_RELATED_P (get_last_insn ()) = 0;
}
}
/* Clear caller-saved registers that leak before doing a non-secure
......@@ -18427,9 +18441,25 @@ cmse_nonsecure_call_inline_register_clear (void)
if (TARGET_HAVE_FPCXT_CMSE)
{
rtx_insn *next, *pop_insn, *after = insn;
rtx_insn *next, *last, *pop_insn, *after = insn;
start_sequence ();
/* Restore VFP callee-saved registers. */
if (TARGET_HARD_FLOAT_ABI)
{
int nb_callee_saved_vfp_regs =
(max_fp_regno - D7_VFP_REGNUM) / 2;
arm_emit_vfp_multi_reg_pop (D7_VFP_REGNUM + 1,
nb_callee_saved_vfp_regs,
stack_pointer_rtx);
/* Disable frame debug info in vpop because the SP adjustment
is made using a CFA adjustment note while CFA used is
sometimes R7. This then causes an assert failure in the
CFI note creation code. */
RTX_FRAME_RELATED_P (get_last_insn ()) = 0;
}
arm_emit_multi_reg_pop (callee_saved_mask);
pop_insn = get_last_insn ();
......@@ -18446,13 +18476,15 @@ cmse_nonsecure_call_inline_register_clear (void)
not reliable. */
RTX_FRAME_RELATED_P (pop_insn) = 0;
seq = get_insns ();
last = get_last_insn ();
end_sequence ();
emit_insn_after (pop_insn, after);
emit_insn_after (seq, after);
/* Skip pop we have just inserted after nonsecure call, we know
it does not contain a nonsecure call. */
insn = pop_insn;
insn = last;
}
}
}
......
2020-01-16 Mihail-Calin Ionescu <mihail.ionescu@arm.com>
2020-01-16 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.target/arm/cmse/mainline/8_1m/hard-sp/cmse-13.c: Add check for
VPUSH and VPOP and update expectation for VSCCLRM.
* 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.
2020-01-16 Mihail-Calin Ionescu <mihail.ionescu@arm.com>
2020-01-16 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.target/arm/cmse/cmse-1.c: Add check for PUSH and POP and update
CLRM check.
* gcc.target/arm/cmse/cmse-14.c: Likewise.
......
......@@ -9,12 +9,14 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { 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" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s1, VPR\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s4-s15, VPR\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s4-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. */
......
......@@ -9,8 +9,10 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s0-s15, VPR\}" } } */
/* { 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. */
......
......@@ -9,10 +9,12 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { 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-s15, VPR\}" } } */
/* { 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. */
......
......@@ -9,6 +9,7 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { dg-final { scan-assembler-not "vmov\.f32\ts0, #1\.0" } } */
/* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
......@@ -16,7 +17,8 @@
/* { dg-final { scan-assembler-not "vmov\.f32\ts2, #1\.0" } } */
/* { dg-final { scan-assembler-not "vmov\.f32\ts3, #1\.0" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s1, VPR\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s4-s15, VPR\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s4-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. */
......
......@@ -9,8 +9,10 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s0-s15, VPR\}" } } */
/* { 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. */
......
......@@ -9,9 +9,11 @@
/* { dg-final { scan-assembler "lsrs\tr4, r4, #1" } } */
/* { dg-final { scan-assembler "lsls\tr4, r4, #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\}" } } */
/* { dg-final { scan-assembler-not "vmov\.f64\td0, #1\.0" } } */
/* { dg-final { scan-assembler "vscclrm\t\{s2-s15, VPR\}" } } */
/* { 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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment