Commit a6ab9fc0 by J"orn Rennecke Committed by Joern Rennecke

re PR target/14798 (In case of SH target with -O2 option #pragma interrupt doesn't get resetted.)

PR target/14798:

gcc:
	* sh.c (pragma_interrupt, trap_exit, sp_switch): Remove variable.
	(pragma_trap, pragma_nosave_low_regs): Likewise.
	(current_function_anonymous_args): Likewise.
	(sh_deferred_function_attributes): New variable.
	(sh_deferred_function_attributes_tail): Likewise.
	(print_operand): For '@', look up trap_exit attribute.
	(calc_live_regs): Look up trapa_handler attribute.  For trapa
	handlers, save/restore fpscr, but don't do any other
	interrupt-specific saves.
	Don't save r0..r7 if the nosave_low_regs attribute is in effect.
	Fix check for partially saved registers to check for SHmedia.
	(sh_expand_prologue, sh_expand_epilogue): Look up sp_switch attribute.
	(sh_output_function_epilogue): Don't clear any of the removed
	variables.
	(sh_insert_attributes): Don't check pragma_interrupt.
	Insert deferred attributes.  Check that interrupt attribute is
	present for other attributes that require its presence.
	(sh_attribute_table): Add new attributes trapa_handler and
	nosave_low_regs.
	(sh_handle_sp_switch_attribute, sh_handle_trap_exit_attribute):
	Don't check for pragma_interrupt.  Don't store argument.
	* sh.h (pragma_interrupt, sp_switch): Don't declare.
	(sh_deferred_function_attributes): Declare.
	(sh_deferred_function_attributes_tail): Likewise.
	* sh.md (sp_switch_1): Add operand.  Change generator caller.
	(sh_pr_interrupt, sh_pr_trapa, sh_pr_nosave_low_regs): Remove.
	(*return_i): Don't use when trap_exit attribute is in effect.
	(*return_trapa): New insn pattern.
	* sh-c.c: New file.
	* config.gcc (sh[123456ble]*-* | sh-*-*): New trailer stanza,
	setting c_target_objs and cxx_target_objs.
	* t-sh: Add rule for sh-c.o.
gcc/testsuite:
	* gcc.dg/pragma-isr.c: Added target sh[1234ble]*-*-*.
	* gcc.dg/pragma-isr2.c, gcc.dg/pragma-isr-trapa.c: New tests.
	* gcc.dg/pragma-isr-trapa2.c: Likewise.
	* gcc.dg/pragma-isr-nosave_low_regs.c: Likewise.
	* gcc.dg/pragma-isr-trap_exit.c: Likewise.
	* gcc.dg/attr-isr.c, gcc.dg/attr-isr-trapa.c: Likewise.
	* gcc.dg/attr-isr-trap_exit.c: Likewise.
	* gcc.dg/attr-isr-nosave_low_regs.c: Likewise.

From-SVN: r110398
parent 52a64bd3
2006-01-30 J"orn Rennecke <joern.rennecke@st.com>
PR target/14798:
* sh.c (pragma_interrupt, trap_exit, sp_switch): Remove variable.
(pragma_trap, pragma_nosave_low_regs): Likewise.
(current_function_anonymous_args): Likewise.
(sh_deferred_function_attributes): New variable.
(sh_deferred_function_attributes_tail): Likewise.
(print_operand): For '@', look up trap_exit attribute.
(calc_live_regs): Look up trapa_handler attribute. For trapa
handlers, save/restore fpscr, but don't do any other
interrupt-specific saves.
Don't save r0..r7 if the nosave_low_regs attribute is in effect.
Fix check for partially saved registers to check for SHmedia.
(sh_expand_prologue, sh_expand_epilogue): Look up sp_switch attribute.
(sh_output_function_epilogue): Don't clear any of the removed
variables.
(sh_insert_attributes): Don't check pragma_interrupt.
Insert deferred attributes. Check that interrupt attribute is
present for other attributes that require its presence.
(sh_attribute_table): Add new attributes trapa_handler and
nosave_low_regs.
(sh_handle_sp_switch_attribute, sh_handle_trap_exit_attribute):
Don't check for pragma_interrupt. Don't store argument.
* sh.h (pragma_interrupt, sp_switch): Don't declare.
(sh_deferred_function_attributes): Declare.
(sh_deferred_function_attributes_tail): Likewise.
* sh.md (sp_switch_1): Add operand. Change generator caller.
(sh_pr_interrupt, sh_pr_trapa, sh_pr_nosave_low_regs): Remove.
(*return_i): Don't use when trap_exit attribute is in effect.
(*return_trapa): New insn pattern.
* sh-c.c: New file.
* config.gcc (sh[123456ble]*-* | sh-*-*): New trailer stanza,
setting c_target_objs and cxx_target_objs.
* t-sh: Add rule for sh-c.o.
2006-01-30 Richard Guenther <rguenther@suse.de>
PR c++/23372
......
......@@ -2938,6 +2938,11 @@ case ${target} in
fi
;;
sh[123456ble]*-*-* | sh-*-*)
c_target_objs="${c_target_objs} sh-c.o"
cxx_target_objs="${cxx_target_objs} sh-c.o"
;;
sparc*-*-*)
# Some standard aliases.
case x$with_cpu in
......
/* Pragma handling for GCC for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Joern Rennecke <joern.rennecke@st.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "tm_p.h"
/* Handle machine specific pragmas to be semi-compatible with Renesas
compiler. */
/* Add ATTR to the attributes of the current function. If there is no
such function, save it to be added to the attributes of the next
function. */
static void
sh_add_function_attribute (const char *attr)
{
tree id = get_identifier (attr);
if (current_function_decl)
decl_attributes (&current_function_decl,
tree_cons (id, NULL_TREE, NULL_TREE), 0);
else
{
*sh_deferred_function_attributes_tail
= tree_cons (id, NULL_TREE, *sh_deferred_function_attributes_tail);
sh_deferred_function_attributes_tail
= &TREE_CHAIN (*sh_deferred_function_attributes_tail);
}
}
void
sh_pr_interrupt (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
{
sh_add_function_attribute ("interrupt_handler");
}
void
sh_pr_trapa (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
{
sh_add_function_attribute ("trapa_handler");
}
void
sh_pr_nosave_low_regs (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
{
sh_add_function_attribute ("nosave_low_regs");
}
......@@ -3277,18 +3277,13 @@ extern enum mdep_reorg_phase_e mdep_reorg_phase;
c_register_pragma (0, "nosave_low_regs", sh_pr_nosave_low_regs); \
} while (0)
/* Set when processing a function with pragma interrupt turned on. */
extern int pragma_interrupt;
extern tree sh_deferred_function_attributes;
extern tree *sh_deferred_function_attributes_tail;
/* Set when processing a function with interrupt attribute. */
extern int current_function_interrupt;
/* Set to an RTX containing the address of the stack to switch to
for interrupt functions. */
extern struct rtx_def *sp_switch;
/* Instructions with unfilled delay slots take up an
extra two bytes for the nop in the delay slot.
......
......@@ -8781,11 +8781,21 @@ mov.l\\t1f,r0\\n\\
"TARGET_SH1 && ! (TARGET_SHCOMPACT
&& (current_function_args_info.call_cookie
& CALL_COOKIE_RET_TRAMP (1)))
&& reload_completed"
&& reload_completed
&& lookup_attribute (\"trap_exit\",
DECL_ATTRIBUTES (current_function_decl)) == NULL_TREE"
"%@ %#"
[(set_attr "type" "return")
(set_attr "needs_delay_slot" "yes")])
;; trapa has no delay slot.
(define_insn "*return_trapa"
[(return)]
"TARGET_SH1 && !TARGET_SHCOMPACT
&& reload_completed"
"%@"
[(set_attr "type" "return")])
(define_expand "shcompact_return_tramp"
[(return)]
"TARGET_SHCOMPACT
......@@ -11209,15 +11219,12 @@ mov.l\\t1f,r0\\n\\
;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */
(define_insn "sp_switch_1"
[(const_int 1)]
[(const_int 1) (match_operand:SI 0 "symbol_ref_operand" "s")]
"TARGET_SH1"
"*
{
rtx xoperands[1];
xoperands[0] = sp_switch;
output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", operands);
output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", operands);
return \"mov r0,r15\";
}"
[(set_attr "length" "10")])
......
sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/sh-c.c
LIB1ASMSRC = sh/lib1funcs.asm
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movmem \
_movmem_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
......
2006-01-30 J"orn Rennecke <joern.rennecke@st.com>
PR target/14798:
* gcc.dg/pragma-isr.c: Added target sh[1234ble]*-*-*.
* gcc.dg/pragma-isr2.c, gcc.dg/pragma-isr-trapa.c: New tests.
* gcc.dg/pragma-isr-trapa2.c: Likewise.
* gcc.dg/pragma-isr-nosave_low_regs.c: Likewise.
* gcc.dg/pragma-isr-trap_exit.c: Likewise.
* gcc.dg/attr-isr.c, gcc.dg/attr-isr-trapa.c: Likewise.
* gcc.dg/attr-isr-trap_exit.c: Likewise.
* gcc.dg/attr-isr-nosave_low_regs.c: Likewise.
2006-01-30 Richard Guenther <rguenther@suse.de>
PR c++/23372
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
extern void bar ();
void foo ()
{
}
#pragma interrupt
void ( __attribute__ ((nosave_low_regs)) isr) ()
{
bar ();
}
void delay(int a)
{
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* A call will clobber all call-saved registers, but because of
#pragma nosave_low_regs, r0..r7 need not be saved/restored.
One of these registers will also do fine to hold the function address.
Call-saved registers r8..r13 also don't need to be restored. */
/* { dg-final { scan-assembler-not "\[^f\]r\[0-9\]\[ \t\]*," } } */
/* { dg-final { scan-assembler-not "\[^f\]r\[89\]" } } */
/* { dg-final { scan-assembler-not "\[^f\]r1\[,0-3\]" } } */
/* { dg-final { scan-assembler-times "macl" 2} } */
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
/* Check that trapa / interrput_handler attributes can paired in
either order. */
void h0() __attribute__ ((trap_exit (4))) __attribute__ ((interrupt_handler));
void h1() __attribute__ ((interrupt_handler)) __attribute__ ((trap_exit (5)));
void foo ()
{
}
void h0 () {}
/* { dg-final { scan-assembler "trapa\[ \t\]\[ \t\]*#4"} } */
/* { dg-final { scan-assembler-times "trapa" 1} } */
void delay(int a)
{
}
int main()
{
return 0;
}
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
extern void foo ();
void
(__attribute__ ((trapa_handler)) isr) ()
{
foo ();
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* No interrupt-specific saves should be needed. /
/* { dg-final { scan-assembler-not "\[^f\]r\[0-7\]\[ \t,\]\[^\n\]*r15" } } */
/* { dg-final { scan-assembler-not "@r15\[^\n\]*\[^f\]r\[0-7\]\n" } } */
/* { dg-final { scan-assembler-not "\[^f\]r\[8-9\]" } } */
/* { dg-final { scan-assembler-not "\[^f\]r1\[,0-3\]" } } */
/* { dg-final { scan-assembler-not "macl" } } */
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
extern void foo ();
void
(__attribute ((interrupt_handler)) isr)()
{
foo ();
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* The call will clobber r0..r7, which will need not be saved/restored.
One of these registers will do fine to hold the function address,
hence the all-saved registers r8..r13 don't need to be restored. */
/* { dg-final { scan-assembler-times "r15\[+\],\[ \t\]*r\[0-9\]\[ \t\]*\n" 8 } } */
/* { dg-final { scan-assembler-times "\[^f\]r\[0-9\]\[ \t\]*," 8 } } */
/* { dg-final { scan-assembler-not "\[^f\]r1\[0-3\]" } } */
/* { dg-final { scan-assembler-times "macl" 2} } */
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
extern void foo ();
#pragma interrupt
#pragma nosave_low_regs
void
isr()
{
foo ();
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* A call will clobber all call-saved registers, but because of
#pragma nosave_low_regs, r0..r7 need not be saved/restored.
One of these registers will also do fine to hold the function address.
Call-saved registers r8..r13 also don't need to be restored. */
/* { dg-final { scan-assembler-not "\[^f\]r\[0-9\]\[ \t\]*," } } */
/* { dg-final { scan-assembler-not "\[^f\]r\[89\]" } } */
/* { dg-final { scan-assembler-not "\[^f\]r1\[,0-3\]" } } */
/* { dg-final { scan-assembler-times "macl" 2} } */
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
/* This test case will check whether trapa is generated only for isr. */
#pragma interrupt
void isr() __attribute__ ((trap_exit (4)));
void isr()
{
}
void delay(int a)
{
}
int main()
{
return 0;
}
/* { dg-final { scan-assembler-times "trapa\[ \t\]\[ \t\]*#4" 1} } */
/* { dg-do compile { target sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
extern void foo ();
#pragma trapa
void
isr()
{
foo ();
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* No interrupt-specific saves should be needed. /
/* { dg-final { scan-assembler-not "r\[0-7\]\[ \t,\]\[^\n\]*r15" } } */
/* { dg-final { scan-assembler-not "@r15\[^\n\]*r\[0-7\]\n" } } */
/* { dg-final { scan-assembler-not "r\[8-9\]" } } */
/* { dg-final { scan-assembler-not "r1\[,0-3\]" } } */
/* { dg-final { scan-assembler-not "macl" } } */
/* { dg-do compile { target sh-*-* sh4*-*-*} } */
/* { dg-options "-O -m4" } */
extern void foo ();
#pragma trapa
void
isr()
{
foo ();
}
/* { dg-final { scan-assembler-times "rte" 1} } */
/* No interrupt-specific saves should be needed.
The function call will require to load the address first into a register,
then use that for a jsr or jmp. It will also need to load a constant
address in order to load fpscr. */
/* { dg-final { scan-assembler-times "r\[0-7\]\n" 3 } } */
/* { dg-final { scan-assembler-not "r\[8-9\]" } } */
/* { dg-final { scan-assembler-not "r1\[,0-3\]" } } */
/* { dg-final { scan-assembler-not "macl" } } */
/* fpscr needs to be saved, loaded and restored. */
/* { dg-final { scan-assembler-times "\[^_\]fpscr" 3 } } */
/* { dg-do compile { target h8300-*-* sh-*-*} } */
/* { dg-do compile { target h8300-*-* sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O3" } */
/* Test case will check whether rte is generated for two ISRs*/
extern void foo();
......
/* { dg-do compile { target h8300-*-* sh-*-* sh[1234ble]*-*-*} } */
/* { dg-options "-O" } */
/* This test case will check whether rte is generated only for isr. */
#pragma interrupt
void isr()
{
}
void delay(int a)
{
}
int main()
{
return 0;
}
/* { dg-final { scan-assembler-times "rte" 1} } */
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