OSDN Git Service

* config/sh/predicates.md: Remove blank lines.
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.md
index 7fa63ea..71db258 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, 2011
+;;  Free Software Foundation, Inc.
 ;;  Contributed by Steve Chamberlain (sac@cygnus.com).
 ;;  Improved by Jim Wilson (wilson@cygnus.com).
 
   (UNSPEC_DIV_INV_TABLE        37)
   (UNSPEC_ASHIFTRT     35)
   (UNSPEC_THUNK                36)
+  (UNSPEC_CHKADD       38)
   (UNSPEC_SP_SET       40)
   (UNSPEC_SP_TEST      41)
   (UNSPEC_MOVUA                42)
 ;; ??? This looks ugly because genattrtab won't allow if_then_else or cond
 ;; inside an le.
 (define_attr "short_cbranch_p" "no,yes"
-  (cond [(ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+  (cond [(match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 506))
         (const_string "yes")
-        (ne (symbol_ref "NEXT_INSN (PREV_INSN (insn)) != insn") (const_int 0))
+        (match_test "NEXT_INSN (PREV_INSN (insn)) != insn")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 252)) (const_int 508))
         (const_string "yes")
   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 990))
              (const_int 1988))
         (const_string "yes")
-        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 4092))
              (const_int 8186))
   (cond [(leu (plus (minus (match_dup 0) (pc)) (const_int 988))
              (const_int 1986))
         (const_string "yes")
-        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 4090))
               (const_int 8184))
         ] (const_string "no")))
 
 (define_attr "braf_branch_p" "no,yes"
-  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
+  (cond [(match_test "! TARGET_SH2")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 10330))
              (const_int 20660))
         (const_string "yes")
-        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 32764))
              (const_int 65530))
         ] (const_string "no")))
 
 (define_attr "braf_cbranch_p" "no,yes"
-  (cond [(ne (symbol_ref "! TARGET_SH2") (const_int 0))
+  (cond [(match_test "! TARGET_SH2")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 10328))
              (const_int 20658))
         (const_string "yes")
-        (ne (symbol_ref "mdep_reorg_phase <= SH_FIXUP_PCLOAD") (const_int 0))
+        (match_test "mdep_reorg_phase <= SH_FIXUP_PCLOAD")
         (const_string "no")
         (leu (plus (minus (match_dup 0) (pc)) (const_int 32762))
              (const_int 65528))
 ;; ??? using pc is not computed transitively.
                (ne (match_dup 0) (match_dup 0))
                (const_int 14)
-               (ne (symbol_ref ("flag_pic")) (const_int 0))
+               (match_test "flag_pic")
                (const_int 24)
                ] (const_int 16))
         (eq_attr "type" "jump")
         (cond [(eq_attr "med_branch_p" "yes")
                (const_int 2)
-               (and (ne (symbol_ref "prev_nonnote_insn (insn)")
-                        (const_int 0))
-                    (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
-                             (symbol_ref "INSN"))
-                         (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
-                             (symbol_ref "code_for_indirect_jump_scratch"))))
+               (and (match_test "prev_nonnote_insn (insn)")
+                    (and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")                              (symbol_ref "INSN"))
+                         (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")                             (symbol_ref "code_for_indirect_jump_scratch"))))
                 (cond [(eq_attr "braf_branch_p" "yes")
                        (const_int 6)
-                       (eq (symbol_ref "flag_pic") (const_int 0))
+                       (not (match_test "flag_pic"))
                        (const_int 10)
-                       (ne (symbol_ref "TARGET_SH2") (const_int 0))
+                       (match_test "TARGET_SH2")
                        (const_int 10)] (const_int 18))
                (eq_attr "braf_branch_p" "yes")
                (const_int 10)
 ;; ??? using pc is not computed transitively.
                (ne (match_dup 0) (match_dup 0))
                (const_int 12)
-               (ne (symbol_ref ("flag_pic")) (const_int 0))
+               (match_test "flag_pic")
                (const_int 22)
                ] (const_int 14))
         (eq_attr "type" "pt_media")
-        (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
+        (if_then_else (match_test "TARGET_SHMEDIA64")
                       (const_int 20) (const_int 12))
         (and (eq_attr "type" "jump_media")
-             (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0)))
+             (match_test "TARGET_SH5_CUT2_WORKAROUND"))
         (const_int 8)
-        ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
+        ] (if_then_else (match_test "TARGET_SHMEDIA")
                         (const_int 4)
                         (const_int 2))))
 
 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
 
 (define_attr "banked" "yes,no" 
-       (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
-                  (const_int 1))
+       (cond [(match_test "sh_loads_bankedreg_p (insn)")
               (const_string "yes")]
              (const_string "no")))
 
 ;; ??? This should be (nil) instead of (const_int 0)
 (define_attr "hit_stack" "yes,no"
-       (cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
-                  (const_int 0))
+       (cond [(not (match_test "find_regno_note (insn, REG_INC, SP_REG)"))
               (const_string "no")]
              (const_string "yes")))
 
                  (eq_attr "type" "!pload,prset"))
             (and (eq_attr "interrupt_function" "yes")
                  (ior
-                  (eq (symbol_ref "TARGET_SH3") (const_int 0))
+                  (not (match_test "TARGET_SH3"))
                   (eq_attr "hit_stack" "no")
                   (eq_attr "banked" "no"))))) (nil) (nil)])
 
 
 (define_delay
   (and (eq_attr "type" "cbranch")
-       (ne (symbol_ref "TARGET_SH2") (const_int 0)))
+       (match_test "TARGET_SH2"))
   ;; SH2e has a hardware bug that pretty much prohibits the use of
   ;; annuled delay slots.
   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
 ;; SImode signed integer comparisons
 ;; -------------------------------------------------------------------------
 
-(define_insn ""
+;; Various patterns to generate the TST #imm, R0 instruction.
+;; Although this adds some pressure on the R0 register, it can potentially
+;; result in faster code, even if the operand has to be moved to R0 first.
+;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group 
+;; instructions and thus will be executed in parallel.  On SH4A TST #imm, R0
+;; is an EX group instruction but still can be executed in parallel with the
+;; MT group MOV Rm, Rn instruction.
+
+;; Usual TST #imm, R0 patterns for SI, HI and QI
+;; This is usually used for bit patterns other than contiguous bits 
+;; and single bits.
+
+(define_insn "tstsi_t"
   [(set (reg:SI T_REG)
-       (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
-                      (match_operand:SI 1 "arith_operand" "K08,r"))
+       (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
+                      (match_operand:SI 1 "logical_operand" "K08,r"))
               (const_int 0)))]
   "TARGET_SH1"
   "tst %1,%0"
   [(set_attr "type" "mt_group")])
 
+(define_insn "tsthi_t"
+  [(set (reg:SI T_REG)
+       (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
+                                 (match_operand 1 "const_int_operand")) 0)
+              (const_int 0)))]
+  "TARGET_SH1
+   && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
+  "tst %1,%0"
+  [(set_attr "type" "mt_group")])
+
+(define_insn "tstqi_t"
+  [(set (reg:SI T_REG)
+       (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
+                                 (match_operand 1 "const_int_operand")) 0)
+              (const_int 0)))]
+  "TARGET_SH1
+   && (CONST_OK_FOR_K08 (INTVAL (operands[1])) 
+       || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
+{
+  operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
+  return "tst  %1,%0";
+}
+  [(set_attr "type" "mt_group")])
+
+;; Test low QI subreg against zero.
+;; This avoids unecessary zero extension before the test.
+
+(define_insn "tstqi_t_zero"
+  [(set (reg:SI T_REG)
+       (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
+  "TARGET_SH1"
+  "tst #255,%0"
+  [(set_attr "type" "mt_group")])
+
+;; Extract LSB, negate and store in T bit.
+
+(define_insn "tstsi_t_and_not"
+  [(set (reg:SI T_REG)
+        (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
+                (const_int 1)))]
+  "TARGET_SH1"
+  "tst #1,%0"
+  [(set_attr "type" "mt_group")])
+
+;; Extract contiguous bits and compare them against zero.
+
+(define_insn "tstsi_t_zero_extract_eq"
+  [(set (reg:SI T_REG)
+       (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
+               (match_operand:SI 1 "const_int_operand")
+               (match_operand:SI 2 "const_int_operand"))
+         (const_int 0)))]
+  "TARGET_SH1
+   && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
+{
+  operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
+  return "tst  %1,%0";
+}
+  [(set_attr "type" "mt_group")])
+
+;; This split is required when testing bits in a QI subreg.
+
+(define_split
+  [(set (reg:SI T_REG)
+   (eq:SI (if_then_else:SI (zero_extract:SI
+                           (match_operand 0 "logical_operand" "")
+                           (match_operand 1 "const_int_operand")
+                           (match_operand 2 "const_int_operand"))
+                          (match_operand 3 "const_int_operand")
+                          (const_int 0))
+         (const_int 0)))]
+  "TARGET_SH1
+   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+   && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+  [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
+                             (const_int 0)))]
+  "
+{
+  if (GET_MODE (operands[0]) == QImode)
+    operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
+}")
+
+;; Extract single bit, negate and store it in the T bit.
+;; Not used for SH4A.
+
+(define_insn "tstsi_t_zero_extract_xor"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+                         (match_operand:SI 3 "const_int_operand"))
+                        (match_operand:SI 1 "const_int_operand")
+                        (match_operand:SI 2 "const_int_operand")))]
+  "TARGET_SH1
+   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+   && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+  "tst %3,%0"
+  [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A little endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_little"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI
+        (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+                           (match_operand:SI 3 "const_int_operand")) 0)
+        (match_operand:SI 1 "const_int_operand")
+        (match_operand:SI 2 "const_int_operand")))]
+  "TARGET_SH1 && TARGET_LITTLE_ENDIAN
+   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+      == (INTVAL (operands[3]) & 255)
+   && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+  operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+  return "tst  %3,%0";
+}
+  [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A big endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_big"
+  [(set (reg:SI T_REG)
+       (zero_extract:SI
+        (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+                           (match_operand:SI 3 "const_int_operand")) 3)
+        (match_operand:SI 1 "const_int_operand")
+        (match_operand:SI 2 "const_int_operand")))]
+  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
+   && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+      == (INTVAL (operands[3]) & 255)
+   && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+  operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+  return "tst  %3,%0";
+}
+  [(set_attr "type" "mt_group")])
+
 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
 ;; That would still allow reload to create cmpi instructions, but would
 ;; perhaps allow forcing the constant into a register when that is better.
    && (arith_reg_operand (operands[1], SImode)
        || (immediate_operand (operands[1], SImode)
           && satisfies_constraint_I08 (operands[1])))"
-  "bt 0f\;mov %1,%0\\n0:"
+  "bt  0f\;mov %1,%0\\n0:"
   [(set_attr "type" "mt_group,arith") ;; poor approximation
    (set_attr "length" "4")])
 
    && (arith_reg_operand (operands[1], SImode)
        || (immediate_operand (operands[1], SImode)
           && satisfies_constraint_I08 (operands[1])))"
-  "bf 0f\;mov %1,%0\\n0:"
+  "bf  0f\;mov %1,%0\\n0:"
   [(set_attr "type" "mt_group,arith") ;; poor approximation
    (set_attr "length" "4")])
 
    (clobber (reg:SI PR_REG))
    (clobber (reg:SI R4_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "TARGET_SH1 && ! TARGET_SH4"
+  "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
    (clobber (reg:SI R2_REG))
    (clobber (reg:SI R3_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "TARGET_SH1 && ! TARGET_SH4"
+  "TARGET_SH1 && (! TARGET_SH4 || TARGET_DIVIDE_CALL_DIV1)"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
@@ -3018,9 +3164,9 @@ label:
 ;; -------------------------------------------------------------------------
 
 (define_insn "*andsi3_compact"
-  [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
+  [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
        (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
-               (match_operand:SI 2 "logical_operand" "r,K08")))]
+               (match_operand:SI 2 "logical_operand" "K08,r")))]
   "TARGET_SH1"
   "and %2,%0"
   [(set_attr "type" "arith")])
@@ -3422,15 +3568,6 @@ label:
 ;;
 ;; shift left
 
-(define_insn "ashlsi3_sh2a"
-  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
-                  (match_operand:SI 2 "arith_reg_operand" "r")))]
-  "TARGET_SH2A"
-  "shad        %2,%0"
-  [(set_attr "type" "arith")
-   (set_attr "length" "4")])
-
 ;; This pattern is used by init_expmed for computing the costs of shift
 ;; insns.
 
@@ -3439,14 +3576,14 @@ label:
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0")
                   (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri")))
    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
-  "TARGET_SH3
+  "(TARGET_SH3 || TARGET_SH2A)
    || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))"
   "@
    shld        %2,%0
    add %0,%0
    shll%O2     %0
    #"
-  "TARGET_SH3
+  "(TARGET_SH3 || TARGET_SH2A)
    && reload_completed
    && CONST_INT_P (operands[2])
    && ! satisfies_constraint_P27 (operands[2])"
@@ -3476,7 +3613,7 @@ label:
   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
   "#"
   [(set (attr "length")
-       (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
+       (cond [(match_test "shift_insns_rtx (insn)")
               (const_string "2")
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
               (const_string "4")
@@ -3525,7 +3662,7 @@ label:
   if (CONST_INT_P (operands[2])
       && sh_dynamicalize_shift_p (operands[2]))
     operands[2] = force_reg (SImode, operands[2]);
-  if (TARGET_SH3)
+  if (TARGET_SH3 || TARGET_SH2A)
     {
       emit_insn (gen_ashlsi3_std (operands[0], operands[1], operands[2]));
       DONE;
@@ -3542,7 +3679,7 @@ label:
   "TARGET_SH1"
   "#"
   [(set (attr "length")
-       (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
+       (cond [(match_test "shift_insns_rtx (insn)")
               (const_string "2")
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
               (const_string "4")]
@@ -3582,15 +3719,6 @@ label:
 ; arithmetic shift right
 ;
 
-(define_insn "ashrsi3_sh2a"
-  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
-                  (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
-  "TARGET_SH2A"
-  "shad        %2,%0"
-  [(set_attr "type" "dyn_shift")
-   (set_attr "length" "4")])
-
 (define_insn "ashrsi3_k"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
@@ -3685,7 +3813,7 @@ label:
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
-  "TARGET_SH3"
+  "TARGET_SH3 || TARGET_SH2A"
   "shad        %2,%0"
   [(set_attr "type" "dyn_shift")])
 
@@ -3733,20 +3861,11 @@ label:
 
 ;; logical shift right
 
-(define_insn "lshrsi3_sh2a"
-  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
-                    (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
-  "TARGET_SH2A"
-  "shld        %2,%0"
-  [(set_attr "type" "dyn_shift")
-   (set_attr "length" "4")])
-
 (define_insn "lshrsi3_d"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
-  "TARGET_SH3"
+  "TARGET_SH3 || TARGET_SH2A"
   "shld        %2,%0"
   [(set_attr "type" "dyn_shift")])
 
@@ -3778,7 +3897,7 @@ label:
   "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
   "#"
   [(set (attr "length")
-       (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
+       (cond [(match_test "shift_insns_rtx (insn)")
               (const_string "2")
               (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
               (const_string "4")
@@ -3827,7 +3946,8 @@ label:
   if (CONST_INT_P (operands[2])
       && sh_dynamicalize_shift_p (operands[2]))
     operands[2] = force_reg (SImode, operands[2]);
-  if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
+  if ((TARGET_SH3 || TARGET_SH2A)
+      && arith_reg_operand (operands[2], GET_MODE (operands[2])))
     {
       rtx count = copy_to_mode_reg (SImode, operands[2]);
       emit_insn (gen_negsi2 (count, count));
@@ -4199,7 +4319,7 @@ label:
   "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
   "#"
   [(set (attr "length")
-       (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
+       (cond [(match_test "shl_sext_length (insn)")
               (const_string "2")
               (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
               (const_string "4")
@@ -4285,28 +4405,37 @@ label:
   "sub r63, %1, %0"
   [(set_attr "type" "arith_media")])
 
+;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
+;; combined.
 (define_expand "negdi2"
-  [(set (match_operand:DI 0 "arith_reg_operand" "")
-       (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
+  [(set (match_operand:DI 0 "arith_reg_dest" "")
+       (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
+   (clobber (reg:SI T_REG))]
   ""
+  "")
+
+(define_insn_and_split "*negdi2"
+  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+       (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
+  [(const_int 0)]
   "
 {
-  if (TARGET_SH1)
-    {
-      int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
-      int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+  int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+  int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
 
-      rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
-      rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+  rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+  rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
 
-      rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
-      rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
+  rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
+  rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
 
-      emit_insn (gen_clrt ());
-      emit_insn (gen_negc (low_dst, low_src));
-      emit_insn (gen_negc (high_dst, high_src));
-      DONE;
-    }
+  emit_insn (gen_clrt ());
+  emit_insn (gen_negc (low_dst, low_src));
+  emit_insn (gen_negc (high_dst, high_src));
+  DONE;
 }")
 
 (define_insn "negsi2"
@@ -4329,27 +4458,76 @@ label:
                (const_int -1)))]
   "TARGET_SHMEDIA" "")
 
-/* The SH4 202 can do zero-offset branches without pipeline stalls.
-   This can be used as some kind of conditional execution, which is useful
-   for abs.  */
-(define_split
+(define_expand "abssi2"
   [(set (match_operand:SI 0 "arith_reg_dest" "")
-       (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
-                        (match_operand:SI 1 "arith_reg_operand" ""))
-                (reg:SI T_REG)))]
-  "TARGET_HARD_SH4"
+       (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
+   (clobber (reg:SI T_REG))]
+  ""
+  "")
+
+(define_insn_and_split "*abssi2"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
   [(const_int 0)]
-  "emit_insn (gen_movsi_i (operands[0], operands[1]));
-   emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
-   DONE;")
+  "
+{
+  emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+  emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+                const1_rtx));
+  DONE;
+}")
 
-(define_insn "cneg"
+(define_insn_and_split "*negabssi2"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
-                     (match_operand:SI 1 "arith_reg_operand" "0")
-                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+       (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
+  [(const_int 0)]
+  "
+{
+  emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+  emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+                const0_rtx));
+  DONE;
+}")
+
+;; The SH4 202 can do zero-offset branches without pipeline stalls.
+;; This can be used as some kind of conditional execution, which is useful
+;; for abs.
+;; Actually the instruction scheduling should decide whether to use a
+;; zero-offset branch or not for any generic case involving a single
+;; instruction on SH4 202.
+
+(define_insn_and_split "negsi_cond"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
+       (if_then_else:SI (eq:SI (reg:SI T_REG)
+                         (match_operand:SI 3 "const_int_operand" "M,N"))
+        (match_operand:SI 1 "arith_reg_operand" "0,0")
+        (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
   "TARGET_HARD_SH4"
-  "bf 0f\;neg %2,%0\\n0:"
+  "@
+       bt\\t0f\;neg\\t%2,%0\\n0:
+       bf\\t0f\;neg\\t%2,%0\\n0:"
+  "!TARGET_HARD_SH4"
+  [(const_int 0)]
+  "
+{
+  rtx skip_neg_label = gen_label_rtx ();
+
+  emit_insn (gen_movsi (operands[0], operands[1]));
+
+  emit_jump_insn (INTVAL (operands[3])
+                 ? gen_branch_true (skip_neg_label)
+                 : gen_branch_false (skip_neg_label));
+
+  emit_label_after (skip_neg_label,
+                   emit_insn (gen_negsi2 (operands[0], operands[1])));
+  DONE;
+}"
   [(set_attr "type" "arith") ;; poor approximation
    (set_attr "length" "4")])
 
@@ -4375,7 +4553,7 @@ label:
        ld%M1.uw        %m1, %0"
   [(set_attr "type" "*,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4411,7 +4589,7 @@ label:
        ld%M1.ub        %m1, %0"
   [(set_attr "type" "arith_media,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4441,7 +4619,7 @@ label:
        ld%M1.uw        %m1, %0"
   [(set_attr "type" "arith_media,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4488,7 +4666,7 @@ label:
        ld%M1.ub        %m1, %0"
   [(set_attr "type" "arith_media,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4517,7 +4695,7 @@ label:
        fmov.sl %1, %0"
   [(set_attr "type" "arith_media,load_media,fpconv_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "extend")))])
 
@@ -4530,7 +4708,7 @@ label:
        ld%M1.w %m1, %0"
   [(set_attr "type" "*,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4555,7 +4733,7 @@ label:
        ld%M1.b %m1, %0"
   [(set_attr "type" "*,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4595,7 +4773,7 @@ label:
        ld%M1.w %m1, %0"
   [(set_attr "type" "arith_media,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4632,7 +4810,7 @@ label:
    (set_attr_alternative "length"
      [(const_int 2)
        (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))])])
 
 (define_insn "*extendqisi2_media"
@@ -4644,7 +4822,7 @@ label:
        ld%M1.b %m1, %0"
   [(set_attr "type" "arith_media,load_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -4675,7 +4853,7 @@ label:
    (set_attr_alternative "length"
      [(const_int 2)
        (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))])])
 
 /* It would seem useful to combine the truncXi patterns into the movXi
@@ -4694,7 +4872,7 @@ label:
        fmov.s  %T1, %0"
   [(set_attr "type"   "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "extend")))])
 
@@ -4708,7 +4886,7 @@ label:
   [(set_attr "type"   "arith_media,store_media")
    (set_attr "length" "8,4")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "extend")))])
 
@@ -4724,7 +4902,7 @@ label:
        st%M0.b %m0, %1"
   [(set_attr "type"   "arith_media,store")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "extend")))])
 ;; -------------------------------------------------------------------------
@@ -4836,6 +5014,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.
@@ -4920,13 +5113,13 @@ label:
       (const_int 4)
       (const_int 2)
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (const_int 2)
       (const_int 2)
       (const_int 2)
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (const_int 2)
       (const_int 2)
@@ -5004,7 +5197,7 @@ label:
   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media")
    (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -5029,7 +5222,7 @@ label:
   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media")
    (set_attr "length" "4,4,8,4,4,4,4,12")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -5224,10 +5417,10 @@ label:
      [(const_int 2)
       (const_int 2)
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (const_int 2)
       (const_int 2)
@@ -5246,7 +5439,7 @@ label:
        st%M0.b %m0, %N1"
   [(set_attr "type" "arith_media,arith_media,load_media,store_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -5272,7 +5465,7 @@ label:
   operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
 }")
 
-/* When storing r0, we have to avoid reg+reg addressing.  */
+;; When storing r0, we have to avoid reg+reg addressing.
 (define_insn "movhi_i"
   [(set (match_operand:HI 0 "general_movdst_operand"   "=r,r,r,r,m,r,l,r")
        (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
@@ -5308,7 +5501,7 @@ label:
        st%M0.w %m0, %N1"
   [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -5814,10 +6007,10 @@ label:
       ;; We can't use 4-byte push/pop on SHcompact, so we have to
       ;; increment or decrement r15 explicitly.
       (if_then_else
-       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
+       (match_test "TARGET_SHCOMPACT")
        (const_int 10) (const_int 8))
       (if_then_else
-       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
+       (match_test "TARGET_SHCOMPACT")
        (const_int 10) (const_int 8))])
    (set_attr "type" "fmove,move,pcfload,fload,fstore,pcload,load,store,load,fload")
    (set_attr "late_fp_use" "*,*,*,*,yes,*,*,*,*,*")
@@ -6497,7 +6690,7 @@ label:
        st%M0.l %m0, %N1"
   [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -6514,7 +6707,7 @@ label:
        st%M0.l %m0, %N1"
   [(set_attr "type" "arith_media,*,load_media,store_media")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -6606,17 +6799,17 @@ label:
       (const_int 2)
       (const_int 4)
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (const_int 2)
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (if_then_else
-       (ne (symbol_ref "TARGET_SH2A") (const_int 0))
+       (match_test "TARGET_SH2A")
        (const_int 4) (const_int 2))
       (const_int 2)
       (const_int 2)
@@ -6889,8 +7082,6 @@ label:
   "TARGET_SHMEDIA"
   "
 {
-  /* hack to generate same code.  */
-  rtx tmp_di = GET_CODE (operands[0]) == UNORDERED ? NULL : gen_reg_rtx (DImode);
   rtx tmp = gen_reg_rtx (SImode);
   rtx cmp;
   if (GET_CODE (operands[0]) == NE)
@@ -6900,13 +7091,12 @@ label:
                          operands[1], operands[2]);
 
   emit_insn (gen_cstore4_media (tmp, cmp, operands[1], operands[2]));
-  if (tmp_di) emit_insn (gen_extendsidi2 (tmp_di, tmp)); else tmp_di = tmp;
 
   if (GET_CODE (cmp) == GET_CODE (operands[0]))
-    operands[0] = gen_rtx_NE (VOIDmode, tmp_di, const0_rtx);
+    operands[0] = gen_rtx_NE (VOIDmode, tmp, const0_rtx);
   else
-    operands[0] = gen_rtx_EQ (VOIDmode, tmp_di, const0_rtx);
-  operands[1] = tmp_di;
+    operands[0] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+  operands[1] = tmp;
   operands[2] = const0_rtx;
   operands[3] = gen_rtx_LABEL_REF (Pmode, operands[3]);
 }")
@@ -7037,22 +7227,21 @@ label:
 
 (define_insn_and_split "doloop_end_split"
   [(set (pc)
-       (if_then_else (ne:SI (match_operand:SI 0 "arith_reg_dest" "+r")
+       (if_then_else (ne:SI  (match_operand:SI 2 "arith_reg_dest" "0")
                          (const_int 1))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))
-   (set (match_dup 0)
-       (plus (match_dup 0) (const_int -1)))
+   (set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (plus (match_dup 2) (const_int -1)))
    (clobber (reg:SI T_REG))]
   "TARGET_SH2"
   "#"
   ""
   [(parallel [(set (reg:SI T_REG)
-                  (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r")
-                         (const_int 1)))
-             (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))])
+                  (eq:SI (match_dup 2) (const_int 1)))
+             (set (match_dup 0) (plus:SI (match_dup 2) (const_int -1)))])
    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
-                          (label_ref (match_operand 1 "" ""))
+                          (label_ref (match_dup 1))
                           (pc)))]
 ""
    [(set_attr "type" "cbranch")])
@@ -7280,7 +7469,7 @@ label:
    (set_attr "fp_set" "unknown")])
 
 ;; This is TBR relative jump instruction for SH2A architecture.
-;; Its use is enabled assigning an attribute "function_vector"
+;; Its use is enabled by assigning an attribute "function_vector"
 ;; and the vector number to a function during its declaration.
 
 (define_insn "call_valuei_tbr_rel"
@@ -8295,8 +8484,9 @@ label:
 
 (define_insn "dect"
   [(set (reg:SI T_REG)
-       (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1)))
-   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
+       (eq:SI (match_operand:SI 1 "arith_reg_dest" "0") (const_int 1)))
+   (set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (plus:SI (match_dup 1) (const_int -1)))]
   "TARGET_SH2"
   "dt  %0"
   [(set_attr "type" "arith")])
@@ -8441,6 +8631,22 @@ label:
   i++;
 }")
 
+;; op0 = op1 + r12 but hide it before reload completed.  See the comment
+;; in symGOT_load expand.
+
+(define_insn_and_split "chk_guard_add"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (unspec:SI [(match_operand:SI 1 "register_operand" "r")
+                   (reg:SI PIC_REG)]
+                  UNSPEC_CHKADD))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1 && reload_completed"
+  [(set (match_dup 0) (reg:SI PIC_REG))
+   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
+  ""
+  [(set_attr "type" "arith")])
+
 (define_expand "sym_label2reg"
   [(set (match_operand:SI 0 "" "")
        (const:SI (unspec:SI [(match_operand:SI 1 "" "")
@@ -8456,7 +8662,7 @@ label:
   ""
   "
 {
-  rtx insn, mem;
+  rtx mem;
 
   operands[2] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
   operands[3] = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
@@ -8483,13 +8689,9 @@ label:
   else
     emit_move_insn (operands[2], operands[1]);
 
-  emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
-                                            operands[2],
-                                            gen_rtx_REG (Pmode, PIC_REG)));
-
   /* When stack protector inserts codes after the result is set to
-     R0, @(rX, r12) will cause a spill failure for R0.  Don't schedule
-     insns to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
+     R0, @(rX, r12) will cause a spill failure for R0.  Use a unspec
+     insn to avoid combining (set A (plus rX r12)) and (set op0 (mem A))
      when rX is a GOT address for the guard symbol.  Ugly but doesn't
      matter because this is a rare situation.  */
   if (!TARGET_SHMEDIA
@@ -8499,13 +8701,16 @@ label:
       && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == SYMBOL_REF
       && strcmp (XSTR (XVECEXP (XEXP (operands[1], 0), 0, 0), 0),
                 \"__stack_chk_guard\") == 0)
-    emit_insn (gen_blockage ());
+    emit_insn (gen_chk_guard_add (operands[3], operands[2]));
+  else
+    emit_move_insn (operands[3], gen_rtx_PLUS (Pmode, operands[2],
+                                              gen_rtx_REG (Pmode, PIC_REG)));
 
   /* N.B. This is not constant for a GOTPLT relocation.  */
   mem = gen_rtx_MEM (Pmode, operands[3]);
   MEM_NOTRAP_P (mem) = 1;
   /* ??? Should we have a special alias set for the GOT?  */
-  insn = emit_move_insn (operands[0], mem);
+  emit_move_insn (operands[0], mem);
 
   DONE;
 }")
@@ -8672,7 +8877,7 @@ mov.l\\t1f,r4\\n\\
   ""
   "
 {
-  rtx dtpoffsym, insn;
+  rtx dtpoffsym;
   rtx t = (!can_create_pseudo_p ()
           ? operands[0]
           : gen_reg_rtx (GET_MODE (operands[0])));
@@ -8680,8 +8885,7 @@ mov.l\\t1f,r4\\n\\
   dtpoffsym = gen_sym2DTPOFF (operands[1]);
   PUT_MODE (dtpoffsym, Pmode);
   emit_move_insn (t, dtpoffsym);
-  insn = emit_move_insn (operands[0],
-                        gen_rtx_PLUS (Pmode, t, operands[2]));
+  emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, operands[2]));
   DONE;
 }")
 
@@ -8723,11 +8927,11 @@ mov.l\\t1f,r0\\n\\
   ""
   "
 {
-  rtx tpoffsym, insn;
+  rtx tpoffsym;
 
   tpoffsym = gen_sym2TPOFF (operands[1]);
   PUT_MODE (tpoffsym, Pmode);
-  insn = emit_move_insn (operands[0], tpoffsym);
+  emit_move_insn (operands[0], tpoffsym);
   DONE;
 }")
 
@@ -9204,6 +9408,39 @@ mov.l\\t1f,r0\\n\\
   ""
   [(set_attr "length" "0")])
 \f
+;; Define movml instructions for SH2A target.  Currently they are
+;; used to push and pop all banked registers only.
+
+(define_insn "movml_push_banked"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+         (plus (match_dup 0) (const_int -32)))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
+  "TARGET_SH2A && REGNO (operands[0]) == 15"
+  "movml.l\tr7,@-r15"
+  [(set_attr "in_delay_slot" "no")])
+
+(define_insn "movml_pop_banked"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+         (plus (match_dup 0) (const_int 32)))
+   (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
+   (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
+   (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
+   (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
+   (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
+   (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
+   (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
+   (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
+  "TARGET_SH2A && REGNO (operands[0]) == 15"
+  "movml.l\t@r15+,r7"
+  [(set_attr "in_delay_slot" "no")])
+\f
 ;; ------------------------------------------------------------------------
 ;; Scc instructions
 ;; ------------------------------------------------------------------------
@@ -9341,8 +9578,6 @@ mov.l\\t1f,r0\\n\\
    DONE;
 ")
 
-
-
 ;; sne moves the complement of the T reg to DEST like this:
 ;;      cmp/eq ...
 ;;      mov    #-1,temp
@@ -9365,7 +9600,6 @@ mov.l\\t1f,r0\\n\\
   operands[1] = gen_reg_rtx (SImode);
 }")
 
-
 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
 ;; This prevents a regression that occurred when we switched from xor to
 ;; mov/neg for sne.
@@ -9419,7 +9653,6 @@ mov.l\\t1f,r0\\n\\
    DONE;
 ")
 
-
 ;; -------------------------------------------------------------------------
 ;; Instructions to cope with inline literal tables
 ;; -------------------------------------------------------------------------
@@ -11009,7 +11242,7 @@ mov.l\\t1f,r0\\n\\
       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
     {
       rtx src = adjust_address (operands[1], BLKmode, 0);
-      set_mem_size (src, GEN_INT (4));
+      set_mem_size (src, 4);
       emit_insn (gen_movua (operands[0], src));
       DONE;
     }
@@ -11041,7 +11274,7 @@ mov.l\\t1f,r0\\n\\
       && MEM_P (operands[1]) && MEM_ALIGN (operands[1]) < 32)
     {
       rtx src = adjust_address (operands[1], BLKmode, 0);
-      set_mem_size (src, GEN_INT (4));
+      set_mem_size (src, 4);
       emit_insn (gen_movua (operands[0], src));
       DONE;
     }
@@ -11552,7 +11785,7 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type"   "arith_media,arith_media,*,load_media,store_media")
    (set_attr "length" "4,4,16,4,4")
    (set (attr "highpart")
-       (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0))
+       (cond [(match_test "sh_contains_memref_p (insn)")
               (const_string "user")]
              (const_string "ignore")))])
 
@@ -12448,7 +12681,7 @@ mov.l\\t1f,r0\\n\\
   [(set_attr "type" "arith_media")
    (set_attr "highpart" "ignore")])
 
-/* These are useful to expand ANDs and as combiner patterns.  */
+;; These are useful to expand ANDs and as combiner patterns.
 (define_insn_and_split "mshfhi_l_di"
   [(set (match_operand:DI 0 "arith_reg_dest" "=r,f")
        (ior:DI (lshiftrt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rZ,f")
@@ -13427,3 +13660,5 @@ mov.l\\t1f,r0\\n\\
   "ld%M1.q\t%m1, %0\;ld%M2.q\t%m2, %3\;cmpeq\t%0, %3, %0\;movi\t0, %3"
   [(set_attr "type" "other")
    (set_attr "length" "16")])
+
+(include "sync.md")