arm.md revision 90075
163248Speter;;- Machine description for ARM for GNU compiler
263248Speter;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
349887Snsayer;;  2001, 2002  Free Software Foundation, Inc.
449887Snsayer;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
549887Snsayer;;  and Martin Simmons (@harleqn.co.uk).
649887Snsayer;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
749887Snsayer
849887Snsayer;; This file is part of GNU CC.
949887Snsayer
1049887Snsayer;; GNU CC is free software; you can redistribute it and/or modify
1149887Snsayer;; it under the terms of the GNU General Public License as published by
1249887Snsayer;; the Free Software Foundation; either version 2, or (at your option)
1349887Snsayer;; any later version.
1449887Snsayer
1549887Snsayer;; GNU CC is distributed in the hope that it will be useful,
1676339Snsayer;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1776339Snsayer;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1876339Snsayer;; GNU General Public License for more details.
1976339Snsayer
2076610Snsayer;; You should have received a copy of the GNU General Public License
2176610Snsayer;; along with GNU CC; see the file COPYING.  If not, write to
2249887Snsayer;; the Free Software Foundation, 59 Temple Place - Suite 330,
2349887Snsayer;; Boston, MA 02111-1307, USA.
2449887Snsayer
2549887Snsayer;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
2649887Snsayer
2749887Snsayer;; There are patterns in this file to support XFmode arithmetic.
2849887Snsayer;; Unfortunately RISC iX doesn't work well with these so they are disabled.
2949887Snsayer;; (See arm.h)
3049887Snsayer
3149887Snsayer;;---------------------------------------------------------------------------
3249887Snsayer;; Constants
3376610Snsayer
3476610Snsayer;; Register numbers
3549887Snsayer(define_constants
3649887Snsayer  [(IP_REGNUM	    12)		; Scratch register
3749887Snsayer   (SP_REGNUM	    13)		; Stack pointer
3849887Snsayer   (LR_REGNUM       14)		; Return address register
3949887Snsayer   (PC_REGNUM	    15)		; Program counter
4049887Snsayer   (CC_REGNUM       24)		; Condition code pseudo register
4149887Snsayer   (LAST_ARM_REGNUM 15)
4249887Snsayer  ]
4349887Snsayer)
4449887Snsayer
4549887Snsayer;; UNSPEC Usage:
4649887Snsayer;; Note: sin and cos are no-longer used.
4749887Snsayer
4849887Snsayer(define_constants
4949887Snsayer  [(UNSPEC_SIN       0)	; `sin' operation (MODE_FLOAT):
5049887Snsayer			;   operand 0 is the result,
5149887Snsayer			;   operand 1 the parameter.
5249887Snsayer   (UNPSEC_COS	     1)	; `cos' operation (MODE_FLOAT):
5349887Snsayer			;   operand 0 is the result,
5449887Snsayer			;   operand 1 the parameter.
5549887Snsayer   (UNSPEC_PUSH_MULT 2)	; `push multiple' operation:
5649887Snsayer			;   operand 0 is the first register,
5749887Snsayer			;   subsequent registers are in parallel (use ...)
5849887Snsayer			;   expressions.
5949887Snsayer   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
6049887Snsayer			;   usage, that is, we will add the pic_register
6149887Snsayer			;   value to it before trying to dereference it.
6249887Snsayer   (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
6349887Snsayer			;   being scheduled before the stack adjustment insn.
6449887Snsayer   (UNSPEC_CLZ	     5) ; `clz' instruction, count leading zeros (SImode):
6549887Snsayer			;   operand 0 is the result,
6649887Snsayer			;   operand 1 is the parameter.
6749887Snsayer   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
6849887Snsayer   			; this unspec is used to prevent the deletion of
6949887Snsayer   			; instructions setting registers for EH handling
7049887Snsayer   			; and stack frame generation.  Operand 0 is the
7149887Snsayer   			; register to "use".
7249887Snsayer  ]
7349887Snsayer)
7449887Snsayer
7549887Snsayer;; UNSPEC_VOLATILE Usage:
7649887Snsayer
7749887Snsayer(define_constants
7849887Snsayer  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
7949887Snsayer			;   insn in the code.
8049887Snsayer   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
8149887Snsayer			;   instruction epilogue sequence that isn't expanded
8249887Snsayer			;   into normal RTL.  Used for both normal and sibcall
8349887Snsayer			;   epilogues.
8449887Snsayer   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
8549887Snsayer			;   for inlined constants.
8649887Snsayer   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
8749887Snsayer			;   table.
8849887Snsayer   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
8949887Snsayer			;   an 8-bit object.
9049887Snsayer   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
9149887Snsayer			;   a 16-bit object.
9249887Snsayer   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
9349887Snsayer			;   a 32-bit object.
9449887Snsayer   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
9549887Snsayer			;   a 64-bit object.
9649887Snsayer  ]
9749887Snsayer)
9849887Snsayer
9949887Snsayer;;---------------------------------------------------------------------------
10049887Snsayer;; Attributes
10149887Snsayer
10249887Snsayer; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
10349887Snsayer; generating ARM code.  This is used to control the length of some insn
10449887Snsayer; patterns that share the same RTL in both ARM and Thumb code.
10549887Snsayer(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
10649887Snsayer
10749887Snsayer; PROG_MODE attribute is used to determine whether condition codes are
10849887Snsayer; clobbered by a call insn: they are if in prog32 mode.  This is controlled
10949887Snsayer; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
11049887Snsayer(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
11149887Snsayer
11249887Snsayer; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
11349887Snsayer; scheduling decisions for the load unit and the multiplier.
11449887Snsayer(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
11549887Snsayer
11649887Snsayer;; Operand number of an input operand that is shifted.  Zero if the
11749887Snsayer;; given instruction does not shift one of its input operands.
11849887Snsayer(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
11949887Snsayer(define_attr "shift" "" (const_int 0))
12049887Snsayer
12149887Snsayer; Floating Point Unit.  If we only have floating point emulation, then there
12249887Snsayer; is no point in scheduling the floating point insns.  (Well, for best
12349887Snsayer; performance we should try and group them together).
12449887Snsayer(define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
12549887Snsayer
12649887Snsayer; LENGTH of an instruction (in bytes)
12749887Snsayer(define_attr "length" "" (const_int 4))
12849887Snsayer
12949887Snsayer; POOL_RANGE is how far away from a constant pool entry that this insn
13049887Snsayer; can be placed.  If the distance is zero, then this insn will never
13149887Snsayer; reference the pool.
13249887Snsayer; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
13349887Snsayer; before its address.
13449887Snsayer(define_attr "pool_range" "" (const_int 0))
13549887Snsayer(define_attr "neg_pool_range" "" (const_int 0))
13649887Snsayer
13749887Snsayer; An assembler sequence may clobber the condition codes without us knowing.
13849887Snsayer(define_asm_attributes
13949887Snsayer [(set_attr "conds" "clob")])
14049887Snsayer
14149887Snsayer; TYPE attribute is used to detect floating point instructions which, if
14249887Snsayer; running on a co-processor can run in parallel with other, basic instructions
14349887Snsayer; If write-buffer scheduling is enabled then it can also be used in the
14449887Snsayer; scheduling of writes.
14549887Snsayer
14649887Snsayer; Classification of each insn
14749887Snsayer; normal	any data instruction that doesn't hit memory or fp regs
14849887Snsayer; mult		a multiply instruction
14949887Snsayer; block		blockage insn, this blocks all functional units
15049887Snsayer; float		a floating point arithmetic operation (subject to expansion)
15149887Snsayer; fdivx		XFmode floating point division
15249887Snsayer; fdivd		DFmode floating point division
15349887Snsayer; fdivs		SFmode floating point division
15449887Snsayer; fmul		Floating point multiply
15549887Snsayer; ffmul		Fast floating point multiply
15649887Snsayer; farith	Floating point arithmetic (4 cycle)
15749887Snsayer; ffarith	Fast floating point arithmetic (2 cycle)
15849887Snsayer; float_em	a floating point arithmetic operation that is normally emulated
15949887Snsayer;		even on a machine with an fpa.
16049887Snsayer; f_load	a floating point load from memory
16149887Snsayer; f_store	a floating point store to memory
16249887Snsayer; f_mem_r	a transfer of a floating point register to a real reg via mem
16349887Snsayer; r_mem_f	the reverse of f_mem_r
16449887Snsayer; f_2_r		fast transfer float to arm (no memory needed)
16549887Snsayer; r_2_f		fast transfer arm to float
16649887Snsayer; call		a subroutine call
16749887Snsayer; load		any load from memory
16849887Snsayer; store1	store 1 word to memory from arm registers
16949887Snsayer; store2	store 2 words
17049887Snsayer; store3	store 3 words
17149887Snsayer; store4	store 4 words
17249887Snsayer;
17349887Snsayer(define_attr "type"
17449887Snsayer	"normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4" 
17549887Snsayer	(const_string "normal"))
17649887Snsayer
17749887Snsayer; Load scheduling, set from the arm_ld_sched variable
17849887Snsayer; initialised by arm_override_options() 
17949887Snsayer(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
18049887Snsayer
18149887Snsayer; condition codes: this one is used by final_prescan_insn to speed up
18249887Snsayer; conditionalizing instructions.  It saves having to scan the rtl to see if
18349887Snsayer; it uses or alters the condition codes.
18449887Snsayer; 
18549887Snsayer; USE means that the condition codes are used by the insn in the process of
18649887Snsayer;   outputting code, this means (at present) that we can't use the insn in
18749887Snsayer;   inlined branches
18849887Snsayer;
18949887Snsayer; SET means that the purpose of the insn is to set the condition codes in a
19049887Snsayer;   well defined manner.
19149887Snsayer;
19249887Snsayer; CLOB means that the condition codes are altered in an undefined manner, if
19349887Snsayer;   they are altered at all
19449887Snsayer;
19549887Snsayer; JUMP_CLOB is used when the condition cannot be represented by a single
19649887Snsayer;   instruction (UNEQ and LTGT).  These cannot be predicated.
19749887Snsayer;
19849887Snsayer; NOCOND means that the condition codes are neither altered nor affect the
19949887Snsayer;   output of this insn
20049887Snsayer
20149887Snsayer(define_attr "conds" "use,set,clob,jump_clob,nocond"
20249887Snsayer	(if_then_else (eq_attr "type" "call")
20349887Snsayer	 (if_then_else (eq_attr "prog_mode" "prog32")
20449887Snsayer	  (const_string "clob") (const_string "nocond"))
20549887Snsayer	 (const_string "nocond")))
20649887Snsayer
20749887Snsayer; Predicable means that the insn can be conditionally executed based on
20849887Snsayer; an automatically added predicate (additional patterns are generated by 
20949887Snsayer; gen...).  We default to 'no' because no Thumb patterns match this rule
21049887Snsayer; and not all ARM patterns do.
21149887Snsayer(define_attr "predicable" "no,yes" (const_string "no"))
21249887Snsayer
21349887Snsayer; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
21449887Snsayer; have one.  Later ones, such as StrongARM, have write-back caches, so don't
21549887Snsayer; suffer blockages enough to warrent modelling this (and it can adversely
21649887Snsayer; affect the schedule).
21749887Snsayer(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
21849887Snsayer
21949887Snsayer; WRITE_CONFLICT implies that a read following an unrelated write is likely
22049887Snsayer; to stall the processor.  Used with model_wbuf above.
22149887Snsayer(define_attr "write_conflict" "no,yes"
22249887Snsayer  (if_then_else (eq_attr "type"
22349887Snsayer		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
22449887Snsayer		(const_string "yes")
22549887Snsayer		(const_string "no")))
22649887Snsayer
22749887Snsayer; Classify the insns into those that take one cycle and those that take more
22849887Snsayer; than one on the main cpu execution unit.
22949887Snsayer(define_attr "core_cycles" "single,multi"
23049887Snsayer  (if_then_else (eq_attr "type"
23149887Snsayer		 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
23249887Snsayer		(const_string "single")
23349887Snsayer	        (const_string "multi")))
23449887Snsayer
23549887Snsayer;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
23649887Snsayer;; distant label.  Only applicable to Thumb code.
23749887Snsayer(define_attr "far_jump" "yes,no" (const_string "no"))
23849887Snsayer
23949887Snsayer;; (define_function_unit {name} {num-units} {n-users} {test}
24049887Snsayer;;                       {ready-delay} {issue-delay} [{conflict-list}])
24149887Snsayer
24249887Snsayer;;--------------------------------------------------------------------
24349887Snsayer;; Floating point unit (FPA)
24449887Snsayer;;--------------------------------------------------------------------
24549887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
24649887Snsayer				     (eq_attr "type" "fdivx")) 71 69)
24749887Snsayer
24849887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
24949887Snsayer				     (eq_attr "type" "fdivd")) 59 57)
25049887Snsayer
25149887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
25249887Snsayer				     (eq_attr "type" "fdivs")) 31 29)
25349887Snsayer
25449887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
25549887Snsayer				     (eq_attr "type" "fmul")) 9 7)
25649887Snsayer
25749887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
25849887Snsayer				     (eq_attr "type" "ffmul")) 6 4)
25949887Snsayer
26049887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
26149887Snsayer				     (eq_attr "type" "farith")) 4 2)
26249887Snsayer
26349887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
26449887Snsayer				     (eq_attr "type" "ffarith")) 2 2)
26549887Snsayer
26649887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
26749887Snsayer				     (eq_attr "type" "r_2_f")) 5 3)
26849887Snsayer
26949887Snsayer(define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
27049887Snsayer				     (eq_attr "type" "f_2_r")) 1 2)
27149887Snsayer
27249887Snsayer; The fpa10 doesn't really have a memory read unit, but it can start to
27349887Snsayer; speculatively execute the instruction in the pipeline, provided the data
27449887Snsayer; is already loaded, so pretend reads have a delay of 2 (and that the
27549887Snsayer; pipeline is infinite).
27649887Snsayer
27749887Snsayer(define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
27849887Snsayer					 (eq_attr "type" "f_load")) 3 1)
27949887Snsayer
28049887Snsayer;;--------------------------------------------------------------------
28149887Snsayer;; Write buffer
28249887Snsayer;;--------------------------------------------------------------------
28349887Snsayer; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
28449887Snsayer;
28549887Snsayer; The write buffer on some of the arm6 processors is hard to model exactly.
28649887Snsayer; There is room in the buffer for up to two addresses and up to eight words
28749887Snsayer; of memory, but the two needn't be split evenly.  When writing the two
28849887Snsayer; addresses are fully pipelined.  However, a read from memory that is not
28949887Snsayer; currently in the cache will block until the writes have completed.
29049887Snsayer; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
29149887Snsayer; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
29249887Snsayer; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
29349887Snsayer; cycle to add as well.
29449887Snsayer
29549887Snsayer(define_function_unit "write_buf" 1 2
29649887Snsayer  (and (eq_attr "model_wbuf" "yes")
29749887Snsayer       (eq_attr "type" "store1,r_mem_f")) 5 3)
29849887Snsayer(define_function_unit "write_buf" 1 2 
29949887Snsayer  (and (eq_attr "model_wbuf" "yes")
30049887Snsayer       (eq_attr "type" "store2")) 7 4)
30149887Snsayer(define_function_unit "write_buf" 1 2
30249887Snsayer  (and (eq_attr "model_wbuf" "yes")
30349887Snsayer       (eq_attr "type" "store3")) 9 5)
30449887Snsayer(define_function_unit "write_buf" 1 2
30549887Snsayer  (and (eq_attr "model_wbuf" "yes")
30649887Snsayer       (eq_attr "type" "store4")) 11 6)
30749887Snsayer
30849887Snsayer;;--------------------------------------------------------------------
30949887Snsayer;; Write blockage unit
31049887Snsayer;;--------------------------------------------------------------------
31149887Snsayer; The write_blockage unit models (partially), the fact that reads will stall
31249887Snsayer; until the write buffer empties.
31349887Snsayer; The f_mem_r and r_mem_f could also block, but they are to the stack,
31449887Snsayer; so we don't model them here
31549887Snsayer(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
31649887Snsayer						(eq_attr "type" "store1")) 5 5
31749887Snsayer	[(eq_attr "write_conflict" "yes")])
31849887Snsayer(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
31949887Snsayer						(eq_attr "type" "store2")) 7 7
32049887Snsayer	[(eq_attr "write_conflict" "yes")])
32149887Snsayer(define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
32249887Snsayer						(eq_attr "type" "store3")) 9 9
32349887Snsayer	[(eq_attr "write_conflict" "yes")])
32449887Snsayer(define_function_unit "write_blockage" 1 0
32549887Snsayer	(and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
32649887Snsayer	[(eq_attr "write_conflict" "yes")])
32749887Snsayer(define_function_unit "write_blockage" 1 0
32849887Snsayer	(and (eq_attr "model_wbuf" "yes")
32949887Snsayer	     (eq_attr "write_conflict" "yes")) 1 1)
33049887Snsayer
33149887Snsayer;;--------------------------------------------------------------------
33249887Snsayer;; Core unit
33349887Snsayer;;--------------------------------------------------------------------
33449887Snsayer; Everything must spend at least one cycle in the core unit
33549887Snsayer(define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
33649887Snsayer
33749887Snsayer(define_function_unit "core" 1 0
33849887Snsayer  (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
33949887Snsayer
34049887Snsayer(define_function_unit "core" 1 0
34149887Snsayer  (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
34249887Snsayer
34349887Snsayer;; We do not need to conditionalize the define_function_unit immediately
34449887Snsayer;; above.  This one will be ignored for anything other than xscale
34549887Snsayer;; compiles and for xscale compiles it provides a larger delay
34649887Snsayer;; and the scheduler will DTRT.
34749887Snsayer;; FIXME: this test needs to be revamped to not depend on this feature 
34849887Snsayer;; of the scheduler.
34949887Snsayer
35049887Snsayer(define_function_unit "core" 1 0
35149887Snsayer  (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
35249887Snsayer       (eq_attr "is_xscale" "yes"))
35349887Snsayer   3 1)
35449887Snsayer
35549887Snsayer(define_function_unit "core" 1 0
35649887Snsayer  (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
35749887Snsayer
35849887Snsayer(define_function_unit "core" 1 0
35949887Snsayer  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
36049887Snsayer
36149887Snsayer(define_function_unit "core" 1 0
36249887Snsayer  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
36349887Snsayer
36449887Snsayer(define_function_unit "core" 1 0
36549887Snsayer  (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
36649887Snsayer
36749887Snsayer(define_function_unit "core" 1 0
36849887Snsayer  (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
36949887Snsayer
37049887Snsayer(define_function_unit "core" 1 0
37149887Snsayer  (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
37249887Snsayer
37349887Snsayer(define_function_unit "core" 1 0
37449887Snsayer  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
37549887Snsayer       (eq_attr "type" "mult")) 4 4)
37649887Snsayer
37749887Snsayer(define_function_unit "core" 1 0
37849887Snsayer  (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
37949887Snsayer       (eq_attr "type" "mult")) 3 2)
38049887Snsayer
38149887Snsayer(define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
38249887Snsayer
38349887Snsayer(define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
38449887Snsayer
38549887Snsayer(define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
38649887Snsayer
38749887Snsayer(define_function_unit "core" 1 0
38849887Snsayer  (and (eq_attr "core_cycles" "multi")
38949887Snsayer       (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
39049887Snsayer
39149887Snsayer;;---------------------------------------------------------------------------
39249887Snsayer;; Insn patterns
39349887Snsayer;;
39449887Snsayer;; Addition insns.
39549887Snsayer
39649887Snsayer;; Note: For DImode insns, there is normally no reason why operands should
39749887Snsayer;; not be in the same register, what we don't want is for something being
39849887Snsayer;; written to partially overlap something that is an input.
39949887Snsayer
40049887Snsayer(define_expand "adddi3"
40149887Snsayer [(parallel
40249887Snsayer   [(set (match_operand:DI           0 "s_register_operand" "")
40349887Snsayer	  (plus:DI (match_operand:DI 1 "s_register_operand" "")
40449887Snsayer	           (match_operand:DI 2 "s_register_operand" "")))
40549887Snsayer    (clobber (reg:CC CC_REGNUM))])]
40649887Snsayer  "TARGET_EITHER"
40749887Snsayer  "
40849887Snsayer  if (TARGET_THUMB)
40949887Snsayer    {
41049887Snsayer      if (GET_CODE (operands[1]) != REG)
41149887Snsayer        operands[1] = force_reg (SImode, operands[1]);
41249887Snsayer      if (GET_CODE (operands[2]) != REG)
41349887Snsayer        operands[2] = force_reg (SImode, operands[2]);
41449887Snsayer     }
41549887Snsayer  "
41649887Snsayer)
41749887Snsayer
41849887Snsayer(define_insn "*thumb_adddi3"
41949887Snsayer  [(set (match_operand:DI          0 "register_operand" "=l")
42049887Snsayer	(plus:DI (match_operand:DI 1 "register_operand" "%0")
42149887Snsayer		 (match_operand:DI 2 "register_operand" "l")))
42249887Snsayer   (clobber (reg:CC CC_REGNUM))
42349887Snsayer  ]
42449887Snsayer  "TARGET_THUMB"
42549887Snsayer  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
42649887Snsayer  [(set_attr "length" "4")]
42749887Snsayer)
42849887Snsayer
42949887Snsayer(define_insn_and_split "*arm_adddi3"
43049887Snsayer  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
43149887Snsayer	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
43249887Snsayer		 (match_operand:DI 2 "s_register_operand" "r,  0")))
43349887Snsayer   (clobber (reg:CC CC_REGNUM))]
43449887Snsayer  "TARGET_ARM"
43549887Snsayer  "#"
43649887Snsayer  "TARGET_ARM && reload_completed"
43749887Snsayer  [(parallel [(set (reg:CC_C CC_REGNUM)
43849887Snsayer		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
43949887Snsayer				 (match_dup 1)))
44049887Snsayer	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
44149887Snsayer   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
44249887Snsayer			       (plus:SI (match_dup 4) (match_dup 5))))]
44349887Snsayer  "
44449887Snsayer  {
44549887Snsayer    operands[3] = gen_highpart (SImode, operands[0]);
44649887Snsayer    operands[0] = gen_lowpart (SImode, operands[0]);
44749887Snsayer    operands[4] = gen_highpart (SImode, operands[1]);
44849887Snsayer    operands[1] = gen_lowpart (SImode, operands[1]);
44949887Snsayer    operands[5] = gen_highpart (SImode, operands[2]);
45049887Snsayer    operands[2] = gen_lowpart (SImode, operands[2]);
45149887Snsayer  }"
45249887Snsayer  [(set_attr "conds" "clob")
45349887Snsayer   (set_attr "length" "8")]
45449887Snsayer)
45549887Snsayer
45649887Snsayer(define_insn_and_split "*adddi_sesidi_di"
45749887Snsayer  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
45876610Snsayer	(plus:DI (sign_extend:DI
45976610Snsayer		  (match_operand:SI 2 "s_register_operand" "r,r"))
46076610Snsayer		 (match_operand:DI 1 "s_register_operand" "r,0")))
46176610Snsayer   (clobber (reg:CC CC_REGNUM))]
46276610Snsayer  "TARGET_ARM"
46376610Snsayer  "#"
46476610Snsayer  "TARGET_ARM && reload_completed"
46576610Snsayer  [(parallel [(set (reg:CC_C CC_REGNUM)
46676610Snsayer		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
46776610Snsayer				 (match_dup 1)))
46876610Snsayer	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
46976610Snsayer   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
47076610Snsayer			       (plus:SI (ashiftrt:SI (match_dup 2)
47176610Snsayer						     (const_int 31))
47276610Snsayer					(match_dup 4))))]
47376610Snsayer  "
47476610Snsayer  {
47576610Snsayer    operands[3] = gen_highpart (SImode, operands[0]);
47676610Snsayer    operands[0] = gen_lowpart (SImode, operands[0]);
47776610Snsayer    operands[4] = gen_highpart (SImode, operands[1]);
47876339Snsayer    operands[1] = gen_lowpart (SImode, operands[1]);
47949887Snsayer    operands[2] = gen_lowpart (SImode, operands[2]);
48049887Snsayer  }"
48149887Snsayer  [(set_attr "conds" "clob")
48249887Snsayer   (set_attr "length" "8")]
48349887Snsayer)
48449887Snsayer
48549887Snsayer(define_insn_and_split "*adddi_zesidi_di"
48649887Snsayer  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
48749887Snsayer	(plus:DI (zero_extend:DI
48876610Snsayer		  (match_operand:SI 2 "s_register_operand" "r,r"))
48976610Snsayer		 (match_operand:DI 1 "s_register_operand" "r,0")))
49076610Snsayer   (clobber (reg:CC CC_REGNUM))]
49176610Snsayer  "TARGET_ARM"
49276610Snsayer  "#"
49376610Snsayer  "TARGET_ARM && reload_completed"
49449887Snsayer  [(parallel [(set (reg:CC_C CC_REGNUM)
49549887Snsayer		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
49649887Snsayer				 (match_dup 1)))
49749887Snsayer	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
49849887Snsayer   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
49949887Snsayer			       (plus:SI (match_dup 4) (const_int 0))))]
50049887Snsayer  "
50149887Snsayer  {
50249887Snsayer    operands[3] = gen_highpart (SImode, operands[0]);
50349887Snsayer    operands[0] = gen_lowpart (SImode, operands[0]);
50449887Snsayer    operands[4] = gen_highpart (SImode, operands[1]);
50549887Snsayer    operands[1] = gen_lowpart (SImode, operands[1]);
50649887Snsayer    operands[2] = gen_lowpart (SImode, operands[2]);
50749887Snsayer  }"
50849887Snsayer  [(set_attr "conds" "clob")
50949887Snsayer   (set_attr "length" "8")]
51049887Snsayer)
51149887Snsayer
51276339Snsayer(define_expand "addsi3"
51349887Snsayer  [(set (match_operand:SI          0 "s_register_operand" "")
51476339Snsayer	(plus:SI (match_operand:SI 1 "s_register_operand" "")
51576339Snsayer		 (match_operand:SI 2 "reg_or_int_operand" "")))]
51676339Snsayer  "TARGET_EITHER"
51776339Snsayer  "
51876339Snsayer  if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
51976339Snsayer    {
52049887Snsayer      arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
52176339Snsayer			  operands[1],
52276339Snsayer			  (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
52376339Snsayer      DONE;
52476339Snsayer    }
52576339Snsayer  "
52676339Snsayer)
52776339Snsayer
52876339Snsayer; If there is a scratch available, this will be faster than synthesising the
52976339Snsayer; addition.
53076339Snsayer(define_peephole2
53176339Snsayer  [(match_scratch:SI 3 "r")
53276339Snsayer   (set (match_operand:SI          0 "s_register_operand" "")
53376339Snsayer	(plus:SI (match_operand:SI 1 "s_register_operand" "")
53476339Snsayer		 (match_operand:SI 2 "const_int_operand"  "")))]
53576339Snsayer  "TARGET_ARM &&
53676339Snsayer   !(const_ok_for_arm (INTVAL (operands[2]))
53776339Snsayer     || const_ok_for_arm (-INTVAL (operands[2])))
53876339Snsayer    && const_ok_for_arm (~INTVAL (operands[2]))"
53976339Snsayer  [(set (match_dup 3) (match_dup 2))
54076339Snsayer   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
54176339Snsayer  ""
54276339Snsayer)
54376339Snsayer
54476339Snsayer(define_insn_and_split "*arm_addsi3"
54576339Snsayer  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
54676339Snsayer	(plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
54776339Snsayer		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
54876339Snsayer  "TARGET_ARM"
54976339Snsayer  "@
55076339Snsayer   add%?\\t%0, %1, %2
55176339Snsayer   sub%?\\t%0, %1, #%n2
55276339Snsayer   #"
55376339Snsayer  "TARGET_ARM &&
55476339Snsayer   GET_CODE (operands[2]) == CONST_INT
55576339Snsayer   && !(const_ok_for_arm (INTVAL (operands[2]))
55676339Snsayer        || const_ok_for_arm (-INTVAL (operands[2])))"
55776339Snsayer  [(clobber (const_int 0))]
55876339Snsayer  "
55976339Snsayer  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
56076339Snsayer		      operands[1], 0);
56176339Snsayer  DONE;
56276339Snsayer  "
56376339Snsayer  [(set_attr "length" "4,4,16")
56476339Snsayer   (set_attr "predicable" "yes")]
56576339Snsayer)
56676339Snsayer
56776339Snsayer;; Register group 'k' is a single register group containing only the stack
56876339Snsayer;; register.  Trying to reload it will always fail catastrophically,
56976339Snsayer;; so never allow those alternatives to match if reloading is needed.
57076339Snsayer
57176339Snsayer(define_insn "*thumb_addsi3"
57276339Snsayer  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
57376339Snsayer	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
57476339Snsayer		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
57576339Snsayer  "TARGET_THUMB"
57676339Snsayer  "*
57776339Snsayer   static const char * const asms[] = 
57876339Snsayer   {
57976339Snsayer     \"add\\t%0, %0, %2\",
58076339Snsayer     \"sub\\t%0, %0, #%n2\",
58176339Snsayer     \"add\\t%0, %1, %2\",
58276339Snsayer     \"add\\t%0, %0, %2\",
58376339Snsayer     \"add\\t%0, %0, %2\",
58476339Snsayer     \"add\\t%0, %1, %2\",
58576339Snsayer     \"add\\t%0, %1, %2\"
58676339Snsayer   };
58776339Snsayer   if ((which_alternative == 2 || which_alternative == 6)
58876339Snsayer       && GET_CODE (operands[2]) == CONST_INT
58976339Snsayer       && INTVAL (operands[2]) < 0)
59049887Snsayer     return \"sub\\t%0, %1, #%n2\";
59149887Snsayer   return asms[which_alternative];
59276339Snsayer  "
59376339Snsayer  [(set_attr "length" "2")]
59476339Snsayer)
59576339Snsayer
59676339Snsayer;; Reloading and elimination of the frame pointer can
59776339Snsayer;; sometimes cause this optimization to be missed.
59876339Snsayer(define_peephole2
59976339Snsayer  [(set (match_operand:SI 0 "register_operand" "=l")
60076339Snsayer	(match_operand:SI 1 "const_int_operand" "M"))
60176339Snsayer   (set (match_dup 0)
60276339Snsayer	(plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
60376339Snsayer  "TARGET_THUMB
60476339Snsayer   && REGNO (operands[2]) == STACK_POINTER_REGNUM 
60576339Snsayer   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
60676339Snsayer   && (INTVAL (operands[1]) & 3) == 0"
60776339Snsayer  [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
60876339Snsayer  ""
60976339Snsayer)
61076339Snsayer
61176339Snsayer(define_insn "*addsi3_compare0"
61276339Snsayer  [(set (reg:CC_NOOV CC_REGNUM)
61376339Snsayer	(compare:CC_NOOV
61476339Snsayer	 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
61576339Snsayer		  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
61676339Snsayer	 (const_int 0)))
61776339Snsayer   (set (match_operand:SI 0 "s_register_operand" "=r,r")
61876610Snsayer	(plus:SI (match_dup 1) (match_dup 2)))]
61976610Snsayer  "TARGET_ARM"
62076610Snsayer  "@
62176610Snsayer   add%?s\\t%0, %1, %2
62276339Snsayer   sub%?s\\t%0, %1, #%n2"
62376339Snsayer  [(set_attr "conds" "set")]
62476339Snsayer)
62576339Snsayer
62676339Snsayer(define_insn "*addsi3_compare0_scratch"
62776339Snsayer  [(set (reg:CC_NOOV CC_REGNUM)
62876339Snsayer	(compare:CC_NOOV
62976339Snsayer	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
63076339Snsayer		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
63176339Snsayer	 (const_int 0)))]
63276339Snsayer  "TARGET_ARM"
63376339Snsayer  "@
63476339Snsayer   cmn%?\\t%0, %1
63576339Snsayer   cmp%?\\t%0, #%n1"
63676339Snsayer  [(set_attr "conds" "set")]
63776339Snsayer)
63876339Snsayer
63976339Snsayer;; These patterns are the same ones as the two regular addsi3_compare0
64076339Snsayer;; patterns, except we write them slightly different - the combiner
64176339Snsayer;; tends to generate them this way.
64276339Snsayer(define_insn "*addsi3_compare0_for_combiner"
64376339Snsayer  [(set (reg:CC CC_REGNUM)
64476339Snsayer	(compare:CC
64576339Snsayer	 (match_operand:SI 1 "s_register_operand" "r,r")
64676339Snsayer	 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
647   (set (match_operand:SI 0 "s_register_operand" "=r,r")
648	(plus:SI (match_dup 1) (match_dup 2)))]
649  "TARGET_ARM"
650  "@
651   add%?s\\t%0, %1, %2
652   sub%?s\\t%0, %1, #%n2"
653  [(set_attr "conds" "set")]
654)
655
656(define_insn "*addsi3_compare0_scratch_for_combiner"
657  [(set (reg:CC CC_REGNUM)
658	(compare:CC
659	 (match_operand:SI 0 "s_register_operand" "r,r")
660	 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
661  "TARGET_ARM"
662  "@
663   cmn%?\\t%0, %1
664   cmp%?\\t%0, #%n1"
665  [(set_attr "conds" "set")]
666)
667
668;; The next four insns work because they compare the result with one of
669;; the operands, and we know that the use of the condition code is
670;; either GEU or LTU, so we can use the carry flag from the addition
671;; instead of doing the compare a second time.
672(define_insn "*addsi3_compare_op1"
673  [(set (reg:CC_C CC_REGNUM)
674	(compare:CC_C
675	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
677	 (match_dup 1)))
678   (set (match_operand:SI 0 "s_register_operand" "=r,r")
679	(plus:SI (match_dup 1) (match_dup 2)))]
680  "TARGET_ARM"
681  "@
682   add%?s\\t%0, %1, %2
683   sub%?s\\t%0, %1, #%n2"
684  [(set_attr "conds" "set")]
685)
686
687(define_insn "*addsi3_compare_op2"
688  [(set (reg:CC_C CC_REGNUM)
689	(compare:CC_C
690	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
692	 (match_dup 2)))
693   (set (match_operand:SI 0 "s_register_operand" "=r,r")
694	(plus:SI (match_dup 1) (match_dup 2)))]
695  "TARGET_ARM"
696  "@
697   add%?s\\t%0, %1, %2
698   sub%?s\\t%0, %1, #%n2"
699  [(set_attr "conds" "set")]
700)
701
702(define_insn "*compare_addsi2_op0"
703  [(set (reg:CC_C CC_REGNUM)
704	(compare:CC_C
705	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
706		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
707	 (match_dup 0)))]
708  "TARGET_ARM"
709  "@
710   cmn%?\\t%0, %1
711   cmp%?\\t%0, #%n1"
712  [(set_attr "conds" "set")]
713)
714
715(define_insn "*compare_addsi2_op1"
716  [(set (reg:CC_C CC_REGNUM)
717	(compare:CC_C
718	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
719		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
720	 (match_dup 1)))]
721  "TARGET_ARM"
722  "@
723   cmn%?\\t%0, %1
724   cmp%?\\t%0, #%n1"
725  [(set_attr "conds" "set")]
726)
727
728(define_insn "*addsi3_carryin"
729  [(set (match_operand:SI 0 "s_register_operand" "=r")
730	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
731		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
732			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
733  "TARGET_ARM"
734  "adc%?\\t%0, %1, %2"
735  [(set_attr "conds" "use")]
736)
737
738(define_insn "*addsi3_carryin_shift"
739  [(set (match_operand:SI 0 "s_register_operand" "")
740	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
741		 (plus:SI
742		   (match_operator:SI 2 "shift_operator"
743		      [(match_operand:SI 3 "s_register_operand" "")
744		       (match_operand:SI 4 "reg_or_int_operand" "")])
745		    (match_operand:SI 1 "s_register_operand" ""))))]
746  "TARGET_ARM"
747  "adc%?\\t%0, %1, %3%S2"
748  [(set_attr "conds" "use")]
749)
750
751(define_insn "*addsi3_carryin_alt1"
752  [(set (match_operand:SI 0 "s_register_operand" "=r")
753	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
755		 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756  "TARGET_ARM"
757  "adc%?\\t%0, %1, %2"
758  [(set_attr "conds" "use")]
759)
760
761(define_insn "*addsi3_carryin_alt2"
762  [(set (match_operand:SI 0 "s_register_operand" "=r")
763	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764			  (match_operand:SI 1 "s_register_operand" "r"))
765		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766  "TARGET_ARM"
767  "adc%?\\t%0, %1, %2"
768  [(set_attr "conds" "use")]
769)
770
771(define_insn "*addsi3_carryin_alt3"
772  [(set (match_operand:SI 0 "s_register_operand" "=r")
773	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
775		 (match_operand:SI 1 "s_register_operand" "r")))]
776  "TARGET_ARM"
777  "adc%?\\t%0, %1, %2"
778  [(set_attr "conds" "use")]
779)
780
781(define_insn "incscc"
782  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
786  "TARGET_ARM"
787  "@
788  add%d2\\t%0, %1, #1
789  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790  [(set_attr "conds" "use")
791   (set_attr "length" "4,8")]
792)
793
794(define_insn "addsf3"
795  [(set (match_operand:SF          0 "s_register_operand" "=f,f")
796	(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
797		 (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
798  "TARGET_ARM && TARGET_HARD_FLOAT"
799  "@
800   adf%?s\\t%0, %1, %2
801   suf%?s\\t%0, %1, #%N2"
802  [(set_attr "type" "farith")
803   (set_attr "predicable" "yes")]
804)
805
806(define_insn "adddf3"
807  [(set (match_operand:DF          0 "s_register_operand" "=f,f")
808	(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
809		 (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
810  "TARGET_ARM && TARGET_HARD_FLOAT"
811  "@
812   adf%?d\\t%0, %1, %2
813   suf%?d\\t%0, %1, #%N2"
814  [(set_attr "type" "farith")
815   (set_attr "predicable" "yes")]
816)
817
818(define_insn "*adddf_esfdf_df"
819  [(set (match_operand:DF           0 "s_register_operand" "=f,f")
820	(plus:DF (float_extend:DF
821		  (match_operand:SF 1 "s_register_operand"  "f,f"))
822		 (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
823  "TARGET_ARM && TARGET_HARD_FLOAT"
824  "@
825   adf%?d\\t%0, %1, %2
826   suf%?d\\t%0, %1, #%N2"
827  [(set_attr "type" "farith")
828   (set_attr "predicable" "yes")]
829)
830
831(define_insn "*adddf_df_esfdf"
832  [(set (match_operand:DF           0 "s_register_operand" "=f")
833	(plus:DF (match_operand:DF  1 "s_register_operand"  "f")
834		 (float_extend:DF
835		  (match_operand:SF 2 "s_register_operand"  "f"))))]
836  "TARGET_ARM && TARGET_HARD_FLOAT"
837  "adf%?d\\t%0, %1, %2"
838  [(set_attr "type" "farith")
839   (set_attr "predicable" "yes")]
840)
841
842(define_insn "*adddf_esfdf_esfdf"
843  [(set (match_operand:DF           0 "s_register_operand" "=f")
844	(plus:DF (float_extend:DF 
845		  (match_operand:SF 1 "s_register_operand" "f"))
846		 (float_extend:DF
847		  (match_operand:SF 2 "s_register_operand" "f"))))]
848  "TARGET_ARM && TARGET_HARD_FLOAT"
849  "adf%?d\\t%0, %1, %2"
850  [(set_attr "type" "farith")
851   (set_attr "predicable" "yes")]
852)
853
854(define_insn "addxf3"
855  [(set (match_operand:XF          0 "s_register_operand" "=f,f")
856	(plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
857		 (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
858  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
859  "@
860   adf%?e\\t%0, %1, %2
861   suf%?e\\t%0, %1, #%N2"
862  [(set_attr "type" "farith")
863   (set_attr "predicable" "yes")]
864)
865
866(define_expand "subdi3"
867 [(parallel
868   [(set (match_operand:DI            0 "s_register_operand" "")
869	  (minus:DI (match_operand:DI 1 "s_register_operand" "")
870	            (match_operand:DI 2 "s_register_operand" "")))
871    (clobber (reg:CC CC_REGNUM))])]
872  "TARGET_EITHER"
873  "
874  if (TARGET_THUMB)
875    {
876      if (GET_CODE (operands[1]) != REG)
877        operands[1] = force_reg (SImode, operands[1]);
878      if (GET_CODE (operands[2]) != REG)
879        operands[2] = force_reg (SImode, operands[2]);
880     }	
881  "
882)
883
884(define_insn "*arm_subdi3"
885  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
886	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
887		  (match_operand:DI 2 "s_register_operand" "r,0,0")))
888   (clobber (reg:CC CC_REGNUM))]
889  "TARGET_ARM"
890  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
891  [(set_attr "conds" "clob")
892   (set_attr "length" "8")]
893)
894
895(define_insn "*thumb_subdi3"
896  [(set (match_operand:DI           0 "register_operand" "=l")
897	(minus:DI (match_operand:DI 1 "register_operand"  "0")
898		  (match_operand:DI 2 "register_operand"  "l")))
899   (clobber (reg:CC CC_REGNUM))]
900  "TARGET_THUMB"
901  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
902  [(set_attr "length" "4")]
903)
904
905(define_insn "*subdi_di_zesidi"
906  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
907	(minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
908		  (zero_extend:DI
909		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
910   (clobber (reg:CC CC_REGNUM))]
911  "TARGET_ARM"
912  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
913  [(set_attr "conds" "clob")
914   (set_attr "length" "8")]
915)
916
917(define_insn "*subdi_di_sesidi"
918  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
919	(minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
920		  (sign_extend:DI
921		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
922   (clobber (reg:CC CC_REGNUM))]
923  "TARGET_ARM"
924  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
925  [(set_attr "conds" "clob")
926   (set_attr "length" "8")]
927)
928
929(define_insn "*subdi_zesidi_di"
930  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
931	(minus:DI (zero_extend:DI
932		   (match_operand:SI 2 "s_register_operand"  "r,r"))
933		  (match_operand:DI  1 "s_register_operand" "?r,0")))
934   (clobber (reg:CC CC_REGNUM))]
935  "TARGET_ARM"
936  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
937  [(set_attr "conds" "clob")
938   (set_attr "length" "8")]
939)
940
941(define_insn "*subdi_sesidi_di"
942  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
943	(minus:DI (sign_extend:DI
944		   (match_operand:SI 2 "s_register_operand"   "r,r"))
945		  (match_operand:DI  1 "s_register_operand"  "?r,0")))
946   (clobber (reg:CC CC_REGNUM))]
947  "TARGET_ARM"
948  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
949  [(set_attr "conds" "clob")
950   (set_attr "length" "8")]
951)
952
953(define_insn "*subdi_zesidi_zesidi"
954  [(set (match_operand:DI            0 "s_register_operand" "=r")
955	(minus:DI (zero_extend:DI
956		   (match_operand:SI 1 "s_register_operand"  "r"))
957		  (zero_extend:DI
958		   (match_operand:SI 2 "s_register_operand"  "r"))))
959   (clobber (reg:CC CC_REGNUM))]
960  "TARGET_ARM"
961  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
962  [(set_attr "conds" "clob")
963   (set_attr "length" "8")]
964)
965
966(define_expand "subsi3"
967  [(set (match_operand:SI           0 "s_register_operand" "")
968	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
969		  (match_operand:SI 2 "s_register_operand" "")))]
970  "TARGET_EITHER"
971  "
972  if (GET_CODE (operands[1]) == CONST_INT)
973    {
974      if (TARGET_ARM)
975        {
976          arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
977	  		      operands[2],
978			      (no_new_pseudos ? 0
979			       :  preserve_subexpressions_p ()));
980          DONE;
981	}
982      else /* TARGET_THUMB */
983        operands[1] = force_reg (SImode, operands[1]);
984    }
985  "
986)
987
988(define_insn "*thumb_subsi3_insn"
989  [(set (match_operand:SI           0 "register_operand" "=l")
990	(minus:SI (match_operand:SI 1 "register_operand" "l")
991		  (match_operand:SI 2 "register_operand" "l")))]
992  "TARGET_THUMB"
993  "sub\\t%0, %1, %2"
994  [(set_attr "length" "2")]
995)
996
997(define_insn_and_split "*arm_subsi3_insn"
998  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
999	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1000		  (match_operand:SI 2 "s_register_operand" "r,r")))]
1001  "TARGET_ARM"
1002  "@
1003   rsb%?\\t%0, %2, %1
1004   #"
1005  "TARGET_ARM
1006   && GET_CODE (operands[1]) == CONST_INT
1007   && !const_ok_for_arm (INTVAL (operands[1]))"
1008  [(clobber (const_int 0))]
1009  "
1010  arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1011		      operands[2], 0);
1012  DONE;
1013  "
1014  [(set_attr "length" "4,16")
1015   (set_attr "predicable" "yes")]
1016)
1017
1018(define_peephole2
1019  [(match_scratch:SI 3 "r")
1020   (set (match_operand:SI           0 "s_register_operand" "")
1021	(minus:SI (match_operand:SI 1 "const_int_operand" "")
1022		  (match_operand:SI 2 "s_register_operand" "")))]
1023  "TARGET_ARM
1024   && !const_ok_for_arm (INTVAL (operands[1]))
1025   && const_ok_for_arm (~INTVAL (operands[1]))"
1026  [(set (match_dup 3) (match_dup 1))
1027   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1028  ""
1029)
1030
1031(define_insn "*subsi3_compare0"
1032  [(set (reg:CC_NOOV CC_REGNUM)
1033	(compare:CC_NOOV
1034	 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1035		   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1036	 (const_int 0)))
1037   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1038	(minus:SI (match_dup 1) (match_dup 2)))]
1039  "TARGET_ARM"
1040  "@
1041   sub%?s\\t%0, %1, %2
1042   rsb%?s\\t%0, %2, %1"
1043  [(set_attr "conds" "set")]
1044)
1045
1046(define_insn "decscc"
1047  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1048        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1049		  (match_operator:SI 2 "arm_comparison_operator"
1050                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1051  "TARGET_ARM"
1052  "@
1053   sub%d2\\t%0, %1, #1
1054   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1055  [(set_attr "conds" "use")
1056   (set_attr "length" "*,8")]
1057)
1058
1059(define_insn "subsf3"
1060  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1061	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1062		  (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1063  "TARGET_ARM && TARGET_HARD_FLOAT"
1064  "@
1065   suf%?s\\t%0, %1, %2
1066   rsf%?s\\t%0, %2, %1"
1067  [(set_attr "type" "farith")]
1068)
1069
1070(define_insn "subdf3"
1071  [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1072	(minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1073		  (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1074  "TARGET_ARM && TARGET_HARD_FLOAT"
1075  "@
1076   suf%?d\\t%0, %1, %2
1077   rsf%?d\\t%0, %2, %1"
1078  [(set_attr "type" "farith")
1079   (set_attr "predicable" "yes")]
1080)
1081
1082(define_insn "*subdf_esfdf_df"
1083  [(set (match_operand:DF            0 "s_register_operand" "=f")
1084	(minus:DF (float_extend:DF
1085		   (match_operand:SF 1 "s_register_operand"  "f"))
1086		  (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1087  "TARGET_ARM && TARGET_HARD_FLOAT"
1088  "suf%?d\\t%0, %1, %2"
1089  [(set_attr "type" "farith")
1090   (set_attr "predicable" "yes")]
1091)
1092
1093(define_insn "*subdf_df_esfdf"
1094  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1095	(minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1096		  (float_extend:DF
1097		   (match_operand:SF 2 "s_register_operand" "f,f"))))]
1098  "TARGET_ARM && TARGET_HARD_FLOAT"
1099  "@
1100   suf%?d\\t%0, %1, %2
1101   rsf%?d\\t%0, %2, %1"
1102  [(set_attr "type" "farith")
1103   (set_attr "predicable" "yes")]
1104)
1105
1106(define_insn "*subdf_esfdf_esfdf"
1107  [(set (match_operand:DF 0 "s_register_operand" "=f")
1108	(minus:DF (float_extend:DF
1109		   (match_operand:SF 1 "s_register_operand" "f"))
1110		  (float_extend:DF
1111		   (match_operand:SF 2 "s_register_operand" "f"))))]
1112  "TARGET_ARM && TARGET_HARD_FLOAT"
1113  "suf%?d\\t%0, %1, %2"
1114  [(set_attr "type" "farith")
1115   (set_attr "predicable" "yes")]
1116)
1117
1118(define_insn "subxf3"
1119  [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1120	(minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1121		  (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1122  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1123  "@
1124   suf%?e\\t%0, %1, %2
1125   rsf%?e\\t%0, %2, %1"
1126  [(set_attr "type" "farith")
1127   (set_attr "predicable" "yes")]
1128)
1129
1130;; Multiplication insns
1131
1132(define_expand "mulsi3"
1133  [(set (match_operand:SI          0 "s_register_operand" "")
1134	(mult:SI (match_operand:SI 2 "s_register_operand" "")
1135		 (match_operand:SI 1 "s_register_operand" "")))]
1136  "TARGET_EITHER"
1137  ""
1138)
1139
1140;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141(define_insn "*arm_mulsi3"
1142  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1143	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1145  "TARGET_ARM"
1146  "mul%?\\t%0, %2, %1"
1147  [(set_attr "type" "mult")
1148   (set_attr "predicable" "yes")]
1149)
1150
1151; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1152; 1 and 2; are the same, because reload will make operand 0 match 
1153; operand 1 without realizing that this conflicts with operand 2.  We fix 
1154; this by adding another alternative to match this case, and then `reload' 
1155; it ourselves.  This alternative must come first.
1156(define_insn "*thumb_mulsi3"
1157  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1158	(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159		 (match_operand:SI 2 "register_operand" "l,l,l")))]
1160  "TARGET_THUMB"
1161  "*
1162  if (which_alternative < 2)
1163    return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1164  else
1165    return \"mul\\t%0, %0, %2\";
1166  "
1167  [(set_attr "length" "4,4,2")
1168   (set_attr "type" "mult")]
1169)
1170
1171(define_insn "*mulsi3_compare0"
1172  [(set (reg:CC_NOOV CC_REGNUM)
1173	(compare:CC_NOOV (mult:SI
1174			  (match_operand:SI 2 "s_register_operand" "r,r")
1175			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1176			 (const_int 0)))
1177   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178	(mult:SI (match_dup 2) (match_dup 1)))]
1179  "TARGET_ARM && !arm_is_xscale"
1180  "mul%?s\\t%0, %2, %1"
1181  [(set_attr "conds" "set")
1182   (set_attr "type" "mult")]
1183)
1184
1185(define_insn "*mulsi_compare0_scratch"
1186  [(set (reg:CC_NOOV CC_REGNUM)
1187	(compare:CC_NOOV (mult:SI
1188			  (match_operand:SI 2 "s_register_operand" "r,r")
1189			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
1190			 (const_int 0)))
1191   (clobber (match_scratch:SI 0 "=&r,&r"))]
1192  "TARGET_ARM && !arm_is_xscale"
1193  "mul%?s\\t%0, %2, %1"
1194  [(set_attr "conds" "set")
1195   (set_attr "type" "mult")]
1196)
1197
1198;; Unnamed templates to match MLA instruction.
1199
1200(define_insn "*mulsi3addsi"
1201  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1202	(plus:SI
1203	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1206  "TARGET_ARM"
1207  "mla%?\\t%0, %2, %1, %3"
1208  [(set_attr "type" "mult")
1209   (set_attr "predicable" "yes")]
1210)
1211
1212(define_insn "*mulsi3addsi_compare0"
1213  [(set (reg:CC_NOOV CC_REGNUM)
1214	(compare:CC_NOOV
1215	 (plus:SI (mult:SI
1216		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1219	 (const_int 0)))
1220   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
1222		 (match_dup 3)))]
1223  "TARGET_ARM && !arm_is_xscale"
1224  "mla%?s\\t%0, %2, %1, %3"
1225  [(set_attr "conds" "set")
1226   (set_attr "type" "mult")]
1227)
1228
1229(define_insn "*mulsi3addsi_compare0_scratch"
1230  [(set (reg:CC_NOOV CC_REGNUM)
1231	(compare:CC_NOOV
1232	 (plus:SI (mult:SI
1233		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1236	 (const_int 0)))
1237   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238  "TARGET_ARM && !arm_is_xscale"
1239  "mla%?s\\t%0, %2, %1, %3"
1240  [(set_attr "conds" "set")
1241   (set_attr "type" "mult")]
1242)
1243
1244;; Unnamed template to match long long multiply-accumlate (smlal)
1245
1246(define_insn "*mulsidi3adddi"
1247  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1248	(plus:DI
1249	 (mult:DI
1250	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252	 (match_operand:DI 1 "s_register_operand" "0")))]
1253  "TARGET_ARM && arm_fast_multiply"
1254  "smlal%?\\t%Q0, %R0, %3, %2"
1255  [(set_attr "type" "mult")
1256   (set_attr "predicable" "yes")]
1257)
1258
1259(define_insn "mulsidi3"
1260  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261	(mult:DI
1262	 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263	 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264  "TARGET_ARM && arm_fast_multiply"
1265  "smull%?\\t%Q0, %R0, %1, %2"
1266  [(set_attr "type" "mult")
1267   (set_attr "predicable" "yes")]
1268)
1269
1270(define_insn "umulsidi3"
1271  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1272	(mult:DI
1273	 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274	 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275  "TARGET_ARM && arm_fast_multiply"
1276  "umull%?\\t%Q0, %R0, %1, %2"
1277  [(set_attr "type" "mult")
1278   (set_attr "predicable" "yes")]
1279)
1280
1281;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1282
1283(define_insn "*umulsidi3adddi"
1284  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1285	(plus:DI
1286	 (mult:DI
1287	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289	 (match_operand:DI 1 "s_register_operand" "0")))]
1290  "TARGET_ARM && arm_fast_multiply"
1291  "umlal%?\\t%Q0, %R0, %3, %2"
1292  [(set_attr "type" "mult")
1293   (set_attr "predicable" "yes")]
1294)
1295
1296(define_insn "smulsi3_highpart"
1297  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1298	(truncate:SI
1299	 (lshiftrt:DI
1300	  (mult:DI
1301	   (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302	   (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1303	  (const_int 32))))
1304   (clobber (match_scratch:SI 3 "=&r,&r"))]
1305  "TARGET_ARM && arm_fast_multiply"
1306  "smull%?\\t%3, %0, %2, %1"
1307  [(set_attr "type" "mult")
1308   (set_attr "predicable" "yes")]
1309)
1310
1311(define_insn "umulsi3_highpart"
1312  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313	(truncate:SI
1314	 (lshiftrt:DI
1315	  (mult:DI
1316	   (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317	   (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1318	  (const_int 32))))
1319   (clobber (match_scratch:SI 3 "=&r,&r"))]
1320  "TARGET_ARM && arm_fast_multiply"
1321  "umull%?\\t%3, %0, %2, %1"
1322  [(set_attr "type" "mult")
1323   (set_attr "predicable" "yes")]
1324)
1325
1326(define_insn "mulhisi3"
1327  [(set (match_operand:SI 0 "s_register_operand" "=r")
1328	(mult:SI (sign_extend:SI
1329		  (match_operand:HI 1 "s_register_operand" "%r"))
1330		 (sign_extend:SI
1331		  (match_operand:HI 2 "s_register_operand" "r"))))]
1332  "TARGET_ARM && arm_is_xscale"
1333  "smulbb%?\\t%0, %1, %2"
1334  [(set_attr "type" "mult")]
1335)
1336
1337(define_insn "*mulhisi3addsi"
1338  [(set (match_operand:SI 0 "s_register_operand" "=r")
1339	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340		 (mult:SI (sign_extend:SI
1341			   (match_operand:HI 2 "s_register_operand" "%r"))
1342			  (sign_extend:SI
1343			   (match_operand:HI 3 "s_register_operand" "r")))))]
1344  "TARGET_ARM && arm_is_xscale"
1345  "smlabb%?\\t%0, %2, %3, %1"
1346  [(set_attr "type" "mult")]
1347)
1348
1349(define_insn "*mulhidi3adddi"
1350  [(set (match_operand:DI 0 "s_register_operand" "=r")
1351	(plus:DI
1352	  (match_operand:DI 1 "s_register_operand" "0")
1353	  (mult:DI (sign_extend:DI
1354	 	    (match_operand:HI 2 "s_register_operand" "%r"))
1355		   (sign_extend:DI
1356		    (match_operand:HI 3 "s_register_operand" "r")))))]
1357  "TARGET_ARM && arm_is_xscale"
1358  "smlalbb%?\\t%Q0, %R0, %2, %3"
1359[(set_attr "type" "mult")])
1360
1361(define_insn "mulsf3"
1362  [(set (match_operand:SF 0 "s_register_operand" "=f")
1363	(mult:SF (match_operand:SF 1 "s_register_operand" "f")
1364		 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1365  "TARGET_ARM && TARGET_HARD_FLOAT"
1366  "fml%?s\\t%0, %1, %2"
1367  [(set_attr "type" "ffmul")
1368   (set_attr "predicable" "yes")]
1369)
1370
1371(define_insn "muldf3"
1372  [(set (match_operand:DF 0 "s_register_operand" "=f")
1373	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
1374		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1375  "TARGET_ARM && TARGET_HARD_FLOAT"
1376  "muf%?d\\t%0, %1, %2"
1377  [(set_attr "type" "fmul")
1378   (set_attr "predicable" "yes")]
1379)
1380
1381(define_insn "*muldf_esfdf_df"
1382  [(set (match_operand:DF 0 "s_register_operand" "=f")
1383	(mult:DF (float_extend:DF
1384		  (match_operand:SF 1 "s_register_operand" "f"))
1385		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1386  "TARGET_ARM && TARGET_HARD_FLOAT"
1387  "muf%?d\\t%0, %1, %2"
1388  [(set_attr "type" "fmul")
1389   (set_attr "predicable" "yes")]
1390)
1391
1392(define_insn "*muldf_df_esfdf"
1393  [(set (match_operand:DF 0 "s_register_operand" "=f")
1394	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
1395		 (float_extend:DF
1396		  (match_operand:SF 2 "s_register_operand" "f"))))]
1397  "TARGET_ARM && TARGET_HARD_FLOAT"
1398  "muf%?d\\t%0, %1, %2"
1399  [(set_attr "type" "fmul")
1400   (set_attr "predicable" "yes")]
1401)
1402
1403(define_insn "*muldf_esfdf_esfdf"
1404  [(set (match_operand:DF 0 "s_register_operand" "=f")
1405	(mult:DF
1406	 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1407	 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1408  "TARGET_ARM && TARGET_HARD_FLOAT"
1409  "muf%?d\\t%0, %1, %2"
1410  [(set_attr "type" "fmul")
1411   (set_attr "predicable" "yes")]
1412)
1413
1414(define_insn "mulxf3"
1415  [(set (match_operand:XF 0 "s_register_operand" "=f")
1416	(mult:XF (match_operand:XF 1 "s_register_operand" "f")
1417		 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1418  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1419  "muf%?e\\t%0, %1, %2"
1420  [(set_attr "type" "fmul")
1421   (set_attr "predicable" "yes")]
1422)
1423
1424;; Division insns
1425
1426(define_insn "divsf3"
1427  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1428	(div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1429		(match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1430  "TARGET_ARM && TARGET_HARD_FLOAT"
1431  "@
1432   fdv%?s\\t%0, %1, %2
1433   frd%?s\\t%0, %2, %1"
1434  [(set_attr "type" "fdivs")
1435   (set_attr "predicable" "yes")]
1436)
1437
1438(define_insn "divdf3"
1439  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1440	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1441		(match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1442  "TARGET_ARM && TARGET_HARD_FLOAT"
1443  "@
1444   dvf%?d\\t%0, %1, %2
1445   rdf%?d\\t%0, %2, %1"
1446  [(set_attr "type" "fdivd")
1447   (set_attr "predicable" "yes")]
1448)
1449
1450(define_insn "*divdf_esfdf_df"
1451  [(set (match_operand:DF 0 "s_register_operand" "=f")
1452	(div:DF (float_extend:DF
1453		 (match_operand:SF 1 "s_register_operand" "f"))
1454		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1455  "TARGET_ARM && TARGET_HARD_FLOAT"
1456  "dvf%?d\\t%0, %1, %2"
1457  [(set_attr "type" "fdivd")
1458   (set_attr "predicable" "yes")]
1459)
1460
1461(define_insn "*divdf_df_esfdf"
1462  [(set (match_operand:DF 0 "s_register_operand" "=f")
1463	(div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1464		(float_extend:DF
1465		 (match_operand:SF 2 "s_register_operand" "f"))))]
1466  "TARGET_ARM && TARGET_HARD_FLOAT"
1467  "rdf%?d\\t%0, %2, %1"
1468  [(set_attr "type" "fdivd")
1469   (set_attr "predicable" "yes")]
1470)
1471
1472(define_insn "*divdf_esfdf_esfdf"
1473  [(set (match_operand:DF 0 "s_register_operand" "=f")
1474	(div:DF (float_extend:DF
1475		 (match_operand:SF 1 "s_register_operand" "f"))
1476		(float_extend:DF
1477		 (match_operand:SF 2 "s_register_operand" "f"))))]
1478  "TARGET_ARM && TARGET_HARD_FLOAT"
1479  "dvf%?d\\t%0, %1, %2"
1480  [(set_attr "type" "fdivd")
1481   (set_attr "predicable" "yes")]
1482)
1483
1484(define_insn "divxf3"
1485  [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1486	(div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1487		(match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1488  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1489  "@
1490   dvf%?e\\t%0, %1, %2
1491   rdf%?e\\t%0, %2, %1"
1492  [(set_attr "type" "fdivx")
1493   (set_attr "predicable" "yes")]
1494)
1495
1496;; Modulo insns
1497
1498(define_insn "modsf3"
1499  [(set (match_operand:SF 0 "s_register_operand" "=f")
1500	(mod:SF (match_operand:SF 1 "s_register_operand" "f")
1501		(match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1502  "TARGET_ARM && TARGET_HARD_FLOAT"
1503  "rmf%?s\\t%0, %1, %2"
1504  [(set_attr "type" "fdivs")
1505   (set_attr "predicable" "yes")]
1506)
1507
1508(define_insn "moddf3"
1509  [(set (match_operand:DF 0 "s_register_operand" "=f")
1510	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1511		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1512  "TARGET_ARM && TARGET_HARD_FLOAT"
1513  "rmf%?d\\t%0, %1, %2"
1514  [(set_attr "type" "fdivd")
1515   (set_attr "predicable" "yes")]
1516)
1517
1518(define_insn "*moddf_esfdf_df"
1519  [(set (match_operand:DF 0 "s_register_operand" "=f")
1520	(mod:DF (float_extend:DF
1521		 (match_operand:SF 1 "s_register_operand" "f"))
1522		(match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1523  "TARGET_ARM && TARGET_HARD_FLOAT"
1524  "rmf%?d\\t%0, %1, %2"
1525  [(set_attr "type" "fdivd")
1526   (set_attr "predicable" "yes")]
1527)
1528
1529(define_insn "*moddf_df_esfdf"
1530  [(set (match_operand:DF 0 "s_register_operand" "=f")
1531	(mod:DF (match_operand:DF 1 "s_register_operand" "f")
1532		(float_extend:DF
1533		 (match_operand:SF 2 "s_register_operand" "f"))))]
1534  "TARGET_ARM && TARGET_HARD_FLOAT"
1535  "rmf%?d\\t%0, %1, %2"
1536  [(set_attr "type" "fdivd")
1537   (set_attr "predicable" "yes")]
1538)
1539
1540(define_insn "*moddf_esfdf_esfdf"
1541  [(set (match_operand:DF 0 "s_register_operand" "=f")
1542	(mod:DF (float_extend:DF
1543		 (match_operand:SF 1 "s_register_operand" "f"))
1544		(float_extend:DF
1545		 (match_operand:SF 2 "s_register_operand" "f"))))]
1546  "TARGET_ARM && TARGET_HARD_FLOAT"
1547  "rmf%?d\\t%0, %1, %2"
1548  [(set_attr "type" "fdivd")
1549   (set_attr "predicable" "yes")]
1550)
1551
1552(define_insn "modxf3"
1553  [(set (match_operand:XF 0 "s_register_operand" "=f")
1554	(mod:XF (match_operand:XF 1 "s_register_operand" "f")
1555		(match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1556  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1557  "rmf%?e\\t%0, %1, %2"
1558  [(set_attr "type" "fdivx")
1559   (set_attr "predicable" "yes")]
1560)
1561
1562;; Boolean and,ior,xor insns
1563
1564;; Split up double word logical operations
1565
1566;; Split up simple DImode logical operations.  Simply perform the logical
1567;; operation on the upper and lower halves of the registers.
1568(define_split
1569  [(set (match_operand:DI 0 "s_register_operand" "")
1570	(match_operator:DI 6 "logical_binary_operator"
1571	  [(match_operand:DI 1 "s_register_operand" "")
1572	   (match_operand:DI 2 "s_register_operand" "")]))]
1573  "TARGET_ARM && reload_completed"
1574  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1575   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1576  "
1577  {
1578    operands[3] = gen_highpart (SImode, operands[0]);
1579    operands[0] = gen_lowpart (SImode, operands[0]);
1580    operands[4] = gen_highpart (SImode, operands[1]);
1581    operands[1] = gen_lowpart (SImode, operands[1]);
1582    operands[5] = gen_highpart (SImode, operands[2]);
1583    operands[2] = gen_lowpart (SImode, operands[2]);
1584  }"
1585)
1586
1587(define_split
1588  [(set (match_operand:DI 0 "s_register_operand" "")
1589	(match_operator:DI 6 "logical_binary_operator"
1590	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1591	   (match_operand:DI 1 "s_register_operand" "")]))]
1592  "TARGET_ARM && reload_completed"
1593  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1594   (set (match_dup 3) (match_op_dup:SI 6
1595			[(ashiftrt:SI (match_dup 2) (const_int 31))
1596			 (match_dup 4)]))]
1597  "
1598  {
1599    operands[3] = gen_highpart (SImode, operands[0]);
1600    operands[0] = gen_lowpart (SImode, operands[0]);
1601    operands[4] = gen_highpart (SImode, operands[1]);
1602    operands[1] = gen_lowpart (SImode, operands[1]);
1603    operands[5] = gen_highpart (SImode, operands[2]);
1604    operands[2] = gen_lowpart (SImode, operands[2]);
1605  }"
1606)
1607
1608;; The zero extend of operand 2 means we can just copy the high part of
1609;; operand1 into operand0.
1610(define_split
1611  [(set (match_operand:DI 0 "s_register_operand" "")
1612	(ior:DI
1613	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1614	  (match_operand:DI 1 "s_register_operand" "")))]
1615  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1616  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1617   (set (match_dup 3) (match_dup 4))]
1618  "
1619  {
1620    operands[4] = gen_highpart (SImode, operands[1]);
1621    operands[3] = gen_highpart (SImode, operands[0]);
1622    operands[0] = gen_lowpart (SImode, operands[0]);
1623    operands[1] = gen_lowpart (SImode, operands[1]);
1624  }"
1625)
1626
1627;; The zero extend of operand 2 means we can just copy the high part of
1628;; operand1 into operand0.
1629(define_split
1630  [(set (match_operand:DI 0 "s_register_operand" "")
1631	(xor:DI
1632	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1633	  (match_operand:DI 1 "s_register_operand" "")))]
1634  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1635  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1636   (set (match_dup 3) (match_dup 4))]
1637  "
1638  {
1639    operands[4] = gen_highpart (SImode, operands[1]);
1640    operands[3] = gen_highpart (SImode, operands[0]);
1641    operands[0] = gen_lowpart (SImode, operands[0]);
1642    operands[1] = gen_lowpart (SImode, operands[1]);
1643  }"
1644)
1645
1646(define_insn "anddi3"
1647  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1648	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1649		(match_operand:DI 2 "s_register_operand"   "r,r")))]
1650  "TARGET_ARM"
1651  "#"
1652  [(set_attr "length" "8")]
1653)
1654
1655(define_insn_and_split "*anddi_zesidi_di"
1656  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1657	(and:DI (zero_extend:DI
1658		 (match_operand:SI 2 "s_register_operand" "r,r"))
1659		(match_operand:DI 1 "s_register_operand" "?r,0")))]
1660  "TARGET_ARM"
1661  "#"
1662  "TARGET_ARM && reload_completed"
1663  ; The zero extend of operand 2 clears the high word of the output
1664  ; operand.
1665  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1666   (set (match_dup 3) (const_int 0))]
1667  "
1668  {
1669    operands[3] = gen_highpart (SImode, operands[0]);
1670    operands[0] = gen_lowpart (SImode, operands[0]);
1671    operands[1] = gen_lowpart (SImode, operands[1]);
1672  }"
1673  [(set_attr "length" "8")]
1674)
1675
1676(define_insn "*anddi_sesdi_di"
1677  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1678	(and:DI (sign_extend:DI
1679		 (match_operand:SI 2 "s_register_operand" "r,r"))
1680		(match_operand:DI  1 "s_register_operand" "?r,0")))]
1681  "TARGET_ARM"
1682  "#"
1683  [(set_attr "length" "8")]
1684)
1685
1686(define_expand "andsi3"
1687  [(set (match_operand:SI         0 "s_register_operand" "")
1688	(and:SI (match_operand:SI 1 "s_register_operand" "")
1689		(match_operand:SI 2 "reg_or_int_operand" "")))]
1690  "TARGET_EITHER"
1691  "
1692  if (TARGET_ARM)
1693    {
1694      if (GET_CODE (operands[2]) == CONST_INT)
1695        {
1696          arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1697			      operands[1],
1698			      (no_new_pseudos
1699			       ? 0 : preserve_subexpressions_p ()));
1700          DONE;
1701        }
1702    }
1703  else /* TARGET_THUMB */
1704    {
1705      if (GET_CODE (operands[2]) != CONST_INT)
1706        operands[2] = force_reg (SImode, operands[2]);
1707      else
1708        {
1709          int i;
1710	  
1711          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1712  	    {
1713	      operands[2] = force_reg (SImode,
1714				       GEN_INT (~INTVAL (operands[2])));
1715	      
1716	      emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1717	      
1718	      DONE;
1719	    }
1720
1721          for (i = 9; i <= 31; i++)
1722	    {
1723	      if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1724	        {
1725	          emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1726			 	        const0_rtx));
1727	          DONE;
1728	        }
1729	      else if ((((HOST_WIDE_INT) 1) << i) - 1
1730		       == ~INTVAL (operands[2]))
1731	        {
1732	          rtx shift = GEN_INT (i);
1733	          rtx reg = gen_reg_rtx (SImode);
1734		
1735	          emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1736	          emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1737		  
1738	          DONE;
1739	        }
1740	    }
1741
1742          operands[2] = force_reg (SImode, operands[2]);
1743        }
1744    }
1745  "
1746)
1747
1748(define_insn_and_split "*arm_andsi3_insn"
1749  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1750	(and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1751		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1752  "TARGET_ARM"
1753  "@
1754   and%?\\t%0, %1, %2
1755   bic%?\\t%0, %1, #%B2
1756   #"
1757  "TARGET_ARM
1758   && GET_CODE (operands[2]) == CONST_INT
1759   && !(const_ok_for_arm (INTVAL (operands[2]))
1760	|| const_ok_for_arm (~INTVAL (operands[2])))"
1761  [(clobber (const_int 0))]
1762  "
1763  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1764		       operands[1], 0);
1765  DONE;
1766  "
1767  [(set_attr "length" "4,4,16")
1768   (set_attr "predicable" "yes")]
1769)
1770
1771(define_insn "*thumb_andsi3_insn"
1772  [(set (match_operand:SI         0 "register_operand" "=l")
1773	(and:SI (match_operand:SI 1 "register_operand" "%0")
1774		(match_operand:SI 2 "register_operand" "l")))]
1775  "TARGET_THUMB"
1776  "and\\t%0, %0, %2"
1777  [(set_attr "length" "2")]
1778)
1779
1780(define_insn "*andsi3_compare0"
1781  [(set (reg:CC_NOOV CC_REGNUM)
1782	(compare:CC_NOOV
1783	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1784		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1785	 (const_int 0)))
1786   (set (match_operand:SI          0 "s_register_operand" "=r,r")
1787	(and:SI (match_dup 1) (match_dup 2)))]
1788  "TARGET_ARM"
1789  "@
1790   and%?s\\t%0, %1, %2
1791   bic%?s\\t%0, %1, #%B2"
1792  [(set_attr "conds" "set")]
1793)
1794
1795(define_insn "*andsi3_compare0_scratch"
1796  [(set (reg:CC_NOOV CC_REGNUM)
1797	(compare:CC_NOOV
1798	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1799		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1800	 (const_int 0)))
1801   (clobber (match_scratch:SI 2 "=X,r"))]
1802  "TARGET_ARM"
1803  "@
1804   tst%?\\t%0, %1
1805   bic%?s\\t%2, %0, #%B1"
1806  [(set_attr "conds" "set")]
1807)
1808
1809(define_insn "*zeroextractsi_compare0_scratch"
1810  [(set (reg:CC_NOOV CC_REGNUM)
1811	(compare:CC_NOOV (zero_extract:SI
1812			  (match_operand:SI 0 "s_register_operand" "r")
1813		 	  (match_operand 1 "const_int_operand" "n")
1814			  (match_operand 2 "const_int_operand" "n"))
1815			 (const_int 0)))]
1816  "TARGET_ARM
1817  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1818      && INTVAL (operands[1]) > 0 
1819      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1820      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1821  "*
1822  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1823			 << INTVAL (operands[2]));
1824  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1825  return \"\";
1826  "
1827  [(set_attr "conds" "set")]
1828)
1829
1830(define_insn "*ne_zeroextractsi"
1831  [(set (match_operand:SI 0 "s_register_operand" "=r")
1832	(ne:SI (zero_extract:SI
1833		(match_operand:SI 1 "s_register_operand" "r")
1834		(match_operand:SI 2 "const_int_operand" "n")
1835		(match_operand:SI 3 "const_int_operand" "n"))
1836	       (const_int 0)))]
1837  "TARGET_ARM
1838   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1839       && INTVAL (operands[2]) > 0 
1840       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1841       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1842  "*
1843  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1844			 << INTVAL (operands[3]));
1845  output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1846  return \"movne\\t%0, #1\";
1847  "
1848  [(set_attr "conds" "clob")
1849   (set_attr "length" "8")]
1850)
1851
1852;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1853;;; represented by the bitfield, then this will produce incorrect results.
1854;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1855;;; which have a real bitfield insert instruction, the truncation happens
1856;;; in the bitfield insert instruction itself.  Since arm does not have a
1857;;; bitfield insert instruction, we would have to emit code here to truncate
1858;;; the value before we insert.  This loses some of the advantage of having
1859;;; this insv pattern, so this pattern needs to be reevalutated.
1860
1861(define_expand "insv"
1862  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1863                         (match_operand:SI 1 "general_operand" "")
1864                         (match_operand:SI 2 "general_operand" ""))
1865        (match_operand:SI 3 "nonmemory_operand" ""))]
1866  "TARGET_ARM"
1867  "
1868  {
1869    int start_bit = INTVAL (operands[2]);
1870    int width = INTVAL (operands[1]);
1871    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1872    rtx target, subtarget;
1873
1874    target = operands[0];
1875    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1876       subreg as the final target.  */
1877    if (GET_CODE (target) == SUBREG)
1878      {
1879	subtarget = gen_reg_rtx (SImode);
1880	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1881	    < GET_MODE_SIZE (SImode))
1882	  target = SUBREG_REG (target);
1883      }
1884    else
1885      subtarget = target;    
1886
1887    if (GET_CODE (operands[3]) == CONST_INT)
1888      {
1889	/* Since we are inserting a known constant, we may be able to
1890	   reduce the number of bits that we have to clear so that
1891	   the mask becomes simple.  */
1892	/* ??? This code does not check to see if the new mask is actually
1893	   simpler.  It may not be.  */
1894	rtx op1 = gen_reg_rtx (SImode);
1895	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
1896	   start of this pattern.  */
1897	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1898	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1899
1900	emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1901	emit_insn (gen_iorsi3 (subtarget, op1,
1902			       GEN_INT (op3_value << start_bit)));
1903      }
1904    else if (start_bit == 0
1905	     && !(const_ok_for_arm (mask)
1906		  || const_ok_for_arm (~mask)))
1907      {
1908	/* A Trick, since we are setting the bottom bits in the word,
1909	   we can shift operand[3] up, operand[0] down, OR them together
1910	   and rotate the result back again.  This takes 3 insns, and
1911	   the third might be mergable into another op.  */
1912	/* The shift up copes with the possibility that operand[3] is
1913           wider than the bitfield.  */
1914	rtx op0 = gen_reg_rtx (SImode);
1915	rtx op1 = gen_reg_rtx (SImode);
1916
1917	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1918	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1919	emit_insn (gen_iorsi3  (op1, op1, op0));
1920	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1921      }
1922    else if ((width + start_bit == 32)
1923	     && !(const_ok_for_arm (mask)
1924		  || const_ok_for_arm (~mask)))
1925      {
1926	/* Similar trick, but slightly less efficient.  */
1927
1928	rtx op0 = gen_reg_rtx (SImode);
1929	rtx op1 = gen_reg_rtx (SImode);
1930
1931	emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1932	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1933	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1934	emit_insn (gen_iorsi3 (subtarget, op1, op0));
1935      }
1936    else
1937      {
1938	rtx op0 = GEN_INT (mask);
1939	rtx op1 = gen_reg_rtx (SImode);
1940	rtx op2 = gen_reg_rtx (SImode);
1941
1942	if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1943	  {
1944	    rtx tmp = gen_reg_rtx (SImode);
1945
1946	    emit_insn (gen_movsi (tmp, op0));
1947	    op0 = tmp;
1948	  }
1949
1950	/* Mask out any bits in operand[3] that are not needed.  */
1951	   emit_insn (gen_andsi3 (op1, operands[3], op0));
1952
1953	if (GET_CODE (op0) == CONST_INT
1954	    && (const_ok_for_arm (mask << start_bit)
1955		|| const_ok_for_arm (~(mask << start_bit))))
1956	  {
1957	    op0 = GEN_INT (~(mask << start_bit));
1958	    emit_insn (gen_andsi3 (op2, operands[0], op0));
1959	  }
1960	else
1961	  {
1962	    if (GET_CODE (op0) == CONST_INT)
1963	      {
1964		rtx tmp = gen_reg_rtx (SImode);
1965
1966		emit_insn (gen_movsi (tmp, op0));
1967		op0 = tmp;
1968	      }
1969
1970	    if (start_bit != 0)
1971	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1972	    
1973	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1974	  }
1975
1976	if (start_bit != 0)
1977          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1978
1979	emit_insn (gen_iorsi3 (subtarget, op1, op2));
1980      }
1981
1982    if (subtarget != target)
1983      {
1984	/* If TARGET is still a SUBREG, then it must be wider than a word,
1985	   so we must be careful only to set the subword we were asked to.  */
1986	if (GET_CODE (target) == SUBREG)
1987	  emit_move_insn (target, subtarget);
1988	else
1989	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1990      }
1991
1992    DONE;
1993  }"
1994)
1995
1996; constants for op 2 will never be given to these patterns.
1997(define_insn_and_split "*anddi_notdi_di"
1998  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1999	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2000		(match_operand:DI 2 "s_register_operand" "0,r")))]
2001  "TARGET_ARM"
2002  "#"
2003  "TARGET_ARM && reload_completed"
2004  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2005   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2006  "
2007  {
2008    operands[3] = gen_highpart (SImode, operands[0]);
2009    operands[0] = gen_lowpart (SImode, operands[0]);
2010    operands[4] = gen_highpart (SImode, operands[1]);
2011    operands[1] = gen_lowpart (SImode, operands[1]);
2012    operands[5] = gen_highpart (SImode, operands[2]);
2013    operands[2] = gen_lowpart (SImode, operands[2]);
2014  }"
2015  [(set_attr "length" "8")
2016   (set_attr "predicable" "yes")]
2017)
2018  
2019(define_insn_and_split "*anddi_notzesidi_di"
2020  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2021	(and:DI (not:DI (zero_extend:DI
2022			 (match_operand:SI 2 "s_register_operand" "r,r")))
2023		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2024  "TARGET_ARM"
2025  "@
2026   bic%?\\t%Q0, %Q1, %2
2027   #"
2028  ; (not (zero_extend ...)) allows us to just copy the high word from
2029  ; operand1 to operand0.
2030  "TARGET_ARM
2031   && reload_completed
2032   && operands[0] != operands[1]"
2033  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2034   (set (match_dup 3) (match_dup 4))]
2035  "
2036  {
2037    operands[3] = gen_highpart (SImode, operands[0]);
2038    operands[0] = gen_lowpart (SImode, operands[0]);
2039    operands[4] = gen_highpart (SImode, operands[1]);
2040    operands[1] = gen_lowpart (SImode, operands[1]);
2041  }"
2042  [(set_attr "length" "4,8")
2043   (set_attr "predicable" "yes")]
2044)
2045  
2046(define_insn_and_split "*anddi_notsesidi_di"
2047  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2048	(and:DI (not:DI (sign_extend:DI
2049			 (match_operand:SI 2 "s_register_operand" "r,r")))
2050		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2051  "TARGET_ARM"
2052  "#"
2053  "TARGET_ARM && reload_completed"
2054  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2055   (set (match_dup 3) (and:SI (not:SI
2056				(ashiftrt:SI (match_dup 2) (const_int 31)))
2057			       (match_dup 4)))]
2058  "
2059  {
2060    operands[3] = gen_highpart (SImode, operands[0]);
2061    operands[0] = gen_lowpart (SImode, operands[0]);
2062    operands[4] = gen_highpart (SImode, operands[1]);
2063    operands[1] = gen_lowpart (SImode, operands[1]);
2064  }"
2065  [(set_attr "length" "8")
2066   (set_attr "predicable" "yes")]
2067)
2068  
2069(define_insn "andsi_notsi_si"
2070  [(set (match_operand:SI 0 "s_register_operand" "=r")
2071	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2072		(match_operand:SI 1 "s_register_operand" "r")))]
2073  "TARGET_ARM"
2074  "bic%?\\t%0, %1, %2"
2075  [(set_attr "predicable" "yes")]
2076)
2077
2078(define_insn "bicsi3"
2079  [(set (match_operand:SI                 0 "register_operand" "=l")
2080	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2081		(match_operand:SI         2 "register_operand" "0")))]
2082  "TARGET_THUMB"
2083  "bic\\t%0, %0, %1"
2084  [(set_attr "length" "2")]
2085)
2086
2087(define_insn "andsi_not_shiftsi_si"
2088  [(set (match_operand:SI                   0 "s_register_operand" "=r")
2089	(and:SI (not:SI (match_operator:SI  4 "shift_operator"
2090			 [(match_operand:SI 2 "s_register_operand"  "r")
2091			  (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2092		(match_operand:SI           1 "s_register_operand"  "r")))]
2093  "TARGET_ARM"
2094  "bic%?\\t%0, %1, %2%S4"
2095  [(set_attr "predicable" "yes")
2096   (set_attr "shift" "2")
2097   ]
2098)
2099
2100(define_insn "*andsi_notsi_si_compare0"
2101  [(set (reg:CC_NOOV CC_REGNUM)
2102	(compare:CC_NOOV
2103	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2104		 (match_operand:SI 1 "s_register_operand" "r"))
2105	 (const_int 0)))
2106   (set (match_operand:SI 0 "s_register_operand" "=r")
2107	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2108  "TARGET_ARM"
2109  "bic%?s\\t%0, %1, %2"
2110  [(set_attr "conds" "set")]
2111)
2112
2113(define_insn "*andsi_notsi_si_compare0_scratch"
2114  [(set (reg:CC_NOOV CC_REGNUM)
2115	(compare:CC_NOOV
2116	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2117		 (match_operand:SI 1 "s_register_operand" "r"))
2118	 (const_int 0)))
2119   (clobber (match_scratch:SI 0 "=r"))]
2120  "TARGET_ARM"
2121  "bic%?s\\t%0, %1, %2"
2122  [(set_attr "conds" "set")]
2123)
2124
2125(define_insn "iordi3"
2126  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2127	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2128		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2129  "TARGET_ARM"
2130  "#"
2131  [(set_attr "length" "8")
2132   (set_attr "predicable" "yes")]
2133)
2134
2135(define_insn "*iordi_zesidi_di"
2136  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137	(ior:DI (zero_extend:DI
2138		 (match_operand:SI 2 "s_register_operand" "r,r"))
2139		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2140  "TARGET_ARM"
2141  "@
2142   orr%?\\t%Q0, %Q1, %2
2143   #"
2144  [(set_attr "length" "4,8")
2145   (set_attr "predicable" "yes")]
2146)
2147
2148(define_insn "*iordi_sesidi_di"
2149  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2150	(ior:DI (sign_extend:DI
2151		 (match_operand:SI 2 "s_register_operand" "r,r"))
2152		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2153  "TARGET_ARM"
2154  "#"
2155  [(set_attr "length" "8")
2156   (set_attr "predicable" "yes")]
2157)
2158
2159(define_expand "iorsi3"
2160  [(set (match_operand:SI         0 "s_register_operand" "")
2161	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2162		(match_operand:SI 2 "reg_or_int_operand" "")))]
2163  "TARGET_EITHER"
2164  "
2165  if (GET_CODE (operands[2]) == CONST_INT)
2166    {
2167      if (TARGET_ARM)
2168        {
2169          arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2170		 	      operands[1],
2171			      (no_new_pseudos
2172			      ? 0 : preserve_subexpressions_p ()));
2173          DONE;
2174	}
2175      else /* TARGET_THUMB */
2176	operands [2] = force_reg (SImode, operands [2]);
2177    }
2178  "
2179)
2180
2181(define_insn_and_split "*arm_iorsi3"
2182  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2183	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184		(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2185  "TARGET_ARM"
2186  "@
2187   orr%?\\t%0, %1, %2
2188   #"
2189  "TARGET_ARM
2190   && GET_CODE (operands[2]) == CONST_INT
2191   && !const_ok_for_arm (INTVAL (operands[2]))"
2192  [(clobber (const_int 0))]
2193  "
2194  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2195		      operands[1], 0);
2196  DONE;
2197  "
2198  [(set_attr "length" "4,16")
2199   (set_attr "predicable" "yes")]
2200)
2201
2202(define_insn "*thumb_iorsi3"
2203  [(set (match_operand:SI         0 "register_operand" "=l")
2204	(ior:SI (match_operand:SI 1 "register_operand" "%0")
2205		(match_operand:SI 2 "register_operand" "l")))]
2206  "TARGET_THUMB"
2207  "orr\\t%0, %0, %2"
2208  [(set_attr "length" "2")]
2209)
2210
2211(define_peephole2
2212  [(match_scratch:SI 3 "r")
2213   (set (match_operand:SI         0 "s_register_operand" "")
2214	(ior:SI (match_operand:SI 1 "s_register_operand" "")
2215		(match_operand:SI 2 "const_int_operand" "")))]
2216  "TARGET_ARM
2217   && !const_ok_for_arm (INTVAL (operands[2]))
2218   && const_ok_for_arm (~INTVAL (operands[2]))"
2219  [(set (match_dup 3) (match_dup 2))
2220   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221  ""
2222)
2223
2224(define_insn "*iorsi3_compare0"
2225  [(set (reg:CC_NOOV CC_REGNUM)
2226	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228			 (const_int 0)))
2229   (set (match_operand:SI 0 "s_register_operand" "=r")
2230	(ior:SI (match_dup 1) (match_dup 2)))]
2231  "TARGET_ARM"
2232  "orr%?s\\t%0, %1, %2"
2233  [(set_attr "conds" "set")]
2234)
2235
2236(define_insn "*iorsi3_compare0_scratch"
2237  [(set (reg:CC_NOOV CC_REGNUM)
2238	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240			 (const_int 0)))
2241   (clobber (match_scratch:SI 0 "=r"))]
2242  "TARGET_ARM"
2243  "orr%?s\\t%0, %1, %2"
2244  [(set_attr "conds" "set")]
2245)
2246
2247(define_insn "xordi3"
2248  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2249	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2250		(match_operand:DI 2 "s_register_operand"   "r,r")))]
2251  "TARGET_ARM"
2252  "#"
2253  [(set_attr "length" "8")
2254   (set_attr "predicable" "yes")]
2255)
2256
2257(define_insn "*xordi_zesidi_di"
2258  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259	(xor:DI (zero_extend:DI
2260		 (match_operand:SI 2 "s_register_operand" "r,r"))
2261		(match_operand:DI 1 "s_register_operand" "0,?r")))]
2262  "TARGET_ARM"
2263  "@
2264   eor%?\\t%Q0, %Q1, %2
2265   #"
2266  [(set_attr "length" "4,8")
2267   (set_attr "predicable" "yes")]
2268)
2269
2270(define_insn "*xordi_sesidi_di"
2271  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272	(xor:DI (sign_extend:DI
2273		 (match_operand:SI 2 "s_register_operand" "r,r"))
2274		(match_operand:DI 1 "s_register_operand" "?r,0")))]
2275  "TARGET_ARM"
2276  "#"
2277  [(set_attr "length" "8")
2278   (set_attr "predicable" "yes")]
2279)
2280
2281(define_expand "xorsi3"
2282  [(set (match_operand:SI         0 "s_register_operand" "")
2283	(xor:SI (match_operand:SI 1 "s_register_operand" "")
2284		(match_operand:SI 2 "arm_rhs_operand"  "")))]
2285  "TARGET_EITHER"
2286  "if (TARGET_THUMB)
2287     if (GET_CODE (operands[2]) == CONST_INT)
2288       operands[2] = force_reg (SImode, operands[2]);
2289  "
2290)
2291
2292(define_insn "*arm_xorsi3"
2293  [(set (match_operand:SI         0 "s_register_operand" "=r")
2294	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
2296  "TARGET_ARM"
2297  "eor%?\\t%0, %1, %2"
2298  [(set_attr "predicable" "yes")]
2299)
2300
2301(define_insn "*thumb_xorsi3"
2302  [(set (match_operand:SI         0 "register_operand" "=l")
2303	(xor:SI (match_operand:SI 1 "register_operand" "%0")
2304		(match_operand:SI 2 "register_operand" "l")))]
2305  "TARGET_THUMB"
2306  "eor\\t%0, %0, %2"
2307  [(set_attr "length" "2")]
2308)
2309
2310(define_insn "*xorsi3_compare0"
2311  [(set (reg:CC_NOOV CC_REGNUM)
2312	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314			 (const_int 0)))
2315   (set (match_operand:SI 0 "s_register_operand" "=r")
2316	(xor:SI (match_dup 1) (match_dup 2)))]
2317  "TARGET_ARM"
2318  "eor%?s\\t%0, %1, %2"
2319  [(set_attr "conds" "set")]
2320)
2321
2322(define_insn "*xorsi3_compare0_scratch"
2323  [(set (reg:CC_NOOV CC_REGNUM)
2324	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326			 (const_int 0)))]
2327  "TARGET_ARM"
2328  "teq%?\\t%0, %1"
2329  [(set_attr "conds" "set")]
2330)
2331
2332; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2333; (NOT D) we can sometimes merge the final NOT into one of the following
2334; insns.
2335
2336(define_split
2337  [(set (match_operand:SI 0 "s_register_operand" "=r")
2338	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2339			(not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2340		(match_operand:SI 3 "arm_rhs_operand" "rI")))
2341   (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2342  "TARGET_ARM"
2343  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344			      (not:SI (match_dup 3))))
2345   (set (match_dup 0) (not:SI (match_dup 4)))]
2346  ""
2347)
2348
2349(define_insn "*andsi_iorsi3_notsi"
2350  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2354  "TARGET_ARM"
2355  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356  [(set_attr "length" "8")
2357   (set_attr "predicable" "yes")]
2358)
2359
2360
2361
2362;; Minimum and maximum insns
2363
2364(define_insn "smaxsi3"
2365  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2366	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2367		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2368   (clobber (reg:CC CC_REGNUM))]
2369  "TARGET_ARM"
2370  "@
2371   cmp\\t%1, %2\;movlt\\t%0, %2
2372   cmp\\t%1, %2\;movge\\t%0, %1
2373   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2374  [(set_attr "conds" "clob")
2375   (set_attr "length" "8,8,12")]
2376)
2377
2378(define_insn "sminsi3"
2379  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2380	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2381		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2382   (clobber (reg:CC CC_REGNUM))]
2383  "TARGET_ARM"
2384  "@
2385   cmp\\t%1, %2\;movge\\t%0, %2
2386   cmp\\t%1, %2\;movlt\\t%0, %1
2387   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2388  [(set_attr "conds" "clob")
2389   (set_attr "length" "8,8,12")]
2390)
2391
2392(define_insn "umaxsi3"
2393  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2394	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2395		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2396   (clobber (reg:CC CC_REGNUM))]
2397  "TARGET_ARM"
2398  "@
2399   cmp\\t%1, %2\;movcc\\t%0, %2
2400   cmp\\t%1, %2\;movcs\\t%0, %1
2401   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2402  [(set_attr "conds" "clob")
2403   (set_attr "length" "8,8,12")]
2404)
2405
2406(define_insn "uminsi3"
2407  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2408	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2409		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2410   (clobber (reg:CC CC_REGNUM))]
2411  "TARGET_ARM"
2412  "@
2413   cmp\\t%1, %2\;movcs\\t%0, %2
2414   cmp\\t%1, %2\;movcc\\t%0, %1
2415   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2416  [(set_attr "conds" "clob")
2417   (set_attr "length" "8,8,12")]
2418)
2419
2420(define_insn "*store_minmaxsi"
2421  [(set (match_operand:SI 0 "memory_operand" "=m")
2422	(match_operator:SI 3 "minmax_operator"
2423	 [(match_operand:SI 1 "s_register_operand" "r")
2424	  (match_operand:SI 2 "s_register_operand" "r")]))
2425   (clobber (reg:CC CC_REGNUM))]
2426  "TARGET_ARM"
2427  "*
2428  operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2429			 operands[2]);
2430  output_asm_insn (\"cmp\\t%1, %2\", operands);
2431  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2432  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2433  return \"\";
2434  "
2435  [(set_attr "conds" "clob")
2436   (set_attr "length" "12")
2437   (set_attr "type" "store1")]
2438)
2439
2440; Reject the frame pointer in operand[1], since reloading this after
2441; it has been eliminated can cause carnage.
2442(define_insn "*minmax_arithsi"
2443  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2444	(match_operator:SI 4 "shiftable_operator"
2445	 [(match_operator:SI 5 "minmax_operator"
2446	   [(match_operand:SI 2 "s_register_operand" "r,r")
2447	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2448	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
2449   (clobber (reg:CC CC_REGNUM))]
2450  "TARGET_ARM
2451   && (GET_CODE (operands[1]) != REG
2452       || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2453           && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2454  "*
2455  {
2456    enum rtx_code code = GET_CODE (operands[4]);
2457
2458    operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2459			   operands[3]);
2460    output_asm_insn (\"cmp\\t%2, %3\", operands);
2461    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2462    if (which_alternative != 0 || operands[3] != const0_rtx
2463        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2464      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2465    return \"\";
2466  }"
2467  [(set_attr "conds" "clob")
2468   (set_attr "length" "12")]
2469)
2470
2471
2472;; Shift and rotation insns
2473
2474(define_expand "ashlsi3"
2475  [(set (match_operand:SI            0 "s_register_operand" "")
2476	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
2477		   (match_operand:SI 2 "arm_rhs_operand" "")))]
2478  "TARGET_EITHER"
2479  "
2480  if (GET_CODE (operands[2]) == CONST_INT
2481      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2482    {
2483      emit_insn (gen_movsi (operands[0], const0_rtx));
2484      DONE;
2485    }
2486  "
2487)
2488
2489(define_insn "*thumb_ashlsi3"
2490  [(set (match_operand:SI            0 "register_operand" "=l,l")
2491	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2492		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2493  "TARGET_THUMB"
2494  "lsl\\t%0, %1, %2"
2495  [(set_attr "length" "2")]
2496)
2497
2498(define_expand "ashrsi3"
2499  [(set (match_operand:SI              0 "s_register_operand" "")
2500	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2501		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2502  "TARGET_EITHER"
2503  "
2504  if (GET_CODE (operands[2]) == CONST_INT
2505      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2506    operands[2] = GEN_INT (31);
2507  "
2508)
2509
2510(define_insn "*thumb_ashrsi3"
2511  [(set (match_operand:SI              0 "register_operand" "=l,l")
2512	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2513		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2514  "TARGET_THUMB"
2515  "asr\\t%0, %1, %2"
2516  [(set_attr "length" "2")]
2517)
2518
2519(define_expand "lshrsi3"
2520  [(set (match_operand:SI              0 "s_register_operand" "")
2521	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2522		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2523  "TARGET_EITHER"
2524  "
2525  if (GET_CODE (operands[2]) == CONST_INT
2526      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2527    {
2528      emit_insn (gen_movsi (operands[0], const0_rtx));
2529      DONE;
2530    }
2531  "
2532)
2533
2534(define_insn "*thumb_lshrsi3"
2535  [(set (match_operand:SI              0 "register_operand" "=l,l")
2536	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2537		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2538  "TARGET_THUMB"
2539  "lsr\\t%0, %1, %2"
2540  [(set_attr "length" "2")]
2541)
2542
2543(define_expand "rotlsi3"
2544  [(set (match_operand:SI              0 "s_register_operand" "")
2545	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2546		     (match_operand:SI 2 "reg_or_int_operand" "")))]
2547  "TARGET_ARM"
2548  "
2549  if (GET_CODE (operands[2]) == CONST_INT)
2550    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2551  else
2552    {
2553      rtx reg = gen_reg_rtx (SImode);
2554      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2555      operands[2] = reg;
2556    }
2557  "
2558)
2559
2560(define_expand "rotrsi3"
2561  [(set (match_operand:SI              0 "s_register_operand" "")
2562	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2563		     (match_operand:SI 2 "arm_rhs_operand" "")))]
2564  "TARGET_EITHER"
2565  "
2566  if (TARGET_ARM)
2567    {
2568      if (GET_CODE (operands[2]) == CONST_INT
2569          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2570        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2571    }
2572  else /* TARGET_THUMB */
2573    {
2574      if (GET_CODE (operands [2]) == CONST_INT)
2575        operands [2] = force_reg (SImode, operands[2]);
2576    }
2577  "
2578)
2579
2580(define_insn "*thumb_rotrsi3"
2581  [(set (match_operand:SI              0 "register_operand" "=l")
2582	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
2583		     (match_operand:SI 2 "register_operand" "l")))]
2584  "TARGET_THUMB"
2585  "ror\\t%0, %0, %2"
2586  [(set_attr "length" "2")]
2587)
2588
2589(define_insn "*arm_shiftsi3"
2590  [(set (match_operand:SI   0 "s_register_operand" "=r")
2591	(match_operator:SI  3 "shift_operator"
2592	 [(match_operand:SI 1 "s_register_operand"  "r")
2593	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2594  "TARGET_ARM"
2595  "mov%?\\t%0, %1%S3"
2596  [(set_attr "predicable" "yes")
2597   (set_attr "shift" "1")
2598   ]
2599)
2600
2601(define_insn "*shiftsi3_compare0"
2602  [(set (reg:CC_NOOV CC_REGNUM)
2603	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2604			  [(match_operand:SI 1 "s_register_operand" "r")
2605			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2606			 (const_int 0)))
2607   (set (match_operand:SI 0 "s_register_operand" "=r")
2608	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2609  "TARGET_ARM"
2610  "mov%?s\\t%0, %1%S3"
2611  [(set_attr "conds" "set")
2612   (set_attr "shift" "1")
2613   ]
2614)
2615
2616(define_insn "*shiftsi3_compare0_scratch"
2617  [(set (reg:CC_NOOV CC_REGNUM)
2618	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2619			  [(match_operand:SI 1 "s_register_operand" "r")
2620			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
2621			 (const_int 0)))
2622   (clobber (match_scratch:SI 0 "=r"))]
2623  "TARGET_ARM"
2624  "mov%?s\\t%0, %1%S3"
2625  [(set_attr "conds" "set")
2626   (set_attr "shift" "1")
2627   ]
2628)
2629
2630(define_insn "*notsi_shiftsi"
2631  [(set (match_operand:SI 0 "s_register_operand" "=r")
2632	(not:SI (match_operator:SI 3 "shift_operator"
2633		 [(match_operand:SI 1 "s_register_operand" "r")
2634		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2635  "TARGET_ARM"
2636  "mvn%?\\t%0, %1%S3"
2637  [(set_attr "predicable" "yes")
2638   (set_attr "shift" "1")
2639   ]
2640)
2641
2642(define_insn "*notsi_shiftsi_compare0"
2643  [(set (reg:CC_NOOV CC_REGNUM)
2644	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2645			  [(match_operand:SI 1 "s_register_operand" "r")
2646			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2647			 (const_int 0)))
2648   (set (match_operand:SI 0 "s_register_operand" "=r")
2649	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2650  "TARGET_ARM"
2651  "mvn%?s\\t%0, %1%S3"
2652  [(set_attr "conds" "set")
2653   (set_attr "shift" "1")
2654   ]
2655)
2656
2657(define_insn "*not_shiftsi_compare0_scratch"
2658  [(set (reg:CC_NOOV CC_REGNUM)
2659	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2660			  [(match_operand:SI 1 "s_register_operand" "r")
2661			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2662			 (const_int 0)))
2663   (clobber (match_scratch:SI 0 "=r"))]
2664  "TARGET_ARM"
2665  "mvn%?s\\t%0, %1%S3"
2666  [(set_attr "conds" "set")
2667   (set_attr "shift" "1")
2668  ]
2669)
2670
2671;; We don't really have extzv, but defining this using shifts helps
2672;; to reduce register pressure later on.
2673
2674(define_expand "extzv"
2675  [(set (match_dup 4)
2676	(ashift:SI (match_operand:SI   1 "register_operand" "")
2677		   (match_operand:SI   2 "const_int_operand" "")))
2678   (set (match_operand:SI              0 "register_operand" "")
2679	(lshiftrt:SI (match_dup 4)
2680		     (match_operand:SI 3 "const_int_operand" "")))]
2681  "TARGET_THUMB"
2682  "
2683  {
2684    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2685    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2686    
2687    operands[3] = GEN_INT (rshift);
2688    
2689    if (lshift == 0)
2690      {
2691        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2692        DONE;
2693      }
2694      
2695    operands[2] = GEN_INT (lshift);
2696    operands[4] = gen_reg_rtx (SImode);
2697  }"
2698)
2699
2700
2701;; Unary arithmetic insns
2702
2703(define_expand "negdi2"
2704 [(parallel
2705   [(set (match_operand:DI          0 "s_register_operand" "")
2706	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2707    (clobber (reg:CC CC_REGNUM))])]
2708  "TARGET_EITHER"
2709  "
2710  if (TARGET_THUMB)
2711    {
2712      if (GET_CODE (operands[1]) != REG)
2713        operands[1] = force_reg (SImode, operands[1]);
2714     }
2715  "
2716)
2717
2718;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2719;; The second alternative is to allow the common case of a *full* overlap.
2720(define_insn "*arm_negdi2"
2721  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2722	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2723   (clobber (reg:CC CC_REGNUM))]
2724  "TARGET_ARM"
2725  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2726  [(set_attr "conds" "clob")
2727   (set_attr "length" "8")]
2728)
2729
2730(define_insn "*thumb_negdi2"
2731  [(set (match_operand:DI         0 "register_operand" "=&l")
2732	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
2733   (clobber (reg:CC CC_REGNUM))]
2734  "TARGET_THUMB"
2735  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2736  [(set_attr "length" "6")]
2737)
2738
2739(define_expand "negsi2"
2740  [(set (match_operand:SI         0 "s_register_operand" "")
2741	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2742  "TARGET_EITHER"
2743  ""
2744)
2745
2746(define_insn "*arm_negsi2"
2747  [(set (match_operand:SI         0 "s_register_operand" "=r")
2748	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2749  "TARGET_ARM"
2750  "rsb%?\\t%0, %1, #0"
2751  [(set_attr "predicable" "yes")]
2752)
2753
2754(define_insn "*thumb_negsi2"
2755  [(set (match_operand:SI         0 "register_operand" "=l")
2756	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
2757  "TARGET_THUMB"
2758  "neg\\t%0, %1"
2759  [(set_attr "length" "2")]
2760)
2761
2762(define_insn "negsf2"
2763  [(set (match_operand:SF         0 "s_register_operand" "=f")
2764	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2765  "TARGET_ARM && TARGET_HARD_FLOAT"
2766  "mnf%?s\\t%0, %1"
2767  [(set_attr "type" "ffarith")
2768   (set_attr "predicable" "yes")]
2769)
2770
2771(define_insn "negdf2"
2772  [(set (match_operand:DF         0 "s_register_operand" "=f")
2773	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2774  "TARGET_ARM && TARGET_HARD_FLOAT"
2775  "mnf%?d\\t%0, %1"
2776  [(set_attr "type" "ffarith")
2777   (set_attr "predicable" "yes")]
2778)
2779
2780(define_insn "*negdf_esfdf"
2781  [(set (match_operand:DF 0 "s_register_operand" "=f")
2782	(neg:DF (float_extend:DF
2783		 (match_operand:SF 1 "s_register_operand" "f"))))]
2784  "TARGET_ARM && TARGET_HARD_FLOAT"
2785  "mnf%?d\\t%0, %1"
2786  [(set_attr "type" "ffarith")
2787   (set_attr "predicable" "yes")]
2788)
2789
2790(define_insn "negxf2"
2791  [(set (match_operand:XF 0 "s_register_operand" "=f")
2792	(neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2793  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2794  "mnf%?e\\t%0, %1"
2795  [(set_attr "type" "ffarith")
2796   (set_attr "predicable" "yes")]
2797)
2798
2799;; abssi2 doesn't really clobber the condition codes if a different register
2800;; is being set.  To keep things simple, assume during rtl manipulations that
2801;; it does, but tell the final scan operator the truth.  Similarly for
2802;; (neg (abs...))
2803
2804(define_insn "abssi2"
2805  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2806	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2807   (clobber (reg:CC CC_REGNUM))]
2808  "TARGET_ARM"
2809  "@
2810   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2811   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2812  [(set_attr "conds" "clob,*")
2813   (set_attr "shift" "1")
2814   ;; predicable can't be set based on the variant, so left as no
2815   (set_attr "length" "8")]
2816)
2817
2818(define_insn "*neg_abssi2"
2819  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2820	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2821   (clobber (reg:CC CC_REGNUM))]
2822  "TARGET_ARM"
2823  "@
2824   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2825   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2826  [(set_attr "conds" "clob,*")
2827   (set_attr "shift" "1")
2828   ;; predicable can't be set based on the variant, so left as no
2829   (set_attr "length" "8")]
2830)
2831
2832(define_insn "abssf2"
2833  [(set (match_operand:SF          0 "s_register_operand" "=f")
2834	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2835  "TARGET_ARM && TARGET_HARD_FLOAT"
2836  "abs%?s\\t%0, %1"
2837  [(set_attr "type" "ffarith")
2838   (set_attr "predicable" "yes")]
2839)
2840
2841(define_insn "absdf2"
2842  [(set (match_operand:DF         0 "s_register_operand" "=f")
2843	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2844  "TARGET_ARM && TARGET_HARD_FLOAT"
2845  "abs%?d\\t%0, %1"
2846  [(set_attr "type" "ffarith")
2847   (set_attr "predicable" "yes")]
2848)
2849
2850(define_insn "*absdf_esfdf"
2851  [(set (match_operand:DF 0 "s_register_operand" "=f")
2852	(abs:DF (float_extend:DF
2853		 (match_operand:SF 1 "s_register_operand" "f"))))]
2854  "TARGET_ARM && TARGET_HARD_FLOAT"
2855  "abs%?d\\t%0, %1"
2856  [(set_attr "type" "ffarith")
2857   (set_attr "predicable" "yes")]
2858)
2859
2860(define_insn "absxf2"
2861  [(set (match_operand:XF 0 "s_register_operand" "=f")
2862	(abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2863  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2864  "abs%?e\\t%0, %1"
2865  [(set_attr "type" "ffarith")
2866   (set_attr "predicable" "yes")]
2867)
2868
2869(define_insn "sqrtsf2"
2870  [(set (match_operand:SF 0 "s_register_operand" "=f")
2871	(sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2872  "TARGET_ARM && TARGET_HARD_FLOAT"
2873  "sqt%?s\\t%0, %1"
2874  [(set_attr "type" "float_em")
2875   (set_attr "predicable" "yes")]
2876)
2877
2878(define_insn "sqrtdf2"
2879  [(set (match_operand:DF 0 "s_register_operand" "=f")
2880	(sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2881  "TARGET_ARM && TARGET_HARD_FLOAT"
2882  "sqt%?d\\t%0, %1"
2883  [(set_attr "type" "float_em")
2884   (set_attr "predicable" "yes")]
2885)
2886
2887(define_insn "*sqrtdf_esfdf"
2888  [(set (match_operand:DF 0 "s_register_operand" "=f")
2889	(sqrt:DF (float_extend:DF
2890		  (match_operand:SF 1 "s_register_operand" "f"))))]
2891  "TARGET_ARM && TARGET_HARD_FLOAT"
2892  "sqt%?d\\t%0, %1"
2893  [(set_attr "type" "float_em")
2894   (set_attr "predicable" "yes")]
2895)
2896
2897(define_insn "sqrtxf2"
2898  [(set (match_operand:XF 0 "s_register_operand" "=f")
2899	(sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2900  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2901  "sqt%?e\\t%0, %1"
2902  [(set_attr "type" "float_em")
2903   (set_attr "predicable" "yes")]
2904)
2905
2906;; SIN COS TAN and family are always emulated, so it's probably better
2907;; to always call a library function.
2908;(define_insn "sinsf2"
2909;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2910;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2911;		    UNSPEC_SIN))]
2912;  "TARGET_ARM && TARGET_HARD_FLOAT"
2913;  "sin%?s\\t%0, %1"
2914;[(set_attr "type" "float_em")])
2915;
2916;(define_insn "sindf2"
2917;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2918;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2919;		    UNSPEC_SIN))]
2920;  "TARGET_ARM && TARGET_HARD_FLOAT"
2921;  "sin%?d\\t%0, %1"
2922;[(set_attr "type" "float_em")])
2923;
2924;(define_insn "*sindf_esfdf"
2925;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2926;	(unspec:DF [(float_extend:DF
2927;		     (match_operand:SF 1 "s_register_operand" "f"))]
2928;		    UNSPEC_SIN))]
2929;  "TARGET_ARM && TARGET_HARD_FLOAT"
2930;  "sin%?d\\t%0, %1"
2931;[(set_attr "type" "float_em")])
2932;
2933;(define_insn "sinxf2"
2934;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2935;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2936;		   UNSPEC_SIN))]
2937;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2938;  "sin%?e\\t%0, %1"
2939;[(set_attr "type" "float_em")])
2940;
2941;(define_insn "cossf2"
2942;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2943;	(unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2944;		   UNSPEC_COS))]
2945;  "TARGET_ARM && TARGET_HARD_FLOAT"
2946;  "cos%?s\\t%0, %1"
2947;[(set_attr "type" "float_em")])
2948;
2949;(define_insn "cosdf2"
2950;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2951;	(unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2952;		   UNSPEC_COS))]
2953;  "TARGET_ARM && TARGET_HARD_FLOAT"
2954;  "cos%?d\\t%0, %1"
2955;[(set_attr "type" "float_em")])
2956;
2957;(define_insn "*cosdf_esfdf"
2958;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2959;	(unspec:DF [(float_extend:DF
2960;		     (match_operand:SF 1 "s_register_operand" "f"))]
2961;		   UNSPEC_COS))]
2962;  "TARGET_ARM && TARGET_HARD_FLOAT"
2963;  "cos%?d\\t%0, %1"
2964;[(set_attr "type" "float_em")])
2965;
2966;(define_insn "cosxf2"
2967;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2968;	(unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2969;		   UNSEPC_COS))]
2970;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2971;  "cos%?e\\t%0, %1"
2972;[(set_attr "type" "float_em")])
2973
2974(define_insn_and_split "one_cmpldi2"
2975  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2976	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2977  "TARGET_ARM"
2978  "#"
2979  "TARGET_ARM && reload_completed"
2980  [(set (match_dup 0) (not:SI (match_dup 1)))
2981   (set (match_dup 2) (not:SI (match_dup 3)))]
2982  "
2983  {
2984    operands[2] = gen_highpart (SImode, operands[0]);
2985    operands[0] = gen_lowpart (SImode, operands[0]);
2986    operands[3] = gen_highpart (SImode, operands[1]);
2987    operands[1] = gen_lowpart (SImode, operands[1]);
2988  }"
2989  [(set_attr "length" "8")
2990   (set_attr "predicable" "yes")]
2991)
2992
2993(define_expand "one_cmplsi2"
2994  [(set (match_operand:SI         0 "s_register_operand" "")
2995	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
2996  "TARGET_EITHER"
2997  ""
2998)
2999
3000(define_insn "*arm_one_cmplsi2"
3001  [(set (match_operand:SI         0 "s_register_operand" "=r")
3002	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3003  "TARGET_ARM"
3004  "mvn%?\\t%0, %1"
3005  [(set_attr "predicable" "yes")]
3006)
3007
3008(define_insn "*thumb_one_cmplsi2"
3009  [(set (match_operand:SI         0 "register_operand" "=l")
3010	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
3011  "TARGET_THUMB"
3012  "mvn\\t%0, %1"
3013  [(set_attr "length" "2")]
3014)
3015
3016(define_insn "*notsi_compare0"
3017  [(set (reg:CC_NOOV CC_REGNUM)
3018	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3019			 (const_int 0)))
3020   (set (match_operand:SI 0 "s_register_operand" "=r")
3021	(not:SI (match_dup 1)))]
3022  "TARGET_ARM"
3023  "mvn%?s\\t%0, %1"
3024  [(set_attr "conds" "set")]
3025)
3026
3027(define_insn "*notsi_compare0_scratch"
3028  [(set (reg:CC_NOOV CC_REGNUM)
3029	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3030			 (const_int 0)))
3031   (clobber (match_scratch:SI 0 "=r"))]
3032  "TARGET_ARM"
3033  "mvn%?s\\t%0, %1"
3034  [(set_attr "conds" "set")]
3035)
3036
3037;; Fixed <--> Floating conversion insns
3038
3039(define_insn "floatsisf2"
3040  [(set (match_operand:SF           0 "s_register_operand" "=f")
3041	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3042  "TARGET_ARM && TARGET_HARD_FLOAT"
3043  "flt%?s\\t%0, %1"
3044  [(set_attr "type" "r_2_f")
3045   (set_attr "predicable" "yes")]
3046)
3047
3048(define_insn "floatsidf2"
3049  [(set (match_operand:DF           0 "s_register_operand" "=f")
3050	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3051  "TARGET_ARM && TARGET_HARD_FLOAT"
3052  "flt%?d\\t%0, %1"
3053  [(set_attr "type" "r_2_f")
3054   (set_attr "predicable" "yes")]
3055)
3056
3057(define_insn "floatsixf2"
3058  [(set (match_operand:XF 0 "s_register_operand" "=f")
3059	(float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3060  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3061  "flt%?e\\t%0, %1"
3062  [(set_attr "type" "r_2_f")
3063   (set_attr "predicable" "yes")]
3064)
3065
3066(define_insn "fix_truncsfsi2"
3067  [(set (match_operand:SI         0 "s_register_operand" "=r")
3068	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3069  "TARGET_ARM && TARGET_HARD_FLOAT"
3070  "fix%?z\\t%0, %1"
3071  [(set_attr "type" "f_2_r")
3072   (set_attr "predicable" "yes")]
3073)
3074
3075(define_insn "fix_truncdfsi2"
3076  [(set (match_operand:SI         0 "s_register_operand" "=r")
3077	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3078  "TARGET_ARM && TARGET_HARD_FLOAT"
3079  "fix%?z\\t%0, %1"
3080  [(set_attr "type" "f_2_r")
3081   (set_attr "predicable" "yes")]
3082)
3083
3084(define_insn "fix_truncxfsi2"
3085  [(set (match_operand:SI 0 "s_register_operand" "=r")
3086	(fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3087  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3088  "fix%?z\\t%0, %1"
3089  [(set_attr "type" "f_2_r")
3090   (set_attr "predicable" "yes")]
3091)
3092
3093;; Truncation insns
3094
3095(define_insn "truncdfsf2"
3096  [(set (match_operand:SF 0 "s_register_operand" "=f")
3097	(float_truncate:SF
3098	 (match_operand:DF 1 "s_register_operand" "f")))]
3099  "TARGET_ARM && TARGET_HARD_FLOAT"
3100  "mvf%?s\\t%0, %1"
3101  [(set_attr "type" "ffarith")
3102   (set_attr "predicable" "yes")]
3103)
3104
3105(define_insn "truncxfsf2"
3106  [(set (match_operand:SF 0 "s_register_operand" "=f")
3107	(float_truncate:SF
3108	 (match_operand:XF 1 "s_register_operand" "f")))]
3109  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3110  "mvf%?s\\t%0, %1"
3111  [(set_attr "type" "ffarith")
3112   (set_attr "predicable" "yes")]
3113)
3114
3115(define_insn "truncxfdf2"
3116  [(set (match_operand:DF 0 "s_register_operand" "=f")
3117	(float_truncate:DF
3118	 (match_operand:XF 1 "s_register_operand" "f")))]
3119  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3120  "mvf%?d\\t%0, %1"
3121  [(set_attr "type" "ffarith")
3122   (set_attr "predicable" "yes")]
3123)
3124
3125;; Zero and sign extension instructions.
3126
3127(define_insn "zero_extendsidi2"
3128  [(set (match_operand:DI 0 "s_register_operand" "=r")
3129        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3130  "TARGET_ARM"
3131  "*
3132    if (REGNO (operands[1])
3133        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3134      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3135    return \"mov%?\\t%R0, #0\";
3136  "
3137  [(set_attr "length" "8")
3138   (set_attr "predicable" "yes")]
3139)
3140
3141(define_insn "zero_extendqidi2"
3142  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3143	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3144  "TARGET_ARM"
3145  "@
3146   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3147   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3148  [(set_attr "length" "8")
3149   (set_attr "predicable" "yes")
3150   (set_attr "type" "*,load")
3151   (set_attr "pool_range" "*,4092")
3152   (set_attr "neg_pool_range" "*,4084")]
3153)
3154
3155(define_insn "extendsidi2"
3156  [(set (match_operand:DI 0 "s_register_operand" "=r")
3157        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3158  "TARGET_ARM"
3159  "*
3160    if (REGNO (operands[1])
3161        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3162      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3163    return \"mov%?\\t%R0, %Q0, asr #31\";
3164  "
3165  [(set_attr "length" "8")
3166   (set_attr "shift" "1")
3167   (set_attr "predicable" "yes")]
3168)
3169
3170(define_expand "zero_extendhisi2"
3171  [(set (match_dup 2)
3172	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3173		   (const_int 16)))
3174   (set (match_operand:SI 0 "s_register_operand" "")
3175	(lshiftrt:SI (match_dup 2) (const_int 16)))]
3176  "TARGET_EITHER"
3177  "
3178  {
3179    if (TARGET_ARM)
3180      {
3181        if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3182          {
3183           /* Note: We do not have to worry about TARGET_MMU_TRAPS
3184	      here because the insn below will generate an LDRH instruction
3185	      rather than an LDR instruction, so we cannot get an unaligned
3186	      word access.  */
3187            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3188			            gen_rtx_ZERO_EXTEND (SImode,
3189							 operands[1])));
3190            DONE;
3191          }
3192        if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3193          {
3194            emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3195            DONE;
3196          }
3197        if (!s_register_operand (operands[1], HImode))
3198          operands[1] = copy_to_mode_reg (HImode, operands[1]);
3199        operands[1] = gen_lowpart (SImode, operands[1]);
3200        operands[2] = gen_reg_rtx (SImode);
3201      }
3202    else /* TARGET_THUMB */
3203      {
3204        if (GET_CODE (operands[1]) == MEM)
3205	  {
3206	    rtx tmp;
3207
3208	    tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3209	    tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3210	    emit_insn (tmp);
3211	  }
3212	else
3213	  {
3214	    rtx ops[3];
3215	    
3216	    if (!s_register_operand (operands[1], HImode))
3217	      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3218	    operands[1] = gen_lowpart (SImode, operands[1]);
3219	    operands[2] = gen_reg_rtx (SImode);
3220	    
3221	    ops[0] = operands[2];
3222	    ops[1] = operands[1];
3223	    ops[2] = GEN_INT (16);
3224	    
3225	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3226				    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3227
3228	    ops[0] = operands[0];
3229	    ops[1] = operands[2];
3230	    ops[2] = GEN_INT (16);
3231
3232	    emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3233				    gen_rtx_LSHIFTRT (SImode, ops[1],
3234						      ops[2])));
3235	  }
3236	DONE; 
3237      }
3238  }"
3239)
3240
3241(define_insn "*thumb_zero_extendhisi2"
3242  [(set (match_operand:SI                 0 "register_operand" "=l")
3243	(zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3244  "TARGET_THUMB"
3245  "*
3246  rtx mem = XEXP (operands[1], 0);
3247
3248  if (GET_CODE (mem) == CONST)
3249    mem = XEXP (mem, 0);
3250    
3251  if (GET_CODE (mem) == LABEL_REF)
3252    return \"ldr\\t%0, %1\";
3253    
3254  if (GET_CODE (mem) == PLUS)
3255    {
3256      rtx a = XEXP (mem, 0);
3257      rtx b = XEXP (mem, 1);
3258
3259      /* This can happen due to bugs in reload.  */
3260      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3261        {
3262          rtx ops[2];
3263          ops[0] = operands[0];
3264          ops[1] = a;
3265      
3266          output_asm_insn (\"mov	%0, %1\", ops);
3267
3268          XEXP (mem, 0) = operands[0];
3269       }
3270
3271      else if (   GET_CODE (a) == LABEL_REF
3272	       && GET_CODE (b) == CONST_INT)
3273        return \"ldr\\t%0, %1\";
3274    }
3275    
3276  return \"ldrh\\t%0, %1\";
3277  "
3278  [(set_attr "length" "4")
3279   (set_attr "type" "load")
3280   (set_attr "pool_range" "60")]
3281)
3282
3283(define_insn "*arm_zero_extendhisi2"
3284  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3285	(zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3286  "TARGET_ARM && arm_arch4"
3287  "ldr%?h\\t%0, %1"
3288  [(set_attr "type" "load")
3289   (set_attr "predicable" "yes")
3290   (set_attr "pool_range" "256")
3291   (set_attr "neg_pool_range" "244")]
3292)
3293
3294(define_split
3295  [(set (match_operand:SI 0 "s_register_operand" "")
3296	(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3297   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3298  "TARGET_ARM && (!arm_arch4)"
3299  [(set (match_dup 2) (match_dup 1))
3300   (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3301  "
3302  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3303    FAIL;
3304  "
3305)
3306
3307(define_split
3308  [(set (match_operand:SI 0 "s_register_operand" "")
3309	(match_operator:SI 3 "shiftable_operator"
3310	 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3311	  (match_operand:SI 4 "s_register_operand" "")]))
3312   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3313  "TARGET_ARM && (!arm_arch4)"
3314  [(set (match_dup 2) (match_dup 1))
3315   (set (match_dup 0)
3316	(match_op_dup 3
3317	 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3318  "
3319  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3320    FAIL;
3321  "
3322)
3323
3324(define_expand "zero_extendqisi2"
3325  [(set (match_operand:SI 0 "s_register_operand" "")
3326	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3327  "TARGET_EITHER"
3328  "
3329  if (GET_CODE (operands[1]) != MEM)
3330    {
3331      if (TARGET_ARM)
3332        {
3333          emit_insn (gen_andsi3 (operands[0],
3334				 gen_lowpart (SImode, operands[1]),
3335			         GEN_INT (255)));
3336        }
3337      else /* TARGET_THUMB */
3338        {
3339          rtx temp = gen_reg_rtx (SImode);
3340	  rtx ops[3];
3341	  
3342          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3343          operands[1] = gen_lowpart (SImode, operands[1]);
3344
3345	  ops[0] = temp;
3346	  ops[1] = operands[1];
3347	  ops[2] = GEN_INT (24);
3348
3349	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3350				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3351	  
3352          ops[0] = operands[0];
3353	  ops[1] = temp;
3354	  ops[2] = GEN_INT (24);
3355
3356	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3357				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3358	}
3359      DONE;
3360    }
3361  "
3362)
3363
3364(define_insn "*thumb_zero_extendqisi2"
3365  [(set (match_operand:SI                 0 "register_operand" "=l")
3366	(zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3367  "TARGET_THUMB"
3368  "ldrb\\t%0, %1"
3369  [(set_attr "length" "2")
3370   (set_attr "type" "load")
3371   (set_attr "pool_range" "32")]
3372)
3373
3374(define_insn "*arm_zero_extendqisi2"
3375  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3376	(zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3377  "TARGET_ARM"
3378  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3379  [(set_attr "type" "load")
3380   (set_attr "predicable" "yes")
3381   (set_attr "pool_range" "4096")
3382   (set_attr "neg_pool_range" "4084")]
3383)
3384
3385(define_split
3386  [(set (match_operand:SI 0 "s_register_operand" "")
3387	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3388   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3389  "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3390  [(set (match_dup 2) (match_dup 1))
3391   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3392  ""
3393)
3394
3395(define_insn "*compareqi_eq0"
3396  [(set (reg:CC_Z CC_REGNUM)
3397	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3398			 (const_int 0)))]
3399  "TARGET_ARM"
3400  "tst\\t%0, #255"
3401  [(set_attr "conds" "set")]
3402)
3403
3404(define_expand "extendhisi2"
3405  [(set (match_dup 2)
3406	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3407		   (const_int 16)))
3408   (set (match_operand:SI 0 "s_register_operand" "")
3409	(ashiftrt:SI (match_dup 2)
3410		     (const_int 16)))]
3411  "TARGET_EITHER"
3412  "
3413  {
3414    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3415      {
3416       /* Note: We do not have to worry about TARGET_MMU_TRAPS
3417	  here because the insn below will generate an LDRH instruction
3418	  rather than an LDR instruction, so we cannot get an unaligned
3419	  word access.  */
3420        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3421		   gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3422        DONE;
3423      }
3424
3425    if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3426      {
3427        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3428        DONE;
3429      }
3430    if (!s_register_operand (operands[1], HImode))
3431      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3432    operands[1] = gen_lowpart (SImode, operands[1]);
3433    operands[2] = gen_reg_rtx (SImode);
3434
3435    if (TARGET_THUMB)
3436      {
3437	rtx ops[3];
3438	
3439	ops[0] = operands[2];
3440	ops[1] = operands[1];
3441	ops[2] = GEN_INT (16);
3442	
3443        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444				gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3445	    
3446	ops[0] = operands[0];
3447	ops[1] = operands[2];
3448	ops[2] = GEN_INT (16);
3449	
3450        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451				gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3452	
3453	DONE;
3454      }
3455  }"
3456)
3457
3458(define_insn "*thumb_extendhisi2_insn"
3459  [(set (match_operand:SI                 0 "register_operand" "=l")
3460	(sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3461   (clobber (match_scratch:SI             2                   "=&l"))]
3462  "TARGET_THUMB"
3463  "*
3464  {
3465    rtx ops[4];
3466    rtx mem = XEXP (operands[1], 0);
3467
3468    /* This code used to try to use 'V', and fix the address only if it was
3469       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3470       range of QImode offsets, and offsettable_address_p does a QImode
3471       address check.  */
3472       
3473    if (GET_CODE (mem) == CONST)
3474      mem = XEXP (mem, 0);
3475    
3476    if (GET_CODE (mem) == LABEL_REF)
3477      return \"ldr\\t%0, %1\";
3478    
3479    if (GET_CODE (mem) == PLUS)
3480      {
3481        rtx a = XEXP (mem, 0);
3482        rtx b = XEXP (mem, 1);
3483
3484        if (GET_CODE (a) == LABEL_REF
3485	    && GET_CODE (b) == CONST_INT)
3486          return \"ldr\\t%0, %1\";
3487
3488        if (GET_CODE (b) == REG)
3489          return \"ldrsh\\t%0, %1\";
3490	  
3491        ops[1] = a;
3492        ops[2] = b;
3493      }
3494    else
3495      {
3496        ops[1] = mem;
3497        ops[2] = const0_rtx;
3498      }
3499      
3500    if (GET_CODE (ops[1]) != REG)
3501      {
3502        debug_rtx (ops[1]);
3503        abort ();
3504      }
3505
3506    ops[0] = operands[0];
3507    ops[3] = operands[2];
3508    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3509    return \"\";
3510  }"
3511  [(set_attr "length" "4")
3512   (set_attr "type" "load")
3513   (set_attr "pool_range" "1020")]
3514)
3515
3516(define_expand "extendhisi2_mem"
3517  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3518   (set (match_dup 3)
3519	(zero_extend:SI (match_dup 7)))
3520   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3521   (set (match_operand:SI 0 "" "")
3522	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3523  "TARGET_ARM"
3524  "
3525  {
3526    rtx mem1, mem2;
3527    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3528
3529    mem1 = gen_rtx_MEM (QImode, addr);
3530    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3531    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3532    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3533    operands[0] = gen_lowpart (SImode, operands[0]);
3534    operands[1] = mem1;
3535    operands[2] = gen_reg_rtx (SImode);
3536    operands[3] = gen_reg_rtx (SImode);
3537    operands[6] = gen_reg_rtx (SImode);
3538    operands[7] = mem2;
3539
3540    if (BYTES_BIG_ENDIAN)
3541      {
3542	operands[4] = operands[2];
3543	operands[5] = operands[3];
3544      }
3545    else
3546      {
3547	operands[4] = operands[3];
3548	operands[5] = operands[2];
3549      }
3550  }"
3551)
3552
3553(define_insn "*arm_extendhisi_insn"
3554  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3555	(sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3556  "TARGET_ARM && arm_arch4"
3557  "ldr%?sh\\t%0, %1"
3558  [(set_attr "type" "load")
3559   (set_attr "predicable" "yes")
3560   (set_attr "pool_range" "256")
3561   (set_attr "neg_pool_range" "244")]
3562)
3563
3564(define_split
3565  [(set (match_operand:SI                 0 "s_register_operand" "")
3566	(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3567   (clobber (match_operand:SI             2 "s_register_operand" ""))]
3568  "TARGET_ARM && (!arm_arch4)"
3569  [(set (match_dup 2) (match_dup 1))
3570   (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3571  "
3572  if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3573    FAIL;
3574  "
3575)
3576
3577(define_split
3578  [(set (match_operand:SI                   0 "s_register_operand" "")
3579	(match_operator:SI                  3 "shiftable_operator"
3580	 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3581	  (match_operand:SI                 4 "s_register_operand" "")]))
3582   (clobber (match_operand:SI               2 "s_register_operand" ""))]
3583  "TARGET_ARM && (!arm_arch4)"
3584  [(set (match_dup 2) (match_dup 1))
3585   (set (match_dup 0)
3586	(match_op_dup 3
3587	 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3588  "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3589     FAIL;
3590  "
3591)
3592
3593(define_expand "extendqihi2"
3594  [(set (match_dup 2)
3595	(ashift:SI (match_operand:QI 1 "general_operand" "")
3596		   (const_int 24)))
3597   (set (match_operand:HI 0 "s_register_operand" "")
3598	(ashiftrt:SI (match_dup 2)
3599		     (const_int 24)))]
3600  "TARGET_ARM"
3601  "
3602  {
3603    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3604      {
3605	emit_insn (gen_rtx_SET (VOIDmode,
3606				operands[0],
3607				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3608	DONE;
3609      }
3610    if (!s_register_operand (operands[1], QImode))
3611      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3612    operands[0] = gen_lowpart (SImode, operands[0]);
3613    operands[1] = gen_lowpart (SImode, operands[1]);
3614    operands[2] = gen_reg_rtx (SImode);
3615  }"
3616)
3617
3618; Rather than restricting all byte accesses to memory addresses that ldrsb
3619; can handle, we fix up the ones that ldrsb can't grok with a split.
3620(define_insn "*extendqihi_insn"
3621  [(set (match_operand:HI                 0 "s_register_operand" "=r")
3622	(sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3623  "TARGET_ARM && arm_arch4"
3624  "*
3625  /* If the address is invalid, this will split the instruction into two. */
3626  if (bad_signed_byte_operand (operands[1], VOIDmode))
3627    return \"#\";
3628  return \"ldr%?sb\\t%0, %1\";
3629  "
3630  [(set_attr "type" "load")
3631   (set_attr "predicable" "yes")
3632   (set_attr "length" "8")
3633   (set_attr "pool_range" "256")
3634   (set_attr "neg_pool_range" "244")]
3635)
3636
3637(define_split
3638  [(set (match_operand:HI 0 "s_register_operand" "")
3639	(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3640  "TARGET_ARM && arm_arch4 && reload_completed"
3641  [(set (match_dup 3) (match_dup 1))
3642   (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3643  "
3644  {
3645    HOST_WIDE_INT offset;
3646
3647    operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3648    operands[2] = gen_rtx_MEM (QImode, operands[3]);
3649    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3650    operands[1] = XEXP (operands[1], 0);
3651    if (GET_CODE (operands[1]) == PLUS
3652	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3653	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3654	     || const_ok_for_arm (-offset)))
3655      {
3656	HOST_WIDE_INT low = (offset > 0
3657			     ? (offset & 0xff) : -((-offset) & 0xff));
3658	XEXP (operands[2], 0) = plus_constant (operands[3], low);
3659	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3660      }
3661    /* Ensure the sum is in correct canonical form */
3662    else if (GET_CODE (operands[1]) == PLUS
3663	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3664	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3665      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3666					   XEXP (operands[1], 1),
3667					   XEXP (operands[1], 0));
3668  }"
3669)
3670
3671(define_expand "extendqisi2"
3672  [(set (match_dup 2)
3673	(ashift:SI (match_operand:QI 1 "general_operand" "")
3674		   (const_int 24)))
3675   (set (match_operand:SI 0 "s_register_operand" "")
3676	(ashiftrt:SI (match_dup 2)
3677		     (const_int 24)))]
3678  "TARGET_EITHER"
3679  "
3680  {
3681    if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3682      {
3683        emit_insn (gen_rtx_SET (VOIDmode,
3684			        operands[0],
3685			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3686        DONE;
3687      }
3688    if (!s_register_operand (operands[1], QImode))
3689      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3690    operands[1] = gen_lowpart (SImode, operands[1]);
3691    operands[2] = gen_reg_rtx (SImode);
3692    
3693    if (TARGET_THUMB)
3694      {
3695	rtx ops[3];
3696	
3697	ops[0] = operands[2];
3698	ops[1] = operands[1];
3699	ops[2] = GEN_INT (24);
3700	
3701        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3702		   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3703
3704	ops[0] = operands[0];
3705	ops[1] = operands[2];
3706	ops[2] = GEN_INT (24);
3707	
3708        emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3709		   gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3710	
3711	DONE;
3712      }
3713  }"
3714)
3715
3716; Rather than restricting all byte accesses to memory addresses that ldrsb
3717; can handle, we fix up the ones that ldrsb can't grok with a split.
3718(define_insn "*arm_extendqisi_insn"
3719  [(set (match_operand:SI                 0 "s_register_operand" "=r")
3720	(sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3721  "TARGET_ARM && arm_arch4"
3722  "*
3723  /* If the address is invalid, this will split the instruction into two. */
3724  if (bad_signed_byte_operand (operands[1], VOIDmode))
3725    return \"#\";
3726  return \"ldr%?sb\\t%0, %1\";
3727  "
3728  [(set_attr "type" "load")
3729   (set_attr "predicable" "yes")
3730   (set_attr "length" "8")
3731   (set_attr "pool_range" "256")
3732   (set_attr "neg_pool_range" "244")]
3733)
3734
3735(define_split
3736  [(set (match_operand:SI 0 "s_register_operand" "")
3737	(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3738  "TARGET_ARM && arm_arch4 && reload_completed"
3739  [(set (match_dup 0) (match_dup 1))
3740   (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3741  "
3742  {
3743    HOST_WIDE_INT offset;
3744
3745    operands[2] = gen_rtx_MEM (QImode, operands[0]);
3746    MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3747    operands[1] = XEXP (operands[1], 0);
3748    if (GET_CODE (operands[1]) == PLUS
3749	&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3750	&& !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3751	     || const_ok_for_arm (-offset)))
3752      {
3753	HOST_WIDE_INT low = (offset > 0
3754			     ? (offset & 0xff) : -((-offset) & 0xff));
3755	XEXP (operands[2], 0) = plus_constant (operands[0], low);
3756	operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3757      }
3758    /* Ensure the sum is in correct canonical form */
3759    else if (GET_CODE (operands[1]) == PLUS
3760	     && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3761	     && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3762      operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3763					   XEXP (operands[1], 1),
3764					   XEXP (operands[1], 0));
3765  }"
3766)
3767
3768(define_insn "*thumb_extendqisi2_insn"
3769  [(set (match_operand:SI                 0 "register_operand" "=l,l")
3770	(sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3771  "TARGET_THUMB"
3772  "*
3773  {
3774    rtx ops[3];
3775    rtx mem = XEXP (operands[1], 0);
3776    
3777    if (GET_CODE (mem) == CONST)
3778      mem = XEXP (mem, 0);
3779    
3780    if (GET_CODE (mem) == LABEL_REF)
3781      return \"ldr\\t%0, %1\";
3782
3783    if (GET_CODE (mem) == PLUS
3784        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3785      return \"ldr\\t%0, %1\";
3786      
3787    if (which_alternative == 0)
3788      return \"ldrsb\\t%0, %1\";
3789      
3790    ops[0] = operands[0];
3791    
3792    if (GET_CODE (mem) == PLUS)
3793      {
3794        rtx a = XEXP (mem, 0);
3795	rtx b = XEXP (mem, 1);
3796	
3797        ops[1] = a;
3798        ops[2] = b;
3799
3800        if (GET_CODE (a) == REG)
3801	  {
3802	    if (GET_CODE (b) == REG)
3803              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3804            else if (REGNO (a) == REGNO (ops[0]))
3805	      {
3806                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3807		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3808		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3809	      }
3810	    else
3811              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3812	  }
3813        else if (GET_CODE (b) != REG)
3814	  abort ();
3815	else
3816          {
3817            if (REGNO (b) == REGNO (ops[0]))
3818	      {
3819                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3820		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3821		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3822	      }
3823	    else
3824              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3825          }
3826      }
3827    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3828      {
3829        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3830	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3831	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3832      }
3833    else
3834      {
3835        ops[1] = mem;
3836        ops[2] = const0_rtx;
3837	
3838        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3839      }
3840    return \"\";
3841  }"
3842  [(set_attr "length" "2,6")
3843   (set_attr "type" "load,load")
3844   (set_attr "pool_range" "32,32")]
3845)
3846
3847(define_insn "extendsfdf2"
3848  [(set (match_operand:DF                  0 "s_register_operand" "=f")
3849	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3850  "TARGET_ARM && TARGET_HARD_FLOAT"
3851  "mvf%?d\\t%0, %1"
3852  [(set_attr "type" "ffarith")
3853   (set_attr "predicable" "yes")]
3854)
3855
3856(define_insn "extendsfxf2"
3857  [(set (match_operand:XF 0 "s_register_operand" "=f")
3858	(float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3859  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3860  "mvf%?e\\t%0, %1"
3861  [(set_attr "type" "ffarith")
3862   (set_attr "predicable" "yes")]
3863)
3864
3865(define_insn "extenddfxf2"
3866  [(set (match_operand:XF 0 "s_register_operand" "=f")
3867	(float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3868  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3869  "mvf%?e\\t%0, %1"
3870  [(set_attr "type" "ffarith")
3871   (set_attr "predicable" "yes")]
3872)
3873
3874
3875;; Move insns (including loads and stores)
3876
3877;; XXX Just some ideas about movti.
3878;; I don't think these are a good idea on the arm, there just aren't enough
3879;; registers
3880;;(define_expand "loadti"
3881;;  [(set (match_operand:TI 0 "s_register_operand" "")
3882;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
3883;;  "" "")
3884
3885;;(define_expand "storeti"
3886;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3887;;	(match_operand:TI 1 "s_register_operand" ""))]
3888;;  "" "")
3889
3890;;(define_expand "movti"
3891;;  [(set (match_operand:TI 0 "general_operand" "")
3892;;	(match_operand:TI 1 "general_operand" ""))]
3893;;  ""
3894;;  "
3895;;{
3896;;  rtx insn;
3897;;
3898;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3899;;    operands[1] = copy_to_reg (operands[1]);
3900;;  if (GET_CODE (operands[0]) == MEM)
3901;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3902;;  else if (GET_CODE (operands[1]) == MEM)
3903;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3904;;  else
3905;;    FAIL;
3906;;
3907;;  emit_insn (insn);
3908;;  DONE;
3909;;}")
3910
3911;; Recognise garbage generated above.
3912
3913;;(define_insn ""
3914;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3915;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3916;;  ""
3917;;  "*
3918;;  {
3919;;    register mem = (which_alternative < 3);
3920;;    register const char *template;
3921;;
3922;;    operands[mem] = XEXP (operands[mem], 0);
3923;;    switch (which_alternative)
3924;;      {
3925;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3926;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3927;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3928;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3929;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3930;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3931;;      }
3932;;    output_asm_insn (template, operands);
3933;;    return \"\";
3934;;  }")
3935
3936(define_expand "movdi"
3937  [(set (match_operand:DI 0 "general_operand" "")
3938	(match_operand:DI 1 "general_operand" ""))]
3939  "TARGET_EITHER"
3940  "
3941  if (TARGET_THUMB)
3942    {
3943      if (!no_new_pseudos)
3944        {
3945          if (GET_CODE (operands[0]) != REG)
3946	    operands[1] = force_reg (DImode, operands[1]);
3947        }
3948    }
3949  "
3950)
3951
3952(define_insn "*arm_movdi"
3953  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3954	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3955  "TARGET_ARM"
3956  "*
3957  return (output_move_double (operands));
3958  "
3959  [(set_attr "length" "8")
3960   (set_attr "type" "*,load,store2")
3961   (set_attr "pool_range" "*,1020,*")
3962   (set_attr "neg_pool_range" "*,1012,*")]
3963)
3964
3965;;; ??? This should have alternatives for constants.
3966;;; ??? This was originally identical to the movdf_insn pattern.
3967;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3968;;; thumb_reorg with a memory reference.
3969(define_insn "*thumb_movdi_insn"
3970  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3971	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3972  "TARGET_THUMB
3973   && (   register_operand (operands[0], DImode)
3974       || register_operand (operands[1], DImode))"
3975  "*
3976  {
3977  switch (which_alternative)
3978    {
3979    default:
3980    case 0:
3981      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3982	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3983      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3984    case 1:
3985      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3986    case 2:
3987      operands[1] = GEN_INT (- INTVAL (operands[1]));
3988      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3989    case 3:
3990      return \"ldmia\\t%1, {%0, %H0}\";
3991    case 4:
3992      return \"stmia\\t%0, {%1, %H1}\";
3993    case 5:
3994      return thumb_load_double_from_address (operands);
3995    case 6:
3996      operands[2] = gen_rtx (MEM, SImode,
3997			     plus_constant (XEXP (operands[0], 0), 4));
3998      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3999      return \"\";
4000    case 7:
4001      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4002	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4003      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4004    }
4005  }"
4006  [(set_attr "length" "4,4,6,2,2,6,4,4")
4007   (set_attr "type" "*,*,*,load,store2,load,store2,*")
4008   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4009)
4010
4011(define_expand "movsi"
4012  [(set (match_operand:SI 0 "general_operand" "")
4013        (match_operand:SI 1 "general_operand" ""))]
4014  "TARGET_EITHER"
4015  "
4016  if (TARGET_ARM)
4017    {
4018      /* Everything except mem = const or mem = mem can be done easily */
4019      if (GET_CODE (operands[0]) == MEM)
4020        operands[1] = force_reg (SImode, operands[1]);
4021      if (GET_CODE (operands[1]) == CONST_INT
4022          && !(const_ok_for_arm (INTVAL (operands[1]))
4023               || const_ok_for_arm (~INTVAL (operands[1]))))
4024        {
4025           arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4026		    	      NULL_RTX,
4027			      (no_new_pseudos ? 0
4028			       : preserve_subexpressions_p ()));
4029          DONE;
4030        }
4031    }
4032  else /* TARGET_THUMB.... */
4033    {
4034      if (!no_new_pseudos)
4035        {
4036          if (GET_CODE (operands[0]) != REG)
4037	    operands[1] = force_reg (SImode, operands[1]);
4038        }
4039    }
4040    
4041  if (flag_pic
4042      && (CONSTANT_P (operands[1])
4043	 || symbol_mentioned_p (operands[1])
4044	 || label_mentioned_p (operands[1])))
4045    operands[1] = legitimize_pic_address (operands[1], SImode,
4046					  (no_new_pseudos ? operands[0] : 0));
4047  "
4048)
4049
4050(define_insn "*arm_movsi_insn"
4051  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4052	(match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4053  "TARGET_ARM
4054   && (   register_operand (operands[0], SImode)
4055       || register_operand (operands[1], SImode))"
4056  "@
4057   mov%?\\t%0, %1
4058   mvn%?\\t%0, #%B1
4059   ldr%?\\t%0, %1
4060   str%?\\t%1, %0"
4061  [(set_attr "type" "*,*,load,store1")
4062   (set_attr "predicable" "yes")
4063   (set_attr "pool_range" "*,*,4096,*")
4064   (set_attr "neg_pool_range" "*,*,4084,*")]
4065)
4066
4067(define_split
4068  [(set (match_operand:SI 0 "s_register_operand" "")
4069	(match_operand:SI 1 "const_int_operand" ""))]
4070  "TARGET_ARM
4071  && (!(const_ok_for_arm (INTVAL (operands[1]))
4072        || const_ok_for_arm (~INTVAL (operands[1]))))"
4073  [(clobber (const_int 0))]
4074  "
4075  arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4076		      NULL_RTX, 0);
4077  DONE;
4078  "
4079)
4080
4081(define_insn "*thumb_movsi_insn"
4082  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4083	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4084  "TARGET_THUMB
4085   && (   register_operand (operands[0], SImode) 
4086       || register_operand (operands[1], SImode))"
4087  "@
4088   mov	%0, %1
4089   mov	%0, %1
4090   #
4091   #
4092   ldmia\\t%1, {%0}
4093   stmia\\t%0, {%1}
4094   ldr\\t%0, %1
4095   str\\t%1, %0
4096   mov\\t%0, %1"
4097  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4098   (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4099   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4100)
4101
4102(define_split 
4103  [(set (match_operand:SI 0 "register_operand" "")
4104	(match_operand:SI 1 "const_int_operand" ""))]
4105  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4106  [(set (match_dup 0) (match_dup 1))
4107   (set (match_dup 0) (neg:SI (match_dup 0)))]
4108  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4109)
4110
4111(define_split 
4112  [(set (match_operand:SI 0 "register_operand" "")
4113	(match_operand:SI 1 "const_int_operand" ""))]
4114  "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4115  [(set (match_dup 0) (match_dup 1))
4116   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4117  "
4118  {
4119    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4120    unsigned HOST_WIDE_INT mask = 0xff;
4121    int i;
4122    
4123    for (i = 0; i < 25; i++)
4124      if ((val & (mask << i)) == val)
4125        break;
4126
4127    if (i == 0)
4128      FAIL;
4129
4130    operands[1] = GEN_INT (val >> i);
4131    operands[2] = GEN_INT (i);
4132  }"
4133)
4134
4135(define_expand "movaddr"
4136  [(set (match_operand:SI 0 "s_register_operand" "")
4137	(match_operand:DI 1 "address_operand" ""))]
4138  "TARGET_ARM"
4139  ""
4140)
4141
4142(define_insn "*movaddr_insn"
4143  [(set (match_operand:SI 0 "s_register_operand" "=r")
4144	(match_operand:DI 1 "address_operand" "p"))]
4145  "TARGET_ARM
4146   && reload_completed
4147   && (GET_CODE (operands[1]) == LABEL_REF
4148       || (GET_CODE (operands[1]) == CONST
4149	   && GET_CODE (XEXP (operands[1], 0)) == PLUS
4150	   && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4151	   && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4152  "adr%?\\t%0, %a1"
4153  [(set_attr "predicable" "yes")]
4154)
4155
4156;; When generating pic, we need to load the symbol offset into a register.
4157;; So that the optimizer does not confuse this with a normal symbol load
4158;; we use an unspec.  The offset will be loaded from a constant pool entry,
4159;; since that is the only type of relocation we can use.
4160
4161;; The rather odd constraints on the following are to force reload to leave
4162;; the insn alone, and to force the minipool generation pass to then move
4163;; the GOT symbol to memory.
4164
4165(define_insn "pic_load_addr_arm"
4166  [(set (match_operand:SI 0 "s_register_operand" "=r")
4167	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4168  "TARGET_ARM && flag_pic"
4169  "ldr%?\\t%0, %1"
4170  [(set_attr "type" "load")
4171   (set (attr "pool_range")     (const_int 4096))
4172   (set (attr "neg_pool_range") (const_int 4084))]
4173)
4174
4175(define_insn "pic_load_addr_thumb"
4176  [(set (match_operand:SI 0 "s_register_operand" "=l")
4177	(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4178  "TARGET_THUMB && flag_pic"
4179  "ldr\\t%0, %1"
4180  [(set_attr "type" "load")
4181   (set (attr "pool_range") (const_int 1024))]
4182)
4183
4184;; This variant is used for AOF assembly, since it needs to mention the
4185;; pic register in the rtl.
4186(define_expand "pic_load_addr_based"
4187  [(set (match_operand:SI 0 "s_register_operand" "=r")
4188	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4189  "TARGET_ARM && flag_pic"
4190  "operands[2] = pic_offset_table_rtx;"
4191)
4192
4193(define_insn "*pic_load_addr_based_insn"
4194  [(set (match_operand:SI 0 "s_register_operand" "=r")
4195	(unspec:SI [(match_operand 1 "" "")
4196		    (match_operand 2 "s_register_operand" "r")]
4197		   UNSPEC_PIC_SYM))]
4198  "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4199  "*
4200#ifdef AOF_ASSEMBLER
4201  operands[1] = aof_pic_entry (operands[1]);
4202#endif
4203  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4204  return \"\";
4205  "
4206  [(set_attr "type" "load")
4207   (set (attr "pool_range")
4208	(if_then_else (eq_attr "is_thumb" "yes")
4209		      (const_int 1024)
4210		      (const_int 4096)))
4211   (set (attr "neg_pool_range")
4212	(if_then_else (eq_attr "is_thumb" "yes")
4213		      (const_int 0)
4214		      (const_int 4084)))]
4215)
4216
4217(define_insn "pic_add_dot_plus_four"
4218  [(set (match_operand:SI 0 "register_operand" "+r")
4219	(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4220   (use (label_ref (match_operand 1 "" "")))]
4221  "TARGET_THUMB && flag_pic"
4222  "*
4223  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4224			     CODE_LABEL_NUMBER (operands[1]));
4225  return \"add\\t%0, %|pc\";
4226  "
4227  [(set_attr "length" "2")]
4228)
4229
4230(define_insn "pic_add_dot_plus_eight"
4231  [(set (match_operand:SI 0 "register_operand" "+r")
4232	(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4233   (use (label_ref (match_operand 1 "" "")))]
4234  "TARGET_ARM && flag_pic"
4235  "*
4236    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4237			       CODE_LABEL_NUMBER (operands[1]));
4238    return \"add%?\\t%0, %|pc, %0\";
4239  "
4240  [(set_attr "predicable" "yes")]
4241)
4242
4243(define_expand "builtin_setjmp_receiver"
4244  [(label_ref (match_operand 0 "" ""))]
4245  "flag_pic"
4246  "
4247{
4248  arm_finalize_pic (0);
4249  DONE;
4250}")
4251
4252;; If copying one reg to another we can set the condition codes according to
4253;; its value.  Such a move is common after a return from subroutine and the
4254;; result is being tested against zero.
4255
4256(define_insn "*movsi_compare0"
4257  [(set (reg:CC CC_REGNUM)
4258	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4259		    (const_int 0)))
4260   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4261	(match_dup 1))]
4262  "TARGET_ARM"
4263  "@
4264   cmp%?\\t%0, #0
4265   sub%?s\\t%0, %1, #0"
4266  [(set_attr "conds" "set")]
4267)
4268
4269;; Subroutine to store a half word from a register into memory.
4270;; Operand 0 is the source register (HImode)
4271;; Operand 1 is the destination address in a register (SImode)
4272
4273;; In both this routine and the next, we must be careful not to spill
4274;; a memory address of reg+large_const into a separate PLUS insn, since this
4275;; can generate unrecognizable rtl.
4276
4277(define_expand "storehi"
4278  [;; store the low byte
4279   (set (match_operand 1 "" "") (match_dup 3))
4280   ;; extract the high byte
4281   (set (match_dup 2)
4282	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4283   ;; store the high byte
4284   (set (match_dup 4) (subreg:QI (match_dup 2) 0))]	;explicit subreg safe
4285  "TARGET_ARM"
4286  "
4287  {
4288    rtx op1 = operands[1];
4289    rtx addr = XEXP (op1, 0);
4290    enum rtx_code code = GET_CODE (addr);
4291
4292    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4293	|| code == MINUS)
4294      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4295
4296    operands[4] = adjust_address (op1, QImode, 1);
4297    operands[1] = adjust_address (operands[1], QImode, 0);
4298    operands[3] = gen_lowpart (QImode, operands[0]);
4299    operands[0] = gen_lowpart (SImode, operands[0]);
4300    operands[2] = gen_reg_rtx (SImode); 
4301  }"
4302)
4303
4304(define_expand "storehi_bigend"
4305  [(set (match_dup 4) (match_dup 3))
4306   (set (match_dup 2)
4307	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4308   (set (match_operand 1 "" "")	(subreg:QI (match_dup 2) 0))]
4309  "TARGET_ARM"
4310  "
4311  {
4312    rtx op1 = operands[1];
4313    rtx addr = XEXP (op1, 0);
4314    enum rtx_code code = GET_CODE (addr);
4315
4316    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4317	|| code == MINUS)
4318      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4319
4320    operands[4] = adjust_address (op1, QImode, 1);
4321    operands[1] = adjust_address (operands[1], QImode, 0);
4322    operands[3] = gen_lowpart (QImode, operands[0]);
4323    operands[0] = gen_lowpart (SImode, operands[0]);
4324    operands[2] = gen_reg_rtx (SImode);
4325  }"
4326)
4327
4328;; Subroutine to store a half word integer constant into memory.
4329(define_expand "storeinthi"
4330  [(set (match_operand 0 "" "")
4331	(subreg:QI (match_operand 1 "" "") 0))
4332   (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4333  "TARGET_ARM"
4334  "
4335  {
4336    HOST_WIDE_INT value = INTVAL (operands[1]);
4337    rtx addr = XEXP (operands[0], 0);
4338    rtx op0 = operands[0];
4339    enum rtx_code code = GET_CODE (addr);
4340
4341    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4342	|| code == MINUS)
4343      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4344
4345    operands[1] = gen_reg_rtx (SImode);
4346    if (BYTES_BIG_ENDIAN)
4347      {
4348	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4349	if ((value & 255) == ((value >> 8) & 255))
4350	  operands[2] = operands[1];
4351	else
4352	  {
4353	    operands[2] = gen_reg_rtx (SImode);
4354	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4355	  }
4356      }
4357    else
4358      {
4359	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4360	if ((value & 255) == ((value >> 8) & 255))
4361	  operands[2] = operands[1];
4362	else
4363	  {
4364	    operands[2] = gen_reg_rtx (SImode);
4365	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4366	  }
4367      }
4368
4369    operands[3] = adjust_address (op0, QImode, 1);
4370    operands[0] = adjust_address (operands[0], QImode, 0);
4371  }"
4372)
4373
4374(define_expand "storehi_single_op"
4375  [(set (match_operand:HI 0 "memory_operand" "")
4376	(match_operand:HI 1 "general_operand" ""))]
4377  "TARGET_ARM && arm_arch4"
4378  "
4379  if (!s_register_operand (operands[1], HImode))
4380    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4381  "
4382)
4383
4384(define_expand "movhi"
4385  [(set (match_operand:HI 0 "general_operand" "")
4386	(match_operand:HI 1 "general_operand" ""))]
4387  "TARGET_EITHER"
4388  "
4389  if (TARGET_ARM)
4390    {
4391      if (!no_new_pseudos)
4392        {
4393          if (GET_CODE (operands[0]) == MEM)
4394	    {
4395	      if (arm_arch4)
4396	        {
4397	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4398	          DONE;
4399	        }
4400	      if (GET_CODE (operands[1]) == CONST_INT)
4401	        emit_insn (gen_storeinthi (operands[0], operands[1]));
4402	      else
4403	        {
4404	          if (GET_CODE (operands[1]) == MEM)
4405		    operands[1] = force_reg (HImode, operands[1]);
4406	          if (BYTES_BIG_ENDIAN)
4407		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4408	          else
4409		   emit_insn (gen_storehi (operands[1], operands[0]));
4410	        }
4411	      DONE;
4412	    }
4413          /* Sign extend a constant, and keep it in an SImode reg.  */
4414          else if (GET_CODE (operands[1]) == CONST_INT)
4415	    {
4416	      rtx reg = gen_reg_rtx (SImode);
4417	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4418
4419	      /* If the constant is already valid, leave it alone.  */
4420	      if (!const_ok_for_arm (val))
4421	        {
4422	          /* If setting all the top bits will make the constant 
4423		     loadable in a single instruction, then set them.  
4424		     Otherwise, sign extend the number.  */
4425
4426	          if (const_ok_for_arm (~(val | ~0xffff)))
4427		    val |= ~0xffff;
4428	          else if (val & 0x8000)
4429		    val |= ~0xffff;
4430	        }
4431
4432	      emit_insn (gen_movsi (reg, GEN_INT (val)));
4433	      operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4434	    }
4435          else if (!arm_arch4)
4436	    {
4437	     /* Note: We do not have to worry about TARGET_MMU_TRAPS
4438	        for v4 and up architectures because LDRH instructions will
4439	        be used to access the HI values, and these cannot generate
4440	        unaligned word access faults in the MMU.  */
4441	      if (GET_CODE (operands[1]) == MEM)
4442	        {
4443	          if (TARGET_MMU_TRAPS)
4444		    {
4445		      rtx base;
4446		      rtx offset = const0_rtx;
4447		      rtx reg = gen_reg_rtx (SImode);
4448
4449		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4450		           || (GET_CODE (base) == PLUS
4451			       && (GET_CODE (offset = XEXP (base, 1))
4452				   == CONST_INT)
4453                               && ((INTVAL(offset) & 1) != 1)
4454			       && GET_CODE (base = XEXP (base, 0)) == REG))
4455		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4456		        {
4457		          HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4458		          rtx new;
4459
4460		          new = gen_rtx_MEM (SImode,
4461				   	     plus_constant (base, new_offset));
4462	                  MEM_COPY_ATTRIBUTES (new, operands[1]);
4463		          emit_insn (gen_movsi (reg, new));
4464		          if (((INTVAL (offset) & 2) != 0)
4465			      ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4466			    {
4467			      rtx reg2 = gen_reg_rtx (SImode);
4468
4469			      emit_insn (gen_lshrsi3 (reg2, reg,
4470					 GEN_INT (16)));
4471			      reg = reg2;
4472			    }
4473		        }
4474		      else
4475		        emit_insn (gen_movhi_bytes (reg, operands[1]));
4476
4477		      operands[1] = gen_lowpart (HImode, reg);
4478		    }
4479	          else if (BYTES_BIG_ENDIAN)
4480		    {
4481		      rtx base;
4482		      rtx offset = const0_rtx;
4483
4484		      if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4485		           || (GET_CODE (base) == PLUS
4486			      && (GET_CODE (offset = XEXP (base, 1))
4487				  == CONST_INT)
4488			      && GET_CODE (base = XEXP (base, 0)) == REG))
4489		          && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4490		        {
4491		          rtx reg = gen_reg_rtx (SImode);
4492		          rtx new;
4493
4494		          if ((INTVAL (offset) & 2) == 2)
4495			    {
4496			      HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4497			      new = gen_rtx_MEM (SImode,
4498				  	         plus_constant (base,
4499								new_offset));
4500                              MEM_COPY_ATTRIBUTES (new, operands[1]);
4501			      emit_insn (gen_movsi (reg, new));
4502			    }
4503		          else
4504			    {
4505			      new = gen_rtx_MEM (SImode,
4506						 XEXP (operands[1], 0));
4507	                      MEM_COPY_ATTRIBUTES (new, operands[1]);
4508			      emit_insn (gen_rotated_loadsi (reg, new));
4509			    }
4510
4511		          operands[1] = gen_lowpart (HImode, reg);
4512		        }
4513		      else
4514		        {
4515		          emit_insn (gen_movhi_bigend (operands[0],
4516						       operands[1]));
4517		          DONE;
4518		        }
4519		    }
4520	       }
4521	   }
4522        }
4523      /* Handle loading a large integer during reload */
4524      else if (GET_CODE (operands[1]) == CONST_INT
4525	       && !const_ok_for_arm (INTVAL (operands[1]))
4526	       && !const_ok_for_arm (~INTVAL (operands[1])))
4527        {
4528          /* Writing a constant to memory needs a scratch, which should
4529	     be handled with SECONDARY_RELOADs.  */
4530          if (GET_CODE (operands[0]) != REG)
4531	    abort ();
4532
4533          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4534          emit_insn (gen_movsi (operands[0], operands[1]));
4535          DONE;
4536       }
4537    }
4538  else /* TARGET_THUMB */
4539    {
4540      if (!no_new_pseudos)
4541        {
4542          if (GET_CODE (operands[0]) != REG)
4543	    operands[1] = force_reg (HImode, operands[1]);
4544
4545          /* ??? We shouldn't really get invalid addresses here, but this can
4546	     happen if we are passed a SP (never OK for HImode/QImode) or 
4547	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4548	     HImode/QImode) relative address.  */
4549          /* ??? This should perhaps be fixed elsewhere, for instance, in
4550	     fixup_stack_1, by checking for other kinds of invalid addresses,
4551	     e.g. a bare reference to a virtual register.  This may confuse the
4552	     alpha though, which must handle this case differently.  */
4553          if (GET_CODE (operands[0]) == MEM
4554	      && !memory_address_p (GET_MODE (operands[0]),
4555				    XEXP (operands[0], 0)))
4556	    operands[0]
4557	      = replace_equiv_address (operands[0],
4558				       copy_to_reg (XEXP (operands[0], 0)));
4559   
4560          if (GET_CODE (operands[1]) == MEM
4561	      && !memory_address_p (GET_MODE (operands[1]),
4562				    XEXP (operands[1], 0)))
4563	    operands[1]
4564	      = replace_equiv_address (operands[1],
4565				       copy_to_reg (XEXP (operands[1], 0)));
4566        }
4567      /* Handle loading a large integer during reload */
4568      else if (GET_CODE (operands[1]) == CONST_INT
4569	        && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4570        {
4571          /* Writing a constant to memory needs a scratch, which should
4572	     be handled with SECONDARY_RELOADs.  */
4573          if (GET_CODE (operands[0]) != REG)
4574	    abort ();
4575
4576          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4577          emit_insn (gen_movsi (operands[0], operands[1]));
4578          DONE;
4579        }
4580    }
4581  "
4582)
4583
4584(define_insn "*thumb_movhi_insn"
4585  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4586	(match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4587  "TARGET_THUMB
4588   && (   register_operand (operands[0], HImode)
4589       || register_operand (operands[1], HImode))"
4590  "*
4591  switch (which_alternative)
4592    {
4593    case 0: return \"add	%0, %1, #0\";
4594    case 2: return \"strh	%1, %0\";
4595    case 3: return \"mov	%0, %1\";
4596    case 4: return \"mov	%0, %1\";
4597    case 5: return \"mov	%0, %1\";
4598    default: abort ();
4599    case 1:
4600      /* The stack pointer can end up being taken as an index register.
4601          Catch this case here and deal with it.  */
4602      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4603	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4604	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4605        {
4606	  rtx ops[2];
4607          ops[0] = operands[0];
4608          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4609      
4610          output_asm_insn (\"mov	%0, %1\", ops);
4611
4612          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4613    
4614	}
4615      return \"ldrh	%0, %1\";
4616    }"
4617  [(set_attr "length" "2,4,2,2,2,2")
4618   (set_attr "type" "*,load,store1,*,*,*")
4619   (set_attr "pool_range" "*,64,*,*,*,*")]
4620)
4621
4622
4623(define_insn "rotated_loadsi"
4624  [(set (match_operand:SI            0 "s_register_operand"        "=r")
4625	(rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4626		   (const_int 16)))]
4627  "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4628  "*
4629  {
4630    rtx ops[2];
4631
4632    ops[0] = operands[0];
4633    ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4634    output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4635    return \"\";
4636  }"
4637  [(set_attr "type" "load")
4638   (set_attr "predicable" "yes")]
4639)
4640
4641(define_expand "movhi_bytes"
4642  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4643   (set (match_dup 3)
4644	(zero_extend:SI (match_dup 6)))
4645   (set (match_operand:SI 0 "" "")
4646	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4647  "TARGET_ARM"
4648  "
4649  {
4650    rtx mem1, mem2;
4651    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4652
4653    mem1 = gen_rtx_MEM (QImode, addr);
4654    MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4655    mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4656    MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4657    operands[0] = gen_lowpart (SImode, operands[0]);
4658    operands[1] = mem1;
4659    operands[2] = gen_reg_rtx (SImode);
4660    operands[3] = gen_reg_rtx (SImode);
4661    operands[6] = mem2;
4662
4663    if (BYTES_BIG_ENDIAN)
4664      {
4665	operands[4] = operands[2];
4666	operands[5] = operands[3];
4667      }
4668    else
4669      {
4670	operands[4] = operands[3];
4671	operands[5] = operands[2];
4672      }
4673  }"
4674)
4675
4676(define_expand "movhi_bigend"
4677  [(set (match_dup 2)
4678	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4679		   (const_int 16)))
4680   (set (match_dup 3)
4681	(ashiftrt:SI (match_dup 2) (const_int 16)))
4682   (set (match_operand:HI 0 "s_register_operand" "")
4683	(subreg:HI (match_dup 3) 0))]
4684  "TARGET_ARM"
4685  "
4686  operands[2] = gen_reg_rtx (SImode);
4687  operands[3] = gen_reg_rtx (SImode);
4688  "
4689)
4690
4691;; Pattern to recognise insn generated default case above
4692(define_insn "*movhi_insn_arch4"
4693  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4694	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4695  "TARGET_ARM
4696   && arm_arch4
4697   && (GET_CODE (operands[1]) != CONST_INT
4698       || const_ok_for_arm (INTVAL (operands[1]))
4699       || const_ok_for_arm (~INTVAL (operands[1])))"
4700  "@
4701   mov%?\\t%0, %1\\t%@ movhi
4702   mvn%?\\t%0, #%B1\\t%@ movhi
4703   str%?h\\t%1, %0\\t%@ movhi 
4704   ldr%?h\\t%0, %1\\t%@ movhi"
4705  [(set_attr "type" "*,*,store1,load")
4706   (set_attr "predicable" "yes")
4707   (set_attr "pool_range" "*,*,*,256")
4708   (set_attr "neg_pool_range" "*,*,*,244")]
4709)
4710
4711(define_insn "*movhi_insn_littleend"
4712  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4713	(match_operand:HI 1 "general_operand"  "rI,K,m"))]
4714  "TARGET_ARM
4715   && !arm_arch4
4716   && !BYTES_BIG_ENDIAN
4717   && !TARGET_MMU_TRAPS
4718   && (GET_CODE (operands[1]) != CONST_INT
4719       || const_ok_for_arm (INTVAL (operands[1]))
4720       || const_ok_for_arm (~INTVAL (operands[1])))"
4721  "@
4722   mov%?\\t%0, %1\\t%@ movhi
4723   mvn%?\\t%0, #%B1\\t%@ movhi
4724   ldr%?\\t%0, %1\\t%@ movhi"
4725  [(set_attr "type" "*,*,load")
4726   (set_attr "predicable" "yes")
4727   (set_attr "pool_range" "4096")
4728   (set_attr "neg_pool_range" "4084")]
4729)
4730
4731(define_insn "*movhi_insn_bigend"
4732  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4733	(match_operand:HI 1 "general_operand"    "rI,K,m"))]
4734  "TARGET_ARM
4735   && !arm_arch4
4736   && BYTES_BIG_ENDIAN
4737   && !TARGET_MMU_TRAPS
4738   && (GET_CODE (operands[1]) != CONST_INT
4739       || const_ok_for_arm (INTVAL (operands[1]))
4740       || const_ok_for_arm (~INTVAL (operands[1])))"
4741  "@
4742   mov%?\\t%0, %1\\t%@ movhi
4743   mvn%?\\t%0, #%B1\\t%@ movhi
4744   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4745  [(set_attr "type" "*,*,load")
4746   (set_attr "predicable" "yes")
4747   (set_attr "length" "4,4,8")
4748   (set_attr "pool_range" "*,*,4092")
4749   (set_attr "neg_pool_range" "*,*,4084")]
4750)
4751
4752(define_insn "*loadhi_si_bigend"
4753  [(set (match_operand:SI                       0 "s_register_operand" "=r")
4754	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4755		   (const_int 16)))]
4756  "TARGET_ARM
4757   && BYTES_BIG_ENDIAN
4758   && !TARGET_MMU_TRAPS"
4759  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4760  [(set_attr "type" "load")
4761   (set_attr "predicable" "yes")
4762   (set_attr "pool_range" "4096")
4763   (set_attr "neg_pool_range" "4084")]
4764)
4765
4766(define_insn "*movhi_bytes"
4767  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4768	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4769  "TARGET_ARM && TARGET_MMU_TRAPS"
4770  "@
4771   mov%?\\t%0, %1\\t%@ movhi
4772   mvn%?\\t%0, #%B1\\t%@ movhi"
4773  [(set_attr "predicable" "yes")]
4774)
4775
4776(define_insn "thumb_movhi_clobber"
4777  [(set (match_operand:HI     0 "memory_operand"   "=m")
4778	(match_operand:HI     1 "register_operand" "l"))
4779   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4780  "TARGET_THUMB"
4781  "*
4782  abort ();"
4783)
4784	
4785;; We use a DImode scratch because we may occasionally need an additional
4786;; temporary if the address isn't offsettable -- push_reload doesn't seem
4787;; to take any notice of the "o" constraints on reload_memory_operand operand.
4788(define_expand "reload_outhi"
4789  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4790	      (match_operand:HI 1 "s_register_operand"        "r")
4791	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
4792  "TARGET_EITHER"
4793  "if (TARGET_ARM)
4794     arm_reload_out_hi (operands);
4795   else
4796     thumb_reload_out_hi (operands);
4797  DONE;
4798  "
4799)
4800
4801(define_expand "reload_inhi"
4802  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4803	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
4804	      (match_operand:DI 2 "s_register_operand" "=&r")])]
4805  "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4806  "
4807  if (TARGET_ARM)
4808    arm_reload_in_hi (operands);
4809  else
4810    thumb_reload_out_hi (operands);
4811  DONE;
4812")
4813
4814(define_expand "movqi"
4815  [(set (match_operand:QI 0 "general_operand" "")
4816        (match_operand:QI 1 "general_operand" ""))]
4817  "TARGET_EITHER"
4818  "
4819  if (TARGET_ARM)
4820    {
4821      /* Everything except mem = const or mem = mem can be done easily */
4822
4823      if (!no_new_pseudos)
4824        {
4825          if (GET_CODE (operands[1]) == CONST_INT)
4826	    {
4827	      rtx reg = gen_reg_rtx (SImode);
4828
4829	      emit_insn (gen_movsi (reg, operands[1]));
4830	      operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4831	    }
4832         if (GET_CODE (operands[0]) == MEM)
4833	   operands[1] = force_reg (QImode, operands[1]);
4834       }
4835    }
4836  else /* TARGET_THUMB */
4837    {
4838      if (!no_new_pseudos)
4839        {
4840          if (GET_CODE (operands[0]) != REG)
4841	    operands[1] = force_reg (QImode, operands[1]);
4842
4843          /* ??? We shouldn't really get invalid addresses here, but this can
4844	     happen if we are passed a SP (never OK for HImode/QImode) or
4845	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4846	     HImode/QImode) relative address.  */
4847          /* ??? This should perhaps be fixed elsewhere, for instance, in
4848	     fixup_stack_1, by checking for other kinds of invalid addresses,
4849	     e.g. a bare reference to a virtual register.  This may confuse the
4850	     alpha though, which must handle this case differently.  */
4851          if (GET_CODE (operands[0]) == MEM
4852	      && !memory_address_p (GET_MODE (operands[0]),
4853		  		     XEXP (operands[0], 0)))
4854	    operands[0]
4855	      = replace_equiv_address (operands[0],
4856				       copy_to_reg (XEXP (operands[0], 0)));
4857          if (GET_CODE (operands[1]) == MEM
4858	      && !memory_address_p (GET_MODE (operands[1]),
4859				    XEXP (operands[1], 0)))
4860	     operands[1]
4861	       = replace_equiv_address (operands[1],
4862					copy_to_reg (XEXP (operands[1], 0)));
4863        }
4864      /* Handle loading a large integer during reload */
4865      else if (GET_CODE (operands[1]) == CONST_INT
4866	       && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4867        {
4868          /* Writing a constant to memory needs a scratch, which should
4869	     be handled with SECONDARY_RELOADs.  */
4870          if (GET_CODE (operands[0]) != REG)
4871	    abort ();
4872
4873          operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4874          emit_insn (gen_movsi (operands[0], operands[1]));
4875          DONE;
4876       }
4877    }
4878  "
4879)
4880
4881
4882(define_insn "*arm_movqi_insn"
4883  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4884	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4885  "TARGET_ARM
4886   && (   register_operand (operands[0], QImode)
4887       || register_operand (operands[1], QImode))"
4888  "@
4889   mov%?\\t%0, %1
4890   mvn%?\\t%0, #%B1
4891   ldr%?b\\t%0, %1
4892   str%?b\\t%1, %0"
4893  [(set_attr "type" "*,*,load,store1")
4894   (set_attr "predicable" "yes")]
4895)
4896
4897(define_insn "*thumb_movqi_insn"
4898  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4899	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4900  "TARGET_THUMB
4901   && (   register_operand (operands[0], QImode)
4902       || register_operand (operands[1], QImode))"
4903  "@
4904   add\\t%0, %1, #0
4905   ldrb\\t%0, %1
4906   strb\\t%1, %0
4907   mov\\t%0, %1
4908   mov\\t%0, %1
4909   mov\\t%0, %1"
4910  [(set_attr "length" "2")
4911   (set_attr "type" "*,load,store1,*,*,*")
4912   (set_attr "pool_range" "*,32,*,*,*,*")]
4913)
4914
4915(define_expand "movsf"
4916  [(set (match_operand:SF 0 "general_operand" "")
4917	(match_operand:SF 1 "general_operand" ""))]
4918  "TARGET_EITHER"
4919  "
4920  if (TARGET_ARM)
4921    {
4922      if (GET_CODE (operands[0]) == MEM)
4923        operands[1] = force_reg (SFmode, operands[1]);
4924    }
4925  else /* TARGET_THUMB */
4926    {
4927      if (!no_new_pseudos)
4928        {
4929           if (GET_CODE (operands[0]) != REG)
4930	     operands[1] = force_reg (SFmode, operands[1]);
4931        }
4932    }
4933  "
4934)
4935
4936(define_split
4937  [(set (match_operand:SF 0 "nonimmediate_operand" "")
4938	(match_operand:SF 1 "immediate_operand" ""))]
4939  "TARGET_ARM
4940   && !TARGET_HARD_FLOAT
4941   && reload_completed
4942   && GET_CODE (operands[1]) == CONST_DOUBLE"
4943  [(set (match_dup 2) (match_dup 3))]
4944  "
4945  operands[2] = gen_lowpart (SImode, operands[0]);
4946  operands[3] = gen_lowpart (SImode, operands[1]);
4947  if (operands[2] == 0 || operands[3] == 0)
4948    FAIL;
4949  "
4950)
4951
4952(define_insn "*arm_movsf_hard_insn"
4953  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4954	(match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4955  "TARGET_ARM
4956   && TARGET_HARD_FLOAT
4957   && (GET_CODE (operands[0]) != MEM
4958       || register_operand (operands[1], SFmode))"
4959  "@
4960   mvf%?s\\t%0, %1
4961   mnf%?s\\t%0, #%N1
4962   ldf%?s\\t%0, %1
4963   stf%?s\\t%1, %0
4964   str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4965   stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4966   mov%?\\t%0, %1
4967   ldr%?\\t%0, %1\\t%@ float
4968   str%?\\t%1, %0\\t%@ float"
4969  [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4970   (set_attr "predicable" "yes")
4971   (set_attr "type"
4972	 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4973   (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4974   (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4975)
4976
4977;; Exactly the same as above, except that all `f' cases are deleted.
4978;; This is necessary to prevent reload from ever trying to use a `f' reg
4979;; when -msoft-float.
4980
4981(define_insn "*arm_movsf_soft_insn"
4982  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4983	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
4984  "TARGET_ARM
4985   && TARGET_SOFT_FLOAT
4986   && (GET_CODE (operands[0]) != MEM
4987       || register_operand (operands[1], SFmode))"
4988  "@
4989   mov%?\\t%0, %1
4990   ldr%?\\t%0, %1\\t%@ float
4991   str%?\\t%1, %0\\t%@ float"
4992  [(set_attr "length" "4,4,4")
4993   (set_attr "predicable" "yes")
4994   (set_attr "type" "*,load,store1")
4995   (set_attr "pool_range" "*,4096,*")
4996   (set_attr "neg_pool_range" "*,4084,*")]
4997)
4998
4999;;; ??? This should have alternatives for constants.
5000(define_insn "*thumb_movsf_insn"
5001  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5002	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5003  "TARGET_THUMB
5004   && (   register_operand (operands[0], SFmode) 
5005       || register_operand (operands[1], SFmode))"
5006  "@
5007   add\\t%0, %1, #0
5008   ldmia\\t%1, {%0}
5009   stmia\\t%0, {%1}
5010   ldr\\t%0, %1
5011   str\\t%1, %0
5012   mov\\t%0, %1
5013   mov\\t%0, %1"
5014  [(set_attr "length" "2")
5015   (set_attr "type" "*,load,store1,load,store1,*,*")
5016   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5017)
5018
5019(define_expand "movdf"
5020  [(set (match_operand:DF 0 "general_operand" "")
5021	(match_operand:DF 1 "general_operand" ""))]
5022  "TARGET_EITHER"
5023  "
5024  if (TARGET_ARM)
5025    {
5026      if (GET_CODE (operands[0]) == MEM)
5027        operands[1] = force_reg (DFmode, operands[1]);
5028    }
5029  else /* TARGET_THUMB */
5030    {
5031      if (!no_new_pseudos)
5032        {
5033          if (GET_CODE (operands[0]) != REG)
5034	    operands[1] = force_reg (DFmode, operands[1]);
5035        }
5036    }
5037  "
5038)
5039
5040;; Reloading a df mode value stored in integer regs to memory can require a
5041;; scratch reg.
5042(define_expand "reload_outdf"
5043  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5044   (match_operand:DF 1 "s_register_operand" "r")
5045   (match_operand:SI 2 "s_register_operand" "=&r")]
5046  "TARGET_ARM"
5047  "
5048  {
5049    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5050
5051    if (code == REG)
5052      operands[2] = XEXP (operands[0], 0);
5053    else if (code == POST_INC || code == PRE_DEC)
5054      {
5055	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5056	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5057	emit_insn (gen_movdi (operands[0], operands[1]));
5058	DONE;
5059      }
5060    else if (code == PRE_INC)
5061      {
5062	rtx reg = XEXP (XEXP (operands[0], 0), 0);
5063
5064	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5065	operands[2] = reg;
5066      }
5067    else if (code == POST_DEC)
5068      operands[2] = XEXP (XEXP (operands[0], 0), 0);
5069    else
5070      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5071			     XEXP (XEXP (operands[0], 0), 1)));
5072
5073    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5074			    operands[1]));
5075
5076    if (code == POST_DEC)
5077      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5078
5079    DONE;
5080  }"
5081)
5082
5083(define_insn "*movdf_hard_insn"
5084  [(set (match_operand:DF 0 "nonimmediate_operand"
5085						"=r,Q,r,m,r, f, f,f, m,!f,!r")
5086	(match_operand:DF 1 "general_operand"
5087						"Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5088  "TARGET_ARM
5089   && TARGET_HARD_FLOAT
5090   && (GET_CODE (operands[0]) != MEM
5091       || register_operand (operands[1], DFmode))"
5092  "*
5093  {
5094  switch (which_alternative)
5095    {
5096    default:
5097    case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5098    case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5099    case 2: case 3: case 4: return output_move_double (operands);
5100    case 5: return \"mvf%?d\\t%0, %1\";
5101    case 6: return \"mnf%?d\\t%0, #%N1\";
5102    case 7: return \"ldf%?d\\t%0, %1\";
5103    case 8: return \"stf%?d\\t%1, %0\";
5104    case 9: return output_mov_double_fpu_from_arm (operands);
5105    case 10: return output_mov_double_arm_from_fpu (operands);
5106    }
5107  }
5108  "
5109  [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5110   (set_attr "predicable" "yes")
5111   (set_attr "type"
5112    "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5113   (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5114   (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5115)
5116
5117;; Software floating point version.  This is essentially the same as movdi.
5118;; Do not use `f' as a constraint to prevent reload from ever trying to use
5119;; an `f' reg.
5120
5121(define_insn "*movdf_soft_insn"
5122  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5123	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5124  "TARGET_ARM && TARGET_SOFT_FLOAT
5125  "
5126  "* return output_move_double (operands);"
5127  [(set_attr "length" "8,8,8")
5128   (set_attr "type" "*,load,store2")
5129   (set_attr "pool_range" "252")
5130   (set_attr "neg_pool_range" "244")]
5131)
5132
5133;;; ??? This should have alternatives for constants.
5134;;; ??? This was originally identical to the movdi_insn pattern.
5135;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5136;;; thumb_reorg with a memory reference.
5137(define_insn "*thumb_movdf_insn"
5138  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5139	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5140  "TARGET_THUMB
5141   && (   register_operand (operands[0], DFmode)
5142       || register_operand (operands[1], DFmode))"
5143  "*
5144  switch (which_alternative)
5145    {
5146    default:
5147    case 0:
5148      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5150      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5151    case 1:
5152      return \"ldmia\\t%1, {%0, %H0}\";
5153    case 2:
5154      return \"stmia\\t%0, {%1, %H1}\";
5155    case 3:
5156      return thumb_load_double_from_address (operands);
5157    case 4:
5158      operands[2] = gen_rtx (MEM, SImode,
5159			     plus_constant (XEXP (operands[0], 0), 4));
5160      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5161      return \"\";
5162    case 5:
5163      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5164	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5165      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5166    }
5167  "
5168  [(set_attr "length" "4,2,2,6,4,4")
5169   (set_attr "type" "*,load,store2,load,store2,*")
5170   (set_attr "pool_range" "*,*,*,1020,*,*")]
5171)
5172
5173
5174(define_expand "movxf"
5175  [(set (match_operand:XF 0 "general_operand" "")
5176	(match_operand:XF 1 "general_operand" ""))]
5177  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5178  "")
5179
5180;; Even when the XFmode patterns aren't enabled, we enable this after
5181;; reloading so that we can push floating point registers in the prologue.
5182
5183(define_insn "*movxf_hard_insn"
5184  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5185	(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5186  "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5187  "*
5188  switch (which_alternative)
5189    {
5190    default:
5191    case 0: return \"mvf%?e\\t%0, %1\";
5192    case 1: return \"mnf%?e\\t%0, #%N1\";
5193    case 2: return \"ldf%?e\\t%0, %1\";
5194    case 3: return \"stf%?e\\t%1, %0\";
5195    case 4: return output_mov_long_double_fpu_from_arm (operands);
5196    case 5: return output_mov_long_double_arm_from_fpu (operands);
5197    case 6: return output_mov_long_double_arm_from_arm (operands);
5198    }
5199  "
5200  [(set_attr "length" "4,4,4,4,8,8,12")
5201   (set_attr "predicable" "yes")
5202   (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5203   (set_attr "pool_range" "*,*,1024,*,*,*,*")
5204   (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5205)
5206
5207
5208;; load- and store-multiple insns
5209;; The arm can load/store any set of registers, provided that they are in
5210;; ascending order; but that is beyond GCC so stick with what it knows.
5211
5212(define_expand "load_multiple"
5213  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5214                          (match_operand:SI 1 "" ""))
5215                     (use (match_operand:SI 2 "" ""))])]
5216  "TARGET_ARM"
5217  "
5218  /* Support only fixed point registers.  */
5219  if (GET_CODE (operands[2]) != CONST_INT
5220      || INTVAL (operands[2]) > 14
5221      || INTVAL (operands[2]) < 2
5222      || GET_CODE (operands[1]) != MEM
5223      || GET_CODE (operands[0]) != REG
5224      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5225      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5226    FAIL;
5227
5228  operands[3]
5229    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5230			     force_reg (SImode, XEXP (operands[1], 0)),
5231			     TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5232			     MEM_IN_STRUCT_P(operands[1]),
5233	                     MEM_SCALAR_P (operands[1]));
5234  "
5235)
5236
5237;; Load multiple with write-back
5238
5239(define_insn "*ldmsi_postinc4"
5240  [(match_parallel 0 "load_multiple_operation"
5241    [(set (match_operand:SI 1 "s_register_operand" "=r")
5242	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5243		   (const_int 16)))
5244     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5245	  (mem:SI (match_dup 2)))
5246     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5247	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5248     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5249	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5250     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5251	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5252  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5253  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5254  [(set_attr "type" "load")
5255   (set_attr "predicable" "yes")]
5256)
5257
5258(define_insn "*ldmsi_postinc3"
5259  [(match_parallel 0 "load_multiple_operation"
5260    [(set (match_operand:SI 1 "s_register_operand" "=r")
5261	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5262		   (const_int 12)))
5263     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264	  (mem:SI (match_dup 2)))
5265     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5267     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5268	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5269  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5270  "ldm%?ia\\t%1!, {%3, %4, %5}"
5271  [(set_attr "type" "load")
5272   (set_attr "predicable" "yes")]
5273)
5274
5275(define_insn "*ldmsi_postinc2"
5276  [(match_parallel 0 "load_multiple_operation"
5277    [(set (match_operand:SI 1 "s_register_operand" "=r")
5278	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5279		   (const_int 8)))
5280     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281	  (mem:SI (match_dup 2)))
5282     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5284  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5285  "ldm%?ia\\t%1!, {%3, %4}"
5286  [(set_attr "type" "load")
5287   (set_attr "predicable" "yes")]
5288)
5289
5290;; Ordinary load multiple
5291
5292(define_insn "*ldmsi4"
5293  [(match_parallel 0 "load_multiple_operation"
5294    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5295	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5296     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5298     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5300     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5302  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5304  [(set_attr "type" "load")
5305   (set_attr "predicable" "yes")]
5306)
5307
5308(define_insn "*ldmsi3"
5309  [(match_parallel 0 "load_multiple_operation"
5310    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5311	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5312     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5313	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5314     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5315	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5316  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5317  "ldm%?ia\\t%1, {%2, %3, %4}"
5318  [(set_attr "type" "load")
5319   (set_attr "predicable" "yes")]
5320)
5321
5322(define_insn "*ldmsi2"
5323  [(match_parallel 0 "load_multiple_operation"
5324    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5328  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5329  "ldm%?ia\\t%1, {%2, %3}"
5330  [(set_attr "type" "load")
5331   (set_attr "predicable" "yes")]
5332)
5333
5334(define_expand "store_multiple"
5335  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5336                          (match_operand:SI 1 "" ""))
5337                     (use (match_operand:SI 2 "" ""))])]
5338  "TARGET_ARM"
5339  "
5340  /* Support only fixed point registers */
5341  if (GET_CODE (operands[2]) != CONST_INT
5342      || INTVAL (operands[2]) > 14
5343      || INTVAL (operands[2]) < 2
5344      || GET_CODE (operands[1]) != REG
5345      || GET_CODE (operands[0]) != MEM
5346      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5347      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5348    FAIL;
5349
5350  operands[3]
5351    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5352			      force_reg (SImode, XEXP (operands[0], 0)),
5353			      TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5354			      MEM_IN_STRUCT_P(operands[0]), 
5355	                      MEM_SCALAR_P (operands[0]));
5356  "
5357)
5358
5359;; Store multiple with write-back
5360
5361(define_insn "*stmsi_postinc4"
5362  [(match_parallel 0 "store_multiple_operation"
5363    [(set (match_operand:SI 1 "s_register_operand" "=r")
5364	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5365		   (const_int 16)))
5366     (set (mem:SI (match_dup 2))
5367	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5368     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5369	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5370     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5371	  (match_operand:SI 5 "arm_hard_register_operand" ""))
5372     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5373	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5374  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5375  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5376  [(set_attr "predicable" "yes")
5377   (set_attr "type" "store4")]
5378)
5379
5380(define_insn "*stmsi_postinc3"
5381  [(match_parallel 0 "store_multiple_operation"
5382    [(set (match_operand:SI 1 "s_register_operand" "=r")
5383	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5384		   (const_int 12)))
5385     (set (mem:SI (match_dup 2))
5386	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5387     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5389     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5390	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5391  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5392  "stm%?ia\\t%1!, {%3, %4, %5}"
5393  [(set_attr "predicable" "yes")
5394   (set_attr "type" "store3")]
5395)
5396
5397(define_insn "*stmsi_postinc2"
5398  [(match_parallel 0 "store_multiple_operation"
5399    [(set (match_operand:SI 1 "s_register_operand" "=r")
5400	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401		   (const_int 8)))
5402     (set (mem:SI (match_dup 2))
5403	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5404     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5406  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5407  "stm%?ia\\t%1!, {%3, %4}"
5408  [(set_attr "predicable" "yes")
5409   (set_attr "type" "store2")]
5410)
5411
5412;; Ordinary store multiple
5413
5414(define_insn "*stmsi4"
5415  [(match_parallel 0 "store_multiple_operation"
5416    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5417	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5418     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5419	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5420     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5421	  (match_operand:SI 4 "arm_hard_register_operand" ""))
5422     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5423	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5424  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5425  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5426  [(set_attr "predicable" "yes")
5427   (set_attr "type" "store4")]
5428)
5429
5430(define_insn "*stmsi3"
5431  [(match_parallel 0 "store_multiple_operation"
5432    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5433	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5434     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5435	  (match_operand:SI 3 "arm_hard_register_operand" ""))
5436     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5437	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439  "stm%?ia\\t%1, {%2, %3, %4}"
5440  [(set_attr "predicable" "yes")
5441   (set_attr "type" "store3")]
5442)
5443
5444(define_insn "*stmsi2"
5445  [(match_parallel 0 "store_multiple_operation"
5446    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447	  (match_operand:SI 2 "arm_hard_register_operand" ""))
5448     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5450  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5451  "stm%?ia\\t%1, {%2, %3}"
5452  [(set_attr "predicable" "yes")
5453   (set_attr "type" "store2")]
5454)
5455
5456;; Move a block of memory if it is word aligned and MORE than 2 words long.
5457;; We could let this apply for blocks of less than this, but it clobbers so
5458;; many registers that there is then probably a better way.
5459
5460(define_expand "movstrqi"
5461  [(match_operand:BLK 0 "general_operand" "")
5462   (match_operand:BLK 1 "general_operand" "")
5463   (match_operand:SI 2 "const_int_operand" "")
5464   (match_operand:SI 3 "const_int_operand" "")]
5465  "TARGET_EITHER"
5466  "
5467  if (TARGET_ARM)
5468    {
5469      if (arm_gen_movstrqi (operands))
5470        DONE;
5471      FAIL;
5472    }
5473  else /* TARGET_THUMB */
5474    {
5475      if (   INTVAL (operands[3]) != 4
5476          || INTVAL (operands[2]) > 48)
5477        FAIL;
5478
5479      thumb_expand_movstrqi (operands);
5480      DONE;
5481    }
5482  "
5483)
5484
5485;; Thumb block-move insns
5486
5487(define_insn "movmem12b"
5488  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5489	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5490   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5491	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5492   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5493	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
5494   (set (match_operand:SI 0 "register_operand" "=l")
5495	(plus:SI (match_dup 2) (const_int 12)))
5496   (set (match_operand:SI 1 "register_operand" "=l")
5497	(plus:SI (match_dup 3) (const_int 12)))
5498   (clobber (match_scratch:SI 4 "=&l"))
5499   (clobber (match_scratch:SI 5 "=&l"))
5500   (clobber (match_scratch:SI 6 "=&l"))]
5501  "TARGET_THUMB"
5502  "* return thumb_output_move_mem_multiple (3, operands);"
5503  [(set_attr "length" "4")
5504   ; This isn't entirely accurate...  It loads as well, but in terms of
5505   ; scheduling the following insn it is better to consider it as a store
5506   (set_attr "type" "store3")]
5507)
5508
5509(define_insn "movmem8b"
5510  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5511	(mem:SI (match_operand:SI 3 "register_operand" "1")))
5512   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5513	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
5514   (set (match_operand:SI 0 "register_operand" "=l")
5515	(plus:SI (match_dup 2) (const_int 8)))
5516   (set (match_operand:SI 1 "register_operand" "=l")
5517	(plus:SI (match_dup 3) (const_int 8)))
5518   (clobber (match_scratch:SI 4 "=&l"))
5519   (clobber (match_scratch:SI 5 "=&l"))]
5520  "TARGET_THUMB"
5521  "* return thumb_output_move_mem_multiple (2, operands);"
5522  [(set_attr "length" "4")
5523   ; This isn't entirely accurate...  It loads as well, but in terms of
5524   ; scheduling the following insn it is better to consider it as a store
5525   (set_attr "type" "store2")]
5526)
5527
5528
5529
5530;; Compare & branch insns
5531;; The range calcualations are based as follows:
5532;; For forward branches, the address calculation returns the address of
5533;; the next instruction.  This is 2 beyond the branch instruction.
5534;; For backward branches, the address calculation returns the address of
5535;; the first instruction in this pattern (cmp).  This is 2 before the branch
5536;; instruction for the shortest sequence, and 4 before the branch instruction
5537;; if we have to jump around an unconditional branch.
5538;; To the basic branch range the PC offset must be added (this is +4).
5539;; So for forward branches we have 
5540;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5541;; And for backward branches we have 
5542;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5543;;
5544;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5545;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5546
5547(define_insn "cbranchsi4"
5548  [(set (pc)
5549	(if_then_else
5550	    (match_operator                    0 "arm_comparison_operator"
5551	                    [(match_operand:SI 1 "register_operand"   "l,r")
5552			     (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5553	    (label_ref       (match_operand    3 "" ""))
5554	    (pc)))]
5555  "TARGET_THUMB"
5556  "*
5557  output_asm_insn (\"cmp\\t%1, %2\", operands);
5558  switch (get_attr_length (insn))
5559    {
5560    case 4:  return \"b%d0\\t%l3\";
5561    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5562    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5563    }
5564  "
5565  [(set (attr "far_jump")
5566        (if_then_else
5567	    (eq_attr "length" "8")
5568	    (const_string "yes")
5569            (const_string "no")))
5570   (set (attr "length") 
5571        (if_then_else
5572	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5573	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5574	    (const_int 4)
5575	    (if_then_else
5576	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5577		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5578		(const_int 6)
5579		(const_int 8))))]
5580)
5581
5582(define_insn "*negated_cbranchsi4"
5583  [(set (pc)
5584	(if_then_else
5585	 (match_operator             0 "arm_comparison_operator"
5586	  [(match_operand:SI         1 "register_operand"  "l")
5587	   (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5588	 (label_ref (match_operand   3 "" ""))
5589	 (pc)))]
5590  "TARGET_THUMB"
5591  "*
5592  output_asm_insn (\"cmn\\t%1, %2\", operands);
5593  switch (get_attr_length (insn))
5594    {
5595    case 4:  return \"b%d0\\t%l3\";
5596    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5597    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5598    }
5599  "
5600  [(set (attr "far_jump")
5601        (if_then_else
5602	    (eq_attr "length" "8")
5603	    (const_string "yes")
5604            (const_string "no")))
5605   (set (attr "length") 
5606        (if_then_else
5607	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5608	         (le (minus (match_dup 3) (pc)) (const_int 256)))
5609	    (const_int 4)
5610	    (if_then_else
5611	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5612		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5613		(const_int 6)
5614		(const_int 8))))]
5615)
5616
5617
5618;; Comparison and test insns
5619
5620(define_expand "cmpsi"
5621  [(match_operand:SI 0 "s_register_operand" "")
5622   (match_operand:SI 1 "arm_add_operand" "")]
5623  "TARGET_ARM"
5624  "{
5625    arm_compare_op0 = operands[0];
5626    arm_compare_op1 = operands[1];
5627    DONE;
5628  }"
5629)
5630
5631(define_expand "cmpsf"
5632  [(match_operand:SF 0 "s_register_operand" "")
5633   (match_operand:SF 1 "fpu_rhs_operand" "")]
5634  "TARGET_ARM && TARGET_HARD_FLOAT"
5635  "
5636  arm_compare_op0 = operands[0];
5637  arm_compare_op1 = operands[1];
5638  DONE;
5639  "
5640)
5641
5642(define_expand "cmpdf"
5643  [(match_operand:DF 0 "s_register_operand" "")
5644   (match_operand:DF 1 "fpu_rhs_operand" "")]
5645  "TARGET_ARM && TARGET_HARD_FLOAT"
5646  "
5647  arm_compare_op0 = operands[0];
5648  arm_compare_op1 = operands[1];
5649  DONE;
5650  "
5651)
5652
5653(define_expand "cmpxf"
5654  [(match_operand:XF 0 "s_register_operand" "")
5655   (match_operand:XF 1 "fpu_rhs_operand" "")]
5656  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5657  "
5658  arm_compare_op0 = operands[0];
5659  arm_compare_op1 = operands[1];
5660  DONE;
5661  "
5662)
5663
5664(define_insn "*arm_cmpsi_insn"
5665  [(set (reg:CC CC_REGNUM)
5666	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5667		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5668  "TARGET_ARM"
5669  "@
5670   cmp%?\\t%0, %1
5671   cmn%?\\t%0, #%n1"
5672  [(set_attr "conds" "set")]
5673)
5674
5675(define_insn "*cmpsi_shiftsi"
5676  [(set (reg:CC CC_REGNUM)
5677	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
5678		    (match_operator:SI  3 "shift_operator"
5679		     [(match_operand:SI 1 "s_register_operand" "r")
5680		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5681  "TARGET_ARM"
5682  "cmp%?\\t%0, %1%S3"
5683  [(set_attr "conds" "set")
5684   (set_attr "shift" "1")
5685   ]
5686)
5687
5688(define_insn "*cmpsi_shiftsi_swp"
5689  [(set (reg:CC_SWP CC_REGNUM)
5690	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
5691			 [(match_operand:SI 1 "s_register_operand" "r")
5692			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
5693			(match_operand:SI 0 "s_register_operand" "r")))]
5694  "TARGET_ARM"
5695  "cmp%?\\t%0, %1%S3"
5696  [(set_attr "conds" "set")
5697   (set_attr "shift" "1")
5698   ]
5699)
5700
5701(define_insn "*cmpsi_neg_shiftsi"
5702  [(set (reg:CC CC_REGNUM)
5703	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
5704		    (neg:SI (match_operator:SI 3 "shift_operator"
5705			     [(match_operand:SI 1 "s_register_operand" "r")
5706			      (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5707  "TARGET_ARM"
5708  "cmn%?\\t%0, %1%S3"
5709  [(set_attr "conds" "set")
5710   (set_attr "shift" "1")
5711   ]
5712)
5713
5714(define_insn "*cmpsf_insn"
5715  [(set (reg:CCFP CC_REGNUM)
5716	(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5717		      (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5718  "TARGET_ARM && TARGET_HARD_FLOAT"
5719  "@
5720   cmf%?\\t%0, %1
5721   cnf%?\\t%0, #%N1"
5722  [(set_attr "conds" "set")
5723   (set_attr "type" "f_2_r")]
5724)
5725
5726(define_insn "*cmpdf_insn"
5727  [(set (reg:CCFP CC_REGNUM)
5728	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5729		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5730  "TARGET_ARM && TARGET_HARD_FLOAT"
5731  "@
5732   cmf%?\\t%0, %1
5733   cnf%?\\t%0, #%N1"
5734  [(set_attr "conds" "set")
5735   (set_attr "type" "f_2_r")]
5736)
5737
5738(define_insn "*cmpesfdf_df"
5739  [(set (reg:CCFP CC_REGNUM)
5740	(compare:CCFP (float_extend:DF
5741		       (match_operand:SF 0 "s_register_operand" "f,f"))
5742		      (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5743  "TARGET_ARM && TARGET_HARD_FLOAT"
5744  "@
5745   cmf%?\\t%0, %1
5746   cnf%?\\t%0, #%N1"
5747  [(set_attr "conds" "set")
5748   (set_attr "type" "f_2_r")]
5749)
5750
5751(define_insn "*cmpdf_esfdf"
5752  [(set (reg:CCFP CC_REGNUM)
5753	(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5754		      (float_extend:DF
5755		       (match_operand:SF 1 "s_register_operand" "f"))))]
5756  "TARGET_ARM && TARGET_HARD_FLOAT"
5757  "cmf%?\\t%0, %1"
5758  [(set_attr "conds" "set")
5759   (set_attr "type" "f_2_r")]
5760)
5761
5762(define_insn "*cmpxf_insn"
5763  [(set (reg:CCFP CC_REGNUM)
5764	(compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5765		      (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5766  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5767  "@
5768   cmf%?\\t%0, %1
5769   cnf%?\\t%0, #%N1"
5770  [(set_attr "conds" "set")
5771   (set_attr "type" "f_2_r")]
5772)
5773
5774(define_insn "*cmpsf_trap"
5775  [(set (reg:CCFPE CC_REGNUM)
5776	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5777		       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5778  "TARGET_ARM && TARGET_HARD_FLOAT"
5779  "@
5780   cmf%?e\\t%0, %1
5781   cnf%?e\\t%0, #%N1"
5782  [(set_attr "conds" "set")
5783   (set_attr "type" "f_2_r")]
5784)
5785
5786(define_insn "*cmpdf_trap"
5787  [(set (reg:CCFPE CC_REGNUM)
5788	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5789		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5790  "TARGET_ARM && TARGET_HARD_FLOAT"
5791  "@
5792   cmf%?e\\t%0, %1
5793   cnf%?e\\t%0, #%N1"
5794  [(set_attr "conds" "set")
5795   (set_attr "type" "f_2_r")]
5796)
5797
5798(define_insn "*cmp_esfdf_df_trap"
5799  [(set (reg:CCFPE CC_REGNUM)
5800	(compare:CCFPE (float_extend:DF
5801			(match_operand:SF 0 "s_register_operand" "f,f"))
5802		       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5803  "TARGET_ARM && TARGET_HARD_FLOAT"
5804  "@
5805   cmf%?e\\t%0, %1
5806   cnf%?e\\t%0, #%N1"
5807  [(set_attr "conds" "set")
5808   (set_attr "type" "f_2_r")]
5809)
5810
5811(define_insn "*cmp_df_esfdf_trap"
5812  [(set (reg:CCFPE CC_REGNUM)
5813	(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5814		       (float_extend:DF
5815			(match_operand:SF 1 "s_register_operand" "f"))))]
5816  "TARGET_ARM && TARGET_HARD_FLOAT"
5817  "cmf%?e\\t%0, %1"
5818  [(set_attr "conds" "set")
5819   (set_attr "type" "f_2_r")]
5820)
5821
5822(define_insn "*cmpxf_trap"
5823  [(set (reg:CCFPE CC_REGNUM)
5824	(compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5825		       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5826  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5827  "@
5828   cmf%?e\\t%0, %1
5829   cnf%?e\\t%0, #%N1"
5830  [(set_attr "conds" "set")
5831   (set_attr "type" "f_2_r")]
5832)
5833
5834; This insn allows redundant compares to be removed by cse, nothing should
5835; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5836; is deleted later on. The match_dup will match the mode here, so that
5837; mode changes of the condition codes aren't lost by this even though we don't
5838; specify what they are.
5839
5840(define_insn "*deleted_compare"
5841  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5842  "TARGET_ARM"
5843  "\\t%@ deleted compare"
5844  [(set_attr "conds" "set")
5845   (set_attr "length" "0")]
5846)
5847
5848
5849;; Conditional branch insns
5850
5851(define_expand "beq"
5852  [(set (pc)
5853	(if_then_else (eq (match_dup 1) (const_int 0))
5854		      (label_ref (match_operand 0 "" ""))
5855		      (pc)))]
5856  "TARGET_ARM"
5857  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5858)
5859
5860(define_expand "bne"
5861  [(set (pc)
5862	(if_then_else (ne (match_dup 1) (const_int 0))
5863		      (label_ref (match_operand 0 "" ""))
5864		      (pc)))]
5865  "TARGET_ARM"
5866  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5867)
5868
5869(define_expand "bgt"
5870  [(set (pc)
5871	(if_then_else (gt (match_dup 1) (const_int 0))
5872		      (label_ref (match_operand 0 "" ""))
5873		      (pc)))]
5874  "TARGET_ARM"
5875  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5876)
5877
5878(define_expand "ble"
5879  [(set (pc)
5880	(if_then_else (le (match_dup 1) (const_int 0))
5881		      (label_ref (match_operand 0 "" ""))
5882		      (pc)))]
5883  "TARGET_ARM"
5884  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5885)
5886
5887(define_expand "bge"
5888  [(set (pc)
5889	(if_then_else (ge (match_dup 1) (const_int 0))
5890		      (label_ref (match_operand 0 "" ""))
5891		      (pc)))]
5892  "TARGET_ARM"
5893  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5894)
5895
5896(define_expand "blt"
5897  [(set (pc)
5898	(if_then_else (lt (match_dup 1) (const_int 0))
5899		      (label_ref (match_operand 0 "" ""))
5900		      (pc)))]
5901  "TARGET_ARM"
5902  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5903)
5904
5905(define_expand "bgtu"
5906  [(set (pc)
5907	(if_then_else (gtu (match_dup 1) (const_int 0))
5908		      (label_ref (match_operand 0 "" ""))
5909		      (pc)))]
5910  "TARGET_ARM"
5911  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5912)
5913
5914(define_expand "bleu"
5915  [(set (pc)
5916	(if_then_else (leu (match_dup 1) (const_int 0))
5917		      (label_ref (match_operand 0 "" ""))
5918		      (pc)))]
5919  "TARGET_ARM"
5920  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5921)
5922
5923(define_expand "bgeu"
5924  [(set (pc)
5925	(if_then_else (geu (match_dup 1) (const_int 0))
5926		      (label_ref (match_operand 0 "" ""))
5927		      (pc)))]
5928  "TARGET_ARM"
5929  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5930)
5931
5932(define_expand "bltu"
5933  [(set (pc)
5934	(if_then_else (ltu (match_dup 1) (const_int 0))
5935		      (label_ref (match_operand 0 "" ""))
5936		      (pc)))]
5937  "TARGET_ARM"
5938  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5939)
5940
5941(define_expand "bunordered"
5942  [(set (pc)
5943	(if_then_else (unordered (match_dup 1) (const_int 0))
5944		      (label_ref (match_operand 0 "" ""))
5945		      (pc)))]
5946  "TARGET_ARM && TARGET_HARD_FLOAT"
5947  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5948				      arm_compare_op1);"
5949)
5950
5951(define_expand "bordered"
5952  [(set (pc)
5953	(if_then_else (ordered (match_dup 1) (const_int 0))
5954		      (label_ref (match_operand 0 "" ""))
5955		      (pc)))]
5956  "TARGET_ARM && TARGET_HARD_FLOAT"
5957  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5958				      arm_compare_op1);"
5959)
5960
5961(define_expand "bungt"
5962  [(set (pc)
5963	(if_then_else (ungt (match_dup 1) (const_int 0))
5964		      (label_ref (match_operand 0 "" ""))
5965		      (pc)))]
5966  "TARGET_ARM && TARGET_HARD_FLOAT"
5967  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5968)
5969
5970(define_expand "bunlt"
5971  [(set (pc)
5972	(if_then_else (unlt (match_dup 1) (const_int 0))
5973		      (label_ref (match_operand 0 "" ""))
5974		      (pc)))]
5975  "TARGET_ARM && TARGET_HARD_FLOAT"
5976  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5977)
5978
5979(define_expand "bunge"
5980  [(set (pc)
5981	(if_then_else (unge (match_dup 1) (const_int 0))
5982		      (label_ref (match_operand 0 "" ""))
5983		      (pc)))]
5984  "TARGET_ARM && TARGET_HARD_FLOAT"
5985  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5986)
5987
5988(define_expand "bunle"
5989  [(set (pc)
5990	(if_then_else (unle (match_dup 1) (const_int 0))
5991		      (label_ref (match_operand 0 "" ""))
5992		      (pc)))]
5993  "TARGET_ARM && TARGET_HARD_FLOAT"
5994  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5995)
5996
5997;; The following two patterns need two branch instructions, since there is
5998;; no single instruction that will handle all cases.
5999(define_expand "buneq"
6000  [(set (pc)
6001	(if_then_else (uneq (match_dup 1) (const_int 0))
6002		      (label_ref (match_operand 0 "" ""))
6003		      (pc)))]
6004  "TARGET_ARM && TARGET_HARD_FLOAT"
6005  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6006)
6007
6008(define_expand "bltgt"
6009  [(set (pc)
6010	(if_then_else (ltgt (match_dup 1) (const_int 0))
6011		      (label_ref (match_operand 0 "" ""))
6012		      (pc)))]
6013  "TARGET_ARM && TARGET_HARD_FLOAT"
6014  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6015)
6016
6017;;
6018;; Patterns to match conditional branch insns.
6019;;
6020
6021; Special pattern to match UNEQ.
6022(define_insn "*arm_buneq"
6023  [(set (pc)
6024	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6025		      (label_ref (match_operand 0 "" ""))
6026		      (pc)))]
6027  "TARGET_ARM && TARGET_HARD_FLOAT"
6028  "*
6029  if (arm_ccfsm_state != 0)
6030    abort ();
6031
6032  return \"bvs\\t%l0;beq\\t%l0\";
6033  "
6034  [(set_attr "conds" "jump_clob")
6035   (set_attr "length" "8")]
6036)
6037
6038; Special pattern to match LTGT.
6039(define_insn "*arm_bltgt"
6040  [(set (pc)
6041	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6042		      (label_ref (match_operand 0 "" ""))
6043		      (pc)))]
6044  "TARGET_ARM && TARGET_HARD_FLOAT"
6045  "*
6046  if (arm_ccfsm_state != 0)
6047    abort ();
6048
6049  return \"bmi\\t%l0;bgt\\t%l0\";
6050  "
6051  [(set_attr "conds" "jump_clob")
6052   (set_attr "length" "8")]
6053)
6054
6055(define_insn "*arm_cond_branch"
6056  [(set (pc)
6057	(if_then_else (match_operator 1 "arm_comparison_operator"
6058		       [(match_operand 2 "cc_register" "") (const_int 0)])
6059		      (label_ref (match_operand 0 "" ""))
6060		      (pc)))]
6061  "TARGET_ARM"
6062  "*
6063  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6064    {
6065      arm_ccfsm_state += 2;
6066      return \"\";
6067    }
6068  return \"b%d1\\t%l0\";
6069  "
6070  [(set_attr "conds" "use")]
6071)
6072
6073; Special pattern to match reversed UNEQ.
6074(define_insn "*arm_buneq_reversed"
6075  [(set (pc)
6076	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6077		      (pc)
6078		      (label_ref (match_operand 0 "" ""))))]
6079  "TARGET_ARM && TARGET_HARD_FLOAT"
6080  "*
6081  if (arm_ccfsm_state != 0)
6082    abort ();
6083
6084  return \"bmi\\t%l0;bgt\\t%l0\";
6085  "
6086  [(set_attr "conds" "jump_clob")
6087   (set_attr "length" "8")]
6088)
6089
6090; Special pattern to match reversed LTGT.
6091(define_insn "*arm_bltgt_reversed"
6092  [(set (pc)
6093	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6094		      (pc)
6095		      (label_ref (match_operand 0 "" ""))))]
6096  "TARGET_ARM && TARGET_HARD_FLOAT"
6097  "*
6098  if (arm_ccfsm_state != 0)
6099    abort ();
6100
6101  return \"bvs\\t%l0;beq\\t%l0\";
6102  "
6103  [(set_attr "conds" "jump_clob")
6104   (set_attr "length" "8")]
6105)
6106
6107(define_insn "*arm_cond_branch_reversed"
6108  [(set (pc)
6109	(if_then_else (match_operator 1 "arm_comparison_operator"
6110		       [(match_operand 2 "cc_register" "") (const_int 0)])
6111		      (pc)
6112		      (label_ref (match_operand 0 "" ""))))]
6113  "TARGET_ARM"
6114  "*
6115  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6116    {
6117      arm_ccfsm_state += 2;
6118      return \"\";
6119    }
6120  return \"b%D1\\t%l0\";
6121  "
6122  [(set_attr "conds" "use")]
6123)
6124
6125
6126
6127; scc insns
6128
6129(define_expand "seq"
6130  [(set (match_operand:SI 0 "s_register_operand" "=r")
6131	(eq:SI (match_dup 1) (const_int 0)))]
6132  "TARGET_ARM"
6133  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6134)
6135
6136(define_expand "sne"
6137  [(set (match_operand:SI 0 "s_register_operand" "=r")
6138	(ne:SI (match_dup 1) (const_int 0)))]
6139  "TARGET_ARM"
6140  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6141)
6142
6143(define_expand "sgt"
6144  [(set (match_operand:SI 0 "s_register_operand" "=r")
6145	(gt:SI (match_dup 1) (const_int 0)))]
6146  "TARGET_ARM"
6147  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6148)
6149
6150(define_expand "sle"
6151  [(set (match_operand:SI 0 "s_register_operand" "=r")
6152	(le:SI (match_dup 1) (const_int 0)))]
6153  "TARGET_ARM"
6154  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6155)
6156
6157(define_expand "sge"
6158  [(set (match_operand:SI 0 "s_register_operand" "=r")
6159	(ge:SI (match_dup 1) (const_int 0)))]
6160  "TARGET_ARM"
6161  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6162)
6163
6164(define_expand "slt"
6165  [(set (match_operand:SI 0 "s_register_operand" "=r")
6166	(lt:SI (match_dup 1) (const_int 0)))]
6167  "TARGET_ARM"
6168  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6169)
6170
6171(define_expand "sgtu"
6172  [(set (match_operand:SI 0 "s_register_operand" "=r")
6173	(gtu:SI (match_dup 1) (const_int 0)))]
6174  "TARGET_ARM"
6175  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6176)
6177
6178(define_expand "sleu"
6179  [(set (match_operand:SI 0 "s_register_operand" "=r")
6180	(leu:SI (match_dup 1) (const_int 0)))]
6181  "TARGET_ARM"
6182  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6183)
6184
6185(define_expand "sgeu"
6186  [(set (match_operand:SI 0 "s_register_operand" "=r")
6187	(geu:SI (match_dup 1) (const_int 0)))]
6188  "TARGET_ARM"
6189  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6190)
6191
6192(define_expand "sltu"
6193  [(set (match_operand:SI 0 "s_register_operand" "=r")
6194	(ltu:SI (match_dup 1) (const_int 0)))]
6195  "TARGET_ARM"
6196  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6197)
6198
6199(define_expand "sunordered"
6200  [(set (match_operand:SI 0 "s_register_operand" "=r")
6201	(unordered:SI (match_dup 1) (const_int 0)))]
6202  "TARGET_ARM && TARGET_HARD_FLOAT"
6203  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6204				      arm_compare_op1);"
6205)
6206
6207(define_expand "sordered"
6208  [(set (match_operand:SI 0 "s_register_operand" "=r")
6209	(ordered:SI (match_dup 1) (const_int 0)))]
6210  "TARGET_ARM && TARGET_HARD_FLOAT"
6211  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6212				      arm_compare_op1);"
6213)
6214
6215(define_expand "sungt"
6216  [(set (match_operand:SI 0 "s_register_operand" "=r")
6217	(ungt:SI (match_dup 1) (const_int 0)))]
6218  "TARGET_ARM && TARGET_HARD_FLOAT"
6219  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6220				      arm_compare_op1);"
6221)
6222
6223(define_expand "sunge"
6224  [(set (match_operand:SI 0 "s_register_operand" "=r")
6225	(unge:SI (match_dup 1) (const_int 0)))]
6226  "TARGET_ARM && TARGET_HARD_FLOAT"
6227  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6228				      arm_compare_op1);"
6229)
6230
6231(define_expand "sunlt"
6232  [(set (match_operand:SI 0 "s_register_operand" "=r")
6233	(unlt:SI (match_dup 1) (const_int 0)))]
6234  "TARGET_ARM && TARGET_HARD_FLOAT"
6235  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6236				      arm_compare_op1);"
6237)
6238
6239(define_expand "sunle"
6240  [(set (match_operand:SI 0 "s_register_operand" "=r")
6241	(unle:SI (match_dup 1) (const_int 0)))]
6242  "TARGET_ARM && TARGET_HARD_FLOAT"
6243  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6244				      arm_compare_op1);"
6245)
6246
6247;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6248;;; simple ARM instructions. 
6249;
6250; (define_expand "suneq"
6251;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6252; 	(uneq:SI (match_dup 1) (const_int 0)))]
6253;   "TARGET_ARM && TARGET_HARD_FLOAT"
6254;   "abort ();"
6255; )
6256;
6257; (define_expand "sltgt"
6258;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6259; 	(ltgt:SI (match_dup 1) (const_int 0)))]
6260;   "TARGET_ARM && TARGET_HARD_FLOAT"
6261;   "abort ();"
6262; )
6263
6264(define_insn "*mov_scc"
6265  [(set (match_operand:SI 0 "s_register_operand" "=r")
6266	(match_operator:SI 1 "arm_comparison_operator"
6267	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6268  "TARGET_ARM"
6269  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6270  [(set_attr "conds" "use")
6271   (set_attr "length" "8")]
6272)
6273
6274(define_insn "*mov_negscc"
6275  [(set (match_operand:SI 0 "s_register_operand" "=r")
6276	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
6277		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6278  "TARGET_ARM"
6279  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6280  [(set_attr "conds" "use")
6281   (set_attr "length" "8")]
6282)
6283
6284(define_insn "*mov_notscc"
6285  [(set (match_operand:SI 0 "s_register_operand" "=r")
6286	(not:SI (match_operator:SI 1 "arm_comparison_operator"
6287		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6288  "TARGET_ARM"
6289  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6290  [(set_attr "conds" "use")
6291   (set_attr "length" "8")]
6292)
6293
6294
6295;; Conditional move insns
6296
6297(define_expand "movsicc"
6298  [(set (match_operand:SI 0 "s_register_operand" "")
6299	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6300			 (match_operand:SI 2 "arm_not_operand" "")
6301			 (match_operand:SI 3 "arm_not_operand" "")))]
6302  "TARGET_ARM"
6303  "
6304  {
6305    enum rtx_code code = GET_CODE (operands[1]);
6306    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6307
6308    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6309  }"
6310)
6311
6312(define_expand "movsfcc"
6313  [(set (match_operand:SF 0 "s_register_operand" "")
6314	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6315			 (match_operand:SF 2 "s_register_operand" "")
6316			 (match_operand:SF 3 "nonmemory_operand" "")))]
6317  "TARGET_ARM"
6318  "
6319  {
6320    enum rtx_code code = GET_CODE (operands[1]);
6321    rtx ccreg;
6322
6323    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6324       Otherwise, ensure it is a valid FP add operand */
6325    if ((!TARGET_HARD_FLOAT)
6326        || (!fpu_add_operand (operands[3], SFmode)))
6327      operands[3] = force_reg (SFmode, operands[3]);
6328
6329    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6330    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6331  }"
6332)
6333
6334(define_expand "movdfcc"
6335  [(set (match_operand:DF 0 "s_register_operand" "")
6336	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6337			 (match_operand:DF 2 "s_register_operand" "")
6338			 (match_operand:DF 3 "fpu_add_operand" "")))]
6339  "TARGET_ARM && TARGET_HARD_FLOAT"
6340  "
6341  {
6342    enum rtx_code code = GET_CODE (operands[1]);
6343    rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6344
6345    operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6346  }"
6347)
6348
6349(define_insn "*movsicc_insn"
6350  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6351	(if_then_else:SI
6352	 (match_operator 3 "arm_comparison_operator"
6353	  [(match_operand 4 "cc_register" "") (const_int 0)])
6354	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6355	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6356  "TARGET_ARM"
6357  "@
6358   mov%D3\\t%0, %2
6359   mvn%D3\\t%0, #%B2
6360   mov%d3\\t%0, %1
6361   mvn%d3\\t%0, #%B1
6362   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6363   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6364   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6365   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6366  [(set_attr "length" "4,4,4,4,8,8,8,8")
6367   (set_attr "conds" "use")]
6368)
6369
6370(define_insn "*movsfcc_hard_insn"
6371  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6372	(if_then_else:SF
6373	 (match_operator 3 "arm_comparison_operator" 
6374	  [(match_operand 4 "cc_register" "") (const_int 0)])
6375	 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6376	 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6377  "TARGET_ARM && TARGET_HARD_FLOAT"
6378  "@
6379   mvf%D3s\\t%0, %2
6380   mnf%D3s\\t%0, #%N2
6381   mvf%d3s\\t%0, %1
6382   mnf%d3s\\t%0, #%N1
6383   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6384   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6385   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6386   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6387  [(set_attr "length" "4,4,4,4,8,8,8,8")
6388   (set_attr "type" "ffarith")
6389   (set_attr "conds" "use")]
6390)
6391
6392(define_insn "*movsfcc_soft_insn"
6393  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6394	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
6395			  [(match_operand 4 "cc_register" "") (const_int 0)])
6396			 (match_operand:SF 1 "s_register_operand" "0,r")
6397			 (match_operand:SF 2 "s_register_operand" "r,0")))]
6398  "TARGET_ARM && TARGET_SOFT_FLOAT"
6399  "@
6400   mov%D3\\t%0, %2
6401   mov%d3\\t%0, %1"
6402  [(set_attr "conds" "use")]
6403)
6404
6405(define_insn "*movdfcc_insn"
6406  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6407	(if_then_else:DF
6408	 (match_operator 3 "arm_comparison_operator"
6409	  [(match_operand 4 "cc_register" "") (const_int 0)])
6410	 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6411	 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6412  "TARGET_ARM && TARGET_HARD_FLOAT"
6413  "@
6414   mvf%D3d\\t%0, %2
6415   mnf%D3d\\t%0, #%N2
6416   mvf%d3d\\t%0, %1
6417   mnf%d3d\\t%0, #%N1
6418   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6419   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6420   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6421   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6422  [(set_attr "length" "4,4,4,4,8,8,8,8")
6423   (set_attr "type" "ffarith")
6424   (set_attr "conds" "use")]
6425)
6426
6427
6428;; Jump and linkage insns
6429
6430(define_expand "jump"
6431  [(set (pc)
6432	(label_ref (match_operand 0 "" "")))]
6433  "TARGET_EITHER"
6434  ""
6435)
6436
6437(define_insn "*arm_jump"
6438  [(set (pc)
6439	(label_ref (match_operand 0 "" "")))]
6440  "TARGET_ARM"
6441  "*
6442  {
6443    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6444      {
6445        arm_ccfsm_state += 2;
6446        return \"\";
6447      }
6448    return \"b%?\\t%l0\";
6449  }
6450  "
6451  [(set_attr "predicable" "yes")]
6452)
6453
6454(define_insn "*thumb_jump"
6455  [(set (pc)
6456	(label_ref (match_operand 0 "" "")))]
6457  "TARGET_THUMB"
6458  "*
6459  if (get_attr_length (insn) == 2)
6460    return \"b\\t%l0\";
6461  return \"bl\\t%l0\\t%@ far jump\";
6462  "
6463  [(set (attr "far_jump")
6464        (if_then_else
6465	    (eq_attr "length" "4")
6466	    (const_string "yes")
6467	    (const_string "no")))
6468   (set (attr "length") 
6469        (if_then_else
6470	    (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6471		 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6472  	    (const_int 2)
6473	    (const_int 4)))]
6474)
6475
6476(define_expand "call"
6477  [(parallel [(call (match_operand 0 "memory_operand" "")
6478	            (match_operand 1 "general_operand" ""))
6479	      (use (match_operand 2 "" ""))
6480	      (clobber (reg:SI LR_REGNUM))])]
6481  "TARGET_EITHER"
6482  "
6483  {
6484    rtx callee;
6485    
6486    /* In an untyped call, we can get NULL for operand 2.  */
6487    if (operands[2] == NULL_RTX)
6488      operands[2] = const0_rtx;
6489      
6490    /* This is to decide if we should generate indirect calls by loading the
6491       32 bit address of the callee into a register before performing the
6492       branch and link.  operand[2] encodes the long_call/short_call
6493       attribute of the function being called.  This attribute is set whenever
6494       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6495       is used, and the short_call attribute can also be set if function is
6496       declared as static or if it has already been defined in the current
6497       compilation unit.  See arm.c and arm.h for info about this.  The third
6498       parameter to arm_is_longcall_p is used to tell it which pattern
6499       invoked it.  */
6500    callee  = XEXP (operands[0], 0);
6501    
6502    if (GET_CODE (callee) != REG
6503       && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6504      XEXP (operands[0], 0) = force_reg (Pmode, callee);
6505  }"
6506)
6507
6508(define_insn "*call_reg"
6509  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6510         (match_operand 1 "" ""))
6511   (use (match_operand 2 "" ""))
6512   (clobber (reg:SI LR_REGNUM))]
6513  "TARGET_ARM"
6514  "*
6515  return output_call (operands);
6516  "
6517  ;; length is worst case, normally it is only two
6518  [(set_attr "length" "12")
6519   (set_attr "type" "call")]
6520)
6521
6522(define_insn "*call_mem"
6523  [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6524	 (match_operand 1 "" ""))
6525   (use (match_operand 2 "" ""))
6526   (clobber (reg:SI LR_REGNUM))]
6527  "TARGET_ARM"
6528  "*
6529  return output_call_mem (operands);
6530  "
6531  [(set_attr "length" "12")
6532   (set_attr "type" "call")]
6533)
6534
6535(define_insn "*call_indirect"
6536  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6537	 (match_operand 1 "" ""))
6538   (use (match_operand 2 "" ""))
6539   (clobber (reg:SI LR_REGNUM))]
6540  "TARGET_THUMB"
6541  "*
6542  {
6543    if (TARGET_CALLER_INTERWORKING)
6544      return \"bl\\t%__interwork_call_via_%0\";
6545    else
6546      return \"bl\\t%__call_via_%0\";
6547  }"
6548  [(set_attr "type" "call")]
6549)
6550
6551(define_insn "*call_value_indirect"
6552  [(set (match_operand 0 "" "=l")
6553	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6554	      (match_operand 2 "" "")))
6555   (use (match_operand 3 "" ""))
6556   (clobber (reg:SI LR_REGNUM))]
6557  "TARGET_THUMB"
6558  "*
6559  {
6560    if (TARGET_CALLER_INTERWORKING)
6561      return \"bl\\t%__interwork_call_via_%1\";
6562    else
6563      return \"bl\\t%__call_via_%1\";
6564  }"
6565  [(set_attr "type" "call")]
6566)
6567
6568(define_expand "call_value"
6569  [(parallel [(set (match_operand       0 "" "")
6570	           (call (match_operand 1 "memory_operand" "")
6571		         (match_operand 2 "general_operand" "")))
6572	      (use (match_operand 3 "" ""))
6573	      (clobber (reg:SI LR_REGNUM))])]
6574  "TARGET_EITHER"
6575  "
6576  {
6577    rtx callee = XEXP (operands[1], 0);
6578    
6579    /* In an untyped call, we can get NULL for operand 2.  */
6580    if (operands[3] == 0)
6581      operands[3] = const0_rtx;
6582      
6583    /* See the comment in define_expand \"call\".  */
6584    if (GET_CODE (callee) != REG
6585	&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6586      XEXP (operands[1], 0) = force_reg (Pmode, callee);
6587  }"
6588)
6589
6590(define_insn "*call_value_reg"
6591  [(set (match_operand 0 "" "=r,f")
6592        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6593	      (match_operand 2 "" "")))
6594   (use (match_operand 3 "" ""))
6595   (clobber (reg:SI LR_REGNUM))]
6596  "TARGET_ARM"
6597  "*
6598  return output_call (&operands[1]);
6599  "
6600  [(set_attr "length" "12")
6601   (set_attr "type" "call")]
6602)
6603
6604(define_insn "*call_value_mem"
6605  [(set (match_operand 0 "" "=r,f")
6606	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6607	      (match_operand 2 "" "")))
6608   (use (match_operand 3 "" ""))
6609   (clobber (reg:SI LR_REGNUM))]
6610  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6611  "*
6612  return output_call_mem (&operands[1]);
6613  "
6614  [(set_attr "length" "12")
6615   (set_attr "type" "call")]
6616)
6617
6618;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6619;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6620
6621(define_insn "*call_symbol"
6622  [(call (mem:SI (match_operand:SI 0 "" "X"))
6623	 (match_operand 1 "" ""))
6624   (use (match_operand 2 "" ""))
6625   (clobber (reg:SI LR_REGNUM))]
6626  "TARGET_ARM
6627   && (GET_CODE (operands[0]) == SYMBOL_REF)
6628   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6629  "*
6630  {
6631    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6632  }"
6633  [(set_attr "type" "call")]
6634)
6635
6636(define_insn "*call_value_symbol"
6637  [(set (match_operand 0 "s_register_operand" "=r,f")
6638	(call (mem:SI (match_operand:SI 1 "" "X,X"))
6639	(match_operand:SI 2 "" "")))
6640   (use (match_operand 3 "" ""))
6641   (clobber (reg:SI LR_REGNUM))]
6642  "TARGET_ARM
6643   && (GET_CODE (operands[1]) == SYMBOL_REF)
6644   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6645  "*
6646  {
6647    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6648  }"
6649  [(set_attr "type" "call")]
6650)
6651
6652(define_insn "*call_insn"
6653  [(call (mem:SI (match_operand:SI 0 "" "X"))
6654	 (match_operand:SI 1 "" ""))
6655   (use (match_operand 2 "" ""))
6656   (clobber (reg:SI LR_REGNUM))]
6657  "TARGET_THUMB
6658   && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6659  "bl\\t%a0"
6660  [(set_attr "length" "4")
6661   (set_attr "type" "call")]
6662)
6663
6664(define_insn "*call_value_insn"
6665  [(set (match_operand 0 "register_operand" "=l")
6666	(call (mem:SI (match_operand 1 "" "X"))
6667	      (match_operand 2 "" "")))
6668   (use (match_operand 3 "" ""))
6669   (clobber (reg:SI LR_REGNUM))]
6670  "TARGET_THUMB
6671   && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6672  "bl\\t%a1"
6673  [(set_attr "length" "4")
6674   (set_attr "type" "call")]
6675)
6676
6677;; We may also be able to do sibcalls for Thumb, but it's much harder...
6678(define_expand "sibcall"
6679  [(parallel [(call (match_operand 0 "memory_operand" "")
6680		    (match_operand 1 "general_operand" ""))
6681	      (use (match_operand 2 "" ""))
6682	      (use (reg:SI LR_REGNUM))])]
6683  "TARGET_ARM"
6684  "
6685  {
6686    if (operands[2] == NULL_RTX)
6687      operands[2] = const0_rtx;
6688  }"
6689)
6690
6691(define_expand "sibcall_value"
6692  [(parallel [(set (match_operand 0 "register_operand" "")
6693		   (call (match_operand 1 "memory_operand" "")
6694			 (match_operand 2 "general_operand" "")))
6695	      (use (match_operand 3 "" ""))
6696	      (use (reg:SI LR_REGNUM))])]
6697  "TARGET_ARM"
6698  "
6699  {
6700    if (operands[3] == NULL_RTX)
6701      operands[3] = const0_rtx;
6702  }"
6703)
6704
6705(define_insn "*sibcall_insn"
6706 [(call (mem:SI (match_operand:SI 0 "" "X"))
6707	(match_operand 1 "" ""))
6708  (use (match_operand 2 "" ""))
6709  (use (reg:SI LR_REGNUM))]
6710  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6711  "*
6712  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6713  "
6714  [(set_attr "type" "call")]
6715)
6716
6717(define_insn "*sibcall_value_insn"
6718 [(set (match_operand 0 "s_register_operand" "=r,f")
6719       (call (mem:SI (match_operand:SI 1 "" "X,X"))
6720	     (match_operand 2 "" "")))
6721  (use (match_operand 3 "" ""))
6722  (use (reg:SI LR_REGNUM))]
6723  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6724  "*
6725  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6726  "
6727  [(set_attr "type" "call")]
6728)
6729
6730;; Often the return insn will be the same as loading from memory, so set attr
6731(define_insn "return"
6732  [(return)]
6733  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6734  "*
6735  {
6736    if (arm_ccfsm_state == 2)
6737      {
6738        arm_ccfsm_state += 2;
6739        return \"\";
6740      }
6741    return output_return_instruction (NULL, TRUE, FALSE);
6742  }"
6743  [(set_attr "type" "load")
6744   (set_attr "predicable" "yes")]
6745)
6746
6747(define_insn "*cond_return"
6748  [(set (pc)
6749        (if_then_else (match_operator 0 "arm_comparison_operator"
6750		       [(match_operand 1 "cc_register" "") (const_int 0)])
6751                      (return)
6752                      (pc)))]
6753  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6754  "*
6755  {
6756    if (arm_ccfsm_state == 2)
6757      {
6758        arm_ccfsm_state += 2;
6759        return \"\";
6760      }
6761    return output_return_instruction (operands[0], TRUE, FALSE);
6762  }"
6763  [(set_attr "conds" "use")
6764   (set_attr "type" "load")]
6765)
6766
6767(define_insn "*cond_return_inverted"
6768  [(set (pc)
6769        (if_then_else (match_operator 0 "arm_comparison_operator"
6770		       [(match_operand 1 "cc_register" "") (const_int 0)])
6771                      (pc)
6772		      (return)))]
6773  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6774  "*
6775  {
6776    if (arm_ccfsm_state == 2)
6777      {
6778        arm_ccfsm_state += 2;
6779        return \"\";
6780      }
6781    return output_return_instruction (operands[0], TRUE, TRUE);
6782  }"
6783  [(set_attr "conds" "use")
6784   (set_attr "type" "load")]
6785)
6786
6787;; Call subroutine returning any type.
6788
6789(define_expand "untyped_call"
6790  [(parallel [(call (match_operand 0 "" "")
6791		    (const_int 0))
6792	      (match_operand 1 "" "")
6793	      (match_operand 2 "" "")])]
6794  "TARGET_ARM"
6795  "
6796  {
6797    int i;
6798
6799    emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6800
6801    for (i = 0; i < XVECLEN (operands[2], 0); i++)
6802      {
6803	rtx set = XVECEXP (operands[2], 0, i);
6804
6805	emit_move_insn (SET_DEST (set), SET_SRC (set));
6806      }
6807
6808    /* The optimizer does not know that the call sets the function value
6809       registers we stored in the result block.  We avoid problems by
6810       claiming that all hard registers are used and clobbered at this
6811       point.  */
6812    emit_insn (gen_blockage ());
6813
6814    DONE;
6815  }"
6816)
6817
6818;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6819;; all of memory.  This blocks insns from being moved across this point.
6820
6821(define_insn "blockage"
6822  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6823  "TARGET_EITHER"
6824  ""
6825  [(set_attr "length" "0")
6826   (set_attr "type" "block")]
6827)
6828
6829(define_expand "casesi"
6830  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
6831   (match_operand:SI 1 "const_int_operand" "")	; lower bound
6832   (match_operand:SI 2 "const_int_operand" "")	; total range
6833   (match_operand:SI 3 "" "")			; table label
6834   (match_operand:SI 4 "" "")]			; Out of range label
6835  "TARGET_ARM"
6836  "
6837  {
6838    rtx reg;
6839    if (operands[1] != const0_rtx)
6840      {
6841	reg = gen_reg_rtx (SImode);
6842
6843	emit_insn (gen_addsi3 (reg, operands[0],
6844			       GEN_INT (-INTVAL (operands[1]))));
6845	operands[0] = reg;
6846      }
6847
6848    if (!const_ok_for_arm (INTVAL (operands[2])))
6849      operands[2] = force_reg (SImode, operands[2]);
6850
6851    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6852					 operands[4]));
6853    DONE;
6854  }"
6855)
6856
6857;; The USE in this pattern is needed to tell flow analysis that this is
6858;; a CASESI insn.  It has no other purpose.
6859(define_insn "casesi_internal"
6860  [(parallel [(set (pc)
6861	       (if_then_else
6862		(leu (match_operand:SI 0 "s_register_operand" "r")
6863		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
6864		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6865				 (label_ref (match_operand 2 "" ""))))
6866		(label_ref (match_operand 3 "" ""))))
6867	      (clobber (reg:CC CC_REGNUM))
6868	      (use (label_ref (match_dup 2)))])]
6869  "TARGET_ARM"
6870  "*
6871    if (flag_pic)
6872      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6873    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6874  "
6875  [(set_attr "conds" "clob")
6876   (set_attr "length" "12")]
6877)
6878
6879(define_expand "indirect_jump"
6880  [(set (pc)
6881	(match_operand:SI 0 "s_register_operand" ""))]
6882  "TARGET_EITHER"
6883  ""
6884)
6885
6886(define_insn "*arm_indirect_jump"
6887  [(set (pc)
6888	(match_operand:SI 0 "s_register_operand" "r"))]
6889  "TARGET_ARM"
6890  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6891  [(set_attr "predicable" "yes")]
6892)
6893
6894;; Although not supported by the define_expand above,
6895;; cse/combine may generate this form.
6896(define_insn "*load_indirect_jump"
6897  [(set (pc)
6898	(match_operand:SI 0 "memory_operand" "m"))]
6899  "TARGET_ARM"
6900  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6901  [(set_attr "type" "load")
6902   (set_attr "pool_range" "4096")
6903   (set_attr "neg_pool_range" "4084")
6904   (set_attr "predicable" "yes")]
6905)
6906
6907(define_insn "*thumb_indirect_jump"
6908  [(set (pc)
6909	(match_operand:SI 0 "register_operand" "l*r"))]
6910  "TARGET_THUMB"
6911  "mov\\tpc, %0"
6912  [(set_attr "conds" "clob")
6913   (set_attr "length" "2")]
6914)
6915
6916
6917;; Misc insns
6918
6919(define_insn "nop"
6920  [(const_int 0)]
6921  "TARGET_EITHER"
6922  "*
6923  if (TARGET_ARM)
6924    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6925  return  \"mov\\tr8, r8\";
6926  "
6927  [(set (attr "length")
6928	(if_then_else (eq_attr "is_thumb" "yes")
6929		      (const_int 2)
6930		      (const_int 4)))]
6931)
6932
6933
6934;; Patterns to allow combination of arithmetic, cond code and shifts
6935
6936(define_insn "*arith_shiftsi"
6937  [(set (match_operand:SI 0 "s_register_operand" "=r")
6938        (match_operator:SI 1 "shiftable_operator"
6939          [(match_operator:SI 3 "shift_operator"
6940             [(match_operand:SI 4 "s_register_operand" "r")
6941              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6942           (match_operand:SI 2 "s_register_operand" "r")]))]
6943  "TARGET_ARM"
6944  "%i1%?\\t%0, %2, %4%S3"
6945  [(set_attr "predicable" "yes")
6946   (set_attr "shift" "4")
6947   ]
6948)
6949
6950(define_insn "*arith_shiftsi_compare0"
6951  [(set (reg:CC_NOOV CC_REGNUM)
6952        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6953		          [(match_operator:SI 3 "shift_operator"
6954		            [(match_operand:SI 4 "s_register_operand" "r")
6955		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6956		           (match_operand:SI 2 "s_register_operand" "r")])
6957			 (const_int 0)))
6958   (set (match_operand:SI 0 "s_register_operand" "=r")
6959	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6960			 (match_dup 2)]))]
6961  "TARGET_ARM"
6962  "%i1%?s\\t%0, %2, %4%S3"
6963  [(set_attr "conds" "set")
6964   (set_attr "shift" "4")
6965   ]
6966)
6967
6968(define_insn "*arith_shiftsi_compare0_scratch"
6969  [(set (reg:CC_NOOV CC_REGNUM)
6970        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6971		          [(match_operator:SI 3 "shift_operator"
6972		            [(match_operand:SI 4 "s_register_operand" "r")
6973		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
6974		           (match_operand:SI 2 "s_register_operand" "r")])
6975			 (const_int 0)))
6976   (clobber (match_scratch:SI 0 "=r"))]
6977  "TARGET_ARM"
6978  "%i1%?s\\t%0, %2, %4%S3"
6979  [(set_attr "conds" "set")
6980   (set_attr "shift" "4")
6981   ]
6982)
6983
6984(define_insn "*sub_shiftsi"
6985  [(set (match_operand:SI 0 "s_register_operand" "=r")
6986	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
6987		  (match_operator:SI 2 "shift_operator"
6988		   [(match_operand:SI 3 "s_register_operand" "r")
6989		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6990  "TARGET_ARM"
6991  "sub%?\\t%0, %1, %3%S2"
6992  [(set_attr "predicable" "yes")
6993   (set_attr "shift" "3")
6994   ]
6995)
6996
6997(define_insn "*sub_shiftsi_compare0"
6998  [(set (reg:CC_NOOV CC_REGNUM)
6999	(compare:CC_NOOV
7000	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7001		   (match_operator:SI 2 "shift_operator"
7002		    [(match_operand:SI 3 "s_register_operand" "r")
7003		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7004	 (const_int 0)))
7005   (set (match_operand:SI 0 "s_register_operand" "=r")
7006	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7007						 (match_dup 4)])))]
7008  "TARGET_ARM"
7009  "sub%?s\\t%0, %1, %3%S2"
7010  [(set_attr "conds" "set")
7011   (set_attr "shift" "3") 
7012   ]
7013)
7014
7015(define_insn "*sub_shiftsi_compare0_scratch"
7016  [(set (reg:CC_NOOV CC_REGNUM)
7017	(compare:CC_NOOV
7018	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7019		   (match_operator:SI 2 "shift_operator"
7020		    [(match_operand:SI 3 "s_register_operand" "r")
7021		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7022	 (const_int 0)))
7023   (clobber (match_scratch:SI 0 "=r"))]
7024  "TARGET_ARM"
7025  "sub%?s\\t%0, %1, %3%S2"
7026  [(set_attr "conds" "set")
7027   (set_attr "shift" "3") 
7028   ]
7029)
7030
7031;; These variants of the above insns can occur if the first operand is the
7032;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
7033;; seem to be a way around it.  Most of the predicates have to be null
7034;; because the format can be generated part way through reload, so
7035;; if we don't match it as soon as it becomes available, reload doesn't know
7036;; how to reload pseudos that haven't got hard registers; the constraints will
7037;; sort everything out.
7038
7039(define_insn "*reload_mulsi3"
7040  [(set (match_operand:SI 0 "" "=&r")
7041	(plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7042			   [(match_operand:SI 3 "" "r")
7043			    (match_operand:SI 4 "" "rM")])
7044			  (match_operand:SI 2 "" "r"))
7045		 (match_operand:SI 1 "const_int_operand" "n")))]
7046  "TARGET_ARM && reload_in_progress"
7047  "*
7048  output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7049  operands[2] = operands[1];
7050  operands[1] = operands[0];
7051  return output_add_immediate (operands);
7052  "
7053  [
7054   ; we have no idea how long the add_immediate is, it could be up to 4.
7055   (set_attr "length" "20")]
7056)
7057
7058(define_insn "*reload_mulsi_compare0"
7059  [(set (reg:CC_NOOV CC_REGNUM)
7060	(compare:CC_NOOV (plus:SI
7061			  (plus:SI 
7062			   (match_operator:SI 5 "shift_operator"
7063			    [(match_operand:SI 3 "" "r")
7064			     (match_operand:SI 4 "" "rM")])
7065			   (match_operand:SI 1 "" "r"))
7066			  (match_operand:SI 2 "const_int_operand" "n"))
7067			 (const_int 0)))
7068   (set (match_operand:SI 0 "" "=&r")
7069	(plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7070			  (match_dup 1))
7071		 (match_dup 2)))]
7072  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7073  "*
7074    output_add_immediate (operands);
7075    return \"add%?s\\t%0, %0, %3%S5\";
7076  "
7077  [(set_attr "conds" "set")
7078   (set_attr "shift" "3")
7079   (set_attr "length" "20")]
7080)
7081
7082(define_insn "*reload_mulsi_compare0_scratch"
7083  [(set (reg:CC_NOOV CC_REGNUM)
7084	(compare:CC_NOOV (plus:SI
7085			  (plus:SI 
7086			   (match_operator:SI 5 "shift_operator"
7087			    [(match_operand:SI 3 "" "r")
7088			     (match_operand:SI 4 "" "rM")])
7089			   (match_operand:SI 1 "" "r"))
7090			  (match_operand:SI 2 "const_int_operand" "n"))
7091			 (const_int 0)))
7092   (clobber (match_scratch:SI 0 "=&r"))]
7093  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7094  "*
7095    output_add_immediate (operands);
7096    return \"add%?s\\t%0, %0, %3%S5\";
7097  "
7098  [(set_attr "conds" "set")
7099   (set_attr "shift" "3")
7100   (set_attr "length" "20")]
7101)
7102
7103;; These are similar, but are needed when the mla pattern contains the
7104;; eliminated register as operand 3.
7105
7106(define_insn "*reload_muladdsi"
7107  [(set (match_operand:SI 0 "" "=&r,&r")
7108	(plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7109				   (match_operand:SI 2 "" "r,r"))
7110			  (match_operand:SI 3 "" "r,r"))
7111		 (match_operand:SI 4 "const_int_operand" "n,n")))]
7112  "TARGET_ARM && reload_in_progress"
7113  "*
7114  output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7115  operands[2] = operands[4];
7116  operands[1] = operands[0];
7117  return output_add_immediate (operands);
7118  "
7119  [(set_attr "length" "20")
7120   (set_attr "type" "mult")]
7121)
7122
7123(define_insn "*reload_muladdsi_compare0"
7124  [(set (reg:CC_NOOV CC_REGNUM)
7125	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7126					    (match_operand:SI 3 "" "r")
7127					    (match_operand:SI 4 "" "r"))
7128					   (match_operand:SI 1 "" "r"))
7129				  (match_operand:SI 2 "const_int_operand" "n"))
7130			 (const_int 0)))
7131   (set (match_operand:SI 0 "" "=&r")
7132	(plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7133		 (match_dup 2)))]
7134  "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7135  "*
7136    output_add_immediate (operands);
7137    output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7138    return \"\";
7139  "
7140  [(set_attr "length" "20")
7141   (set_attr "conds" "set")
7142   (set_attr "type" "mult")]
7143)
7144
7145(define_insn "*reload_muladdsi_compare0_scratch"
7146  [(set (reg:CC_NOOV CC_REGNUM)
7147	(compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7148					    (match_operand:SI 3 "" "r")
7149					    (match_operand:SI 4 "" "r"))
7150					   (match_operand:SI 1 "" "r"))
7151				  (match_operand:SI 2 "const_int_operand" "n"))
7152			 (const_int 0)))
7153   (clobber (match_scratch:SI 0 "=&r"))]
7154  "TARGET_ARM && reload_in_progress"
7155  "*
7156    output_add_immediate (operands);
7157    return \"mla%?s\\t%0, %3, %4, %0\";
7158  "
7159  [(set_attr "length" "20")
7160   (set_attr "conds" "set")
7161   (set_attr "type" "mult")]
7162)
7163
7164
7165
7166(define_insn "*and_scc"
7167  [(set (match_operand:SI 0 "s_register_operand" "=r")
7168	(and:SI (match_operator:SI 1 "arm_comparison_operator"
7169		 [(match_operand 3 "cc_register" "") (const_int 0)])
7170		(match_operand:SI 2 "s_register_operand" "r")))]
7171  "TARGET_ARM"
7172  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7173  [(set_attr "conds" "use")
7174   (set_attr "length" "8")]
7175)
7176
7177(define_insn "*ior_scc"
7178  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7179	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
7180		 [(match_operand 3 "cc_register" "") (const_int 0)])
7181		(match_operand:SI 1 "s_register_operand" "0,?r")))]
7182  "TARGET_ARM"
7183  "@
7184   orr%d2\\t%0, %1, #1
7185   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7186  [(set_attr "conds" "use")
7187   (set_attr "length" "4,8")]
7188)
7189
7190(define_insn "*compare_scc"
7191  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7192	(match_operator:SI 1 "arm_comparison_operator"
7193	 [(match_operand:SI 2 "s_register_operand" "r,r")
7194	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7195   (clobber (reg:CC CC_REGNUM))]
7196  "TARGET_ARM"
7197  "*
7198    if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7199      return \"mov\\t%0, %2, lsr #31\";
7200
7201    if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7202      return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7203
7204    if (GET_CODE (operands[1]) == NE)
7205      {
7206        if (which_alternative == 1)
7207	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7208        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7209      }
7210    if (which_alternative == 1)
7211      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7212    else
7213      output_asm_insn (\"cmp\\t%2, %3\", operands);
7214    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7215  "
7216  [(set_attr "conds" "clob")
7217   (set_attr "length" "12")]
7218)
7219
7220(define_insn "*cond_move"
7221  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7222	(if_then_else:SI (match_operator 3 "equality_operator"
7223			  [(match_operator 4 "arm_comparison_operator"
7224			    [(match_operand 5 "cc_register" "") (const_int 0)])
7225			   (const_int 0)])
7226			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7227			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7228  "TARGET_ARM"
7229  "*
7230    if (GET_CODE (operands[3]) == NE)
7231      {
7232        if (which_alternative != 1)
7233	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7234        if (which_alternative != 0)
7235	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7236        return \"\";
7237      }
7238    if (which_alternative != 0)
7239      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7240    if (which_alternative != 1)
7241      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7242    return \"\";
7243  "
7244  [(set_attr "conds" "use")
7245   (set_attr "length" "4,4,8")]
7246)
7247
7248(define_insn "*cond_arith"
7249  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7250        (match_operator:SI 5 "shiftable_operator" 
7251	 [(match_operator:SI 4 "arm_comparison_operator"
7252           [(match_operand:SI 2 "s_register_operand" "r,r")
7253	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7254          (match_operand:SI 1 "s_register_operand" "0,?r")]))
7255   (clobber (reg:CC CC_REGNUM))]
7256  "TARGET_ARM"
7257  "*
7258    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7259      return \"%i5\\t%0, %1, %2, lsr #31\";
7260
7261    output_asm_insn (\"cmp\\t%2, %3\", operands);
7262    if (GET_CODE (operands[5]) == AND)
7263      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7264    else if (GET_CODE (operands[5]) == MINUS)
7265      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7266    else if (which_alternative != 0)
7267      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7268    return \"%i5%d4\\t%0, %1, #1\";
7269  "
7270  [(set_attr "conds" "clob")
7271   (set_attr "length" "12")]
7272)
7273
7274(define_insn "*cond_sub"
7275  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7276        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7277		  (match_operator:SI 4 "arm_comparison_operator"
7278                   [(match_operand:SI 2 "s_register_operand" "r,r")
7279		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7280   (clobber (reg:CC CC_REGNUM))]
7281  "TARGET_ARM"
7282  "*
7283    output_asm_insn (\"cmp\\t%2, %3\", operands);
7284    if (which_alternative != 0)
7285      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7286    return \"sub%d4\\t%0, %1, #1\";
7287  "
7288  [(set_attr "conds" "clob")
7289   (set_attr "length" "8,12")]
7290)
7291
7292(define_insn "*cmp_ite0"
7293  [(set (match_operand 6 "dominant_cc_register" "")
7294	(compare
7295	 (if_then_else:SI
7296	  (match_operator 4 "arm_comparison_operator"
7297	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7298	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7299	  (match_operator:SI 5 "arm_comparison_operator"
7300	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7301	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7302	  (const_int 0))
7303	 (const_int 0)))]
7304  "TARGET_ARM"
7305  "*
7306  {
7307    static const char * const opcodes[4][2] =
7308    {
7309      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7310       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7311      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7312       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7313      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7314       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7315      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7316       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7317    };
7318    int swap =
7319      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7320
7321    return opcodes[which_alternative][swap];
7322  }"
7323  [(set_attr "conds" "set")
7324   (set_attr "length" "8")]
7325)
7326
7327(define_insn "*cmp_ite1"
7328  [(set (match_operand 6 "dominant_cc_register" "")
7329	(compare
7330	 (if_then_else:SI
7331	  (match_operator 4 "arm_comparison_operator"
7332	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7333	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7334	  (match_operator:SI 5 "arm_comparison_operator"
7335	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7336	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7337	  (const_int 1))
7338	 (const_int 0)))]
7339  "TARGET_ARM"
7340  "*
7341  {
7342    static const char * const opcodes[4][2] =
7343    {
7344      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7345       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7346      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7347       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7348      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7349       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7350      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7351       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7352    };
7353    int swap =
7354      comparison_dominates_p (GET_CODE (operands[5]),
7355			      reverse_condition (GET_CODE (operands[4])));
7356
7357    return opcodes[which_alternative][swap];
7358  }"
7359  [(set_attr "conds" "set")
7360   (set_attr "length" "8")]
7361)
7362
7363(define_insn "*cmp_and"
7364  [(set (match_operand 6 "dominant_cc_register" "")
7365	(compare
7366	 (and:SI
7367	  (match_operator 4 "arm_comparison_operator"
7368	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7369	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7370	  (match_operator:SI 5 "arm_comparison_operator"
7371	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7372	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7373	 (const_int 0)))]
7374  "TARGET_ARM"
7375  "*
7376  {
7377    static const char *const opcodes[4][2] =
7378    {
7379      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7380       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7381      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7382       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7383      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7384       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7385      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7386       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7387    };
7388    int swap =
7389      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7390
7391    return opcodes[which_alternative][swap];
7392  }"
7393  [(set_attr "conds" "set")
7394   (set_attr "predicable" "no")
7395   (set_attr "length" "8")]
7396)
7397
7398(define_insn "*cmp_ior"
7399  [(set (match_operand 6 "dominant_cc_register" "")
7400	(compare
7401	 (ior:SI
7402	  (match_operator 4 "arm_comparison_operator"
7403	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7404	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7405	  (match_operator:SI 5 "arm_comparison_operator"
7406	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7407	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7408	 (const_int 0)))]
7409  "TARGET_ARM"
7410  "*
7411{
7412  static const char *const opcodes[4][2] =
7413  {
7414    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7415     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7416    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7417     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7418    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7419     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7420    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7421     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7422  };
7423  int swap =
7424    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7425
7426  return opcodes[which_alternative][swap];
7427}
7428"
7429  [(set_attr "conds" "set")
7430   (set_attr "length" "8")]
7431)
7432
7433(define_insn "*negscc"
7434  [(set (match_operand:SI 0 "s_register_operand" "=r")
7435	(neg:SI (match_operator 3 "arm_comparison_operator"
7436		 [(match_operand:SI 1 "s_register_operand" "r")
7437		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7438   (clobber (reg:CC CC_REGNUM))]
7439  "TARGET_ARM"
7440  "*
7441  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7442    return \"mov\\t%0, %1, asr #31\";
7443
7444  if (GET_CODE (operands[3]) == NE)
7445    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7446
7447  if (GET_CODE (operands[3]) == GT)
7448    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7449
7450  output_asm_insn (\"cmp\\t%1, %2\", operands);
7451  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7452  return \"mvn%d3\\t%0, #0\";
7453  "
7454  [(set_attr "conds" "clob")
7455   (set_attr "length" "12")]
7456)
7457
7458(define_insn "movcond"
7459  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7460	(if_then_else:SI
7461	 (match_operator 5 "arm_comparison_operator"
7462	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
7463	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7464	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7465	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7466   (clobber (reg:CC CC_REGNUM))]
7467  "TARGET_ARM"
7468  "*
7469  if (GET_CODE (operands[5]) == LT
7470      && (operands[4] == const0_rtx))
7471    {
7472      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7473	{
7474	  if (operands[2] == const0_rtx)
7475	    return \"and\\t%0, %1, %3, asr #31\";
7476	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7477	}
7478      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7479	{
7480	  if (operands[1] == const0_rtx)
7481	    return \"bic\\t%0, %2, %3, asr #31\";
7482	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7483	}
7484      /* The only case that falls through to here is when both ops 1 & 2
7485	 are constants */
7486    }
7487
7488  if (GET_CODE (operands[5]) == GE
7489      && (operands[4] == const0_rtx))
7490    {
7491      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7492	{
7493	  if (operands[2] == const0_rtx)
7494	    return \"bic\\t%0, %1, %3, asr #31\";
7495	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7496	}
7497      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7498	{
7499	  if (operands[1] == const0_rtx)
7500	    return \"and\\t%0, %2, %3, asr #31\";
7501	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7502	}
7503      /* The only case that falls through to here is when both ops 1 & 2
7504	 are constants */
7505    }
7506  if (GET_CODE (operands[4]) == CONST_INT
7507      && !const_ok_for_arm (INTVAL (operands[4])))
7508    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7509  else
7510    output_asm_insn (\"cmp\\t%3, %4\", operands);
7511  if (which_alternative != 0)
7512    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7513  if (which_alternative != 1)
7514    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7515  return \"\";
7516  "
7517  [(set_attr "conds" "clob")
7518   (set_attr "length" "8,8,12")]
7519)
7520
7521(define_insn "*ifcompare_plus_move"
7522  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7523	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7524			  [(match_operand:SI 4 "s_register_operand" "r,r")
7525			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7526			 (plus:SI
7527			  (match_operand:SI 2 "s_register_operand" "r,r")
7528			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7529			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7530   (clobber (reg:CC CC_REGNUM))]
7531  "TARGET_ARM"
7532  "#"
7533  [(set_attr "conds" "clob")
7534   (set_attr "length" "8,12")]
7535)
7536
7537(define_insn "*if_plus_move"
7538  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7539	(if_then_else:SI
7540	 (match_operator 4 "arm_comparison_operator"
7541	  [(match_operand 5 "cc_register" "") (const_int 0)])
7542	 (plus:SI
7543	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7544	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7545	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7546  "TARGET_ARM"
7547  "@
7548   add%d4\\t%0, %2, %3
7549   sub%d4\\t%0, %2, #%n3
7550   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7551   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7552  [(set_attr "conds" "use")
7553   (set_attr "length" "4,4,8,8")
7554   (set_attr "type" "*,*,*,*")]
7555)
7556
7557(define_insn "*ifcompare_move_plus"
7558  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7559	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7560			  [(match_operand:SI 4 "s_register_operand" "r,r")
7561			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7562			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7563			 (plus:SI
7564			  (match_operand:SI 2 "s_register_operand" "r,r")
7565			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7566   (clobber (reg:CC CC_REGNUM))]
7567  "TARGET_ARM"
7568  "#"
7569  [(set_attr "conds" "clob")
7570   (set_attr "length" "8,12")]
7571)
7572
7573(define_insn "*if_move_plus"
7574  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7575	(if_then_else:SI
7576	 (match_operator 4 "arm_comparison_operator"
7577	  [(match_operand 5 "cc_register" "") (const_int 0)])
7578	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7579	 (plus:SI
7580	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7581	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7582  "TARGET_ARM"
7583  "@
7584   add%D4\\t%0, %2, %3
7585   sub%D4\\t%0, %2, #%n3
7586   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7587   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7588  [(set_attr "conds" "use")
7589   (set_attr "length" "4,4,8,8")
7590   (set_attr "type" "*,*,*,*")]
7591)
7592
7593(define_insn "*ifcompare_arith_arith"
7594  [(set (match_operand:SI 0 "s_register_operand" "=r")
7595	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
7596			  [(match_operand:SI 5 "s_register_operand" "r")
7597			   (match_operand:SI 6 "arm_add_operand" "rIL")])
7598			 (match_operator:SI 8 "shiftable_operator"
7599			  [(match_operand:SI 1 "s_register_operand" "r")
7600			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7601			 (match_operator:SI 7 "shiftable_operator"
7602			  [(match_operand:SI 3 "s_register_operand" "r")
7603			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7604   (clobber (reg:CC CC_REGNUM))]
7605  "TARGET_ARM"
7606  "#"
7607  [(set_attr "conds" "clob")
7608   (set_attr "length" "12")]
7609)
7610
7611(define_insn "*if_arith_arith"
7612  [(set (match_operand:SI 0 "s_register_operand" "=r")
7613	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
7614			  [(match_operand 8 "cc_register" "") (const_int 0)])
7615			 (match_operator:SI 6 "shiftable_operator"
7616			  [(match_operand:SI 1 "s_register_operand" "r")
7617			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
7618			 (match_operator:SI 7 "shiftable_operator"
7619			  [(match_operand:SI 3 "s_register_operand" "r")
7620			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7621  "TARGET_ARM"
7622  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7623  [(set_attr "conds" "use")
7624   (set_attr "length" "8")]
7625)
7626
7627(define_insn "*ifcompare_arith_move"
7628  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7629	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7630			  [(match_operand:SI 2 "s_register_operand" "r,r")
7631			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7632			 (match_operator:SI 7 "shiftable_operator"
7633			  [(match_operand:SI 4 "s_register_operand" "r,r")
7634			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7635			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7636   (clobber (reg:CC CC_REGNUM))]
7637  "TARGET_ARM"
7638  "*
7639  /* If we have an operation where (op x 0) is the identity operation and
7640     the conditional operator is LT or GE and we are comparing against zero and
7641     everything is in registers then we can do this in two instructions */
7642  if (operands[3] == const0_rtx
7643      && GET_CODE (operands[7]) != AND
7644      && GET_CODE (operands[5]) == REG
7645      && GET_CODE (operands[1]) == REG 
7646      && REGNO (operands[1]) == REGNO (operands[4])
7647      && REGNO (operands[4]) != REGNO (operands[0]))
7648    {
7649      if (GET_CODE (operands[6]) == LT)
7650	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7651      else if (GET_CODE (operands[6]) == GE)
7652	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7653    }
7654  if (GET_CODE (operands[3]) == CONST_INT
7655      && !const_ok_for_arm (INTVAL (operands[3])))
7656    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7657  else
7658    output_asm_insn (\"cmp\\t%2, %3\", operands);
7659  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7660  if (which_alternative != 0)
7661    return \"mov%D6\\t%0, %1\";
7662  return \"\";
7663  "
7664  [(set_attr "conds" "clob")
7665   (set_attr "length" "8,12")]
7666)
7667
7668(define_insn "*if_arith_move"
7669  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7670	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
7671			  [(match_operand 6 "cc_register" "") (const_int 0)])
7672			 (match_operator:SI 5 "shiftable_operator"
7673			  [(match_operand:SI 2 "s_register_operand" "r,r")
7674			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7675			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7676  "TARGET_ARM"
7677  "@
7678   %I5%d4\\t%0, %2, %3
7679   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7680  [(set_attr "conds" "use")
7681   (set_attr "length" "4,8")
7682   (set_attr "type" "*,*")]
7683)
7684
7685(define_insn "*ifcompare_move_arith"
7686  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7687	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
7688			  [(match_operand:SI 4 "s_register_operand" "r,r")
7689			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7690			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7691			 (match_operator:SI 7 "shiftable_operator"
7692			  [(match_operand:SI 2 "s_register_operand" "r,r")
7693			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7694   (clobber (reg:CC CC_REGNUM))]
7695  "TARGET_ARM"
7696  "*
7697  /* If we have an operation where (op x 0) is the identity operation and
7698     the conditional operator is LT or GE and we are comparing against zero and
7699     everything is in registers then we can do this in two instructions */
7700  if (operands[5] == const0_rtx
7701      && GET_CODE (operands[7]) != AND
7702      && GET_CODE (operands[3]) == REG
7703      && GET_CODE (operands[1]) == REG 
7704      && REGNO (operands[1]) == REGNO (operands[2])
7705      && REGNO (operands[2]) != REGNO (operands[0]))
7706    {
7707      if (GET_CODE (operands[6]) == GE)
7708	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7709      else if (GET_CODE (operands[6]) == LT)
7710	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7711    }
7712
7713  if (GET_CODE (operands[5]) == CONST_INT
7714      && !const_ok_for_arm (INTVAL (operands[5])))
7715    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7716  else
7717    output_asm_insn (\"cmp\\t%4, %5\", operands);
7718
7719  if (which_alternative != 0)
7720    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7721  return \"%I7%D6\\t%0, %2, %3\";
7722  "
7723  [(set_attr "conds" "clob")
7724   (set_attr "length" "8,12")]
7725)
7726
7727(define_insn "*if_move_arith"
7728  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7729	(if_then_else:SI
7730	 (match_operator 4 "arm_comparison_operator"
7731	  [(match_operand 6 "cc_register" "") (const_int 0)])
7732	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7733	 (match_operator:SI 5 "shiftable_operator"
7734	  [(match_operand:SI 2 "s_register_operand" "r,r")
7735	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7736  "TARGET_ARM"
7737  "@
7738   %I5%D4\\t%0, %2, %3
7739   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7740  [(set_attr "conds" "use")
7741   (set_attr "length" "4,8")
7742   (set_attr "type" "*,*")]
7743)
7744
7745(define_insn "*ifcompare_move_not"
7746  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7747	(if_then_else:SI
7748	 (match_operator 5 "arm_comparison_operator"
7749	  [(match_operand:SI 3 "s_register_operand" "r,r")
7750	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7751	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7752	 (not:SI
7753	  (match_operand:SI 2 "s_register_operand" "r,r"))))
7754   (clobber (reg:CC CC_REGNUM))]
7755  "TARGET_ARM"
7756  "#"
7757  [(set_attr "conds" "clob")
7758   (set_attr "length" "8,12")]
7759)
7760
7761(define_insn "*if_move_not"
7762  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7763	(if_then_else:SI
7764	 (match_operator 4 "arm_comparison_operator"
7765	  [(match_operand 3 "cc_register" "") (const_int 0)])
7766	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7767	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7768  "TARGET_ARM"
7769  "@
7770   mvn%D4\\t%0, %2
7771   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7772   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7773  [(set_attr "conds" "use")
7774   (set_attr "length" "4,8,8")]
7775)
7776
7777(define_insn "*ifcompare_not_move"
7778  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7779	(if_then_else:SI 
7780	 (match_operator 5 "arm_comparison_operator"
7781	  [(match_operand:SI 3 "s_register_operand" "r,r")
7782	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7783	 (not:SI
7784	  (match_operand:SI 2 "s_register_operand" "r,r"))
7785	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7786   (clobber (reg:CC CC_REGNUM))]
7787  "TARGET_ARM"
7788  "#"
7789  [(set_attr "conds" "clob")
7790   (set_attr "length" "8,12")]
7791)
7792
7793(define_insn "*if_not_move"
7794  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7795	(if_then_else:SI
7796	 (match_operator 4 "arm_comparison_operator"
7797	  [(match_operand 3 "cc_register" "") (const_int 0)])
7798	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7799	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7800  "TARGET_ARM"
7801  "@
7802   mvn%d4\\t%0, %2
7803   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7804   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7805  [(set_attr "conds" "use")
7806   (set_attr "length" "4,8,8")]
7807)
7808
7809(define_insn "*ifcompare_shift_move"
7810  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7811	(if_then_else:SI
7812	 (match_operator 6 "arm_comparison_operator"
7813	  [(match_operand:SI 4 "s_register_operand" "r,r")
7814	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7815	 (match_operator:SI 7 "shift_operator"
7816	  [(match_operand:SI 2 "s_register_operand" "r,r")
7817	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7818	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7819   (clobber (reg:CC CC_REGNUM))]
7820  "TARGET_ARM"
7821  "#"
7822  [(set_attr "conds" "clob")
7823   (set_attr "length" "8,12")]
7824)
7825
7826(define_insn "*if_shift_move"
7827  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7828	(if_then_else:SI
7829	 (match_operator 5 "arm_comparison_operator"
7830	  [(match_operand 6 "cc_register" "") (const_int 0)])
7831	 (match_operator:SI 4 "shift_operator"
7832	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7833	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7834	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7835  "TARGET_ARM"
7836  "@
7837   mov%d5\\t%0, %2%S4
7838   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7839   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7840  [(set_attr "conds" "use")
7841   (set_attr "shift" "2")
7842   (set_attr "length" "4,8,8")]
7843)
7844
7845(define_insn "*ifcompare_move_shift"
7846  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7847	(if_then_else:SI
7848	 (match_operator 6 "arm_comparison_operator"
7849	  [(match_operand:SI 4 "s_register_operand" "r,r")
7850	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7851	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7852	 (match_operator:SI 7 "shift_operator"
7853	  [(match_operand:SI 2 "s_register_operand" "r,r")
7854	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7855   (clobber (reg:CC CC_REGNUM))]
7856  "TARGET_ARM"
7857  "#"
7858  [(set_attr "conds" "clob")
7859   (set_attr "length" "8,12")]
7860)
7861
7862(define_insn "*if_move_shift"
7863  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7864	(if_then_else:SI
7865	 (match_operator 5 "arm_comparison_operator"
7866	  [(match_operand 6 "cc_register" "") (const_int 0)])
7867	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7868	 (match_operator:SI 4 "shift_operator"
7869	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
7870	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7871  "TARGET_ARM"
7872  "@
7873   mov%D5\\t%0, %2%S4
7874   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7875   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7876  [(set_attr "conds" "use")
7877   (set_attr "shift" "2")
7878   (set_attr "length" "4,8,8")]
7879)
7880
7881(define_insn "*ifcompare_shift_shift"
7882  [(set (match_operand:SI 0 "s_register_operand" "=r")
7883	(if_then_else:SI
7884	 (match_operator 7 "arm_comparison_operator"
7885	  [(match_operand:SI 5 "s_register_operand" "r")
7886	   (match_operand:SI 6 "arm_add_operand" "rIL")])
7887	 (match_operator:SI 8 "shift_operator"
7888	  [(match_operand:SI 1 "s_register_operand" "r")
7889	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7890	 (match_operator:SI 9 "shift_operator"
7891	  [(match_operand:SI 3 "s_register_operand" "r")
7892	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7893   (clobber (reg:CC CC_REGNUM))]
7894  "TARGET_ARM"
7895  "#"
7896  [(set_attr "conds" "clob")
7897   (set_attr "length" "12")]
7898)
7899
7900(define_insn "*if_shift_shift"
7901  [(set (match_operand:SI 0 "s_register_operand" "=r")
7902	(if_then_else:SI
7903	 (match_operator 5 "arm_comparison_operator"
7904	  [(match_operand 8 "cc_register" "") (const_int 0)])
7905	 (match_operator:SI 6 "shift_operator"
7906	  [(match_operand:SI 1 "s_register_operand" "r")
7907	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
7908	 (match_operator:SI 7 "shift_operator"
7909	  [(match_operand:SI 3 "s_register_operand" "r")
7910	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7911  "TARGET_ARM"
7912  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7913  [(set_attr "conds" "use")
7914   (set_attr "shift" "1")
7915   (set_attr "length" "8")]
7916)
7917
7918(define_insn "*ifcompare_not_arith"
7919  [(set (match_operand:SI 0 "s_register_operand" "=r")
7920	(if_then_else:SI
7921	 (match_operator 6 "arm_comparison_operator"
7922	  [(match_operand:SI 4 "s_register_operand" "r")
7923	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7924	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7925	 (match_operator:SI 7 "shiftable_operator"
7926	  [(match_operand:SI 2 "s_register_operand" "r")
7927	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7928   (clobber (reg:CC CC_REGNUM))]
7929  "TARGET_ARM"
7930  "#"
7931  [(set_attr "conds" "clob")
7932   (set_attr "length" "12")]
7933)
7934
7935(define_insn "*if_not_arith"
7936  [(set (match_operand:SI 0 "s_register_operand" "=r")
7937	(if_then_else:SI
7938	 (match_operator 5 "arm_comparison_operator"
7939	  [(match_operand 4 "cc_register" "") (const_int 0)])
7940	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7941	 (match_operator:SI 6 "shiftable_operator"
7942	  [(match_operand:SI 2 "s_register_operand" "r")
7943	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7944  "TARGET_ARM"
7945  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7946  [(set_attr "conds" "use")
7947   (set_attr "length" "8")]
7948)
7949
7950(define_insn "*ifcompare_arith_not"
7951  [(set (match_operand:SI 0 "s_register_operand" "=r")
7952	(if_then_else:SI
7953	 (match_operator 6 "arm_comparison_operator"
7954	  [(match_operand:SI 4 "s_register_operand" "r")
7955	   (match_operand:SI 5 "arm_add_operand" "rIL")])
7956	 (match_operator:SI 7 "shiftable_operator"
7957	  [(match_operand:SI 2 "s_register_operand" "r")
7958	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7959	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7960   (clobber (reg:CC CC_REGNUM))]
7961  "TARGET_ARM"
7962  "#"
7963  [(set_attr "conds" "clob")
7964   (set_attr "length" "12")]
7965)
7966
7967(define_insn "*if_arith_not"
7968  [(set (match_operand:SI 0 "s_register_operand" "=r")
7969	(if_then_else:SI
7970	 (match_operator 5 "arm_comparison_operator"
7971	  [(match_operand 4 "cc_register" "") (const_int 0)])
7972	 (match_operator:SI 6 "shiftable_operator"
7973	  [(match_operand:SI 2 "s_register_operand" "r")
7974	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
7975	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7976  "TARGET_ARM"
7977  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7978  [(set_attr "conds" "use")
7979   (set_attr "length" "8")]
7980)
7981
7982(define_insn "*ifcompare_neg_move"
7983  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7984	(if_then_else:SI
7985	 (match_operator 5 "arm_comparison_operator"
7986	  [(match_operand:SI 3 "s_register_operand" "r,r")
7987	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7988	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7989	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7990   (clobber (reg:CC CC_REGNUM))]
7991  "TARGET_ARM"
7992  "#"
7993  [(set_attr "conds" "clob")
7994   (set_attr "length" "8,12")]
7995)
7996
7997(define_insn "*if_neg_move"
7998  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7999	(if_then_else:SI
8000	 (match_operator 4 "arm_comparison_operator"
8001	  [(match_operand 3 "cc_register" "") (const_int 0)])
8002	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8003	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8004  "TARGET_ARM"
8005  "@
8006   rsb%d4\\t%0, %2, #0
8007   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8008   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8009  [(set_attr "conds" "use")
8010   (set_attr "length" "4,8,8")]
8011)
8012
8013(define_insn "*ifcompare_move_neg"
8014  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8015	(if_then_else:SI
8016	 (match_operator 5 "arm_comparison_operator"
8017	  [(match_operand:SI 3 "s_register_operand" "r,r")
8018	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8019	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8020	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8021   (clobber (reg:CC CC_REGNUM))]
8022  "TARGET_ARM"
8023  "#"
8024  [(set_attr "conds" "clob")
8025   (set_attr "length" "8,12")]
8026)
8027
8028(define_insn "*if_move_neg"
8029  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8030	(if_then_else:SI
8031	 (match_operator 4 "arm_comparison_operator"
8032	  [(match_operand 3 "cc_register" "") (const_int 0)])
8033	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8034	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8035  "TARGET_ARM"
8036  "@
8037   rsb%D4\\t%0, %2, #0
8038   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8039   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8040  [(set_attr "conds" "use")
8041   (set_attr "length" "4,8,8")]
8042)
8043
8044(define_insn "*arith_adjacentmem"
8045  [(set (match_operand:SI 0 "s_register_operand" "=r")
8046	(match_operator:SI 1 "shiftable_operator"
8047	 [(match_operand:SI 2 "memory_operand" "m")
8048	  (match_operand:SI 3 "memory_operand" "m")]))
8049   (clobber (match_scratch:SI 4 "=r"))]
8050  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8051  "*
8052  {
8053    rtx ldm[3];
8054    rtx arith[4];
8055    int val1 = 0, val2 = 0;
8056
8057    if (REGNO (operands[0]) > REGNO (operands[4]))
8058      {
8059	ldm[1] = operands[4];
8060	ldm[2] = operands[0];
8061      }
8062    else
8063      {
8064	ldm[1] = operands[0];
8065	ldm[2] = operands[4];
8066      }
8067    if (GET_CODE (XEXP (operands[2], 0)) != REG)
8068      val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8069    if (GET_CODE (XEXP (operands[3], 0)) != REG)
8070      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8071    arith[0] = operands[0];
8072    arith[3] = operands[1];
8073    if (val1 < val2)
8074      {
8075	arith[1] = ldm[1];
8076	arith[2] = ldm[2];
8077      }
8078    else
8079      {
8080	arith[1] = ldm[2];
8081	arith[2] = ldm[1];
8082      }
8083   if (val1 && val2)
8084      {
8085	rtx ops[3];
8086	ldm[0] = ops[0] = operands[4];
8087	ops[1] = XEXP (XEXP (operands[2], 0), 0);
8088	ops[2] = XEXP (XEXP (operands[2], 0), 1);
8089	output_add_immediate (ops);
8090	if (val1 < val2)
8091	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8092	else
8093	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8094      }
8095    else if (val1)
8096      {
8097	ldm[0] = XEXP (operands[3], 0);
8098	if (val1 < val2)
8099	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8100	else
8101	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8102      }
8103    else
8104      {
8105	ldm[0] = XEXP (operands[2], 0);
8106	if (val1 < val2)
8107	  output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8108	else
8109	  output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8110      }
8111    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8112    return \"\";
8113  }"
8114  [(set_attr "length" "12")
8115   (set_attr "predicable" "yes")
8116   (set_attr "type" "load")]
8117)
8118
8119;; the arm can support extended pre-inc instructions
8120
8121;; In all these cases, we use operands 0 and 1 for the register being
8122;; incremented because those are the operands that local-alloc will
8123;; tie and these are the pair most likely to be tieable (and the ones
8124;; that will benefit the most).
8125
8126;; We reject the frame pointer if it occurs anywhere in these patterns since
8127;; elimination will cause too many headaches.
8128
8129(define_insn "*strqi_preinc"
8130  [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8131			 (match_operand:SI 2 "index_operand" "rJ")))
8132	(match_operand:QI 3 "s_register_operand" "r"))
8133   (set (match_operand:SI 0 "s_register_operand" "=r")
8134	(plus:SI (match_dup 1) (match_dup 2)))]
8135  "TARGET_ARM
8136   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8137   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8138   && (GET_CODE (operands[2]) != REG
8139       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8140  "str%?b\\t%3, [%0, %2]!"
8141  [(set_attr "type" "store1")
8142   (set_attr "predicable" "yes")]
8143)
8144
8145(define_insn "*strqi_predec"
8146  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8147			  (match_operand:SI 2 "s_register_operand" "r")))
8148	(match_operand:QI 3 "s_register_operand" "r"))
8149   (set (match_operand:SI 0 "s_register_operand" "=r")
8150	(minus:SI (match_dup 1) (match_dup 2)))]
8151  "TARGET_ARM
8152   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8153   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8154   && (GET_CODE (operands[2]) != REG
8155       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8156  "str%?b\\t%3, [%0, -%2]!"
8157  [(set_attr "type" "store1")
8158   (set_attr "predicable" "yes")]
8159)
8160
8161(define_insn "*loadqi_preinc"
8162  [(set (match_operand:QI 3 "s_register_operand" "=r")
8163	(mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8164			 (match_operand:SI 2 "index_operand" "rJ"))))
8165   (set (match_operand:SI 0 "s_register_operand" "=r")
8166	(plus:SI (match_dup 1) (match_dup 2)))]
8167  "TARGET_ARM
8168   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8169   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8170   && (GET_CODE (operands[2]) != REG
8171       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8172  "ldr%?b\\t%3, [%0, %2]!"
8173  [(set_attr "type" "load")
8174   (set_attr "predicable" "yes")]
8175)
8176
8177(define_insn "*loadqi_predec"
8178  [(set (match_operand:QI 3 "s_register_operand" "=r")
8179	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8180			  (match_operand:SI 2 "s_register_operand" "r"))))
8181   (set (match_operand:SI 0 "s_register_operand" "=r")
8182	(minus:SI (match_dup 1) (match_dup 2)))]
8183  "TARGET_ARM
8184   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8185   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8186   && (GET_CODE (operands[2]) != REG
8187       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8188  "ldr%?b\\t%3, [%0, -%2]!"
8189  [(set_attr "type" "load")
8190   (set_attr "predicable" "yes")]
8191)
8192
8193(define_insn "*loadqisi_preinc"
8194  [(set (match_operand:SI 3 "s_register_operand" "=r")
8195	(zero_extend:SI
8196	 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8197			  (match_operand:SI 2 "index_operand" "rJ")))))
8198   (set (match_operand:SI 0 "s_register_operand" "=r")
8199	(plus:SI (match_dup 1) (match_dup 2)))]
8200  "TARGET_ARM
8201   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8202   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8203   && (GET_CODE (operands[2]) != REG
8204       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8205  "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8206  [(set_attr "type" "load")
8207   (set_attr "predicable" "yes")]
8208)
8209
8210(define_insn "*loadqisi_predec"
8211  [(set (match_operand:SI 3 "s_register_operand" "=r")
8212	(zero_extend:SI
8213	 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8214			   (match_operand:SI 2 "s_register_operand" "r")))))
8215   (set (match_operand:SI 0 "s_register_operand" "=r")
8216	(minus:SI (match_dup 1) (match_dup 2)))]
8217  "TARGET_ARM
8218   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8219   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8220   && (GET_CODE (operands[2]) != REG
8221       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8222  "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8223  [(set_attr "type" "load")
8224   (set_attr "predicable" "yes")]
8225)
8226
8227(define_insn "*strsi_preinc"
8228  [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8229			 (match_operand:SI 2 "index_operand" "rJ")))
8230	(match_operand:SI 3 "s_register_operand" "r"))
8231   (set (match_operand:SI 0 "s_register_operand" "=r")
8232	(plus:SI (match_dup 1) (match_dup 2)))]
8233  "TARGET_ARM
8234   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8235   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8236   && (GET_CODE (operands[2]) != REG
8237       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8238  "str%?\\t%3, [%0, %2]!"
8239  [(set_attr "type" "store1")
8240   (set_attr "predicable" "yes")]
8241)
8242
8243(define_insn "*strsi_predec"
8244  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8245			  (match_operand:SI 2 "s_register_operand" "r")))
8246	(match_operand:SI 3 "s_register_operand" "r"))
8247   (set (match_operand:SI 0 "s_register_operand" "=r")
8248	(minus:SI (match_dup 1) (match_dup 2)))]
8249  "TARGET_ARM
8250   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8251   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8252   && (GET_CODE (operands[2]) != REG
8253       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8254  "str%?\\t%3, [%0, -%2]!"
8255  [(set_attr "type" "store1")
8256   (set_attr "predicable" "yes")]
8257)
8258
8259(define_insn "*loadsi_preinc"
8260  [(set (match_operand:SI 3 "s_register_operand" "=r")
8261	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8262			 (match_operand:SI 2 "index_operand" "rJ"))))
8263   (set (match_operand:SI 0 "s_register_operand" "=r")
8264	(plus:SI (match_dup 1) (match_dup 2)))]
8265  "TARGET_ARM
8266   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8267   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8268   && (GET_CODE (operands[2]) != REG
8269       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8270  "ldr%?\\t%3, [%0, %2]!"
8271  [(set_attr "type" "load")
8272   (set_attr "predicable" "yes")]
8273)
8274
8275(define_insn "*loadsi_predec"
8276  [(set (match_operand:SI 3 "s_register_operand" "=r")
8277	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8278			  (match_operand:SI 2 "s_register_operand" "r"))))
8279   (set (match_operand:SI 0 "s_register_operand" "=r")
8280	(minus:SI (match_dup 1) (match_dup 2)))]
8281  "TARGET_ARM
8282   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8283   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8284   && (GET_CODE (operands[2]) != REG
8285       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8286  "ldr%?\\t%3, [%0, -%2]!"
8287  [(set_attr "type" "load")
8288   (set_attr "predicable" "yes")]
8289)
8290
8291(define_insn "*loadhi_preinc"
8292  [(set (match_operand:HI 3 "s_register_operand" "=r")
8293	(mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8294			 (match_operand:SI 2 "index_operand" "rJ"))))
8295   (set (match_operand:SI 0 "s_register_operand" "=r")
8296	(plus:SI (match_dup 1) (match_dup 2)))]
8297  "TARGET_ARM
8298   && !BYTES_BIG_ENDIAN
8299   && !TARGET_MMU_TRAPS
8300   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8301   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8302   && (GET_CODE (operands[2]) != REG
8303       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8304  "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8305  [(set_attr "type" "load")
8306   (set_attr "predicable" "yes")]
8307)
8308
8309(define_insn "*loadhi_predec"
8310  [(set (match_operand:HI 3 "s_register_operand" "=r")
8311	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8312			  (match_operand:SI 2 "s_register_operand" "r"))))
8313   (set (match_operand:SI 0 "s_register_operand" "=r")
8314	(minus:SI (match_dup 1) (match_dup 2)))]
8315  "TARGET_ARM
8316   && !BYTES_BIG_ENDIAN
8317   && !TARGET_MMU_TRAPS
8318   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8319   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8320   && (GET_CODE (operands[2]) != REG
8321       || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8322  "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8323  [(set_attr "type" "load")
8324   (set_attr "predicable" "yes")]
8325)
8326
8327(define_insn "*strqi_shiftpreinc"
8328  [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8329			  [(match_operand:SI 3 "s_register_operand" "r")
8330			   (match_operand:SI 4 "const_shift_operand" "n")])
8331			 (match_operand:SI 1 "s_register_operand" "0")))
8332	(match_operand:QI 5 "s_register_operand" "r"))
8333   (set (match_operand:SI 0 "s_register_operand" "=r")
8334	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8335		 (match_dup 1)))]
8336  "TARGET_ARM
8337   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8338   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8339   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8340  "str%?b\\t%5, [%0, %3%S2]!"
8341  [(set_attr "type" "store1")
8342   (set_attr "predicable" "yes")]
8343)
8344
8345(define_insn "*strqi_shiftpredec"
8346  [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8347			  (match_operator:SI 2 "shift_operator"
8348			   [(match_operand:SI 3 "s_register_operand" "r")
8349			    (match_operand:SI 4 "const_shift_operand" "n")])))
8350	(match_operand:QI 5 "s_register_operand" "r"))
8351   (set (match_operand:SI 0 "s_register_operand" "=r")
8352	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8353						 (match_dup 4)])))]
8354  "TARGET_ARM
8355   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8356   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8357   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8358  "str%?b\\t%5, [%0, -%3%S2]!"
8359  [(set_attr "type" "store1")
8360   (set_attr "predicable" "yes")]
8361)
8362
8363(define_insn "*loadqi_shiftpreinc"
8364  [(set (match_operand:QI 5 "s_register_operand" "=r")
8365	(mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8366			  [(match_operand:SI 3 "s_register_operand" "r")
8367			   (match_operand:SI 4 "const_shift_operand" "n")])
8368			 (match_operand:SI 1 "s_register_operand" "0"))))
8369   (set (match_operand:SI 0 "s_register_operand" "=r")
8370	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8371		 (match_dup 1)))]
8372  "TARGET_ARM
8373   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8374   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8375   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8376  "ldr%?b\\t%5, [%0, %3%S2]!"
8377  [(set_attr "type" "load")
8378   (set_attr "predicable" "yes")]
8379)
8380
8381(define_insn "*loadqi_shiftpredec"
8382  [(set (match_operand:QI 5 "s_register_operand" "=r")
8383	(mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8384			  (match_operator:SI 2 "shift_operator"
8385			   [(match_operand:SI 3 "s_register_operand" "r")
8386			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8387   (set (match_operand:SI 0 "s_register_operand" "=r")
8388	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8389						 (match_dup 4)])))]
8390  "TARGET_ARM
8391   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8392   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8393   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8394  "ldr%?b\\t%5, [%0, -%3%S2]!"
8395  [(set_attr "type" "load")
8396   (set_attr "predicable" "yes")]
8397)
8398
8399(define_insn "*strsi_shiftpreinc"
8400  [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8401			  [(match_operand:SI 3 "s_register_operand" "r")
8402			   (match_operand:SI 4 "const_shift_operand" "n")])
8403			 (match_operand:SI 1 "s_register_operand" "0")))
8404	(match_operand:SI 5 "s_register_operand" "r"))
8405   (set (match_operand:SI 0 "s_register_operand" "=r")
8406	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8407		 (match_dup 1)))]
8408  "TARGET_ARM
8409   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8410   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8411   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8412  "str%?\\t%5, [%0, %3%S2]!"
8413  [(set_attr "type" "store1")
8414   (set_attr "predicable" "yes")]
8415)
8416
8417(define_insn "*strsi_shiftpredec"
8418  [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8419			  (match_operator:SI 2 "shift_operator"
8420			   [(match_operand:SI 3 "s_register_operand" "r")
8421			    (match_operand:SI 4 "const_shift_operand" "n")])))
8422	(match_operand:SI 5 "s_register_operand" "r"))
8423   (set (match_operand:SI 0 "s_register_operand" "=r")
8424	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8425						 (match_dup 4)])))]
8426  "TARGET_ARM
8427   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8428   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8429   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8430  "str%?\\t%5, [%0, -%3%S2]!"
8431  [(set_attr "type" "store1")
8432   (set_attr "predicable" "yes")]
8433)
8434
8435(define_insn "*loadsi_shiftpreinc"
8436  [(set (match_operand:SI 5 "s_register_operand" "=r")
8437	(mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8438			  [(match_operand:SI 3 "s_register_operand" "r")
8439			   (match_operand:SI 4 "const_shift_operand" "n")])
8440			 (match_operand:SI 1 "s_register_operand" "0"))))
8441   (set (match_operand:SI 0 "s_register_operand" "=r")
8442	(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8443		 (match_dup 1)))]
8444  "TARGET_ARM
8445   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8446   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8447   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8448  "ldr%?\\t%5, [%0, %3%S2]!"
8449  [(set_attr "type" "load")
8450   (set_attr "predicable" "yes")]
8451)
8452
8453(define_insn "*loadsi_shiftpredec"
8454  [(set (match_operand:SI 5 "s_register_operand" "=r")
8455	(mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8456			  (match_operator:SI 2 "shift_operator"
8457			   [(match_operand:SI 3 "s_register_operand" "r")
8458			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8459   (set (match_operand:SI 0 "s_register_operand" "=r")
8460	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8461						 (match_dup 4)])))]
8462  "TARGET_ARM
8463   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8464   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8465   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8466  "ldr%?\\t%5, [%0, -%3%S2]!"
8467  [(set_attr "type" "load")
8468   (set_attr "predicable" "yes")])
8469
8470(define_insn "*loadhi_shiftpreinc"
8471  [(set (match_operand:HI 5 "s_register_operand" "=r")
8472	(mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8473			  [(match_operand:SI 3 "s_register_operand" "r")
8474			   (match_operand:SI 4 "const_shift_operand" "n")])
8475			 (match_operand:SI 1 "s_register_operand" "0"))))
8476   (set (match_operand:SI 0 "s_register_operand" "=r")
8477	(plus:SI (match_op_dup 2 [(match_dup 3)	(match_dup 4)])
8478		 (match_dup 1)))]
8479  "TARGET_ARM
8480   && !BYTES_BIG_ENDIAN
8481   && !TARGET_MMU_TRAPS
8482   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8483   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8484   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8485  "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8486  [(set_attr "type" "load")
8487   (set_attr "predicable" "yes")]
8488)
8489
8490(define_insn "*loadhi_shiftpredec"
8491  [(set (match_operand:HI 5 "s_register_operand" "=r")
8492	(mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8493			  (match_operator:SI 2 "shift_operator"
8494			   [(match_operand:SI 3 "s_register_operand" "r")
8495			    (match_operand:SI 4 "const_shift_operand" "n")]))))
8496   (set (match_operand:SI 0 "s_register_operand" "=r")
8497	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8498						 (match_dup 4)])))]
8499  "TARGET_ARM
8500   && !BYTES_BIG_ENDIAN
8501   && !TARGET_MMU_TRAPS
8502   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8503   && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8504   && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8505  "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8506  [(set_attr "type" "load")
8507   (set_attr "predicable" "yes")]
8508)
8509
8510; It can also support extended post-inc expressions, but combine doesn't
8511; try these....
8512; It doesn't seem worth adding peepholes for anything but the most common
8513; cases since, unlike combine, the increment must immediately follow the load
8514; for this pattern to match.
8515; We must watch to see that the source/destination register isn't also the
8516; same as the base address register, and that if the index is a register,
8517; that it is not the same as the base address register.  In such cases the
8518; instruction that we would generate would have UNPREDICTABLE behaviour so 
8519; we cannot use it.
8520
8521(define_peephole
8522  [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8523	(match_operand:QI 2 "s_register_operand" "r"))
8524   (set (match_dup 0)
8525	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8526  "TARGET_ARM
8527   && (REGNO (operands[2]) != REGNO (operands[0]))
8528   && (GET_CODE (operands[1]) != REG
8529       || (REGNO (operands[1]) != REGNO (operands[0])))"
8530  "str%?b\\t%2, [%0], %1"
8531)
8532
8533(define_peephole
8534  [(set (match_operand:QI 0 "s_register_operand" "=r")
8535	(mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8536   (set (match_dup 1)
8537	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8538  "TARGET_ARM
8539   && REGNO (operands[0]) != REGNO(operands[1])
8540   && (GET_CODE (operands[2]) != REG
8541       || REGNO(operands[0]) != REGNO (operands[2]))"
8542  "ldr%?b\\t%0, [%1], %2"
8543)
8544
8545(define_peephole
8546  [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8547	(match_operand:SI 2 "s_register_operand" "r"))
8548   (set (match_dup 0)
8549	(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8550  "TARGET_ARM
8551   && (REGNO (operands[2]) != REGNO (operands[0]))
8552   && (GET_CODE (operands[1]) != REG
8553       || (REGNO (operands[1]) != REGNO (operands[0])))"
8554  "str%?\\t%2, [%0], %1"
8555)
8556
8557(define_peephole
8558  [(set (match_operand:HI 0 "s_register_operand" "=r")
8559	(mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8560   (set (match_dup 1)
8561	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8562  "TARGET_ARM
8563   && !BYTES_BIG_ENDIAN
8564   && !TARGET_MMU_TRAPS
8565   && REGNO (operands[0]) != REGNO(operands[1])
8566   && (GET_CODE (operands[2]) != REG
8567       || REGNO(operands[0]) != REGNO (operands[2]))"
8568  "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8569)
8570
8571(define_peephole
8572  [(set (match_operand:SI 0 "s_register_operand" "=r")
8573	(mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8574   (set (match_dup 1)
8575	(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8576  "TARGET_ARM
8577   && REGNO (operands[0]) != REGNO(operands[1])
8578   && (GET_CODE (operands[2]) != REG
8579       || REGNO(operands[0]) != REGNO (operands[2]))"
8580  "ldr%?\\t%0, [%1], %2"
8581)
8582
8583(define_peephole
8584  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8585			 (match_operand:SI 1 "index_operand" "rJ")))
8586	(match_operand:QI 2 "s_register_operand" "r"))
8587   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8588  "TARGET_ARM
8589   && (REGNO (operands[2]) != REGNO (operands[0]))
8590   && (GET_CODE (operands[1]) != REG
8591       || (REGNO (operands[1]) != REGNO (operands[0])))"
8592  "str%?b\\t%2, [%0, %1]!"
8593)
8594
8595(define_peephole
8596  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8597			  [(match_operand:SI 0 "s_register_operand" "r")
8598			   (match_operand:SI 1 "const_int_operand" "n")])
8599			 (match_operand:SI 2 "s_register_operand" "+r")))
8600	(match_operand:QI 3 "s_register_operand" "r"))
8601   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8602			       (match_dup 2)))]
8603  "TARGET_ARM
8604   && (REGNO (operands[3]) != REGNO (operands[2]))
8605   && (REGNO (operands[0]) != REGNO (operands[2]))"
8606  "str%?b\\t%3, [%2, %0%S4]!"
8607)
8608
8609; This pattern is never tried by combine, so do it as a peephole
8610
8611(define_peephole2
8612  [(set (match_operand:SI 0 "s_register_operand" "")
8613	(match_operand:SI 1 "s_register_operand" ""))
8614   (set (reg:CC CC_REGNUM)
8615	(compare:CC (match_dup 1) (const_int 0)))]
8616  "TARGET_ARM
8617  "
8618  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8619	      (set (match_dup 0) (match_dup 1))])]
8620  ""
8621)
8622
8623; Peepholes to spot possible load- and store-multiples, if the ordering is
8624; reversed, check that the memory references aren't volatile.
8625
8626(define_peephole
8627  [(set (match_operand:SI 0 "s_register_operand" "=r")
8628        (match_operand:SI 4 "memory_operand" "m"))
8629   (set (match_operand:SI 1 "s_register_operand" "=r")
8630        (match_operand:SI 5 "memory_operand" "m"))
8631   (set (match_operand:SI 2 "s_register_operand" "=r")
8632        (match_operand:SI 6 "memory_operand" "m"))
8633   (set (match_operand:SI 3 "s_register_operand" "=r")
8634        (match_operand:SI 7 "memory_operand" "m"))]
8635  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8636  "*
8637  return emit_ldm_seq (operands, 4);
8638  "
8639)
8640
8641(define_peephole
8642  [(set (match_operand:SI 0 "s_register_operand" "=r")
8643        (match_operand:SI 3 "memory_operand" "m"))
8644   (set (match_operand:SI 1 "s_register_operand" "=r")
8645        (match_operand:SI 4 "memory_operand" "m"))
8646   (set (match_operand:SI 2 "s_register_operand" "=r")
8647        (match_operand:SI 5 "memory_operand" "m"))]
8648  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8649  "*
8650  return emit_ldm_seq (operands, 3);
8651  "
8652)
8653
8654(define_peephole
8655  [(set (match_operand:SI 0 "s_register_operand" "=r")
8656        (match_operand:SI 2 "memory_operand" "m"))
8657   (set (match_operand:SI 1 "s_register_operand" "=r")
8658        (match_operand:SI 3 "memory_operand" "m"))]
8659  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8660  "*
8661  return emit_ldm_seq (operands, 2);
8662  "
8663)
8664
8665(define_peephole
8666  [(set (match_operand:SI 4 "memory_operand" "=m")
8667        (match_operand:SI 0 "s_register_operand" "r"))
8668   (set (match_operand:SI 5 "memory_operand" "=m")
8669        (match_operand:SI 1 "s_register_operand" "r"))
8670   (set (match_operand:SI 6 "memory_operand" "=m")
8671        (match_operand:SI 2 "s_register_operand" "r"))
8672   (set (match_operand:SI 7 "memory_operand" "=m")
8673        (match_operand:SI 3 "s_register_operand" "r"))]
8674  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8675  "*
8676  return emit_stm_seq (operands, 4);
8677  "
8678)
8679
8680(define_peephole
8681  [(set (match_operand:SI 3 "memory_operand" "=m")
8682        (match_operand:SI 0 "s_register_operand" "r"))
8683   (set (match_operand:SI 4 "memory_operand" "=m")
8684        (match_operand:SI 1 "s_register_operand" "r"))
8685   (set (match_operand:SI 5 "memory_operand" "=m")
8686        (match_operand:SI 2 "s_register_operand" "r"))]
8687  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8688  "*
8689  return emit_stm_seq (operands, 3);
8690  "
8691)
8692
8693(define_peephole
8694  [(set (match_operand:SI 2 "memory_operand" "=m")
8695        (match_operand:SI 0 "s_register_operand" "r"))
8696   (set (match_operand:SI 3 "memory_operand" "=m")
8697        (match_operand:SI 1 "s_register_operand" "r"))]
8698  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8699  "*
8700  return emit_stm_seq (operands, 2);
8701  "
8702)
8703
8704(define_split
8705  [(set (match_operand:SI 0 "s_register_operand" "")
8706	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8707		       (const_int 0))
8708		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
8709			 [(match_operand:SI 3 "s_register_operand" "")
8710			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
8711   (clobber (match_operand:SI 5 "s_register_operand" ""))]
8712  "TARGET_ARM"
8713  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8714   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8715			      (match_dup 5)))]
8716  ""
8717)
8718
8719;; This split can be used because CC_Z mode implies that the following
8720;; branch will be an equality, or an unsigned inequality, so the sign
8721;; extension is not needed.
8722
8723(define_split
8724  [(set (reg:CC_Z CC_REGNUM)
8725	(compare:CC_Z
8726	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8727		    (const_int 24))
8728	 (match_operand 1 "const_int_operand" "")))
8729   (clobber (match_scratch:SI 2 ""))]
8730  "TARGET_ARM
8731   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8732       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8733  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8734   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8735  "
8736  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8737  "
8738)
8739
8740(define_expand "prologue"
8741  [(clobber (const_int 0))]
8742  "TARGET_EITHER"
8743  "if (TARGET_ARM)
8744     arm_expand_prologue ();
8745   else
8746     thumb_expand_prologue ();
8747  DONE;
8748  "
8749)
8750
8751(define_expand "epilogue"
8752  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8753  "TARGET_EITHER"
8754  "
8755  if (TARGET_THUMB)
8756    thumb_expand_epilogue ();
8757  else if (USE_RETURN_INSN (FALSE))
8758    {
8759      emit_jump_insn (gen_return ());
8760      DONE;
8761    }
8762  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8763	gen_rtvec (1,
8764		gen_rtx_RETURN (VOIDmode)),
8765	VUNSPEC_EPILOGUE));
8766  DONE;
8767  "
8768)
8769
8770(define_insn "sibcall_epilogue"
8771  [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8772  "TARGET_ARM"
8773  "*
8774  output_asm_insn (\"%@ Sibcall epilogue\", operands);
8775  if (USE_RETURN_INSN (FALSE))
8776    return output_return_instruction (NULL, FALSE, FALSE);
8777  return arm_output_epilogue (FALSE);
8778  "
8779;; Length is absolute worst case
8780  [(set_attr "length" "44")
8781   (set_attr "type" "block")]
8782)
8783
8784(define_insn "*epilogue_insns"
8785  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8786  "TARGET_EITHER"
8787  "*
8788  if (TARGET_ARM)
8789    return arm_output_epilogue (TRUE);
8790  else /* TARGET_THUMB */
8791    return thumb_unexpanded_epilogue ();
8792  "
8793  ; Length is absolute worst case
8794  [(set_attr "length" "44")
8795   (set_attr "type" "block")]
8796)
8797
8798(define_expand "eh_epilogue"
8799  [(use (match_operand:SI 0 "register_operand" "r"))
8800   (use (match_operand:SI 1 "register_operand" "r"))
8801   (use (match_operand:SI 2 "register_operand" "r"))]
8802  "TARGET_EITHER"
8803  "
8804  {
8805    cfun->machine->eh_epilogue_sp_ofs = operands[1];
8806    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8807      {
8808	rtx ra = gen_rtx_REG (Pmode, 2);
8809
8810	emit_move_insn (ra, operands[2]);
8811	operands[2] = ra;
8812      }
8813    /* This is a hack -- we may have crystalized the function type too
8814       early.  */
8815    cfun->machine->func_type = 0;
8816  }"
8817)
8818
8819;; This split is only used during output to reduce the number of patterns
8820;; that need assembler instructions adding to them.  We allowed the setting
8821;; of the conditions to be implicit during rtl generation so that
8822;; the conditional compare patterns would work.  However this conflicts to
8823;; some extent with the conditional data operations, so we have to split them
8824;; up again here.
8825
8826(define_split
8827  [(set (match_operand:SI 0 "s_register_operand" "")
8828	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8829			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8830			 (match_dup 0)
8831			 (match_operand 4 "" "")))
8832   (clobber (reg:CC CC_REGNUM))]
8833  "TARGET_ARM && reload_completed"
8834  [(set (match_dup 5) (match_dup 6))
8835   (cond_exec (match_dup 7)
8836	      (set (match_dup 0) (match_dup 4)))]
8837  "
8838  {
8839    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8840					     operands[2], operands[3]);
8841    enum rtx_code rc = GET_CODE (operands[1]);
8842
8843    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8844    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8845    if (mode == CCFPmode || mode == CCFPEmode)
8846      rc = reverse_condition_maybe_unordered (rc);
8847    else
8848      rc = reverse_condition (rc);
8849
8850    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8851  }"
8852)
8853
8854(define_split
8855  [(set (match_operand:SI 0 "s_register_operand" "")
8856	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8857			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8858			 (match_operand 4 "" "")
8859			 (match_dup 0)))
8860   (clobber (reg:CC CC_REGNUM))]
8861  "TARGET_ARM && reload_completed"
8862  [(set (match_dup 5) (match_dup 6))
8863   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8864	      (set (match_dup 0) (match_dup 4)))]
8865  "
8866  {
8867    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8868					     operands[2], operands[3]);
8869
8870    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8871    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8872  }"
8873)
8874
8875(define_split
8876  [(set (match_operand:SI 0 "s_register_operand" "")
8877	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8878			  [(match_operand 2 "" "") (match_operand 3 "" "")])
8879			 (match_operand 4 "" "")
8880			 (match_operand 5 "" "")))
8881   (clobber (reg:CC CC_REGNUM))]
8882  "TARGET_ARM && reload_completed"
8883  [(set (match_dup 6) (match_dup 7))
8884   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8885	      (set (match_dup 0) (match_dup 4)))
8886   (cond_exec (match_dup 8)
8887	      (set (match_dup 0) (match_dup 5)))]
8888  "
8889  {
8890    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8891					     operands[2], operands[3]);
8892    enum rtx_code rc = GET_CODE (operands[1]);
8893
8894    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8895    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8896    if (mode == CCFPmode || mode == CCFPEmode)
8897      rc = reverse_condition_maybe_unordered (rc);
8898    else
8899      rc = reverse_condition (rc);
8900
8901    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8902  }"
8903)
8904
8905(define_split
8906  [(set (match_operand:SI 0 "s_register_operand" "")
8907	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
8908			  [(match_operand:SI 2 "s_register_operand" "")
8909			   (match_operand:SI 3 "arm_add_operand" "")])
8910			 (match_operand:SI 4 "arm_rhs_operand" "")
8911			 (not:SI
8912			  (match_operand:SI 5 "s_register_operand" ""))))
8913   (clobber (reg:CC CC_REGNUM))]
8914  "TARGET_ARM && reload_completed"
8915  [(set (match_dup 6) (match_dup 7))
8916   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8917	      (set (match_dup 0) (match_dup 4)))
8918   (cond_exec (match_dup 8)
8919	      (set (match_dup 0) (not:SI (match_dup 5))))]
8920  "
8921  {
8922    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8923					     operands[2], operands[3]);
8924    enum rtx_code rc = GET_CODE (operands[1]);
8925
8926    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8927    operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8928    if (mode == CCFPmode || mode == CCFPEmode)
8929      rc = reverse_condition_maybe_unordered (rc);
8930    else
8931      rc = reverse_condition (rc);
8932
8933    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8934  }"
8935)
8936
8937(define_insn "*cond_move_not"
8938  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8939	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
8940			  [(match_operand 3 "cc_register" "") (const_int 0)])
8941			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8942			 (not:SI
8943			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
8944  "TARGET_ARM"
8945  "@
8946   mvn%D4\\t%0, %2
8947   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8948  [(set_attr "conds" "use")
8949   (set_attr "length" "4,8")]
8950)
8951
8952;; The next two patterns occur when an AND operation is followed by a
8953;; scc insn sequence 
8954
8955(define_insn "*sign_extract_onebit"
8956  [(set (match_operand:SI 0 "s_register_operand" "=r")
8957	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8958			 (const_int 1)
8959			 (match_operand:SI 2 "const_int_operand" "n")))]
8960  "TARGET_ARM"
8961  "*
8962    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8963    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8964    return \"mvnne\\t%0, #0\";
8965  "
8966  [(set_attr "conds" "clob")
8967   (set_attr "length" "8")]
8968)
8969
8970(define_insn "*not_signextract_onebit"
8971  [(set (match_operand:SI 0 "s_register_operand" "=r")
8972	(not:SI
8973	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8974			  (const_int 1)
8975			  (match_operand:SI 2 "const_int_operand" "n"))))]
8976  "TARGET_ARM"
8977  "*
8978    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8979    output_asm_insn (\"tst\\t%1, %2\", operands);
8980    output_asm_insn (\"mvneq\\t%0, #0\", operands);
8981    return \"movne\\t%0, #0\";
8982  "
8983  [(set_attr "conds" "clob")
8984   (set_attr "length" "12")]
8985)
8986
8987;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8988;; expressions.  For simplicity, the first register is also in the unspec
8989;; part.
8990(define_insn "*push_multi"
8991  [(match_parallel 2 "multi_register_push"
8992    [(set (match_operand:BLK 0 "memory_operand" "=m")
8993	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8994		      UNSPEC_PUSH_MULT))])]
8995  "TARGET_ARM"
8996  "*
8997  {
8998    int num_saves = XVECLEN (operands[2], 0);
8999     
9000    /* For the StrongARM at least it is faster to
9001       use STR to store only a single register.  */
9002    if (num_saves == 1)
9003      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9004    else
9005      {
9006	int i;
9007	char pattern[100];
9008
9009	strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9010
9011	for (i = 1; i < num_saves; i++)
9012	  {
9013	    strcat (pattern, \", %|\");
9014	    strcat (pattern,
9015		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9016	  }
9017
9018	strcat (pattern, \"}\");
9019	output_asm_insn (pattern, operands);
9020      }
9021
9022    return \"\";
9023  }"
9024  [(set_attr "type" "store4")]
9025)
9026
9027;; Similarly for the floating point registers
9028(define_insn "*push_fp_multi"
9029  [(match_parallel 2 "multi_register_push"
9030    [(set (match_operand:BLK 0 "memory_operand" "=m")
9031	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9032		      UNSPEC_PUSH_MULT))])]
9033  "TARGET_ARM"
9034  "*
9035  {
9036    char pattern[100];
9037
9038    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9039    output_asm_insn (pattern, operands);
9040    return \"\";
9041  }"
9042  [(set_attr "type" "f_store")]
9043)
9044
9045;; Special patterns for dealing with the constant pool
9046
9047(define_insn "align_4"
9048  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9049  "TARGET_EITHER"
9050  "*
9051  assemble_align (32);
9052  return \"\";
9053  "
9054)
9055
9056(define_insn "consttable_end"
9057  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9058  "TARGET_EITHER"
9059  "*
9060  making_const_table = FALSE;
9061  return \"\";
9062  "
9063)
9064
9065(define_insn "consttable_1"
9066  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9067  "TARGET_THUMB"
9068  "*
9069  making_const_table = TRUE;
9070  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9071  assemble_zeros (3);
9072  return \"\";
9073  "
9074  [(set_attr "length" "4")]
9075)
9076
9077(define_insn "consttable_2"
9078  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9079  "TARGET_THUMB"
9080  "*
9081  making_const_table = TRUE;
9082  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9083  assemble_zeros (2);
9084  return \"\";
9085  "
9086  [(set_attr "length" "4")]
9087)
9088
9089(define_insn "consttable_4"
9090  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9091  "TARGET_EITHER"
9092  "*
9093  {
9094    making_const_table = TRUE;
9095    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9096      {
9097      case MODE_FLOAT:
9098      {
9099        union real_extract u;
9100        memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9101        assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9102        break;
9103      }
9104      default:
9105        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9106        break;
9107      }
9108    return \"\";
9109  }"
9110  [(set_attr "length" "4")]
9111)
9112
9113(define_insn "consttable_8"
9114  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9115  "TARGET_EITHER"
9116  "*
9117  {
9118    making_const_table = TRUE;
9119    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9120      {
9121       case MODE_FLOAT:
9122        {
9123          union real_extract u;
9124          memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9125          assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9126          break;
9127        }
9128      default:
9129        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9130        break;
9131      }
9132    return \"\";
9133  }"
9134  [(set_attr "length" "8")]
9135)
9136
9137;; Miscellaneous Thumb patterns
9138
9139(define_insn "tablejump"
9140  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9141   (use (label_ref (match_operand 1 "" "")))]
9142  "TARGET_THUMB"
9143  "mov	pc, %0"
9144  [(set_attr "length" "2")]
9145)
9146
9147;; V5 Instructions,
9148
9149(define_insn "clz"
9150  [(set (match_operand:SI             0 "s_register_operand" "=r")
9151	(unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9152		   UNSPEC_CLZ))]
9153  "TARGET_ARM && arm_arch5"
9154  "clz\\t%0, %1")
9155
9156(define_expand "ffssi2"
9157  [(set (match_operand:SI 0 "s_register_operand" "")
9158	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9159  "TARGET_ARM && arm_arch5"
9160  "
9161  {
9162    rtx t1, t2, t3;
9163
9164    t1 = gen_reg_rtx (SImode);
9165    t2 = gen_reg_rtx (SImode);
9166    t3 = gen_reg_rtx (SImode);
9167
9168    emit_insn (gen_negsi2 (t1, operands[1]));
9169    emit_insn (gen_andsi3 (t2, operands[1], t1));
9170    emit_insn (gen_clz (t3, t2));
9171    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9172    DONE;
9173  }"
9174)
9175
9176;; V5E instructions.
9177
9178(define_insn "prefetch"
9179  [(prefetch (match_operand:SI 0 "address_operand" "p")
9180	     (match_operand:SI 1 "" "")
9181	     (match_operand:SI 2 "" ""))]
9182  "TARGET_ARM && arm_arch5e"
9183  "pld\\t%a0")
9184
9185;; General predication pattern
9186
9187(define_cond_exec
9188  [(match_operator 0 "arm_comparison_operator"
9189    [(match_operand 1 "cc_register" "")
9190     (const_int 0)])]
9191  "TARGET_ARM"
9192  ""
9193)
9194
9195(define_insn "prologue_use"
9196  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9197  ""
9198  "%@ %0 needed for prologue"
9199)
9200