Commit 3bd0817d by Richard Sandiford

mips.c (mips_epilogue): New structure.

gcc/
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.

From-SVN: r178794
parent 42ae51f4
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
......@@ -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 ());
}
/* 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. */
......
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.
......
/* 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 ();
}
/* 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 ();
}
......@@ -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"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment