* Claudiu Zissulescu <claudiu.zissule...@synopsys.com> [2017-05-05 13:02:44 +0200]:
> When a processor enters a fast interrupts handler, and duplicate > register banks are configured, the processor saves the user context by > saving the registers in the main register bank to these additional > registers in the duplicate register bank. In this fast interrupt > context, when you specify the rgf_banked_regs option,the compiler does > not save the registers duplicated in the additional register bank are > not saved. > > gcc/ > 2016-10-04 Claudiu Zissulescu <claz...@synopsys.com> > Andrew Burgess <andrew.burg...@embecosm.com> > > * config/arc/arc.c (ARC_AUTOBLINK_IRQ_P): Consider fast interrupts > case also. > (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. > * testsuite/gcc.target/arc/firq-1.c: New file. > * testsuite/gcc.target/arc/firq-2.c: Likewise. > * testsuite/gcc.target/arc/firq-3.c: Likewise. > * testsuite/gcc.target/arc/firq-4.c: Likewise. > * testsuite/gcc.target/arc/firq-5.c: Likewise. > * testsuite/gcc.target/arc/firq-6.c: Likewise. Looks fine to me, Thanks, Andrew > --- > gcc/config/arc/arc.c | 106 > +++++++++++++++++++++++++++------- > gcc/config/arc/arc.h | 13 +++-- > gcc/config/arc/arc.md | 9 ++- > gcc/config/arc/arc.opt | 4 ++ > gcc/doc/invoke.texi | 10 ++++ > gcc/testsuite/gcc.target/arc/firq-1.c | 27 +++++++++ > gcc/testsuite/gcc.target/arc/firq-2.c | 31 ++++++++++ > gcc/testsuite/gcc.target/arc/firq-3.c | 40 +++++++++++++ > gcc/testsuite/gcc.target/arc/firq-4.c | 31 ++++++++++ > gcc/testsuite/gcc.target/arc/firq-5.c | 15 +++++ > gcc/testsuite/gcc.target/arc/firq-6.c | 21 +++++++ > 11 files changed, 277 insertions(+), 30 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/arc/firq-1.c > create mode 100644 gcc/testsuite/gcc.target/arc/firq-2.c > create mode 100644 gcc/testsuite/gcc.target/arc/firq-3.c > create mode 100644 gcc/testsuite/gcc.target/arc/firq-4.c > create mode 100644 gcc/testsuite/gcc.target/arc/firq-5.c > create mode 100644 gcc/testsuite/gcc.target/arc/firq-6.c > > diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c > index a61faef..a0cd597 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) > - > -#define ARC_AUTOFP_IRQ_P(FNTYPE) \ > - (ARC_INTERRUPT_P (FNTYPE) && (irq_ctrl_saved.irq_save_last_reg > 26)) > - > -#define ARC_AUTO_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)) \ > + || (ARC_FAST_INTERRUPT_P (FNTYPE) \ > + && rgf_banked_register_count > 8)) > + > +#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 5491130..52f121f 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 2221fb5..5c3766c 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 483470d..f01a2ff 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 bd3b339..35c97f0 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 > @@ -14554,6 +14555,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/gcc.target/arc/firq-1.c > b/gcc/testsuite/gcc.target/arc/firq-1.c > new file mode 100644 > index 0000000..87f4087 > --- /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 0000000..dc7dafc > --- /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 0000000..a1d604d > --- /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 0000000..03d3746 > --- /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 0000000..29f17a3 > --- /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 0000000..9421200 > --- /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" } } */ > -- > 1.9.1 >