diff --git a/ChangeLog b/ChangeLog index 530ade2d031..d8eb87e7b17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2017-05-09 Claudiu Zissulescu + Andrew Burgess + + * config/arc/arc.c (ARC_AUTOBLINK_IRQ_P): Consider fast interrupts + case. + (ARC_AUTOFP_IRQ_P): Likewise. + (ARC_AUTO_IRQ_P): Likewise. + (rgf_banked_register_count): New variable. + (parse_mrgf_banked_regs_option): New function. + (arc_override_options): Handle rgf_banked_regs option. + (arc_handle_interrupt_attribute): Add firq option. + (arc_compute_function_type): Return fast irq type when required. + (arc_must_save_register): Handle fast interrupts. + (arc_expand_prologue): Do not emit dwarf info for fast interrupts. + (arc_return_address_regs): Update. + * config/arc/arc.h (arc_return_address_regs): Update. + (arc_function_type): Add fast interrupt type. + (ARC_INTERRUPT_P): Update. + (RC_FAST_INTERRUPT_P): Define. + * config/arc/arc.md (simple_return): Update for fast interrupts. + (p_return_i): Likewise. + * config/arc/arc.opt (mrgf-banked-regs): New option. + * doc/invoke.texi (mrgf-banked-regs): Document. + 2017-05-09 Claudiu Zissulescu * config/arc/arc.c (irq_ctrl_saved): New variable. diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index c754d827c81..46ad31e52e0 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -125,16 +125,25 @@ typedef struct irq_ctrl_saved_t static irq_ctrl_saved_t irq_ctrl_saved; #define ARC_AUTOBLINK_IRQ_P(FNTYPE) \ - (ARC_INTERRUPT_P (FNTYPE) && irq_ctrl_saved.irq_save_blink) + ((ARC_INTERRUPT_P (FNTYPE) \ + && irq_ctrl_saved.irq_save_blink) \ + || (ARC_FAST_INTERRUPT_P (FNTYPE) \ + && rgf_banked_register_count > 8)) -#define ARC_AUTOFP_IRQ_P(FNTYPE) \ - (ARC_INTERRUPT_P (FNTYPE) && (irq_ctrl_saved.irq_save_last_reg > 26)) +#define ARC_AUTOFP_IRQ_P(FNTYPE) \ + ((ARC_INTERRUPT_P (FNTYPE) \ + && (irq_ctrl_saved.irq_save_last_reg > 26)) \ + || (ARC_FAST_INTERRUPT_P (FNTYPE) \ + && rgf_banked_register_count > 8)) -#define ARC_AUTO_IRQ_P(FNTYPE) \ - (ARC_INTERRUPT_P (FNTYPE) \ - && (irq_ctrl_saved.irq_save_blink \ +#define ARC_AUTO_IRQ_P(FNTYPE) \ + (ARC_INTERRUPT_P (FNTYPE) && !ARC_FAST_INTERRUPT_P (FNTYPE) \ + && (irq_ctrl_saved.irq_save_blink \ || (irq_ctrl_saved.irq_save_last_reg >= 0))) +/* Number of registers in second bank for FIRQ support. */ +static int rgf_banked_register_count; + #define arc_ccfsm_current cfun->machine->ccfsm_current #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \ @@ -924,6 +933,27 @@ irq_range (const char *cstr) irq_ctrl_saved.irq_save_lpcount = (lpcount == 60); } +/* Parse -mrgf-banked-regs=NUM option string. Valid values for NUM are 4, + 8, 16, or 32. */ + +static void +parse_mrgf_banked_regs_option (const char *arg) +{ + long int val; + char *end_ptr; + + errno = 0; + val = strtol (arg, &end_ptr, 10); + if (errno != 0 || *arg == '\0' || *end_ptr != '\0' + || (val != 0 && val != 4 && val != 8 && val != 16 && val != 32)) + { + error ("invalid number in -mrgf-banked-regs=%s " + "valid values are 0, 4, 8, 16, or 32", arg); + return; + } + rgf_banked_register_count = (int) val; +} + /* Check ARC options, generate derived target attributes. */ static void @@ -966,6 +996,8 @@ arc_override_options (void) irq_ctrl_saved.irq_save_blink = false; irq_ctrl_saved.irq_save_lpcount = false; + rgf_banked_register_count = 0; + /* Handle the deferred options. */ if (vopt) FOR_EACH_VEC_ELT (*vopt, i, opt) @@ -979,6 +1011,13 @@ arc_override_options (void) warning (0, "option -mirq-ctrl-saved valid only for ARC v2 processors"); break; + case OPT_mrgf_banked_regs_: + if (TARGET_V2) + parse_mrgf_banked_regs_option (opt->arg); + else + warning (0, "option -mrgf-banked-regs valid only for ARC v2 processors"); + break; + default: gcc_unreachable(); } @@ -1787,9 +1826,9 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int, name); *no_add_attrs = true; } - else if (strcmp (TREE_STRING_POINTER (value), "ilink1") - && strcmp (TREE_STRING_POINTER (value), "ilink2") - && !TARGET_V2) + else if (!TARGET_V2 + && strcmp (TREE_STRING_POINTER (value), "ilink1") + && strcmp (TREE_STRING_POINTER (value), "ilink2")) { warning (OPT_Wattributes, "argument of %qE attribute is not \"ilink1\" or \"ilink2\"", @@ -1797,10 +1836,11 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int, *no_add_attrs = true; } else if (TARGET_V2 - && strcmp (TREE_STRING_POINTER (value), "ilink")) + && strcmp (TREE_STRING_POINTER (value), "ilink") + && strcmp (TREE_STRING_POINTER (value), "firq")) { warning (OPT_Wattributes, - "argument of %qE attribute is not \"ilink\"", + "argument of %qE attribute is not \"ilink\" or \"firq\"", name); *no_add_attrs = true; } @@ -2360,6 +2400,8 @@ arc_compute_function_type (struct function *fun) fn_type = ARC_FUNCTION_ILINK1; else if (!strcmp (TREE_STRING_POINTER (value), "ilink2")) fn_type = ARC_FUNCTION_ILINK2; + else if (!strcmp (TREE_STRING_POINTER (value), "firq")) + fn_type = ARC_FUNCTION_FIRQ; else gcc_unreachable (); break; @@ -2386,7 +2428,29 @@ arc_must_save_register (int regno, struct function *func) { enum arc_function_type fn_type = arc_compute_function_type (func); bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno) - && ARC_INTERRUPT_P (fn_type)); + && ARC_AUTO_IRQ_P (fn_type)); + bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type); + + switch (rgf_banked_register_count) + { + case 4: + firq_auto_save_p &= (regno < 4); + break; + case 8: + firq_auto_save_p &= ((regno < 4) || ((regno > 11) && (regno < 16))); + break; + case 16: + firq_auto_save_p &= ((regno < 4) || ((regno > 9) && (regno < 16)) + || ((regno > 25) && (regno < 29)) + || ((regno > 29) && (regno < 32))); + break; + case 32: + firq_auto_save_p &= (regno != 29) && (regno < 32); + break; + default: + firq_auto_save_p = false; + break; + } if ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM @@ -2394,7 +2458,8 @@ arc_must_save_register (int regno, struct function *func) && (!call_used_regs[regno] || ARC_INTERRUPT_P (fn_type)) /* Do not emit code for auto saved regs. */ - && !irq_auto_save_p) + && !irq_auto_save_p + && !firq_auto_save_p) return true; if (flag_pic && crtl->uses_pic_offset_table @@ -2723,11 +2788,6 @@ arc_save_restore (rtx base_reg, } } /* arc_save_restore */ - -int arc_return_address_regs[4] - = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM}; - - /* Build dwarf information when the context is saved via AUX_IRQ_CTRL mechanism. */ @@ -2841,7 +2901,8 @@ arc_expand_prologue (void) /* IRQ using automatic save mechanism will save the register before anything we do. */ - if (ARC_AUTO_IRQ_P (fn_type)) + if (ARC_AUTO_IRQ_P (fn_type) + && !ARC_FAST_INTERRUPT_P (fn_type)) { arc_dwarf_emit_irq_save_regs (); } @@ -9700,6 +9761,9 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee) return true; } +int arc_return_address_regs[5] = + {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM}; + /* Implement EPILOGUE__USES. Return true if REGNO should be added to the deemed uses of the epilogue. diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 549113070e0..52f121f71d8 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -1364,7 +1364,7 @@ do { \ /* To translate the return value of arc_function_type into a register number to jump through for function return. */ -extern int arc_return_address_regs[4]; +extern int arc_return_address_regs[5]; /* Debugging information. */ @@ -1501,10 +1501,15 @@ enum arc_function_type { ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL, /* These are interrupt handlers. The name corresponds to the register name that contains the return address. */ - ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2 + ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2, + /* Fast interrupt is only available on ARCv2 processors. */ + ARC_FUNCTION_FIRQ }; -#define ARC_INTERRUPT_P(TYPE) \ -((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2) +#define ARC_INTERRUPT_P(TYPE) \ + (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2) \ + || ((TYPE) == ARC_FUNCTION_FIRQ)) + +#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ) /* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */ struct function; diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 2221fb564d8..5c3766c4604 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -4740,8 +4740,8 @@ = gen_rtx_REG (Pmode, arc_return_address_regs[arc_compute_function_type (cfun)]); - if (arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1 - && TARGET_V2) + if (TARGET_V2 + && ARC_INTERRUPT_P (arc_compute_function_type (cfun))) { return \"rtie\"; } @@ -4751,8 +4751,7 @@ return \"\"; } [(set (attr "type") - (cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)") - (symbol_ref "ARC_FUNCTION_ILINK1")) + (cond [(and (match_test "ARC_INTERRUPT_P (arc_compute_function_type (cfun))") (match_test "TARGET_V2")) (const_string "brcc_no_delay_slot")] (const_string "return"))) @@ -4782,7 +4781,7 @@ (simple_return) (pc)))] "reload_completed && !(TARGET_V2 - && arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1)" + && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))" { rtx xop[2]; xop[0] = operands[0]; diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt index 483470de7cf..f01a2ff0e58 100644 --- a/gcc/config/arc/arc.opt +++ b/gcc/config/arc/arc.opt @@ -490,3 +490,7 @@ Enable unaligned word and halfword accesses to packed data. mirq-ctrl-saved= Target RejectNegative Joined Var(arc_deferred_options) Defer Specifies the registers that the processor saves on an interrupt entry and exit. + +mrgf-banked-regs= +Target RejectNegative Joined Var(arc_deferred_options) Defer +Specifies the number of registers replicated in second register bank on entry to fast interrupt. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6f82e24653f..5360255a67c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -607,6 +607,7 @@ Objective-C and Objective-C++ Dialects}. -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol -mlong-calls -mmedium-calls -msdata -mirq-ctrl-saved @gol +-mrgf-banked-regs @gol -mvolatile-cache -mtp-regno=@var{regno} @gol -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol -mcase-vector-pcrel -mcompact-casesi -mno-cond-exec -mearly-cbranchsi @gol @@ -14556,6 +14557,15 @@ always starts with @code{r0}, the upper limit is @code{fp} register. @var{blink} and @var{lp_count} are optional. This option is only valid for ARC EM and ARC HS cores. +@item -mrgf-banked-regs=@var{number} +@opindex mrgf-banked-regs +Specifies the number of registers replicated in second register bank +on entry to fast interrupt. Fast interrupts are interrupts with the +highest priority level P0. These interrupts save only PC and STATUS32 +registers to avoid memory transactions during interrupt entry and exit +sequences. Use this option when you are using fast interrupts in an +ARC V2 family processor. Permitted values are 4, 8, 16, and 32. + @end table The following options are passed through to the assembler, and also diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0cbe360f697..36d4d1dd958 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2017-05-09 Claudiu Zissulescu + Andrew Burgess + + * gcc.target/arc/firq-1.c: New file. + * gcc.target/arc/firq-2.c: Likewise. + * gcc.target/arc/firq-3.c: Likewise. + * gcc.target/arc/firq-4.c: Likewise. + * gcc.target/arc/firq-5.c: Likewise. + * gcc.target/arc/firq-6.c: Likewise. + 2017-05-09 Claudiu Zissulescu * gcc.target/arc/interrupt-5.c: Newfile. diff --git a/gcc/testsuite/gcc.target/arc/firq-1.c b/gcc/testsuite/gcc.target/arc/firq-1.c new file mode 100644 index 00000000000..87f408793dc --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O0 -mll64 -mirq-ctrl-saved=r0-r9" } */ + +/* Check that on archs the 'firq' interrupt function type is + available, these are the fast interrupts. For fast interrupts, + despite the use of 'irq-ctrl-saved', no registers are automatically + saved on entry to the function, and so, in the following register + r0 to r9 should all be saved to the stack. + + We also take the opportunity to check the use of the 'rtie' + instruction at the end of the interrupt function. */ + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + asm ("" + : + : + : "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9"); +} +/* { dg-final { scan-assembler-times "r2,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r4,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler "rtie" } } */ diff --git a/gcc/testsuite/gcc.target/arc/firq-2.c b/gcc/testsuite/gcc.target/arc/firq-2.c new file mode 100644 index 00000000000..dc7dafca11a --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-2.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O0 -mll64 -mirq-ctrl-saved=r0-r9 -mrgf-banked-regs=4" } */ + +/* Check that on archs the 'firq' interrupt function type is + available, these are the fast interrupts. For fast interrupts, + despite the use of 'irq-ctrl-saved', no registers are automatically + saved on stack on entry to the function. However, the cpu save via + bank switch R0-R3. + + We also take the opportunity to check the use of the 'rtie' instruction + at the end of the interrupt function. */ + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + asm ("" + : + : + : "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9"); +} +/* { dg-final { scan-assembler-not "r0,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "push.*r0" } } */ +/* { dg-final { scan-assembler-not "r1,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r2,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r3,\\\[sp" } } */ +/* { dg-final { scan-assembler "st.*r4,\\\[sp" } } */ +/* { dg-final { scan-assembler "st.*r6,\\\[sp,\[0-9\]+\\\]" } } */ +/* { dg-final { scan-assembler "st.*r8,\\\[sp,\[0-9\]+\\\]" } } */ +/* { dg-final { scan-assembler "rtie" } } */ diff --git a/gcc/testsuite/gcc.target/arc/firq-3.c b/gcc/testsuite/gcc.target/arc/firq-3.c new file mode 100644 index 00000000000..a1d604d8ef7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-3.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O2 -mll64 -mrgf-banked-regs=8" } */ + +/* Check if R4 to R11 and R16-R27 are correctly saved on stack. */ + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + asm volatile ("" + : + : + : "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "r13", "r14", + "r15", "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", "r24", + "r25", "fp"); +} +/* { dg-final { scan-assembler-not "r0,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "push.*r0" } } */ +/* { dg-final { scan-assembler-not "r1,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r2,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r3,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r12,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r13,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r14,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "r15,\\\[sp" } } */ + +/* { dg-final { scan-assembler-times "r4,\\\[sp" 2 } } */ +/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r10,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r16,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r18,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r20,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r24,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "fp,\\\[sp," 2 } } */ + +/* { dg-final { scan-assembler "rtie" } } */ diff --git a/gcc/testsuite/gcc.target/arc/firq-4.c b/gcc/testsuite/gcc.target/arc/firq-4.c new file mode 100644 index 00000000000..03d3746a500 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-4.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O2 -mll64 -mrgf-banked-regs=16" } */ + +/* Check if R4-R9 and R16-R25 are correctly saved on stack. */ + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + asm volatile ("" + : + : + : "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "r13", "r14", + "r15", "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", "r24", + "r25", "fp"); +} +/* { dg-final { scan-assembler-times "r4,\\\[sp" 2 } } */ +/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */ + +/* { dg-final { scan-assembler-times "r16,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r18,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r20,\\\[sp,\[0-9\]+\\\]" 2 } } */ +/* { dg-final { scan-assembler-times "r24,\\\[sp,\[0-9\]+\\\]" 2 } } */ + +/* { dg-final { scan-assembler-not "fp,\\\[sp" } } */ +/* { dg-final { scan-assembler-not "push.*fp" } } */ +/* { dg-final { scan-assembler "mov_s.*fp,sp" } } */ diff --git a/gcc/testsuite/gcc.target/arc/firq-5.c b/gcc/testsuite/gcc.target/arc/firq-5.c new file mode 100644 index 00000000000..29f17a3f0cc --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O2 -mrgf-banked-regs=16" } */ + +/* Check if blink is pushed on the stack or not. */ + +extern void bar (void); + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + bar (); +} +/* { dg-final { scan-assembler-not "push.*blink" } } */ +/* { dg-final { scan-assembler-not "pop.*blink" } } */ diff --git a/gcc/testsuite/gcc.target/arc/firq-6.c b/gcc/testsuite/gcc.target/arc/firq-6.c new file mode 100644 index 00000000000..9421200d630 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/firq-6.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target archs }*/ +/* { dg-options "-O2 -mll64 -mrgf-banked-regs=32" } */ + +/* Check if we have any register saved on stack. */ + +void __attribute__ ((interrupt("firq"))) +handler1 (void) +{ + asm volatile ("" + : + : + : "r0", "r1", "r2", "r3", "r4", + "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "r13", "r14", + "r15", "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", "r24", + "r25", "fp"); +} +/* { dg-final { scan-assembler-not "(s|l)(t|d)d.*r\[0-9\]+,\\\[sp,\[0-9\]+\\\]" } } */ +/* { dg-final { scan-assembler "mov_s.*fp,sp" } } */