aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm')
-rw-r--r--gcc/config/arm/arm.c40
-rw-r--r--gcc/config/arm/unspecs.md4
-rw-r--r--gcc/config/arm/vfp.md24
3 files changed, 64 insertions, 4 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 2cb2b8e..5e93f52 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -186,6 +186,7 @@ static int arm_register_move_cost (machine_mode, reg_class_t, reg_class_t);
static int arm_memory_move_cost (machine_mode, reg_class_t, bool);
static void emit_constant_insn (rtx cond, rtx pattern);
static rtx_insn *emit_set_insn (rtx, rtx);
+static void arm_add_cfa_adjust_cfa_note (rtx, int, 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);
@@ -18283,6 +18284,9 @@ cmse_nonsecure_call_inline_register_clear (void)
FOR_BB_INSNS (bb, insn)
{
bool clear_callee_saved = TARGET_HAVE_FPCXT_CMSE;
+ /* frame = VFP regs + FPSCR + VPR. */
+ unsigned lazy_store_stack_frame_size
+ = (LAST_VFP_REGNUM - FIRST_VFP_REGNUM + 1 + 2) * UNITS_PER_WORD;
unsigned long callee_saved_mask
= ((1 << (LAST_HI_REGNUM + 1)) - 1)
& ~((1 << (LAST_ARG_REGNUM + 1)) - 1);
@@ -18300,7 +18304,7 @@ cmse_nonsecure_call_inline_register_clear (void)
CUMULATIVE_ARGS args_so_far_v;
cumulative_args_t args_so_far;
tree arg_type, fntype;
- bool first_param = true;
+ bool first_param = true, lazy_fpclear = !TARGET_HARD_FLOAT_ABI;
function_args_iterator args_iter;
uint32_t padding_bits_to_clear[4] = {0U, 0U, 0U, 0U};
@@ -18334,7 +18338,7 @@ cmse_nonsecure_call_inline_register_clear (void)
-mfloat-abi=hard. For -mfloat-abi=softfp we will be using the
lazy store and loads which clear both caller- and callee-saved
registers. */
- if (TARGET_HARD_FLOAT_ABI)
+ if (!lazy_fpclear)
{
auto_sbitmap float_bitmap (maxregno + 1);
@@ -18418,8 +18422,23 @@ cmse_nonsecure_call_inline_register_clear (void)
disabled for pop (see below). */
RTX_FRAME_RELATED_P (push_insn) = 0;
+ /* Lazy store multiple. */
+ if (lazy_fpclear)
+ {
+ rtx imm;
+ rtx_insn *add_insn;
+
+ imm = gen_int_mode (- lazy_store_stack_frame_size, SImode);
+ add_insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx, imm));
+ arm_add_cfa_adjust_cfa_note (add_insn,
+ - lazy_store_stack_frame_size,
+ stack_pointer_rtx,
+ stack_pointer_rtx);
+ emit_insn (gen_lazy_store_multiple_insn (stack_pointer_rtx));
+ }
/* Save VFP callee-saved registers. */
- if (TARGET_HARD_FLOAT_ABI)
+ else
{
vfp_emit_fstmd (D7_VFP_REGNUM + 1,
(max_fp_regno - D7_VFP_REGNUM) / 2);
@@ -18445,8 +18464,21 @@ cmse_nonsecure_call_inline_register_clear (void)
start_sequence ();
+ /* Lazy load multiple done as part of libcall in Armv8-M. */
+ if (lazy_fpclear)
+ {
+ rtx imm = gen_int_mode (lazy_store_stack_frame_size, SImode);
+ emit_insn (gen_lazy_load_multiple_insn (stack_pointer_rtx));
+ rtx_insn *add_insn =
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx, imm));
+ arm_add_cfa_adjust_cfa_note (add_insn,
+ lazy_store_stack_frame_size,
+ stack_pointer_rtx,
+ stack_pointer_rtx);
+ }
/* Restore VFP callee-saved registers. */
- if (TARGET_HARD_FLOAT_ABI)
+ else
{
int nb_callee_saved_vfp_regs =
(max_fp_regno - D7_VFP_REGNUM) / 2;
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 22a1491..8f4a705 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -243,6 +243,10 @@
VUNSPEC_CLRM_APSR ; Represent the clearing of APSR with clrm instruction.
VUNSPEC_VSCCLRM_VPR ; Represent the clearing of VPR with vscclrm
; instruction.
+ VUNSPEC_VLSTM ; Represent the lazy store multiple with vlstm
+ ; instruction.
+ VUNSPEC_VLLDM ; Represent the lazy load multiple with vlldm
+ ; instruction.
])
;; Enumerators for NEON unspecs.
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 92e8d8f..930ef46 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -1673,6 +1673,30 @@
(set_attr "type" "mov_reg")]
)
+(define_insn "lazy_store_multiple_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "+&rk")
+ (post_dec:SI (match_dup 0)))
+ (unspec_volatile [(const_int 0)
+ (mem:SI (post_dec:SI (match_dup 0)))]
+ VUNSPEC_VLSTM)]
+ "use_cmse && reload_completed"
+ "vlstm%?\\t%0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "store_4")]
+)
+
+(define_insn "lazy_load_multiple_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "+&rk")
+ (post_inc:SI (match_dup 0)))
+ (unspec_volatile:SI [(const_int 0)
+ (mem:SI (match_dup 0))]
+ VUNSPEC_VLLDM)]
+ "use_cmse && reload_completed"
+ "vlldm%?\\t%0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "load_4")]
+)
+
(define_insn_and_split "*cmpsf_split_vfp"
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:SF 0 "s_register_operand" "t")