OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Sep 2011 19:25:59 +0000 (19:25 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Sep 2011 19:25:59 +0000 (19:25 +0000)
2011-09-11  Bernd Schmidt  <bernds@codesourcery.com>
    Richard Sandiford  <rdsandiford@googlemail.com>

* config/mips/mips.c (mips_epilogue): New structure.
(mips16e_save_restore_reg): Queue REG_CFA_RESTORE notes when
restoring registers.
(mips_epilogue_emit_cfa_restores): New function.
(mips_epilogue_set_cfa): Likewise.
(mips_restore_reg): Queue REG_CFA_RESTORE notes.  When restoring
the current CFA register from the stack, redefine the CFA in terms
of the stack pointer.
(mips_expand_epilogue): Set up mips_epilogue.  Attach CFA information
to the epilogue instructions.

gcc/testsuite/
* gcc.target/mips/mips.exp (mips_option_groups): Add debug options.
* gcc.target/mips/interrupt_handler-2.c: New test.
* gcc.target/mips/interrupt_handler-3.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178794 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/interrupt_handler-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/interrupt_handler-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mips.exp

index 29c86fb..48b4af7 100644 (file)
@@ -1,3 +1,17 @@
+2011-09-12  Bernd Schmidt  <bernds@codesourcery.com>
+           Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * config/mips/mips.c (mips_epilogue): New structure.
+       (mips16e_save_restore_reg): Queue REG_CFA_RESTORE notes when
+       restoring registers.
+       (mips_epilogue_emit_cfa_restores): New function.
+       (mips_epilogue_set_cfa): Likewise.
+       (mips_restore_reg): Queue REG_CFA_RESTORE notes.  When restoring
+       the current CFA register from the stack, redefine the CFA in terms
+       of the stack pointer.
+       (mips_expand_epilogue): Set up mips_epilogue.  Attach CFA information
+       to the epilogue instructions.
+
 2011-09-12  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * config/mips/mips.c (mips16e_save_restore_reg): Add a reg_parm_p
index a5fed3d..0c3b184 100644 (file)
@@ -501,6 +501,21 @@ int sdb_label_count;
 int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
 int mips_dwarf_regno[FIRST_PSEUDO_REGISTER];
 
+/* Information about the current function's epilogue, used only while
+   expanding it.  */
+static struct {
+  /* A list of queued REG_CFA_RESTORE notes.  */
+  rtx cfa_restores;
+
+  /* The CFA is currently defined as CFA_REG + CFA_OFFSET.  */
+  rtx cfa_reg;
+  HOST_WIDE_INT cfa_offset;
+
+  /* The offset of the CFA from the stack pointer while restoring
+     registers.  */
+  HOST_WIDE_INT cfa_restore_sp_offset;
+} mips_epilogue;
+
 /* The nesting depth of the PRINT_OPERAND '%(', '%<' and '%[' constructs.  */
 struct mips_asm_switch mips_noreorder = { "reorder", 0 };
 struct mips_asm_switch mips_nomacro = { "macro", 0 };
@@ -8377,7 +8392,11 @@ mips16e_save_restore_reg (bool restore_p, bool reg_parm_p,
   mem = gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, offset));
   reg = gen_rtx_REG (SImode, regno);
   if (restore_p)
-    return gen_rtx_SET (VOIDmode, reg, mem);
+    {
+      mips_epilogue.cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+                                                  mips_epilogue.cfa_restores);
+      return gen_rtx_SET (VOIDmode, reg, mem);
+    }
   if (reg_parm_p)
     return gen_rtx_SET (VOIDmode, mem, reg);
   return mips_frame_set (mem, reg);
@@ -10222,7 +10241,47 @@ mips_expand_prologue (void)
     emit_insn (gen_blockage ());
 }
 \f
-/* Emit instructions to restore register REG from slot MEM.  */
+/* Attach all pending register saves to the previous instruction.
+   Return that instruction.  */
+
+static rtx
+mips_epilogue_emit_cfa_restores (void)
+{
+  rtx insn;
+
+  insn = get_last_insn ();
+  gcc_assert (insn && !REG_NOTES (insn));
+  if (mips_epilogue.cfa_restores)
+    {
+      RTX_FRAME_RELATED_P (insn) = 1;
+      REG_NOTES (insn) = mips_epilogue.cfa_restores;
+      mips_epilogue.cfa_restores = 0;
+    }
+  return insn;
+}
+
+/* Like mips_epilogue_emit_cfa_restores, but also record that the CFA is
+   now at REG + OFFSET.  */
+
+static void
+mips_epilogue_set_cfa (rtx reg, HOST_WIDE_INT offset)
+{
+  rtx insn;
+
+  insn = mips_epilogue_emit_cfa_restores ();
+  if (reg != mips_epilogue.cfa_reg || offset != mips_epilogue.cfa_offset)
+    {
+      RTX_FRAME_RELATED_P (insn) = 1;
+      REG_NOTES (insn) = alloc_reg_note (REG_CFA_DEF_CFA,
+                                        plus_constant (reg, offset),
+                                        REG_NOTES (insn));
+      mips_epilogue.cfa_reg = reg;
+      mips_epilogue.cfa_offset = offset;
+    }
+}
+
+/* Emit instructions to restore register REG from slot MEM.  Also update
+   the cfa_restores list.  */
 
 static void
 mips_restore_reg (rtx reg, rtx mem)
@@ -10231,8 +10290,17 @@ mips_restore_reg (rtx reg, rtx mem)
      $7 instead and adjust the return insn appropriately.  */
   if (TARGET_MIPS16 && REGNO (reg) == RETURN_ADDR_REGNUM)
     reg = gen_rtx_REG (GET_MODE (reg), GP_REG_FIRST + 7);
+  else
+    mips_epilogue.cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+                                                mips_epilogue.cfa_restores);
 
   mips_emit_save_slot_move (reg, mem, MIPS_EPILOGUE_TEMP (GET_MODE (reg)));
+  if (REGNO (reg) == REGNO (mips_epilogue.cfa_reg))
+    /* The CFA is currently defined in terms of the register whose
+       value we have just restored.  Redefine the CFA in terms of
+       the stack pointer.  */
+    mips_epilogue_set_cfa (stack_pointer_rtx,
+                          mips_epilogue.cfa_restore_sp_offset);
 }
 
 /* Emit any instructions needed before a return.  */
@@ -10291,6 +10359,9 @@ mips_expand_epilogue (bool sibcall_p)
       base = hard_frame_pointer_rtx;
       step1 -= frame->hard_frame_pointer_offset;
     }
+  mips_epilogue.cfa_reg = base;
+  mips_epilogue.cfa_offset = step1;
+  mips_epilogue.cfa_restores = NULL_RTX;
 
   /* If we need to restore registers, deallocate as much stack as
      possible in the second step without going out of range.  */
@@ -10320,6 +10391,7 @@ mips_expand_epilogue (bool sibcall_p)
        target = stack_pointer_rtx;
 
       emit_insn (gen_add3_insn (target, base, adjust));
+      mips_epilogue_set_cfa (target, step2);
     }
 
   /* Copy TARGET into the stack pointer.  */
@@ -10332,6 +10404,7 @@ mips_expand_epilogue (bool sibcall_p)
   if (TARGET_CALL_SAVED_GP && !TARGET_EXPLICIT_RELOCS)
     emit_insn (gen_blockage ());
 
+  mips_epilogue.cfa_restore_sp_offset = step2;
   if (GENERATE_MIPS16E_SAVE_RESTORE && frame->mask != 0)
     {
       unsigned int regno, mask;
@@ -10353,6 +10426,7 @@ mips_expand_epilogue (bool sibcall_p)
       /* Restore the remaining registers and deallocate the final bit
         of the frame.  */
       emit_insn (restore);
+      mips_epilogue_set_cfa (stack_pointer_rtx, 0);
     }
   else
     {
@@ -10388,9 +10462,15 @@ mips_expand_epilogue (bool sibcall_p)
 
          /* If we don't use shoadow register set, we need to update SP.  */
          if (!cfun->machine->use_shadow_register_set_p && step2 > 0)
-           emit_insn (gen_add3_insn (stack_pointer_rtx,
-                                     stack_pointer_rtx,
-                                     GEN_INT (step2)));
+           {
+             emit_insn (gen_add3_insn (stack_pointer_rtx,
+                                       stack_pointer_rtx,
+                                       GEN_INT (step2)));
+             mips_epilogue_set_cfa (stack_pointer_rtx, 0);
+           }
+         else
+           /* The choice of position is somewhat arbitrary in this case.  */
+           mips_epilogue_emit_cfa_restores ();
 
          /* Move to COP0 Status.  */
          emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
@@ -10400,11 +10480,15 @@ mips_expand_epilogue (bool sibcall_p)
        {
          /* Deallocate the final bit of the frame.  */
          if (step2 > 0)
-           emit_insn (gen_add3_insn (stack_pointer_rtx,
-                                     stack_pointer_rtx,
-                                     GEN_INT (step2)));
+           {
+             emit_insn (gen_add3_insn (stack_pointer_rtx,
+                                       stack_pointer_rtx,
+                                       GEN_INT (step2)));
+             mips_epilogue_set_cfa (stack_pointer_rtx, 0);
+           }
        }
     }
+  gcc_assert (!mips_epilogue.cfa_restores);
 
   /* Add in the __builtin_eh_return stack adjustment.  We need to
      use a temporary in MIPS16 code.  */
index dde09f5..eea712e 100644 (file)
@@ -1,3 +1,9 @@
+2011-09-12  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gcc.target/mips/mips.exp (mips_option_groups): Add debug options.
+       * gcc.target/mips/interrupt_handler-2.c: New test.
+       * gcc.target/mips/interrupt_handler-3.c: Likewise.
+
 2011-09-12  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/fntmpdefarg2.C: Add more tests.
diff --git a/gcc/testsuite/gcc.target/mips/interrupt_handler-2.c b/gcc/testsuite/gcc.target/mips/interrupt_handler-2.c
new file mode 100644 (file)
index 0000000..13b41e1
--- /dev/null
@@ -0,0 +1,14 @@
+/* Make sure that we emit .cfa_restore notes for LO and HI.  */
+/* { dg-options "-mips32r2 -msoft-float -O -g" } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 64\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 65\n" } } */
+/* { dg-final { scan-assembler-not "\\\.cfi_def_cfa( |\t)" } } */
+/* { dg-final { scan-assembler-not "\\\.cfi_def_cfa_register( |\t)" } } */
+
+extern void f (void);
+
+NOMIPS16 void __attribute__ ((interrupt, use_shadow_register_set))
+v1 (void)
+{
+  f ();
+}
diff --git a/gcc/testsuite/gcc.target/mips/interrupt_handler-3.c b/gcc/testsuite/gcc.target/mips/interrupt_handler-3.c
new file mode 100644 (file)
index 0000000..2380123
--- /dev/null
@@ -0,0 +1,33 @@
+/* Make sure that we emit .cfa_restore notes for LO, HI and GPRs.  */
+/* { dg-options "-mips32r2 -msoft-float -O -g" } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 1\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 2\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 3\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 4\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 5\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 6\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 7\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 8\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 9\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 10\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 11\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 12\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 13\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 14\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 15\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 24\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 25\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 31\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 64\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_restore 65\n" } } */
+/* { dg-final { scan-assembler "\t\\\.cfi_def_cfa_offset 0\n" } } */
+/* { dg-final { scan-assembler-not "\\\.cfi_def_cfa( |\t)" } } */
+/* { dg-final { scan-assembler-not "\\\.cfi_def_cfa_register( |\t)" } } */
+
+extern void f (void);
+
+NOMIPS16 void __attribute__ ((interrupt))
+v1 (void)
+{
+  f ();
+}
index 5889902..857cfe8 100644 (file)
@@ -226,6 +226,7 @@ set mips_option_groups {
     abi "-mabi=.*"
     addressing "addressing=.*"
     arch "-mips([1-5]|32.*|64.*)|-march=.*|isa(|_rev)(=|<=|>=).*"
+    debug "-g*"
     dump_pattern "-dp"
     endianness "-E(L|B)|-me(l|b)"
     float "-m(hard|soft)-float"