sh.md (*movqi_pop): New insn pattern.
authorKaushik Phatak <kaushik.phatak@kpitcummins.com>
Sun, 11 Apr 2010 22:53:30 +0000 (22:53 +0000)
committerKaz Kojima <kkojima@gcc.gnu.org>
Sun, 11 Apr 2010 22:53:30 +0000 (22:53 +0000)
* config/sh/sh.md (*movqi_pop): New insn pattern.
* config/sh/predicates.md (sh_no_delay_pop_operand): New predicate.
* gcc.target/sh/rte-delay-slot.c: New test.

From-SVN: r158207

gcc/ChangeLog
gcc/config/sh/predicates.md
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/rte-delay-slot.c [new file with mode: 0644]

index c3de163..defa3ba 100644 (file)
@@ -1,3 +1,8 @@
+2010-04-11  Kaushik Phatak  <kaushik.phatak@kpitcummins.com>
+
+       * config/sh/sh.md (*movqi_pop): New insn pattern.
+       * config/sh/predicates.md (sh_no_delay_pop_operand): New predicate.
+
 2010-04-11  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (any_shiftrt): New code iterator.
index 909b4a4..b6508b7 100644 (file)
@@ -1,5 +1,6 @@
 ;; Predicate definitions for Renesas / SuperH SH.
-;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+;; Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 ;;
   return general_operand (op, mode);
 })
 
+
+;; Returns 1 if OP is a POST_INC on stack pointer register.
+
+(define_predicate "sh_no_delay_pop_operand"
+  (match_code "mem")
+{
+  rtx inside;
+  inside = XEXP (op, 0);
+
+  if (GET_CODE (op) == MEM && GET_MODE (op) == SImode 
+      && GET_CODE (inside) == POST_INC 
+      && GET_CODE (XEXP (inside, 0)) == REG
+      && REGNO (XEXP (inside, 0)) == SP_REG)
+    return 1;
+
+  return 0;
+})
+
+
 ;; Returns 1 if OP is a MEM that can be source of a simple move operation.
 
 (define_predicate "unaligned_load_operand"
index 4318c70..d8d6ca7 100644 (file)
@@ -1,6 +1,7 @@
 ;;- Machine description for Renesas / SuperH SH.
 ;;  Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-;;  2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;;  2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;;  Free Software Foundation, Inc.
 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
 ;;  Improved by Jim Wilson (wilson@cygnus.com).
 
@@ -4836,6 +4837,21 @@ label:
   "TARGET_SH1"
   "sett")
 
+;; Define additional pop for SH1 and SH2 so it does not get 
+;; placed in the delay slot.
+(define_insn "*movsi_pop"
+  [(set (match_operand:SI 0 "register_operand" "=r,x,l")
+        (match_operand:SI 1 "sh_no_delay_pop_operand" ">,>,>"))]
+  "(TARGET_SH1 || TARGET_SH2E || TARGET_SH2A)
+   && ! TARGET_SH3"
+  "@
+   mov.l   %1,%0
+   lds.l   %1,%0
+   lds.l   %1,%0"
+  [(set_attr "type" "load_si,mem_mac,pload")
+   (set_attr "length" "2,2,2")
+   (set_attr "in_delay_slot" "no,no,no")])
+
 ;; t/r must come after r/r, lest reload will try to reload stuff like
 ;; (set (subreg:SI (mem:QI (plus:SI (reg:SI SP_REG) (const_int 12)) 0) 0)
 ;; (made from (set (subreg:SI (reg:QI ###) 0) ) into T.
index 1c4c5de..24eebcf 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-11  Kaushik Phatak  <kaushik.phatak@kpitcummins.com>
+
+       * gcc.target/sh/rte-delay-slot.c: New test.
+
 2010-04-11  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/pack9.adb: Remove -cargs option.
diff --git a/gcc/testsuite/gcc.target/sh/rte-delay-slot.c b/gcc/testsuite/gcc.target/sh/rte-delay-slot.c
new file mode 100644 (file)
index 0000000..eca5db9
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile { target "sh-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } "*" "-m1 -m2*" }  */
+/* { dg-final { scan-assembler-not "\trte\t\n\tmov.l\t@r15\\+" } } */
+
+/* This test checks if the compiler generates a pop instruction
+   in the delay slot after rte.  For the sh and sh2, the rte
+   instruction reads the return pc from the stack and any pop
+   in the delay slot crashes the hardware.
+
+   Incorrect code generated
+        mov.l   @r15+,r1
+        rte
+        mov.l   @r15+,r14
+
+   The right code should be
+
+        mov.l   @r15+,r1
+        mov.l   @r15+,r14
+        rte
+        nop
+*/
+void INT_MTU2_1_TGIA1 (void)
+  __attribute__ ((interrupt_handler));
+void
+INT_MTU2_1_TGIA1 (void)
+{
+  volatile int i = 0;
+  volatile int x, y;
+
+  for (i = 0; i < 10; i++)
+    y = y + x;
+}