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