diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 696e4a0..35c5295 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "rtl-iter.h"
 #include "alias.h"
+#include "opts.h"
 
 /* Which cpu we're compiling for (ARC600, ARC601, ARC700).  */
 static char arc_cpu_name[10] = "";
@@ -111,6 +112,29 @@ struct GTY (()) arc_ccfsm
   int target_label;
 };
 
+/* Status of the IRQ_CTRL_AUX register.  */
+typedef struct irq_ctrl_saved_t
+{
+  short irq_save_last_reg;      /* Last register number used by
+				   IRQ_CTRL_SAVED aux_reg.  */
+  bool  irq_save_blink;         /* True if BLINK is automatically
+				   saved.  */
+  bool  irq_save_lpcount;       /* True if LPCOUNT is automatically
+				   saved.  */
+} 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			\
+       || (irq_ctrl_saved.irq_save_last_reg >= 0)))
+
 #define arc_ccfsm_current cfun->machine->ccfsm_current
 
 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
@@ -809,11 +833,110 @@ arc_init (void)
     }
 }
 
+/* Parse -mirq-ctrl-saved= option string.  Registers may be specified
+   individually, or as ranges such as "r0-r3".  Registers accepted are
+   r0 through r31 and lp_count.  Registers and ranges must be
+   comma-separated.  */
+
+static void
+irq_range (const char *cstr)
+{
+  int i, first, last, blink, lpcount, xreg;
+  char *str, *dash, *comma;
+
+  i = strlen (cstr);
+  str = (char *) alloca (i + 1);
+  memcpy (str, cstr, i + 1);
+  blink = -1;
+  lpcount = -1;
+
+  dash = strchr (str, '-');
+  if (!dash)
+    {
+      warning (0, "value of -mirq-ctrl-saved must have form R0-REGx");
+      return;
+    }
+  *dash = '\0';
+
+  comma = strchr (dash + 1, ',');
+  if (comma)
+    *comma = '\0';
+
+  first = decode_reg_name (str);
+  if (first != 0)
+    {
+      warning (0, "first register must be R0");
+      return;
+    }
+
+  /* At this moment we do not have the register names initialized
+     accordingly.  */
+  if (!strcmp (dash + 1, "ilink"))
+    last = 29;
+  else
+    last = decode_reg_name (dash + 1);
+
+  if (last < 0)
+    {
+      warning (0, "unknown register name: %s", dash + 1);
+      return;
+    }
+
+  if (!(last & 0x01))
+    {
+      warning (0, "last register name %s must be an odd register", dash + 1);
+      return;
+    }
+
+  *dash = '-';
+
+  if (first > last)
+    {
+      warning (0, "%s-%s is an empty range", str, dash + 1);
+      return;
+    }
+
+  while (comma)
+    {
+      *comma = ',';
+      str = comma + 1;
+
+      comma = strchr (str, ',');
+      if (comma)
+	*comma = '\0';
+
+      xreg = decode_reg_name (str);
+      switch (xreg)
+	{
+	case 31:
+	  blink = 31;
+	  break;
+
+	case 60:
+	  lpcount = 60;
+	  break;
+
+	default:
+	  warning (0, "unknown register name: %s", str);
+	  return;
+	}
+    }
+
+  irq_ctrl_saved.irq_save_last_reg = last;
+  irq_ctrl_saved.irq_save_blink    = (blink == 31) || (last == 31);
+  irq_ctrl_saved.irq_save_lpcount  = (lpcount == 60);
+}
+
 /* Check ARC options, generate derived target attributes.  */
 
 static void
 arc_override_options (void)
 {
+  unsigned int i;
+  cl_deferred_option *opt;
+  vec<cl_deferred_option> *vopt
+    = (vec<cl_deferred_option> *) arc_deferred_options;
+
   if (arc_cpu == PROCESSOR_NONE)
     arc_cpu = TARGET_CPU_DEFAULT;
 
@@ -842,6 +965,28 @@ arc_override_options (void)
       gcc_unreachable ();
     }
 
+  irq_ctrl_saved.irq_save_last_reg = -1;
+  irq_ctrl_saved.irq_save_blink    = false;
+  irq_ctrl_saved.irq_save_lpcount  = false;
+
+  /* Handle the deferred options.  */
+  if (vopt)
+    FOR_EACH_VEC_ELT (*vopt, i, opt)
+      {
+	switch (opt->opt_index)
+	  {
+	  case OPT_mirq_ctrl_saved_:
+	    if (TARGET_V2)
+	      irq_range (opt->arg);
+	    else
+	      warning (0, "option -mirq-ctrl-saved valid only for ARC v2 processors");
+	    break;
+
+	  default:
+	    gcc_unreachable();
+	  }
+      }
+
   /* Set cpu flags accordingly to architecture/selected cpu.  The cpu
      specific flags are set in arc-common.c.  The architecture forces
      the default hardware configurations in, regardless what command
@@ -2254,15 +2399,43 @@ arc_compute_function_type (struct function *fun)
    code like this.  The number of frames that use __builtin_eh_return
    is pretty low, so optimising them is not critical right now.  */
 
-#define MUST_SAVE_REGISTER(regno, interrupt_p)				\
-  (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM	\
-    && (df_regs_ever_live_p (regno)					\
-	&& (!call_used_regs[regno] || interrupt_p)))			\
-   || (flag_pic && crtl->uses_pic_offset_table				\
-       && regno == PIC_OFFSET_TABLE_REGNUM)				\
-   || (crtl->calls_eh_return && (regno > 2 && regno < 27)))
+static bool
+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));
+
+  if ((regno) != RETURN_ADDR_REGNUM
+      && (regno) != FRAME_POINTER_REGNUM
+      && df_regs_ever_live_p (regno)
+      && (!call_used_regs[regno]
+	  || ARC_INTERRUPT_P (fn_type))
+      /* Do not emit code for auto saved regs.  */
+      && !irq_auto_save_p)
+    return true;
+
+  if (flag_pic && crtl->uses_pic_offset_table
+      && regno == PIC_OFFSET_TABLE_REGNUM)
+    return true;
+
+  if (crtl->calls_eh_return && (regno > 2 && regno < 27))
+    return true;
+
+  return false;
+}
+
+/* Return true if the return address must be saved in the current function,
+   otherwise return false.  */
+
+static bool
+arc_must_save_return_addr (struct function *func)
+{
+  if (func->machine->frame_info.save_return_addr)
+    return true;
 
-#define MUST_SAVE_RETURN_ADDR	(cfun->machine->frame_info.save_return_addr)
+  return false;
+}
 
 /* Helper function to wrap FRAME_POINTER_NEEDED.  We do this as
    FRAME_POINTER_NEEDED will not be true until the IRA (Integrated
@@ -2280,9 +2453,9 @@ arc_compute_function_type (struct function *fun)
 
    As the frame pointer is handled as a special case in our prologue
    and epilogue code it must not be saved and restored using the
-   MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC
-   believes that the function is not using a frame pointer and that
-   the value in the fp register is the frame pointer, while the
+   arc_must_save_register mechanism otherwise we run into issues where
+   GCC believes that the function is not using a frame pointer and
+   that the value in the fp register is the frame pointer, while the
    prologue and epilogue are busy saving and restoring the fp
    register.  This issue is fixed in this commit too.
 
@@ -2352,8 +2525,6 @@ arc_compute_frame_size (void)
   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
   unsigned int reg_size, reg_offset;
   unsigned int gmask;
-  enum arc_function_type fn_type;
-  int interrupt_p;
   struct arc_frame_info *frame_info;
   int size;
 
@@ -2378,15 +2549,13 @@ arc_compute_frame_size (void)
 
   reg_size = 0;
   gmask = 0;
-  fn_type = arc_compute_function_type (cfun);
-  interrupt_p = ARC_INTERRUPT_P (fn_type);
 
   for (regno = 0; regno <= 31; regno++)
     {
-      if (MUST_SAVE_REGISTER (regno, interrupt_p))
+      if (arc_must_save_register (regno, cfun))
 	{
 	  reg_size += UNITS_PER_WORD;
-	  gmask |= 1 << regno;
+	  gmask |= 1L << regno;
 	}
     }
 
@@ -2419,7 +2588,7 @@ arc_compute_frame_size (void)
     }
 
   extra_size = 0;
-  if (MUST_SAVE_RETURN_ADDR)
+  if (arc_must_save_return_addr (cfun))
     extra_size = 4;
   if (arc_frame_pointer_needed ())
     extra_size += 4;
@@ -2641,6 +2810,77 @@ arc_save_restore (rtx base_reg,
 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.  */
+
+static void
+arc_dwarf_emit_irq_save_regs (void)
+{
+  rtx tmp, par, insn, reg;
+  int i, offset, j;
+
+  par = gen_rtx_SEQUENCE (VOIDmode,
+			  rtvec_alloc (irq_ctrl_saved.irq_save_last_reg + 1
+				       + irq_ctrl_saved.irq_save_blink
+				       + irq_ctrl_saved.irq_save_lpcount
+				       + 1));
+
+  /* Build the stack adjustment note for unwind info.  */
+  j = 0;
+  offset = UNITS_PER_WORD * (irq_ctrl_saved.irq_save_last_reg + 1
+			     + irq_ctrl_saved.irq_save_blink
+			     + irq_ctrl_saved.irq_save_lpcount);
+  tmp = plus_constant (Pmode, stack_pointer_rtx, -1 * offset);
+  tmp = gen_rtx_SET (stack_pointer_rtx, tmp);
+  RTX_FRAME_RELATED_P (tmp) = 1;
+  XVECEXP (par, 0, j++) = tmp;
+
+  offset -= UNITS_PER_WORD;
+
+  /* 1st goes LP_COUNT.  */
+  if (irq_ctrl_saved.irq_save_lpcount)
+    {
+      reg = gen_rtx_REG (SImode, 60);
+      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
+      tmp = gen_frame_mem (SImode, tmp);
+      tmp = gen_rtx_SET (tmp, reg);
+      RTX_FRAME_RELATED_P (tmp) = 1;
+      XVECEXP (par, 0, j++) = tmp;
+      offset -= UNITS_PER_WORD;
+    }
+
+  /* 2nd goes BLINK.  */
+  if (irq_ctrl_saved.irq_save_blink)
+    {
+      reg = gen_rtx_REG (SImode, 31);
+      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
+      tmp = gen_frame_mem (SImode, tmp);
+      tmp = gen_rtx_SET (tmp, reg);
+      RTX_FRAME_RELATED_P (tmp) = 1;
+      XVECEXP (par, 0, j++) = tmp;
+      offset -= UNITS_PER_WORD;
+    }
+
+  /* Build the parallel of the remaining registers recorded as saved
+     for unwind.  */
+  for (i = irq_ctrl_saved.irq_save_last_reg; i >= 0; i--)
+    {
+      reg = gen_rtx_REG (SImode, i);
+      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
+      tmp = gen_frame_mem (SImode, tmp);
+      tmp = gen_rtx_SET (tmp, reg);
+      RTX_FRAME_RELATED_P (tmp) = 1;
+      XVECEXP (par, 0, j++) = tmp;
+      offset -= UNITS_PER_WORD;
+    }
+
+  /* Dummy insn used to anchor the dwarf info.  */
+  insn = emit_insn (gen_stack_irq_dwarf());
+  add_reg_note (insn, REG_FRAME_RELATED_EXPR, par);
+  RTX_FRAME_RELATED_P (insn) = 1;
+}
+
 /* Set up the stack and frame pointer (if desired) for the function.  */
 
 void
@@ -2654,6 +2894,7 @@ arc_expand_prologue (void)
      Change the stack layout so that we rather store a high register with the
      PRE_MODIFY, thus enabling more short insn generation.)  */
   int first_offset = 0;
+  enum arc_function_type fn_type = arc_compute_function_type (cfun);
 
   /* Compute total frame size.  */
   size = arc_compute_frame_size ();
@@ -2677,30 +2918,41 @@ arc_expand_prologue (void)
       frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
     }
 
+  /* IRQ using automatic save mechanism will save the register before
+     anything we do.  */
+  if (ARC_AUTO_IRQ_P (fn_type))
+    {
+      arc_dwarf_emit_irq_save_regs ();
+    }
+
   /* The home-grown ABI says link register is saved first.  */
-  if (MUST_SAVE_RETURN_ADDR)
+  if (arc_must_save_return_addr (cfun)
+      && !ARC_AUTOBLINK_IRQ_P (fn_type))
     {
       rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
-      rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
+      rtx mem = gen_frame_mem (Pmode,
+			       gen_rtx_PRE_DEC (Pmode,
+						stack_pointer_rtx));
 
       frame_move_inc (mem, ra, stack_pointer_rtx, 0);
       frame_size_to_allocate -= UNITS_PER_WORD;
-
-    } /* MUST_SAVE_RETURN_ADDR */
+    }
 
   /* Save any needed call-saved regs (and call-used if this is an
      interrupt handler) for ARCompact ISA.  */
   if (cfun->machine->frame_info.reg_size)
     {
       first_offset = -cfun->machine->frame_info.reg_size;
+
       /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask.  */
       arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
       frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
     }
 
-
-  /* Save frame pointer if needed.  */
-  if (arc_frame_pointer_needed ())
+  /* Save frame pointer if needed.  First save the FP on stack, if not
+     autosaved.  */
+  if (arc_frame_pointer_needed ()
+      && !ARC_AUTOFP_IRQ_P (fn_type))
     {
       rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
 			       GEN_INT (-UNITS_PER_WORD + first_offset));
@@ -2710,6 +2962,11 @@ arc_expand_prologue (void)
       frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
       frame_size_to_allocate -= UNITS_PER_WORD;
       first_offset = 0;
+    }
+
+  /* Emit mov fp,sp.  */
+  if (arc_frame_pointer_needed ())
+    {
       frame_move (frame_pointer_rtx, stack_pointer_rtx);
     }
 
@@ -2778,7 +3035,8 @@ arc_expand_epilogue (int sibcall_p)
 
 
   /* Restore any saved registers.  */
-  if (arc_frame_pointer_needed ())
+  if (arc_frame_pointer_needed ()
+      && !ARC_AUTOFP_IRQ_P (fn_type))
     {
       rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
 
@@ -2816,14 +3074,15 @@ arc_expand_epilogue (int sibcall_p)
 	    : satisfies_constraint_C2a (GEN_INT (first_offset))))
        /* Also do this if we have both gprs and return
 	  address to restore, and they both would need a LIMM.  */
-       || (MUST_SAVE_RETURN_ADDR
-	   && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
-	   && cfun->machine->frame_info.gmask))
+      || (arc_must_save_return_addr (cfun)
+	  && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
+	  && cfun->machine->frame_info.gmask))
     {
       frame_stack_add (first_offset);
       first_offset = 0;
     }
-  if (MUST_SAVE_RETURN_ADDR)
+  if (arc_must_save_return_addr (cfun)
+      && !ARC_AUTOBLINK_IRQ_P (fn_type))
     {
       rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
       int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
@@ -2888,7 +3147,6 @@ arc_expand_epilogue (int sibcall_p)
 			   & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
     }
 
-
   /* The rest of this function does the following:
      ARCompact    : handle epilogue_delay, restore sp (phase-2), return
   */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 42ea9a7..0f03170 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -6208,6 +6208,14 @@
   [(set (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 2))
 	(zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)))])
 
+;; Dummy pattern used as a place holder for automatically saved
+;; registers.
+(define_insn "stack_irq_dwarf"
+  [(unspec_volatile [(const_int 1)] VUNSPEC_ARC_STACK_IRQ)]
+  ""
+  ""
+  [(set_attr "length" "0")])
+
 ;; include the arc-FPX instructions
 (include "fpx.md")
 
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
index 6060ded..483470d 100644
--- a/gcc/config/arc/arc.opt
+++ b/gcc/config/arc/arc.opt
@@ -486,3 +486,7 @@ Enable use of NPS400 xld/xst extension.
 munaligned-access
 Target Report Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
 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.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0eeea7b..cebafe6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -606,7 +606,7 @@ Objective-C and Objective-C++ Dialects}.
 -mnorm  -mspfp  -mspfp-compact  -mspfp-fast  -msimd  -msoft-float  -mswap @gol
 -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 @gol
+-mlong-calls  -mmedium-calls  -msdata -mirq-ctrl-saved @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
@@ -14578,6 +14578,15 @@ hardware extensions.  Not available for ARC EM@.
 
 @end table
 
+@item -mirq-ctrl-saved="REGS"
+@opindex mirq-ctrl-saved
+Specifies gneral-purposes registers that the processor saves/restores
+on interrupt entry and exit.  Permited values: r0-r29, fp, blink, and
+lp_count.  Registers needs to be specified as ranges such as "r0-r3".
+A register range always starts with r0.  Registers blink and lp_count
+can be specified individually.  Only valid for ARC EM and ARC HS
+cores.
+
 @end table
 
 The following options are passed through to the assembler, and also
diff --git a/gcc/testsuite/gcc.target/arc/interrupt-5.c b/gcc/testsuite/gcc.target/arc/interrupt-5.c
new file mode 100644
index 0000000..ee01d76
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/interrupt-5.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "Not available for ARCv1" { arc700 ||  arc6xx } } */
+/* { dg-options "-O2 -mirq-ctrl-saved=r0-r3,blink" } */
+
+/* Check if the registers R0-R3,blink are automatically saved. */
+
+extern int bar (void *);
+
+void  __attribute__ ((interrupt("ilink")))
+foo(void)
+{
+  bar (0);
+  __asm__ volatile ( "" : : : "r0","r1","r2","r3");
+}
+/* { dg-final { scan-assembler-not "st.*r0,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r1,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r2,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r3,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "push_s blink" } } */
diff --git a/gcc/testsuite/gcc.target/arc/interrupt-6.c b/gcc/testsuite/gcc.target/arc/interrupt-6.c
new file mode 100644
index 0000000..509ff30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/interrupt-6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-skip-if "Not available for ARCv1" { arc700 || arc6xx } } */
+/* { dg-options "-O2 -mirq-ctrl-saved=r0-ilink" } */
+
+#include <alloca.h>
+
+/* Check if ilink is recognized. Check how FP and BLINK are saved.
+   BLINK is saved last on the stack because the IRQ autosave will do
+   first r0-ilink.  To avoid this ABI exception, one needs to autosave
+   always blink when using the IRQ autosave feature.  */
+
+extern int bar (void *);
+
+void  __attribute__ ((interrupt("ilink")))
+foo(void)
+{
+  int *p = alloca (10);
+  bar (p);
+}
+/* { dg-final { scan-assembler-not ".*fp,\\\[sp" } } */
+/* { dg-final { scan-assembler "ld.*blink,\\\[sp\\\]" } } */
+/* { dg-final { scan-assembler "push_s.*blink" } } */
diff --git a/gcc/testsuite/gcc.target/arc/interrupt-7.c b/gcc/testsuite/gcc.target/arc/interrupt-7.c
new file mode 100644
index 0000000..547dfd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/interrupt-7.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "Not available for ARCv1" { arc700 ||  arc6xx } } */
+/* { dg-options "-O2 -mirq-ctrl-saved=r0-r17,blink" } */
+
+/* Check if the registers R0-R17,blink are automatically saved. */
+
+void  __attribute__ ((interrupt("ilink")))
+foo(void)
+{
+  __asm__ volatile ( "" : : : "r13","r14","r15","r16");
+}
+/* { dg-final { scan-assembler-not "st.*r13,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r14,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r15,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r16,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "push_s blink" } } */
diff --git a/gcc/testsuite/gcc.target/arc/interrupt-8.c b/gcc/testsuite/gcc.target/arc/interrupt-8.c
new file mode 100644
index 0000000..60fd87b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/interrupt-8.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-skip-if "Not available for ARCv1" { arc700 || arc6xx } } */
+/* { dg-options "-O2 -mirq-ctrl-saved=r0-r17" } */
+
+/* Check if the registers R0-R17 are automatically saved.  GP is saved
+   by the compiler.  */
+
+int a;
+
+void  __attribute__ ((interrupt("ilink")))
+foo(void)
+{
+  __asm__ volatile ( "" : : : "r0","r1","r2","r3");
+  __asm__ volatile ( "" : : : "r13","r14","r15","r16");
+  a++;
+}
+/* { dg-final { scan-assembler-not "st.*r13,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r14,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r15,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r16,\\\[sp" } } */
+/* { dg-final { scan-assembler "st.*gp,\\\[sp,-4\\\]" } } */
+/* { dg-final { scan-assembler "ld.*gp,\\\[sp\\\]" } } */
+/* { dg-final { scan-assembler-not "st.*r0,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r1,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r2,\\\[sp" } } */
+/* { dg-final { scan-assembler-not "st.*r3,\\\[sp" } } */
+/* { dg-final { scan-assembler "rtie" } } */
diff --git a/gcc/testsuite/gcc.target/arc/interrupt-9.c b/gcc/testsuite/gcc.target/arc/interrupt-9.c
new file mode 100644
index 0000000..4547fef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/interrupt-9.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target archs }*/
+/* { dg-options "-O0 -mirq-ctrl-saved=r0-fp" } */
+
+/* Check if we get the move operation between fp and sp.  */
+
+void __attribute__ ((interrupt("ilink")))
+handler1 (void)
+{
+  asm (""
+       :
+       :
+       : "r0", "r1", "r2", "r3", "r4",
+         "r5", "r6", "r7", "r8", "r9");
+}
+/* { dg-final { scan-assembler "mov.*fp,sp" } } */
+/* { dg-final { scan-assembler-not ".*fp,\\\[sp" } } */
