X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Fcris%2Fcris.md;h=c6bfe2756f72c29595fab50cda21ac223e7723e8;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=32a652f84fe904c399b14e3d83963d6f1c7bee5e;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 32a652f8..c6bfe275 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -1,12 +1,13 @@
;; GCC machine description for CRIS cpu cores.
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+;; 2008, 2009 Free Software Foundation, Inc.
;; Contributed by Axis Communications.
;; 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)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; GCC is distributed in the hope that it will be useful,
@@ -15,9 +16,8 @@
;; 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, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GCC; see the file COPYING3. If not see
+;; .
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
@@ -31,10 +31,10 @@
;; There are several instructions that are orthogonal in size, and seems
;; they could be matched by a single pattern without a specified size
;; for the operand that is orthogonal. However, this did not work on
-;; gcc-2.7.2 (and problably not on gcc-2.8.1), relating to that when a
+;; gcc-2.7.2 (and probably not on gcc-2.8.1), relating to that when a
;; constant is substituted into an operand, the actual mode must be
;; deduced from the pattern. There is reasonable hope that that has been
-;; fixed in egcs post 1.1.1, so FIXME: try again.
+;; fixed, so FIXME: try again.
;; You will notice that three-operand alternatives ("=r", "r", "!To")
;; are marked with a "!" constraint modifier to avoid being reloaded
@@ -54,9 +54,61 @@
;; [rX=gotless_symbol].
;; The movsi for a gotless symbol could be split (post reload).
-;; UNSPEC Usage:
-;; 0 PLT reference from call expansion: operand 0 is the address,
-;; the mode is VOIDmode. Always wrapped in CONST.
+
+(define_constants
+ [
+ ;; PLT reference from call expansion: operand 0 is the address,
+ ;; the mode is VOIDmode. Always wrapped in CONST.
+ ;; The value is relative to the GOT.
+ (CRIS_UNSPEC_PLT_GOTREL 0)
+
+ ;; PLT reference from call expansion: operand 0 is the address,
+ ;; the mode is VOIDmode. Always wrapped in CONST.
+ ;; The value is relative to the PC. It's arch-dependent whether
+ ;; the offset counts from the start or the end of the current item.
+ (CRIS_UNSPEC_PLT_PCREL 1)
+
+ ;; The address of the global offset table as a source operand.
+ (CRIS_UNSPEC_GOT 2)
+
+ ;; The offset from the global offset table to the operand.
+ (CRIS_UNSPEC_GOTREL 3)
+
+ ;; The PC-relative offset to the operand. It's arch-dependent whether
+ ;; the offset counts from the start or the end of the current item.
+ (CRIS_UNSPEC_PCREL 4)
+
+ ;; The index into the global offset table of a symbol, while
+ ;; also generating a GOT entry for the symbol.
+ (CRIS_UNSPEC_GOTREAD 5)
+
+ ;; Similar to CRIS_UNSPEC_GOTREAD, but also generating a PLT entry.
+ (CRIS_UNSPEC_PLTGOTREAD 6)
+
+ ;; Condition for v32 casesi jump, since it needs to have if_then_else
+ ;; form with register as one branch and default label as other.
+ ;; Operand 0 is const_int 0.
+ (CRIS_UNSPEC_CASESI 7)
+
+ ;; Stack frame deallocation barrier.
+ (CRIS_UNSPEC_FRAME_DEALLOC 8)
+
+ ;; Swap all 32 bits of the operand; 31 <=> 0, 30 <=> 1...
+ (CRIS_UNSPEC_SWAP_BITS 9)
+ ])
+
+;; Register numbers.
+(define_constants
+ [(CRIS_GOT_REGNUM 0)
+ (CRIS_STATIC_CHAIN_REGNUM 7)
+ (CRIS_FP_REGNUM 8)
+ (CRIS_SP_REGNUM 14)
+ (CRIS_ACR_REGNUM 15)
+ (CRIS_SRP_REGNUM 16)
+ (CRIS_MOF_REGNUM 17)
+ (CRIS_AP_REGNUM 18)
+ (CRIS_CC0_REGNUM 19)]
+)
;; We need an attribute to define whether an instruction can be put in
;; a branch-delay slot or not, and whether it has a delay slot.
@@ -74,14 +126,21 @@
;; In short, any "slottable" instruction must be 16 bit and not refer
;; to pc, or alter it.
;;
-;; The possible values are "yes", "no" and "has_slot". Yes/no means if
-;; the insn is slottable or not. Has_slot means that the insn is a
-;; return insn or branch insn (which are not considered slottable since
-;; that is generally true). Having the semmingly illogical value
-;; "has_slot" means we do not have to add another attribute just to say
-;; that an insn has a delay-slot, since it also infers that it is not
-;; slottable. Better names for the attribute were found to be longer and
-;; not add readability to the machine description.
+;; The possible values are "yes", "no", "has_slot", "has_return_slot"
+;; and "has_call_slot".
+;; Yes/no tells whether the insn is slottable or not. Has_call_slot means
+;; that the insn is a call insn, which for CRIS v32 has a delay-slot.
+;; Of special concern is that no RTX_FRAME_RELATED insn must go in that
+;; call delay slot, as it's located in the address *after* the call insn,
+;; and the unwind machinery doesn't know about delay slots.
+;; Has_slot means that the insn is a branch insn (which are
+;; not considered slottable since that is generally true). Having the
+;; seemingly illogical value "has_slot" means we do not have to add
+;; another attribute just to say that an insn has a delay-slot, since it
+;; also infers that it is not slottable. Better names for the attribute
+;; were found to be longer and not add readability to the machine
+;; description.
+;; Has_return_slot is similar, for the return insn.
;;
;; The default that is defined here for this attribute is "no", not
;; slottable, not having a delay-slot, so there's no need to worry about
@@ -90,23 +149,29 @@
;; mode, but that would need more attributes and hairier, more error
;; prone code.
;;
-;; There is an extra constraint, 'Q', which recognizes indirect reg,
-;; except when the reg is pc. The constraints 'Q' and '>' together match
-;; all possible memory operands that are slottable.
+;; There is an extra memory constraint, 'Q', which recognizes an indirect
+;; register. The constraints 'Q' and '>' together match all possible
+;; memory operands that are slottable.
;; For other operands, you need to check if it has a valid "slottable"
;; quick-immediate operand, where the particular signedness-variation
;; may match the constraints 'I' or 'J'.), and include it in the
;; constraint pattern for the slottable pattern. An alternative using
;; only "r" constraints is most often slottable.
-(define_attr "slottable" "no,yes,has_slot" (const_string "no"))
+(define_attr "slottable" "no,yes,has_slot,has_return_slot,has_call_slot"
+ (const_string "no"))
;; We also need attributes to sanely determine the condition code
;; state. See cris_notice_update_cc for how this is used.
-(define_attr "cc" "none,clobber,normal" (const_string "normal"))
+(define_attr "cc" "none,clobber,normal,noov32,rev" (const_string "normal"))
+
+;; At the moment, this attribute is just used to help bb-reorder do its
+;; work; the default 0 doesn't help it. Many insns have other lengths,
+;; though none are shorter.
+(define_attr "length" "" (const_int 2))
-;; A branch or return has one delay-slot. The instruction in the
+;; A branch has one delay-slot. The instruction in the
;; delay-slot is always executed, independent of whether the branch is
;; taken or not. Note that besides setting "slottable" to "has_slot",
;; there also has to be a "%#" at the end of a "delayed" instruction
@@ -116,6 +181,70 @@
(define_delay (eq_attr "slottable" "has_slot")
[(eq_attr "slottable" "yes") (nil) (nil)])
+
+;; We can't put prologue insns in call-insn delay-slots when
+;; DWARF2 unwind info is emitted, because the unwinder matches the
+;; address after the insn. It must see the return address of a call at
+;; a position at least *one byte after* the insn, or it'll think that
+;; the insn hasn't been executed. If the insn is in a delay-slot of a
+;; call, it's just *exactly* after the insn.
+
+(define_delay (eq_attr "slottable" "has_call_slot")
+ [(and (eq_attr "slottable" "yes")
+ (ior (eq (symbol_ref "RTX_FRAME_RELATED_P (insn)")
+ (const_int 0))
+ (eq (symbol_ref "flag_exceptions")
+ (const_int 0))))
+ (nil) (nil)])
+
+;; The insn in the return insn slot must not be the
+;; return-address-register restore. FIXME: Use has_slot and express
+;; as a parallel with a use of the return-address-register (currently
+;; only SRP). However, this requires an amount of fixing tests for
+;; naked RETURN in middle-end.
+(define_delay (eq_attr "slottable" "has_return_slot")
+ [(and (eq_attr "slottable" "yes")
+ (eq (symbol_ref "dead_or_set_regno_p (insn, CRIS_SRP_REGNUM)")
+ (const_int 0)))
+ (nil) (nil)])
+
+
+;; Iterator definitions.
+
+;; For the "usual" pattern size alternatives.
+(define_mode_iterator BWD [SI HI QI])
+(define_mode_iterator WD [SI HI])
+(define_mode_iterator BW [HI QI])
+(define_mode_attr S [(SI "HI") (HI "QI")])
+(define_mode_attr s [(SI "hi") (HI "qi")])
+(define_mode_attr m [(SI ".d") (HI ".w") (QI ".b")])
+(define_mode_attr mm [(SI ".w") (HI ".b")])
+(define_mode_attr nbitsm1 [(SI "31") (HI "15") (QI "7")])
+
+;; For the sign_extend+zero_extend variants.
+(define_code_iterator szext [sign_extend zero_extend])
+(define_code_attr u [(sign_extend "") (zero_extend "u")])
+(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+
+;; For the shift variants.
+(define_code_iterator shift [ashiftrt lshiftrt ashift])
+(define_code_iterator shiftrt [ashiftrt lshiftrt])
+(define_code_attr shlr [(ashiftrt "ashr") (lshiftrt "lshr") (ashift "ashl")])
+(define_code_attr slr [(ashiftrt "asr") (lshiftrt "lsr") (ashift "lsl")])
+
+(define_code_iterator ncond [eq ne gtu ltu geu leu])
+(define_code_iterator ocond [gt le])
+(define_code_iterator rcond [lt ge])
+(define_code_attr CC [(eq "eq") (ne "ne") (gt "gt") (gtu "hi") (lt "lt")
+ (ltu "lo") (ge "ge") (geu "hs") (le "le") (leu "ls")])
+(define_code_attr rCC [(eq "ne") (ne "eq") (gt "le") (gtu "ls") (lt "ge")
+ (ltu "hs") (ge "lt") (geu "lo") (le "gt") (leu "hi")])
+(define_code_attr oCC [(lt "mi") (ge "pl")])
+(define_code_attr roCC [(lt "pl") (ge "mi")])
+
+;; Operand and operator predicates.
+
+(include "predicates.md")
;; Test insns.
@@ -124,39 +253,69 @@
;; Allow register and offsettable mem operands only; post-increment is
;; not worth the trouble.
-(define_insn "tstdi"
+(define_expand "tstdi"
+ [(set (cc0) (match_operand:DI 0 "nonimmediate_operand"))]
+ ""
+{
+ if (TARGET_V32 && MEM_P (operands[0]))
+ operands[0] = force_reg (DImode, operands[0]);
+})
+
+(define_insn "*tstdi_non_v32"
[(set (cc0)
(match_operand:DI 0 "nonimmediate_operand" "r,o"))]
- ""
+ "!TARGET_V32"
"test.d %M0\;ax\;test.d %H0")
+(define_insn "*tstdi_v32"
+ [(set (cc0)
+ (match_operand:DI 0 "register_operand" "r"))]
+ "TARGET_V32"
+ "cmpq 0,%M0\;ax\;cmpq 0,%H0")
+
;; No test insns with side-effect on the mem addressing.
;;
;; See note on cmp-insns with side-effects (or lack of them)
;; Normal named test patterns from SI on.
-;; FIXME: Seems they should change to be in order smallest..largest.
(define_insn "tstsi"
[(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "r,Q>,m"))]
""
- "test.d %0"
+{
+ if (which_alternative == 0 && TARGET_V32)
+ return "cmpq 0,%0";
+ return "test.d %0";
+}
[(set_attr "slottable" "yes,yes,no")])
-(define_insn "tsthi"
+(define_expand "tst"
[(set (cc0)
- (match_operand:HI 0 "nonimmediate_operand" "r,Q>,m"))]
+ (match_operand:BW 0 "nonimmediate_operand"))]
""
- "test.w %0"
- [(set_attr "slottable" "yes,yes,no")])
+ "")
-(define_insn "tstqi"
+(define_insn "*tst_cmp"
[(set (cc0)
- (match_operand:QI 0 "nonimmediate_operand" "r,Q>,m"))]
- ""
- "test.b %0"
- [(set_attr "slottable" "yes,yes,no")])
+ (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
+ "cris_cc0_user_requires_cmp (insn)"
+ "@
+ cmp 0,%0
+ test %0
+ test %0"
+ [(set_attr "slottable" "no,yes,no")])
+
+(define_insn "*tst_non_cmp"
+ [(set (cc0)
+ (match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
+ "!cris_cc0_user_requires_cmp (insn)"
+ "@
+ move %0,%0
+ test %0
+ test %0"
+ [(set_attr "slottable" "yes,yes,no")
+ (set_attr "cc" "noov32,*,*")])
;; It seems that the position of the sign-bit and the fact that 0.0 is
;; all 0-bits would make "tstsf" a straight-forward implementation;
@@ -173,11 +332,23 @@
;; DImode for anything else but a structure/block-mode. Just do the
;; obvious stuff for the straight-forward constraint letters.
-(define_insn "cmpdi"
+(define_expand "cmpdi"
[(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o")
- (match_operand:DI 1 "general_operand" "K,I,P,n,r,o,r")))]
+ (compare (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" "")))]
""
+{
+ if (TARGET_V32 && !REG_P (operands[0]))
+ operands[0] = force_reg (DImode, operands[0]);
+ if (TARGET_V32 && MEM_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+})
+
+(define_insn "*cmpdi_non_v32"
+ [(set (cc0)
+ (compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o")
+ (match_operand:DI 1 "general_operand" "Kc,I,P,n,r,o,r")))]
+ "!TARGET_V32"
"@
cmpq %1,%M0\;ax\;cmpq 0,%H0
cmpq %1,%M0\;ax\;cmpq -1,%H0
@@ -187,6 +358,18 @@
cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
cmp.d %M0,%M1\;ax\;cmp.d %H0,%H1")
+(define_insn "*cmpdi_v32"
+ [(set (cc0)
+ (compare (match_operand:DI 0 "register_operand" "r,r,r,r,r")
+ (match_operand:DI 1 "nonmemory_operand" "Kc,I,P,n,r")))]
+ "TARGET_V32"
+ "@
+ cmpq %1,%M0\;ax\;cmpq 0,%H0
+ cmpq %1,%M0\;ax\;cmpq -1,%H0
+ cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
+ cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
+ cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0")
+
;; Note that compare insns with side effect addressing mode (e.g.):
;;
;; cmp.S [rx=ry+i],rz;
@@ -205,115 +388,65 @@
;; These are mostly useful for compares in SImode, using 8 or 16-bit
;; constants, but sometimes gcc will find its way to use it for other
;; (memory) operands. Avoid side-effect patterns, though (see above).
-;;
-;; FIXME: These could have an anonymous mode for operand 1.
-
-;; QImode
-
-(define_insn "*cmp_extsi"
- [(set (cc0)
- (compare
- (match_operand:SI 0 "register_operand" "r,r")
- (match_operator:SI 2 "cris_extend_operator"
- [(match_operand:QI 1 "memory_operand" "Q>,m")])))]
- ""
- "cmp%e2.%s1 %1,%0"
- [(set_attr "slottable" "yes,no")])
-;; HImode
-(define_insn "*cmp_exthi"
+(define_insn "*cmp_ext"
[(set (cc0)
(compare
(match_operand:SI 0 "register_operand" "r,r")
(match_operator:SI 2 "cris_extend_operator"
- [(match_operand:HI 1 "memory_operand" "Q>,m")])))]
+ [(match_operand:BW 1 "memory_operand" "Q>,m")])))]
""
- "cmp%e2.%s1 %1,%0"
+ "cmp%e2 %1,%0"
[(set_attr "slottable" "yes,no")])
;; Swap operands; it seems the canonical look (if any) is not enforced.
;;
;; FIXME: Investigate that.
-;; FIXME: These could have an anonymous mode for operand 1.
-
-;; QImode
-
-(define_insn "*cmp_swapextqi"
- [(set (cc0)
- (compare
- (match_operator:SI 2 "cris_extend_operator"
- [(match_operand:QI 0 "memory_operand" "Q>,m")])
- (match_operand:SI 1 "register_operand" "r,r")))]
- ""
- "cmp%e2.%s0 %0,%1" ; The function cris_notice_update_cc knows about
- ; swapped operands to compares.
- [(set_attr "slottable" "yes,no")])
-;; HImode
-
-(define_insn "*cmp_swapexthi"
+(define_insn "*cmp_swapext"
[(set (cc0)
(compare
(match_operator:SI 2 "cris_extend_operator"
- [(match_operand:HI 0 "memory_operand" "Q>,m")])
+ [(match_operand:BW 0 "memory_operand" "Q>,m")])
(match_operand:SI 1 "register_operand" "r,r")))]
""
- "cmp%e2.%s0 %0,%1" ; The function cris_notice_update_cc knows about
- ; swapped operands to compares.
- [(set_attr "slottable" "yes,no")])
+ "cmp%e2 %0,%1"
+ [(set_attr "slottable" "yes,no")
+ (set_attr "cc" "rev")])
-;; The "normal" compare patterns, from SI on.
+;; The "normal" compare patterns, from SI on. Special-cases with zero
+;; should not happen.
(define_insn "cmpsi"
[(set (cc0)
(compare
- (match_operand:SI 0 "nonimmediate_operand" "r,r,r,r,Q>,Q>,r,r,m,m")
- (match_operand:SI 1 "general_operand" "I,r,Q>,M,M,r,P,g,M,r")))]
+ (match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m")
+ (match_operand:SI 1 "general_operand" "I,r,Q>,r, P,g,r")))]
""
"@
cmpq %1,%0
cmp.d %1,%0
cmp.d %1,%0
- test.d %0
- test.d %0
cmp.d %0,%1
cmp%e1.%z1 %1,%0
cmp.d %1,%0
- test.d %0
cmp.d %0,%1"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no")])
-
-(define_insn "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "r,r,Q>,Q>,r,m,m")
- (match_operand:HI 1 "general_operand" "r,Q>,M,r,g,M,r")))]
- ""
- "@
- cmp.w %1,%0
- cmp.w %1,%0
- test.w %0
- cmp.w %0,%1
- cmp.w %1,%0
- test.w %0
- cmp.w %0,%1"
- [(set_attr "slottable" "yes,yes,yes,yes,no,no,no")])
+ [(set_attr "slottable" "yes,yes,yes,yes,no,no,no")
+ (set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")])
-(define_insn "cmpqi"
+(define_insn "cmp"
[(set (cc0)
- (compare
- (match_operand:QI 0 "nonimmediate_operand" "r,r,r,Q>,Q>,r,m,m")
- (match_operand:QI 1 "general_operand" "r,Q>,M,M,r,g,M,r")))]
+ (compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m")
+ (match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))]
""
"@
- cmp.b %1,%0
- cmp.b %1,%0
- test.b %0
- test.b %0
- cmp.b %0,%1
- cmp.b %1,%0
- test.b %0
- cmp.b %0,%1"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
+ cmp %1,%0
+ cmp %1,%0
+ cmp %0,%1
+ cmp %1,%0
+ cmp %0,%1"
+ [(set_attr "slottable" "yes,yes,yes,no,no")
+ (set_attr "cc" "normal,normal,rev,normal,rev")])
;; Pattern matching the BTST insn.
;; It is useful for "if (i & val)" constructs, where val is an exact
@@ -321,23 +454,25 @@
;; of zeros starting at bit 0).
;; SImode. This mode is the only one needed, since gcc automatically
-;; extends subregs for lower-size modes. FIXME: Add test-case.
+;; extends subregs for lower-size modes. FIXME: Add testcase.
(define_insn "*btst"
[(set (cc0)
(zero_extract
- (match_operand:SI 0 "nonmemory_operand" "r,r,r,r,r,r,n")
- (match_operand:SI 1 "const_int_operand" "K,n,K,n,K,n,n")
- (match_operand:SI 2 "nonmemory_operand" "M,M,K,n,r,r,r")))]
+ (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp")
+ (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n")
+ (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")))]
;; Either it is a single bit, or consecutive ones starting at 0.
- "GET_CODE (operands[1]) == CONST_INT
+ ;; The btst ones depend on stuff in NOTICE_UPDATE_CC.
+ "CONST_INT_P (operands[1])
&& (operands[1] == const1_rtx || operands[2] == const0_rtx)
&& (REG_S_P (operands[0])
|| (operands[1] == const1_rtx
&& REG_S_P (operands[2])
- && GET_CODE (operands[0]) == CONST_INT
- && exact_log2 (INTVAL (operands[0])) >= 0))"
+ && CONST_INT_P (operands[0])
+ && exact_log2 (INTVAL (operands[0])) >= 0))
+ && !TARGET_CCINIT"
-;; The last "&&" condition above should be caught by some kind of
+;; The next-to-last "&&" condition above should be caught by some kind of
;; canonicalization in gcc, but we can easily help with it here.
;; It results from expressions of the type
;; "power_of_2_value & (1 << y)".
@@ -349,13 +484,14 @@
"@
btstq (%1-1),%0
- test.d %0
+ cmpq 0,%0
btstq %2,%0
clearf nz
btst %2,%0
clearf nz
cmpq %p0,%2"
- [(set_attr "slottable" "yes")])
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; Move insns.
@@ -372,13 +508,38 @@
;; The truth has IMO is not been decided yet, so check from time to
;; time by disabling the movdi patterns.
+;; To appease testcase gcc.c-torture/execute/920501-2.c (and others) at
+;; -O0, we need a movdi as a temporary measure. Here's how things fail:
+;; A cmpdi RTX needs reloading (global):
+;; (insn 185 326 186 (set (cc0)
+;; (compare (mem/f:DI (reg/v:SI 22) 0)
+;; (const_int 1 [0x1]))) 4 {cmpdi} (nil)
+;; (nil))
+;; Now, reg 22 is reloaded for input address, and the mem is also moved
+;; out of the instruction (into a register), since one of the operands
+;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is
+;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok
+;; wrt. overlap). The bad things happen with the synthesis in
+;; emit_move_insn_1; the location where to substitute reg 10 is lost into
+;; two new RTX:es, both still having reg 22. Later on, the left-over reg
+;; 22 is recognized to have an equivalent in memory which is substituted
+;; straight in, and we end up with an unrecognizable insn:
+;; (insn 325 324 326 (set (reg:SI 9 r9)
+;; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8)
+;; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil)
+;; (nil))
+;; which is the first part of the reloaded synthesized "movdi".
+;; The right thing would be to add equivalent replacement locations for
+;; insn with pseudos that need more reloading. The question is where.
+
(define_expand "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
- "
{
- if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
+ if (MEM_P (operands[0])
+ && operands[1] != const0_rtx
+ && (!TARGET_V32 || (!REG_P (operands[1]) && can_create_pseudo_p ())))
operands[1] = copy_to_mode_reg (DImode, operands[1]);
/* Some other ports (as of 2001-09-10 for example mcore and romp) also
@@ -386,11 +547,8 @@
gcc.c-torture/execute/961213-1.c shows that CSE2 gets confused by the
resulting subreg sets when using the construct from mcore (as of FSF
CVS, version -r 1.5), and it believes that the high part (the last one
- emitted) is the final value. This construct from romp seems more
- robust, especially considering the head comments from
- emit_no_conflict_block. */
- if ((GET_CODE (operands[1]) == CONST_INT
- || GET_CODE (operands[1]) == CONST_DOUBLE)
+ emitted) is the final value. */
+ if ((CONST_INT_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
&& ! reload_completed
&& ! reload_in_progress)
{
@@ -406,23 +564,69 @@
insns = get_insns ();
end_sequence ();
- emit_no_conflict_block (insns, op0, op1, 0, op1);
+ emit_insn (insns);
DONE;
}
-}")
+})
+
+(define_insn_and_split "*movdi_insn_non_v32"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m")
+ (match_operand:DI 1 "general_operand" "rx,g,rxM"))]
+ "(register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode)
+ || operands[1] == const0_rtx)
+ && !TARGET_V32"
+ "#"
+ "&& reload_completed"
+ [(match_dup 2)]
+ "operands[2] = cris_split_movdx (operands);")
+
+;; Overlapping (but non-identical) source memory address and destination
+;; register would be a compiler bug, so we don't have to specify that.
+(define_insn "*movdi_v32"
+ [(set
+ (match_operand:DI 0 "nonimmediate_operand" "=r,rx,&r,>, m,r,x,m")
+ (match_operand:DI 1 "general_operand" "rxi,r>,m, rx,r,m,m,x"))]
+ "TARGET_V32"
+{
+ switch (which_alternative)
+ {
+ /* FIXME: 1) Use autoincrement where possible. 2) Have peephole2,
+ particularly for cases where the address register is dead. */
+ case 5:
+ if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
+ return "addq 4,%L1\;move.d %1,%H0\;subq 4,%L1\;move.d %1,%M0";
+ gcc_assert (REGNO (operands[0]) + 1 == REGNO (XEXP (operands[1], 0)));
+ return "move.d [%L1+],%M0\;move.d [%L1],%H0";
+ case 2:
+ /* We could do away with the addq if we knew the address-register
+ isn't ACR. If we knew the address-register is dead, we could do
+ away with the subq too. */
+ return "move.d [%L1],%M0\;addq 4,%L1\;move.d [%L1],%H0\;subq 4,%L1";
+ case 4:
+ return "move.d %M1,[%L0]\;addq 4,%L0\;move.d %H1,[%L0]\;subq 4,%L0";
+ case 6:
+ return "move [%L1],%M0\;addq 4,%L1\;move [%L1],%H0\;subq 4,%L1";
+ case 7:
+ return "move %M1,[%L0]\;addq 4,%L0\;move %H1,[%L0]\;subq 4,%L0";
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DI 1 "general_operand" "r,g,rM"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)
- || operands[1] == const0_rtx"
- "#")
+ default:
+ return "#";
+ }
+}
+ ;; The non-split cases clobber cc0 because of their adds and subs.
+ ;; Beware that NOTICE_UPDATE_CC is called before the forced split happens.
+ [(set_attr "cc" "*,*,clobber,*,clobber,clobber,*,*")])
+;; Much like "*movdi_insn_non_v32". Overlapping registers and constants
+;; is handled so much better in cris_split_movdx.
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
- "reload_completed"
+ "TARGET_V32
+ && reload_completed
+ && (!MEM_P (operands[0]) || !REG_P (XEXP (operands[0], 0)))
+ && (!MEM_P (operands[1]) || !REG_P (XEXP (operands[1], 0)))"
[(match_dup 2)]
"operands[2] = cris_split_movdx (operands);")
@@ -432,12 +636,11 @@
;;
;; move.S1 [rx=ry+rz.S],rw avoiding when rx is ry, or rw is rx
;; FIXME: These could have anonymous mode for operand 0.
+;; FIXME: Special registers' alternatives too.
-;; QImode
-
-(define_insn "*mov_sideqi_biap"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (mem:QI (plus:SI
+(define_insn "*mov_side_biap"
+ [(set (match_operand:BW 0 "register_operand" "=r,r")
+ (mem:BW (plus:SI
(mult:SI (match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "n,n"))
(match_operand:SI 3 "register_operand" "r,r"))))
@@ -448,116 +651,83 @@
"cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
"@
#
- move.%s0 [%4=%3+%1%T2],%0")
+ move [%4=%3+%1%T2],%0")
-;; HImode
-
-(define_insn "*mov_sidehi_biap"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (mem:HI (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (match_operand:SI 3 "register_operand" "r,r"))))
- (set (match_operand:SI 4 "register_operand" "=*3,r")
+(define_insn "*mov_sidesisf_biap"
+ [(set (match_operand 0 "register_operand" "=r,r,x,x")
+ (mem (plus:SI
+ (mult:SI (match_operand:SI 1 "register_operand" "r,r,r,r")
+ (match_operand:SI 2 "const_int_operand" "n,n,n,n"))
+ (match_operand:SI 3 "register_operand" "r,r,r,r"))))
+ (set (match_operand:SI 4 "register_operand" "=*3,r,*3,r")
(plus:SI (mult:SI (match_dup 1)
(match_dup 2))
(match_dup 3)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
+ "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
"@
#
- move.%s0 [%4=%3+%1%T2],%0")
-
-;; SImode
-
-(define_insn "*mov_sidesi_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (mem:SI (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (match_operand:SI 3 "register_operand" "r,r"))))
- (set (match_operand:SI 4 "register_operand" "=*3,r")
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
- (match_dup 3)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
- "@
+ move.%s0 [%4=%3+%1%T2],%0
#
- move.%s0 [%4=%3+%1%T2],%0")
+ move [%4=%3+%1%T2],%0")
;; move.S1 [rx=ry+i],rz
;; avoiding move.S1 [ry=ry+i],rz
;; and move.S1 [rz=ry+i],rz
;; Note that "i" is allowed to be a register.
-;; FIXME: These could have anonymous mode for operand 0.
-
-;; QImode
-
-(define_insn "*mov_sideqi"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r")
- (mem:QI
- (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
- (plus:SI (match_dup 1)
- (match_dup 2)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 127
- || INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"move.%s0 [%3=%1%S2],%0\";
-}")
-
-;; HImode
-(define_insn "*mov_sidehi"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (mem:HI
- (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
+(define_insn "*mov_side"
+ [(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r")
+ (mem:BW
+ (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r"))))
+ (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
"cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[2])
|| INTVAL (operands[2]) > 127
|| INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"move.%s0 [%3=%1%S2],%0\";
-}")
-
-;; SImode
-
-(define_insn "*mov_sidesi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (mem:SI
- (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "move [%3=%2%S1],%0";
+ return "move [%3=%1%S2],%0";
+})
+
+(define_insn "*mov_sidesisf"
+ [(set (match_operand 0 "register_operand" "=r,r,r,x,x,x,r,r,x,x")
+ (mem
+ (plus:SI
+ (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,r,r,r,R,R,R,R")
+ (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r>Rn,r,>Rn,r,r,r,r"))))
+ (set (match_operand:SI 3 "register_operand" "=*1,r,r,*1,r,r,*2,r,*2,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
+ "GET_MODE_SIZE (GET_MODE (operands[0])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
+ if ((which_alternative == 0
+ || which_alternative == 3
+ || which_alternative == 6
+ || which_alternative == 8)
+ && (!CONST_INT_P (operands[2])
|| INTVAL (operands[2]) > 127
|| INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"move.%s0 [%3=%1%S2],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
+ return "#";
+ if (which_alternative < 3)
+ return "move.%s0 [%3=%1%S2],%0";
+ if (which_alternative == 7)
+ return "move.%s0 [%3=%2%S1],%0";
+ if (which_alternative == 9)
+ return "move [%3=%2%S1],%0";
+ return "move [%3=%1%S2],%0";
+})
;; Other way around; move to memory.
@@ -577,17 +747,14 @@
;;
;; move.s rz,[ry=rx+rw.S]
-;; FIXME: These could have anonymous mode for operand 3.
-;; QImode
-
-(define_insn "*mov_sideqi_biap_mem"
- [(set (mem:QI (plus:SI
+(define_insn "*mov_side_biap_mem"
+ [(set (mem:BW (plus:SI
(mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
(match_operand:SI 1 "const_int_operand" "n,n,n"))
(match_operand:SI 2 "register_operand" "r,r,r")))
- (match_operand:QI 3 "register_operand" "r,r,r"))
- (set (match_operand:SI 4 "register_operand" "=*2,!*3,r")
+ (match_operand:BW 3 "register_operand" "r,r,r"))
+ (set (match_operand:SI 4 "register_operand" "=*2,!3,r")
(plus:SI (mult:SI (match_dup 0)
(match_dup 1))
(match_dup 2)))]
@@ -595,43 +762,27 @@
"@
#
#
- move.%s3 %3,[%4=%2+%0%T1]")
-
-;; HImode
-
-(define_insn "*mov_sidehi_biap_mem"
- [(set (mem:HI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "const_int_operand" "n,n,n"))
- (match_operand:SI 2 "register_operand" "r,r,r")))
- (match_operand:HI 3 "register_operand" "r,r,r"))
- (set (match_operand:SI 4 "register_operand" "=*2,!*3,r")
+ move %3,[%4=%2+%0%T1]")
+
+(define_insn "*mov_sidesisf_biap_mem"
+ [(set (mem (plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "r,r,r,r,r,r")
+ (match_operand:SI 1 "const_int_operand" "n,n,n,n,n,n"))
+ (match_operand:SI 2 "register_operand" "r,r,r,r,r,r")))
+ (match_operand 3 "register_operand" "r,r,r,x,x,x"))
+ (set (match_operand:SI 4 "register_operand" "=*2,!3,r,*2,!3,r")
(plus:SI (mult:SI (match_dup 0)
(match_dup 1))
(match_dup 2)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
+ "GET_MODE_SIZE (GET_MODE (operands[3])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
"@
#
#
- move.%s3 %3,[%4=%2+%0%T1]")
-
-;; SImode
-
-(define_insn "*mov_sidesi_biap_mem"
- [(set (mem:SI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "const_int_operand" "n,n,n"))
- (match_operand:SI 2 "register_operand" "r,r,r")))
- (match_operand:SI 3 "register_operand" "r,r,r"))
- (set (match_operand:SI 4 "register_operand" "=*2,!*3,r")
- (plus:SI (mult:SI (match_dup 0)
- (match_dup 1))
- (match_dup 2)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 2, 0, 1, 3)"
- "@
+ move.%s3 %3,[%4=%2+%0%T1]
#
#
- move.%s3 %3,[%4=%2+%0%T1]")
+ move %3,[%4=%2+%0%T1]")
;; Split for the case above where we're out of luck with register
;; allocation (again, the condition isn't checked for that), and we end up
@@ -640,10 +791,12 @@
(define_split
[(parallel
- [(set (mem (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))
- (match_operand:SI 2 "register_operand" "")))
+ [(set (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
+ (match_operand:SI 2 "register_operand" ""))])
(match_operand 3 "register_operand" ""))
(set (match_operand:SI 4 "register_operand" "")
(plus:SI (mult:SI (match_dup 0)
@@ -657,89 +810,82 @@
(match_dup 1))
(match_dup 4)))]
"operands[5]
- = gen_rtx_MEM (GET_MODE (operands[3]),
- gen_rtx_PLUS (SImode,
- gen_rtx_MULT (SImode,
- operands[0], operands[1]),
- operands[2]));")
+ = replace_equiv_address (operands[6],
+ gen_rtx_PLUS (SImode,
+ gen_rtx_MULT (SImode,
+ operands[0],
+ operands[1]),
+ operands[2]));")
;; move.s rx,[ry=rz+i]
;; FIXME: These could have anonymous mode for operand 2.
;; QImode
-(define_insn "*mov_sideqi_mem"
- [(set (mem:QI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn")))
- (match_operand:QI 2 "register_operand" "r,r,r,r"))
- (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r")
- (plus:SI (match_dup 0)
- (match_dup 1)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) > 127
- || INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- if (which_alternative == 1)
- return \"#\";
- return \"move.%s2 %2,[%3=%0%S1]\";
-}")
-
-;; HImode
-
-(define_insn "*mov_sidehi_mem"
- [(set (mem:HI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn")))
- (match_operand:HI 2 "register_operand" "r,r,r,r"))
- (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r")
+(define_insn "*mov_side_mem"
+ [(set (mem:BW
+ (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r,R,R,R")
+ (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn,r,r,r")))
+ (match_operand:BW 2 "register_operand" "r,r,r,r,r,r,r"))
+ (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r,*1,!*2,r")
(plus:SI (match_dup 0)
(match_dup 1)))]
"cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 4)
+ && (!CONST_INT_P (operands[1])
|| INTVAL (operands[1]) > 127
|| INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- if (which_alternative == 1)
- return \"#\";
- return \"move.%s2 %2,[%3=%0%S1]\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
+ return "#";
+ if (which_alternative == 1 || which_alternative == 5)
+ return "#";
+ if (which_alternative == 6)
+ return "move.%s2 %2,[%3=%1%S0]";
+ return "move %2,[%3=%0%S1]";
+})
;; SImode
-(define_insn "*mov_sidesi_mem"
- [(set (mem:SI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r>Rn,r,>Rn")))
- (match_operand:SI 2 "register_operand" "r,r,r,r"))
- (set (match_operand:SI 3 "register_operand" "=*0,!*2,r,r")
+(define_insn "*mov_sidesisf_mem"
+ [(set (mem
+ (plus:SI
+ (match_operand:SI
+ 0 "cris_bdap_operand"
+ "%r, r, r,r, r, r,r, R,R, R,R, R")
+ (match_operand:SI
+ 1 "cris_bdap_operand"
+ "r>Rn,r>Rn,r,>Rn,r>Rn,r,>Rn,r,r, r,r, r")))
+ (match_operand 2 "register_operand"
+ "r, r, r,r, x, x,x, r,r, r,x, x"))
+ (set (match_operand:SI 3 "register_operand"
+ "=*0,!2, r,r, *0, r,r, *1,!*2,r,*1,r")
(plus:SI (match_dup 0)
(match_dup 1)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
- "*
+ "GET_MODE_SIZE (GET_MODE (operands[2])) == UNITS_PER_WORD
+ && cris_side_effect_mode_ok (PLUS, operands, 3, 0, 1, -1, 2)"
{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 4)
+ && (!CONST_INT_P (operands[1])
|| INTVAL (operands[1]) > 127
|| INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- if (which_alternative == 1)
- return \"#\";
- return \"move.%s2 %2,[%3=%0%S1]\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
+ return "#";
+ if (which_alternative == 1
+ || which_alternative == 7
+ || which_alternative == 8
+ || which_alternative == 10)
+ return "#";
+ if (which_alternative < 4)
+ return "move.%s2 %2,[%3=%0%S1]";
+ if (which_alternative == 9)
+ return "move.%s2 %2,[%3=%1%S0]";
+ if (which_alternative == 11)
+ return "move %2,[%3=%1%S0]";
+ return "move %2,[%3=%0%S1]";
+})
;; Like the biap case, a split where the set in the side-effect gets the
;; same register as the input register to the main insn, since the
@@ -747,9 +893,11 @@
(define_split
[(parallel
- [(set (mem (plus:SI
- (match_operand:SI 0 "cris_bdap_operand" "")
- (match_operand:SI 1 "cris_bdap_operand" "")))
+ [(set (match_operator
+ 4 "cris_mem_op"
+ [(plus:SI
+ (match_operand:SI 0 "cris_bdap_operand" "")
+ (match_operand:SI 1 "cris_bdap_operand" ""))])
(match_operand 2 "register_operand" ""))
(set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 0) (match_dup 1)))])]
@@ -757,100 +905,18 @@
[(set (match_dup 4) (match_dup 2))
(set (match_dup 3) (match_dup 0))
(set (match_dup 3) (plus:SI (match_dup 3) (match_dup 1)))]
- "operands[4]
- = gen_rtx_MEM (GET_MODE (operands[2]),
- gen_rtx_PLUS (SImode, operands[0], operands[1]));")
+ "")
;; Clear memory side-effect patterns. It is hard to get to the mode if
;; the MEM was anonymous, so there will be one for each mode.
-;; clear.d [ry=rx+rw.s2]
-
-(define_insn "*clear_sidesi_biap"
- [(set (mem:SI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "const_int_operand" "n,n"))
- (match_operand:SI 2 "register_operand" "r,r")))
- (const_int 0))
- (set (match_operand:SI 3 "register_operand" "=*2,r")
- (plus:SI (mult:SI (match_dup 0)
- (match_dup 1))
- (match_dup 2)))]
- "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)"
- "@
- #
- clear.d [%3=%2+%0%T1]")
-
-;; clear.d [ry=rz+i]
-
-(define_insn "*clear_sidesi"
- [(set (mem:SI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn")))
- (const_int 0))
- (set (match_operand:SI 2 "register_operand" "=*0,r,r")
- (plus:SI (match_dup 0)
- (match_dup 1)))]
- "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) > 127
- || INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- return \"clear.d [%2=%0%S1]\";
-}")
-
-;; clear.w [ry=rx+rw.s2]
-
-(define_insn "*clear_sidehi_biap"
- [(set (mem:HI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "const_int_operand" "n,n"))
- (match_operand:SI 2 "register_operand" "r,r")))
- (const_int 0))
- (set (match_operand:SI 3 "register_operand" "=*2,r")
- (plus:SI (mult:SI (match_dup 0)
- (match_dup 1))
- (match_dup 2)))]
- "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)"
- "@
- #
- clear.w [%3=%2+%0%T1]")
-
-;; clear.w [ry=rz+i]
+;; clear.[bwd] [ry=rx+rw.s2]
-(define_insn "*clear_sidehi"
- [(set (mem:HI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn")))
- (const_int 0))
- (set (match_operand:SI 2 "register_operand" "=*0,r,r")
- (plus:SI (match_dup 0)
- (match_dup 1)))]
- "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) > 127
- || INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- return \"clear.w [%2=%0%S1]\";
-}")
-
-;; clear.b [ry=rx+rw.s2]
-
-(define_insn "*clear_sideqi_biap"
- [(set (mem:QI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "const_int_operand" "n,n"))
- (match_operand:SI 2 "register_operand" "r,r")))
+(define_insn "*clear_side_biap"
+ [(set (mem:BWD (plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "const_int_operand" "n,n"))
+ (match_operand:SI 2 "register_operand" "r,r")))
(const_int 0))
(set (match_operand:SI 3 "register_operand" "=*2,r")
(plus:SI (mult:SI (match_dup 0)
@@ -859,55 +925,32 @@
"cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)"
"@
#
- clear.b [%3=%2+%0%T1]")
+ clear [%3=%2+%0%T1]")
-;; clear.b [ry=rz+i]
+;; clear.[bwd] [ry=rz+i]
-(define_insn "*clear_sideqi"
- [(set (mem:QI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn")))
+(define_insn "*clear_side"
+ [(set (mem:BWD
+ (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))
(const_int 0))
- (set (match_operand:SI 2 "register_operand" "=*0,r,r")
+ (set (match_operand:SI 2 "register_operand" "=*0,r,r,*1,r")
(plus:SI (match_dup 0)
(match_dup 1)))]
"cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[1]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[1])
|| INTVAL (operands[1]) > 127
|| INTVAL (operands[1]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
- return \"#\";
- return \"clear.b [%2=%0%S1]\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "clear [%2=%1%S0]";
+ return "clear [%2=%0%S1]";
+})
-;; To appease test-case gcc.c-torture/execute/920501-2.c (and others) at
-;; -O0, we need a movdi as a temporary measure. Here's how things fail:
-;; A cmpdi RTX needs reloading (global):
-;; (insn 185 326 186 (set (cc0)
-;; (compare (mem/f:DI (reg/v:SI 22) 0)
-;; (const_int 1 [0x1]))) 4 {cmpdi} (nil)
-;; (nil))
-;; Now, reg 22 is reloaded for input address, and the mem is also moved
-;; out of the instruction (into a register), since one of the operands
-;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is
-;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok
-;; wrt. overlap). The bad things happen with the synthesis in
-;; emit_move_insn_1; the location where to substitute reg 10 is lost into
-;; two new RTX:es, both still having reg 22. Later on, the left-over reg
-;; 22 is recognized to have an equivalent in memory which is substituted
-;; straight in, and we end up with an unrecognizable insn:
-;; (insn 325 324 326 (set (reg:SI 9 r9)
-;; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8)
-;; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil)
-;; (nil))
-;; which is the first part of the reloaded synthesized "movdi".
-;; The right thing would be to add equivalent replacement locations for
-;; insn with pseudos that need more reloading. The question is where.
-
;; Normal move patterns from SI on.
(define_expand "movsi"
@@ -915,14 +958,13 @@
(match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "cris_general_operand_or_symbol" ""))]
""
- "
{
/* If the output goes to a MEM, make sure we have zero or a register as
input. */
- if (GET_CODE (operands[0]) == MEM
+ if (MEM_P (operands[0])
&& ! REG_S_P (operands[1])
&& operands[1] != const0_rtx
- && ! no_new_pseudos)
+ && can_create_pseudo_p ())
operands[1] = force_reg (SImode, operands[1]);
/* If we're generating PIC and have an incoming symbol, validize it to a
@@ -931,126 +973,254 @@
FIXME: Do we *have* to recognize anything that would normally be a
valid symbol? Can we exclude global PIC addresses with an added
offset? */
- if (flag_pic
- && CONSTANT_ADDRESS_P (operands[1])
- && cris_symbol (operands[1]))
- {
- /* We must have a register as destination for what we're about to
- do, and for the patterns we generate. */
- if (! REG_S_P (operands[0]))
- {
- if (no_new_pseudos)
- abort ();
- operands[1] = force_reg (SImode, operands[1]);
- }
- else
- {
- /* Mark a needed PIC setup for a LABEL_REF:s coming in here:
- they are so rare not-being-branch-targets that we don't mark
- a function as needing PIC setup just because we have
- inspected LABEL_REF:s as operands. It is only in
- __builtin_setjmp and such that we can get a LABEL_REF
- assigned to a register. */
- if (GET_CODE (operands[1]) == LABEL_REF)
- current_function_uses_pic_offset_table = 1;
-
- /* We don't have to do anything for global PIC operands; they
- look just like ``[rPIC+sym]''. */
- if (! cris_got_symbol (operands[1])
- /* We don't do anything for local PIC operands; we match
- that with a special alternative. */
- && ! cris_gotless_symbol (operands[1]))
- {
- /* We get here when we have to change something that would
- be recognizable if it wasn't PIC. A ``sym'' is ok for
- PIC symbols both with and without a GOT entry. And ``sym
- + offset'' is ok for local symbols, so the only thing it
- could be, is a global symbol with an offset. Check and
- abort if not. */
- rtx sym = get_related_value (operands[1]);
- HOST_WIDE_INT offs = get_integer_term (operands[1]);
-
- if (sym == NULL_RTX || offs == 0)
- abort ();
- emit_move_insn (operands[0], sym);
- if (expand_binop (SImode, add_optab, operands[0],
- GEN_INT (offs), operands[0], 0,
- OPTAB_LIB_WIDEN) != operands[0])
- abort ();
- DONE;
- }
- }
- }
-}")
+ if (flag_pic
+ && CONSTANT_ADDRESS_P (operands[1])
+ && !cris_valid_pic_const (operands[1], false))
+ {
+ enum cris_pic_symbol_type t = cris_pic_symbol_type_of (operands[1]);
+
+ gcc_assert (t != cris_no_symbol);
+
+ if (! REG_S_P (operands[0]))
+ {
+ /* We must have a register as destination for what we're about to
+ do, and for the patterns we generate. */
+ CRIS_ASSERT (can_create_pseudo_p ());
+ operands[1] = force_reg (SImode, operands[1]);
+ }
+ else
+ {
+ /* FIXME: add a REG_EQUAL (or is it REG_EQUIV) note to the
+ destination register for the symbol. It might not be
+ worth it. Measure. */
+ crtl->uses_pic_offset_table = 1;
+ if (t == cris_rel_symbol)
+ {
+ /* Change a "move.d sym(+offs),rN" into (allocate register rM)
+ for pre-v32:
+ "move.d (const (plus (unspec [sym]
+ CRIS_UNSPEC_GOTREL) offs)),rM" "add.d rPIC,rM,rN"
+ and for v32:
+ "move.d (const (plus (unspec [sym]
+ CRIS_UNSPEC_PCREL) offs)),rN". */
+ rtx tem, rm, rn = operands[0];
+ rtx sym = GET_CODE (operands[1]) != CONST
+ ? operands[1] : get_related_value (operands[1]);
+ HOST_WIDE_INT offs = get_integer_term (operands[1]);
+
+ gcc_assert (can_create_pseudo_p ());
+
+ if (TARGET_V32)
+ {
+ tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
+ CRIS_UNSPEC_PCREL);
+ if (offs != 0)
+ tem = plus_constant (tem, offs);
+ rm = rn;
+ emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
+ }
+ else
+ {
+ /* We still uses GOT-relative addressing for
+ pre-v32. */
+ crtl->uses_pic_offset_table = 1;
+ tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
+ CRIS_UNSPEC_GOTREL);
+ if (offs != 0)
+ tem = plus_constant (tem, offs);
+ rm = gen_reg_rtx (Pmode);
+ emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
+ if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
+ rn, 0, OPTAB_LIB_WIDEN) != rn)
+ internal_error ("expand_binop failed in movsi gotrel");
+ }
+ DONE;
+ }
+ else if (t == cris_got_symbol)
+ {
+ /* Change a "move.d sym,rN" into (allocate register rM, rO)
+ "move.d (const (unspec [sym] CRIS_UNSPEC_GOTREAD)),rM"
+ "add.d rPIC,rM,rO", "move.d [rO],rN" with
+ the memory access marked as read-only. */
+ rtx tem, mem, rm, ro, rn = operands[0];
+ gcc_assert (can_create_pseudo_p ());
+ tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
+ CRIS_UNSPEC_GOTREAD);
+ rm = gen_reg_rtx (Pmode);
+ emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
+ ro = gen_reg_rtx (Pmode);
+ if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
+ ro, 0, OPTAB_LIB_WIDEN) != ro)
+ internal_error ("expand_binop failed in movsi got");
+ mem = gen_rtx_MEM (Pmode, ro);
+
+ /* This MEM doesn't alias anything. Whether it
+ aliases other same symbols is unimportant. */
+ set_mem_alias_set (mem, new_alias_set ());
+ MEM_NOTRAP_P (mem) = 1;
+
+ /* We can set the GOT memory read of a non-called symbol
+ to readonly, but not that of a call symbol, as those
+ are subject to lazy evaluation and usually have the value
+ changed from the first call to the second (but
+ constant thereafter). */
+ MEM_READONLY_P (mem) = 1;
+ emit_move_insn (rn, mem);
+ DONE;
+ }
+ else
+ {
+ /* We get here when we have to change something that would
+ be recognizable if it wasn't PIC. A ``sym'' is ok for
+ PIC symbols both with and without a GOT entry. And ``sym
+ + offset'' is ok for local symbols, so the only thing it
+ could be, is a global symbol with an offset. Check and
+ abort if not. */
+ rtx reg = gen_reg_rtx (Pmode);
+ rtx sym = get_related_value (operands[1]);
+ HOST_WIDE_INT offs = get_integer_term (operands[1]);
+
+ gcc_assert (can_create_pseudo_p ()
+ && t == cris_got_symbol_needing_fixup
+ && sym != NULL_RTX && offs != 0);
+
+ emit_move_insn (reg, sym);
+ if (expand_binop (SImode, add_optab, reg,
+ GEN_INT (offs), operands[0], 0,
+ OPTAB_LIB_WIDEN) != operands[0])
+ internal_error ("expand_binop failed in movsi got+offs");
+ DONE;
+ }
+ }
+ }
+})
+
+(define_insn "*movsi_got_load"
+ [(set (reg:SI CRIS_GOT_REGNUM) (unspec:SI [(const_int 0)] CRIS_UNSPEC_GOT))]
+ "flag_pic"
+{
+ return TARGET_V32
+ ? "lapc _GLOBAL_OFFSET_TABLE_,%:"
+ : "move.d $pc,%:\;sub.d .:GOTOFF,%:";
+}
+ [(set_attr "cc" "clobber")])
(define_insn "*movsi_internal"
[(set
- (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Q>,r,Q>,g,r,r,r,g")
- (match_operand:SI 1
- ;; FIXME: We want to put S last, but apparently g matches S.
- ;; It's a bug: an S is not a general_operand and shouldn't match g.
- "cris_general_operand_or_gotless_symbol" "r,Q>,M,M,I,r,M,n,!S,g,r"))]
+ (match_operand:SI 0 "nonimmediate_operand"
+ "=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x")
+ (match_operand:SI 1 "cris_general_operand_or_pic_source"
+ "r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))]
+ ;; Note that we prefer not to use the S alternative (if for some reason
+ ;; it competes with others) above, but g matches S.
""
- "*
{
/* Better to have c-switch here; it is worth it to optimize the size of
move insns. The alternative would be to try to find more constraint
letters. FIXME: Check again. It seems this could shrink a bit. */
switch (which_alternative)
{
+ case 9:
+ if (TARGET_V32)
+ {
+ if (!flag_pic
+ && (GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == LABEL_REF
+ || GET_CODE (operands[1]) == CONST))
+ {
+ /* FIXME: Express this through (set_attr cc none) instead,
+ since we can't express the ``none'' at this point. FIXME:
+ Use lapc for everything except const_int and when next cc0
+ user would want the flag setting. */
+ CC_STATUS_INIT;
+ return "lapc %1,%0";
+ }
+ if (flag_pic == 1
+ && GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == UNSPEC
+ && XINT (XEXP (operands[1], 0), 1) == CRIS_UNSPEC_GOTREAD)
+ return "movu.w %1,%0";
+ }
+ /* FALLTHROUGH */
case 0:
case 1:
case 5:
- case 9:
case 10:
- return \"move.d %1,%0\";
+ return "move.d %1,%0";
+
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ return "move %d1,%0";
case 2:
case 3:
case 6:
- return \"clear.d %0\";
+ return "clear.d %0";
/* Constants -32..31 except 0. */
case 4:
- return \"moveq %1,%0\";
+ return "moveq %1,%0";
/* We can win a little on constants -32768..-33, 32..65535. */
case 7:
if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) < 65536)
{
if (INTVAL (operands[1]) < 256)
- return \"movu.b %1,%0\";
- return \"movu.w %1,%0\";
+ return "movu.b %1,%0";
+ return "movu.w %1,%0";
}
else if (INTVAL (operands[1]) >= -32768 && INTVAL (operands[1]) < 32768)
{
if (INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) < 128)
- return \"movs.b %1,%0\";
- return \"movs.w %1,%0\";
+ return "movs.b %1,%0";
+ return "movs.w %1,%0";
}
- return \"move.d %1,%0\";
-
- case 8:
- /* FIXME: Try and split this into pieces GCC makes better code of,
- than this multi-insn pattern. Synopsis: wrap the GOT-relative
- symbol into an unspec, and when PIC, recognize the unspec
- everywhere a symbol is normally recognized. (The PIC register
- should be recognized by GCC as pic_offset_table_rtx when needed
- and similar for PC.) Each component can then be optimized with
- the rest of the code; it should be possible to have a constant
- term added on an unspec. Don't forget to add a REG_EQUAL (or
- is it REG_EQUIV) note to the destination. It might not be
- worth it. Measure.
-
- Note that the 'v' modifier makes PLT references be output as
- sym:PLT rather than [rPIC+sym:GOTPLT]. */
- return \"move.d %v1,%0\;add.d %P1,%0\";
+ return "move.d %1,%0";
+ case 8:
+ {
+ rtx tem = operands[1];
+ gcc_assert (GET_CODE (tem) == CONST);
+ tem = XEXP (tem, 0);
+ if (GET_CODE (tem) == PLUS
+ && GET_CODE (XEXP (tem, 0)) == UNSPEC
+ && (XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
+ || XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_PCREL)
+ && CONST_INT_P (XEXP (tem, 1)))
+ tem = XEXP (tem, 0);
+ gcc_assert (GET_CODE (tem) == UNSPEC);
+ switch (XINT (tem, 1))
+ {
+ case CRIS_UNSPEC_GOTREAD:
+ case CRIS_UNSPEC_PLTGOTREAD:
+ /* Using sign-extend mostly to be consistent with the
+ indexed addressing mode. */
+ if (flag_pic == 1)
+ return "movs.w %1,%0";
+ return "move.d %1,%0";
+
+ case CRIS_UNSPEC_GOTREL:
+ case CRIS_UNSPEC_PLT_GOTREL:
+ gcc_assert (!TARGET_V32);
+ return "move.d %1,%0";
+
+ case CRIS_UNSPEC_PCREL:
+ case CRIS_UNSPEC_PLT_PCREL:
+ gcc_assert (TARGET_V32);
+ return "lapc %1,%0";
+
+ default:
+ gcc_unreachable ();
+ }
+ }
default:
- return \"BOGUS: %1 to %0\";
+ return "BOGUS: %1 to %0";
}
-}"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no")])
+}
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no,yes,yes,no,no")
+ (set_attr "cc" "*,*,*,*,*,*,*,*,*,*,*,none,none,none,none")])
;; Extend operations with side-effect from mem to register, using
;; MOVS/MOVU. These are from mem to register only.
@@ -1079,13 +1249,11 @@
#
mov%e5.%m5 [%4=%3+%1%T2],%0")
-;; QImode to SImode
-
-(define_insn "*ext_sideqisi_biap"
+(define_insn "*ext_sidesi_biap"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI
5 "cris_extend_operator"
- [(mem:QI (plus:SI
+ [(mem:BW (plus:SI
(mult:SI (match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "n,n"))
(match_operand:SI 3 "register_operand" "r,r")))]))
@@ -1096,112 +1264,67 @@
"cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
"@
#
- mov%e5.%m5 [%4=%3+%1%T2],%0")
+ mov%e5 [%4=%3+%1%T2],%0")
+
+;; Same but [rx=ry+i]
-;; HImode to SImode
-
-(define_insn "*ext_sidehisi_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operator:SI
- 5 "cris_extend_operator"
- [(mem:HI (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "r,r")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (match_operand:SI 3 "register_operand" "r,r")))]))
- (set (match_operand:SI 4 "register_operand" "=*3,r")
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
- (match_dup 3)))]
- "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)"
- "@
- #
- mov%e5.%m5 [%4=%3+%1%T2],%0")
-
-;; Same but [rx=ry+i]
-
-;; QImode to HImode
+;; QImode to HImode
(define_insn "*ext_sideqihi"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
(match_operator:HI
4 "cris_extend_operator"
[(mem:QI (plus:SI
- (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
- (plus:SI (match_dup 1)
- (match_dup 2)))]
- "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 127
- || INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"mov%e4.%m4 [%3=%1%S2],%0\";
-}")
-
-;; QImode to SImode
-
-(define_insn "*ext_sideqisi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (match_operator:SI
- 4 "cris_extend_operator"
- [(mem:QI (plus:SI
- (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
+ (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
+ (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
"cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[2])
|| INTVAL (operands[2]) > 127
|| INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"mov%e4.%m4 [%3=%1%S2],%0\";
-}")
-
-;; HImode to SImode
-
-(define_insn "*ext_sidehisi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "mov%e4.%m4 [%3=%2%S1],%0";
+ return "mov%e4.%m4 [%3=%1%S2],%0";
+})
+
+(define_insn "*ext_sidesi"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
(match_operator:SI
4 "cris_extend_operator"
- [(mem:HI (plus:SI
- (match_operand:SI 1 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 3 "register_operand" "=*1,r,r")
+ [(mem:BW (plus:SI
+ (match_operand:SI 1 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
+ (set (match_operand:SI 3 "register_operand" "=*1,r,r,*2,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
"cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[2]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[2])
|| INTVAL (operands[2]) > 127
|| INTVAL (operands[2]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
- return \"#\";
- return \"mov%e4.%m4 [%3=%1%S2],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "mov%e4 [%3=%2%S1],%0";
+ return "mov%e4 [%3=%1%S2],%0";
+})
;; FIXME: See movsi.
(define_insn "movhi"
[(set
- (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,Q>,r,Q>,r,r,r,g,g,r")
- (match_operand:HI 1 "general_operand" "r,Q>,M,M,I,r,L,O,n,M,r,g"))]
+ (match_operand:HI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,r,r,r,g,g,r,r,x")
+ (match_operand:HI 1 "general_operand" "r,Q>,M,M, I,r, L,O,n,M,r,g,x,r"))]
""
- "*
{
switch (which_alternative)
{
@@ -1210,39 +1333,39 @@
case 5:
case 10:
case 11:
- return \"move.w %1,%0\";
+ return "move.w %1,%0";
+ case 12:
+ case 13:
+ return "move %1,%0";
case 2:
case 3:
case 9:
- return \"clear.w %0\";
+ return "clear.w %0";
case 4:
- return \"moveq %1,%0\";
+ return "moveq %1,%0";
case 6:
case 8:
if (INTVAL (operands[1]) < 256 && INTVAL (operands[1]) >= -128)
{
if (INTVAL (operands[1]) > 0)
- return \"movu.b %1,%0\";
- return \"movs.b %1,%0\";
+ return "movu.b %1,%0";
+ return "movs.b %1,%0";
}
- return \"move.w %1,%0\";
+ return "move.w %1,%0";
case 7:
- return \"movEq %b1,%0\";
+ return "movEq %b1,%0";
default:
- return \"BOGUS: %1 to %0\";
+ return "BOGUS: %1 to %0";
}
-}"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no")
- (set (attr "cc")
- (if_then_else (eq_attr "alternative" "7")
- (const_string "clobber")
- (const_string "normal")))])
+}
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,yes,no,no,no,no,yes,yes")
+ (set_attr "cc" "*,*,none,none,*,none,*,clobber,*,none,none,*,none,none")])
(define_insn "movstricthi"
[(set
(strict_low_part
- (match_operand:HI 0 "nonimmediate_operand" "+r,r,r,Q>,Q>,g,r,g"))
- (match_operand:HI 1 "general_operand" "r,Q>,M,M,r,M,g,r"))]
+ (match_operand:HI 0 "nonimmediate_operand" "+r,r, r,Q>,Q>,g,r,g"))
+ (match_operand:HI 1 "general_operand" "r,Q>,M,M, r, M,g,r"))]
""
"@
move.w %1,%0
@@ -1254,10 +1377,26 @@
move.w %1,%0
move.w %1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
+
+(define_expand "reload_in"
+ [(set (match_operand:BW 2 "register_operand" "=r")
+ (match_operand:BW 1 "memory_operand" "m"))
+ (set (match_operand:BW 0 "register_operand" "=x")
+ (match_dup 2))]
+ ""
+ "")
+
+(define_expand "reload_out"
+ [(set (match_operand:BW 2 "register_operand" "=&r")
+ (match_operand:BW 1 "register_operand" "x"))
+ (set (match_operand:BW 0 "memory_operand" "=m")
+ (match_dup 2))]
+ ""
+ "")
(define_insn "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r,r,Q>,r,g,g,r,r")
- (match_operand:QI 1 "general_operand" "r,r,Q>,M,M,I,M,r,O,g"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,r,g,g,r,r,r,x")
+ (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, I,M,r,O,g,x,r"))]
""
"@
move.b %1,%0
@@ -1269,17 +1408,16 @@
clear.b %0
move.b %1,%0
moveq %b1,%0
- move.b %1,%0"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no")
- (set (attr "cc")
- (if_then_else (eq_attr "alternative" "8")
- (const_string "clobber")
- (const_string "normal")))])
+ move.b %1,%0
+ move %1,%0
+ move %1,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,yes,no,yes,yes")
+ (set_attr "cc" "*,*,*,*,*,*,*,*,clobber,*,none,none")])
(define_insn "movstrictqi"
[(set (strict_low_part
- (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r,r,Q>,g,g,r"))
- (match_operand:QI 1 "general_operand" "r,r,Q>,M,M,M,r,g"))]
+ (match_operand:QI 0 "nonimmediate_operand" "+r,Q>,r, r,Q>,g,g,r"))
+ (match_operand:QI 1 "general_operand" "r,r, Q>,M,M, M,r,g"))]
""
"@
move.b %1,%0
@@ -1298,8 +1436,8 @@
;; It will use clear, so we know ALL types of immediate 0 never change cc.
(define_insn "movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r,r,Q>,g,g,r")
- (match_operand:SF 1 "general_operand" "r,r,Q>,G,G,G,r,g"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,Q>,r, r,Q>,g,g,r,r,x,Q>,m,x, x")
+ (match_operand:SF 1 "general_operand" "r,r, Q>,G,G, G,r,g,x,r,x, x,Q>,g"))]
""
"@
move.d %1,%0
@@ -1309,8 +1447,101 @@
clear.d %0
clear.d %0
move.d %1,%0
- move.d %1,%0"
- [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
+ move.d %1,%0
+ move %1,%0
+ move %1,%0
+ move %1,%0
+ move %1,%0
+ move %1,%0
+ move %1,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")])
+
+;; Movem patterns. Primarily for use in function prologue and epilogue.
+;; The V32 variants have an ordering matching the expectations of the
+;; standard names "load_multiple" and "store_multiple"; pre-v32 movem
+;; store R0 in the highest memory location.
+
+(define_expand "load_multiple"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "memory_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_V32"
+{
+ rtx indreg;
+
+ /* Apparently the predicate isn't checked, so we need to do so
+ manually. Once happened for libstdc++-v3 locale_facets.tcc. */
+ if (!MEM_P (operands[1]))
+ FAIL;
+
+ indreg = XEXP (operands[1], 0);
+
+ if (GET_CODE (indreg) == POST_INC)
+ indreg = XEXP (indreg, 0);
+ if (!REG_P (indreg)
+ || GET_CODE (operands[2]) != CONST_INT
+ || !REG_P (operands[0])
+ || REGNO (operands[0]) != 0
+ || INTVAL (operands[2]) > CRIS_SP_REGNUM
+ || (int) REGNO (indreg) < INTVAL (operands[2]))
+ FAIL;
+ gcc_unreachable ();
+ emit_insn (cris_gen_movem_load (operands[1], operands[2], 0));
+ DONE;
+})
+
+(define_expand "store_multiple"
+ [(match_operand:SI 0 "memory_operand" "")
+ (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_V32"
+{
+ rtx indreg;
+
+ /* See load_multiple. */
+ if (!MEM_P (operands[0]))
+ FAIL;
+
+ indreg = XEXP (operands[0], 0);
+
+ if (GET_CODE (indreg) == POST_INC)
+ indreg = XEXP (indreg, 0);
+ if (!REG_P (indreg)
+ || GET_CODE (operands[2]) != CONST_INT
+ || !REG_P (operands[1])
+ || REGNO (operands[1]) != 0
+ || INTVAL (operands[2]) > CRIS_SP_REGNUM
+ || (int) REGNO (indreg) < INTVAL (operands[2]))
+ FAIL;
+ gcc_unreachable ();
+ cris_emit_movem_store (operands[0], operands[2], 0, false);
+ DONE;
+})
+
+(define_insn "*cris_load_multiple"
+ [(match_parallel 0 "cris_load_multiple_op"
+ [(set (match_operand:SI 1 "register_operand" "=r,r")
+ (match_operand:SI 2 "memory_operand" "Q,m"))])]
+ ""
+ "movem %O0,%o0"
+ [(set_attr "cc" "none")
+ (set_attr "slottable" "yes,no")
+ ;; Not true, but setting the length to 0 causes return sequences (ret
+ ;; movem) to have the cost they had when (return) included the movem
+ ;; and reduces the performance penalty taken for needing to emit an
+ ;; epilogue (in turn copied by bb-reorder) instead of return patterns.
+ ;; FIXME: temporary change until all insn lengths are correctly
+ ;; described. FIXME: have better target control over bb-reorder.
+ (set_attr "length" "0")])
+
+(define_insn "*cris_store_multiple"
+ [(match_parallel 0 "cris_store_multiple_op"
+ [(set (match_operand:SI 2 "memory_operand" "=Q,m")
+ (match_operand:SI 1 "register_operand" "r,r"))])]
+ ""
+ "movem %o0,%O0"
+ [(set_attr "cc" "none")
+ (set_attr "slottable" "yes,no")])
;; Sign- and zero-extend insns with standard names.
@@ -1325,33 +1556,20 @@
""
"move.d %1,%M0\;smi %H0\;neg.d %H0,%H0")
-(define_insn "extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (sign_extend:DI (match_operand:HI 1 "general_operand" "g")))]
- ""
- "movs.w %1,%M0\;smi %H0\;neg.d %H0,%H0")
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (sign_extend:SI (match_operand:HI 1 "general_operand" "r,Q>,g")))]
- ""
- "movs.w %1,%0"
- [(set_attr "slottable" "yes,yes,no")])
-
-(define_insn "extendqidi2"
+(define_insn "extenddi2"
[(set (match_operand:DI 0 "register_operand" "=r")
- (sign_extend:DI (match_operand:QI 1 "general_operand" "g")))]
+ (sign_extend:DI (match_operand:BW 1 "general_operand" "g")))]
""
- "movs.b %1,%M0\;smi %H0\;neg.d %H0,%H0")
+ "movs %1,%M0\;smi %H0\;neg.d %H0,%H0")
-(define_insn "extendqisi2"
+(define_insn "extendsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (sign_extend:SI (match_operand:QI 1 "general_operand" "r,Q>,g")))]
+ (sign_extend:SI (match_operand:BW 1 "general_operand" "r,Q>,g")))]
""
- "movs.b %1,%0"
+ "movs %1,%0"
[(set_attr "slottable" "yes,yes,no")])
-;; To do a byte->word exension, extend to dword, exept that the top half
+;; To do a byte->word extension, extend to dword, exept that the top half
;; of the register will be clobbered. FIXME: Perhaps this is not needed.
(define_insn "extendqihi2"
@@ -1365,20 +1583,12 @@
;; Zero-extend. The DImode ones are synthesized by gcc, so we don't
;; specify them here.
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "r,Q>,m")))]
- ""
- "movu.w %1,%0"
- [(set_attr "slottable" "yes,yes,no")])
-
-(define_insn "zero_extendqisi2"
+(define_insn "zero_extendsi2"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(zero_extend:SI
- (match_operand:QI 1 "nonimmediate_operand" "r,Q>,m")))]
+ (match_operand:BW 1 "nonimmediate_operand" "r,Q>,m")))]
""
- "movu.b %1,%0"
+ "movu %1,%0"
[(set_attr "slottable" "yes,yes,no")])
;; Same comment as sign-extend QImode to HImode above applies.
@@ -1399,59 +1609,16 @@
;; op.S [rx=ry+I],rz; (add, sub, or, and, bound).
;;
;; [rx=ry+rz.S]
-;; FIXME: These could have anonymous mode for operand 0.
-
-;; QImode
-
-(define_insn "*op_sideqi_biap"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (match_operator:QI
- 6 "cris_orthogonal_operator"
- [(match_operand:QI 1 "register_operand" "0,0")
- (mem:QI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x6.%s0 [%5=%4+%2%T3],%0")
-
-;; HImode
-
-(define_insn "*op_sidehi_biap"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (match_operator:HI
- 6 "cris_orthogonal_operator"
- [(match_operand:HI 1 "register_operand" "0,0")
- (mem:HI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x6.%s0 [%5=%4+%2%T3],%0")
-
-;; SImode
-(define_insn "*op_sidesi_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operator:SI
+(define_insn "*op_side_biap"
+ [(set (match_operand:BWD 0 "register_operand" "=r,r")
+ (match_operator:BWD
6 "cris_orthogonal_operator"
- [(match_operand:SI 1 "register_operand" "0,0")
- (mem:SI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))]))
+ [(match_operand:BWD 1 "register_operand" "0,0")
+ (mem:BWD (plus:SI
+ (mult:SI (match_operand:SI 2 "register_operand" "r,r")
+ (match_operand:SI 3 "const_int_operand" "n,n"))
+ (match_operand:SI 4 "register_operand" "r,r")))]))
(set (match_operand:SI 5 "register_operand" "=*4,r")
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
@@ -1459,88 +1626,34 @@
"cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
- %x6.%s0 [%5=%4+%2%T3],%0")
+ %x6 [%5=%4+%2%T3],%0")
;; [rx=ry+i] ([%4=%2+%3])
-;; FIXME: These could have anonymous mode for operand 0.
-
-;; QImode
-
-(define_insn "*op_sideqi"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r")
- (match_operator:QI
- 5 "cris_orthogonal_operator"
- [(match_operand:QI 1 "register_operand" "0,0,0")
- (mem:QI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
-
-;; HImode
-
-(define_insn "*op_sidehi"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (match_operator:HI
- 5 "cris_orthogonal_operator"
- [(match_operand:HI 1 "register_operand" "0,0,0")
- (mem:HI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
-
-;; SImode
-(define_insn "*op_sidesi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (match_operator:SI
+(define_insn "*op_side"
+ [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r")
+ (match_operator:BWD
5 "cris_orthogonal_operator"
- [(match_operand:SI 1 "register_operand" "0,0,0")
- (mem:SI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ [(match_operand:BWD 1 "register_operand" "0,0,0,0,0")
+ (mem:BWD (plus:SI
+ (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))]))
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
"cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "%x5.%s0 [%4=%3%S2],%0";
+ return "%x5 [%4=%2%S3],%0";
+})
;; To match all cases for commutative operations we may have to have the
;; following pattern for add, or & and. I do not know really, but it does
@@ -1551,59 +1664,16 @@
;; op.S [rx=ry+I],rz;
;;
;; [rx=ry+rz.S]
-;; FIXME: These could have anonymous mode for operand 0.
-
-;; QImode
-
-(define_insn "*op_swap_sideqi_biap"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (match_operator:QI
- 6 "cris_commutative_orth_op"
- [(mem:QI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))
- (match_operand:QI 1 "register_operand" "0,0")]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x6.%s0 [%5=%4+%2%T3],%0")
-
-;; HImode
-
-(define_insn "*op_swap_sidehi_biap"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (match_operator:HI
- 6 "cris_commutative_orth_op"
- [(mem:HI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))
- (match_operand:HI 1 "register_operand" "0,0")]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x6.%s0 [%5=%4+%2%T3],%0")
-
-;; SImode
-(define_insn "*op_swap_sidesi_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operator:SI
+(define_insn "*op_swap_side_biap"
+ [(set (match_operand:BWD 0 "register_operand" "=r,r")
+ (match_operator:BWD
6 "cris_commutative_orth_op"
- [(mem:SI (plus:SI
+ [(mem:BWD (plus:SI
(mult:SI (match_operand:SI 2 "register_operand" "r,r")
(match_operand:SI 3 "const_int_operand" "n,n"))
(match_operand:SI 4 "register_operand" "r,r")))
- (match_operand:SI 1 "register_operand" "0,0")]))
+ (match_operand:BWD 1 "register_operand" "0,0")]))
(set (match_operand:SI 5 "register_operand" "=*4,r")
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
@@ -1611,99 +1681,58 @@
"cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
- %x6.%s0 [%5=%4+%2%T3],%0")
+ %x6 [%5=%4+%2%T3],%0")
;; [rx=ry+i] ([%4=%2+%3])
;; FIXME: These could have anonymous mode for operand 0.
;; QImode
-(define_insn "*op_swap_sideqi"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r")
- (match_operator:QI
- 5 "cris_commutative_orth_op"
- [(mem:QI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))
- (match_operand:QI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
-
-;; HImode
-
-(define_insn "*op_swap_sidehi"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (match_operator:HI
- 5 "cris_commutative_orth_op"
- [(mem:HI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))
- (match_operand:HI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
-
-;; SImode
-
-(define_insn "*op_swap_sidesi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (match_operator:SI
+(define_insn "*op_swap_side"
+ [(set (match_operand:BWD 0 "register_operand" "=r,r,r,r,r")
+ (match_operator:BWD
5 "cris_commutative_orth_op"
- [(mem:SI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))
- (match_operand:SI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ [(mem:BWD
+ (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))
+ (match_operand:BWD 1 "register_operand" "0,0,0,0,0")]))
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
"cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5.%s0 [%4=%2%S3],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "%x5 [%4=%3%S2],%0";
+ return "%x5 [%4=%2%S3],%0";
+})
;; Add operations, standard names.
;; Note that for the 'P' constraint, the high part can be -1 or 0. We
;; output the insn through the 'A' output modifier as "adds.w" and "addq",
;; respectively.
-(define_insn "adddi3"
+(define_expand "adddi3"
+ [(set (match_operand:DI 0 "register_operand")
+ (plus:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "general_operand")))]
+ ""
+{
+ if (MEM_P (operands[2]) && TARGET_V32)
+ operands[2] = force_reg (DImode, operands[2]);
+})
+
+(define_insn "*adddi3_non_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
(plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r")
(match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
- ""
+ "!TARGET_V32"
"@
addq %2,%M0\;ax\;addq 0,%H0
subq %n2,%M0\;ax\;subq 0,%H0
@@ -1711,64 +1740,141 @@
add.d %M2,%M0\;ax\;add.d %H2,%H0
add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0")
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r")
+; It seems no use allowing a memory operand for this one, because we'd
+; need a scratch register for incrementing the address.
+(define_insn "*adddi3_v32"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:DI 2 "nonmemory_operand" "J,N,P,r,n")))]
+ "TARGET_V32"
+ "@
+ addq %2,%M0\;addc 0,%H0
+ subq %n2,%M0\;ax\;subq 0,%H0
+ add%e2.%z2 %2,%M0\;addc %H2,%H0
+ add.d %M2,%M0\;addc %H2,%H0
+ add.d %M2,%M0\;addc %H2,%H0")
+
+(define_expand "add3"
+ [(set (match_operand:BWD 0 "register_operand")
+ (plus:BWD
+ (match_operand:BWD 1 "register_operand")
+ (match_operand:BWD 2 "general_operand")))]
+ ""
+ "")
+
+(define_insn "*addsi3_non_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r,r, r")
(plus:SI
- (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r")
- (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,g,!To,0")))]
+ (match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0, 0,r, r")
+ (match_operand:SI 2 "general_operand" "r,Q>,J,N,n,!S,g,!To,0")))]
;; The last constraint is due to that after reload, the '%' is not
;; honored, and canonicalization doesn't care about keeping the same
;; register as in destination. This will happen after insn splitting.
;; gcc <= 2.7.2. FIXME: Check for gcc-2.9x
- ""
- "*
+ "!TARGET_V32"
{
switch (which_alternative)
{
case 0:
case 1:
- return \"add.d %2,%0\";
+ return "add.d %2,%0";
case 2:
- return \"addq %2,%0\";
+ return "addq %2,%0";
case 3:
- return \"subq %n2,%0\";
+ return "subq %n2,%0";
case 4:
/* 'Known value', but not in -63..63.
Check if addu/subu may be used. */
if (INTVAL (operands[2]) > 0)
{
if (INTVAL (operands[2]) < 256)
- return \"addu.b %2,%0\";
+ return "addu.b %2,%0";
if (INTVAL (operands[2]) < 65536)
- return \"addu.w %2,%0\";
+ return "addu.w %2,%0";
}
else
{
if (INTVAL (operands[2]) >= -255)
- return \"subu.b %n2,%0\";
+ return "subu.b %n2,%0";
if (INTVAL (operands[2]) >= -65535)
- return \"subu.w %n2,%0\";
+ return "subu.w %n2,%0";
}
- return \"add.d %2,%0\";
- case 6:
- return \"add.d %2,%1,%0\";
+ return "add.d %2,%0";
case 5:
- return \"add.d %2,%0\";
+ {
+ rtx tem = operands[2];
+ gcc_assert (GET_CODE (tem) == CONST);
+ tem = XEXP (tem, 0);
+ if (GET_CODE (tem) == PLUS
+ && GET_CODE (XEXP (tem, 0)) == UNSPEC
+ /* We don't allow CRIS_UNSPEC_PCREL here; we can't have a
+ pc-relative operand in an add insn. */
+ && XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
+ && CONST_INT_P (XEXP (tem, 1)))
+ tem = XEXP (tem, 0);
+ gcc_assert (GET_CODE (tem) == UNSPEC);
+ switch (XINT (tem, 1))
+ {
+ case CRIS_UNSPEC_GOTREAD:
+ case CRIS_UNSPEC_PLTGOTREAD:
+ /* Using sign-extend mostly to be consistent with the
+ indexed addressing mode. */
+ if (flag_pic == 1)
+ return "adds.w %2,%0";
+ return "add.d %2,%0";
+
+ case CRIS_UNSPEC_PLT_GOTREL:
+ case CRIS_UNSPEC_GOTREL:
+ return "add.d %2,%0";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ case 6:
+ return "add%u2 %2,%0";
case 7:
- return \"add.d %1,%0\";
+ return "add.d %2,%1,%0";
+ case 8:
+ return "add.d %1,%0";
default:
- return \"BOGUS addsi %2+%1 to %0\";
+ return "BOGUS addsi %2+%1 to %0";
}
-}"
- [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,yes")])
+}
+ [(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no,yes")])
+
+; FIXME: Check what's best: having the three-operand ACR alternative
+; before or after the corresponding-operand2 alternative. Check for
+; *all* insns. FIXME: constant constraint letter for -128..127.
+(define_insn "*addsi3_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,!a,r,r,r,!a")
+ (plus:SI
+ (match_operand:SI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r, 0,0,0,r")
+ (match_operand:SI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,L,L, P,n,g,g")))]
+ "TARGET_V32"
+ "@
+ add.d %2,%0
+ addi %2.b,%1,%0
+ add.d %2,%0
+ addo.d %2,%1,%0
+ addq %2,%0
+ subq %n2,%0
+ addoq %2,%1,%0
+ adds.w %2,%0
+ addo %2,%1,%0
+ addu.w %2,%0
+ add.d %2,%0
+ add%u2 %2,%0
+ addo.%Z2 %2,%1,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no,no,no,no,no")
+ (set_attr "cc" "*,none,*,none,*,*,none,*,*,*,*,*,none")])
-(define_insn "addhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,r")
- (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
- ""
+(define_insn "*addhi3_non_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
+ (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
+ "!TARGET_V32"
"@
add.w %2,%0
add.w %2,%0
@@ -1779,11 +1885,30 @@
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r,r")
- (plus:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,r")
- (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))]
- ""
+(define_insn "*addhi3_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r, !a,r,!a, r,r,!a,r,!a")
+ (plus:HI
+ (match_operand:HI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r")
+ (match_operand:HI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,g,g")))]
+ "TARGET_V32"
+ "@
+ add.w %2,%0
+ addi %2.b,%1,%0
+ add.w %2,%0
+ addo.w %2,%1,%0
+ addq %2,%0
+ subq %n2,%0
+ addoq %2,%1,%0
+ add.w %2,%0
+ addo.w %2,%1,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no")
+ (set_attr "cc" "*,none,*,none,clobber,clobber,none,*,none")])
+
+(define_insn "*addqi3_non_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r")
+ (plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r")
+ (match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))]
+ "!TARGET_V32"
"@
add.b %2,%0
add.b %2,%0
@@ -1794,6 +1919,26 @@
add.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,clobber,normal,normal")])
+
+(define_insn "*addqi3_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,r,!a")
+ (plus:QI
+ (match_operand:QI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,0,r")
+ (match_operand:QI 2 "general_operand" "r,r, Q>,Q>,J,N,NJ,O,g,g")))]
+ "TARGET_V32"
+ "@
+ add.b %2,%0
+ addi %2.b,%1,%0
+ add.b %2,%0
+ addo.b %2,%1,%0
+ addq %2,%0
+ subq %n2,%0
+ addoq %2,%1,%0
+ subQ -%b2,%0
+ add.b %2,%0
+ addo.b %2,%1,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,yes,no,no")
+ (set_attr "cc" "*,none,*,none,clobber,clobber,none,clobber,*,none")])
;; Subtract.
;;
@@ -1803,11 +1948,21 @@
;; Note that for the 'P' constraint, the high part can be -1 or 0. We
;; output the insn through the 'D' output modifier as "subs.w" and "subq",
;; respectively.
-(define_insn "subdi3"
+(define_expand "subdi3"
+ [(set (match_operand:DI 0 "register_operand")
+ (minus:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "general_operand")))]
+ ""
+{
+ if (TARGET_V32 && MEM_P (operands[2]))
+ operands[2] = force_reg (DImode, operands[2]);
+})
+
+(define_insn "*subdi3_non_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
(minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r")
(match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
- ""
+ "!TARGET_V32"
"@
subq %2,%M0\;ax\;subq 0,%H0
addq %n2,%M0\;ax\;addq 0,%H0
@@ -1815,12 +1970,31 @@
sub.d %M2,%M0\;ax\;sub.d %H2,%H0
sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0")
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r")
- (minus:SI
- (match_operand:SI 1 "register_operand" "0,0,0,0,0,0,0,r")
- (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))]
+(define_insn "*subdi3_v32"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r,&r")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0")
+ (match_operand:DI 2 "nonmemory_operand" "J,N,P,r")))]
+ "TARGET_V32"
+ "@
+ subq %2,%M0\;ax\;subq 0,%H0
+ addq %n2,%M0\;ax\;addq 0,%H0
+ sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0
+ sub.d %M2,%M0\;ax\;sub.d %H2,%H0")
+
+(define_expand "sub3"
+ [(set (match_operand:BWD 0 "register_operand")
+ (minus:BWD
+ (match_operand:BWD 1 "register_operand")
+ (match_operand:BWD 2 "general_operand")))]
""
+ "")
+
+(define_insn "*subsi3_non_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r")
+ (minus:SI
+ (match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r")
+ (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))]
+ "!TARGET_V32"
;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative.
;; But then again, %2 should not be negative.
@@ -1835,36 +2009,51 @@
sub.d %2,%0
sub.d %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no")])
+
+(define_insn "*subsi3_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
+ (minus:SI
+ (match_operand:SI 1 "register_operand" "0,0,0,0,0,0,0")
+ (match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g")))]
+ "TARGET_V32"
+ "@
+ sub.d %2,%0
+ sub.d %2,%0
+ subq %2,%0
+ addq %n2,%0
+ sub%e2.%z2 %2,%0
+ sub.d %2,%0
+ sub.d %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,no,no,no")])
-(define_insn "subhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,r")
- (match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
- ""
+(define_insn "*sub3_nonv32"
+ [(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r")
+ (minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r")
+ (match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To")))]
+ "!TARGET_V32"
"@
- sub.w %2,%0
- sub.w %2,%0
+ sub %2,%0
+ sub %2,%0
subq %2,%0
addq %n2,%0
- sub.w %2,%0
- sub.w %2,%1,%0"
+ sub %2,%0
+ sub %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r")
- (minus:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,r")
- (match_operand:QI 2 "general_operand" "r,Q>,J,N,g,!To")))]
- ""
+(define_insn "*sub3_v32"
+ [(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r")
+ (minus:BW (match_operand:BW 1 "register_operand" "0,0,0,0,0")
+ (match_operand:BW 2 "general_operand" "r,Q>,J,N,g")))]
+ "TARGET_V32"
"@
- sub.b %2,%0
- sub.b %2,%0
+ sub %2,%0
+ sub %2,%0
subq %2,%0
- addq %2,%0
- sub.b %2,%0
- sub.b %2,%1,%0"
- [(set_attr "slottable" "yes,yes,yes,yes,no,no")
- (set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
+ addq %n2,%0
+ sub %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,no")
+ (set_attr "cc" "normal,normal,clobber,clobber,normal")])
;; CRIS has some add/sub-with-sign/zero-extend instructions.
;; Although these perform sign/zero-extension to SImode, they are
@@ -1878,7 +2067,6 @@
;; ADDS/SUBS/ADDU/SUBU and BOUND, which needs a check for zero_extend
;;
;; adds/subs/addu/subu bound [rx=ry+rz.S]
-;; FIXME: These could have anonymous mode for operand 0.
;; QImode to HImode
;; FIXME: GCC should widen.
@@ -1886,7 +2074,7 @@
(define_insn "*extopqihi_side_biap"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI
- 6 "cris_operand_extend_operator"
+ 6 "cris_additive_operand_extend_operator"
[(match_operand:HI 1 "register_operand" "0,0")
(match_operator:HI
7 "cris_extend_operator"
@@ -1898,22 +2086,19 @@
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
(match_dup 4)))]
- "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
+ "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
%x6%e7.%m7 [%5=%4+%2%T3],%0")
-;; QImode to SImode
-
-(define_insn "*extopqisi_side_biap"
+(define_insn "*extopsi_side_biap"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI
6 "cris_operand_extend_operator"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operator:SI
7 "cris_extend_operator"
- [(mem:QI (plus:SI
+ [(mem:BW (plus:SI
(mult:SI (match_operand:SI 2 "register_operand" "r,r")
(match_operand:SI 3 "const_int_operand" "n,n"))
(match_operand:SI 4 "register_operand" "r,r")))])]))
@@ -1921,192 +2106,109 @@
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
(match_dup 4)))]
- "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
+ "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
&& cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
- %x6%e7.%m7 [%5=%4+%2%T3],%0")
+ %x6%e7 [%5=%4+%2%T3],%0")
+
-;; HImode to SImode
-
-(define_insn "*extophisi_side_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operator:SI
- 6 "cris_operand_extend_operator"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operator:SI
- 7 "cris_extend_operator"
- [(mem:HI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))])]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[7]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x6%e7.%m7 [%5=%4+%2%T3],%0")
-
-
-;; [rx=ry+i]
-;; FIXME: These could have anonymous mode for operand 0.
+;; [rx=ry+i]
;; QImode to HImode
(define_insn "*extopqihi_side"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
(match_operator:HI
- 5 "cris_operand_extend_operator"
- [(match_operand:HI 1 "register_operand" "0,0,0")
+ 5 "cris_additive_operand_extend_operator"
+ [(match_operand:HI 1 "register_operand" "0,0,0,0,0")
(match_operator:HI
6 "cris_extend_operator"
[(mem:QI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")
- ))])]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5%e6.%m6 [%4=%2%S3],%0\";
-}")
-
-;; QImode to SImode
-
-(define_insn "*extopqisi_side"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (match_operator:SI
- 5 "cris_operand_extend_operator"
- [(match_operand:SI 1 "register_operand" "0,0,0")
- (match_operator:SI
- 6 "cris_extend_operator"
- [(mem:QI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")
+ (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")
))])]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
-
- "(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
+ "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5%e6.%m6 [%4=%2%S3],%0\";
-}")
-
-;; HImode to SImode
-
-(define_insn "*extophisi_side"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "%x5%E6.%m6 [%4=%3%S2],%0";
+ return "%x5%E6.%m6 [%4=%2%S3],%0";
+})
+
+(define_insn "*extopsi_side"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
(match_operator:SI
5 "cris_operand_extend_operator"
- [(match_operand:SI 1 "register_operand" "0,0,0")
+ [(match_operand:SI 1 "register_operand" "0,0,0,0,0")
(match_operator:SI
6 "cris_extend_operator"
- [(mem:HI
- (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")
+ [(mem:BW
+ (plus:SI (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")
))])]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
"(GET_CODE (operands[5]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
&& cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x5%e6.%m6 [%4=%2%S3],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "%x5%E6 [%4=%3%S2],%0";
+ return "%x5%E6 [%4=%2%S3],%0";
+})
;; As with op.S we may have to add special pattern to match commuted
-;; operands to adds/addu and bound
+;; operands to adds/addu and bound
;;
;; adds/addu/bound [rx=ry+rz.S]
;; QImode to HImode
;; FIXME: GCC should widen.
-;; FIXME: These could have anonymous mode for operand 0.
(define_insn "*extopqihi_swap_side_biap"
[(set (match_operand:HI 0 "register_operand" "=r,r")
- (match_operator:HI
- 7 "cris_plus_or_bound_operator"
- [(match_operator:HI
- 6 "cris_extend_operator"
- [(mem:QI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))])
- (match_operand:HI 1 "register_operand" "0,0")]))
- (set (match_operand:SI 5 "register_operand" "=*4,r")
- (plus:SI (mult:SI (match_dup 2)
- (match_dup 3))
- (match_dup 4)))]
- "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
- "@
- #
- %x7%e6.%m6 [%5=%4+%2%T3],%0")
-
-;; QImode to SImode
-
-(define_insn "*extopqisi_swap_side_biap"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (match_operator:SI
- 7 "cris_plus_or_bound_operator"
- [(match_operator:SI
- 6 "cris_extend_operator"
- [(mem:QI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r,r")
- (match_operand:SI 3 "const_int_operand" "n,n"))
- (match_operand:SI 4 "register_operand" "r,r")))])
- (match_operand:SI 1 "register_operand" "0,0")]))
+ (plus:HI
+ (match_operator:HI
+ 6 "cris_extend_operator"
+ [(mem:QI (plus:SI
+ (mult:SI (match_operand:SI 2 "register_operand" "r,r")
+ (match_operand:SI 3 "const_int_operand" "n,n"))
+ (match_operand:SI 4 "register_operand" "r,r")))])
+ (match_operand:HI 1 "register_operand" "0,0")))
(set (match_operand:SI 5 "register_operand" "=*4,r")
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
(match_dup 4)))]
- "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
+ "cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
- %x7%e6.%m6 [%5=%4+%2%T3],%0")
+ add%e6.b [%5=%4+%2%T3],%0")
-;; HImode to SImode
-(define_insn "*extophisi_swap_side_biap"
+(define_insn "*extopsi_swap_side_biap"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI
7 "cris_plus_or_bound_operator"
[(match_operator:SI
6 "cris_extend_operator"
- [(mem:HI (plus:SI
+ [(mem:BW (plus:SI
(mult:SI (match_operand:SI 2 "register_operand" "r,r")
(match_operand:SI 3 "const_int_operand" "n,n"))
(match_operand:SI 4 "register_operand" "r,r")))])
@@ -2115,232 +2217,240 @@
(plus:SI (mult:SI (match_dup 2)
(match_dup 3))
(match_dup 4)))]
- "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
+ "(GET_CODE (operands[7]) != UMIN || GET_CODE (operands[6]) == ZERO_EXTEND)
&& cris_side_effect_mode_ok (MULT, operands, 5, 4, 2, 3, 0)"
"@
#
- %x7%e6.%m6 [%5=%4+%2%T3],%0")
+ %x7%E6 [%5=%4+%2%T3],%0")
;; [rx=ry+i]
-;; FIXME: These could have anonymous mode for operand 0.
;; FIXME: GCC should widen.
;; QImode to HImode
(define_insn "*extopqihi_swap_side"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (match_operator:HI
- 6 "cris_plus_or_bound_operator"
- [(match_operator:HI
- 5 "cris_extend_operator"
- [(mem:QI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))])
- (match_operand:HI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
- (plus:SI (match_dup 2)
- (match_dup 3)))]
- "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
-{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[3]) > 127
- || INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x6%e5.%m5 [%4=%2%S3],%0\";
-}")
-
-;; QImode to SImode
-
-(define_insn "*extopqisi_swap_side"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (match_operator:SI
- 6 "cris_plus_or_bound_operator"
- [(match_operator:SI
- 5 "cris_extend_operator"
- [(mem:QI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))])
- (match_operand:SI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r")
+ (plus:HI
+ (match_operator:HI
+ 5 "cris_extend_operator"
+ [(mem:QI (plus:SI
+ (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])
+ (match_operand:HI 1 "register_operand" "0,0,0,0,0")))
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
- "(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND)
- && cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
+ "cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x6%e5.%m5 [%4=%2%S3],%0\";
-}")
-
-;; HImode to SImode
-
-(define_insn "*extophisi_swap_side"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return "add%e5.b [%4=%3%S2],%0";
+ return "add%e5.b [%4=%2%S3],%0";
+})
+
+(define_insn "*extopsi_swap_side"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
(match_operator:SI
6 "cris_plus_or_bound_operator"
[(match_operator:SI
5 "cris_extend_operator"
- [(mem:HI (plus:SI
- (match_operand:SI 2 "cris_bdap_operand" "%r,r,r")
- (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn")))])
- (match_operand:SI 1 "register_operand" "0,0,0")]))
- (set (match_operand:SI 4 "register_operand" "=*2,r,r")
+ [(mem:BW (plus:SI
+ (match_operand:SI 2 "cris_bdap_operand" "%r,r,r,R,R")
+ (match_operand:SI 3 "cris_bdap_operand" "r>Rn,r,>Rn,r,r")))])
+ (match_operand:SI 1 "register_operand" "0,0,0,0,0")]))
+ (set (match_operand:SI 4 "register_operand" "=*2,r,r,*3,r")
(plus:SI (match_dup 2)
(match_dup 3)))]
"(GET_CODE (operands[6]) != UMIN || GET_CODE (operands[5]) == ZERO_EXTEND)
&& cris_side_effect_mode_ok (PLUS, operands, 4, 2, 3, -1, 0)"
- "*
{
- if (which_alternative == 0
- && (GET_CODE (operands[3]) != CONST_INT
+ if ((which_alternative == 0 || which_alternative == 3)
+ && (!CONST_INT_P (operands[3])
|| INTVAL (operands[3]) > 127
|| INTVAL (operands[3]) < -128
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
- return \"#\";
- return \"%x6%e5.%m5 [%4=%2%S3],%0\";
-}")
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'N')
+ || CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'J')))
+ return "#";
+ if (which_alternative == 4)
+ return \"%x6%E5.%m5 [%4=%3%S2],%0\";
+ return "%x6%E5 [%4=%2%S3],%0";
+})
;; Extend versions (zero/sign) of normal add/sub (no side-effects).
-;; FIXME: These could have anonymous mode for operand 0.
;; QImode to HImode
;; FIXME: GCC should widen.
-(define_insn "*extopqihi"
+(define_insn "*extopqihi_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
(match_operator:HI
- 3 "cris_operand_extend_operator"
+ 3 "cris_additive_operand_extend_operator"
[(match_operand:HI 1 "register_operand" "0,0,0,r")
(match_operator:HI
4 "cris_extend_operator"
[(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
+ "!TARGET_V32 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
"@
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%1,%0"
+ %x3%E4.%m4 %2,%0
+ %x3%E4.%m4 %2,%0
+ %x3%E4.%m4 %2,%0
+ %x3%E4.%m4 %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")
(set_attr "cc" "clobber")])
+(define_insn "*extopqihi_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI
+ 3 "cris_additive_operand_extend_operator"
+ [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operator:HI
+ 4 "cris_extend_operator"
+ [(match_operand:QI 2 "nonimmediate_operand" "r,m")])]))]
+ "TARGET_V32"
+ "%x3%e4.%m4 %2,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "clobber")])
+
;; QImode to SImode
-(define_insn "*extopqisi"
+(define_insn "*extopsi_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(match_operator:SI
3 "cris_operand_extend_operator"
[(match_operand:SI 1 "register_operand" "0,0,0,r")
(match_operator:SI
4 "cris_extend_operator"
- [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
+ [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
+ "!TARGET_V32
+ && (GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
"@
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%1,%0"
+ %x3%E4 %2,%0
+ %x3%E4 %2,%0
+ %x3%E4 %2,%0
+ %x3%E4 %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")])
-;; HImode to SImode
-
-(define_insn "*extophisi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+(define_insn "*extopsi_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI
- 3 "cris_operand_extend_operator"
- [(match_operand:SI 1 "register_operand" "0,0,0,r")
+ 3 "cris_additive_operand_extend_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
(match_operator:SI
4 "cris_extend_operator"
- [(match_operand:HI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
- && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
- "@
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%0
- %x3%e4.%m4 %2,%1,%0"
- [(set_attr "slottable" "yes,yes,no,no")])
+ [(match_operand:BW 2 "nonimmediate_operand" "r,m")])]))]
+ "TARGET_V32"
+ "%x3%e4.%m4 %2,%0"
+ [(set_attr "slottable" "yes")])
-
;; As with the side-effect patterns, may have to have swapped operands for add.
-;; FIXME: *should* be redundant to gcc.
+;; For commutative operands, these are the canonical forms.
;; QImode to HImode
-(define_insn "*extopqihi_swap"
+(define_insn "*addxqihi_swap_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
- (match_operator:HI
- 4 "cris_plus_or_bound_operator"
- [(match_operator:HI
- 3 "cris_extend_operator"
- [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
- (match_operand:HI 1 "register_operand" "0,0,0,r")]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
- && operands[1] != frame_pointer_rtx"
+ (plus:HI
+ (match_operator:HI
+ 3 "cris_extend_operator"
+ [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
+ (match_operand:HI 1 "register_operand" "0,0,0,r")))]
+ "!TARGET_V32 && operands[1] != frame_pointer_rtx"
"@
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%1,%0"
+ add%e3.b %2,%0
+ add%e3.b %2,%0
+ add%e3.b %2,%0
+ add%e3.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")
(set_attr "cc" "clobber")])
-;; QImode to SImode
+;; A case for v32, to catch the "addo" insn in addition to "adds". We
+;; only care to match the canonical form; there should be no other.
-(define_insn "*extopqisi_swap"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operator:SI
- 4 "cris_plus_or_bound_operator"
- [(match_operator:SI
- 3 "cris_extend_operator"
- [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
- (match_operand:SI 1 "register_operand" "0,0,0,r")]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
- && operands[1] != frame_pointer_rtx"
+(define_insn "*addsbw_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,!a")
+ (plus:HI
+ (sign_extend:HI
+ (match_operand:QI 2 "nonimmediate_operand" "r,m,m"))
+ (match_operand:HI 1 "register_operand" "0,0,r")))]
+ "TARGET_V32"
"@
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%1,%0"
- [(set_attr "slottable" "yes,yes,no,no")])
+ adds.b %2,%0
+ adds.b %2,%0
+ addo.b %2,%1,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "clobber,clobber,none")])
-;; HImode to SImode
+(define_insn "*addubw_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (plus:HI
+ (zero_extend:HI
+ (match_operand:QI 2 "nonimmediate_operand" "r,m"))
+ (match_operand:HI 1 "register_operand" "0,0")))]
+ "TARGET_V32"
+ "addu.b %2,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "clobber")])
-(define_insn "*extophisi_swap"
+(define_insn "*extopsi_swap_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(match_operator:SI
4 "cris_plus_or_bound_operator"
[(match_operator:SI
3 "cris_extend_operator"
- [(match_operand:HI 2 "nonimmediate_operand" "r,Q>,m,!To")])
+ [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
(match_operand:SI 1 "register_operand" "0,0,0,r")]))]
- "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
- && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
+ "!TARGET_V32
+ && (GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
&& operands[1] != frame_pointer_rtx"
"@
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%0
- %x4%e3.%m3 %2,%1,%0"
+ %x4%E3 %2,%0
+ %x4%E3 %2,%0
+ %x4%E3 %2,%0
+ %x4%E3 %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")])
+
+(define_insn "*adds_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,!a")
+ (plus:SI
+ (sign_extend:SI
+ (match_operand:BW 2 "nonimmediate_operand" "r,m,m"))
+ (match_operand:SI 1 "register_operand" "0,0,r")))]
+ "TARGET_V32"
+ "@
+ adds %2,%0
+ adds %2,%0
+ addo %2,%1,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "*,*,none")])
+
+(define_insn "*addu_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI
+ (zero_extend:SI
+ (match_operand:BW 2 "nonimmediate_operand" "r,m"))
+ (match_operand:SI 1 "register_operand" "0,0")))]
+ "TARGET_V32 && operands[1] != frame_pointer_rtx"
+ "addu %2,%0"
+ [(set_attr "slottable" "yes")])
+
+(define_insn "*bound_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umin:SI
+ (zero_extend:SI
+ (match_operand:BW 2 "register_operand" "r"))
+ (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_V32 && operands[1] != frame_pointer_rtx"
+ "bound %2,%0"
+ [(set_attr "slottable" "yes")])
;; This is the special case when we use what corresponds to the
;; instruction above in "casesi". Do *not* change it to use the generic
@@ -2374,11 +2484,29 @@
(pc))
(label_ref (match_operand 2 "" ""))))
(use (label_ref (match_operand 3 "" "")))]
-
- "operands[0] != frame_pointer_rtx"
-
+ "!TARGET_V32 && operands[0] != frame_pointer_rtx"
"adds.w [$pc+%0.w],$pc"
[(set_attr "cc" "clobber")])
+
+;; For V32, we just have a jump, but we need to mark the table as used,
+;; and the jump insn must have the if_then_else form expected by core
+;; GCC. Since we don't want to prolong the lifetime of the original
+;; index value, we compare against "unspec 0". It's a pity we have to
+;; jump through to get the default label in place and to keep the jump
+;; table around. FIXME: Look into it some time.
+
+(define_insn "*casesi_jump_v32"
+ [(set (pc)
+ (if_then_else
+ (ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI)
+ (match_operand:SI 0 "const_int_operand" "n"))
+ (match_operand:SI 1 "register_operand" "r")
+ (label_ref (match_operand 2 "" ""))))
+ (use (label_ref (match_operand 3 "" "")))]
+ "TARGET_V32"
+ "jump %1%#"
+ [(set_attr "cc" "clobber")
+ (set_attr "slottable" "has_slot")])
;; Multiply instructions.
@@ -2396,22 +2524,21 @@
(match_operand:SI 2 "const_int_operand" "n")))]
"operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
- && GET_CODE (operands[2]) == CONST_INT
+ && CONST_INT_P (operands[2])
&& (INTVAL (operands[2]) == 2
|| INTVAL (operands[2]) == 4 || INTVAL (operands[2]) == 3
|| INTVAL (operands[2]) == 5)"
- "*
{
if (INTVAL (operands[2]) == 2)
- return \"lslq 1,%0\";
+ return "lslq 1,%0";
else if (INTVAL (operands[2]) == 4)
- return \"lslq 2,%0\";
+ return "lslq 2,%0";
else if (INTVAL (operands[2]) == 3)
- return \"addi %0.w,%0\";
+ return "addi %0.w,%0";
else if (INTVAL (operands[2]) == 5)
- return \"addi %0.d,%0\";
- return \"BAD: adr_mulsi: %0=%1*%2\";
-}"
+ return "addi %0.d,%0";
+ return "BAD: adr_mulsi: %0=%1*%2";
+}
[(set_attr "slottable" "yes")
;; No flags are changed if this insn is "addi", but it does not seem
;; worth the trouble to distinguish that to the lslq cases.
@@ -2419,18 +2546,24 @@
;; The addi insn as it is normally used.
+;; Make the the ACR alternative taste bad enough to not choose it as a
+;; preference to avoid spilling problems (unwind-dw2-fde.c at build).
+;; FIXME: Revisit for new register allocator.
+
(define_insn "*addi"
- [(set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "=r,!a")
(plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r")
- (match_operand:SI 3 "const_int_operand" "n"))
- (match_operand:SI 1 "register_operand" "0")))]
+ (mult:SI (match_operand:SI 2 "register_operand" "r,r")
+ (match_operand:SI 3 "const_int_operand" "n,n"))
+ (match_operand:SI 1 "register_operand" "0,r")))]
"operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
- && GET_CODE (operands[3]) == CONST_INT
+ && CONST_INT_P (operands[3])
&& (INTVAL (operands[3]) == 1
|| INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)"
- "addi %2%T3,%0"
+ "@
+ addi %2%T3,%0
+ addi %2%T3,%1,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
@@ -2447,7 +2580,7 @@
(match_operand:SI 2 "register_operand" "r"))
(ashift:SI (match_operand:SI 3 "register_operand" "0")
(const_int 1))))]
- ""
+ "!TARGET_V32"
"mstep %2,%0"
[(set_attr "slottable" "yes")])
@@ -2465,33 +2598,30 @@
(match_operand:SI 2 "register_operand" "r"))
(mult:SI (match_operand:SI 3 "register_operand" "0")
(const_int 2))))]
- "operands[0] != frame_pointer_rtx
+ "!TARGET_V32
+ && operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
&& operands[2] != frame_pointer_rtx
&& operands[3] != frame_pointer_rtx"
"mstep %2,%0"
[(set_attr "slottable" "yes")])
-(define_insn "umulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI
- (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
- (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
- "TARGET_HAS_MUL_INSNS"
- "mulu.w %2,%0"
- [(set_attr "slottable" "yes")
- ;; Just N unusable here, but let's be safe.
- (set_attr "cc" "clobber")])
-
-(define_insn "umulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (mult:HI
- (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
- (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
+(define_insn "mul3"
+ [(set (match_operand:WD 0 "register_operand" "=r")
+ (mult:WD
+ (szext:WD (match_operand: 1 "register_operand" "%0"))
+ (szext:WD (match_operand: 2 "register_operand" "r"))))
+ (clobber (match_scratch:SI 3 "=h"))]
"TARGET_HAS_MUL_INSNS"
- "mulu.b %2,%0"
- [(set_attr "slottable" "yes")
- ;; Not exactly sure, but let's be safe.
+ "%!mul %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
+ ;; For umuls.[bwd] it's just N unusable here, but let's be safe.
+ ;; For muls.b, this really extends to SImode, so cc should be
+ ;; considered clobbered.
+ ;; For muls.w, it's just N unusable here, but let's be safe.
(set_attr "cc" "clobber")])
;; Note that gcc does not make use of such a thing as umulqisi3. It gets
@@ -2502,93 +2632,66 @@
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "register_operand" "r")))]
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "r")))
+ (clobber (match_scratch:SI 3 "=h"))]
"TARGET_HAS_MUL_INSNS"
- "muls.d %2,%0"
- [(set_attr "slottable" "yes")
+ "%!muls.d %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
;; Just N unusable here, but let's be safe.
(set_attr "cc" "clobber")])
;; A few multiply variations.
-;; This really extends to SImode, so cc should be considered clobbered.
-
-(define_insn "mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (mult:HI
- (sign_extend:HI (match_operand:QI 1 "register_operand" "0"))
- (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
- "TARGET_HAS_MUL_INSNS"
- "muls.b %2,%0"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "clobber")])
-
-(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI
- (sign_extend:SI (match_operand:HI 1 "register_operand" "0"))
- (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
- "TARGET_HAS_MUL_INSNS"
- "muls.w %2,%0"
- [(set_attr "slottable" "yes")
- ;; Just N unusable here, but let's be safe.
- (set_attr "cc" "clobber")])
-
;; When needed, we can get the high 32 bits from the overflow
;; register. We don't care to split and optimize these.
;;
;; Note that cc0 is still valid after the move-from-overflow-register
;; insn; no special precaution need to be taken in cris_notice_update_cc.
-(define_insn "mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (mult:DI
- (sign_extend:DI (match_operand:SI 1 "register_operand" "0"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
- "TARGET_HAS_MUL_INSNS"
- "muls.d %2,%M0\;move $mof,%H0")
-
-(define_insn "umulsidi3"
+(define_insn "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
- (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
- "TARGET_HAS_MUL_INSNS"
- "mulu.d %2,%M0\;move $mof,%H0")
-
-;; This pattern would probably not be needed if we add "mof" in its own
-;; register class (and open a can of worms about /not/ pairing it with a
-;; "normal" register). Having multiple register classes here, and
-;; applicable to the v10 variant only, seems worse than having these two
-;; patterns with multi-insn contents for now (may change; having a free
-;; call-clobbered register is worth some trouble).
-
-(define_insn "smulsi3_highpart"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m")
- (truncate:SI
- (lshiftrt:DI
- (mult:DI
- (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r"))
- (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r,r")))
- (const_int 32))))
- (clobber (match_scratch:SI 3 "=X,1,1"))]
+ (szext:DI (match_operand:SI 1 "register_operand" "%0"))
+ (szext:DI (match_operand:SI 2 "register_operand" "r"))))
+ (clobber (match_scratch:SI 3 "=h"))]
"TARGET_HAS_MUL_INSNS"
- "muls.d %2,%1\;move $mof,%0"
- [(set_attr "cc" "clobber")])
-
-(define_insn "umulsi3_highpart"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m")
+ "%!mul.d %2,%M0\;move $mof,%H0")
+
+;; These two patterns may be expressible by other means, perhaps by making
+;; [u]?mulsidi3 a define_expand.
+
+;; Due to register allocation braindamage, the clobber 1,2 alternatives
+;; cause a move into the clobbered register *before* the insn, then
+;; after the insn, mof is moved too, rather than the clobber assigned
+;; the last mof target. This became apparent when making MOF and SRP
+;; visible registers, with the necessary tweak to smulsi3_highpart.
+;; Because these patterns are used in division by constants, that damage
+;; is visible (ipps regression tests). Therefore the last two
+;; alternatives, "helping" reload to avoid an unnecessary move, but
+;; punished by force of one "?". Check code from "int d (int a) {return
+;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit.
+
+(define_insn "mulsi3_highpart"
+ [(set (match_operand:SI 0 "register_operand" "=h,h,?r,?r")
(truncate:SI
(lshiftrt:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,r,r"))
- (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r,r")))
+ (szext:DI (match_operand:SI 1 "register_operand" "r,r,0,r"))
+ (szext:DI (match_operand:SI 2 "register_operand" "r,r,r,0")))
(const_int 32))))
- (clobber (match_scratch:SI 3 "=X,1,1"))]
+ (clobber (match_scratch:SI 3 "=1,2,h,h"))]
"TARGET_HAS_MUL_INSNS"
- "mulu.d %2,%1\;move $mof,%0"
- [(set_attr "cc" "clobber")])
+ "@
+ %!mul.d %2,%1
+ %!mul.d %1,%2
+ %!mul.d %2,%1\;move $mof,%0
+ %!mul.d %1,%2\;move $mof,%0"
+ [(set_attr "slottable" "yes,yes,no,no")
+ (set_attr "cc" "clobber")])
;; Divide and modulus instructions. CRIS only has a step instruction.
@@ -2605,7 +2708,8 @@
(const_int 1))))]
""
"dstep %2,%0"
- [(set_attr "slottable" "yes")])
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; Here's a variant with mult instead of ashift.
;;
@@ -2627,7 +2731,8 @@
&& operands[2] != frame_pointer_rtx
&& operands[3] != frame_pointer_rtx"
"dstep %2,%0"
- [(set_attr "slottable" "yes")])
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; Logical operators.
@@ -2649,9 +2754,8 @@
(and:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "general_operand" "")))]
""
- "
{
- if (! (GET_CODE (operands[2]) == CONST_INT
+ if (! (CONST_INT_P (operands[2])
&& (((INTVAL (operands[2]) == -256
|| INTVAL (operands[2]) == -65536)
&& rtx_equal_p (operands[1], operands[0]))
@@ -2686,23 +2790,25 @@
DONE;
}
-}")
+})
;; Some special cases of andsi3.
(define_insn "*andsi_movu"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q>,m")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%r,Q,To")
(match_operand:SI 2 "const_int_operand" "n,n,n")))]
- "INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535"
+ "(INTVAL (operands[2]) == 255 || INTVAL (operands[2]) == 65535)
+ && !side_effects_p (operands[1])"
"movu.%z2 %1,%0"
[(set_attr "slottable" "yes,yes,no")])
(define_insn "*andsi_clear"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q>,Q>,m,m")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,Q,Q,To,To")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0")
(match_operand:SI 2 "const_int_operand" "P,n,P,n,P,n")))]
- "INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256"
+ "(INTVAL (operands[2]) == -65536 || INTVAL (operands[2]) == -256)
+ && !side_effects_p (operands[0])"
"@
cLear.b %0
cLear.w %0
@@ -2721,11 +2827,11 @@
;; pressure (worse code). That will hopefully change with an
;; improved reload pass.
-(define_insn "*expanded_andsi"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
- (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,r")
- (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))]
- ""
+(define_insn "*expanded_andsi_non_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r")
+ (match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))]
+ "!TARGET_V32"
"@
andq %2,%0
and.d %2,%0
@@ -2733,6 +2839,19 @@
and.d %2,%0
and.d %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,no,no")])
+
+(define_insn "*expanded_andsi_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "I,r,Q>,g")))]
+ "TARGET_V32"
+ "@
+ andq %2,%0
+ and.d %2,%0
+ and.d %2,%0
+ and.d %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,no")
+ (set_attr "cc" "noov32")])
;; For both QI and HI we may use the quick patterns. This results in
;; useless condition codes, but that is used rarely enough for it to
@@ -2746,9 +2865,8 @@
(and:HI (match_operand:HI 1 "nonimmediate_operand" "")
(match_operand:HI 2 "general_operand" "")))]
""
- "
{
- if (! (GET_CODE (operands[2]) == CONST_INT
+ if (! (CONST_INT_P (operands[2])
&& (((INTVAL (operands[2]) == -256
|| INTVAL (operands[2]) == 65280)
&& rtx_equal_p (operands[1], operands[0]))
@@ -2774,50 +2892,40 @@
DONE;
}
-}")
+})
;; Some fast andhi3 special cases.
(define_insn "*andhi_movu"
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q>,m")
+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "r,Q,To")
(const_int 255)))]
- ""
+ "!side_effects_p (operands[1])"
"mOvu.b %1,%0"
[(set_attr "slottable" "yes,yes,no")])
-(define_insn "*andhi_clear_signed"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q>,m")
+(define_insn "*andhi_clear"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,To")
(and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0")
(const_int -256)))]
- ""
- "cLear.b %0"
- [(set_attr "slottable" "yes,yes,no")
- (set_attr "cc" "none")])
-
-;; FIXME: Either this or the pattern above should be redundant.
-(define_insn "*andhi_clear_unsigned"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q>,m")
- (and:HI (match_operand:HI 1 "nonimmediate_operand" "0,0,0")
- (const_int 65280)))]
- ""
+ "!side_effects_p (operands[0])"
"cLear.b %0"
[(set_attr "slottable" "yes,yes,no")
(set_attr "cc" "none")])
;; Catch-all andhi3 pattern.
-(define_insn "*expanded_andhi"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
- (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,r")
- (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
+(define_insn "*expanded_andhi_non_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
+ (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
;; Sidenote: the tightening from "general_operand" to
;; "register_operand" for operand 1 actually increased the register
;; pressure (worse code). That will hopefully change with an
;; improved reload pass.
- ""
+ "!TARGET_V32"
"@
andq %2,%0
and.w %2,%0
@@ -2829,14 +2937,29 @@
[(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
(set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
+(define_insn "*expanded_andhi_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
+ (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
+ "TARGET_V32"
+ "@
+ andq %2,%0
+ and.w %2,%0
+ and.w %2,%0
+ and.w %2,%0
+ anDq %b2,%0
+ and.w %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,no,yes,no")
+ (set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
+
;; A strict_low_part pattern.
-(define_insn "*andhi_lowpart"
+(define_insn "*andhi_lowpart_non_v32"
[(set (strict_low_part
- (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r"))
- (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,r")
- (match_operand:HI 2 "general_operand" "r,Q>,L,O,g,!To")))]
- ""
+ (match_operand:HI 0 "register_operand" "+r,r, r,r,r,r"))
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
+ (match_operand:HI 2 "general_operand" "r,Q>,L,O,g,!To")))]
+ "!TARGET_V32"
"@
and.w %2,%0
and.w %2,%0
@@ -2846,12 +2969,34 @@
and.w %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,yes,no,no")
(set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
+
+(define_insn "*andhi_lowpart_v32"
+ [(set (strict_low_part
+ (match_operand:HI 0 "register_operand" "+r,r,r,r,r"))
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:HI 2 "general_operand" "r,Q>,L,O,g")))]
+ "TARGET_V32"
+ "@
+ and.w %2,%0
+ and.w %2,%0
+ and.w %2,%0
+ anDq %b2,%0
+ and.w %2,%0"
+ [(set_attr "slottable" "yes,yes,no,yes,no")
+ (set_attr "cc" "noov32,noov32,noov32,clobber,noov32")])
-(define_insn "andqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r")
- (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,r")
- (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
+(define_expand "andqi3"
+ [(set (match_operand:QI 0 "register_operand")
+ (and:QI (match_operand:QI 1 "register_operand")
+ (match_operand:QI 2 "general_operand")))]
""
+ "")
+
+(define_insn "*andqi3_non_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
+ (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
+ "!TARGET_V32"
"@
andq %2,%0
and.b %2,%0
@@ -2862,12 +3007,26 @@
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
-(define_insn "*andqi_lowpart"
+(define_insn "*andqi3_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
+ "TARGET_V32"
+ "@
+ andq %2,%0
+ and.b %2,%0
+ and.b %2,%0
+ andQ %b2,%0
+ and.b %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,no")
+ (set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
+
+(define_insn "*andqi_lowpart_non_v32"
[(set (strict_low_part
- (match_operand:QI 0 "register_operand" "=r,r,r,r,r"))
- (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,r")
- (match_operand:QI 2 "general_operand" "r,Q>,O,g,!To")))]
- ""
+ (match_operand:QI 0 "register_operand" "+r,r, r,r,r"))
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,r")
+ (match_operand:QI 2 "general_operand" "r,Q>,O,g,!To")))]
+ "!TARGET_V32"
"@
and.b %2,%0
and.b %2,%0
@@ -2876,19 +3035,40 @@
and.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,normal,normal")])
-
-;; Bitwise or.
+
+(define_insn "*andqi_lowpart_v32"
+ [(set (strict_low_part
+ (match_operand:QI 0 "register_operand" "+r,r,r,r"))
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0")
+ (match_operand:QI 2 "general_operand" "r,Q>,O,g")))]
+ "TARGET_V32"
+ "@
+ and.b %2,%0
+ and.b %2,%0
+ andQ %b2,%0
+ and.b %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,no")
+ (set_attr "cc" "noov32,noov32,clobber,noov32")])
+
+;; Bitwise or.
;; Same comment as anddi3 applies here - no need for such a pattern.
;; It seems there's no need to jump through hoops to get good code such as
;; with andsi3.
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
- (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,r")
- (match_operand:SI 2 "general_operand" "I,r,Q>,n,g,!To")))]
+(define_expand "ior3"
+ [(set (match_operand:BWD 0 "register_operand")
+ (ior:BWD (match_operand:BWD 1 "register_operand")
+ (match_operand:BWD 2 "general_operand")))]
""
+ "")
+
+(define_insn "*iorsi3_non_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r")
+ (match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To")))]
+ "!TARGET_V32"
"@
orq %2,%0
or.d %2,%0
@@ -2899,11 +3079,25 @@
[(set_attr "slottable" "yes,yes,yes,no,no,no")
(set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
-(define_insn "iorhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r,r")
- (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,r")
- (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
- ""
+(define_insn "*iorsi3_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:SI 2 "general_operand" "I,r,Q>,n,g")))]
+ "TARGET_V32"
+ "@
+ orq %2,%0
+ or.d %2,%0
+ or.d %2,%0
+ oR.%s2 %2,%0
+ or.d %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,no,no")
+ (set_attr "cc" "noov32,noov32,noov32,clobber,noov32")])
+
+(define_insn "*iorhi3_non_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
+ (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
+ (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
+ "!TARGET_V32"
"@
orq %2,%0
or.w %2,%0
@@ -2915,11 +3109,26 @@
[(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
(set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
-(define_insn "iorqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r,r")
- (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,r")
- (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
- ""
+(define_insn "*iorhi3_v32"
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
+ (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
+ (match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
+ "TARGET_V32"
+ "@
+ orq %2,%0
+ or.w %2,%0
+ or.w %2,%0
+ or.w %2,%0
+ oRq %b2,%0
+ or.w %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,no,yes,no")
+ (set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
+
+(define_insn "*iorqi3_non_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
+ (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
+ (match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
+ "!TARGET_V32"
"@
orq %2,%0
or.b %2,%0
@@ -2929,10 +3138,25 @@
or.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
+
+(define_insn "*iorqi3_v32"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
+ (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
+ "TARGET_V32"
+ "@
+ orq %2,%0
+ or.b %2,%0
+ or.b %2,%0
+ orQ %b2,%0
+ or.b %2,%0"
+ [(set_attr "slottable" "yes,yes,yes,yes,no")
+ (set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
;; Exclusive-or
;; See comment about "anddi3" for xordi3 - no need for such a pattern.
+;; FIXME: Do we really need the shorter variants?
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -2940,21 +3164,13 @@
(match_operand:SI 2 "register_operand" "r")))]
""
"xor %2,%0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "xorhi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (xor:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "register_operand" "r")))]
- ""
- "xor %2,%0"
[(set_attr "slottable" "yes")
- (set_attr "cc" "clobber")])
+ (set_attr "cc" "noov32")])
-(define_insn "xorqi3"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (xor:QI (match_operand:QI 1 "register_operand" "%0")
- (match_operand:QI 2 "register_operand" "r")))]
+(define_insn "xor3"
+ [(set (match_operand:BW 0 "register_operand" "=r")
+ (xor:BW (match_operand:BW 1 "register_operand" "%0")
+ (match_operand:BW 2 "register_operand" "r")))]
""
"xor %2,%0"
[(set_attr "slottable" "yes")
@@ -2973,11 +3189,10 @@
"register_operand" "0")))
(use (match_dup 2))])]
""
- "
{
operands[2] = gen_reg_rtx (SImode);
operands[3] = GEN_INT (1 << 31);
-}")
+})
(define_insn "*expanded_negsf2"
[(set (match_operand:SF 0 "register_operand" "=r")
@@ -2990,69 +3205,49 @@
;; No "negdi2" although we could make one up that may be faster than
;; the one in libgcc.
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "register_operand" "r")))]
+(define_insn "neg2"
+ [(set (match_operand:BWD 0 "register_operand" "=r")
+ (neg:BWD (match_operand:BWD 1 "register_operand" "r")))]
""
- "neg.d %1,%0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "neghi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (neg:HI (match_operand:HI 1 "register_operand" "r")))]
- ""
- "neg.w %1,%0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "negqi2"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (neg:QI (match_operand:QI 1 "register_operand" "r")))]
- ""
- "neg.b %1,%0"
+ "neg %1,%0"
[(set_attr "slottable" "yes")])
;; One-complements.
;; See comment on anddi3 - no need for a DImode pattern.
+;; See also xor comment.
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operand:SI 1 "register_operand" "0")))]
""
"not %0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (not:HI (match_operand:HI 1 "register_operand" "0")))]
- ""
- "not %0"
[(set_attr "slottable" "yes")
- (set_attr "cc" "clobber")])
+ (set_attr "cc" "noov32")])
-(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (not:QI (match_operand:QI 1 "register_operand" "0")))]
+(define_insn "one_cmpl2"
+ [(set (match_operand:BW 0 "register_operand" "=r")
+ (not:BW (match_operand:BW 1 "register_operand" "0")))]
""
"not %0"
[(set_attr "slottable" "yes")
(set_attr "cc" "clobber")])
-;; Arithmetic shift right.
+;; Arithmetic/Logical shift right (and SI left).
-(define_insn "ashrsi3"
+(define_insn "si3"
[(set (match_operand:SI 0 "register_operand" "=r")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "Kr")))]
+ (shift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "Kcr")))]
""
- "*
{
if (REG_S_P (operands[2]))
- return \"asr.d %2,%0\";
+ return ".d %2,%0";
- return \"asrq %2,%0\";
-}"
- [(set_attr "slottable" "yes")])
+ return "q %2,%0";
+}
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; Since gcc gets lost, and forgets to zero-extend the source (or mask
;; the destination) when it changes shifts of lower modes into SImode,
@@ -3062,238 +3257,89 @@
;; FIXME: Is this legacy or still true for gcc >= 2.7.2?
-(define_expand "ashrhi3"
- [(set (match_dup 3)
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))
- (set (match_dup 4)
- (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm")))
- (set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4)))
- (set (match_operand:HI 0 "general_operand" "=g")
- (subreg:HI (match_dup 5) 0))]
- ""
- "
-{
- int i;
-
- for (i = 3; i < 6; i++)
- operands[i] = gen_reg_rtx (SImode);
-}")
-
-(define_insn "*expanded_ashrhi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- ""
- "asr.w %2,%0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "*ashrhi_lowpart"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
- (ashiftrt:HI (match_dup 0)
- (match_operand:HI 1 "register_operand" "r")))]
- ""
- "asr.w %1,%0"
- [(set_attr "slottable" "yes")])
-
-;; Same comment goes as for "ashrhi3".
-
-(define_expand "ashrqi3"
+;; FIXME: Can't parametrize sign_extend and zero_extend (before
+;; mentioning "shiftrt"), so we need two patterns.
+(define_expand "ashr3"
[(set (match_dup 3)
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (sign_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
(set (match_dup 4)
- (zero_extend:SI (match_operand:QI 2 "nonimmediate_operand" "g")))
+ (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
(set (match_dup 5) (ashiftrt:SI (match_dup 3) (match_dup 4)))
- (set (match_operand:QI 0 "general_operand" "=g")
- (subreg:QI (match_dup 5) 0))]
- ""
- "
-{
- int i;
-
- for (i = 3; i < 6; i++)
- operands[i] = gen_reg_rtx (SImode);
-}")
-
-(define_insn "*expanded_ashrqi"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
- ""
- "asr.b %2,%0"
- [(set_attr "slottable" "yes")])
-
-;; A strict_low_part matcher.
-
-(define_insn "*ashrqi_lowpart"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
- (ashiftrt:QI (match_dup 0)
- (match_operand:QI 1 "register_operand" "r")))]
- ""
- "asr.b %1,%0"
- [(set_attr "slottable" "yes")])
-
-;; Logical shift right.
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "Kr")))]
- ""
- "*
-{
- if (REG_S_P (operands[2]))
- return \"lsr.d %2,%0\";
-
- return \"lsrq %2,%0\";
-}"
- [(set_attr "slottable" "yes")])
-
-;; Same comments as for ashrhi3.
-
-(define_expand "lshrhi3"
- [(set (match_dup 3)
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
- (set (match_dup 4)
- (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "g")))
- (set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4)))
- (set (match_operand:HI 0 "general_operand" "=g")
- (subreg:HI (match_dup 5) 0))]
+ (set (match_operand:BW 0 "general_operand" "")
+ (subreg:BW (match_dup 5) 0))]
""
- "
{
int i;
for (i = 3; i < 6; i++)
operands[i] = gen_reg_rtx (SImode);
-}")
+})
-(define_insn "*expanded_lshrhi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- ""
- "lsr.w %2,%0"
- [(set_attr "slottable" "yes")])
-
-;; A strict_low_part matcher.
-
-(define_insn "*lshrhi_lowpart"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
- (lshiftrt:HI (match_dup 0)
- (match_operand:HI 1 "register_operand" "r")))]
- ""
- "lsr.w %1,%0"
- [(set_attr "slottable" "yes")])
-
-;; Same comments as for ashrhi3.
-
-(define_expand "lshrqi3"
+(define_expand "lshr3"
[(set (match_dup 3)
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+ (zero_extend:SI (match_operand:BW 1 "nonimmediate_operand" "")))
(set (match_dup 4)
- (zero_extend:SI (match_operand:QI 2 "nonimmediate_operand" "g")))
+ (zero_extend:SI (match_operand:BW 2 "nonimmediate_operand" "")))
(set (match_dup 5) (lshiftrt:SI (match_dup 3) (match_dup 4)))
- (set (match_operand:QI 0 "general_operand" "=g")
- (subreg:QI (match_dup 5) 0))]
+ (set (match_operand:BW 0 "general_operand" "")
+ (subreg:BW (match_dup 5) 0))]
""
- "
{
int i;
for (i = 3; i < 6; i++)
operands[i] = gen_reg_rtx (SImode);
-}")
+})
-(define_insn "*expanded_lshrqi"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
+(define_insn "*expanded_"
+ [(set (match_operand:BW 0 "register_operand" "=r")
+ (shiftrt:BW (match_operand:BW 1 "register_operand" "0")
+ (match_operand:BW 2 "register_operand" "r")))]
""
- "lsr.b %2,%0"
- [(set_attr "slottable" "yes")])
-
-;; A strict_low_part matcher.
+ " %2,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
-(define_insn "*lshrqi_lowpart"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
- (lshiftrt:QI (match_dup 0)
- (match_operand:QI 1 "register_operand" "r")))]
+(define_insn "*_lowpart"
+ [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
+ (shiftrt:BW (match_dup 0)
+ (match_operand:BW 1 "register_operand" "r")))]
""
- "lsr.b %1,%0"
- [(set_attr "slottable" "yes")])
+ " %1,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; Arithmetic/logical shift left.
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ashift:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "Kr")))]
- ""
- "*
-{
- if (REG_S_P (operands[2]))
- return \"lsl.d %2,%0\";
-
- return \"lslq %2,%0\";
-}"
- [(set_attr "slottable" "yes")])
-
;; For narrower modes than SI, we can use lslq although it makes cc
;; unusable. The win is that we do not have to reload the shift-count
;; into a register.
-(define_insn "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "nonmemory_operand" "r,K")))]
+(define_insn "ashl3"
+ [(set (match_operand:BW 0 "register_operand" "=r,r")
+ (ashift:BW (match_operand:BW 1 "register_operand" "0,0")
+ (match_operand:BW 2 "nonmemory_operand" "r,Kc")))]
""
- "*
{
return
- (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 15)
- ? \"moveq 0,%0\"
+ (CONST_INT_P (operands[2]) && INTVAL (operands[2]) > )
+ ? "moveq 0,%0"
: (CONSTANT_P (operands[2])
- ? \"lslq %2,%0\" : \"lsl.w %2,%0\");
-}"
+ ? "lslq %2,%0" : "lsl %2,%0");
+}
[(set_attr "slottable" "yes")
- (set_attr "cc" "normal,clobber")])
+ (set_attr "cc" "noov32,clobber")])
;; A strict_low_part matcher.
-(define_insn "*ashlhi_lowpart"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
- (ashift:HI (match_dup 0)
+(define_insn "*ashl_lowpart"
+ [(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
+ (ashift:BW (match_dup 0)
(match_operand:HI 1 "register_operand" "r")))]
""
- "lsl.w %1,%0"
- [(set_attr "slottable" "yes")])
-
-(define_insn "ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "=r,r")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "r,K")))]
- ""
- "*
-{
- return
- (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) > 7)
- ? \"moveq 0,%0\"
- : (CONSTANT_P (operands[2])
- ? \"lslq %2,%0\" : \"lsl.b %2,%0\");
-}"
+ "lsl %1,%0"
[(set_attr "slottable" "yes")
- (set_attr "cc" "normal,clobber")])
-
-;; A strict_low_part matcher.
-
-(define_insn "*ashlqi_lowpart"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
- (ashift:QI (match_dup 0)
- (match_operand:QI 1 "register_operand" "r")))]
- ""
- "lsl.b %1,%0"
- [(set_attr "slottable" "yes")])
+ (set_attr "cc" "noov32")])
;; Various strange insns that gcc likes.
@@ -3311,53 +3357,125 @@
(abs:SI (match_operand:SI 1 "register_operand" "r")))]
""
"abs %1,%0"
- [(set_attr "slottable" "yes")])
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
;; FIXME: GCC should be able to do these expansions itself.
-(define_expand "abshi2"
+(define_expand "abs2"
[(set (match_dup 2)
- (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))
+ (sign_extend:SI (match_operand:BW 1 "general_operand" "")))
(set (match_dup 3) (abs:SI (match_dup 2)))
- (set (match_operand:HI 0 "register_operand" "=r")
- (subreg:HI (match_dup 3) 0))]
+ (set (match_operand:BW 0 "register_operand" "")
+ (subreg:BW (match_dup 3) 0))]
""
"operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
-(define_expand "absqi2"
+(define_insn "clzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" "r")))]
+ "TARGET_HAS_LZ"
+ "lz %1,%0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
+
+(define_insn "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (bswap:SI (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_HAS_SWAP"
+ "swapwb %0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
+
+;; This instruction swaps all bits in a register.
+;; That means that the most significant bit is put in the place
+;; of the least significant bit, and so on.
+
+(define_insn "cris_swap_bits"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0")]
+ CRIS_UNSPEC_SWAP_BITS))]
+ "TARGET_HAS_SWAP"
+ "swapwbr %0"
+ [(set_attr "slottable" "yes")
+ (set_attr "cc" "noov32")])
+
+;; Implement ctz using two instructions, one for bit swap and one for clz.
+;; Defines a scratch register to avoid clobbering input.
+
+(define_expand "ctzsi2"
[(set (match_dup 2)
- (sign_extend:SI (match_operand:QI 1 "general_operand" "g")))
- (set (match_dup 3) (abs:SI (match_dup 2)))
- (set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (match_dup 3) 0))]
- ""
- "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
-
+ (match_operand:SI 1 "register_operand"))
+ (set (match_dup 2)
+ (unspec:SI [(match_dup 2)] CRIS_UNSPEC_SWAP_BITS))
+ (set (match_operand:SI 0 "register_operand")
+ (clz:SI (match_dup 2)))]
+ "TARGET_HAS_LZ && TARGET_HAS_SWAP"
+ "operands[2] = gen_reg_rtx (SImode);")
+
;; Bound-insn. Defined to be the same as an unsigned minimum, which is an
;; operation supported by gcc. Used in casesi, but used now and then in
;; normal code too.
-(define_insn "uminsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (umin:SI (match_operand:SI 1 "register_operand" "%0,0,0,r")
- (match_operand:SI 2 "general_operand" "r,Q>,g,!STo")))]
+(define_expand "uminsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (umin:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
""
- "*
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (MEM_P (operands[2]) && TARGET_V32)
+ operands[2] = force_reg (SImode, operands[2]);
+})
+
+(define_insn "*uminsi3_non_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
+ (umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r")
+ (match_operand:SI 2 "general_operand" "r,Q>,g,!To")))]
+ "!TARGET_V32"
+{
+ if (CONST_INT_P (operands[2]))
{
- if (INTVAL (operands[2]) < 256)
- return \"bound.b %2,%0\";
+ /* Constant operands are zero-extended, so only 32-bit operands
+ may be negative. */
+ if (INTVAL (operands[2]) >= 0)
+ {
+ if (INTVAL (operands[2]) < 256)
+ return "bound.b %2,%0";
- if (INTVAL (operands[2]) < 65536)
- return \"bound.w %2,%0\";
+ if (INTVAL (operands[2]) < 65536)
+ return "bound.w %2,%0";
+ }
}
else if (which_alternative == 3)
- return \"bound.d %2,%1,%0\";
+ return "bound.d %2,%1,%0";
- return \"bound.d %2,%0\";
-}"
+ return "bound.d %2,%0";
+}
[(set_attr "slottable" "yes,yes,no,no")])
+
+(define_insn "*uminsi3_v32"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (umin:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,i")))]
+ "TARGET_V32"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ /* Constant operands are zero-extended, so only 32-bit operands
+ may be negative. */
+ if (INTVAL (operands[2]) >= 0)
+ {
+ if (INTVAL (operands[2]) < 256)
+ return "bound.b %2,%0";
+
+ if (INTVAL (operands[2]) < 65536)
+ return "bound.w %2,%0";
+ }
+ }
+
+ return "bound.d %2,%0";
+}
+ [(set_attr "slottable" "yes,no")])
;; Jump and branch insns.
@@ -3373,76 +3491,62 @@
;; jmp_uses_reg_or_mem used by computed_jump_p. Perhaps it is a kludge to
;; change from general_operand to nonimmediate_operand (at least the docs
;; should be changed), but then again the pattern is called indirect_jump.
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+(define_expand "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "nonimmediate_operand"))]
""
+{
+ if (TARGET_V32 && MEM_P (operands[0]))
+ operands[0] = force_reg (SImode, operands[0]);
+})
+
+(define_insn "*indirect_jump_non_v32"
+ [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+ "!TARGET_V32"
"jump %0")
+(define_insn "*indirect_jump_v32"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ "TARGET_V32"
+ "jump %0%#"
+ [(set_attr "slottable" "has_slot")])
+
;; Return insn. Used whenever the epilogue is very simple; if it is only
-;; a single ret or jump [sp+] or a contiguous sequence of movem:able saved
-;; registers. No allocated stack space is allowed.
+;; a single ret or jump [sp+]. No allocated stack space or saved
+;; registers are allowed.
;; Note that for this pattern, although named, it is ok to check the
;; context of the insn in the test, not only compiler switches.
-(define_insn "return"
+(define_expand "return"
[(return)]
"cris_simple_epilogue ()"
- "*
-{
- int i;
-
- /* Just needs to hold a 'movem [sp+],rN'. */
- char rd[sizeof (\"movem [$sp+],$r99\")];
-
- /* Try to avoid reorg.c surprises; avoid emitting invalid code, prefer
- crashing. This test would have avoided invalid code for target/7042. */
- if (current_function_epilogue_delay_list != NULL)
- abort ();
-
- *rd = 0;
-
- /* Start from the last call-saved register. We know that we have a
- simple epilogue, so we just have to find the last register in the
- movem sequence. */
- for (i = 8; i >= 0; i--)
- if (regs_ever_live[i]
- || (i == PIC_OFFSET_TABLE_REGNUM
- && current_function_uses_pic_offset_table))
- break;
-
- if (i >= 0)
- sprintf (rd, \"movem [$sp+],$%s\", reg_names [i]);
-
- if (regs_ever_live[CRIS_SRP_REGNUM])
- {
- if (*rd)
- output_asm_insn (rd, operands);
- return \"jump [$sp+]\";
- }
-
- if (*rd)
- {
- output_asm_insn (\"reT\", operands);
- output_asm_insn (rd, operands);
- return \"\";
- }
+ "cris_expand_return (cris_return_address_on_stack ()); DONE;")
- return \"ret%#\";
-}"
+(define_insn "*return_expanded"
+ [(return)]
+ ""
+{
+ return cris_return_address_on_stack_for_return ()
+ ? "jump [$sp+]" : "ret%#";
+}
[(set (attr "slottable")
- (if_then_else
- (ne (symbol_ref "regs_ever_live[CRIS_SRP_REGNUM]") (const_int 0))
- (const_string "no") ; If jump then not slottable.
- (if_then_else
- (ne (symbol_ref
- "(regs_ever_live[0]
- || (flag_pic != 0 && regs_ever_live[1])
- || (PIC_OFFSET_TABLE_REGNUM == 0
- && cris_cfun_uses_pic_table ()))")
- (const_int 0))
- (const_string "no") ; ret+movem [sp+],rx: slot already filled.
- (const_string "has_slot")))) ; If ret then need to fill a slot.
- (set_attr "cc" "none")])
+ (if_then_else
+ (ne (symbol_ref
+ "(cris_return_address_on_stack_for_return ())")
+ (const_int 0))
+ (const_string "no")
+ (const_string "has_return_slot")))])
+
+(define_expand "prologue"
+ [(const_int 0)]
+ "TARGET_PROLOGUE_EPILOGUE"
+ "cris_expand_prologue (); DONE;")
+
+;; Note that the (return) from the expander itself is always the last
+;; insn in the epilogue.
+(define_expand "epilogue"
+ [(const_int 0)]
+ "TARGET_PROLOGUE_EPILOGUE"
+ "cris_expand_epilogue (); DONE;")
;; Conditional branches.
@@ -3450,350 +3554,118 @@
;; e.g. m68k, so we have to check if overflow bit is set on all "signed"
;; conditions.
-(define_insn "beq"
+(define_insn "b"
[(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
+ (if_then_else (ncond (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "beq %l0%#"
+ "b %l0%#"
[(set_attr "slottable" "has_slot")])
-(define_insn "bne"
+(define_insn "b"
[(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
+ (if_then_else (ocond (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "bne %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
{
return
(cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"bgt %l0%#\";
-}"
+ ? 0 : "b %l0%#";
+}
[(set_attr "slottable" "has_slot")])
-(define_insn "bgtu"
+(define_insn "b"
[(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
+ (if_then_else (rcond (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "bhi %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
{
return
(cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"bmi %l0%#\" : \"blt %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "blo %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"bpl %l0%#\" : \"bge %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bhs %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"ble %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bls %l0%#"
+ ? "b %l0%#" : "b %l0%#";
+}
[(set_attr "slottable" "has_slot")])
;; Reversed anonymous patterns to the ones above, as mandated.
-(define_insn "*beq_reversed"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bne %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*bne_reversed"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "beq %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*bgt_reversed"
+(define_insn "*b_reversed"
[(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
+ (if_then_else (ncond (cc0)
+ (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"ble %l0%#\";
-}"
+ "b %l0%#"
[(set_attr "slottable" "has_slot")])
-(define_insn "*bgtu_reversed"
+(define_insn "*b_reversed"
[(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
+ (if_then_else (ocond (cc0)
+ (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "bls %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*blt_reversed"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
{
return
(cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"bpl %l0%#\" : \"bge %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*bltu_reversed"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhs %l0%#"
+ ? 0 : "b %l0%#";
+}
[(set_attr "slottable" "has_slot")])
-(define_insn "*bge_reversed"
+(define_insn "*b_reversed"
[(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
+ (if_then_else (rcond (cc0)
+ (const_int 0))
(pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"bmi %l0%#\" : \"blt %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*bgeu_reversed"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "blo %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*ble_reversed"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"bgt %l0%#\";
-}"
- [(set_attr "slottable" "has_slot")])
-
-(define_insn "*bleu_reversed"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhi %l0%#"
- [(set_attr "slottable" "has_slot")])
-
-;; Set on condition: sCC.
-
-;; Like bCC, we have to check the overflow bit for
-;; signed conditions.
-
-(define_insn "sgeu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (geu:SI (cc0) (const_int 0)))]
- ""
- "shs %0"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "sltu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ltu:SI (cc0) (const_int 0)))]
- ""
- "slo %0"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "seq"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (cc0) (const_int 0)))]
- ""
- "seq %0"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "sge"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ge:SI (cc0) (const_int 0)))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"spl %0\" : \"sge %0\";
-}"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "sgt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gt:SI (cc0) (const_int 0)))]
- ""
- "*
-{
- return
- (cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"sgt %0\";
-}"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "sgtu"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (gtu:SI (cc0) (const_int 0)))]
- ""
- "shi %0"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
-
-(define_insn "sle"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (le:SI (cc0) (const_int 0)))]
+ (label_ref (match_operand 0 "" ""))))]
""
- "*
{
return
(cc_prev_status.flags & CC_NO_OVERFLOW)
- ? 0 : \"sle %0\";
-}"
- [(set_attr "slottable" "yes")
- (set_attr "cc" "none")])
+ ? "b %l0%#" : "b %l0%#";
+}
+ [(set_attr "slottable" "has_slot")])
+
+;; Set on condition: sCC.
+
+;; Like bCC, we have to check the overflow bit for
+;; signed conditions.
-(define_insn "sleu"
+(define_insn "s"
[(set (match_operand:SI 0 "register_operand" "=r")
- (leu:SI (cc0) (const_int 0)))]
+ (ncond:SI (cc0) (const_int 0)))]
""
- "sls %0"
+ "s %0"
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
-(define_insn "slt"
+(define_insn "s"
[(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (cc0) (const_int 0)))]
+ (rcond:SI (cc0) (const_int 0)))]
""
- "*
{
return
(cc_prev_status.flags & CC_NO_OVERFLOW)
- ? \"smi %0\" : \"slt %0\";
-}"
+ ? "s %0" : "s %0";
+}
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
-(define_insn "sne"
+(define_insn "s"
[(set (match_operand:SI 0 "register_operand" "=r")
- (ne:SI (cc0) (const_int 0)))]
+ (ocond:SI (cc0) (const_int 0)))]
""
- "sne %0"
+{
+ return
+ (cc_prev_status.flags & CC_NO_OVERFLOW)
+ ? 0 : "s %0";
+}
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
@@ -3809,112 +3681,67 @@
(define_expand "call"
[(parallel [(call (match_operand:QI 0 "cris_mem_call_operand" "")
(match_operand 1 "general_operand" ""))
- ;; 16 is the srp (can't use the symbolic name here)
- (clobber (reg:SI 16))])]
+ (clobber (reg:SI CRIS_SRP_REGNUM))])]
""
- "
{
- rtx op0;
-
- if (GET_CODE (operands[0]) != MEM)
- abort ();
-
+ gcc_assert (MEM_P (operands[0]));
if (flag_pic)
- {
- op0 = XEXP (operands[0], 0);
-
- /* It might be that code can be generated that jumps to 0 (or to a
- specific address). Don't abort on that. At least there's a
- test-case. */
- if (CONSTANT_ADDRESS_P (op0) && GET_CODE (op0) != CONST_INT)
- {
- if (no_new_pseudos)
- abort ();
-
- /* For local symbols (non-PLT), get the plain symbol reference
- into a register. For symbols that can be PLT, make them PLT. */
- if (cris_gotless_symbol (op0) || GET_CODE (op0) != SYMBOL_REF)
- op0 = force_reg (Pmode, op0);
- else if (cris_symbol (op0))
- /* FIXME: Would hanging a REG_EQUIV/EQUAL on that register
- for the symbol cause bad recombinatorial effects? */
- op0 = force_reg (Pmode,
- gen_rtx_CONST
- (VOIDmode,
- gen_rtx_UNSPEC (VOIDmode,
- gen_rtvec (1, op0), 0)));
- else
- abort ();
-
- operands[0] = gen_rtx_MEM (GET_MODE (operands[0]), op0);
- }
- }
-}")
+ cris_expand_pic_call_address (&operands[0]);
+})
;; Accept *anything* as operand 1. Accept operands for operand 0 in
-;; order of preference (Q includes r, but r is shorter, faster)
+;; order of preference.
-(define_insn "*expanded_call"
- [(call (mem:QI (match_operand:SI
- 0 "cris_general_operand_or_plt_symbol" "r,Q>,g,S"))
+(define_insn "*expanded_call_non_v32"
+ [(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g"))
(match_operand 1 "" ""))
- (clobber (reg:SI 16))] ;; 16 is the srp (can't use symbolic name)
- "! TARGET_AVOID_GOTPLT"
+ (clobber (reg:SI CRIS_SRP_REGNUM))]
+ "!TARGET_V32"
"jsr %0")
-;; Same as above, since can't afford wasting a constraint letter to mean
-;; "S unless TARGET_AVOID_GOTPLT".
-(define_insn "*expanded_call_no_gotplt"
- [(call (mem:QI (match_operand:SI
- 0 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
- (match_operand 1 "" ""))
- (clobber (reg:SI 16))] ;; 16 is the srp (can't use symbolic name)
- "TARGET_AVOID_GOTPLT"
- "jsr %0")
+(define_insn "*expanded_call_v32"
+ [(call
+ (mem:QI
+ (match_operand:SI 0 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI CRIS_SRP_REGNUM))]
+ "TARGET_V32"
+ "@
+ jsr %0%#
+ jsr %0%#
+ bsr %0%#
+ bsr %0%#"
+ [(set_attr "slottable" "has_call_slot")])
+
+;; Parallel when calculating and reusing address of indirect pointer
+;; with simple offset. (Makes most sense with PIC.) It looks a bit
+;; wrong not to have the clobber last, but that's the way combine
+;; generates it (except it doesn' look into the *inner* mem, so this
+;; just matches a peephole2). FIXME: investigate that.
+(define_insn "*expanded_call_side"
+ [(call (mem:QI
+ (mem:SI
+ (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r, r,r")
+ (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))))
+ (match_operand 2 "" ""))
+ (clobber (reg:SI CRIS_SRP_REGNUM))
+ (set (match_operand:SI 3 "register_operand" "=*0,r,r")
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+ "jsr [%3=%0%S1]")
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand:QI 1 "cris_mem_call_operand" "")
(match_operand 2 "" "")))
- ;; 16 is the srp (can't use symbolic name)
- (clobber (reg:SI 16))])]
+ (clobber (reg:SI CRIS_SRP_REGNUM))])]
""
- "
{
- rtx op1;
-
- if (GET_CODE (operands[1]) != MEM)
- abort ();
-
+ gcc_assert (MEM_P (operands[1]));
if (flag_pic)
- {
- op1 = XEXP (operands[1], 0);
-
- /* It might be that code can be generated that jumps to 0 (or to a
- specific address). Don't abort on that. At least there's a
- test-case. */
- if (CONSTANT_ADDRESS_P (op1) && GET_CODE (op1) != CONST_INT)
- {
- if (no_new_pseudos)
- abort ();
-
- if (cris_gotless_symbol (op1))
- op1 = force_reg (Pmode, op1);
- else if (cris_symbol (op1))
- /* FIXME: Would hanging a REG_EQUIV/EQUAL on that register
- for the symbol cause bad recombinatorial effects? */
- op1 = force_reg (Pmode,
- gen_rtx_CONST
- (VOIDmode,
- gen_rtx_UNSPEC (VOIDmode,
- gen_rtvec (1, op1), 0)));
- else
- abort ();
-
- operands[1] = gen_rtx_MEM (GET_MODE (operands[1]), op1);
- }
- }
-}")
+ cris_expand_pic_call_address (&operands[1]);
+})
;; Accept *anything* as operand 2. The validity other than "general" of
;; operand 0 will be checked elsewhere. Accept operands for operand 1 in
@@ -3922,28 +3749,49 @@
;; We also accept a PLT symbol. We output it as [rPIC+sym:GOTPLT] rather
;; than requiring getting rPIC + sym:PLT into a register.
-(define_insn "*expanded_call_value"
- [(set (match_operand 0 "nonimmediate_operand" "=g,g,g,g")
- (call (mem:QI (match_operand:SI
- 1 "cris_general_operand_or_plt_symbol" "r,Q>,g,S"))
+(define_insn "*expanded_call_value_non_v32"
+ [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
+ (call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g"))
(match_operand 2 "" "")))
- (clobber (reg:SI 16))]
- "! TARGET_AVOID_GOTPLT"
+ (clobber (reg:SI CRIS_SRP_REGNUM))]
+ "!TARGET_V32"
"Jsr %1"
[(set_attr "cc" "clobber")])
-;; Same as above, since can't afford wasting a constraint letter to mean
-;; "S unless TARGET_AVOID_GOTPLT".
-(define_insn "*expanded_call_value_no_gotplt"
+;; See similar call special-case.
+(define_insn "*expanded_call_value_side"
[(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
- (call (mem:QI (match_operand:SI
- 1 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
- (match_operand 2 "" "")))
- (clobber (reg:SI 16))]
- "TARGET_AVOID_GOTPLT"
- "Jsr %1"
+ (call
+ (mem:QI
+ (mem:SI
+ (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r, r,r")
+ (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
+ (match_operand 3 "" "")))
+ (clobber (reg:SI CRIS_SRP_REGNUM))
+ (set (match_operand:SI 4 "register_operand" "=*1,r,r")
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+ "Jsr [%4=%1%S2]"
[(set_attr "cc" "clobber")])
+(define_insn "*expanded_call_value_v32"
+ [(set
+ (match_operand 0 "nonimmediate_operand" "=g,g,g,g")
+ (call
+ (mem:QI
+ (match_operand:SI 1 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 16))]
+ "TARGET_V32"
+ "@
+ Jsr %1%#
+ Jsr %1%#
+ Bsr %1%#
+ Bsr %1%#"
+ [(set_attr "cc" "clobber")
+ (set_attr "slottable" "has_call_slot")])
+
;; Used in debugging. No use for the direct pattern; unfilled
;; delayed-branches are taken care of by other means.
@@ -3953,6 +3801,20 @@
"nop"
[(set_attr "cc" "none")])
+;; We need to stop accesses to the stack after the memory is
+;; deallocated. Unfortunately, reorg doesn't look at naked clobbers,
+;; e.g. (insn ... (clobber (mem:BLK (stack_pointer_rtx)))) and we don't
+;; want to use a naked (unspec_volatile) as that would stop any
+;; scheduling in the epilogue. Hence we model it as a "real" insn that
+;; sets the memory in an unspecified manner. FIXME: Unfortunately it
+;; still has the effect of an unspec_volatile.
+(define_insn "cris_frame_deallocated_barrier"
+ [(set (mem:BLK (reg:SI CRIS_SP_REGNUM))
+ (unspec:BLK [(const_int 0)] CRIS_UNSPEC_FRAME_DEALLOC))]
+ ""
+ ""
+ [(set_attr "length" "0")])
+
;; We expand on casesi so we can use "bound" and "add offset fetched from
;; a table to pc" (adds.w [pc+%0.w],pc).
@@ -3960,7 +3822,7 @@
;; this expansion, you must change the macro ASM_OUTPUT_CASE_END
;; accordingly, to add the default case at the end of the jump-table.
-(define_expand "casesi"
+(define_expand "cris_casesi_non_v32"
[(set (match_dup 5) (match_operand:SI 0 "general_operand" ""))
(set (match_dup 6)
(minus:SI (match_dup 5)
@@ -3980,13 +3842,68 @@
(label_ref (match_operand 4 "" ""))))
(use (label_ref (match_operand 3 "" "")))])]
""
- "
{
operands[2] = plus_constant (operands[2], 1);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
operands[7] = gen_reg_rtx (SImode);
-}")
+})
+
+;; FIXME: Check effect of not JUMP_TABLES_IN_TEXT_SECTION.
+(define_expand "cris_casesi_v32"
+ [(set (match_dup 5) (match_operand:SI 0 "general_operand"))
+ (set (match_dup 6)
+ (minus:SI (match_dup 5)
+ (match_operand:SI 1 "const_int_operand")))
+ (set (match_dup 7)
+ (umin:SI (match_dup 6)
+ (match_operand:SI 2 "const_int_operand")))
+ (set (match_dup 8) (match_dup 11))
+ (set (match_dup 9)
+ (plus:SI (mult:SI (match_dup 7) (const_int 2))
+ (match_dup 8)))
+ (set (match_dup 10)
+ (plus:SI (sign_extend:SI (mem:HI (match_dup 9)))
+ (match_dup 9)))
+ (parallel
+ [(set (pc)
+ (if_then_else
+ (ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI) (match_dup 2))
+ (match_dup 10)
+ (label_ref (match_operand 4 "" ""))))
+ (use (label_ref (match_dup 3)))])]
+ "TARGET_V32"
+{
+ int i;
+ rtx xlabel = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
+ for (i = 5; i <= 10; i++)
+ operands[i] = gen_reg_rtx (SImode);
+ operands[2] = plus_constant (operands[2], 1);
+
+ /* Don't forget to decorate labels too, for PIC. */
+ operands[11] = flag_pic
+ ? gen_rtx_CONST (Pmode,
+ gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xlabel),
+ CRIS_UNSPEC_PCREL))
+ : xlabel;
+})
+
+(define_expand "casesi"
+ [(match_operand:SI 0 "general_operand")
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")
+ (match_operand 3 "" "")
+ (match_operand 4 "" "")]
+ ""
+{
+ if (TARGET_V32)
+ emit_insn (gen_cris_casesi_v32 (operands[0], operands[1], operands[2],
+ operands[3], operands[4]));
+ else
+ emit_insn (gen_cris_casesi_non_v32 (operands[0], operands[1], operands[2],
+ operands[3], operands[4]));
+ DONE;
+})
;; Split-patterns. Some of them have modes unspecified. This
;; should always be ok; if for no other reason sparc.md has it as
@@ -4006,7 +3923,9 @@
;; move ry,rz
;; op [rx],rz
;; Lose if rz=ry or rx=rz.
-;; Call this op-extend-split
+;; Call this op-extend-split.
+;; Do not match for V32; the addo and addi shouldn't be split
+;; up.
(define_split
[(set (match_operand 0 "register_operand" "")
@@ -4016,7 +3935,8 @@
(match_operator
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4045,7 +3965,8 @@
(match_operator
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4072,7 +3993,8 @@
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])
(match_operand 1 "register_operand" "")]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4097,7 +4019,8 @@
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])
(match_operand 1 "register_operand" "")]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4125,7 +4048,8 @@
3 "cris_orthogonal_operator"
[(match_operand 1 "register_operand" "")
(match_operand 2 "memory_operand" "")]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4148,7 +4072,8 @@
3 "cris_commutative_orth_op"
[(match_operand 2 "memory_operand" "")
(match_operand 1 "register_operand" "")]))]
- "REG_P (operands[0])
+ "!TARGET_V32
+ && REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
@@ -4171,7 +4096,8 @@
3 "cris_commutative_orth_op"
[(match_operand 1 "register_operand" "")
(match_operand 2 "memory_operand" "")]))]
- "REG_P (operands[0]) && REG_P (operands[1])
+ "!TARGET_V32
+ && REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& REG_P (XEXP (operands[2], 0))
@@ -4193,7 +4119,8 @@
3 "cris_orthogonal_operator"
[(match_operand 2 "memory_operand" "")
(match_operand 1 "register_operand" "")]))]
- "REG_P (operands[0]) && REG_P (operands[1])
+ "!TARGET_V32
+ && REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& REG_P (XEXP (operands[2], 0))
@@ -4214,29 +4141,32 @@
(define_split
[(parallel
[(set (match_operand 0 "register_operand" "")
- (mem (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" ""))
- (match_operand:SI 3 "register_operand" ""))))
+ (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
+ (match_operand:SI 3 "register_operand" ""))]))
(set (match_operand:SI 4 "register_operand" "")
- (plus:SI (mult:SI (match_dup 1)
- (match_dup 2))
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
(match_dup 3)))])]
"REG_P (operands[3]) && REG_P (operands[4])
&& REGNO (operands[3]) == REGNO (operands[4])"
[(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
- (match_dup 3)))
+ (match_dup 3)))
(set (match_dup 0) (match_dup 5))]
- "operands[5] = gen_rtx_MEM (GET_MODE (operands[0]), operands[3]);")
+ "operands[5] = replace_equiv_address (operands[6], operands[3]);")
;; move.S1 [rx=rx+i],ry
(define_split
[(parallel
[(set (match_operand 0 "register_operand" "")
- (mem
- (plus:SI (match_operand:SI 1 "cris_bdap_operand" "")
- (match_operand:SI 2 "cris_bdap_operand" ""))))
+ (match_operator
+ 5 "cris_mem_op"
+ [(plus:SI (match_operand:SI 1 "cris_bdap_operand" "")
+ (match_operand:SI 2 "cris_bdap_operand" ""))]))
(set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 1)
(match_dup 2)))])]
@@ -4244,17 +4174,22 @@
|| rtx_equal_p (operands[3], operands[2]))"
[(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (match_dup 4))]
- "operands[4] = gen_rtx_MEM (GET_MODE (operands[0]), operands[3]);")
+{
+ operands[4] = replace_equiv_address (operands[5], operands[3]);
+ cris_order_for_addsi3 (operands, 1);
+})
;; move.S1 ry,[rx=rx+rz.S2]
(define_split
[(parallel
- [(set (mem (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))
- (match_operand:SI 2 "register_operand" "")))
- (match_operand 3 "register_operand" ""))
+ [(set (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
+ (match_operand:SI 2 "register_operand" ""))])
+ (match_operand 3 "register_operand" ""))
(set (match_operand:SI 4 "register_operand" "")
(plus:SI (mult:SI (match_dup 0)
(match_dup 1))
@@ -4264,16 +4199,17 @@
[(set (match_dup 4) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
(match_dup 2)))
(set (match_dup 5) (match_dup 3))]
- "operands[5] = gen_rtx_MEM (GET_MODE (operands[3]), operands[4]);")
+ "operands[5] = replace_equiv_address (operands[6], operands[4]);")
;; move.S1 ry,[rx=rx+i]
(define_split
[(parallel
- [(set (mem
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
- (match_operand:SI 1 "cris_bdap_operand" "")))
- (match_operand 2 "register_operand" ""))
+ [(set (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
+ (match_operand:SI 1 "cris_bdap_operand" ""))])
+ (match_operand 2 "register_operand" ""))
(set (match_operand:SI 3 "register_operand" "")
(plus:SI (match_dup 0)
(match_dup 1)))])]
@@ -4281,53 +4217,16 @@
|| rtx_equal_p (operands[3], operands[1]))"
[(set (match_dup 3) (plus:SI (match_dup 0) (match_dup 1)))
(set (match_dup 5) (match_dup 2))]
- "operands[5] = gen_rtx_MEM (GET_MODE (operands[2]), operands[3]);")
-
-;; clear.d [rx=rx+rz.S2]
-
-(define_split
- [(parallel
- [(set (mem:SI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))
- (match_operand:SI 2 "register_operand" "")))
- (const_int 0))
- (set (match_operand:SI 3 "register_operand" "")
- (plus:SI (mult:SI (match_dup 0)
- (match_dup 1))
- (match_dup 2)))])]
- "REG_P (operands[2]) && REG_P (operands[3])
- && REGNO (operands[3]) == REGNO (operands[2])"
- [(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
- (match_dup 2)))
- (set (mem:SI (match_dup 3)) (const_int 0))]
- "")
-
-;; clear.w [rx=rx+rz.S2]
-
-(define_split
- [(parallel
- [(set (mem:HI (plus:SI
- (mult:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))
- (match_operand:SI 2 "register_operand" "")))
- (const_int 0))
- (set (match_operand:SI 3 "register_operand" "")
- (plus:SI (mult:SI (match_dup 0)
- (match_dup 1))
- (match_dup 2)))])]
- "REG_P (operands[2]) && REG_P (operands[3])
- && REGNO (operands[3]) == REGNO (operands[2])"
- [(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
- (match_dup 2)))
- (set (mem:HI (match_dup 3)) (const_int 0))]
- "")
+{
+ operands[5] = replace_equiv_address (operands[6], operands[3]);
+ cris_order_for_addsi3 (operands, 0);
+})
-;; clear.b [rx=rx+rz.S2]
+;; clear.[bwd] [rx=rx+rz.S2]
(define_split
[(parallel
- [(set (mem:QI (plus:SI
+ [(set (mem:BWD (plus:SI
(mult:SI (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))
(match_operand:SI 2 "register_operand" "")))
@@ -4340,48 +4239,14 @@
&& REGNO (operands[3]) == REGNO (operands[2])"
[(set (match_dup 3) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
(match_dup 2)))
- (set (mem:QI (match_dup 3)) (const_int 0))]
- "")
-
-;; clear.d [rx=rx+i]
-
-(define_split
- [(parallel
- [(set (mem:SI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
- (match_operand:SI 1 "cris_bdap_operand" "")))
- (const_int 0))
- (set (match_operand:SI 2 "register_operand" "")
- (plus:SI (match_dup 0)
- (match_dup 1)))])]
- "(rtx_equal_p (operands[0], operands[2])
- || rtx_equal_p (operands[2], operands[1]))"
- [(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))
- (set (mem:SI (match_dup 2)) (const_int 0))]
- "")
-
-;; clear.w [rx=rx+i]
-
-(define_split
- [(parallel
- [(set (mem:HI
- (plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
- (match_operand:SI 1 "cris_bdap_operand" "")))
- (const_int 0))
- (set (match_operand:SI 2 "register_operand" "")
- (plus:SI (match_dup 0)
- (match_dup 1)))])]
- "(rtx_equal_p (operands[0], operands[2])
- || rtx_equal_p (operands[2], operands[1]))"
- [(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))
- (set (mem:HI (match_dup 2)) (const_int 0))]
+ (set (mem:BWD (match_dup 3)) (const_int 0))]
"")
-;; clear.b [rx=rx+i]
+;; clear.[bwd] [rx=rx+i]
(define_split
[(parallel
- [(set (mem:QI
+ [(set (mem:BWD
(plus:SI (match_operand:SI 0 "cris_bdap_operand" "")
(match_operand:SI 1 "cris_bdap_operand" "")))
(const_int 0))
@@ -4391,8 +4256,8 @@
"(rtx_equal_p (operands[0], operands[2])
|| rtx_equal_p (operands[2], operands[1]))"
[(set (match_dup 2) (plus:SI (match_dup 0) (match_dup 1)))
- (set (mem:QI (match_dup 2)) (const_int 0))]
- "")
+ (set (mem:BWD (match_dup 2)) (const_int 0))]
+ "cris_order_for_addsi3 (operands, 0);")
;; mov(s|u).S1 [rx=rx+rz.S2],ry
@@ -4415,8 +4280,7 @@
[(set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
(match_dup 3)))
(set (match_dup 0) (match_op_dup 5 [(match_dup 6)]))]
- "operands[6] = gen_rtx_MEM (GET_MODE (XEXP (operands[5],0)),
- operands[4]);")
+ "operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);")
;; mov(s|u).S1 [rx=rx+i],ry
@@ -4435,8 +4299,10 @@
|| rtx_equal_p (operands[2], operands[3]))"
[(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (match_op_dup 4 [(match_dup 5)]))]
- "operands[5] = gen_rtx_MEM (GET_MODE (XEXP (operands[4], 0)),
- operands[3]);")
+{
+ operands[5] = replace_equiv_address (XEXP (operands[4], 0), operands[3]);
+ cris_order_for_addsi3 (operands, 1);
+})
;; op.S1 [rx=rx+i],ry
@@ -4456,7 +4322,10 @@
|| rtx_equal_p (operands[4], operands[3]))"
[(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
(set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 6)]))]
- "operands[6] = gen_rtx_MEM (GET_MODE (operands[0]), operands[4]);")
+{
+ operands[6] = replace_equiv_address (XEXP (operands[5], 1), operands[4]);
+ cris_order_for_addsi3 (operands, 2);
+})
;; op.S1 [rx=rx+rz.S2],ry
@@ -4480,7 +4349,7 @@
[(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
(match_dup 4)))
(set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 7)]))]
- "operands[7] = gen_rtx_MEM (GET_MODE (operands[0]), operands[5]);")
+ "operands[7] = replace_equiv_address (XEXP (operands[6], 1), operands[5]);")
;; op.S1 [rx=rx+rz.S2],ry (swapped)
@@ -4504,7 +4373,7 @@
[(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
(match_dup 4)))
(set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
- "operands[7] = gen_rtx_MEM (GET_MODE (operands[0]), operands[5]);")
+ "operands[7] = replace_equiv_address (XEXP (operands[6], 0), operands[5]);")
;; op.S1 [rx=rx+i],ry (swapped)
@@ -4524,7 +4393,10 @@
|| rtx_equal_p (operands[4], operands[3]))"
[(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
(set (match_dup 0) (match_op_dup 5 [(match_dup 6) (match_dup 1)]))]
- "operands[6] = gen_rtx_MEM (GET_MODE (operands[0]), operands[4]);")
+{
+ operands[6] = replace_equiv_address (XEXP (operands[5], 0), operands[4]);
+ cris_order_for_addsi3 (operands, 2);
+})
;; op(s|u).S1 [rx=rx+rz.S2],ry
@@ -4550,9 +4422,9 @@
[(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
(match_dup 4)))
(set (match_dup 0) (match_op_dup 6 [(match_dup 1) (match_dup 8)]))]
- "operands[8] = gen_rtx (GET_CODE (operands[7]), GET_MODE (operands[7]),
- gen_rtx_MEM (GET_MODE (XEXP (operands[7], 0)),
- operands[5]));")
+ "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[7]), GET_MODE (operands[7]),
+ replace_equiv_address (XEXP (operands[7], 0),
+ operands[5]));")
;; op(s|u).S1 [rx=rx+i],ry
@@ -4575,9 +4447,12 @@
|| rtx_equal_p (operands[4], operands[3]))"
[(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
(set (match_dup 0) (match_op_dup 5 [(match_dup 1) (match_dup 7)]))]
- "operands[7] = gen_rtx (GET_CODE (operands[6]), GET_MODE (operands[6]),
- gen_rtx_MEM (GET_MODE (XEXP (operands[6], 0)),
- operands[4]));")
+{
+ operands[7] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
+ replace_equiv_address (XEXP (operands[6], 0),
+ operands[4]));
+ cris_order_for_addsi3 (operands, 2);
+})
;; op(s|u).S1 [rx=rx+rz.S2],ry (swapped, plus or bound)
@@ -4602,9 +4477,9 @@
[(set (match_dup 5) (plus:SI (mult:SI (match_dup 2) (match_dup 3))
(match_dup 4)))
(set (match_dup 0) (match_op_dup 6 [(match_dup 8) (match_dup 1)]))]
- "operands[8] = gen_rtx (GET_CODE (operands[6]), GET_MODE (operands[6]),
- gen_rtx_MEM (GET_MODE (XEXP (operands[6], 0)),
- operands[5]));")
+ "operands[8] = gen_rtx_fmt_e (GET_CODE (operands[6]), GET_MODE (operands[6]),
+ replace_equiv_address (XEXP (operands[6], 0),
+ operands[5]));")
;; op(s|u).S1 [rx=rx+i],ry (swapped, plus or bound)
@@ -4626,9 +4501,12 @@
|| rtx_equal_p (operands[4], operands[3]))"
[(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3)))
(set (match_dup 0) (match_op_dup 6 [(match_dup 7) (match_dup 1)]))]
- "operands[7] = gen_rtx (GET_CODE (operands[5]), GET_MODE (operands[5]),
- gen_rtx_MEM (GET_MODE (XEXP (operands[5], 0)),
- operands[4]));")
+{
+ operands[7] = gen_rtx_fmt_e (GET_CODE (operands[5]), GET_MODE (operands[5]),
+ replace_equiv_address (XEXP (operands[5], 0),
+ operands[4]));
+ cris_order_for_addsi3 (operands, 2);
+})
;; Splits for addressing prefixes that have no side-effects, so we can
;; fill a delay slot. Never split if we lose something, though.
@@ -4645,18 +4523,18 @@
;; 2001-08-24, unwind-dw2-fde.c, _Unwind_Find_FDE ICE in
;; cselib_invalidate_regno.
-(define_split
+(define_split ; indir_to_reg_split
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "indirect_operand" ""))]
"reload_completed
&& REG_P (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
- && (GET_CODE (XEXP (operands[1], 0)) == MEM
- || CONSTANT_P (XEXP (operands[1], 0)))"
+ && (MEM_P (XEXP (operands[1], 0)) || CONSTANT_P (XEXP (operands[1], 0)))
+ && REGNO (operands[0]) < CRIS_LAST_GENERAL_REGISTER"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 0) (match_dup 3))]
"operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
- operands[3] = gen_rtx_MEM (GET_MODE (operands[0]), operands[2]);
+ operands[3] = replace_equiv_address (operands[1], operands[2]);
operands[4] = XEXP (operands[1], 0);")
;; As the above, but MOVS and MOVU.
@@ -4669,12 +4547,12 @@
"reload_completed
&& REG_P (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
- && (GET_CODE (XEXP (operands[1], 0)) == MEM
+ && (MEM_P (XEXP (operands[1], 0))
|| CONSTANT_P (XEXP (operands[1], 0)))"
[(set (match_dup 2) (match_dup 5))
(set (match_dup 0) (match_op_dup 4 [(match_dup 3)]))]
"operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
- operands[3] = gen_rtx_MEM (GET_MODE (XEXP (operands[4], 0)), operands[2]);
+ operands[3] = replace_equiv_address (XEXP (operands[4], 0), operands[2]);
operands[5] = XEXP (operands[1], 0);")
;; Various peephole optimizations.
@@ -4686,96 +4564,88 @@
;; to keep changes local to their cause.
;;
;; Do not add patterns that you do not know will be matched.
-;; Please also add a self-contained test-case.
+;; Please also add a self-contained testcase.
;; We have trouble with and:s and shifts. Maybe something is broken in
-;; gcc? Or it could just be that bitfield insn expansion is a bit
+;; gcc? Or it could just be that bit-field insn expansion is a bit
;; suboptimal when not having extzv insns.
+;; Testcase for the following four peepholes: gcc.dg/cris-peep2-xsrand.c
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; asrandb (peephole casesi+31)
+ [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
(and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 255
- && INTVAL (operands[1]) > 23"
-
-;; The m flag should be ignored, because this will be a *byte* "and"
-;; operation.
-
- "*
+ && INTVAL (operands[1]) > 23
+ /* Check that the and-operation enables us to use logical-shift. */
+ && (INTVAL (operands[2])
+ & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
+ ;; FIXME: CC0 is valid except for the M bit.
{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.b %2,%0\";
-}")
+ operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
+ operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
+})
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; asrandw (peephole casesi+32)
+ [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 65535
&& INTVAL (operands[2]) != 255
- && INTVAL (operands[1]) > 15"
-
-;; The m flag should be ignored, because this will be a *word* "and"
-;; operation.
-
- "*
+ && INTVAL (operands[1]) > 15
+ /* Check that the and-operation enables us to use logical-shift. */
+ && (INTVAL (operands[2])
+ & ((HOST_WIDE_INT) -1 << (32 - INTVAL (operands[1])))) == 0"
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
+ ;; FIXME: CC0 is valid except for the M bit.
{
- cc_status.flags |= CC_NOT_NEGATIVE;
+ operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
+ operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
+})
- return \"lsrq %1,%0\;and.w %2,%0\";
-}")
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; lsrandb (peephole casesi+33)
+ [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31
&& INTVAL (operands[2]) < 255
&& INTVAL (operands[1]) > 23"
-
-;; The m flag should be ignored, because this will be a *byte* "and"
-;; operation.
-
- "*
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:QI (match_dup 3) (match_dup 4)))]
+ ;; FIXME: CC0 is valid except for the M bit.
{
- cc_status.flags |= CC_NOT_NEGATIVE;
+ operands[3] = gen_rtx_REG (QImode, REGNO (operands[0]));
+ operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode));
+})
- return \"lsrq %1,%0\;and.b %2,%0\";
-}")
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
+(define_peephole2 ; lsrandw (peephole casesi+34)
+ [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_dup 0)
- (match_operand:SI 1 "const_int_operand" "n")))
+ (match_operand:SI 1 "const_int_operand" "")))
(set (match_dup 0)
- (and:SI (match_dup 0)
- (match_operand 2 "const_int_operand" "n")))]
+ (and:SI (match_dup 0) (match_operand 2 "const_int_operand" "")))]
"INTVAL (operands[2]) > 31 && INTVAL (operands[2]) < 65535
&& INTVAL (operands[2]) != 255
&& INTVAL (operands[1]) > 15"
-
-;; The m flag should be ignored, because this will be a *word* "and"
-;; operation.
-
- "*
+ [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 3) (and:HI (match_dup 3) (match_dup 4)))]
+ ;; FIXME: CC0 is valid except for the M bit.
{
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"lsrq %1,%0\;and.w %2,%0\";
-}")
+ operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
+ operands[4] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), HImode));
+})
;; Change
@@ -4785,38 +4655,66 @@
;; move [rx=rx+n],ry
;; when -128 <= n <= 127.
;; This will reduce the size of the assembler code for n = [-128..127],
-;; and speed up accordingly.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (match_operand 3 "register_operand" "=r")
- (mem (match_dup 0)))]
- "GET_MODE (operands[3]) != DImode
- && REGNO (operands[3]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
- "move.%s3 [%0=%1%S2],%3")
+;; and speed up accordingly. Don't match if the previous insn is
+;; (set rx rz) because that combination is matched by another peephole.
+;; No stable test-case.
+
+(define_peephole2 ; moversideqi (peephole casesi+35)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand 3 "register_operand" "")
+ (match_operator 4 "cris_mem_op" [(match_dup 0)]))]
+ "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
+ && REGNO (operands[3]) != REGNO (operands[0])
+ && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
+ && TARGET_SIDE_EFFECT_PREFIXES"
+ [(parallel
+ [(set (match_dup 3) (match_dup 5))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ ;; Checking the previous insn is a bit too awkward for the condition.
+{
+ rtx prev = prev_nonnote_insn (curr_insn);
+ if (prev != NULL_RTX)
+ {
+ rtx set = single_set (prev);
+ if (set != NULL_RTX
+ && REG_S_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) == REGNO (operands[0])
+ && REG_S_P (SET_SRC (set)))
+ FAIL;
+ }
+ operands[5]
+ = replace_equiv_address (operands[4],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));
+})
;; Vice versa: move ry,[rx=rx+n]
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (mem (match_dup 0))
- (match_operand 3 "register_operand" "=r"))]
- "GET_MODE (operands[3]) != DImode
- && REGNO (operands[3]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
- "move.%s3 %3,[%0=%1%S2]"
- [(set_attr "cc" "none")])
+(define_peephole2 ; movemsideqi (peephole casesi+36)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operator 3 "cris_mem_op" [(match_dup 0)])
+ (match_operand 4 "register_operand" ""))]
+ "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
+ && REGNO (operands[4]) != REGNO (operands[0])
+ && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
+ && TARGET_SIDE_EFFECT_PREFIXES"
+ [(parallel
+ [(set (match_dup 5) (match_dup 4))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ "operands[5]
+ = replace_equiv_address (operands[3],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));")
;; As above, change:
;; add.d n,rx
@@ -4829,175 +4727,155 @@
;; out of hand. They probably will not save the time they take typing in,
;; not to mention the bugs that creep in. FIXME: Get rid of as many of
;; the splits and peepholes as possible.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "n")))
- (set (match_operand 3 "register_operand" "=r")
- (match_operator 4 "cris_orthogonal_operator"
- [(match_dup 3)
- (mem (match_dup 0))]))]
+;; No stable test-case.
+
+(define_peephole2 ; mover2side (peephole casesi+37)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand 3 "register_operand" "")
+ (match_operator 4 "cris_orthogonal_operator"
+ [(match_dup 3)
+ (match_operator
+ 5 "cris_mem_op" [(match_dup 0)])]))]
+ ;; FIXME: What about DFmode?
+ ;; Change to GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD?
"GET_MODE (operands[3]) != DImode
- && REGNO (operands[0]) != REGNO (operands[3])
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
- && INTVAL (operands[2]) >= -128
- && INTVAL (operands[2]) <= 127"
- "%x4.%s3 [%0=%1%S2],%3")
+ && REGNO (operands[0]) != REGNO (operands[3])
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
+ && INTVAL (operands[2]) >= -128
+ && INTVAL (operands[2]) <= 127
+ && TARGET_SIDE_EFFECT_PREFIXES"
+ [(parallel
+ [(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)]))
+ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
+ "operands[6]
+ = replace_equiv_address (operands[5],
+ gen_rtx_PLUS (SImode,
+ operands[1], operands[2]));")
;; Sometimes, for some reason the pattern
;; move x,rx
;; add y,rx
;; move [rx],rz
;; will occur. Solve this, and likewise for to-memory.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
- (set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (mem (match_dup 0)))]
- "(rtx_equal_p (operands[2], operands[0])
- || rtx_equal_p (operands[3], operands[0]))
- && cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- move.%s4 [%0=%1%S3],%4
- move.%s4 [%0=%3%S1],%4
- move.%s4 [%0=%1%S2],%4
- move.%s4 [%0=%2%S1],%4")
-
-;; As above but to memory.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
+(define_peephole2 ; moverside (peephole casesi+38)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "cris_bdap_biap_operand" ""))
(set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (mem (match_dup 0))
- (match_operand 4 "register_operand" "=r,r,r,r"))]
+ (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
+ (match_operand:SI 3 "cris_bdap_biap_operand" "")))
+ (set (match_operand 4 "register_operand" "")
+ (match_operator 5 "cris_mem_op" [(match_dup 0)]))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[3], operands[0]))
&& cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- move.%s4 %4,[%0=%1%S3]
- move.%s4 %4,[%0=%3%S1]
- move.%s4 %4,[%0=%1%S2]
- move.%s4 %4,[%0=%2%S1]"
- [(set_attr "cc" "none")])
+ (REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ (! REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ -1, 4)"
+ [(parallel
+ [(set (match_dup 4) (match_dup 6))
+ (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
+{
+ rtx otherop
+ = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
+ /* Make sure we have canonical RTX so we match the insn pattern -
+ not a constant in the first operand. We also require the order
+ (plus reg mem) to match the final pattern. */
+ if (CONSTANT_P (otherop) || MEM_P (otherop))
+ {
+ operands[7] = operands[1];
+ operands[8] = otherop;
+ }
+ else
+ {
+ operands[7] = otherop;
+ operands[8] = operands[1];
+ }
+ operands[6]
+ = replace_equiv_address (operands[5],
+ gen_rtx_PLUS (SImode,
+ operands[7], operands[8]));
+})
-;; As the move from-memory above, but with an operation.
+;; As above but to memory.
+;; FIXME: Split movemside and moverside into variants and prune
+;; the ones that don't trig.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
+(define_peephole2 ; movemside (peephole casesi+39)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "cris_bdap_biap_operand" ""))
(set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (match_operator 5 "cris_orthogonal_operator"
- [(match_dup 3)
- (mem (match_dup 0))]))]
+ (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "")
+ (match_operand:SI 3 "cris_bdap_biap_operand" "")))
+ (set (match_operator 4 "cris_mem_op" [(match_dup 0)])
+ (match_operand 5 "register_operand" ""))]
"(rtx_equal_p (operands[2], operands[0])
|| rtx_equal_p (operands[3], operands[0]))
&& cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- %x5.%s4 [%0=%1%S3],%4
- %x5.%s4 [%0=%3%S1],%4
- %x5.%s4 [%0=%1%S2],%4
- %x5.%s4 [%0=%2%S1],%4")
-
-;; Same, but with swapped operands (and commutative operation).
+ (REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ (! REG_S_P (operands[1])
+ ? 1
+ : (rtx_equal_p (operands[2], operands[0])
+ ? 3 : 2)),
+ -1, 5)"
+ [(parallel
+ [(set (match_dup 6) (match_dup 5))
+ (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 8)))])]
+{
+ rtx otherop
+ = rtx_equal_p (operands[2], operands[0]) ? operands[3] : operands[2];
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,>Rn,r,>Rn"))
- (set (match_dup 0)
- (plus:SI (match_operand:SI 2 "cris_bdap_biap_operand" "0,0,r>Rn,r")
- (match_operand:SI 3 "cris_bdap_biap_operand" "r>Rn,r,0,0")))
- (set (match_operand 4 "register_operand" "=r,r,r,r")
- (match_operator 5 "cris_commutative_orth_op"
- [(mem (match_dup 0))
- (match_dup 3)]))]
- "(rtx_equal_p (operands[2], operands[0])
- || rtx_equal_p (operands[3], operands[0]))
- && cris_side_effect_mode_ok (PLUS, operands, 0,
- (REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- (! REG_S_P (operands[1])
- ? 1
- : (rtx_equal_p (operands[2], operands[0])
- ? 3 : 2)),
- -1, 4)"
- "@
- %x5.%s4 [%0=%1%S3],%4
- %x5.%s4 [%0=%3%S1],%4
- %x5.%s4 [%0=%1%S2],%4
- %x5.%s4 [%0=%2%S1],%4")
+ /* Make sure we have canonical RTX so we match the insn pattern -
+ not a constant in the first operand. We also require the order
+ (plus reg mem) to match the final pattern. */
+ if (CONSTANT_P (otherop) || MEM_P (otherop))
+ {
+ operands[7] = operands[1];
+ operands[8] = otherop;
+ }
+ else
+ {
+ operands[7] = otherop;
+ operands[8] = operands[1];
+ }
+ operands[6]
+ = replace_equiv_address (operands[4],
+ gen_rtx_PLUS (SImode,
+ operands[7], operands[8]));
+})
;; Another spotted bad code:
;; move rx,ry
;; move [ry],ry
+;; No stable test-case.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))
- (set (match_operand 2 "register_operand" "=r")
- (mem (match_dup 0)))]
- "REGNO (operands[0]) == REGNO (operands[2])
- && GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
- "move.%s2 [%1],%0"
- [(set_attr "slottable" "yes")])
-
-;; And a simple variant with extended operand.
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))
- (set (match_operand 2 "register_operand" "=r")
- (match_operator 3 "cris_extend_operator" [(mem (match_dup 0))]))]
+(define_peephole2 ; movei (peephole casesi+42)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (set (match_operand 2 "register_operand" "")
+ (match_operator 3 "cris_mem_op" [(match_dup 0)]))]
"REGNO (operands[0]) == REGNO (operands[2])
+ && (REGNO_REG_CLASS (REGNO (operands[0]))
+ == REGNO_REG_CLASS (REGNO (operands[1])))
&& GET_MODE_SIZE (GET_MODE (operands[2])) <= UNITS_PER_WORD"
- "mov%e3.%m3 [%1],%0"
- [(set_attr "slottable" "yes")])
-
-;; Here are all peepholes that have a saved testcase.
-;; Do not add new peepholes without testcases.
+ [(set (match_dup 2) (match_dup 4))]
+ "operands[4] = replace_equiv_address (operands[3], operands[1]);")
-;; peep-1:
;; move.d [r10+16],r9
;; and.d r12,r9
;; change to
@@ -5010,28 +4888,29 @@
;; register pressure.
;; Note that adding the noncommutative variant did not show any matches
;; in ipps and cc1, so it's not here.
+;; No stable test-case.
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r,r,r,r")
- (mem (plus:SI
- (match_operand:SI 1 "cris_bdap_biap_operand" "r,r>Rn,r,r>Rn")
- (match_operand:SI 2 "cris_bdap_biap_operand" "r>Rn,r,r>Rn,r"))))
+(define_peephole2 ; op3 (peephole casesi+44)
+ [(set (match_operand 0 "register_operand" "")
+ (match_operator
+ 6 "cris_mem_op"
+ [(plus:SI
+ (match_operand:SI 1 "cris_bdap_biap_operand" "")
+ (match_operand:SI 2 "cris_bdap_biap_operand" ""))]))
(set (match_dup 0)
- (match_operator 5 "cris_commutative_orth_op"
- [(match_operand 3 "register_operand" "0,0,r,r")
- (match_operand 4 "register_operand" "r,r,0,0")]))]
+ (match_operator
+ 5 "cris_commutative_orth_op"
+ [(match_operand 3 "register_operand" "")
+ (match_operand 4 "register_operand" "")]))]
"(rtx_equal_p (operands[3], operands[0])
|| rtx_equal_p (operands[4], operands[0]))
&& ! rtx_equal_p (operands[3], operands[4])
&& (REG_S_P (operands[1]) || REG_S_P (operands[2]))
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD"
- "@
- %x5.%s0 [%1%S2],%4,%0
- %x5.%s0 [%2%S1],%4,%0
- %x5.%s0 [%1%S2],%3,%0
- %x5.%s0 [%2%S1],%3,%0")
+ [(set (match_dup 0) (match_op_dup 5 [(match_dup 7) (match_dup 6)]))]
+ "operands[7]
+ = rtx_equal_p (operands[3], operands[0]) ? operands[4] : operands[3];")
-;; peep-2:
;; I cannot tell GCC (2.1, 2.7.2) how to correctly reload an instruction
;; that looks like
;; and.b some_byte,const,reg_32
@@ -5039,61 +4918,167 @@
;; It should be:
;; movu.b some_byte,reg_32
;; and.b const,reg_32
-;; but is turns into:
+;; but it turns into:
;; move.b some_byte,reg_32
;; and.d const,reg_32
;; Fix it here.
+;; Testcases: gcc.dg/cris-peep2-andu1.c gcc.dg/cris-peep2-andu2.c
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "nonimmediate_operand" "rm"))
- (set (match_operand:SI 2 "register_operand" "=0")
+(define_peephole2 ; andu (casesi+45)
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "nonimmediate_operand" ""))
+ (set (match_operand:SI 2 "register_operand" "")
(and:SI (match_dup 0)
- (match_operand:SI 3 "const_int_operand" "n")))]
-
+ (match_operand:SI 3 "const_int_operand" "")))]
;; Since the size of the memory access could be made different here,
;; don't do this for a mem-volatile access.
-
"REGNO (operands[2]) == REGNO (operands[0])
&& INTVAL (operands[3]) <= 65535 && INTVAL (operands[3]) >= 0
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
- && (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
- "*
+ && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
+ && !side_effects_p (operands[1])
+ && (!REG_P (operands[1])
+ || REGNO (operands[1]) <= CRIS_LAST_GENERAL_REGISTER)"
+ ;; FIXME: CC0 valid except for M (i.e. CC_NOT_NEGATIVE).
+ [(set (match_dup 0) (match_dup 4))
+ (set (match_dup 5) (match_dup 6))]
{
- if (CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O'))
- return \"movu.%z3 %1,%0\;andq %b3,%0\";
-
- cc_status.flags |= CC_NOT_NEGATIVE;
-
- return \"movu.%z3 %1,%0\;and.%z3 %3,%0\";
-}")
-
-;; peep-3
-
-(define_peephole
- [(set (match_operand 0 "register_operand" "=r")
- (match_operand 1 "nonimmediate_operand" "rm"))
- (set (match_operand:SI 2 "register_operand" "=r")
- (and:SI (subreg:SI (match_dup 0) 0)
- (match_operand 3 "const_int_operand" "n")))]
+ enum machine_mode zmode = INTVAL (operands[3]) <= 255 ? QImode : HImode;
+ enum machine_mode amode
+ = CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O') ? SImode : zmode;
+ rtx op1
+ = (REG_S_P (operands[1])
+ ? gen_rtx_REG (zmode, REGNO (operands[1]))
+ : adjust_address (operands[1], zmode, 0));
+ operands[4]
+ = gen_rtx_ZERO_EXTEND (SImode, op1);
+ operands[5] = gen_rtx_REG (amode, REGNO (operands[0]));
+ operands[6]
+ = gen_rtx_AND (amode, gen_rtx_REG (amode, REGNO (operands[0])),
+ GEN_INT (trunc_int_for_mode (INTVAL (operands[3]),
+ amode == SImode
+ ? QImode : amode)));
+})
+
+;; Try and avoid GOTPLT reads escaping a call: transform them into
+;; PLT. Curiously (but thankfully), peepholes for instructions
+;; *without side-effects* that just feed a call (or call_value) are
+;; not matched neither in a build or test-suite, so those patterns are
+;; omitted.
+
+;; A "normal" move where we don't check the consumer.
+
+(define_peephole2 ; gotplt-to-plt
+ [(set
+ (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI
+ 1 "cris_mem_op"
+ [(plus:SI
+ (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_operand:SI 2 "cris_general_operand_or_symbol" "")]
+ CRIS_UNSPEC_PLTGOTREAD)))]))]
+ "flag_pic
+ && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
+ && REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
+ [(set (match_dup 0) (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
+ "")
- ;; Since the size of the memory access could be made different here,
- ;; don't do this for a mem-volatile access.
+;; And one set with a side-effect getting the PLTGOT offset.
+;; First call and call_value variants.
- "REGNO (operands[0]) == REGNO (operands[2])
- && INTVAL (operands[3]) > 0
- && INTVAL (operands[3]) <= 65535
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'I')
- && (GET_CODE (operands[1]) != MEM || ! MEM_VOLATILE_P (operands[1]))"
- "*
-{
- if (CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'O'))
- return \"movu.%z3 %1,%0\;andq %b3,%0\";
+(define_peephole2 ; gotplt-to-plt-side-call
+ [(parallel
+ [(set
+ (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI
+ 1 "cris_mem_op"
+ [(plus:SI
+ (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_operand:SI
+ 2 "cris_general_operand_or_symbol" "")]
+ CRIS_UNSPEC_PLTGOTREAD)))]))
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])
+ (parallel [(call (mem:QI (match_dup 0))
+ (match_operand 4 "" ""))
+ (clobber (reg:SI CRIS_SRP_REGNUM))])]
+ "flag_pic
+ && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
+ && peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(call (mem:QI (match_dup 1))
+ (match_dup 4))
+ (clobber (reg:SI CRIS_SRP_REGNUM))
+ (set (match_dup 3)
+ (plus:SI (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_dup 2)]
+ CRIS_UNSPEC_PLTGOTREAD))))])]
+ "")
- cc_status.flags |= CC_NOT_NEGATIVE;
+(define_peephole2 ; gotplt-to-plt-side-call-value
+ [(parallel
+ [(set
+ (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI
+ 1 "cris_mem_op"
+ [(plus:SI
+ (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_operand:SI
+ 2 "cris_general_operand_or_symbol" "")]
+ CRIS_UNSPEC_PLTGOTREAD)))]))
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])
+ (parallel [(set (match_operand 5 "" "")
+ (call (mem:QI (match_dup 0))
+ (match_operand 4 "" "")))
+ (clobber (reg:SI CRIS_SRP_REGNUM))])]
+ "flag_pic
+ && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
+ && peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 5)
+ (call (mem:QI (match_dup 1))
+ (match_dup 4)))
+ (clobber (reg:SI CRIS_SRP_REGNUM))
+ (set (match_dup 3)
+ (plus:SI (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_dup 2)]
+ CRIS_UNSPEC_PLTGOTREAD))))])]
+ "")
- return \"movu.%z3 %1,%0\;and.%z3 %3,%0\";
-}")
+(define_peephole2 ; gotplt-to-plt-side
+ [(parallel
+ [(set
+ (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI
+ 1 "cris_mem_op"
+ [(plus:SI
+ (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_operand:SI
+ 2 "cris_general_operand_or_symbol" "")]
+ CRIS_UNSPEC_PLTGOTREAD)))]))
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (reg:SI CRIS_GOT_REGNUM)
+ (const:SI
+ (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])]
+ "flag_pic
+ && cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
+ && REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
+ [(set (match_dup 3)
+ (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD)))
+ (set (match_dup 3) (plus:SI (match_dup 3) (reg:SI CRIS_GOT_REGNUM)))
+ (set (match_dup 0)
+ (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
+ "")
;; Local variables:
;; mode:emacs-lisp