;;- Machine description for ARM for GNU compiler
;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
;;  2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;;  and Martin Simmons (@harleqn.co.uk).
;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).

;; This file is part of GCC.

;; GCC is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published
;; by the Free Software Foundation; either version 2, or (at your
;; option) any later version.

;; GCC is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING.  If not, write to
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.

;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.


;;---------------------------------------------------------------------------
;; Constants

;; Register numbers
(define_constants
  [(R0_REGNUM        0)		; First CORE register
   (IP_REGNUM	    12)		; Scratch register
   (SP_REGNUM	    13)		; Stack pointer
   (LR_REGNUM       14)		; Return address register
   (PC_REGNUM	    15)		; Program counter
   (CC_REGNUM       24)		; Condition code pseudo register
   (LAST_ARM_REGNUM 15)		;
   (FPA_F0_REGNUM   16)		; FIRST_FPA_REGNUM
   (FPA_F7_REGNUM   23)		; LAST_FPA_REGNUM
  ]
)
;; 3rd operand to select_dominance_cc_mode
(define_constants
  [(DOM_CC_X_AND_Y  0)
   (DOM_CC_NX_OR_Y  1)
   (DOM_CC_X_OR_Y   2)
  ]
)

;; UNSPEC Usage:
;; Note: sin and cos are no-longer used.
;; APPLE LOCAL v7 support. Merge from Codesourcery
;; Unspec constants for Neon are defined in neon.md.

(define_constants
  [(UNSPEC_SIN       0)	; `sin' operation (MODE_FLOAT):
			;   operand 0 is the result,
			;   operand 1 the parameter.
   (UNPSEC_COS	     1)	; `cos' operation (MODE_FLOAT):
			;   operand 0 is the result,
			;   operand 1 the parameter.
   (UNSPEC_PUSH_MULT 2)	; `push multiple' operation:
			;   operand 0 is the first register,
			;   subsequent registers are in parallel (use ...)
			;   expressions.
   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
			;   usage, that is, we will add the pic_register
			;   value to it before trying to dereference it.
   (UNSPEC_PIC_BASE  4)	; Adding the PC value to the offset to the
			;   GLOBAL_OFFSET_TABLE.  The operation is fully
			;   described by the RTL but must be wrapped to
			;   prevent combine from trying to rip it apart.
   (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
			;   being scheduled before the stack adjustment insn.
   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
   			; this unspec is used to prevent the deletion of
   			; instructions setting registers for EH handling
   			; and stack frame generation.  Operand 0 is the
   			; register to "use".
   (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
   (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
   (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
   (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
   (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
   (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
   (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
   (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
   (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
   (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
   (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
   (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
   (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
   (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
   (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
                         ; instruction stream.
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
   (UNSPEC_STACK_ALIGN 22) ; Doubleword aligned stack pointer.  Used to
         ; generate correct unwind information.
   ; APPLE LOCAL ARM setjmp/longjmp interworking
   (UNSPEC_JMP_XCHG 23) ; Indirect jump with possible change in ARM/Thumb state.
;; APPLE LOCAL end v7 support. Merge from Codesourcery
   ; APPLE LOCAL ARM UXTB support
   (UNSPEC_UXTB16   27) ; The UXTB16 instruction (ARM only)
;; APPLE LOCAL begin 6258536 atomic builtins
   (UNSPEC_CMPXCHG  28) ; Atomic compare and swap operations
   (UNSPEC_BARRIER  29) ; memory barrier
   (UNSPEC_SYNC     30) ; memory sync
;; APPLE LOCAL end 6258536 atomic builtins
  ]
)

;; UNSPEC_VOLATILE Usage:

(define_constants
  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
			;   insn in the code.
   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
			;   instruction epilogue sequence that isn't expanded
			;   into normal RTL.  Used for both normal and sibcall
			;   epilogues.
   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
			;   for inlined constants.
   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
			;   table.
   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
			;   an 8-bit object.
   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
			;   a 16-bit object.
   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
			;   a 32-bit object.
   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
			;   a 64-bit object.
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
   (VUNSPEC_POOL_16  8) ; `pool-entry(16)'.  An entry in the constant pool for
			;   a 128-bit object.
   (VUNSPEC_TMRC     9) ; Used by the iWMMXt TMRC instruction.
   (VUNSPEC_TMCR     10) ; Used by the iWMMXt TMCR instruction.
   (VUNSPEC_ALIGN8   11) ; 8-byte alignment version of VUNSPEC_ALIGN
   (VUNSPEC_WCMP_EQ  12) ; Used by the iWMMXt WCMPEQ instructions
   (VUNSPEC_WCMP_GTU 13) ; Used by the iWMMXt WCMPGTU instructions
   (VUNSPEC_WCMP_GT  14) ; Used by the iwMMXT WCMPGT instructions
;; APPLE LOCAL end v7 support. Merge from Codesourcery
   (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
			 ; handling.
			    ; APPLE LOCAL begin ARM strings in code
   (VUNSPEC_POOL_STRING 21) ; `pool-entry(string)'.  An entry in the constant
			    ;   pool for a string.
			    ; APPLE LOCAL end ARM strings in code
;; APPLE LOCAL begin 6258536 atomic builtins
   (VUNSPEC_LL 22)          ; Load locked (ldrex)
   (VUNSPEC_SC 22)          ; Store conditional (strex)
;; APPLE LOCAL end 6258536 atomic builtins
  ]
)

;;---------------------------------------------------------------------------
;; Attributes

; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
; generating ARM code.  This is used to control the length of some insn
; patterns that share the same RTL in both ARM and Thumb code.
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))

; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
; scheduling decisions for the load unit and the multiplier.
(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))

; IS_XSCALE is set to 'yes' when compiling for XScale.
(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))

;; Operand number of an input operand that is shifted.  Zero if the
;; given instruction does not shift one of its input operands.
(define_attr "shift" "" (const_int 0))

; Floating Point Unit.  If we only have floating point emulation, then there
; is no point in scheduling the floating point insns.  (Well, for best
; performance we should try and group them together).
(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
  (const (symbol_ref "arm_fpu_attr")))

; LENGTH of an instruction (in bytes)
(define_attr "length" "" (const_int 4))

; POOL_RANGE is how far away from a constant pool entry that this insn
; can be placed.  If the distance is zero, then this insn will never
; reference the pool.
; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
; before its address.
(define_attr "pool_range" "" (const_int 0))
(define_attr "neg_pool_range" "" (const_int 0))

; An assembler sequence may clobber the condition codes without us knowing.
; If such an insn references the pool, then we have no way of knowing how,
; so use the most conservative value for pool_range.
(define_asm_attributes
 [(set_attr "conds" "clob")
  (set_attr "length" "4")
  (set_attr "pool_range" "250")])

;; The instruction used to implement a particular pattern.  This
;; information is used by pipeline descriptions to provide accurate
;; scheduling information.

(define_attr "insn"
;; APPLE LOCAL v7 support. Merge from Codesourcery
        "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,smmls,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
        (const_string "other"))

; TYPE attribute is used to detect floating point instructions which, if
; running on a co-processor can run in parallel with other, basic instructions
; If write-buffer scheduling is enabled then it can also be used in the
; scheduling of writes.

; Classification of each insn
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
; Note: vfp.md has different meanings for some of these, and some further
; types as well.  See that file for details.
;; APPLE LOCAL end v7 support. Merge from Codesourcery
; alu		any alu  instruction that doesn't hit memory or fp
;		regs or have a shifted source operand
; alu_shift	any data instruction that doesn't hit memory or fp
;		regs, but has a source operand shifted by a constant
; alu_shift_reg	any data instruction that doesn't hit memory or fp
;		regs, but has a source operand shifted by a register value
; mult		a multiply instruction
; block		blockage insn, this blocks all functional units
; float		a floating point arithmetic operation (subject to expansion)
; fdivd		DFmode floating point division
; fdivs		SFmode floating point division
; fmul		Floating point multiply
; ffmul		Fast floating point multiply
; farith	Floating point arithmetic (4 cycle)
; ffarith	Fast floating point arithmetic (2 cycle)
; float_em	a floating point arithmetic operation that is normally emulated
;		even on a machine with an fpa.
; f_load	a floating point load from memory
; f_store	a floating point store to memory
; f_load[sd]	single/double load from memory
; f_store[sd]	single/double store to memory
; f_flag	a transfer of co-processor flags to the CPSR
; f_mem_r	a transfer of a floating point register to a real reg via mem
; r_mem_f	the reverse of f_mem_r
; f_2_r		fast transfer float to arm (no memory needed)
; r_2_f		fast transfer arm to float
; f_cvt		convert floating<->integral
; branch	a branch
; call		a subroutine call
; load_byte	load byte(s) from memory to arm registers
; load1		load 1 word from memory to arm registers
; load2         load 2 words from memory to arm registers
; load3         load 3 words from memory to arm registers
; load4         load 4 words from memory to arm registers
; store		store 1 word to memory from arm registers
; store2	store 2 words
; store3	store 3 words
; store4	store 4 (or more) words
;  Additions for Cirrus Maverick co-processor:
; mav_farith	Floating point arithmetic (4 cycle)
; mav_dmult	Double multiplies (7 cycle)
;
(define_attr "type"
;; APPLE LOCAL v7 support. Merge from Codesourcery
	"alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fmuls,fmuld,fmacs,fmacd"
	(if_then_else 
	 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
	 (const_string "mult")
	 (const_string "alu")))

; Load scheduling, set from the arm_ld_sched variable
; initialized by arm_override_options() 
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))

; condition codes: this one is used by final_prescan_insn to speed up
; conditionalizing instructions.  It saves having to scan the rtl to see if
; it uses or alters the condition codes.
; 
; USE means that the condition codes are used by the insn in the process of
;   outputting code, this means (at present) that we can't use the insn in
;   inlined branches
;
; SET means that the purpose of the insn is to set the condition codes in a
;   well defined manner.
;
; CLOB means that the condition codes are altered in an undefined manner, if
;   they are altered at all
;
; JUMP_CLOB is used when the condition cannot be represented by a single
;   instruction (UNEQ and LTGT).  These cannot be predicated.
;
; NOCOND means that the condition codes are neither altered nor affect the
;   output of this insn

(define_attr "conds" "use,set,clob,jump_clob,nocond"
	(if_then_else (eq_attr "type" "call")
	 (const_string "clob")
	 (const_string "nocond")))

; Predicable means that the insn can be conditionally executed based on
; an automatically added predicate (additional patterns are generated by 
; gen...).  We default to 'no' because no Thumb patterns match this rule
; and not all ARM patterns do.
(define_attr "predicable" "no,yes" (const_string "no"))

; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
; have one.  Later ones, such as StrongARM, have write-back caches, so don't
; suffer blockages enough to warrant modelling this (and it can adversely
; affect the schedule).
(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))

; WRITE_CONFLICT implies that a read following an unrelated write is likely
; to stall the processor.  Used with model_wbuf above.
(define_attr "write_conflict" "no,yes"
  (if_then_else (eq_attr "type"
		 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
		(const_string "yes")
		(const_string "no")))

; Classify the insns into those that take one cycle and those that take more
; than one on the main cpu execution unit.
(define_attr "core_cycles" "single,multi"
  (if_then_else (eq_attr "type"
		 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
		(const_string "single")
	        (const_string "multi")))

;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
;; distant label.  Only applicable to Thumb code.
(define_attr "far_jump" "yes,no" (const_string "no"))


;; APPLE LOCAL begin v7 support. Merge from mainline
;; The number of machine instructions this pattern expands to.
;; Used for Thumb-2 conditional execution.
(define_attr "ce_count" "" (const_int 1))

;; APPLE LOCAL end v7 support. Merge from mainline
;;---------------------------------------------------------------------------
;; Mode macros

; A list of modes that are exactly 64 bits in size.  We use this to expand
; some splits that are the same for all modes when operating on ARM 
; registers.
(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])

;;---------------------------------------------------------------------------
;; Predicates

(include "predicates.md")
(include "constraints.md")

;;---------------------------------------------------------------------------
;; Pipeline descriptions

;; Processor type.  This is created automatically from arm-cores.def.
(include "arm-tune.md")

;; True if the generic scheduling description should be used.

(define_attr "generic_sched" "yes,no"
  (const (if_then_else 
;; APPLE LOCAL v7 support. Merge from Codesourcery
          (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa8,cortexr4") 
          (const_string "no")
          (const_string "yes"))))

(define_attr "generic_vfp" "yes,no"
  (const (if_then_else
	  (and (eq_attr "fpu" "vfp")
;; APPLE LOCAL v7 support. Merge from Codesourcery
	       (eq_attr "tune" "!arm1020e,arm1022e,cortexa8"))
	  (const_string "yes")
	  (const_string "no"))))

(include "arm-generic.md")
(include "arm926ejs.md")
(include "arm1020e.md")
(include "arm1026ejs.md")
(include "arm1136jfs.md")
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
(include "cortex-a8.md")
(include "cortex-r4.md")
(include "vfp11.md")
;; APPLE LOCAL end v7 support. Merge from Codesourcery


;;---------------------------------------------------------------------------
;; Insn patterns
;;
;; Addition insns.

;; Note: For DImode insns, there is normally no reason why operands should
;; not be in the same register, what we don't want is for something being
;; written to partially overlap something that is an input.
;; Cirrus 64bit additions should not be split because we have a native
;; 64bit addition instructions.

;; APPLE LOCAL begin 5831562 long long constants
(define_expand "adddi3"
 [(parallel
   [(set (match_operand:DI           0 "s_register_operand" "")
	  (plus:DI (match_operand:DI 1 "s_register_operand" "")
	           (match_operand:DI 2 "arm_add64_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
  "TARGET_EITHER"
  "
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
    {
      if (!cirrus_fp_register (operands[0], DImode))
        operands[0] = force_reg (DImode, operands[0]);
      if (!cirrus_fp_register (operands[1], DImode))
        operands[1] = force_reg (DImode, operands[1]);
      emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
      DONE;
    }

  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_THUMB1)
    {
      if (GET_CODE (operands[1]) != REG)
        operands[1] = force_reg (SImode, operands[1]);
      if (GET_CODE (operands[2]) != REG)
        operands[2] = force_reg (SImode, operands[2]);
     }

  if (TARGET_ARM 
      && (GET_CODE (operands[2]) == CONST_INT
          || GET_CODE (operands[2]) == CONST_DOUBLE)
      && !const64_ok_for_arm_immediate (operands[2]))
    {
      emit_insn (gen_subdi3 (operands[0], operands[1],
			    negate_rtx (DImode, operands[2])));
      DONE;
    }
  "
)
;; APPLE LOCAL end 5831562 long long constants

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_adddi3"
  [(set (match_operand:DI          0 "register_operand" "=l")
	(plus:DI (match_operand:DI 1 "register_operand" "%0")
		 (match_operand:DI 2 "register_operand" "l")))
   (clobber (reg:CC CC_REGNUM))
  ]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
  [(set_attr "length" "4")]
)

;; APPLE LOCAL begin 5831562 long long constants
(define_insn_and_split "*arm_adddi3"
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r,&r,&r")
	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0")
		 (match_operand:DI 2 "arm_rhs64_operand" "r,  0, Dd,Dd")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(parallel [(set (reg:CC_C CC_REGNUM)
		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
				 (match_dup 1)))
	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
			       (plus:SI (match_dup 4) (match_dup 5))))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)
;; APPLE LOCAL end 5831562 long long constants

(define_insn_and_split "*adddi_sesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(plus:DI (sign_extend:DI
		  (match_operand:SI 2 "s_register_operand" "r,r"))
		 (match_operand:DI 1 "s_register_operand" "r,0")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(parallel [(set (reg:CC_C CC_REGNUM)
		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
				 (match_dup 1)))
	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
			       (plus:SI (ashiftrt:SI (match_dup 2)
						     (const_int 31))
					(match_dup 4))))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn_and_split "*adddi_zesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(plus:DI (zero_extend:DI
		  (match_operand:SI 2 "s_register_operand" "r,r"))
		 (match_operand:DI 1 "s_register_operand" "r,0")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(parallel [(set (reg:CC_C CC_REGNUM)
		   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
				 (match_dup 1)))
	      (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
			       (plus:SI (match_dup 4) (const_int 0))))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_expand "addsi3"
  [(set (match_operand:SI          0 "s_register_operand" "")
	(plus:SI (match_operand:SI 1 "s_register_operand" "")
		 (match_operand:SI 2 "reg_or_int_operand" "")))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
    {
      arm_split_constant (PLUS, SImode, NULL_RTX,
	                  INTVAL (operands[2]), operands[0], operands[1],
			  optimize && !no_new_pseudos);
      DONE;
    }
  "
)

; If there is a scratch available, this will be faster than synthesizing the
; addition.
(define_peephole2
  [(match_scratch:SI 3 "r")
   (set (match_operand:SI          0 "arm_general_register_operand" "")
	(plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
		 (match_operand:SI 2 "const_int_operand"  "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT &&
   !(const_ok_for_arm (INTVAL (operands[2]))
     || const_ok_for_arm (-INTVAL (operands[2])))
    && const_ok_for_arm (~INTVAL (operands[2]))"
  [(set (match_dup 3) (match_dup 2))
   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
  ""
)

(define_insn_and_split "*arm_addsi3"
  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
	(plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
		 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   add%?\\t%0, %1, %2
   sub%?\\t%0, %1, #%n2
   #"
  "TARGET_32BIT &&
   GET_CODE (operands[2]) == CONST_INT
   && !(const_ok_for_arm (INTVAL (operands[2]))
        || const_ok_for_arm (-INTVAL (operands[2])))"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(clobber (const_int 0))]
  "
  arm_split_constant (PLUS, SImode, curr_insn,
	              INTVAL (operands[2]), operands[0],
		      operands[1], 0);
  DONE;
  "
  [(set_attr "length" "4,4,16")
   (set_attr "predicable" "yes")]
)

;; Register group 'k' is a single register group containing only the stack
;; register.  Trying to reload it will always fail catastrophically,
;; so never allow those alternatives to match if reloading is needed.

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_addsi3"
  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
	(plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
		 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
   static const char * const asms[] = 
   {
     \"add\\t%0, %0, %2\",
     \"sub\\t%0, %0, #%n2\",
     \"add\\t%0, %1, %2\",
     \"add\\t%0, %0, %2\",
     \"add\\t%0, %0, %2\",
     \"add\\t%0, %1, %2\",
     \"add\\t%0, %1, %2\"
   };
   if ((which_alternative == 2 || which_alternative == 6)
       && GET_CODE (operands[2]) == CONST_INT
       && INTVAL (operands[2]) < 0)
     return \"sub\\t%0, %1, #%n2\";
   return asms[which_alternative];
  "
  [(set_attr "length" "2")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
;; Reloading and elimination of the frame pointer can
;; sometimes cause this optimization to be missed.
(define_peephole2
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
	(match_operand:SI 1 "const_int_operand" ""))
   (set (match_dup 0)
	(plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
  "TARGET_THUMB1
   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
   && (INTVAL (operands[1]) & 3) == 0"
  [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
  ""
)
;; APPLE LOCAL end v7 support. Merge from mainline

;; APPLE LOCAL begin ARM peephole
;; And sometimes greg will generate the same thing this way...

(define_peephole2
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
	(reg:SI SP_REGNUM))
   (set (match_dup 0)
	(plus:SI (match_dup 0) (match_operand:SI 1 "const_int_operand" "")))]
  "TARGET_THUMB
   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
   && (INTVAL (operands[1]) & 3) == 0"
  [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
  ""
)
;; APPLE LOCAL end ARM peephole

;; APPLE LOCAL v7 support. Merge from mainline
;; ??? Make Thumb-2 variants which prefer low regs
(define_insn "*addsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
		  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(plus:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   add%.\\t%0, %1, %2
   sub%.\\t%0, %1, #%n2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*addsi3_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
		  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
	 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   cmn%?\\t%0, %1
   cmp%?\\t%0, #%n1"
  [(set_attr "conds" "set")]
)

(define_insn "*compare_negsi_si"
  [(set (reg:CC_Z CC_REGNUM)
	(compare:CC_Z
	 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
	 (match_operand:SI 1 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "cmn%?\\t%1, %0"
  [(set_attr "conds" "set")]
)

;; This is the canonicalization of addsi3_compare0_for_combiner when the
;; addend is a constant.
(define_insn "*cmpsi2_addneg"
  [(set (reg:CC CC_REGNUM)
	(compare:CC
	 (match_operand:SI 1 "s_register_operand" "r,r")
	 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(plus:SI (match_dup 1)
		 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
  "@
   sub%.\\t%0, %1, %2
   add%.\\t%0, %1, #%n2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

;; Convert the sequence
;;  sub  rd, rn, #1
;;  cmn  rd, #1	(equivalent to cmp rd, #-1)
;;  bne  dest
;; into
;;  subs rd, rn, #1
;;  bcs  dest	((unsigned)rn >= 1)
;; similarly for the beq variant using bcc.
;; This is a common looping idiom (while (n--))
(define_peephole2
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
	(plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
		 (const_int -1)))
   (set (match_operand 2 "cc_register" "")
	(compare (match_dup 0) (const_int -1)))
   (set (pc)
	(if_then_else (match_operator 3 "equality_operator"
		       [(match_dup 2) (const_int 0)])
		      (match_operand 4 "" "")
		      (match_operand 5 "" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
  [(parallel[
    (set (match_dup 2)
	 (compare:CC
	  (match_dup 1) (const_int 1)))
    (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
   (set (pc)
	(if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
		      (match_dup 4)
		      (match_dup 5)))]
  "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
   operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
				  ? GEU : LTU),
				 VOIDmode, 
				 operands[2], const0_rtx);"
)

;; The next four insns work because they compare the result with one of
;; the operands, and we know that the use of the condition code is
;; either GEU or LTU, so we can use the carry flag from the addition
;; instead of doing the compare a second time.
(define_insn "*addsi3_compare_op1"
  [(set (reg:CC_C CC_REGNUM)
	(compare:CC_C
	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
	 (match_dup 1)))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(plus:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   add%.\\t%0, %1, %2
   sub%.\\t%0, %1, #%n2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*addsi3_compare_op2"
  [(set (reg:CC_C CC_REGNUM)
	(compare:CC_C
	 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
		  (match_operand:SI 2 "arm_add_operand" "rI,L"))
	 (match_dup 2)))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(plus:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   add%.\\t%0, %1, %2
   sub%.\\t%0, %1, #%n2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*compare_addsi2_op0"
  [(set (reg:CC_C CC_REGNUM)
	(compare:CC_C
	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
	 (match_dup 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   cmn%?\\t%0, %1
   cmp%?\\t%0, #%n1"
  [(set_attr "conds" "set")]
)

(define_insn "*compare_addsi2_op1"
  [(set (reg:CC_C CC_REGNUM)
	(compare:CC_C
	 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
		  (match_operand:SI 1 "arm_add_operand" "rI,L"))
	 (match_dup 1)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   cmn%?\\t%0, %1
   cmp%?\\t%0, #%n1"
  [(set_attr "conds" "set")]
)

(define_insn "*addsi3_carryin"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
		 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
			  (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "adc%?\\t%0, %1, %2"
  [(set_attr "conds" "use")]
)

(define_insn "*addsi3_carryin_shift"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
		 (plus:SI
		   (match_operator:SI 2 "shift_operator"
		      [(match_operand:SI 3 "s_register_operand" "r")
		       (match_operand:SI 4 "reg_or_int_operand" "rM")])
		    (match_operand:SI 1 "s_register_operand" "r"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "adc%?\\t%0, %1, %3%S2"
  [(set_attr "conds" "use")
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*addsi3_carryin_alt1"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
		 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "adc%?\\t%0, %1, %2"
  [(set_attr "conds" "use")]
)

(define_insn "*addsi3_carryin_alt2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
			  (match_operand:SI 1 "s_register_operand" "r"))
		 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "adc%?\\t%0, %1, %2"
  [(set_attr "conds" "use")]
)

(define_insn "*addsi3_carryin_alt3"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
			  (match_operand:SI 2 "arm_rhs_operand" "rI"))
		 (match_operand:SI 1 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "adc%?\\t%0, %1, %2"
  [(set_attr "conds" "use")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "incscc"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_incscc"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
  "TARGET_ARM"
  "@
  add%d2\\t%0, %1, #1
  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
			    (match_operand:SI 2 "s_register_operand" ""))
		 (const_int -1)))
   (clobber (match_operand:SI 3 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  [(set (match_dup 3) (match_dup 1))
   (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
  "
  operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
")

(define_expand "addsf3"
  [(set (match_operand:SF          0 "s_register_operand" "")
	(plus:SF (match_operand:SF 1 "s_register_operand" "")
		 (match_operand:SF 2 "arm_float_add_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK
      && !cirrus_fp_register (operands[2], SFmode))
    operands[2] = force_reg (SFmode, operands[2]);
")

(define_expand "adddf3"
  [(set (match_operand:DF          0 "s_register_operand" "")
	(plus:DF (match_operand:DF 1 "s_register_operand" "")
		 (match_operand:DF 2 "arm_float_add_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK
      && !cirrus_fp_register (operands[2], DFmode))
    operands[2] = force_reg (DFmode, operands[2]);
")

;; APPLE LOCAL begin 5831562 long long constants
(define_expand "subdi3"
 [(parallel
   [(set (match_operand:DI            0 "s_register_operand" "")
	  (minus:DI (match_operand:DI 1 "s_register_operand" "")
	            (match_operand:DI 2 "arm_add64_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL begin v7 support. Merge from mainline */
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK
      && TARGET_32BIT
      && cirrus_fp_register (operands[0], DImode)
      && cirrus_fp_register (operands[1], DImode))
    {
      emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
      DONE;
    }

  if (TARGET_THUMB1)
    {
      if (GET_CODE (operands[1]) != REG)
        operands[1] = force_reg (SImode, operands[1]);
      if (GET_CODE (operands[2]) != REG)
        operands[2] = force_reg (SImode, operands[2]);
     }	

  if (TARGET_32BIT
      && (GET_CODE (operands[2]) == CONST_INT
          || GET_CODE (operands[2]) == CONST_DOUBLE)
      && !const64_ok_for_arm_immediate (operands[2]))
    {
      emit_insn (gen_adddi3 (operands[0], operands[1],
                          negate_rtx (DImode, operands[2])));
      DONE;
    }
  /* APPLE LOCAL end v7 support. Merge from mainline */
   "
)

(define_insn "*arm_subdi3"
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r,&r,&r")
	(minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0,r,0")
		  (match_operand:DI 2 "arm_rhs64_operand" "r,0,0,Dd,Dd")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
   if (which_alternative <= 2)
     return \"subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2\";
   else
     {
       operands[3] = gen_lowpart (SImode, operands[2]);
       operands[2] = gen_highpart_mode (SImode, DImode, operands[2]);
       return \"subs\\t%Q0, %Q1, %3\;sbc\\t%R0, %R1, %2\";
     }"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)
;; APPLE LOCAL end 5831562 long long constants

(define_insn "*thumb_subdi3"
  [(set (match_operand:DI           0 "register_operand" "=l")
	(minus:DI (match_operand:DI 1 "register_operand"  "0")
		  (match_operand:DI 2 "register_operand"  "l")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
  [(set_attr "length" "4")]
)

(define_insn "*subdi_di_zesidi"
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
	(minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
		  (zero_extend:DI
		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn "*subdi_di_sesidi"
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
	(minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
		  (sign_extend:DI
		   (match_operand:SI 2 "s_register_operand"  "r,r"))))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn "*subdi_zesidi_di"
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
	(minus:DI (zero_extend:DI
		   (match_operand:SI 2 "s_register_operand"  "r,r"))
		  (match_operand:DI  1 "s_register_operand" "?r,0")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn "*subdi_sesidi_di"
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
	(minus:DI (sign_extend:DI
		   (match_operand:SI 2 "s_register_operand"   "r,r"))
		  (match_operand:DI  1 "s_register_operand"  "?r,0")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn "*subdi_zesidi_zesidi"
  [(set (match_operand:DI            0 "s_register_operand" "=r")
	(minus:DI (zero_extend:DI
		   (match_operand:SI 1 "s_register_operand"  "r"))
		  (zero_extend:DI
		   (match_operand:SI 2 "s_register_operand"  "r"))))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_expand "subsi3"
  [(set (match_operand:SI           0 "s_register_operand" "")
	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
		  (match_operand:SI 2 "s_register_operand" "")))]
  "TARGET_EITHER"
  "
  if (GET_CODE (operands[1]) == CONST_INT)
    {
      /* APPLE LOCAL v7 support. Merge from mainline */
      if (TARGET_32BIT)
        {
          arm_split_constant (MINUS, SImode, NULL_RTX,
	                      INTVAL (operands[1]), operands[0],
	  		      operands[2], optimize && !no_new_pseudos);
          DONE;
	}
      /* APPLE LOCAL v7 support. Merge from mainline */
      else /* TARGET_THUMB1 */
        operands[1] = force_reg (SImode, operands[1]);
    }
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_subsi3_insn"
  [(set (match_operand:SI           0 "register_operand" "=l")
	(minus:SI (match_operand:SI 1 "register_operand" "l")
		  (match_operand:SI 2 "register_operand" "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "sub\\t%0, %1, %2"
  [(set_attr "length" "2")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
; ??? Check Thumb-2 split length
(define_insn_and_split "*arm_subsi3_insn"
  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
		  (match_operand:SI 2 "s_register_operand" "r,r")))]
  "TARGET_32BIT"
  "@
   rsb%?\\t%0, %2, %1
   #"
  "TARGET_32BIT
   && GET_CODE (operands[1]) == CONST_INT
   && !const_ok_for_arm (INTVAL (operands[1]))"
  [(clobber (const_int 0))]
  "
  arm_split_constant (MINUS, SImode, curr_insn,
                      INTVAL (operands[1]), operands[0], operands[2], 0);
  DONE;
  "
  [(set_attr "length" "4,16")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_peephole2
  [(match_scratch:SI 3 "r")
   (set (match_operand:SI 0 "arm_general_register_operand" "")
	(minus:SI (match_operand:SI 1 "const_int_operand" "")
		  (match_operand:SI 2 "arm_general_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && !const_ok_for_arm (INTVAL (operands[1]))
   && const_ok_for_arm (~INTVAL (operands[1]))"
  [(set (match_dup 3) (match_dup 1))
   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
  ""
)

(define_insn "*subsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
		   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(minus:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   sub%.\\t%0, %1, %2
   rsb%.\\t%0, %2, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "decscc"
  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
		  (match_operator:SI 2 "arm_comparison_operator"
                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_decscc"
  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
		  (match_operator:SI 2 "arm_comparison_operator"
                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
  "TARGET_ARM"
  "@
   sub%d2\\t%0, %1, #1
   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
  [(set_attr "conds" "use")
   (set_attr "length" "*,8")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_expand "subsf3"
  [(set (match_operand:SF           0 "s_register_operand" "")
	(minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
		  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
      if (!cirrus_fp_register (operands[1], SFmode))
        operands[1] = force_reg (SFmode, operands[1]);
      if (!cirrus_fp_register (operands[2], SFmode))
        operands[2] = force_reg (SFmode, operands[2]);
    }
")

(define_expand "subdf3"
  [(set (match_operand:DF           0 "s_register_operand" "")
	(minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
		  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
       if (!cirrus_fp_register (operands[1], DFmode))
         operands[1] = force_reg (DFmode, operands[1]);
       if (!cirrus_fp_register (operands[2], DFmode))
         operands[2] = force_reg (DFmode, operands[2]);
    }
")


;; Multiplication insns

(define_expand "mulsi3"
  [(set (match_operand:SI          0 "s_register_operand" "")
	(mult:SI (match_operand:SI 2 "s_register_operand" "")
		 (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_EITHER"
  ""
)

;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
(define_insn "*arm_mulsi3"
  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
	(mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
		 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && !arm_arch6"
  "mul%?\\t%0, %2, %1"
  [(set_attr "insn" "mul")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*arm_mulsi3_v6"
  [(set (match_operand:SI          0 "s_register_operand" "=r")
	(mult:SI (match_operand:SI 1 "s_register_operand" "r")
		 (match_operand:SI 2 "s_register_operand" "r")))]
  "TARGET_32BIT && arm_arch6"
  "mul%?\\t%0, %1, %2"
  [(set_attr "insn" "mul")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

;; APPLE LOCAL begin v7 support. Merge from Codesourcery
; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
; 1 and 2; are the same, because reload will make operand 0 match 
; operand 1 without realizing that this conflicts with operand 2.  We fix 
; this by adding another alternative to match this case, and then `reload' 
; it ourselves.  This alternative must come first.
(define_insn "*thumb_mulsi3"
  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
	(mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
		 (match_operand:SI 2 "register_operand" "l,l,l")))]
  "TARGET_THUMB1 && !arm_arch6"
  "*
  if (which_alternative < 2)
    return \"mov\\t%0, %1\;mul\\t%0, %2\";
  else
    return \"mul\\t%0, %2\";
  "
  [(set_attr "length" "4,4,2")
   (set_attr "insn" "mul")]
)
;; APPLE LOCAL end v7 support. Merge from Codesourcery

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*thumb_mulsi3_v6"
  [(set (match_operand:SI          0 "register_operand" "=l,l,l")
	(mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
		 (match_operand:SI 2 "register_operand" "l,0,0")))]
  "TARGET_THUMB1 && arm_arch6"
  "@
   mul\\t%0, %2
   mul\\t%0, %1
   mul\\t%0, %1"
  [(set_attr "length" "2")
   (set_attr "insn" "mul")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*mulsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (mult:SI
			  (match_operand:SI 2 "s_register_operand" "r,r")
			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
	(mult:SI (match_dup 2) (match_dup 1)))]
  "TARGET_ARM && !arm_arch6"
  "mul%.\\t%0, %2, %1"
  [(set_attr "conds" "set")
   (set_attr "insn" "muls")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*mulsi3_compare0_v6"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (mult:SI
			  (match_operand:SI 2 "s_register_operand" "r")
			  (match_operand:SI 1 "s_register_operand" "r"))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(mult:SI (match_dup 2) (match_dup 1)))]
;; APPLE LOCAL 6040923 unrecognizable insn ICE
  "TARGET_ARM && arm_arch6"
  "mul%.\\t%0, %2, %1"
  [(set_attr "conds" "set")
   (set_attr "insn" "muls")]
)

(define_insn "*mulsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (mult:SI
			  (match_operand:SI 2 "s_register_operand" "r,r")
			  (match_operand:SI 1 "s_register_operand" "%?r,0"))
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=&r,&r"))]
  "TARGET_ARM && !arm_arch6"
  "mul%.\\t%0, %2, %1"
  [(set_attr "conds" "set")
   (set_attr "insn" "muls")]
)

(define_insn "*mulsi_compare0_scratch_v6"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (mult:SI
			  (match_operand:SI 2 "s_register_operand" "r")
			  (match_operand:SI 1 "s_register_operand" "r"))
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
;; APPLE LOCAL 6040923 unrecognizable insn ICE
  "TARGET_ARM && arm_arch6"
  "mul%.\\t%0, %2, %1"
  [(set_attr "conds" "set")
   (set_attr "insn" "muls")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

;; Unnamed templates to match MLA instruction.

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*mulsi3addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
	(plus:SI
	  (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
	  (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
  "TARGET_32BIT && !arm_arch6"
  "mla%?\\t%0, %2, %1, %3"
  [(set_attr "insn" "mla")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulsi3addsi_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI
	  (mult:SI (match_operand:SI 2 "s_register_operand" "r")
		   (match_operand:SI 1 "s_register_operand" "r"))
	  (match_operand:SI 3 "s_register_operand" "r")))]
  "TARGET_32BIT && arm_arch6"
  "mla%?\\t%0, %2, %1, %3"
  [(set_attr "insn" "mla")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "*mulsi3addsi_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (mult:SI
		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
		 (match_dup 3)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_ARM && arm_arch6"
  "mla%.\\t%0, %2, %1, %3"
  [(set_attr "conds" "set")
   (set_attr "insn" "mlas")]
)

(define_insn "*mulsi3addsi_compare0_v6"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (mult:SI
		   (match_operand:SI 2 "s_register_operand" "r")
		   (match_operand:SI 1 "s_register_operand" "r"))
		  (match_operand:SI 3 "s_register_operand" "r"))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (mult:SI (match_dup 2) (match_dup 1))
		 (match_dup 3)))]
  "TARGET_ARM && arm_arch6 && optimize_size"
  "mla%.\\t%0, %2, %1, %3"
  [(set_attr "conds" "set")
   (set_attr "insn" "mlas")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "*mulsi3addsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (mult:SI
		   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
		   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
		  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
	 (const_int 0)))
   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_ARM && !arm_arch6"
  "mla%.\\t%0, %2, %1, %3"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")
   (set_attr "insn" "mlas")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*mulsi3addsi_compare0_scratch_v6"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (plus:SI (mult:SI
		   (match_operand:SI 2 "s_register_operand" "r")
		   (match_operand:SI 1 "s_register_operand" "r"))
		  (match_operand:SI 3 "s_register_operand" "r"))
	 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
  "TARGET_ARM && arm_arch6 && optimize_size"
  "mla%.\\t%0, %2, %1, %3"
  [(set_attr "conds" "set")
   (set_attr "insn" "mlas")]
)

(define_insn "*mulsi3subsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(minus:SI
	  (match_operand:SI 3 "s_register_operand" "r")
	  (mult:SI (match_operand:SI 2 "s_register_operand" "r")
		   (match_operand:SI 1 "s_register_operand" "r"))))]
  "TARGET_32BIT && arm_arch_thumb2"
  "mls%?\\t%0, %2, %1, %3"
  [(set_attr "insn" "mla")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL end v7 support. Merge from mainline
;; Unnamed template to match long long multiply-accumulate (smlal)

(define_insn "*mulsidi3adddi"
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
	(plus:DI
	 (mult:DI
	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
	 (match_operand:DI 1 "s_register_operand" "0")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
  "smlal%?\\t%Q0, %R0, %3, %2"
  [(set_attr "insn" "smlal")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulsidi3adddi_v6"
  [(set (match_operand:DI 0 "s_register_operand" "=r")
	(plus:DI
	 (mult:DI
	  (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
	  (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
	 (match_operand:DI 1 "s_register_operand" "0")))]
  "TARGET_32BIT && arm_arch6"
  "smlal%?\\t%Q0, %R0, %3, %2"
  [(set_attr "insn" "smlal")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "mulsidi3"
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
	(mult:DI
	 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
	 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m"
  "smull%?\\t%Q0, %R0, %1, %2"
  [(set_attr "insn" "smull")
   (set_attr "predicable" "yes")]
)

(define_insn "umulsidi3"
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
	(mult:DI
	 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
	 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m"
  "umull%?\\t%Q0, %R0, %1, %2"
  [(set_attr "insn" "umull")
   (set_attr "predicable" "yes")]
)

;; Unnamed template to match long long unsigned multiply-accumulate (umlal)

(define_insn "*umulsidi3adddi"
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
	(plus:DI
	 (mult:DI
	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
	 (match_operand:DI 1 "s_register_operand" "0")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
  "umlal%?\\t%Q0, %R0, %3, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "insn" "umlal")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*umulsidi3adddi_v6"
  [(set (match_operand:DI 0 "s_register_operand" "=r")
	(plus:DI
	 (mult:DI
	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
	  (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
	 (match_operand:DI 1 "s_register_operand" "0")))]
  "TARGET_32BIT && arm_arch6"
  "umlal%?\\t%Q0, %R0, %3, %2"
  [(set_attr "insn" "umlal")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "smulsi3_highpart"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
	(truncate:SI
	 (lshiftrt:DI
	  (mult:DI
	   (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
	   (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
	  (const_int 32))))
   (clobber (match_scratch:SI 3 "=&r,&r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m"
  "smull%?\\t%3, %0, %2, %1"
  [(set_attr "insn" "smull")
   (set_attr "predicable" "yes")]
)

(define_insn "umulsi3_highpart"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
	(truncate:SI
	 (lshiftrt:DI
	  (mult:DI
	   (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
	   (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
	  (const_int 32))))
   (clobber (match_scratch:SI 3 "=&r,&r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch3m"
  "umull%?\\t%3, %0, %2, %1"
  [(set_attr "insn" "umull")
   (set_attr "predicable" "yes")]
)

(define_insn "mulhisi3"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(mult:SI (sign_extend:SI
		  (match_operand:HI 1 "s_register_operand" "%r"))
		 (sign_extend:SI
		  (match_operand:HI 2 "s_register_operand" "r"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smulbb%?\\t%0, %1, %2"
  [(set_attr "insn" "smulxy")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulhisi3tb"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(mult:SI (ashiftrt:SI
		  (match_operand:SI 1 "s_register_operand" "r")
		  (const_int 16))
		 (sign_extend:SI
		  (match_operand:HI 2 "s_register_operand" "r"))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smultb%?\\t%0, %1, %2"
  [(set_attr "insn" "smulxy")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulhisi3bt"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(mult:SI (sign_extend:SI
		  (match_operand:HI 1 "s_register_operand" "r"))
		 (ashiftrt:SI
		  (match_operand:SI 2 "s_register_operand" "r")
		  (const_int 16))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smulbt%?\\t%0, %1, %2"
  [(set_attr "insn" "smulxy")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulhisi3tt"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(mult:SI (ashiftrt:SI
		  (match_operand:SI 1 "s_register_operand" "r")
		  (const_int 16))
		 (ashiftrt:SI
		  (match_operand:SI 2 "s_register_operand" "r")
		  (const_int 16))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smultt%?\\t%0, %1, %2"
  [(set_attr "insn" "smulxy")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulhisi3addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (match_operand:SI 1 "s_register_operand" "r")
		 (mult:SI (sign_extend:SI
			   (match_operand:HI 2 "s_register_operand" "%r"))
			  (sign_extend:SI
			   (match_operand:HI 3 "s_register_operand" "r")))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smlabb%?\\t%0, %2, %3, %1"
  [(set_attr "insn" "smlaxy")
   (set_attr "predicable" "yes")]
)

(define_insn "*mulhidi3adddi"
  [(set (match_operand:DI 0 "s_register_operand" "=r")
	(plus:DI
	  (match_operand:DI 1 "s_register_operand" "0")
	  (mult:DI (sign_extend:DI
	 	    (match_operand:HI 2 "s_register_operand" "%r"))
		   (sign_extend:DI
		    (match_operand:HI 3 "s_register_operand" "r")))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_DSP_MULTIPLY"
  "smlalbb%?\\t%Q0, %R0, %2, %3"
  [(set_attr "insn" "smlalxy")
   (set_attr "predicable" "yes")])

;; APPLE LOCAL begin DImode multiply enhancement 
;; No DI * DI instruction exists (except on Cirrus), but leave this in 
;; the RTL stream through the early optimization phases
;; to give them a chance to generate the mulsidi3, etc., patterns.

(define_expand "muldi3"
  [(parallel
    [(set (match_operand:DI          0 "s_register_operand" "")
	   (mult:DI (match_operand:DI 1 "s_register_operand" "")
		    (match_operand:DI 2 "s_register_operand" "")))
    (clobber (match_scratch:SI 3 ""))
    (clobber (match_scratch:SI 4 ""))])]
  "TARGET_ARM"
  "
    if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
      {
	if (!cirrus_fp_register (operands[0], DImode))
	  operands[0] = force_reg (DImode, operands[0]);
	if (!cirrus_fp_register (operands[1], DImode))
	  operands[1] = force_reg (DImode, operands[1]);
	emit_insn (gen_cirrus_muldi3 (operands[0], operands[1], operands[2]));
	DONE;
      }
  "
)

; Input and output registers cannot overlap in this pattern.

(define_insn_and_split "*soft_muldi3"
  [(set (match_operand:DI          0 "s_register_operand" "=&r")
	(mult:DI (match_operand:DI 1 "s_register_operand" "%0")
		 (match_operand:DI 2 "s_register_operand" "r")))
   (clobber (match_scratch:SI 3 "=&r"))
   (clobber (match_scratch:SI 4 "=&r"))]
  "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
  ""
  "&& reload_completed"
  [(set (match_dup 3) (subreg:SI (match_dup 1) 0))
   (set (match_dup 4) (subreg:SI (match_dup 1) 4))
   (set (match_dup 0) (mult:DI (zero_extend:DI (match_dup 3))
                               (zero_extend:DI (subreg:SI (match_dup 2) 0))))
   (set (subreg:SI (match_dup 0) 4) (plus:SI
            (mult:SI (match_dup 4) (subreg:SI (match_dup 2) 0))
            (subreg:SI (match_dup 0) 4)))
   (set (subreg:SI (match_dup 0) 4) (plus:SI
            (mult:SI (match_dup 3) (subreg:SI (match_dup 2) 4))
            (subreg:SI (match_dup 0) 4)))]
  ""
  ;; APPLE LOCAL 6110622 constant pool reference out of range
  [(set_attr "length" "20")]
)
;; APPLE LOCAL end DImode multiply enhancement 

(define_expand "mulsf3"
  [(set (match_operand:SF          0 "s_register_operand" "")
	(mult:SF (match_operand:SF 1 "s_register_operand" "")
		 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK
      && !cirrus_fp_register (operands[2], SFmode))
    operands[2] = force_reg (SFmode, operands[2]);
")

(define_expand "muldf3"
  [(set (match_operand:DF          0 "s_register_operand" "")
	(mult:DF (match_operand:DF 1 "s_register_operand" "")
		 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK
      && !cirrus_fp_register (operands[2], DFmode))
    operands[2] = force_reg (DFmode, operands[2]);
")

;; Division insns

(define_expand "divsf3"
  [(set (match_operand:SF 0 "s_register_operand" "")
	(div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
		(match_operand:SF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "")

(define_expand "divdf3"
  [(set (match_operand:DF 0 "s_register_operand" "")
	(div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
		(match_operand:DF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "")

;; Modulo insns

(define_expand "modsf3"
  [(set (match_operand:SF 0 "s_register_operand" "")
	(mod:SF (match_operand:SF 1 "s_register_operand" "")
		(match_operand:SF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
  "")

(define_expand "moddf3"
  [(set (match_operand:DF 0 "s_register_operand" "")
	(mod:DF (match_operand:DF 1 "s_register_operand" "")
		(match_operand:DF 2 "arm_float_rhs_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
  "")

;; Boolean and,ior,xor insns

;; Split up double word logical operations

;; APPLE LOCAL begin 5831562 long long constants
;; Split up simple DImode logical operations.  Simply perform the logical
;; operation on the upper and lower halves of the registers.
(define_split
  [(set (match_operand:DI 0 "s_register_operand" "")
	(match_operator:DI 6 "logical_binary_operator"
	  [(match_operand:DI 1 "s_register_operand" "")
	   (match_operand:DI 2 "arm_rhs64_operand" "")]))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && reload_completed
   && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
)
;; APPLE LOCAL end 5831562 long long constants

(define_split
  [(set (match_operand:DI 0 "s_register_operand" "")
	(match_operator:DI 6 "logical_binary_operator"
	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
	   (match_operand:DI 1 "s_register_operand" "")]))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && reload_completed"
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
   (set (match_dup 3) (match_op_dup:SI 6
			[(ashiftrt:SI (match_dup 2) (const_int 31))
			 (match_dup 4)]))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[5] = gen_highpart (SImode, operands[2]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
)

;; The zero extend of operand 2 means we can just copy the high part of
;; operand1 into operand0.
(define_split
  [(set (match_operand:DI 0 "s_register_operand" "")
	(ior:DI
	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
	  (match_operand:DI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 3) (match_dup 4))]
  "
  {
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
)

;; The zero extend of operand 2 means we can just copy the high part of
;; operand1 into operand0.
(define_split
  [(set (match_operand:DI 0 "s_register_operand" "")
	(xor:DI
	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
	  (match_operand:DI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 3) (match_dup 4))]
  "
  {
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
)

;; APPLE LOCAL begin 5831562 long long constants
(define_insn "anddi3"
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r,&r,&r")
	(and:DI (match_operand:DI 1 "s_register_operand"  "%0,r,0,r")
		(match_operand:DI 2 "s_register_operand"   "r,r,Dd,Dd")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && ! TARGET_IWMMXT"
  "#"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end 5831562 long long constants

(define_insn_and_split "*anddi_zesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(and:DI (zero_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI 1 "s_register_operand" "?r,0")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  ; The zero extend of operand 2 clears the high word of the output
  ; operand.
  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 3) (const_int 0))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
  [(set_attr "length" "8")]
)

(define_insn "*anddi_sesdi_di"
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
	(and:DI (sign_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI  1 "s_register_operand" "?r,0")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  [(set_attr "length" "8")]
)

(define_expand "andsi3"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(and:SI (match_operand:SI 1 "s_register_operand" "")
		(match_operand:SI 2 "reg_or_int_operand" "")))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      if (GET_CODE (operands[2]) == CONST_INT)
        {
          arm_split_constant (AND, SImode, NULL_RTX,
	                      INTVAL (operands[2]), operands[0],
			      operands[1], optimize && !no_new_pseudos);

          DONE;
        }
    }
  /* APPLE LOCAL v7 support. Merge from mainline */
  else /* TARGET_THUMB1 */
    {
      if (GET_CODE (operands[2]) != CONST_INT)
        operands[2] = force_reg (SImode, operands[2]);
      else
        {
          int i;
	  
          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
  	    {
	      operands[2] = force_reg (SImode,
				       GEN_INT (~INTVAL (operands[2])));
	      
	      emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
	      
	      DONE;
	    }

          for (i = 9; i <= 31; i++)
	    {
	      if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
	        {
	          emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
			 	        const0_rtx));
	          DONE;
	        }
	      else if ((((HOST_WIDE_INT) 1) << i) - 1
		       == ~INTVAL (operands[2]))
	        {
	          rtx shift = GEN_INT (i);
	          rtx reg = gen_reg_rtx (SImode);
		
	          emit_insn (gen_lshrsi3 (reg, operands[1], shift));
	          emit_insn (gen_ashlsi3 (operands[0], reg, shift));
		  
	          DONE;
	        }
	    }

          operands[2] = force_reg (SImode, operands[2]);
        }
    }
  "
)

;; APPLE LOCAL begin v7 support. Merge from mainline
; ??? Check split length for Thumb-2
;; APPLE LOCAL begin ARM 4673027 suboptimal loop codegen
(define_insn "*arm_andsi3_insn"
  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
	(and:SI (match_operand:SI 1 "s_register_operand" "r,r")
		(match_operand:SI 2 "arm_not_operand" "rI,K")))]
  "TARGET_32BIT"
  "@
   and%?\\t%0, %1, %2
   bic%?\\t%0, %1, #%B2"
  [(set_attr "length" "4,4")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end ARM 4673027 suboptimal loop codegen
;; APPLE LOCAL end v7 support. Merge from mainline

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_andsi3_insn"
  [(set (match_operand:SI         0 "register_operand" "=l")
	(and:SI (match_operand:SI 1 "register_operand" "%0")
		(match_operand:SI 2 "register_operand" "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "and\\t%0, %0, %2"
  [(set_attr "length" "2")]
)

(define_insn "*andsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
		 (match_operand:SI 2 "arm_not_operand" "rI,K"))
	 (const_int 0)))
   (set (match_operand:SI          0 "s_register_operand" "=r,r")
	(and:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   and%.\\t%0, %1, %2
   bic%.\\t%0, %1, #%B2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*andsi3_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
		 (match_operand:SI 1 "arm_not_operand" "rI,K"))
	 (const_int 0)))
   (clobber (match_scratch:SI 2 "=X,r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   tst%?\\t%0, %1
   bic%.\\t%2, %0, #%B1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*zeroextractsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (zero_extract:SI
			  (match_operand:SI 0 "s_register_operand" "r")
		 	  (match_operand 1 "const_int_operand" "n")
			  (match_operand 2 "const_int_operand" "n"))
			 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
      && INTVAL (operands[1]) > 0 
      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
  "*
  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
			 << INTVAL (operands[2]));
  output_asm_insn (\"tst%?\\t%0, %1\", operands);
  return \"\";
  "
  [(set_attr "conds" "set")]
)

(define_insn_and_split "*ne_zeroextractsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(ne:SI (zero_extract:SI
		(match_operand:SI 1 "s_register_operand" "r")
		(match_operand:SI 2 "const_int_operand" "n")
		(match_operand:SI 3 "const_int_operand" "n"))
	       (const_int 0)))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
       && INTVAL (operands[2]) > 0 
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
  "#"
  "TARGET_32BIT
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
       && INTVAL (operands[2]) > 0 
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
				    (const_int 0)))
	      (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 0)
	(if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
			 (match_dup 0) (const_int 1)))]
  "
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
			 << INTVAL (operands[3])); 
  "
  [(set_attr "conds" "clob")
;; APPLE LOCAL begin v7 support. Merge from mainline
   (set (attr "length")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 12)
		      (const_int 8)))]
;; APPLE LOCAL end v7 support. Merge from mainline
)

(define_insn_and_split "*ne_zeroextractsi_shifted"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(ne:SI (zero_extract:SI
		(match_operand:SI 1 "s_register_operand" "r")
		(match_operand:SI 2 "const_int_operand" "n")
		(const_int 0))
	       (const_int 0)))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
				    (const_int 0)))
	      (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 0)
	(if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
			 (match_dup 0) (const_int 1)))]
  "
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn_and_split "*ite_ne_zeroextractsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI (ne (zero_extract:SI
			      (match_operand:SI 1 "s_register_operand" "r")
			      (match_operand:SI 2 "const_int_operand" "n")
			      (match_operand:SI 3 "const_int_operand" "n"))
			     (const_int 0))
			 (match_operand:SI 4 "arm_not_operand" "rIK")
			 (const_int 0)))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
       && INTVAL (operands[2]) > 0 
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
  "#"
  "TARGET_ARM
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
       && INTVAL (operands[2]) > 0 
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
				    (const_int 0)))
	      (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 0)
	(if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
			 (match_dup 0) (match_dup 4)))]
  "
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
			 << INTVAL (operands[3])); 
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI (ne (zero_extract:SI
			      (match_operand:SI 1 "s_register_operand" "r")
			      (match_operand:SI 2 "const_int_operand" "n")
			      (const_int 0))
			     (const_int 0))
			 (match_operand:SI 3 "arm_not_operand" "rIK")
			 (const_int 0)))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
  "#"
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
				    (const_int 0)))
	      (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 0)
	(if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
			 (match_dup 0) (match_dup 3)))]
  "
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
  "{
     HOST_WIDE_INT temp = INTVAL (operands[2]);

     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
     operands[3] = GEN_INT (32 - temp);
   }"
)

;; APPLE LOCAL v7 support. Merge from mainline
;; ??? Use Thumb-2 has bitfield insert/extract instructions.
(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "shiftable_operator"
	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))
	  (match_operand:SI 5 "s_register_operand" "")]))
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
   (set (match_dup 0)
	(match_op_dup 1
	 [(lshiftrt:SI (match_dup 6) (match_dup 4))
	  (match_dup 5)]))]
  "{
     HOST_WIDE_INT temp = INTVAL (operands[3]);

     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
     operands[4] = GEN_INT (32 - temp);
   }"
)
  
(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
  "{
     HOST_WIDE_INT temp = INTVAL (operands[2]);

     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
     operands[3] = GEN_INT (32 - temp);
   }"
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "shiftable_operator"
	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))
	  (match_operand:SI 5 "s_register_operand" "")]))
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
   (set (match_dup 0)
	(match_op_dup 1
	 [(ashiftrt:SI (match_dup 6) (match_dup 4))
	  (match_dup 5)]))]
  "{
     HOST_WIDE_INT temp = INTVAL (operands[3]);

     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
     operands[4] = GEN_INT (32 - temp);
   }"
)
  
;;; ??? This pattern is bogus.  If operand3 has bits outside the range
;;; represented by the bitfield, then this will produce incorrect results.
;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
;;; which have a real bit-field insert instruction, the truncation happens
;;; in the bit-field insert instruction itself.  Since arm does not have a
;;; bit-field insert instruction, we would have to emit code here to truncate
;;; the value before we insert.  This loses some of the advantage of having
;;; this insv pattern, so this pattern needs to be reevalutated.
;;; APPLE LOCAL begin ARM insv for Thumb

;; APPLE LOCAL v7 support. Merge from mainline
; ??? Use Thumb-2 bitfield insert/extract instructions
(define_expand "insv"
  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
                         (match_operand:SI 1 "general_operand" "")
                         (match_operand:SI 2 "general_operand" ""))
        (match_operand:SI 3 "reg_or_int_operand" ""))]
  "TARGET_EITHER"
  "
  {
    int start_bit = INTVAL (operands[2]);
    int width = INTVAL (operands[1]);
    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
    rtx target, subtarget, orig_target;

    target = orig_target = operands[0];
    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
       subreg as the final target.  */
    if (GET_CODE (target) == SUBREG)
      {
	subtarget = gen_reg_rtx (SImode);
	if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
	    < GET_MODE_SIZE (SImode))
	  target = SUBREG_REG (target);
      }
    else
      subtarget = target;    

    if (GET_CODE (operands[3]) == CONST_INT)
      {
	/* Since we are inserting a known constant, we may be able to
	   reduce the number of bits that we have to clear so that
	   the mask becomes simple.  */
	/* ??? This code does not check to see if the new mask is actually
	   simpler.  It may not be.  */
	rtx op1 = gen_reg_rtx (SImode);
	/* ??? Truncate operand3 to fit in the bitfield.  See comment before
	   start of this pattern.  */
	HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
	HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);

	emit_insn (gen_andsi3 (op1, operands[0],
			       gen_int_mode (~mask2, SImode)));
	emit_insn (gen_iorsi3 (subtarget, op1,
			       gen_int_mode (op3_value << start_bit, SImode)));
      }
    else if (TARGET_ARM
	     && start_bit == 0
	     && !(const_ok_for_arm (mask)
		  || const_ok_for_arm (~mask)))
      {
	/* A Trick, since we are setting the bottom bits in the word,
	   we can shift operand[3] up, operand[0] down, OR them together
	   and rotate the result back again.  This takes 3 insns, and
	   the third might be mergeable into another op.  */
	/* The shift up copes with the possibility that operand[3] is
           wider than the bitfield.  */
	rtx op0 = gen_reg_rtx (SImode);
	rtx op1 = gen_reg_rtx (SImode);

	emit_insn (gen_ashlsi3 (op0, operands[3],
				gen_int_mode (32 - width, SImode)));
	emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
	emit_insn (gen_iorsi3  (op1, op1, op0));
	emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
      }
    else if (width + start_bit == 32
	     && (TARGET_THUMB
		 || !(const_ok_for_arm (mask)
		      || const_ok_for_arm (~mask))))
      {
	/* Similar trick, but slightly less efficient.  */

	rtx op0 = gen_reg_rtx (SImode);
	rtx op1 = gen_reg_rtx (SImode);

	emit_insn (gen_ashlsi3 (op0, operands[3],
				gen_int_mode (32 - width, SImode)));
	emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
	emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
	emit_insn (gen_iorsi3 (subtarget, op1, op0));
      }
    else
      {
	rtx op0 = gen_int_mode (mask, SImode);
	rtx op1 = gen_reg_rtx (SImode);
	rtx op2 = gen_reg_rtx (SImode);

	if (TARGET_THUMB 
	    || !(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
	  {
	    rtx tmp = gen_reg_rtx (SImode);

	    emit_insn (gen_movsi (tmp, op0));
	    op0 = tmp;
	  }

	/* Mask out any bits in operand[3] that are not needed.  */
	if (!TARGET_THUMB)
	   emit_insn (gen_andsi3 (op1, operands[3], op0));

	if (GET_CODE (op0) == CONST_INT
	    && (const_ok_for_arm (mask << start_bit)
		|| const_ok_for_arm (~(mask << start_bit))))
	  {
	    op0 = gen_int_mode (~(mask << start_bit), SImode);
	    emit_insn (gen_andsi3 (op2, operands[0], op0));
	  }
	else
	  {
	    if (GET_CODE (op0) == CONST_INT)
	      {
		rtx tmp = gen_reg_rtx (SImode);

		emit_insn (gen_movsi (tmp, op0));
		op0 = tmp;
	      }

	    if (start_bit != 0)
	      emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
	    
	    emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
	  }

	if (!TARGET_THUMB && start_bit != 0)
          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));

	/* The default code uses AND with constant which is an extra insn on thumb. */
	if (TARGET_THUMB)
	  {
	    /* If we only want a low subreg, we don't need to worry about
	       bits beyond that. */
	    if (GET_CODE (orig_target) == SUBREG
	        && SUBREG_BYTE (orig_target) == 0
	        && GET_MODE_SIZE (GET_MODE (SUBREG_REG (orig_target))) 
			< GET_MODE_SIZE (SImode)
		&& width + start_bit 
			>= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (orig_target))))
	      emit_insn (gen_ashlsi3 (op1, operands[3],
				      gen_int_mode (start_bit, SImode)));
	    else
	      {
		/* Mask unneeded bits in operand[3], and simultaneously move
		   input to the right place in the word.  */
		emit_insn (gen_ashlsi3 (op1, operands[3],
					gen_int_mode (32 - width, SImode)));
		emit_insn (gen_lshrsi3 (op1, op1,
					gen_int_mode (32 - width - start_bit, SImode)));
	      }
	  }

	emit_insn (gen_iorsi3 (subtarget, op1, op2));
      }

    if (subtarget != target)
      {
	/* If TARGET is still a SUBREG, then it must be wider than a word,
	   so we must be careful only to set the subword we were asked to.  */
	if (GET_CODE (target) == SUBREG)
	  emit_move_insn (target, subtarget);
	else
	  emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
      }

    DONE;
  }"
)
;;; APPLE LOCAL end ARM insv for Thumb

; constants for op 2 will never be given to these patterns.
(define_insn_and_split "*anddi_notdi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
		(match_operand:DI 2 "s_register_operand" "0,r")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  "TARGET_32BIT && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[5] = gen_highpart (SImode, operands[2]);
    operands[2] = gen_lowpart (SImode, operands[2]);
  }"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)
  
(define_insn_and_split "*anddi_notzesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(and:DI (not:DI (zero_extend:DI
			 (match_operand:SI 2 "s_register_operand" "r,r")))
		(match_operand:DI 1 "s_register_operand" "0,?r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   bic%?\\t%Q0, %Q1, %2
   #"
  ; (not (zero_extend ...)) allows us to just copy the high word from
  ; operand1 to operand0.
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && reload_completed
   && operands[0] != operands[1]"
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
   (set (match_dup 3) (match_dup 4))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
  [(set_attr "length" "4,8")
   (set_attr "predicable" "yes")]
)
  
(define_insn_and_split "*anddi_notsesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(and:DI (not:DI (sign_extend:DI
			 (match_operand:SI 2 "s_register_operand" "r,r")))
		(match_operand:DI 1 "s_register_operand" "0,r")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
   (set (match_dup 3) (and:SI (not:SI
				(ashiftrt:SI (match_dup 2) (const_int 31)))
			       (match_dup 4)))]
  "
  {
    operands[3] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[4] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)
  
(define_insn "andsi_notsi_si"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
		(match_operand:SI 1 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "bic%?\\t%0, %1, %2"
  [(set_attr "predicable" "yes")]
)

(define_insn "bicsi3"
  [(set (match_operand:SI                 0 "register_operand" "=l")
	(and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
		(match_operand:SI         2 "register_operand" "0")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "bic\\t%0, %0, %1"
  [(set_attr "length" "2")]
)

(define_insn "andsi_not_shiftsi_si"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(and:SI (not:SI (match_operator:SI 4 "shift_operator"
			 [(match_operand:SI 2 "s_register_operand" "r")
			  (match_operand:SI 3 "arm_rhs_operand" "rM")]))
		(match_operand:SI 1 "s_register_operand" "r")))]
  "TARGET_ARM"
  "bic%?\\t%0, %1, %2%S4"
  [(set_attr "predicable" "yes")
   (set_attr "shift" "2")
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*andsi_notsi_si_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
		 (match_operand:SI 1 "s_register_operand" "r"))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "bic%.\\t%0, %1, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*andsi_notsi_si_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
		 (match_operand:SI 1 "s_register_operand" "r"))
	 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "bic%.\\t%0, %1, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

;; APPLE LOCAL begin 5831562 long long constants
(define_insn "iordi3"
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r,&r,&r")
	(ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r,0,r")
		(match_operand:DI 2 "arm_rhs64_operand"   "r,r,Dd,Dd")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && ! TARGET_IWMMXT"
  "#"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end 5831562 long long constants

(define_insn "*iordi_zesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(ior:DI (zero_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI 1 "s_register_operand" "0,?r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   orr%?\\t%Q0, %Q1, %2
   #"
  [(set_attr "length" "4,8")
   (set_attr "predicable" "yes")]
)

(define_insn "*iordi_sesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(ior:DI (sign_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI 1 "s_register_operand" "?r,0")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)

(define_expand "iorsi3"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(ior:SI (match_operand:SI 1 "s_register_operand" "")
		(match_operand:SI 2 "reg_or_int_operand" "")))]
  "TARGET_EITHER"
  "
  if (GET_CODE (operands[2]) == CONST_INT)
    {
      /* APPLE LOCAL v7 support. Merge from mainline */
      if (TARGET_32BIT)
        {
          arm_split_constant (IOR, SImode, NULL_RTX,
	                      INTVAL (operands[2]), operands[0], operands[1],
			      optimize && !no_new_pseudos);
          DONE;
	}
      /* APPLE LOCAL v7 support. Merge from mainline */
      else /* TARGET_THUMB1 */
	operands [2] = force_reg (SImode, operands [2]);
    }
  "
)

;; APPLE LOCAL begin ARM 4673027 suboptimal loop codegen
(define_insn"*arm_iorsi3"
  [(set (match_operand:SI         0 "s_register_operand" "=r")
	(ior:SI (match_operand:SI 1 "s_register_operand" "r")
		(match_operand:SI 2 "reg_or_int_operand" "rI")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "orr%?\\t%0, %1, %2"
  [(set_attr "length" "4")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end ARM 4673027 suboptimal loop codegen

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_iorsi3"
  [(set (match_operand:SI         0 "register_operand" "=l")
	(ior:SI (match_operand:SI 1 "register_operand" "%0")
		(match_operand:SI 2 "register_operand" "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "orr\\t%0, %0, %2"
  [(set_attr "length" "2")]
)

(define_peephole2
  [(match_scratch:SI 3 "r")
   (set (match_operand:SI 0 "arm_general_register_operand" "")
	(ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
		(match_operand:SI 2 "const_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && !const_ok_for_arm (INTVAL (operands[2]))
   && const_ok_for_arm (~INTVAL (operands[2]))"
  [(set (match_dup 3) (match_dup 2))
   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
  ""
)

(define_insn "*iorsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(ior:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "orr%.\\t%0, %1, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*iorsi3_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "orr%.\\t%0, %1, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

;; APPLE LOCAL begin 5831562 long long constants
(define_insn "xordi3"
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r,&r,&r")
	(xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r,0,r")
		(match_operand:DI 2 "s_register_operand"   "r,r,Dd,Dd")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && !TARGET_IWMMXT"
  "#"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end 5831562 long long constants

(define_insn "*xordi_zesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(xor:DI (zero_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI 1 "s_register_operand" "0,?r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   eor%?\\t%Q0, %Q1, %2
   #"
  [(set_attr "length" "4,8")
   (set_attr "predicable" "yes")]
)

(define_insn "*xordi_sesidi_di"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(xor:DI (sign_extend:DI
		 (match_operand:SI 2 "s_register_operand" "r,r"))
		(match_operand:DI 1 "s_register_operand" "?r,0")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)

(define_expand "xorsi3"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(xor:SI (match_operand:SI 1 "s_register_operand" "")
		(match_operand:SI 2 "arm_rhs_operand"  "")))]
  "TARGET_EITHER"
;; APPLE LOCAL v7 support. Merge from mainline
  "if (TARGET_THUMB1)
     if (GET_CODE (operands[2]) == CONST_INT)
       operands[2] = force_reg (SImode, operands[2]);
  "
)

(define_insn "*arm_xorsi3"
  [(set (match_operand:SI         0 "s_register_operand" "=r")
	(xor:SI (match_operand:SI 1 "s_register_operand" "r")
		(match_operand:SI 2 "arm_rhs_operand" "rI")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "eor%?\\t%0, %1, %2"
  [(set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_xorsi3"
  [(set (match_operand:SI         0 "register_operand" "=l")
	(xor:SI (match_operand:SI 1 "register_operand" "%0")
		(match_operand:SI 2 "register_operand" "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "eor\\t%0, %0, %2"
  [(set_attr "length" "2")]
)

(define_insn "*xorsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
				 (match_operand:SI 2 "arm_rhs_operand" "rI"))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(xor:SI (match_dup 1) (match_dup 2)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "eor%.\\t%0, %1, %2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

(define_insn "*xorsi3_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
				 (match_operand:SI 1 "arm_rhs_operand" "rI"))
			 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "teq%?\\t%0, %1"
  [(set_attr "conds" "set")]
)

; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
; (NOT D) we can sometimes merge the final NOT into one of the following
; insns.

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
			(not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
		(match_operand:SI 3 "arm_rhs_operand" "")))
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
			      (not:SI (match_dup 3))))
   (set (match_dup 0) (not:SI (match_dup 4)))]
  ""
)

(define_insn "*andsi_iorsi3_notsi"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
	(and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
			(match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
		(not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
  [(set_attr "length" "8")
   (set_attr "ce_count" "2")
   (set_attr "predicable" "yes")]
;; APPLE LOCAL end v7 support. Merge from mainline
)

;; APPLE LOCAL begin v7 support. Merge from mainline
; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
; insns are available?
;; APPLE LOCAL end v7 support. Merge from mainline
(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "logical_binary_operator"
	 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))
	  (match_operator:SI 9 "logical_binary_operator"
	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
			 (match_operand:SI 6 "const_int_operand" ""))
	    (match_operand:SI 7 "s_register_operand" "")])]))
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
  [(set (match_dup 8)
	(match_op_dup 1
	 [(ashift:SI (match_dup 2) (match_dup 4))
	  (match_dup 5)]))
   (set (match_dup 0)
	(match_op_dup 1
	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
	  (match_dup 7)]))]
  "
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
")

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "logical_binary_operator"
	 [(match_operator:SI 9 "logical_binary_operator"
	   [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
			 (match_operand:SI 6 "const_int_operand" ""))
	    (match_operand:SI 7 "s_register_operand" "")])
	  (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))]))
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
  [(set (match_dup 8)
	(match_op_dup 1
	 [(ashift:SI (match_dup 2) (match_dup 4))
	  (match_dup 5)]))
   (set (match_dup 0)
	(match_op_dup 1
	 [(lshiftrt:SI (match_dup 8) (match_dup 6))
	  (match_dup 7)]))]
  "
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
")

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "logical_binary_operator"
	 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))
	  (match_operator:SI 9 "logical_binary_operator"
	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
			 (match_operand:SI 6 "const_int_operand" ""))
	    (match_operand:SI 7 "s_register_operand" "")])]))
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
  [(set (match_dup 8)
	(match_op_dup 1
	 [(ashift:SI (match_dup 2) (match_dup 4))
	  (match_dup 5)]))
   (set (match_dup 0)
	(match_op_dup 1
	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
	  (match_dup 7)]))]
  "
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
")

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "logical_binary_operator"
	 [(match_operator:SI 9 "logical_binary_operator"
	   [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
			 (match_operand:SI 6 "const_int_operand" ""))
	    (match_operand:SI 7 "s_register_operand" "")])
	  (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "const_int_operand" "")
			   (match_operand:SI 4 "const_int_operand" ""))]))
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
  [(set (match_dup 8)
	(match_op_dup 1
	 [(ashift:SI (match_dup 2) (match_dup 4))
	  (match_dup 5)]))
   (set (match_dup 0)
	(match_op_dup 1
	 [(ashiftrt:SI (match_dup 8) (match_dup 6))
	  (match_dup 7)]))]
  "
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
")


;; Minimum and maximum insns

(define_expand "smaxsi3"
  [(parallel [
    (set (match_operand:SI 0 "s_register_operand" "")
	 (smax:SI (match_operand:SI 1 "s_register_operand" "")
		  (match_operand:SI 2 "arm_rhs_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
    {
      /* No need for a clobber of the condition code register here.  */
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
			      gen_rtx_SMAX (SImode, operands[1],
					    operands[2])));
      DONE;
    }
")

(define_insn "*smax_0"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(smax:SI (match_operand:SI 1 "s_register_operand" "r")
		 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "bic%?\\t%0, %1, %1, asr #31"
  [(set_attr "predicable" "yes")]
)

(define_insn "*smax_m1"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(smax:SI (match_operand:SI 1 "s_register_operand" "r")
		 (const_int -1)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "orr%?\\t%0, %1, %1, asr #31"
  [(set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_smax_insn"
  [(set (match_operand:SI          0 "s_register_operand" "=r,r")
	(smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
		 (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%1, %2\;movlt\\t%0, %2
   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_expand "sminsi3"
  [(parallel [
    (set (match_operand:SI 0 "s_register_operand" "")
	 (smin:SI (match_operand:SI 1 "s_register_operand" "")
		  (match_operand:SI 2 "arm_rhs_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (operands[2] == const0_rtx)
    {
      /* No need for a clobber of the condition code register here.  */
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
			      gen_rtx_SMIN (SImode, operands[1],
					    operands[2])));
      DONE;
    }
")

(define_insn "*smin_0"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(smin:SI (match_operand:SI 1 "s_register_operand" "r")
		 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "and%?\\t%0, %1, %1, asr #31"
  [(set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_smin_insn"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
		 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%1, %2\;movge\\t%0, %2
   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "umaxsi3"
  [(parallel [
    (set (match_operand:SI 0 "s_register_operand" "")
	 (umax:SI (match_operand:SI 1 "s_register_operand" "")
		  (match_operand:SI 2 "arm_rhs_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_umaxsi3"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%1, %2\;movcc\\t%0, %2
   cmp\\t%1, %2\;movcs\\t%0, %1
   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,8,12")]
)

(define_expand "uminsi3"
  [(parallel [
    (set (match_operand:SI 0 "s_register_operand" "")
	 (umin:SI (match_operand:SI 1 "s_register_operand" "")
		  (match_operand:SI 2 "arm_rhs_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_uminsi3"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%1, %2\;movcs\\t%0, %2
   cmp\\t%1, %2\;movcc\\t%0, %1
   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,8,12")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "*store_minmaxsi"
  [(set (match_operand:SI 0 "memory_operand" "=m")
	(match_operator:SI 3 "minmax_operator"
	 [(match_operand:SI 1 "s_register_operand" "r")
	  (match_operand:SI 2 "s_register_operand" "r")]))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
  operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
				operands[1], operands[2]);
  output_asm_insn (\"cmp\\t%1, %2\", operands);
  if (TARGET_THUMB2)
    output_asm_insn (\"ite\t%d3\", operands);
  output_asm_insn (\"str%d3\\t%1, %0\", operands);
  output_asm_insn (\"str%D3\\t%2, %0\", operands);
  return \"\";
  "
  [(set_attr "conds" "clob")
   (set (attr "length")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 14)
		      (const_int 12)))
;; APPLE LOCAL end v7 support. Merge from mainline
   (set_attr "type" "store1")]
)

; Reject the frame pointer in operand[1], since reloading this after
; it has been eliminated can cause carnage.
(define_insn "*minmax_arithsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(match_operator:SI 4 "shiftable_operator"
	 [(match_operator:SI 5 "minmax_operator"
	   [(match_operand:SI 2 "s_register_operand" "r,r")
	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
	  (match_operand:SI 1 "s_register_operand" "0,?r")]))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && !arm_eliminable_register (operands[1])"
  "*
  {
    enum rtx_code code = GET_CODE (operands[4]);
    bool need_else;

    if (which_alternative != 0 || operands[3] != const0_rtx
        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
      need_else = true;
    else
      need_else = false;

    operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
				  operands[2], operands[3]);
    output_asm_insn (\"cmp\\t%2, %3\", operands);
    if (TARGET_THUMB2)
      {
	if (need_else)
	  output_asm_insn (\"ite\\t%d5\", operands);
	else
	  output_asm_insn (\"it\\t%d5\", operands);
      }
    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
    if (need_else)
      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
    return \"\";
  }"
  [(set_attr "conds" "clob")
   (set (attr "length")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 14)
		      (const_int 12)))]
;; APPLE LOCAL end v7 support. Merge from mainline
)


;; Shift and rotation insns

(define_expand "ashldi3"
  [(set (match_operand:DI            0 "s_register_operand" "")
        (ashift:DI (match_operand:DI 1 "s_register_operand" "")
                   (match_operand:SI 2 "reg_or_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (GET_CODE (operands[2]) == CONST_INT)
    {
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
        {
          emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
          DONE;
        }
        /* Ideally we shouldn't fail here if we could know that operands[1] 
           ends up already living in an iwmmxt register. Otherwise it's
           cheaper to have the alternate code being generated than moving
           values to iwmmxt regs and back.  */
        FAIL;
    }
  else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
    FAIL;
  "
)

(define_insn "arm_ashldi3_1bit"
  [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
        (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
                   (const_int 1)))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_expand "ashlsi3"
  [(set (match_operand:SI            0 "s_register_operand" "")
	(ashift:SI (match_operand:SI 1 "s_register_operand" "")
		   (match_operand:SI 2 "arm_rhs_operand" "")))]
  "TARGET_EITHER"
  "
  if (GET_CODE (operands[2]) == CONST_INT
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
    {
      emit_insn (gen_movsi (operands[0], const0_rtx));
      DONE;
    }
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_ashlsi3"
  [(set (match_operand:SI            0 "register_operand" "=l,l")
	(ashift:SI (match_operand:SI 1 "register_operand" "l,0")
		   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "lsl\\t%0, %1, %2"
  [(set_attr "length" "2")]
)

(define_expand "ashrdi3"
  [(set (match_operand:DI              0 "s_register_operand" "")
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (GET_CODE (operands[2]) == CONST_INT)
    {
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
        {
          emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
          DONE;
        }
        /* Ideally we shouldn't fail here if we could know that operands[1] 
           ends up already living in an iwmmxt register. Otherwise it's
           cheaper to have the alternate code being generated than moving
           values to iwmmxt regs and back.  */
        FAIL;
    }
  else if (!TARGET_REALLY_IWMMXT)
    FAIL;
  "
)

(define_insn "arm_ashrdi3_1bit"
  [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
                     (const_int 1)))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
  [(set_attr "conds" "clob")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)

(define_expand "ashrsi3"
  [(set (match_operand:SI              0 "s_register_operand" "")
	(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
		     (match_operand:SI 2 "arm_rhs_operand" "")))]
  "TARGET_EITHER"
  "
  if (GET_CODE (operands[2]) == CONST_INT
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
    operands[2] = GEN_INT (31);
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_ashrsi3"
  [(set (match_operand:SI              0 "register_operand" "=l,l")
	(ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "asr\\t%0, %1, %2"
  [(set_attr "length" "2")]
)

(define_expand "lshrdi3"
  [(set (match_operand:DI              0 "s_register_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (GET_CODE (operands[2]) == CONST_INT)
    {
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
        {
          emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
          DONE;
        }
        /* Ideally we shouldn't fail here if we could know that operands[1] 
           ends up already living in an iwmmxt register. Otherwise it's
           cheaper to have the alternate code being generated than moving
           values to iwmmxt regs and back.  */
        FAIL;
    }
  else if (!TARGET_REALLY_IWMMXT)
    FAIL;
  "
)

(define_insn "arm_lshrdi3_1bit"
  [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
                     (const_int 1)))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
  [(set_attr "conds" "clob")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)

(define_expand "lshrsi3"
  [(set (match_operand:SI              0 "s_register_operand" "")
	(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
		     (match_operand:SI 2 "arm_rhs_operand" "")))]
  "TARGET_EITHER"
  "
  if (GET_CODE (operands[2]) == CONST_INT
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
    {
      emit_insn (gen_movsi (operands[0], const0_rtx));
      DONE;
    }
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_lshrsi3"
  [(set (match_operand:SI              0 "register_operand" "=l,l")
	(lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
		     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "lsr\\t%0, %1, %2"
  [(set_attr "length" "2")]
)

(define_expand "rotlsi3"
  [(set (match_operand:SI              0 "s_register_operand" "")
	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
		     (match_operand:SI 2 "reg_or_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  if (GET_CODE (operands[2]) == CONST_INT)
    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
  else
    {
      rtx reg = gen_reg_rtx (SImode);
      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
      operands[2] = reg;
    }
  "
)

(define_expand "rotrsi3"
  [(set (match_operand:SI              0 "s_register_operand" "")
	(rotatert:SI (match_operand:SI 1 "s_register_operand" "")
		     (match_operand:SI 2 "arm_rhs_operand" "")))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      if (GET_CODE (operands[2]) == CONST_INT
          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
    }
  /* APPLE LOCAL v7 support. Merge from mainline */
  else /* TARGET_THUMB1 */
    {
      if (GET_CODE (operands [2]) == CONST_INT)
        operands [2] = force_reg (SImode, operands[2]);
    }
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_rotrsi3"
  [(set (match_operand:SI              0 "register_operand" "=l")
	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
		     (match_operand:SI 2 "register_operand" "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "ror\\t%0, %0, %2"
  [(set_attr "length" "2")]
)

(define_insn "*arm_shiftsi3"
  [(set (match_operand:SI   0 "s_register_operand" "=r")
	(match_operator:SI  3 "shift_operator"
	 [(match_operand:SI 1 "s_register_operand"  "r")
	  (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "* return arm_output_shift(operands, 0);"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "shift" "1")
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*shiftsi3_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "* return arm_output_shift(operands, 1);"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")
   (set_attr "shift" "1")
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*shiftsi3_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rM")])
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "* return arm_output_shift(operands, 1);"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")
   (set_attr "shift" "1")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_notsi_shiftsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(not:SI (match_operator:SI 3 "shift_operator"
		 [(match_operand:SI 1 "s_register_operand" "r")
		  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
  "TARGET_ARM"
  "mvn%?\\t%0, %1%S3"
  [(set_attr "predicable" "yes")
   (set_attr "shift" "1")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_notsi_shiftsi_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
  "TARGET_ARM"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  "mvn%.\\t%0, %1%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "1")
   (set_attr "insn" "mvn")
;; APPLE LOCAL end v7 support. Merge from Codesourcery
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_not_shiftsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rM")]))
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
  "TARGET_ARM"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  "mvn%.\\t%0, %1%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "1")
   (set_attr "insn" "mvn")
;; APPLE LOCAL end v7 support. Merge from Codesourcery
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

;; We don't really have extzv, but defining this using shifts helps
;; to reduce register pressure later on.

(define_expand "extzv"
  [(set (match_dup 4)
	(ashift:SI (match_operand:SI   1 "register_operand" "")
		   (match_operand:SI   2 "const_int_operand" "")))
   (set (match_operand:SI              0 "register_operand" "")
	(lshiftrt:SI (match_dup 4)
		     (match_operand:SI 3 "const_int_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "
  {
    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
    
    operands[3] = GEN_INT (rshift);
    
    if (lshift == 0)
      {
        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
        DONE;
      }
      
    operands[2] = GEN_INT (lshift);
    operands[4] = gen_reg_rtx (SImode);
  }"
)


;; Unary arithmetic insns

(define_expand "negdi2"
 [(parallel
   [(set (match_operand:DI          0 "s_register_operand" "")
	  (neg:DI (match_operand:DI 1 "s_register_operand" "")))
    (clobber (reg:CC CC_REGNUM))])]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_THUMB1)
    {
      if (GET_CODE (operands[1]) != REG)
        operands[1] = force_reg (SImode, operands[1]);
     }
  "
)

;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
;; The second alternative is to allow the common case of a *full* overlap.
(define_insn "*arm_negdi2"
  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_negdi2"
  [(set (match_operand:DI         0 "register_operand" "=&l")
	(neg:DI (match_operand:DI 1 "register_operand"   "l")))
   (clobber (reg:CC CC_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
  [(set_attr "length" "6")]
)

(define_expand "negsi2"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(neg:SI (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_EITHER"
  ""
)

(define_insn "*arm_negsi2"
  [(set (match_operand:SI         0 "s_register_operand" "=r")
	(neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "rsb%?\\t%0, %1, #0"
  [(set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*thumb1_negsi2"
  [(set (match_operand:SI         0 "register_operand" "=l")
	(neg:SI (match_operand:SI 1 "register_operand" "l")))]
  "TARGET_THUMB1"
  "neg\\t%0, %1"
  [(set_attr "length" "2")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_expand "negsf2"
  [(set (match_operand:SF         0 "s_register_operand" "")
	(neg:SF (match_operand:SF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  ""
)

(define_expand "negdf2"
  [(set (match_operand:DF         0 "s_register_operand" "")
	(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "")

;; abssi2 doesn't really clobber the condition codes if a different register
;; is being set.  To keep things simple, assume during rtl manipulations that
;; it does, but tell the final scan operator the truth.  Similarly for
;; (neg (abs...))

(define_expand "abssi2"
  [(parallel
    [(set (match_operand:SI         0 "s_register_operand" "")
	  (abs:SI (match_operand:SI 1 "s_register_operand" "")))
     (clobber (reg:CC CC_REGNUM))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "")

(define_insn "*arm_abssi2"
;; APPLE LOCAL v7 support. Merge from mainline
  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
  [(set_attr "conds" "clob,*")
   (set_attr "shift" "1")
   ;; predicable can't be set based on the variant, so left as no
   (set_attr "length" "8")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_neg_abssi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "@
   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
  [(set_attr "conds" "clob,*")
   (set_attr "shift" "1")
   ;; predicable can't be set based on the variant, so left as no
   (set_attr "length" "8")]
)

(define_expand "abssf2"
  [(set (match_operand:SF         0 "s_register_operand" "")
	(abs:SF (match_operand:SF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "")

(define_expand "absdf2"
  [(set (match_operand:DF         0 "s_register_operand" "")
	(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "")

(define_expand "sqrtsf2"
  [(set (match_operand:SF 0 "s_register_operand" "")
	(sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "")

(define_expand "sqrtdf2"
  [(set (match_operand:DF 0 "s_register_operand" "")
	(sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "")

(define_insn_and_split "one_cmpldi2"
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "#"
  "TARGET_32BIT && reload_completed"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (match_dup 0) (not:SI (match_dup 1)))
   (set (match_dup 2) (not:SI (match_dup 3)))]
  "
  {
    operands[2] = gen_highpart (SImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[3] = gen_highpart (SImode, operands[1]);
    operands[1] = gen_lowpart (SImode, operands[1]);
  }"
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")]
)

(define_expand "one_cmplsi2"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(not:SI (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_EITHER"
  ""
)

(define_insn "*arm_one_cmplsi2"
  [(set (match_operand:SI         0 "s_register_operand" "=r")
	(not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "mvn%?\\t%0, %1"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "predicable" "yes")
   (set_attr "insn" "mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_one_cmplsi2"
  [(set (match_operand:SI         0 "register_operand" "=l")
	(not:SI (match_operand:SI 1 "register_operand"  "l")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "mvn\\t%0, %1"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "length" "2")
   (set_attr "insn" "mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

(define_insn "*notsi_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(not:SI (match_dup 1)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "mvn%.\\t%0, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "conds" "set")
   (set_attr "insn" "mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

(define_insn "*notsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "mvn%.\\t%0, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "conds" "set")
   (set_attr "insn" "mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

;; Fixed <--> Floating conversion insns

(define_expand "floatsisf2"
  [(set (match_operand:SF           0 "s_register_operand" "")
	(float:SF (match_operand:SI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
      emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
      DONE;
    }
")

(define_expand "floatsidf2"
  [(set (match_operand:DF           0 "s_register_operand" "")
	(float:DF (match_operand:SI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
      emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
      DONE;
    }
")

(define_expand "fix_truncsfsi2"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
      if (!cirrus_fp_register (operands[0], SImode))
        operands[0] = force_reg (SImode, operands[0]);
      if (!cirrus_fp_register (operands[1], SFmode))
        operands[1] = force_reg (SFmode, operands[0]);
      emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
      DONE;
    }
")

(define_expand "fix_truncdfsi2"
  [(set (match_operand:SI         0 "s_register_operand" "")
	(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  if (TARGET_MAVERICK)
    {
      if (!cirrus_fp_register (operands[1], DFmode))
        operands[1] = force_reg (DFmode, operands[0]);
      emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
      DONE;
    }
")

;; Truncation insns

(define_expand "truncdfsf2"
  [(set (match_operand:SF  0 "s_register_operand" "")
	(float_truncate:SF
 	 (match_operand:DF 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  ""
)

;; Zero and sign extension instructions.

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "zero_extendsidi2"
  [(set (match_operand:DI 0 "s_register_operand" "")
        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_zero_extendsidi2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (match_operand:DI 0 "s_register_operand" "=r")
        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
  "TARGET_ARM"
  "*
    if (REGNO (operands[1])
        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
    return \"mov%?\\t%R0, #0\";
  "
  [(set_attr "length" "8")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "zero_extendqidi2"
  [(set (match_operand:DI                 0 "s_register_operand"  "")
	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_zero_extendqidi2"
  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
  "TARGET_ARM"
  "@
   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
   ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "length" "8")
   (set_attr "predicable" "yes")
   (set_attr "type" "*,load_byte")
   (set_attr "pool_range" "*,4092")
   (set_attr "neg_pool_range" "*,4084")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_expand "extendsidi2"
  [(set (match_operand:DI 0 "s_register_operand" "")
        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_32BIT"
  ""
)

(define_insn "*arm_extendsidi2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (match_operand:DI 0 "s_register_operand" "=r")
        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
  "TARGET_ARM"
  "*
    if (REGNO (operands[1])
        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
    return \"mov%?\\t%R0, %Q0, asr #31\";
  "
  [(set_attr "length" "8")
   (set_attr "shift" "1")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "predicable" "yes")]
)

(define_expand "zero_extendhisi2"
  [(set (match_dup 2)
	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
		   (const_int 16)))
   (set (match_operand:SI 0 "s_register_operand" "")
	(lshiftrt:SI (match_dup 2) (const_int 16)))]
  "TARGET_EITHER"
  "
  {
    /* APPLE LOCAL v7 support. Merge from mainline */
    if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM)
      {
	emit_insn (gen_rtx_SET (VOIDmode, operands[0],
				gen_rtx_ZERO_EXTEND (SImode, operands[1])));
	DONE;
      }

    if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
      {
	emit_insn (gen_movhi_bytes (operands[0], operands[1]));
	DONE;
      }

    if (!s_register_operand (operands[1], HImode))
      operands[1] = copy_to_mode_reg (HImode, operands[1]);

    if (arm_arch6)
      {
	emit_insn (gen_rtx_SET (VOIDmode, operands[0],
				gen_rtx_ZERO_EXTEND (SImode, operands[1])));
	DONE;
      }

    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_reg_rtx (SImode);
  }"
)

;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "adjustable_thumb1_zero_extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=l")
	(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
  "TARGET_THUMB1 && !arm_arch6"
;; APPLE LOCAL end v7 support. Merge from mainline
  "*
  rtx mem = XEXP (operands[1], 0);

  if (GET_CODE (mem) == CONST)
    mem = XEXP (mem, 0);
    
  if (GET_CODE (mem) == LABEL_REF)
    return \"ldr\\t%0, %1\";
    
  if (GET_CODE (mem) == PLUS)
    {
      rtx a = XEXP (mem, 0);
      rtx b = XEXP (mem, 1);

      /* This can happen due to bugs in reload.  */
      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
        {
          rtx ops[2];
          ops[0] = operands[0];
          ops[1] = a;
      
          output_asm_insn (\"mov	%0, %1\", ops);

          XEXP (mem, 0) = operands[0];
       }

      else if (   GET_CODE (a) == LABEL_REF
	       && GET_CODE (b) == CONST_INT)
        return \"ldr\\t%0, %1\";
    }
    
  return \"ldrh\\t%0, %1\";
  "
  [(set_attr "length" "4")
   (set_attr "type" "load_byte")
   (set_attr "pool_range" "60")]
)

;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_zero_extendhisi2_v6"
  [(set (match_operand:SI 0 "register_operand" "=l,l")
	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch6"
  "*
  rtx mem;

  if (which_alternative == 0)
    return \"uxth\\t%0, %1\";

  mem = XEXP (operands[1], 0);

  if (GET_CODE (mem) == CONST)
    mem = XEXP (mem, 0);
    
  if (GET_CODE (mem) == LABEL_REF)
    return \"ldr\\t%0, %1\";
    
  if (GET_CODE (mem) == PLUS)
    {
      rtx a = XEXP (mem, 0);
      rtx b = XEXP (mem, 1);

      /* This can happen due to bugs in reload.  */
      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
        {
          rtx ops[2];
          ops[0] = operands[0];
          ops[1] = a;
      
          output_asm_insn (\"mov	%0, %1\", ops);

          XEXP (mem, 0) = operands[0];
       }

      else if (   GET_CODE (a) == LABEL_REF
	       && GET_CODE (b) == CONST_INT)
        return \"ldr\\t%0, %1\";
    }
    
  return \"ldrh\\t%0, %1\";
  "
  [(set_attr "length" "2,4")
   (set_attr "type" "alu_shift,load_byte")
   (set_attr "pool_range" "*,60")]
)

(define_insn "*arm_zero_extendhisi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
  "TARGET_ARM && arm_arch4 && !arm_arch6"
;; APPLE LOCAL v7 support. Merge from mainline
  "ldr%(h%)\\t%0, %1"
  [(set_attr "type" "load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "256")
   (set_attr "neg_pool_range" "244")]
)

(define_insn "*arm_zero_extendhisi2_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
  "TARGET_ARM && arm_arch6"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "@
   uxth%?\\t%0, %1
   ldr%(h%)\\t%0, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "alu_shift,load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "*,256")
   (set_attr "neg_pool_range" "*,244")]
)

(define_insn "*arm_zero_extendhisi2addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
		 (match_operand:SI 2 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_INT_SIMD"
  "uxtah%?\\t%0, %2, %1"
  [(set_attr "type" "alu_shift")
   (set_attr "predicable" "yes")]
)

(define_expand "zero_extendqisi2"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
  "TARGET_EITHER"
  "
  if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
    {
      if (TARGET_ARM)
        {
          emit_insn (gen_andsi3 (operands[0],
				 gen_lowpart (SImode, operands[1]),
			         GEN_INT (255)));
        }
      else /* TARGET_THUMB */
        {
          rtx temp = gen_reg_rtx (SImode);
	  rtx ops[3];
	  
          operands[1] = copy_to_mode_reg (QImode, operands[1]);
          operands[1] = gen_lowpart (SImode, operands[1]);

	  ops[0] = temp;
	  ops[1] = operands[1];
	  ops[2] = GEN_INT (24);

	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
				  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
	  
          ops[0] = operands[0];
	  ops[1] = temp;
	  ops[2] = GEN_INT (24);

	  emit_insn (gen_rtx_SET (VOIDmode, ops[0],
				  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
	}
      DONE;
    }
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_zero_extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=l")
	(zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && !arm_arch6"
  "ldrb\\t%0, %1"
  [(set_attr "length" "2")
   (set_attr "type" "load_byte")
   (set_attr "pool_range" "32")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_zero_extendqisi2_v6"
  [(set (match_operand:SI 0 "register_operand" "=l,l")
	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch6"
  "@
   uxtb\\t%0, %1
   ldrb\\t%0, %1"
  [(set_attr "length" "2,2")
   (set_attr "type" "alu_shift,load_byte")
   (set_attr "pool_range" "*,32")]
)

(define_insn "*arm_zero_extendqisi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
  "TARGET_ARM && !arm_arch6"
;; APPLE LOCAL v7 support. Merge from mainline
  "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
  [(set_attr "type" "load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "4096")
   (set_attr "neg_pool_range" "4084")]
)

(define_insn "*arm_zero_extendqisi2_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
  "TARGET_ARM && arm_arch6"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "@
   uxtb%(%)\\t%0, %1
   ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "alu_shift,load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "*,4096")
   (set_attr "neg_pool_range" "*,4084")]
)

(define_insn "*arm_zero_extendqisi2addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
		 (match_operand:SI 2 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_INT_SIMD"
  "uxtab%?\\t%0, %2, %1"
  [(set_attr "predicable" "yes")
   (set_attr "type" "alu_shift")]
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
  [(set (match_dup 2) (match_dup 1))
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
  ""
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
  [(set (match_dup 2) (match_dup 1))
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
  ""
)

(define_insn "*compareqi_eq0"
  [(set (reg:CC_Z CC_REGNUM)
	(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
			 (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "tst\\t%0, #255"
  [(set_attr "conds" "set")]
)

(define_expand "extendhisi2"
  [(set (match_dup 2)
	(ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
		   (const_int 16)))
   (set (match_operand:SI 0 "s_register_operand" "")
	(ashiftrt:SI (match_dup 2)
		     (const_int 16)))]
  "TARGET_EITHER"
  "
  {
    if (GET_CODE (operands[1]) == MEM)
      {
        /* APPLE LOCAL v7 support. Merge from mainline */
	if (TARGET_THUMB1)
	  {
            /* APPLE LOCAL v7 support. Merge from mainline */
	    emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
	    DONE;
          }
	else if (arm_arch4)
	  {
	    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
		       gen_rtx_SIGN_EXTEND (SImode, operands[1])));
	    DONE;
	  }
      }

    if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
      {
        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
        DONE;
      }

    if (!s_register_operand (operands[1], HImode))
      operands[1] = copy_to_mode_reg (HImode, operands[1]);

    if (arm_arch6)
      {
        /* APPLE LOCAL begin v7 support. Merge from mainline */
	if (TARGET_THUMB1)
	  emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
        /* APPLE LOCAL end v7 support. Merge from mainline */
	else
	  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
		     gen_rtx_SIGN_EXTEND (SImode, operands[1])));

	DONE;
      }

    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_reg_rtx (SImode);
  }"
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "thumb1_extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=l")
	(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
   (clobber (match_scratch:SI 2 "=&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && !arm_arch6"
  "*
  {
    rtx ops[4];
    rtx mem = XEXP (operands[1], 0);

    /* This code used to try to use 'V', and fix the address only if it was
       offsettable, but this fails for e.g. REG+48 because 48 is outside the
       range of QImode offsets, and offsettable_address_p does a QImode
       address check.  */
       
    if (GET_CODE (mem) == CONST)
      mem = XEXP (mem, 0);
    
    if (GET_CODE (mem) == LABEL_REF)
      return \"ldr\\t%0, %1\";
    
    if (GET_CODE (mem) == PLUS)
      {
        rtx a = XEXP (mem, 0);
        rtx b = XEXP (mem, 1);

        if (GET_CODE (a) == LABEL_REF
	    && GET_CODE (b) == CONST_INT)
          return \"ldr\\t%0, %1\";

        if (GET_CODE (b) == REG)
          return \"ldrsh\\t%0, %1\";
	  
        ops[1] = a;
        ops[2] = b;
      }
    else
      {
        ops[1] = mem;
        ops[2] = const0_rtx;
      }

    gcc_assert (GET_CODE (ops[1]) == REG);

    ops[0] = operands[0];
    ops[3] = operands[2];
    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
    return \"\";
  }"
  [(set_attr "length" "4")
   (set_attr "type" "load_byte")
   (set_attr "pool_range" "1020")]
)

;; We used to have an early-clobber on the scratch register here.
;; However, there's a bug somewhere in reload which means that this
;; can be partially ignored during spill allocation if the memory
;; address also needs reloading; this causes us to die later on when
;; we try to verify the operands.  Fortunately, we don't really need
;; the early-clobber: we can always use operand 0 if operand 2
;; overlaps the address.
;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_extendhisi2_insn_v6"
  [(set (match_operand:SI 0 "register_operand" "=l,l")
	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
   (clobber (match_scratch:SI 2 "=X,l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch6"
  "*
  {
    rtx ops[4];
    rtx mem;

    if (which_alternative == 0)
      return \"sxth\\t%0, %1\";

    mem = XEXP (operands[1], 0);

    /* This code used to try to use 'V', and fix the address only if it was
       offsettable, but this fails for e.g. REG+48 because 48 is outside the
       range of QImode offsets, and offsettable_address_p does a QImode
       address check.  */
       
    if (GET_CODE (mem) == CONST)
      mem = XEXP (mem, 0);
    
    if (GET_CODE (mem) == LABEL_REF)
      return \"ldr\\t%0, %1\";
    
    if (GET_CODE (mem) == PLUS)
      {
        rtx a = XEXP (mem, 0);
        rtx b = XEXP (mem, 1);

        if (GET_CODE (a) == LABEL_REF
	    && GET_CODE (b) == CONST_INT)
          return \"ldr\\t%0, %1\";

        if (GET_CODE (b) == REG)
          return \"ldrsh\\t%0, %1\";
	  
        ops[1] = a;
        ops[2] = b;
      }
    else
      {
        ops[1] = mem;
        ops[2] = const0_rtx;
      }
      
    gcc_assert (GET_CODE (ops[1]) == REG);

    ops[0] = operands[0];
    if (reg_mentioned_p (operands[2], ops[1]))
      ops[3] = ops[0];
    else
      ops[3] = operands[2];
    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
    return \"\";
  }"
  [(set_attr "length" "2,4")
   (set_attr "type" "alu_shift,load_byte")
   (set_attr "pool_range" "*,1020")]
)

;; APPLE LOCAL v7 support. Merge from mainline
;; This pattern will only be used when ldsh is not available
(define_expand "extendhisi2_mem"
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
   (set (match_dup 3)
	(zero_extend:SI (match_dup 7)))
   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
   (set (match_operand:SI 0 "" "")
	(ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
  "TARGET_ARM"
  "
  {
    rtx mem1, mem2;
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));

    mem1 = change_address (operands[1], QImode, addr);
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = mem1;
    operands[2] = gen_reg_rtx (SImode);
    operands[3] = gen_reg_rtx (SImode);
    operands[6] = gen_reg_rtx (SImode);
    operands[7] = mem2;

    if (BYTES_BIG_ENDIAN)
      {
	operands[4] = operands[2];
	operands[5] = operands[3];
      }
    else
      {
	operands[4] = operands[3];
	operands[5] = operands[2];
      }
  }"
)

(define_insn "*arm_extendhisi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
  "TARGET_ARM && arm_arch4 && !arm_arch6"
;; APPLE LOCAL v7 support. Merge from mainline
  "ldr%(sh%)\\t%0, %1"
  [(set_attr "type" "load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "256")
   (set_attr "neg_pool_range" "244")]
)

;; APPLE LOCAL v7 support. Merge from mainline
;; ??? Check Thumb-2 pool range
(define_insn "*arm_extendhisi2_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch6"
  "@
   sxth%?\\t%0, %1
   ldr%(sh%)\\t%0, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "alu_shift,load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "*,256")
   (set_attr "neg_pool_range" "*,244")]
)

(define_insn "*arm_extendhisi2addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
		 (match_operand:SI 2 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_INT_SIMD"
  "sxtah%?\\t%0, %2, %1"
)

(define_expand "extendqihi2"
  [(set (match_dup 2)
	(ashift:SI (match_operand:QI 1 "general_operand" "")
		   (const_int 24)))
   (set (match_operand:HI 0 "s_register_operand" "")
	(ashiftrt:SI (match_dup 2)
		     (const_int 24)))]
  "TARGET_ARM"
  "
  {
    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
      {
	emit_insn (gen_rtx_SET (VOIDmode,
				operands[0],
				gen_rtx_SIGN_EXTEND (HImode, operands[1])));
	DONE;
      }
    if (!s_register_operand (operands[1], QImode))
      operands[1] = copy_to_mode_reg (QImode, operands[1]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_reg_rtx (SImode);
  }"
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_extendqihi_insn"
  [(set (match_operand:HI 0 "s_register_operand" "=r")
	(sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
  "TARGET_ARM && arm_arch4"
;; APPLE LOCAL v7 support. Merge from mainline
  "ldr%(sb%)\\t%0, %1"
  [(set_attr "type" "load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "256")
   (set_attr "neg_pool_range" "244")]
)

(define_expand "extendqisi2"
  [(set (match_dup 2)
	(ashift:SI (match_operand:QI 1 "general_operand" "")
		   (const_int 24)))
   (set (match_operand:SI 0 "s_register_operand" "")
	(ashiftrt:SI (match_dup 2)
		     (const_int 24)))]
  "TARGET_EITHER"
  "
  {
    if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
      {
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
        DONE;
      }

    if (!s_register_operand (operands[1], QImode))
      operands[1] = copy_to_mode_reg (QImode, operands[1]);

    if (arm_arch6)
      {
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
			        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
        DONE;
      }

    operands[1] = gen_lowpart (SImode, operands[1]);
    operands[2] = gen_reg_rtx (SImode);
  }"
)

(define_insn "*arm_extendqisi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
  "TARGET_ARM && arm_arch4 && !arm_arch6"
;; APPLE LOCAL v7 support. Merge from mainline
  "ldr%(sb%)\\t%0, %1"
  [(set_attr "type" "load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "256")
   (set_attr "neg_pool_range" "244")]
)

(define_insn "*arm_extendqisi_v6"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
  "TARGET_ARM && arm_arch6"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "@
   sxtb%?\\t%0, %1
   ldr%(sb%)\\t%0, %1"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "alu_shift,load_byte")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "*,256")
   (set_attr "neg_pool_range" "*,244")]
)

(define_insn "*arm_extendqisi2addsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
		 (match_operand:SI 2 "s_register_operand" "r")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_INT_SIMD"
  "sxtab%?\\t%0, %2, %1"
  [(set_attr "type" "alu_shift")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=l,l")
	(sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && !arm_arch6"
  "*
  {
    rtx ops[3];
    rtx mem = XEXP (operands[1], 0);
    
    if (GET_CODE (mem) == CONST)
      mem = XEXP (mem, 0);
    
    if (GET_CODE (mem) == LABEL_REF)
      return \"ldr\\t%0, %1\";

    if (GET_CODE (mem) == PLUS
        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
      return \"ldr\\t%0, %1\";
      
    if (which_alternative == 0)
      return \"ldrsb\\t%0, %1\";
      
    ops[0] = operands[0];
    
    if (GET_CODE (mem) == PLUS)
      {
        rtx a = XEXP (mem, 0);
	rtx b = XEXP (mem, 1);
	
        ops[1] = a;
        ops[2] = b;

        if (GET_CODE (a) == REG)
	  {
	    if (GET_CODE (b) == REG)
              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
            else if (REGNO (a) == REGNO (ops[0]))
	      {
                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
	      }
	    else
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
	  }
	else
          {
	    gcc_assert (GET_CODE (b) == REG);
            if (REGNO (b) == REGNO (ops[0]))
	      {
                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
		output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
		output_asm_insn (\"asr\\t%0, %0, #24\", ops);
	      }
	    else
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
          }
      }
    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
      {
        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
	output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
	output_asm_insn (\"asr\\t%0, %0, #24\", ops);
      }
    else
      {
        ops[1] = mem;
        ops[2] = const0_rtx;
	
        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
      }
    return \"\";
  }"
  [(set_attr "length" "2,6")
   (set_attr "type" "load_byte,load_byte")
   (set_attr "pool_range" "32,32")]
)

;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_extendqisi2_v6"
  [(set (match_operand:SI 0 "register_operand" "=l,l,l")
	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch6"
  "*
  {
    rtx ops[3];
    rtx mem;

    if (which_alternative == 0)
      return \"sxtb\\t%0, %1\";

    mem = XEXP (operands[1], 0);
    
    if (GET_CODE (mem) == CONST)
      mem = XEXP (mem, 0);
    
    if (GET_CODE (mem) == LABEL_REF)
      return \"ldr\\t%0, %1\";

    if (GET_CODE (mem) == PLUS
        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
      return \"ldr\\t%0, %1\";
      
    /* APPLE LOCAL ARM fix obvious typo */
    if (which_alternative == 1)
      return \"ldrsb\\t%0, %1\";
      
    ops[0] = operands[0];
    
    if (GET_CODE (mem) == PLUS)
      {
        rtx a = XEXP (mem, 0);
	rtx b = XEXP (mem, 1);
	
        ops[1] = a;
        ops[2] = b;

        if (GET_CODE (a) == REG)
	  {
	    if (GET_CODE (b) == REG)
              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
            else if (REGNO (a) == REGNO (ops[0]))
	      {
                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
		output_asm_insn (\"sxtb\\t%0, %0\", ops);
	      }
	    else
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
	  }
	else
          {
	    gcc_assert (GET_CODE (b) == REG);
            if (REGNO (b) == REGNO (ops[0]))
	      {
                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
		output_asm_insn (\"sxtb\\t%0, %0\", ops);
	      }
	    else
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
          }
      }
    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
      {
        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
	output_asm_insn (\"sxtb\\t%0, %0\", ops);
      }
    else
      {
        ops[1] = mem;
        ops[2] = const0_rtx;
	
        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
      }
    return \"\";
  }"
  [(set_attr "length" "2,2,4")
   (set_attr "type" "alu_shift,load_byte,load_byte")
   (set_attr "pool_range" "*,32,32")]
)

(define_expand "extendsfdf2"
  [(set (match_operand:DF                  0 "s_register_operand" "")
	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  ""
)

;; Move insns (including loads and stores)

;; XXX Just some ideas about movti.
;; I don't think these are a good idea on the arm, there just aren't enough
;; registers
;;(define_expand "loadti"
;;  [(set (match_operand:TI 0 "s_register_operand" "")
;;	(mem:TI (match_operand:SI 1 "address_operand" "")))]
;;  "" "")

;;(define_expand "storeti"
;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
;;	(match_operand:TI 1 "s_register_operand" ""))]
;;  "" "")

;;(define_expand "movti"
;;  [(set (match_operand:TI 0 "general_operand" "")
;;	(match_operand:TI 1 "general_operand" ""))]
;;  ""
;;  "
;;{
;;  rtx insn;
;;
;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
;;    operands[1] = copy_to_reg (operands[1]);
;;  if (GET_CODE (operands[0]) == MEM)
;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
;;  else if (GET_CODE (operands[1]) == MEM)
;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
;;  else
;;    FAIL;
;;
;;  emit_insn (insn);
;;  DONE;
;;}")

;; Recognize garbage generated above.

;;(define_insn ""
;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
;;	(match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
;;  ""
;;  "*
;;  {
;;    register mem = (which_alternative < 3);
;;    register const char *template;
;;
;;    operands[mem] = XEXP (operands[mem], 0);
;;    switch (which_alternative)
;;      {
;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
;;      case 5: template = \"stmia\\t%0, %M1\"; break;
;;      }
;;    output_asm_insn (template, operands);
;;    return \"\";
;;  }")

(define_expand "movdi"
  [(set (match_operand:DI 0 "general_operand" "")
	(match_operand:DI 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  if (!no_new_pseudos)
    {
      if (GET_CODE (operands[0]) != REG)
	operands[1] = force_reg (DImode, operands[1]);
    }
  "
)

(define_insn "*arm_movdi"
  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
	(match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
  "TARGET_ARM
   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
   && !TARGET_IWMMXT
   && (   register_operand (operands[0], DImode)
       || register_operand (operands[1], DImode))"
  "*
  switch (which_alternative)
    {
    case 0:
    case 1:
    case 2:
      return \"#\";
    default:
      return output_move_double (operands);
    }
  "
  [(set_attr "length" "8,12,16,8,8")
   (set_attr "type" "*,*,*,load2,store2")
   (set_attr "pool_range" "*,*,*,1020,*")
   (set_attr "neg_pool_range" "*,*,*,1008,*")]
)

(define_split
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
	(match_operand:ANY64 1 "const_double_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && reload_completed
   && (arm_const_double_inline_cost (operands[1])
       <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
  [(const_int 0)]
  "
  arm_split_constant (SET, SImode, curr_insn,
		      INTVAL (gen_lowpart (SImode, operands[1])),
		      gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
  arm_split_constant (SET, SImode, curr_insn,
		      INTVAL (gen_highpart_mode (SImode,
						 GET_MODE (operands[0]),
						 operands[1])),
		      gen_highpart (SImode, operands[0]), NULL_RTX, 0);
  DONE;
  "
)

; If optimizing for size, or if we have load delay slots, then 
; we want to split the constant into two separate operations. 
; In both cases this may split a trivial part into a single data op
; leaving a single complex constant to load.  We can also get longer
; offsets in a LDR which means we get better chances of sharing the pool
; entries.  Finally, we can normally do a better job of scheduling
; LDR instructions than we can with LDM.
;; APPLE LOCAL begin ARM split 64-bit constants on Thumb 
; On ARM, This pattern will only match if the one above did not.
; On Thumb, use this form always; don't try to do inline expansions.
(define_split
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
	(match_operand:ANY64 1 "const_double_operand" ""))]
  "TARGET_EITHER && reload_completed
   && (TARGET_THUMB || arm_const_double_by_parts (operands[1]))"
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 2) (match_dup 3))]
  "
  operands[2] = gen_highpart (SImode, operands[0]);
  operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
				   operands[1]);
  operands[0] = gen_lowpart (SImode, operands[0]);
  operands[1] = gen_lowpart (SImode, operands[1]);
  "
)
;; APPLE LOCAL end ARM split 64-bit constants on Thumb 

(define_split
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
	(match_operand:ANY64 1 "arm_general_register_operand" ""))]
  "TARGET_EITHER && reload_completed"
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 2) (match_dup 3))]
  "
  operands[2] = gen_highpart (SImode, operands[0]);
  operands[3] = gen_highpart (SImode, operands[1]);
  operands[0] = gen_lowpart (SImode, operands[0]);
  operands[1] = gen_lowpart (SImode, operands[1]);

  /* Handle a partial overlap.  */
  if (rtx_equal_p (operands[0], operands[3]))
    {
      rtx tmp0 = operands[0];
      rtx tmp1 = operands[1];

      operands[0] = operands[2];
      operands[1] = operands[3];
      operands[2] = tmp0;
      operands[3] = tmp1;
    }
  "
)

;; We can't actually do base+index doubleword loads if the index and
;; destination overlap.  Split here so that we at least have chance to
;; schedule.
(define_split
  [(set (match_operand:DI 0 "s_register_operand" "")
	(mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
			 (match_operand:SI 2 "s_register_operand" ""))))]
  "TARGET_LDRD
  && reg_overlap_mentioned_p (operands[0], operands[1])
  && reg_overlap_mentioned_p (operands[0], operands[2])"
  [(set (match_dup 4)
	(plus:SI (match_dup 1)
		 (match_dup 2)))
   (set (match_dup 0)
	(mem:DI (match_dup 4)))]
  "
  operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
  "
)

;; APPLE LOCAL begin compact switch tables
;;; ??? This should have alternatives for constants.
;;; ??? This was originally identical to the movdf_insn pattern.
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
;;; thumb_reorg with a memory reference.
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_movdi_insn"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
   && (   register_operand (operands[0], DImode)
       || register_operand (operands[1], DImode))"
  "*
  {
  switch (which_alternative)
    {
    default:
    case 0:
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
	return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
    case 1:
      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
    case 2:
      operands[1] = GEN_INT (- INTVAL (operands[1]));
      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
    case 3:
      return \"ldmia\\t%1, {%0, %H0}\";
    case 4:
      return \"stmia\\t%0, {%1, %H1}\";
    case 5:
      return thumb_load_double_from_address (operands);
    case 6:
      operands[2] = gen_rtx_MEM (SImode,
			     plus_constant (XEXP (operands[0], 0), 4));
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
      return \"\";
    case 7:
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
    }
  }"
  [(set_attr "length" "4,4,6,2,2,4,4,4")
   (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "*,mov,*,*,*,*,*,mov")
   (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
)
;; APPLE LOCAL end compact switch tables

(define_expand "movsi"
  [(set (match_operand:SI 0 "general_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      /* Everything except mem = const or mem = mem can be done easily.  */
      if (GET_CODE (operands[0]) == MEM)
        operands[1] = force_reg (SImode, operands[1]);
      if (arm_general_register_operand (operands[0], SImode)
	  && GET_CODE (operands[1]) == CONST_INT
          && !(const_ok_for_arm (INTVAL (operands[1]))
               || const_ok_for_arm (~INTVAL (operands[1]))))
        {
           arm_split_constant (SET, SImode, NULL_RTX,
	                       INTVAL (operands[1]), operands[0], NULL_RTX,
			       optimize && !no_new_pseudos);
          DONE;
        }
    }
  /* APPLE LOCAL v7 support. Merge from mainline */
  else /* TARGET_THUMB1...  */
    {
      if (!no_new_pseudos)
        {
          if (GET_CODE (operands[0]) != REG)
	    operands[1] = force_reg (SImode, operands[1]);
        }
    }

  /* Recognize the case where operand[1] is a reference to thread-local
     data and load its address to a register.  */
  if (arm_tls_referenced_p (operands[1]))
    {
      rtx tmp = operands[1];
      rtx addend = NULL;

      if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
        {
          addend = XEXP (XEXP (tmp, 0), 1);
          tmp = XEXP (XEXP (tmp, 0), 0);
        }

      gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
      gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);

      tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
      if (addend)
        {
          tmp = gen_rtx_PLUS (SImode, tmp, addend);
          tmp = force_operand (tmp, operands[0]);
        }
      operands[1] = tmp;
    }
  /* APPLE LOCAL ARM pic support */
  else if (! LEGITIMATE_INDIRECT_OPERAND_P (operands[1]))
      operands[1] = legitimize_pic_address (operands[1], SImode,
					    (no_new_pseudos ? operands[0] : 0));
  "
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*arm_movsi_insn"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r, m")
	(match_operand:SI 1 "general_operand"      "rI,K,N,mi,r"))]
  "TARGET_ARM && ! TARGET_IWMMXT
   && !(TARGET_HARD_FLOAT && TARGET_VFP)
   && (   register_operand (operands[0], SImode)
       || register_operand (operands[1], SImode))"
  "@
   mov%?\\t%0, %1
   mvn%?\\t%0, #%B1
   movw%?\\t%0, %1
   ldr%?\\t%0, %1
   str%?\\t%1, %0"
  [(set_attr "type" "*,*,*,load1,store1")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov,mvn,mov,*,*")
   (set_attr "predicable" "yes")
   (set_attr "pool_range" "*,*,*,4096,*")
   (set_attr "neg_pool_range" "*,*,*,4084,*")]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_split
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
	(match_operand:SI 1 "const_int_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
  && (!(const_ok_for_arm (INTVAL (operands[1]))
        || const_ok_for_arm (~INTVAL (operands[1]))))"
  [(clobber (const_int 0))]
  "
  arm_split_constant (SET, SImode, NULL_RTX, 
                      INTVAL (operands[1]), operands[0], NULL_RTX, 0);
  DONE;
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_movsi_insn"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
	(match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (   register_operand (operands[0], SImode) 
       || register_operand (operands[1], SImode))"
  "@
   mov	%0, %1
   mov	%0, %1
   #
   #
   ldmia\\t%1, {%0}
   stmia\\t%0, {%1}
   ldr\\t%0, %1
   str\\t%1, %0
   mov\\t%0, %1"
  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
   (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
)

(define_split 
  [(set (match_operand:SI 0 "register_operand" "")
	(match_operand:SI 1 "const_int_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 0) (neg:SI (match_dup 0)))]
  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
)

(define_split 
  [(set (match_operand:SI 0 "register_operand" "")
	(match_operand:SI 1 "const_int_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
  "
  {
    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
    unsigned HOST_WIDE_INT mask = 0xff;
    int i;
    
    for (i = 0; i < 25; i++)
      if ((val & (mask << i)) == val)
        break;

    /* Shouldn't happen, but we don't want to split if the shift is zero.  */
    if (i == 0)
      FAIL;

    operands[1] = GEN_INT (val >> i);
    operands[2] = GEN_INT (i);
  }"
)

;; When generating pic, we need to load the symbol offset into a register.
;; So that the optimizer does not confuse this with a normal symbol load
;; we use an unspec.  The offset will be loaded from a constant pool entry,
;; since that is the only type of relocation we can use.

;; The rather odd constraints on the following are to force reload to leave
;; the insn alone, and to force the minipool generation pass to then move
;; the GOT symbol to memory.

;; APPLE LOCAL begin ARM pic support
(define_insn "pic_load_addr_arm"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "" "mX")
		    (label_ref (match_operand 2 "" ""))] UNSPEC_PIC_SYM))
   (use (label_ref (match_dup 2)))]
  "TARGET_ARM && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "ldr%?\\t%0, %1"
  [(set_attr "type" "load1")
   (set (attr "pool_range")     (const_int 4096))
   (set (attr "neg_pool_range") (const_int 4084))]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "pic_load_addr_thumb1"
  [(set (match_operand:SI 0 "s_register_operand" "=l")
	(unspec:SI [(match_operand:SI 1 "" "mX")
		    (label_ref (match_operand 2 "" ""))] UNSPEC_PIC_SYM))
   (use (label_ref (match_dup 2)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "ldr\\t%0, %1"
  [(set_attr "type" "load1")
   (set (attr "pool_range") (const_int 1022))
   (set_attr "length" "2")]
)
;; APPLE LOCAL end ARM pic support

;; This variant is used for AOF assembly, since it needs to mention the
;; pic register in the rtl.
(define_expand "pic_load_addr_based"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
  "TARGET_ARM && flag_pic"
  "operands[2] = cfun->machine->pic_reg;"
)

;; APPLE LOCAL begin ARM compact switch tables
(define_insn "*pic_load_addr_based_insn"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(unspec:SI [(match_operand 1 "" "")
		    (match_operand 2 "s_register_operand" "r")]
		   UNSPEC_PIC_SYM))]
  "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
  "*
#ifdef AOF_ASSEMBLER
  operands[1] = aof_pic_entry (operands[1]);
#endif
  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
  return \"\";
  "
  [(set_attr "type" "load1")
   (set (attr "pool_range")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 1020)
		      (const_int 4096)))
   (set (attr "neg_pool_range")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 0)
		      (const_int 4084)))
   (set (attr "length")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 2)
		      (const_int 4)))]
)
;; APPLE LOCAL end ARM compact switch tables

;; APPLE LOCAL begin ARM pic support
(define_insn "pic_add_dot_plus_four"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(label_ref (match_operand 1 "" ""))
		    (plus:SI (match_operand:SI 2 "register_operand" "0")
			     (const (plus:SI (pc) (const_int 4))))]
		   UNSPEC_PIC_BASE))]
  "TARGET_THUMB && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "*
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
				     CODE_LABEL_NUMBER (operands[1]));
  return \"add\\t%0, %|pc\";
  "
  [(set_attr "length" "2")]
)

(define_insn "pic_add_dot_plus_eight"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(label_ref (match_operand 1 "" ""))
		    (plus:SI (match_operand:SI 2 "register_operand" "r")
			     (const (plus:SI (pc) (const_int 8))))]
		   UNSPEC_PIC_BASE))]
  "TARGET_ARM && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "*
    (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
				       CODE_LABEL_NUMBER (operands[1]));
    return \"add%?\\t%0, %|pc, %2\";
  "
  [(set_attr "predicable" "yes")]
)
;; APPLE LOCAL end ARM pic support

(define_insn "tls_load_dot_plus_eight"
  [(set (match_operand:SI 0 "register_operand" "+r")
	(mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
				     (const (plus:SI (pc) (const_int 8))))]
			   UNSPEC_PIC_BASE)))
   (use (match_operand 2 "" ""))]
  "TARGET_ARM"
  "*
    (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
				       INTVAL (operands[2]));
    return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
  "
  [(set_attr "predicable" "yes")]
)

;; PIC references to local variables can generate pic_add_dot_plus_eight
;; followed by a load.  These sequences can be crunched down to
;; tls_load_dot_plus_eight by a peephole.

(define_peephole2
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
		   (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
			     	 	(const (plus:SI (pc) (const_int 8))))]
			      UNSPEC_PIC_BASE))
   	      (use (label_ref (match_operand 1 "" "")))])
   (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
  "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
  [(parallel [(set (match_dup 2)
		   (mem:SI (unspec:SI [(plus:SI (match_dup 3)
						(const (plus:SI (pc) (const_int 8))))]
				      UNSPEC_PIC_BASE)))
   	      (use (label_ref (match_dup 1)))])]
  ""
)

;; APPLE LOCAL begin ARM 4224487
;; These short forms work for addresses of scalar globals.  They
;; are produced by combine.  There is no Thumb counterpart, as
;; [Rn+PC] is not a valid addressing mode on Thumb.

(define_insn "*arm_pic_ldrsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mem:SI (unspec:SI [(label_ref (match_operand 1 "" ""))
		    (plus:SI (match_operand:SI 2 "register_operand" "r")
			     (const (plus:SI (pc) (const_int 8))))]
		   UNSPEC_PIC_BASE)))]
  "TARGET_ARM && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "*
    (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
			       CODE_LABEL_NUMBER (operands[1]));
    return \"ldr%?\\t%0, [%|pc, %2]\";
  "
  [(set_attr "predicable" "yes")]
)

(define_insn "*arm_pic_strsi"
  [(set (mem:SI (unspec:SI [(label_ref (match_operand 1 "" ""))
		    (plus:SI (match_operand:SI 2 "register_operand" "r")
			     (const (plus:SI (pc) (const_int 8))))]
		   UNSPEC_PIC_BASE))
	(match_operand:SI 0 "register_operand" "r"))]
  "TARGET_ARM && (flag_pic || (TARGET_MACHO && MACHO_DYNAMIC_NO_PIC_P))"
  "*
    (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
			       CODE_LABEL_NUMBER (operands[1]));
    return \"str%?\\t%0, [%|pc, %2]\";
  "
  [(set_attr "predicable" "yes")]
)
;; APPLE LOCAL end ARM 4224487

;; APPLE LOCAL begin ARM setjmp/longjmp interworking
;; If we'll be  returning to thumb code, we need to set the low-order
;; bit of the resume address.  builtin_setjmp_setup doesn't handle all
;; of the setup, it just augments the logic in builtins.c, to post-
;; process the already-initialized mini-jmp_buf.
(define_expand "builtin_setjmp_setup"
  [(use (match_operand 0 "register_operand"))]
  "TARGET_THUMB"
{
  rtx resume_addr =
    gen_rtx_MEM (Pmode, plus_constant (operands[0],
				       GET_MODE_SIZE (Pmode)));
  rtx resume_reg;

  /* Set low-order bit of resume address */
  resume_reg = force_reg (Pmode, resume_addr);
  resume_reg = gen_rtx_IOR (Pmode, resume_reg, GEN_INT (1));
  emit_move_insn (resume_addr, resume_reg);
  /* APPLE LOCAL 6387939 */
  DONE;
})

;; Very similar to the logic in builtins.c, except that we always
;; restore both ARM_HARD_FRAME_POINTER and THUMB_HARD_FRAME_POINTER,
;; and we emit an "indirect_jump_exchange" instead of the standard
;; "indirect_jump".  If we're jumping back into ARM code, we will
;; unnecessarily (but harmlessly) trash the Thumb FP register.
(define_expand "builtin_longjmp"
  [(use (match_operand 0 "register_operand"))]
  ""
  "
{
  rtx arm_saved_fp = gen_rtx_MEM (Pmode, operands[0]);
  rtx lab =
    gen_rtx_MEM (Pmode, plus_constant (operands[0],
				       GET_MODE_SIZE (Pmode)));
  rtx stack =
    gen_rtx_MEM (Pmode, plus_constant (operands[0],
				       2 * GET_MODE_SIZE (Pmode)));
  rtx arm_fp = gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM);

  emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_MEM (BLKmode, arm_fp)));

  emit_move_insn (arm_fp, arm_saved_fp);

  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);

  if (arm_arch4t)
    {
      lab = copy_to_mode_reg (Pmode, lab);
      emit_insn (gen_rtx_USE (VOIDmode, arm_fp));
      emit_jump_insn (gen_indirect_jump_exchange (lab));
      emit_barrier ();
    }
  else
    emit_indirect_jump (lab);

  DONE;
}")
;; APPLE LOCAL end ARM setjmp/longjmp interworking

;; If copying one reg to another we can set the condition codes according to
;; its value.  Such a move is common after a return from subroutine and the
;; result is being tested against zero.

(define_insn "*movsi_compare0"
  [(set (reg:CC CC_REGNUM)
	(compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
		    (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
	(match_dup 1))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   cmp%?\\t%0, #0
   sub%.\\t%0, %1, #0"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "conds" "set")]
)

;; Subroutine to store a half word from a register into memory.
;; Operand 0 is the source register (HImode)
;; Operand 1 is the destination address in a register (SImode)

;; In both this routine and the next, we must be careful not to spill
;; a memory address of reg+large_const into a separate PLUS insn, since this
;; can generate unrecognizable rtl.

(define_expand "storehi"
  [;; store the low byte
   (set (match_operand 1 "" "") (match_dup 3))
   ;; extract the high byte
   (set (match_dup 2)
	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
   ;; store the high byte
   (set (match_dup 4) (match_dup 5))]
  "TARGET_ARM"
  "
  {
    rtx op1 = operands[1];
    rtx addr = XEXP (op1, 0);
    enum rtx_code code = GET_CODE (addr);

    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
	|| code == MINUS)
      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));

    operands[4] = adjust_address (op1, QImode, 1);
    operands[1] = adjust_address (operands[1], QImode, 0);
    operands[3] = gen_lowpart (QImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[2] = gen_reg_rtx (SImode);
    operands[5] = gen_lowpart (QImode, operands[2]);
  }"
)

(define_expand "storehi_bigend"
  [(set (match_dup 4) (match_dup 3))
   (set (match_dup 2)
	(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
   (set (match_operand 1 "" "")	(match_dup 5))]
  "TARGET_ARM"
  "
  {
    rtx op1 = operands[1];
    rtx addr = XEXP (op1, 0);
    enum rtx_code code = GET_CODE (addr);

    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
	|| code == MINUS)
      op1 = replace_equiv_address (op1, force_reg (SImode, addr));

    operands[4] = adjust_address (op1, QImode, 1);
    operands[1] = adjust_address (operands[1], QImode, 0);
    operands[3] = gen_lowpart (QImode, operands[0]);
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[2] = gen_reg_rtx (SImode);
    operands[5] = gen_lowpart (QImode, operands[2]);
  }"
)

;; Subroutine to store a half word integer constant into memory.
(define_expand "storeinthi"
  [(set (match_operand 0 "" "")
	(match_operand 1 "" ""))
   (set (match_dup 3) (match_dup 2))]
  "TARGET_ARM"
  "
  {
    HOST_WIDE_INT value = INTVAL (operands[1]);
    rtx addr = XEXP (operands[0], 0);
    rtx op0 = operands[0];
    enum rtx_code code = GET_CODE (addr);

    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
	|| code == MINUS)
      op0 = replace_equiv_address (op0, force_reg (SImode, addr));

    operands[1] = gen_reg_rtx (SImode);
    if (BYTES_BIG_ENDIAN)
      {
	emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
	if ((value & 255) == ((value >> 8) & 255))
	  operands[2] = operands[1];
	else
	  {
	    operands[2] = gen_reg_rtx (SImode);
	    emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
	  }
      }
    else
      {
	emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
	if ((value & 255) == ((value >> 8) & 255))
	  operands[2] = operands[1];
	else
	  {
	    operands[2] = gen_reg_rtx (SImode);
	    emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
	  }
      }

    operands[3] = adjust_address (op0, QImode, 1);
    operands[0] = adjust_address (operands[0], QImode, 0);
    operands[2] = gen_lowpart (QImode, operands[2]);
    operands[1] = gen_lowpart (QImode, operands[1]);
  }"
)

(define_expand "storehi_single_op"
  [(set (match_operand:HI 0 "memory_operand" "")
	(match_operand:HI 1 "general_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch4"
  "
  if (!s_register_operand (operands[1], HImode))
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
  "
)

(define_expand "movhi"
  [(set (match_operand:HI 0 "general_operand" "")
	(match_operand:HI 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  if (TARGET_ARM)
    {
      if (!no_new_pseudos)
        {
          if (GET_CODE (operands[0]) == MEM)
	    {
	      if (arm_arch4)
	        {
	          emit_insn (gen_storehi_single_op (operands[0], operands[1]));
	          DONE;
	        }
	      if (GET_CODE (operands[1]) == CONST_INT)
	        emit_insn (gen_storeinthi (operands[0], operands[1]));
	      else
	        {
	          if (GET_CODE (operands[1]) == MEM)
		    operands[1] = force_reg (HImode, operands[1]);
	          if (BYTES_BIG_ENDIAN)
		    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
	          else
		   emit_insn (gen_storehi (operands[1], operands[0]));
	        }
	      DONE;
	    }
          /* Sign extend a constant, and keep it in an SImode reg.  */
          else if (GET_CODE (operands[1]) == CONST_INT)
	    {
	      rtx reg = gen_reg_rtx (SImode);
	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;

	      /* If the constant is already valid, leave it alone.  */
	      if (!const_ok_for_arm (val))
	        {
	          /* If setting all the top bits will make the constant 
		     loadable in a single instruction, then set them.  
		     Otherwise, sign extend the number.  */

	          if (const_ok_for_arm (~(val | ~0xffff)))
		    val |= ~0xffff;
	          else if (val & 0x8000)
		    val |= ~0xffff;
	        }

	      emit_insn (gen_movsi (reg, GEN_INT (val)));
	      operands[1] = gen_lowpart (HImode, reg);
	    }
	  else if (arm_arch4 && optimize && !no_new_pseudos
		   && GET_CODE (operands[1]) == MEM)
	    {
	      rtx reg = gen_reg_rtx (SImode);

	      emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
	      operands[1] = gen_lowpart (HImode, reg);
	    }
          else if (!arm_arch4)
	    {
	      if (GET_CODE (operands[1]) == MEM)
	        {
		  rtx base;
		  rtx offset = const0_rtx;
		  rtx reg = gen_reg_rtx (SImode);

		  if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
		       || (GET_CODE (base) == PLUS
			   && (GET_CODE (offset = XEXP (base, 1))
			       == CONST_INT)
                           && ((INTVAL(offset) & 1) != 1)
			   && GET_CODE (base = XEXP (base, 0)) == REG))
		      && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
		    {
		      rtx new;

		      new = widen_memory_access (operands[1], SImode,
						 ((INTVAL (offset) & ~3)
						  - INTVAL (offset)));
		      emit_insn (gen_movsi (reg, new));
		      if (((INTVAL (offset) & 2) != 0)
			  ^ (BYTES_BIG_ENDIAN ? 1 : 0))
			{
			  rtx reg2 = gen_reg_rtx (SImode);

			  emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
			  reg = reg2;
			}
		    }
		  else
		    emit_insn (gen_movhi_bytes (reg, operands[1]));

		  operands[1] = gen_lowpart (HImode, reg);
	       }
	   }
        }
      /* Handle loading a large integer during reload.  */
      else if (GET_CODE (operands[1]) == CONST_INT
	       && !const_ok_for_arm (INTVAL (operands[1]))
	       && !const_ok_for_arm (~INTVAL (operands[1])))
        {
          /* Writing a constant to memory needs a scratch, which should
	     be handled with SECONDARY_RELOADs.  */
          gcc_assert (GET_CODE (operands[0]) == REG);

          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
          emit_insn (gen_movsi (operands[0], operands[1]));
          DONE;
       }
    }
  /* APPLE LOCAL begin v7 support. Merge from mainline */
  else if (TARGET_THUMB2)
    {
      /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
      if (!no_new_pseudos)
	{
	  if (GET_CODE (operands[0]) != REG)
	    operands[1] = force_reg (HImode, operands[1]);
          /* Zero extend a constant, and keep it in an SImode reg.  */
          else if (GET_CODE (operands[1]) == CONST_INT)
	    {
	      rtx reg = gen_reg_rtx (SImode);
	      HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;

	      emit_insn (gen_movsi (reg, GEN_INT (val)));
	      operands[1] = gen_lowpart (HImode, reg);
	    }
	}
    }
  else /* TARGET_THUMB1 */
    {
      if (!no_new_pseudos)
  /* APPLE LOCAL end v7 support. Merge from mainline */
        {
	  if (GET_CODE (operands[1]) == CONST_INT)
	    {
	      rtx reg = gen_reg_rtx (SImode);

	      emit_insn (gen_movsi (reg, operands[1]));
	      operands[1] = gen_lowpart (HImode, reg);
	    }

          /* ??? We shouldn't really get invalid addresses here, but this can
	     happen if we are passed a SP (never OK for HImode/QImode) or 
	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
	     HImode/QImode) relative address.  */
          /* ??? This should perhaps be fixed elsewhere, for instance, in
	     fixup_stack_1, by checking for other kinds of invalid addresses,
	     e.g. a bare reference to a virtual register.  This may confuse the
	     alpha though, which must handle this case differently.  */
          if (GET_CODE (operands[0]) == MEM
	      && !memory_address_p (GET_MODE (operands[0]),
				    XEXP (operands[0], 0)))
	    operands[0]
	      = replace_equiv_address (operands[0],
				       copy_to_reg (XEXP (operands[0], 0)));
   
          if (GET_CODE (operands[1]) == MEM
	      && !memory_address_p (GET_MODE (operands[1]),
				    XEXP (operands[1], 0)))
	    operands[1]
	      = replace_equiv_address (operands[1],
				       copy_to_reg (XEXP (operands[1], 0)));

	  if (GET_CODE (operands[1]) == MEM && optimize > 0)
	    {
	      rtx reg = gen_reg_rtx (SImode);

	      emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
	      operands[1] = gen_lowpart (HImode, reg);
	    }

          if (GET_CODE (operands[0]) == MEM)
	    operands[1] = force_reg (HImode, operands[1]);
        }
      else if (GET_CODE (operands[1]) == CONST_INT
	        && !satisfies_constraint_I (operands[1]))
        {
	  /* Handle loading a large integer during reload.  */

          /* Writing a constant to memory needs a scratch, which should
	     be handled with SECONDARY_RELOADs.  */
          gcc_assert (GET_CODE (operands[0]) == REG);

          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
          emit_insn (gen_movsi (operands[0], operands[1]));
          DONE;
        }
    }
  "
)

;; APPLE LOCAL ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "adjustable_thumb1_movhi_insn"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
	(match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (   register_operand (operands[0], HImode)
       || register_operand (operands[1], HImode))"
  "*
  switch (which_alternative)
    {
    case 0: return \"add	%0, %1, #0\";
    case 2: return \"strh	%1, %0\";
    case 3: return \"mov	%0, %1\";
    case 4: return \"mov	%0, %1\";
    case 5: return \"mov	%0, %1\";
    default: gcc_unreachable ();
    case 1:
      /* The stack pointer can end up being taken as an index register.
          Catch this case here and deal with it.  */
      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
	  && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
	  && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
        {
	  rtx ops[2];
          ops[0] = operands[0];
          ops[1] = XEXP (XEXP (operands[1], 0), 0);
      
          output_asm_insn (\"mov	%0, %1\", ops);

          XEXP (XEXP (operands[1], 0), 0) = operands[0];
    
	}
      return \"ldrh	%0, %1\";
    }"
  [(set_attr "length" "2,4,2,2,2,2")
   (set_attr "type" "*,load1,store1,*,*,*")]
)


(define_expand "movhi_bytes"
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
   (set (match_dup 3)
	(zero_extend:SI (match_dup 6)))
   (set (match_operand:SI 0 "" "")
	 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
  "TARGET_ARM"
  "
  {
    rtx mem1, mem2;
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));

    mem1 = change_address (operands[1], QImode, addr);
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
    operands[0] = gen_lowpart (SImode, operands[0]);
    operands[1] = mem1;
    operands[2] = gen_reg_rtx (SImode);
    operands[3] = gen_reg_rtx (SImode);
    operands[6] = mem2;

    if (BYTES_BIG_ENDIAN)
      {
	operands[4] = operands[2];
	operands[5] = operands[3];
      }
    else
      {
	operands[4] = operands[3];
	operands[5] = operands[2];
      }
  }"
)

(define_expand "movhi_bigend"
  [(set (match_dup 2)
	(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
		   (const_int 16)))
   (set (match_dup 3)
	(ashiftrt:SI (match_dup 2) (const_int 16)))
   (set (match_operand:HI 0 "s_register_operand" "")
	(match_dup 4))]
  "TARGET_ARM"
  "
  operands[2] = gen_reg_rtx (SImode);
  operands[3] = gen_reg_rtx (SImode);
  operands[4] = gen_lowpart (HImode, operands[3]);
  "
)

;; Pattern to recognize insn generated default case above
(define_insn "*movhi_insn_arch4"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
	(match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
  "TARGET_ARM
   && arm_arch4
   && (GET_CODE (operands[1]) != CONST_INT
       || const_ok_for_arm (INTVAL (operands[1]))
       || const_ok_for_arm (~INTVAL (operands[1])))"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "@
   mov%?\\t%0, %1\\t%@ movhi
   mvn%?\\t%0, #%B1\\t%@ movhi
   str%(h%)\\t%1, %0\\t%@ movhi
   ldr%(h%)\\t%0, %1\\t%@ movhi"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "*,*,store1,load1")
   (set_attr "predicable" "yes")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov,mvn,*,*")
   (set_attr "pool_range" "*,*,*,256")
   (set_attr "neg_pool_range" "*,*,*,244")]
)

(define_insn "*movhi_bytes"
  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
	(match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
  "TARGET_ARM"
  "@
   mov%?\\t%0, %1\\t%@ movhi
   mvn%?\\t%0, #%B1\\t%@ movhi"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "predicable" "yes")
   (set_attr "insn" "mov,mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

(define_expand "thumb_movhi_clobber"
  [(set (match_operand:HI     0 "memory_operand"   "")
	(match_operand:HI     1 "register_operand" ""))
   (clobber (match_operand:DI 2 "register_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "
  if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
      && REGNO (operands[1]) <= LAST_LO_REGNUM)
    {
      emit_insn (gen_movhi (operands[0], operands[1]));
      DONE;
    }
  /* XXX Fixme, need to handle other cases here as well.  */
  gcc_unreachable ();
  "
)
	
;; We use a DImode scratch because we may occasionally need an additional
;; temporary if the address isn't offsettable -- push_reload doesn't seem
;; to take any notice of the "o" constraints on reload_memory_operand operand.
(define_expand "reload_outhi"
  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
	      (match_operand:HI 1 "s_register_operand"        "r")
	      (match_operand:DI 2 "s_register_operand"        "=&l")])]
  "TARGET_EITHER"
  "if (TARGET_ARM)
     arm_reload_out_hi (operands);
   else
     thumb_reload_out_hi (operands);
  DONE;
  "
)

(define_expand "reload_inhi"
  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
	      (match_operand:HI 1 "arm_reload_memory_operand" "o")
	      (match_operand:DI 2 "s_register_operand" "=&r")])]
  "TARGET_EITHER"
  "
  if (TARGET_ARM)
    arm_reload_in_hi (operands);
  else
    thumb_reload_out_hi (operands);
  DONE;
")

(define_expand "movqi"
  [(set (match_operand:QI 0 "general_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  /* Everything except mem = const or mem = mem can be done easily */

  if (!no_new_pseudos)
    {
      if (GET_CODE (operands[1]) == CONST_INT)
	{
	  rtx reg = gen_reg_rtx (SImode);

	  emit_insn (gen_movsi (reg, operands[1]));
	  operands[1] = gen_lowpart (QImode, reg);
	}

      if (TARGET_THUMB)
	{
          /* ??? We shouldn't really get invalid addresses here, but this can
	     happen if we are passed a SP (never OK for HImode/QImode) or
	     virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
	     HImode/QImode) relative address.  */
          /* ??? This should perhaps be fixed elsewhere, for instance, in
	     fixup_stack_1, by checking for other kinds of invalid addresses,
	     e.g. a bare reference to a virtual register.  This may confuse the
	     alpha though, which must handle this case differently.  */
          if (GET_CODE (operands[0]) == MEM
	      && !memory_address_p (GET_MODE (operands[0]),
		  		     XEXP (operands[0], 0)))
	    operands[0]
	      = replace_equiv_address (operands[0],
				       copy_to_reg (XEXP (operands[0], 0)));
          if (GET_CODE (operands[1]) == MEM
	      && !memory_address_p (GET_MODE (operands[1]),
				    XEXP (operands[1], 0)))
	     operands[1]
	       = replace_equiv_address (operands[1],
					copy_to_reg (XEXP (operands[1], 0)));
	}

      if (GET_CODE (operands[1]) == MEM && optimize > 0)
	{
	  rtx reg = gen_reg_rtx (SImode);

	  emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
	  operands[1] = gen_lowpart (QImode, reg);
	}

      if (GET_CODE (operands[0]) == MEM)
	operands[1] = force_reg (QImode, operands[1]);
    }
  else if (TARGET_THUMB
	   && GET_CODE (operands[1]) == CONST_INT
	   && !satisfies_constraint_I (operands[1]))
    {
      /* Handle loading a large integer during reload.  */

      /* Writing a constant to memory needs a scratch, which should
	 be handled with SECONDARY_RELOADs.  */
      gcc_assert (GET_CODE (operands[0]) == REG);

      operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
      emit_insn (gen_movsi (operands[0], operands[1]));
      DONE;
    }
  "
)


(define_insn "*arm_movqi_insn"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
	(match_operand:QI 1 "general_operand" "rI,K,m,r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && (   register_operand (operands[0], QImode)
       || register_operand (operands[1], QImode))"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "@
   mov%?\\t%0, %1
   mvn%?\\t%0, #%B1
   ldr%(b%)\\t%0, %1
   str%(b%)\\t%1, %0"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "*,*,load1,store1")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov,mvn,*,*")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_movqi_insn"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
	(match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (   register_operand (operands[0], QImode)
       || register_operand (operands[1], QImode))"
  "@
   add\\t%0, %1, #0
   ldrb\\t%0, %1
   strb\\t%1, %0
   mov\\t%0, %1
   mov\\t%0, %1
   mov\\t%0, %1"
  [(set_attr "length" "2")
   (set_attr "type" "*,load1,store1,*,*,*")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "*,*,*,mov,mov,mov")
   (set_attr "pool_range" "*,32,*,*,*,*")]
)

(define_expand "movsf"
  [(set (match_operand:SF 0 "general_operand" "")
	(match_operand:SF 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      if (GET_CODE (operands[0]) == MEM)
        operands[1] = force_reg (SFmode, operands[1]);
    }
  /* APPLE LOCAL v7 support. Merge from mainline */
  else /* TARGET_THUMB1 */
    {
      if (!no_new_pseudos)
        {
           if (GET_CODE (operands[0]) != REG)
	     operands[1] = force_reg (SFmode, operands[1]);
        }
    }
  "
)

;; Transform a floating-point move of a constant into a core register into
;; an SImode operation.
(define_split
  [(set (match_operand:SF 0 "arm_general_register_operand" "")
	(match_operand:SF 1 "immediate_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT
   && reload_completed
   && GET_CODE (operands[1]) == CONST_DOUBLE"
  [(set (match_dup 2) (match_dup 3))]
  "
  operands[2] = gen_lowpart (SImode, operands[0]);
  operands[3] = gen_lowpart (SImode, operands[1]);
  if (operands[2] == 0 || operands[3] == 0)
    FAIL;
  "
)

(define_insn "*arm_movsf_soft_insn"
  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
  "TARGET_ARM
   && TARGET_SOFT_FLOAT
   && (GET_CODE (operands[0]) != MEM
       || register_operand (operands[1], SFmode))"
  "@
   mov%?\\t%0, %1
   ldr%?\\t%0, %1\\t%@ float
   str%?\\t%1, %0\\t%@ float"
  [(set_attr "length" "4,4,4")
   (set_attr "predicable" "yes")
   (set_attr "type" "*,load1,store1")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov,*,*")
   (set_attr "pool_range" "*,4096,*")
   (set_attr "neg_pool_range" "*,4084,*")]
)

;;; ??? This should have alternatives for constants.
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_movsf_insn"
  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
	(match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (   register_operand (operands[0], SFmode) 
       || register_operand (operands[1], SFmode))"
  "@
   add\\t%0, %1, #0
   ldmia\\t%1, {%0}
   stmia\\t%0, {%1}
   ldr\\t%0, %1
   str\\t%1, %0
   mov\\t%0, %1
   mov\\t%0, %1"
  [(set_attr "length" "2")
   (set_attr "type" "*,load1,store1,load1,store1,*,*")
   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
)

(define_expand "movdf"
  [(set (match_operand:DF 0 "general_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      if (GET_CODE (operands[0]) == MEM)
        operands[1] = force_reg (DFmode, operands[1]);
    }
  else /* TARGET_THUMB */
    {
      if (!no_new_pseudos)
        {
          if (GET_CODE (operands[0]) != REG)
	    operands[1] = force_reg (DFmode, operands[1]);
        }
    }
  "
)

;; Reloading a df mode value stored in integer regs to memory can require a
;; scratch reg.
(define_expand "reload_outdf"
  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
   (match_operand:DF 1 "s_register_operand" "r")
   (match_operand:SI 2 "s_register_operand" "=&r")]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  {
    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));

    if (code == REG)
      operands[2] = XEXP (operands[0], 0);
    else if (code == POST_INC || code == PRE_DEC)
      {
	operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
	operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
	emit_insn (gen_movdi (operands[0], operands[1]));
	DONE;
      }
    else if (code == PRE_INC)
      {
	rtx reg = XEXP (XEXP (operands[0], 0), 0);

	emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
	operands[2] = reg;
      }
    else if (code == POST_DEC)
      operands[2] = XEXP (XEXP (operands[0], 0), 0);
    else
      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
			     XEXP (XEXP (operands[0], 0), 1)));

    emit_insn (gen_rtx_SET (VOIDmode,
			    replace_equiv_address (operands[0], operands[2]),
			    operands[1]));

    if (code == POST_DEC)
      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));

    DONE;
  }"
)

(define_insn "*movdf_soft_insn"
  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
	(match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
  "TARGET_ARM && TARGET_SOFT_FLOAT
   && (   register_operand (operands[0], DFmode)
       || register_operand (operands[1], DFmode))"
  "*
  switch (which_alternative)
    {
    case 0:
    case 1:
    case 2:
      return \"#\";
    default:
      return output_move_double (operands);
    }
  "
  [(set_attr "length" "8,12,16,8,8")
   (set_attr "type" "*,*,*,load2,store2")
   (set_attr "pool_range" "1020")
   (set_attr "neg_pool_range" "1008")]
)

;; APPLE LOCAL begin ARM compact switch tables
;;; ??? This should have alternatives for constants.
;;; ??? This was originally identical to the movdi_insn pattern.
;;; ??? The 'F' constraint looks funny, but it should always be replaced by
;;; thumb_reorg with a memory reference.
(define_insn "*thumb_movdf_insn"
  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
	(match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (   register_operand (operands[0], DFmode)
       || register_operand (operands[1], DFmode))"
  "*
  switch (which_alternative)
    {
    default:
    case 0:
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
	return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
    case 1:
      return \"ldmia\\t%1, {%0, %H0}\";
    case 2:
      return \"stmia\\t%0, {%1, %H1}\";
    case 3:
      return thumb_load_double_from_address (operands);
    case 4:
      operands[2] = gen_rtx_MEM (SImode,
				 plus_constant (XEXP (operands[0], 0), 4));
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
      return \"\";
    case 5:
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
	return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
    }
  "
  [(set_attr "length" "4,2,2,4,4,4")
   (set_attr "type" "*,load2,store2,load2,store2,*")
   (set_attr "pool_range" "*,*,*,1018,*,*")]
)
;; APPLE LOCAL end ARM compact switch tables

(define_expand "movxf"
  [(set (match_operand:XF 0 "general_operand" "")
	(match_operand:XF 1 "general_operand" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
  "
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (XFmode, operands[1]);
  "
)

;; APPLE LOCAL v7 support. Merge from mainline
;; Removed lines


;; load- and store-multiple insns
;; The arm can load/store any set of registers, provided that they are in
;; ascending order; but that is beyond GCC so stick with what it knows.

(define_expand "load_multiple"
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))
                     (use (match_operand:SI 2 "" ""))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
{
  HOST_WIDE_INT offset = 0;

  /* Support only fixed point registers.  */
  if (GET_CODE (operands[2]) != CONST_INT
      || INTVAL (operands[2]) > 14
      || INTVAL (operands[2]) < 2
      || GET_CODE (operands[1]) != MEM
      || GET_CODE (operands[0]) != REG
      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
    FAIL;

  operands[3]
    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
			     force_reg (SImode, XEXP (operands[1], 0)),
			     TRUE, FALSE, operands[1], &offset);
})

;; Load multiple with write-back

(define_insn "*ldmsi_postinc4"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 16)))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (match_dup 2)))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
     (set (match_operand:SI 6 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
  "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load4")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*ldmsi_postinc4_thumb1"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=l")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 16)))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (match_dup 2)))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))
     (set (match_operand:SI 6 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
  "ldmia\\t%1!, {%3, %4, %5, %6}"
  [(set_attr "type" "load4")
   (set_attr "length" "2")]
)
;; APPLE LOCAL end ARM compact switch tables

(define_insn "*ldmsi_postinc3"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 12)))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (match_dup 2)))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
  "ldm%(ia%)\\t%1!, {%3, %4, %5}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load3")
   (set_attr "predicable" "yes")]
)

(define_insn "*ldmsi_postinc2"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 8)))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (match_dup 2)))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
  "ldm%(ia%)\\t%1!, {%3, %4}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load2")
   (set_attr "predicable" "yes")]
)

;; Ordinary load multiple

(define_insn "*ldmsi4"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
  "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load4")
   (set_attr "predicable" "yes")]
)

(define_insn "*ldmsi3"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
  "ldm%(ia%)\\t%1, {%2, %3, %4}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load3")
   (set_attr "predicable" "yes")]
)

(define_insn "*ldmsi2"
  [(match_parallel 0 "load_multiple_operation"
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
	  (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
  "ldm%(ia%)\\t%1, {%2, %3}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "load2")
   (set_attr "predicable" "yes")]
)

(define_expand "store_multiple"
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))
                     (use (match_operand:SI 2 "" ""))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
{
  HOST_WIDE_INT offset = 0;

  /* Support only fixed point registers.  */
  if (GET_CODE (operands[2]) != CONST_INT
      || INTVAL (operands[2]) > 14
      || INTVAL (operands[2]) < 2
      || GET_CODE (operands[1]) != REG
      || GET_CODE (operands[0]) != MEM
      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
    FAIL;

  operands[3]
    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
			      force_reg (SImode, XEXP (operands[0], 0)),
			      TRUE, FALSE, operands[0], &offset);
})

;; Store multiple with write-back

(define_insn "*stmsi_postinc4"
  [(match_parallel 0 "store_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 16)))
     (set (mem:SI (match_dup 2))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
	  (match_operand:SI 5 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
  "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store4")]
)

;; APPLE LOCAL begin ARM compact switch tables
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*stmsi_postinc4_thumb1"
  [(match_parallel 0 "store_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=l")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 16)))
     (set (mem:SI (match_dup 2))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
	  (match_operand:SI 5 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
	  (match_operand:SI 6 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
  "stmia\\t%1!, {%3, %4, %5, %6}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "store4")
   (set_attr "length" "2")]
)
;; APPLE LOCAL end ARM compact switch tables

(define_insn "*stmsi_postinc3"
  [(match_parallel 0 "store_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 12)))
     (set (mem:SI (match_dup 2))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
  "stm%(ia%)\\t%1!, {%3, %4, %5}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store3")]
)

(define_insn "*stmsi_postinc2"
  [(match_parallel 0 "store_multiple_operation"
    [(set (match_operand:SI 1 "s_register_operand" "=r")
	  (plus:SI (match_operand:SI 2 "s_register_operand" "1")
		   (const_int 8)))
     (set (mem:SI (match_dup 2))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
  "stm%(ia%)\\t%1!, {%3, %4}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store2")]
)

;; Ordinary store multiple

(define_insn "*stmsi4"
  [(match_parallel 0 "store_multiple_operation"
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
	  (match_operand:SI 2 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
	  (match_operand:SI 5 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
  "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store4")]
)

(define_insn "*stmsi3"
  [(match_parallel 0 "store_multiple_operation"
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
	  (match_operand:SI 2 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
	  (match_operand:SI 4 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
  "stm%(ia%)\\t%1, {%2, %3, %4}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store3")]
)

(define_insn "*stmsi2"
  [(match_parallel 0 "store_multiple_operation"
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
	  (match_operand:SI 2 "arm_hard_register_operand" ""))
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
	  (match_operand:SI 3 "arm_hard_register_operand" ""))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
  "stm%(ia%)\\t%1, {%2, %3}"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "predicable" "yes")
   (set_attr "type" "store2")]
)

;; Move a block of memory if it is word aligned and MORE than 2 words long.
;; We could let this apply for blocks of less than this, but it clobbers so
;; many registers that there is then probably a better way.

(define_expand "movmemqi"
  [(match_operand:BLK 0 "general_operand" "")
   (match_operand:BLK 1 "general_operand" "")
   (match_operand:SI 2 "const_int_operand" "")
   (match_operand:SI 3 "const_int_operand" "")]
  "TARGET_EITHER"
  "
  /* APPLE LOCAL v7 support. Merge from mainline */
  if (TARGET_32BIT)
    {
      if (arm_gen_movmemqi (operands))
        DONE;
      FAIL;
    }
  else /* TARGET_THUMB */
    {
      if (   INTVAL (operands[3]) != 4
          || INTVAL (operands[2]) > 48)
        FAIL;

      /* APPLE LOCAL begin ARM use memcpy more at -Os */
      if (optimize_size
	  && INTVAL (operands[2]) != 1
	  && INTVAL (operands[2]) != 2
	  && INTVAL (operands[2]) != 4
	  && INTVAL (operands[2]) != 8
	  && INTVAL (operands[2]) != 12
	  && INTVAL (operands[2]) != 16)
	FAIL;
      /* APPLE LOCAL end ARM use memcpy more at -Os */

      thumb_expand_movmemqi (operands);
      DONE;
    }
  "
)

;; Thumb block-move insns

(define_insn "movmem12b"
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
	(mem:SI (match_operand:SI 3 "register_operand" "1")))
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
	(mem:SI (plus:SI (match_dup 3) (const_int 8))))
   (set (match_operand:SI 0 "register_operand" "=l")
	(plus:SI (match_dup 2) (const_int 12)))
   (set (match_operand:SI 1 "register_operand" "=l")
	(plus:SI (match_dup 3) (const_int 12)))
   (clobber (match_scratch:SI 4 "=&l"))
   (clobber (match_scratch:SI 5 "=&l"))
   (clobber (match_scratch:SI 6 "=&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "* return thumb_output_move_mem_multiple (3, operands);"
  [(set_attr "length" "4")
   ; This isn't entirely accurate...  It loads as well, but in terms of
   ; scheduling the following insn it is better to consider it as a store
   (set_attr "type" "store3")]
)

(define_insn "movmem8b"
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
	(mem:SI (match_operand:SI 3 "register_operand" "1")))
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
	(mem:SI (plus:SI (match_dup 3) (const_int 4))))
   (set (match_operand:SI 0 "register_operand" "=l")
	(plus:SI (match_dup 2) (const_int 8)))
   (set (match_operand:SI 1 "register_operand" "=l")
	(plus:SI (match_dup 3) (const_int 8)))
   (clobber (match_scratch:SI 4 "=&l"))
   (clobber (match_scratch:SI 5 "=&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "* return thumb_output_move_mem_multiple (2, operands);"
  [(set_attr "length" "4")
   ; This isn't entirely accurate...  It loads as well, but in terms of
   ; scheduling the following insn it is better to consider it as a store
   (set_attr "type" "store2")]
)



;; Compare & branch insns
;; The range calculations are based as follows:
;; For forward branches, the address calculation returns the address of
;; the next instruction.  This is 2 beyond the branch instruction.
;; For backward branches, the address calculation returns the address of
;; the first instruction in this pattern (cmp).  This is 2 before the branch
;; instruction for the shortest sequence, and 4 before the branch instruction
;; if we have to jump around an unconditional branch.
;; To the basic branch range the PC offset must be added (this is +4).
;; So for forward branches we have 
;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
;; And for backward branches we have 
;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
;;
;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).

(define_expand "cbranchsi4"
  [(set (pc) (if_then_else
	      (match_operator 0 "arm_comparison_operator"
	       [(match_operand:SI 1 "s_register_operand" "")
	        (match_operand:SI 2 "nonmemory_operand" "")])
	      (label_ref (match_operand 3 "" ""))
	      (pc)))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_THUMB1"
  "
  if (thumb1_cmpneg_operand (operands[2], SImode))
    {
      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
					      operands[3], operands[0]));
      DONE;
    }
  if (!thumb1_cmp_operand (operands[2], SImode))
    operands[2] = force_reg (SImode, operands[2]);
  ")
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "*cbranchsi4_insn"
  [(set (pc) (if_then_else
	      (match_operator 0 "arm_comparison_operator"
	       [(match_operand:SI 1 "s_register_operand" "l,*h")
;; APPLE LOCAL begin v7 support. Merge from mainline
	        (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
	      (label_ref (match_operand 3 "" ""))
	      (pc)))]
  "TARGET_THUMB1"
;; APPLE LOCAL end v7 support. Merge from mainline
  "*
  output_asm_insn (\"cmp\\t%1, %2\", operands);

  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d0\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D0\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D0\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)

(define_insn "cbranchsi4_scratch"
  [(set (pc) (if_then_else
	      (match_operator 4 "arm_comparison_operator"
	       [(match_operand:SI 1 "s_register_operand" "l,0")
;; APPLE LOCAL v7 support. Merge from mainline
	        (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
	      (label_ref (match_operand 3 "" ""))
	      (pc)))
   (clobber (match_scratch:SI 0 "=l,l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);

  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d4\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D4\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D4\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
(define_insn "*movsi_cbranchsi4"
  [(set (pc)
	(if_then_else
	 (match_operator 3 "arm_comparison_operator"
	  [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
	   (const_int 0)])
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
	(match_dup 1))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*{
  if (which_alternative == 0)
    output_asm_insn (\"cmp\t%0, #0\", operands);
  else if (which_alternative == 1)
    output_asm_insn (\"sub\t%0, %1, #0\", operands);
  else
    {
      output_asm_insn (\"cmp\t%1, #0\", operands);
      if (which_alternative == 2)
	output_asm_insn (\"mov\t%0, %1\", operands);
      else
	output_asm_insn (\"str\t%1, %0\", operands);
    }
  switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
    {
    case 4:  return \"b%d3\\t%l2\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D3\\t%~LCB%=\;b\\t%l2\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D3\\t%~LCB%=\;bl\\t%l2\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (gt (symbol_ref ("which_alternative"))
	                  (const_int 1))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (le (symbol_ref ("which_alternative"))
		       (const_int 1))
       (if_then_else
	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
	      (le (minus (match_dup 2) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
		(le (minus (match_dup 2) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
	      (le (minus (match_dup 2) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
		(le (minus (match_dup 2) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

;; APPLE LOCAL begin ARM add this peephole
;; The above pattern is produced by combine in some cases, but not
;; when one of the regs involved is hard, e.g. a function return value.
;; This peephole catches that case.  Valid only for low regs.

(define_peephole2
  [(set (match_operand:SI 0 "thumb_low_register_operand" "")
	(match_operand:SI 1 "thumb_low_register_operand" ""))
   (set (pc) (if_then_else
	      (match_operator 2 "arm_comparison_operator"
	       [(match_dup 0) (const_int 0)])
	      (label_ref (match_operand 3 "" ""))
	      (pc)))]
  "TARGET_THUMB"
  [(parallel
     [(set (pc)
	(if_then_else
	 (match_op_dup 2
	  [(match_dup 1) (const_int 0)])
	 (label_ref (match_dup 3 ))
	 (pc)))
     (set (match_dup 0) (match_dup 1))])]
   ""
)
;; APPLE LOCAL end ARM add this peephole

(define_insn "*negated_cbranchsi4"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "equality_operator"
	  [(match_operand:SI 1 "s_register_operand" "l")
	   (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  output_asm_insn (\"cmn\\t%1, %2\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d0\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D0\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D0\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)

(define_insn "*tbit_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "equality_operator"
	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
			    (const_int 1)
			    (match_operand:SI 2 "const_int_operand" "i"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 4 "=l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  rtx op[3];
  op[0] = operands[4];
  op[1] = operands[1];
  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));

  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d0\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D0\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D0\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*tlobits_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "equality_operator"
	  [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
			    (match_operand:SI 2 "const_int_operand" "i")
			    (const_int 0))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 4 "=l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  rtx op[3];
  op[0] = operands[4];
  op[1] = operands[1];
  op[2] = GEN_INT (32 - INTVAL (operands[2]));

  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d0\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D0\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D0\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*tstsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 3 "equality_operator"
	  [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
		   (match_operand:SI 1 "s_register_operand" "l"))
	   (const_int 0)])
	 (label_ref (match_operand 2 "" ""))
	 (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  output_asm_insn (\"tst\\t%0, %1\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d3\\t%l2\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D3\\t%~LCB%=\;b\\t%l2\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D3\\t%~LCB%=\;bl\\t%l2\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 2) (pc)) (const_int -250))
	         (le (minus (match_dup 2) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
		     (le (minus (match_dup 2) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*andsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 5 "equality_operator"
	  [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
	(and:SI (match_dup 2) (match_dup 3)))
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  if (which_alternative == 0)
    output_asm_insn (\"and\\t%0, %3\", operands);
  else if (which_alternative == 1)
    {
      output_asm_insn (\"and\\t%1, %3\", operands);
      output_asm_insn (\"mov\\t%0, %1\", operands);
    }
  else
    {
      output_asm_insn (\"and\\t%1, %3\", operands);
      output_asm_insn (\"str\\t%1, %0\", operands);
    }

  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
    {
    case 4:  return \"b%d5\\t%l4\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D5\\t%~LCB%=\;b\\t%l4\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D5\\t%~LCB%=\;bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (eq (symbol_ref ("which_alternative"))
		       (const_int 0))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*orrsi3_cbranch_scratch"
  [(set (pc)
	(if_then_else
	 (match_operator 4 "equality_operator"
	  [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
		   (match_operand:SI 2 "s_register_operand" "l"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 0 "=l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  output_asm_insn (\"orr\\t%0, %2\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d4\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D4\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D4\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*orrsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 5 "equality_operator"
	  [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
	(ior:SI (match_dup 2) (match_dup 3)))
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  if (which_alternative == 0)
    output_asm_insn (\"orr\\t%0, %3\", operands);
  else if (which_alternative == 1)
    {
      output_asm_insn (\"orr\\t%1, %3\", operands);
      output_asm_insn (\"mov\\t%0, %1\", operands);
    }
  else
    {
      output_asm_insn (\"orr\\t%1, %3\", operands);
      output_asm_insn (\"str\\t%1, %0\", operands);
    }

  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
    {
    case 4:  return \"b%d5\\t%l4\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D5\\t%~LCB%=\;b\\t%l4\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D5\\t%~LCB%=\;bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (eq (symbol_ref ("which_alternative"))
		       (const_int 0))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*xorsi3_cbranch_scratch"
  [(set (pc)
	(if_then_else
	 (match_operator 4 "equality_operator"
	  [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
		   (match_operand:SI 2 "s_register_operand" "l"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 0 "=l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  output_asm_insn (\"eor\\t%0, %2\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d4\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D4\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D4\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*xorsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 5 "equality_operator"
	  [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
		   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
	(xor:SI (match_dup 2) (match_dup 3)))
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  if (which_alternative == 0)
    output_asm_insn (\"eor\\t%0, %3\", operands);
  else if (which_alternative == 1)
    {
      output_asm_insn (\"eor\\t%1, %3\", operands);
      output_asm_insn (\"mov\\t%0, %1\", operands);
    }
  else
    {
      output_asm_insn (\"eor\\t%1, %3\", operands);
      output_asm_insn (\"str\\t%1, %0\", operands);
    }

  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
    {
    case 4:  return \"b%d5\\t%l4\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D5\\t%~LCB%=\;b\\t%l4\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D5\\t%~LCB%=\;bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (eq (symbol_ref ("which_alternative"))
		       (const_int 0))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*bicsi3_cbranch_scratch"
  [(set (pc)
	(if_then_else
	 (match_operator 4 "equality_operator"
	  [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
		   (match_operand:SI 1 "s_register_operand" "0"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 0 "=l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  output_asm_insn (\"bic\\t%0, %2\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d4\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D4\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D4\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)
  
(define_insn "*bicsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 5 "equality_operator"
	  [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
		   (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
	(and:SI (not:SI (match_dup 3)) (match_dup 2)))
   (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  {
  if (which_alternative == 0)
    output_asm_insn (\"bic\\t%0, %3\", operands);
  else if (which_alternative <= 2)
    {
      output_asm_insn (\"bic\\t%1, %3\", operands);
      /* It's ok if OP0 is a lo-reg, even though the mov will set the
	 conditions again, since we're only testing for equality.  */
      output_asm_insn (\"mov\\t%0, %1\", operands);
    }
  else
    {
      output_asm_insn (\"bic\\t%1, %3\", operands);
      output_asm_insn (\"str\\t%1, %0\", operands);
    }

  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
    {
    case 4:  return \"b%d5\\t%l4\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D5\\t%~LCB%=\;b\\t%l4\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D5\\t%~LCB%=\;bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  }"
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (eq (symbol_ref ("which_alternative"))
		       (const_int 0))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*cbranchne_decr1"
  [(set (pc)
	(if_then_else (match_operator 3 "equality_operator"
		       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
		        (const_int 0)])
		      (label_ref (match_operand 4 "" ""))
		      (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
	(plus:SI (match_dup 2) (const_int -1)))
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
   {
     rtx cond[2];
     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
				? GEU : LTU),
			       VOIDmode, operands[2], const1_rtx);
     cond[1] = operands[4];

     if (which_alternative == 0)
       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
     else if (which_alternative == 1)
       {
	 /* We must provide an alternative for a hi reg because reload 
	    cannot handle output reloads on a jump instruction, but we
	    can't subtract into that.  Fortunately a mov from lo to hi
	    does not clobber the condition codes.  */
	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
	 output_asm_insn (\"mov\\t%0, %1\", operands);
       }
     else
       {
	 /* Similarly, but the target is memory.  */
	 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
	 output_asm_insn (\"str\\t%1, %0\", operands);
       }

     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
       {
	 /* APPLE LOCAL begin ARM MACH assembler */
	 case 4:
	   output_asm_insn (\"b%d0\\t%l1\", cond);
	   return \"\";
	 case 6:
	   output_asm_insn (\"b%D0\\t%~LCB%=\", cond);
	   return \"b\\t%l4\\t%@long jump\\n%~LCB%=:\";
	 default:
	   output_asm_insn (\"b%D0\\t%~LCB%=\", cond);
	   return \"bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
	 /* APPLE LOCAL end ARM MACH assembler */
       }
   }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set_attr_alternative "length"
      [
       ;; Alternative 0
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       ;; Alternative 1
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))
       ;; Alternative 2
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))
       ;; Alternative 3
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))])]
)

(define_insn "*addsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 4 "comparison_operator"
	  [(plus:SI
	    (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
	    (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
	   (const_int 0)])
	 (label_ref (match_operand 5 "" ""))
	 (pc)))
   (set
    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
    (plus:SI (match_dup 2) (match_dup 3)))
   (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (GET_CODE (operands[4]) == EQ
       || GET_CODE (operands[4]) == NE
       || GET_CODE (operands[4]) == GE
       || GET_CODE (operands[4]) == LT)"
  "*
   {
     rtx cond[3];

     
     cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
     cond[1] = operands[2];
     cond[2] = operands[3];

     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
     else
       output_asm_insn (\"add\\t%0, %1, %2\", cond);

     if (which_alternative >= 3
	 && which_alternative < 4)
       output_asm_insn (\"mov\\t%0, %1\", operands);
     else if (which_alternative >= 4)
       output_asm_insn (\"str\\t%1, %0\", operands);

     switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
       {
	 case 4:
	   return \"b%d4\\t%l5\";
	 /* APPLE LOCAL begin ARM MACH assembler */
	 case 6:
	   return \"b%D4\\t%~LCB%=\;b\\t%l5\\t%@long jump\\n%~LCB%=:\";
	 default:
	   return \"b%D4\\t%~LCB%=\;bl\\t%l5\\t%@far jump\\n%~LCB%=:\";
	 /* APPLE LOCAL end ARM MACH assembler */
       }
   }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (lt (symbol_ref ("which_alternative"))
	                  (const_int 3))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (lt (symbol_ref ("which_alternative"))
		       (const_int 3))
       (if_then_else
	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
	      (le (minus (match_dup 5) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
		(le (minus (match_dup 5) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
	      (le (minus (match_dup 5) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
		(le (minus (match_dup 5) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*addsi3_cbranch_scratch"
  [(set (pc)
	(if_then_else
	 (match_operator 3 "comparison_operator"
	  [(plus:SI
	    (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
	    (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (GET_CODE (operands[3]) == EQ
       || GET_CODE (operands[3]) == NE
       || GET_CODE (operands[3]) == GE
       || GET_CODE (operands[3]) == LT)"
  "*
   {
     switch (which_alternative)
       {
       case 0:
	 output_asm_insn (\"cmp\t%1, #%n2\", operands);
	 break;
       case 1:
	 output_asm_insn (\"cmn\t%1, %2\", operands);
	 break;
       case 2:
	 if (INTVAL (operands[2]) < 0)
	   output_asm_insn (\"sub\t%0, %1, %2\", operands);
	 else
	   output_asm_insn (\"add\t%0, %1, %2\", operands);
	 break;
       case 3:
	 if (INTVAL (operands[2]) < 0)
	   output_asm_insn (\"sub\t%0, %0, %2\", operands);
	 else
	   output_asm_insn (\"add\t%0, %0, %2\", operands);
	 break;
       }

     switch (get_attr_length (insn))
       {
	 case 4:
	   return \"b%d3\\t%l4\";
	 /* APPLE LOCAL begin ARM MACH assembler */
	 case 6:
	   return \"b%D3\\t%~LCB%=\;b\\t%l4\\t%@long jump\\n%~LCB%=:\";
	 default:
	   return \"b%D3\\t%~LCB%=\;bl\\t%l4\\t%@far jump\\n%~LCB%=:\";
	 /* APPLE LOCAL end ARM MACH assembler */
       }
   }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
       (if_then_else
	 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
	      (le (minus (match_dup 4) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
		(le (minus (match_dup 4) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8))))]
)

(define_insn "*subsi3_cbranch"
  [(set (pc)
	(if_then_else
	 (match_operator 4 "comparison_operator"
	  [(minus:SI
	    (match_operand:SI 2 "s_register_operand" "l,l,1,l")
	    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
	   (const_int 0)])
	 (label_ref (match_operand 5 "" ""))
	 (pc)))
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
	(minus:SI (match_dup 2) (match_dup 3)))
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (GET_CODE (operands[4]) == EQ
       || GET_CODE (operands[4]) == NE
       || GET_CODE (operands[4]) == GE
       || GET_CODE (operands[4]) == LT)"
  "*
   {
     if (which_alternative == 0)
       output_asm_insn (\"sub\\t%0, %2, %3\", operands);
     else if (which_alternative == 1)
       {
	 /* We must provide an alternative for a hi reg because reload 
	    cannot handle output reloads on a jump instruction, but we
	    can't subtract into that.  Fortunately a mov from lo to hi
	    does not clobber the condition codes.  */
	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
	 output_asm_insn (\"mov\\t%0, %1\", operands);
       }
     else
       {
	 /* Similarly, but the target is memory.  */
	 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
	 output_asm_insn (\"str\\t%1, %0\", operands);
       }

     switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
       {
	 case 4:
	   return \"b%d4\\t%l5\";
	 /* APPLE LOCAL begin ARM MACH assembler */
	 case 6:
	   return \"b%D4\\t%~LCB%=\;b\\t%l5\\t%@long jump\\n%~LCB%=:\";
	 default:
	   return \"b%D4\\t%~LCB%=\;bl\\t%l5\\t%@far jump\\n%~LCB%=:\";
	 /* APPLE LOCAL end ARM MACH assembler */
       }
   }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (ior (and (eq (symbol_ref ("which_alternative"))
	                  (const_int 0))
		      (eq_attr "length" "8"))
		 (eq_attr "length" "10"))
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length")
     (if_then_else
       (eq (symbol_ref ("which_alternative"))
		       (const_int 0))
       (if_then_else
	 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
	      (le (minus (match_dup 5) (pc)) (const_int 256)))
	 (const_int 4)
	 (if_then_else
	   (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
		(le (minus (match_dup 5) (pc)) (const_int 2048)))
	   (const_int 6)
	   (const_int 8)))
       (if_then_else
	 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
	      (le (minus (match_dup 5) (pc)) (const_int 256)))
	 (const_int 6)
	 (if_then_else
	   (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
		(le (minus (match_dup 5) (pc)) (const_int 2048)))
	   (const_int 8)
	   (const_int 10)))))]
)

(define_insn "*subsi3_cbranch_scratch"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "arm_comparison_operator"
	  [(minus:SI (match_operand:SI 1 "register_operand" "l")
		     (match_operand:SI 2 "nonmemory_operand" "l"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1
   && (GET_CODE (operands[0]) == EQ
       || GET_CODE (operands[0]) == NE
       || GET_CODE (operands[0]) == GE
       || GET_CODE (operands[0]) == LT)"
  "*
  output_asm_insn (\"cmp\\t%1, %2\", operands);
  switch (get_attr_length (insn))
    {
    case 4:  return \"b%d0\\t%l3\";
    /* APPLE LOCAL begin ARM MACH assembler */
    case 6:  return \"b%D0\\t%~LCB%=\;b\\t%l3\\t%@long jump\\n%~LCB%=:\";
    default: return \"b%D0\\t%~LCB%=\;bl\\t%l3\\t%@far jump\\n%~LCB%=:\";
    /* APPLE LOCAL end ARM MACH assembler */
    }
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "8")
	    (const_string "yes")
            (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 3) (pc)) (const_int -250))
	         (le (minus (match_dup 3) (pc)) (const_int 256)))
	    (const_int 4)
	    (if_then_else
	        (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
		     (le (minus (match_dup 3) (pc)) (const_int 2048)))
		(const_int 6)
		(const_int 8))))]
)

;; Comparison and test insns

(define_expand "cmpsi"
  [(match_operand:SI 0 "s_register_operand" "")
   (match_operand:SI 1 "arm_add_operand" "")]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "{
    arm_compare_op0 = operands[0];
    arm_compare_op1 = operands[1];
    DONE;
  }"
)

(define_expand "cmpsf"
  [(match_operand:SF 0 "s_register_operand" "")
   (match_operand:SF 1 "arm_float_compare_operand" "")]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  arm_compare_op0 = operands[0];
  arm_compare_op1 = operands[1];
  DONE;
  "
)

(define_expand "cmpdf"
  [(match_operand:DF 0 "s_register_operand" "")
   (match_operand:DF 1 "arm_float_compare_operand" "")]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT"
  "
  arm_compare_op0 = operands[0];
  arm_compare_op1 = operands[1];
  DONE;
  "
)

;; APPLE LOCAL begin ARM enhance conditional insn generation
(define_insn "*arm_cmpsi_insn"
  [(set (reg:CC CC_REGNUM)
	(compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
		    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "@
   cmp%?\\t%0, %1
   cmn%?\\t%0, #%n1"
  [(set_attr "conds" "set")
   (set_attr "predicable" "yes")]
)
;; APPLE LOCAL end ARM enhance conditional insn generation

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_cmpsi_shiftsi"
  [(set (reg:CC CC_REGNUM)
	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
		    (match_operator:SI  3 "shift_operator"
		     [(match_operand:SI 1 "s_register_operand" "r")
		      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
  "TARGET_ARM"
  "cmp%?\\t%0, %1%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "1")
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_cmpsi_shiftsi_swp"
  [(set (reg:CC_SWP CC_REGNUM)
	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
			 [(match_operand:SI 1 "s_register_operand" "r")
			  (match_operand:SI 2 "reg_or_int_operand" "rM")])
			(match_operand:SI 0 "s_register_operand" "r")))]
  "TARGET_ARM"
  "cmp%?\\t%0, %1%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "1")
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*arm_cmpsi_negshiftsi_si"
  [(set (reg:CC_Z CC_REGNUM)
	(compare:CC_Z
	 (neg:SI (match_operator:SI 1 "shift_operator"
		    [(match_operand:SI 2 "s_register_operand" "r")
		     (match_operand:SI 3 "reg_or_int_operand" "rM")]))
	 (match_operand:SI 0 "s_register_operand" "r")))]
  "TARGET_ARM"
  "cmn%?\\t%0, %2%S1"
  [(set_attr "conds" "set")
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
				    (const_string "alu_shift")
				    (const_string "alu_shift_reg")))]
)

;; Cirrus SF compare instruction
(define_insn "*cirrus_cmpsf"
  [(set (reg:CCFP CC_REGNUM)
	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "cfcmps%?\\tr15, %V0, %V1"
  [(set_attr "type"   "mav_farith")
   (set_attr "cirrus" "compare")]
)

;; Cirrus DF compare instruction
(define_insn "*cirrus_cmpdf"
  [(set (reg:CCFP CC_REGNUM)
	(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
		      (match_operand:DF 1 "cirrus_fp_register" "v")))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "cfcmpd%?\\tr15, %V0, %V1"
  [(set_attr "type"   "mav_farith")
   (set_attr "cirrus" "compare")]
)

;; Cirrus DI compare instruction
(define_expand "cmpdi"
  [(match_operand:DI 0 "cirrus_fp_register" "")
   (match_operand:DI 1 "cirrus_fp_register" "")]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "{
     arm_compare_op0 = operands[0];
     arm_compare_op1 = operands[1];
     DONE;
   }")

(define_insn "*cirrus_cmpdi"
  [(set (reg:CC CC_REGNUM)
	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
		    (match_operand:DI 1 "cirrus_fp_register" "v")))]
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
  "cfcmp64%?\\tr15, %V0, %V1"
  [(set_attr "type"   "mav_farith")
   (set_attr "cirrus" "compare")]
)

; This insn allows redundant compares to be removed by cse, nothing should
; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
; is deleted later on. The match_dup will match the mode here, so that
; mode changes of the condition codes aren't lost by this even though we don't
; specify what they are.

(define_insn "*deleted_compare"
  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "\\t%@ deleted compare"
  [(set_attr "conds" "set")
   (set_attr "length" "0")]
)


;; Conditional branch insns

(define_expand "beq"
  [(set (pc)
	(if_then_else (eq (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bne"
  [(set (pc)
	(if_then_else (ne (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bgt"
  [(set (pc)
	(if_then_else (gt (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "ble"
  [(set (pc)
	(if_then_else (le (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bge"
  [(set (pc)
	(if_then_else (ge (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "blt"
  [(set (pc)
	(if_then_else (lt (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bgtu"
  [(set (pc)
	(if_then_else (gtu (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bleu"
  [(set (pc)
	(if_then_else (leu (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bgeu"
  [(set (pc)
	(if_then_else (geu (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bltu"
  [(set (pc)
	(if_then_else (ltu (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bunordered"
  [(set (pc)
	(if_then_else (unordered (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "bordered"
  [(set (pc)
	(if_then_else (ordered (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "bungt"
  [(set (pc)
	(if_then_else (ungt (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bunlt"
  [(set (pc)
	(if_then_else (unlt (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bunge"
  [(set (pc)
	(if_then_else (unge (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bunle"
  [(set (pc)
	(if_then_else (unle (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
)

;; The following two patterns need two branch instructions, since there is
;; no single instruction that will handle all cases.
(define_expand "buneq"
  [(set (pc)
	(if_then_else (uneq (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
)

(define_expand "bltgt"
  [(set (pc)
	(if_then_else (ltgt (match_dup 1) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
)

;;
;; Patterns to match conditional branch insns.
;;

; Special pattern to match UNEQ.
(define_insn "*arm_buneq"
  [(set (pc)
	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "*
  gcc_assert (!arm_ccfsm_state);

  return \"bvs\\t%l0\;beq\\t%l0\";
  "
  [(set_attr "conds" "jump_clob")
   (set_attr "length" "8")]
)

; Special pattern to match LTGT.
(define_insn "*arm_bltgt"
  [(set (pc)
	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "*
  gcc_assert (!arm_ccfsm_state);

  return \"bmi\\t%l0\;bgt\\t%l0\";
  "
  [(set_attr "conds" "jump_clob")
   (set_attr "length" "8")]
)

(define_insn "*arm_cond_branch"
  [(set (pc)
	(if_then_else (match_operator 1 "arm_comparison_operator"
		       [(match_operand 2 "cc_register" "") (const_int 0)])
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
    {
      arm_ccfsm_state += 2;
      return \"\";
    }
  return \"b%d1\\t%l0\";
  "
  [(set_attr "conds" "use")
   (set_attr "type" "branch")]
)

; Special pattern to match reversed UNEQ.
(define_insn "*arm_buneq_reversed"
  [(set (pc)
	(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "*
  gcc_assert (!arm_ccfsm_state);

  return \"bmi\\t%l0\;bgt\\t%l0\";
  "
  [(set_attr "conds" "jump_clob")
   (set_attr "length" "8")]
)

; Special pattern to match reversed LTGT.
(define_insn "*arm_bltgt_reversed"
  [(set (pc)
	(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "*
  gcc_assert (!arm_ccfsm_state);

  return \"bvs\\t%l0\;beq\\t%l0\";
  "
  [(set_attr "conds" "jump_clob")
   (set_attr "length" "8")]
)

(define_insn "*arm_cond_branch_reversed"
  [(set (pc)
	(if_then_else (match_operator 1 "arm_comparison_operator"
		       [(match_operand 2 "cc_register" "") (const_int 0)])
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
    {
      arm_ccfsm_state += 2;
      return \"\";
    }
  return \"b%D1\\t%l0\";
  "
  [(set_attr "conds" "use")
   (set_attr "type" "branch")]
)



; scc insns

(define_expand "seq"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(eq:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sne"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ne:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sgt"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(gt:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sle"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(le:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sge"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ge:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
)

(define_expand "slt"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(lt:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sgtu"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(gtu:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sleu"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(leu:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sgeu"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(geu:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sltu"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ltu:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
)

(define_expand "sunordered"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(unordered:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "sordered"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ordered:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "sungt"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ungt:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "sunge"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(unge:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "sunlt"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(unlt:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
				      arm_compare_op1);"
)

(define_expand "sunle"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(unle:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
				      arm_compare_op1);"
)

;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
;;; simple ARM instructions. 
;
; (define_expand "suneq"
;   [(set (match_operand:SI 0 "s_register_operand" "")
; 	(uneq:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
;   "gcc_unreachable ();"
; )
;
; (define_expand "sltgt"
;   [(set (match_operand:SI 0 "s_register_operand" "")
; 	(ltgt:SI (match_dup 1) (const_int 0)))]
;; APPLE LOCAL v7 support. Merge from mainline
;   "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
;   "gcc_unreachable ();"
; )

(define_insn "*mov_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(match_operator:SI 1 "arm_comparison_operator"
	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
  "TARGET_ARM"
  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)

(define_insn "*mov_negscc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
  "TARGET_ARM"
  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)

(define_insn "*mov_notscc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(not:SI (match_operator:SI 1 "arm_comparison_operator"
		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
  "TARGET_ARM"
  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)


;; Conditional move insns

(define_expand "movsicc"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
			 (match_operand:SI 2 "arm_not_operand" "")
			 (match_operand:SI 3 "arm_not_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  {
    enum rtx_code code = GET_CODE (operands[1]);
    rtx ccreg;

    if (code == UNEQ || code == LTGT)
      FAIL;

    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
  }"
)

(define_expand "movsfcc"
  [(set (match_operand:SF 0 "s_register_operand" "")
	(if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
			 (match_operand:SF 2 "s_register_operand" "")
			 (match_operand:SF 3 "nonmemory_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "
  {
    enum rtx_code code = GET_CODE (operands[1]);
    rtx ccreg;

    if (code == UNEQ || code == LTGT)
      FAIL;

    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
       Otherwise, ensure it is a valid FP add operand */
    if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
        || (!arm_float_add_operand (operands[3], SFmode)))
      operands[3] = force_reg (SFmode, operands[3]);

    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
  }"
)

(define_expand "movdfcc"
  [(set (match_operand:DF 0 "s_register_operand" "")
	(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
			 (match_operand:DF 2 "s_register_operand" "")
			 (match_operand:DF 3 "arm_float_add_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
  "
  {
    enum rtx_code code = GET_CODE (operands[1]);
    rtx ccreg;

    if (code == UNEQ || code == LTGT)
      FAIL;

    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
  }"
)

(define_insn "*movsicc_insn"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
	(if_then_else:SI
	 (match_operator 3 "arm_comparison_operator"
	  [(match_operand 4 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
  "TARGET_ARM"
  "@
   mov%D3\\t%0, %2
   mvn%D3\\t%0, #%B2
   mov%d3\\t%0, %1
   mvn%d3\\t%0, #%B1
   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
  [(set_attr "length" "4,4,4,4,8,8,8,8")
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
   (set_attr "conds" "use")
   (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)

(define_insn "*movsfcc_soft_insn"
  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
			  [(match_operand 4 "cc_register" "") (const_int 0)])
			 (match_operand:SF 1 "s_register_operand" "0,r")
			 (match_operand:SF 2 "s_register_operand" "r,0")))]
  "TARGET_ARM && TARGET_SOFT_FLOAT"
  "@
   mov%D3\\t%0, %2
   mov%d3\\t%0, %1"
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
  [(set_attr "conds" "use")
   (set_attr "insn" "mov")]
;; APPLE LOCAL end v7 support. Merge from Codesourcery
)


;; Jump and linkage insns

(define_expand "jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  "TARGET_EITHER"
  ""
)

(define_insn "*arm_jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  "TARGET_ARM"
  "*
  {
    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
      {
        arm_ccfsm_state += 2;
        return \"\";
      }
    return \"b%?\\t%l0\";
  }
  "
  [(set_attr "predicable" "yes")]
)

;; APPLE LOCAL begin v7 support. Merge from mainline
(define_insn "*thumb2_jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  "TARGET_THUMB2"
  "*
    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
      {
        arm_ccfsm_state += 2;
        return \"\";
      }
    return \"b\\t%l0\";
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "4")
	    (const_string "yes")
	    (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
		 (le (minus (match_dup 0) (pc)) (const_int 2048)))
  	    (const_int 2)
	    (const_int 4)))]
)
;; APPLE LOCAL end v7 support. Merge from mainline

(define_insn "*thumb_jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  if (get_attr_length (insn) == 2)
    return \"b\\t%l0\";
  return \"bl\\t%l0\\t%@ far jump\";
  "
  [(set (attr "far_jump")
        (if_then_else
	    (eq_attr "length" "4")
	    (const_string "yes")
	    (const_string "no")))
   (set (attr "length") 
        (if_then_else
	    (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
		 (le (minus (match_dup 0) (pc)) (const_int 2048)))
  	    (const_int 2)
	    (const_int 4)))]
)

(define_expand "call"
  [(parallel [(call (match_operand 0 "memory_operand" "")
	            (match_operand 1 "general_operand" ""))
	      (use (match_operand 2 "" ""))
	      (clobber (reg:SI LR_REGNUM))])]
  "TARGET_EITHER"
  "
  {
    rtx callee;
    
    /* APPLE LOCAL begin ARM dynamic */
    /* In an untyped call, we can get NULL for operand 2.  */
    if (operands[2] == NULL_RTX)
      operands[2] = const0_rtx;
      
#if TARGET_MACHO
    if (MACHOPIC_INDIRECT
	&& !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
      operands[0] = machopic_indirect_call_target (operands[0]);
#endif

    /* This is to decide if we should generate indirect calls by loading the
       32 bit address of the callee into a register before performing the
       branch and link.  operand[2] encodes the long_call/short_call
       attribute of the function being called.  This attribute is set whenever
       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
       is used, and the short_call attribute can also be set if function is
       declared as static or if it has already been defined in the current
       compilation unit.  See arm.c and arm.h for info about this.  The third
       parameter to arm_is_longcall_p is used to tell it which pattern
       invoked it.  */
    callee  = XEXP (operands[0], 0);
    /* APPLE LOCAL end ARM dynamic */
    
    if ((GET_CODE (callee) == SYMBOL_REF
	 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
	|| (GET_CODE (callee) != SYMBOL_REF
	    && GET_CODE (callee) != REG))
      XEXP (operands[0], 0) = force_reg (Pmode, callee);
  }"
)

;; APPLE LOCAL begin 5831528 make calls predicable
(define_insn "*call_reg_armv5"
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
         (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM && arm_arch5"
  "blx%?\\t%0"
  [(set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_reg_arm"
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
         (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM && !arm_arch5"
  "*
  return output_call (operands);
  "
  ;; length is worst case, normally it is only two
  [(set_attr "length" "12")
   (set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_mem"
  [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
	 (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM"
  "*
  return output_call_mem (operands);
  "
  [(set_attr "length" "12")
   (set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*call_reg_thumb1_v5"
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
	 (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch5"
  "blx\\t%0"
  [(set_attr "length" "2")
   (set_attr "type" "call")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*call_reg_thumb1"
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
	 (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && !arm_arch5"
  "*
  {
    if (!TARGET_CALLER_INTERWORKING)
      return thumb_call_via_reg (operands[0]);
    else if (operands[1] == const0_rtx)
      return \"bl\\t%__interwork_call_via_%0\";
    else if (frame_pointer_needed)
      return \"bl\\t%__interwork_r7_call_via_%0\";
    else
      return \"bl\\t%__interwork_r11_call_via_%0\";
  }"
  [(set_attr "type" "call")]
)

(define_expand "call_value"
  [(parallel [(set (match_operand       0 "" "")
	           (call (match_operand 1 "memory_operand" "")
		         (match_operand 2 "general_operand" "")))
	      (use (match_operand 3 "" ""))
	      (clobber (reg:SI LR_REGNUM))])]
  "TARGET_EITHER"
  "
  {
    /* APPLE LOCAL begin ARM dynamic */
    rtx callee;

    /* In an untyped call, we can get NULL for operand 2.  */
    if (operands[3] == 0)
      operands[3] = const0_rtx;

#if TARGET_MACHO
    if (MACHOPIC_INDIRECT
	&& !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
      operands[1] = machopic_indirect_call_target (operands[1]);
#endif

    callee = XEXP (operands[1], 0);
    /* APPLE LOCAL end ARM dynamic */
    
    /* See the comment in define_expand \"call\".  */
    if ((GET_CODE (callee) == SYMBOL_REF
	 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
	|| (GET_CODE (callee) != SYMBOL_REF
	    && GET_CODE (callee) != REG))
      XEXP (operands[1], 0) = force_reg (Pmode, callee);
  }"
)

(define_insn "*call_value_reg_armv5"
  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM && arm_arch5"
  "blx%?\\t%1"
  [(set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_value_reg_arm"
  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM && !arm_arch5"
  "*
  return output_call (&operands[1]);
  "
  [(set_attr "length" "12")
   (set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_value_mem"
  [(set (match_operand 0 "" "")
	(call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
  "*
  return output_call_mem (&operands[1]);
  "
  [(set_attr "length" "12")
   (set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*call_value_reg_thumb1_v5"
  [(set (match_operand 0 "" "")
	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && arm_arch5"
  "blx\\t%1"
  [(set_attr "length" "2")
   (set_attr "type" "call")]
)

;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*call_value_reg_thumb1"
  [(set (match_operand 0 "" "")
	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1 && !arm_arch5"
  "*
  {
    if (!TARGET_CALLER_INTERWORKING)
      return thumb_call_via_reg (operands[1]);
    else if (operands[2] == const0_rtx)
      return \"bl\\t%__interwork_call_via_%1\";
    else if (frame_pointer_needed)
      return \"bl\\t%__interwork_r7_call_via_%1\";
    else
      return \"bl\\t%__interwork_r11_call_via_%1\";
  }"
  [(set_attr "type" "call")]
)

;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.

;; APPLE LOCAL begin ARM pic support
;; Prevent these patterns from being used with dynamic symbol_refs.  An
;; alternate approach would be to generate a stub, but this would be
;; of questionnable value, as these patterns are not generally used
;; for dynamic code anyway (see rdar://4514281 for an example of what it
;; takes to get here).
(define_insn "*call_symbol_predicable"
  [(call (mem:SI (match_operand:SI 0 "arm_branch_target" ""))
	 (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM
   && !TARGET_INTERWORK
   && (GET_CODE (operands[0]) == SYMBOL_REF)
   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
  "*
  {
    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
  }"
  [(set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_symbol"
  [(call (mem:SI (match_operand:SI 0 "arm_branch_target" ""))
        (match_operand 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM
   && TARGET_INTERWORK
   && (GET_CODE (operands[0]) == SYMBOL_REF)
   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
  "*
  {
    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
  }"
  [(set_attr "type" "call")]
)

(define_insn "*call_value_symbol_predicable"
  [(set (match_operand 0 "" "")
	(call (mem:SI (match_operand:SI 1 "arm_branch_target" ""))
	(match_operand:SI 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM
   && !TARGET_INTERWORK
   && (GET_CODE (operands[1]) == SYMBOL_REF)
   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
  "*
  {
    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
  }"
  [(set_attr "type" "call")
   (set_attr "predicable" "yes")]
)

(define_insn "*call_value_symbol"
  [(set (match_operand 0 "" "")
        (call (mem:SI (match_operand:SI 1 "arm_branch_target" ""))
        (match_operand:SI 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_ARM
   && TARGET_INTERWORK
   && (GET_CODE (operands[1]) == SYMBOL_REF)
   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
  "*
  {
    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
  }"
  [(set_attr "type" "call")]
)
;; APPLE LOCAL end 5831528 make calls predicable
;; APPLE LOCAL end ARM pic support

;; APPLE LOCAL begin ARM dynamic
(define_insn "*call_insn"
  [(call (mem:SI (match_operand:SI 0 "arm_branch_target" ""))
	 (match_operand:SI 1 "" ""))
   (use (match_operand 2 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_THUMB
   && GET_CODE (operands[0]) == SYMBOL_REF
   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
  "*
  {
#if TARGET_MACHO
    if (machopic_lookup_stub_or_non_lazy_ptr (XSTR (operands[0], 0)))
      return \"blx\\t%a0\";
    else
#endif
      return \"bl\\t%a0\";
  }"
  [(set_attr "length" "4")
   (set_attr "type" "call")]
)

(define_insn "*call_value_insn"
  [(set (match_operand 0 "" "")
	(call (mem:SI (match_operand 1 "arm_branch_target" ""))
	      (match_operand 2 "" "")))
   (use (match_operand 3 "" ""))
   (clobber (reg:SI LR_REGNUM))]
  "TARGET_THUMB
   && GET_CODE (operands[1]) == SYMBOL_REF
   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
  "*
  {
#if TARGET_MACHO
    if (machopic_lookup_stub_or_non_lazy_ptr (XSTR (operands[1], 0)))
      return \"blx\\t%a1\";
    else
#endif
      return \"bl\\t%a1\";
  }"
  [(set_attr "length" "4")
   (set_attr "type" "call")]
)
;; APPLE LOCAL end ARM dynamic

;; We may also be able to do sibcalls for Thumb, but it's much harder...
(define_expand "sibcall"
  [(parallel [(call (match_operand 0 "memory_operand" "")
		    (match_operand 1 "general_operand" ""))
	      (return)
	      (use (match_operand 2 "" ""))])]
  "TARGET_ARM"
  "
  {
/* APPLE LOCAL begin ARM dynamic */
#if TARGET_MACHO
    if (MACHOPIC_INDIRECT)
      operands[0] = machopic_indirect_call_target (operands[0]);
#endif
/* APPLE LOCAL end ARM dynamic */

    if (operands[2] == NULL_RTX)
      operands[2] = const0_rtx;
  }"
)

(define_expand "sibcall_value"
  [(parallel [(set (match_operand 0 "" "")
		   (call (match_operand 1 "memory_operand" "")
			 (match_operand 2 "general_operand" "")))
	      (return)
	      (use (match_operand 3 "" ""))])]
  "TARGET_ARM"
  "
  {
/* APPLE LOCAL begin ARM dynamic */
#if TARGET_MACHO
    if (MACHOPIC_INDIRECT)
      operands[1] = machopic_indirect_call_target (operands[1]);
#endif
/* APPLE LOCAL end ARM dynamic */

    if (operands[3] == NULL_RTX)
      operands[3] = const0_rtx;
  }"
)

;; APPLE LOCAL begin ARM indirect sibcalls
(define_insn "*sibcall_insn"
 [(call (mem:SI (match_operand:SI 0 "arm_branch_target" "X"))
        (match_operand 1 "" ""))
  (return)
  (use (match_operand 2 "" ""))]
  "TARGET_ARM && (GET_CODE (operands[0]) == SYMBOL_REF || GET_CODE (operands[0]) == REG)"
  "*
  if (GET_CODE (operands[0]) == REG)
    return \"bx%?\\t%0\";
  else
    return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
  "
  [(set_attr "type" "call")]
)

(define_insn "*sibcall_value_insn"
 [(set (match_operand 0 "" "")
       (call (mem:SI (match_operand:SI 1 "arm_branch_target" "X"))
             (match_operand 2 "" "")))
  (return)
  (use (match_operand 3 "" ""))]
  "TARGET_ARM && (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == REG)"
  "*
  if (GET_CODE (operands[1]) == REG)
    return \"bx%?\\t%1\";
  else
    return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
  "
  [(set_attr "type" "call")]
)
;; APPLE LOCAL end ARM indirect sibcalls

;; Often the return insn will be the same as loading from memory, so set attr
(define_insn "return"
  [(return)]
  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
  "*
  {
    if (arm_ccfsm_state == 2)
      {
        arm_ccfsm_state += 2;
        return \"\";
      }
    return output_return_instruction (const_true_rtx, TRUE, FALSE);
  }"
  [(set_attr "type" "load1")
   (set_attr "length" "12")
   (set_attr "predicable" "yes")]
)

(define_insn "*cond_return"
  [(set (pc)
        (if_then_else (match_operator 0 "arm_comparison_operator"
		       [(match_operand 1 "cc_register" "") (const_int 0)])
                      (return)
                      (pc)))]
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
  "*
  {
    if (arm_ccfsm_state == 2)
      {
        arm_ccfsm_state += 2;
        return \"\";
      }
    return output_return_instruction (operands[0], TRUE, FALSE);
  }"
  [(set_attr "conds" "use")
   (set_attr "length" "12")
   (set_attr "type" "load1")]
)

(define_insn "*cond_return_inverted"
  [(set (pc)
        (if_then_else (match_operator 0 "arm_comparison_operator"
		       [(match_operand 1 "cc_register" "") (const_int 0)])
                      (pc)
		      (return)))]
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
  "*
  {
    if (arm_ccfsm_state == 2)
      {
        arm_ccfsm_state += 2;
        return \"\";
      }
    return output_return_instruction (operands[0], TRUE, TRUE);
  }"
  [(set_attr "conds" "use")
   (set_attr "length" "12")
   (set_attr "type" "load1")]
)

;; Generate a sequence of instructions to determine if the processor is
;; in 26-bit or 32-bit mode, and return the appropriate return address
;; mask.

(define_expand "return_addr_mask"
  [(set (match_dup 1)
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
		       (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "")
      (if_then_else:SI (eq (match_dup 1) (const_int 0))
		       (const_int -1)
		       (const_int 67108860)))] ; 0x03fffffc
  "TARGET_ARM"
  "
  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
  ")

(define_insn "*check_arch2"
  [(set (match_operand:CC_NOOV 0 "cc_register" "")
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
		       (const_int 0)))]
  "TARGET_ARM"
  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
  [(set_attr "length" "8")
   (set_attr "conds" "set")]
)

;; Call subroutine returning any type.

(define_expand "untyped_call"
  [(parallel [(call (match_operand 0 "" "")
		    (const_int 0))
	      (match_operand 1 "" "")
	      (match_operand 2 "" "")])]
  "TARGET_EITHER"
  "
  {
    int i;
    rtx par = gen_rtx_PARALLEL (VOIDmode,
				rtvec_alloc (XVECLEN (operands[2], 0)));
    rtx addr = gen_reg_rtx (Pmode);
    rtx mem;
    int size = 0;

    emit_move_insn (addr, XEXP (operands[1], 0));
    mem = change_address (operands[1], BLKmode, addr);

    for (i = 0; i < XVECLEN (operands[2], 0); i++)
      {
	rtx src = SET_SRC (XVECEXP (operands[2], 0, i));

	/* Default code only uses r0 as a return value, but we could
	   be using anything up to 4 registers.  */
	if (REGNO (src) == R0_REGNUM)
	  src = gen_rtx_REG (TImode, R0_REGNUM);

        XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
						 GEN_INT (size));
        size += GET_MODE_SIZE (GET_MODE (src));
      }

    emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
				    const0_rtx));

    size = 0;

    for (i = 0; i < XVECLEN (par, 0); i++)
      {
	HOST_WIDE_INT offset = 0;
	rtx reg = XEXP (XVECEXP (par, 0, i), 0);

	if (size != 0)
	  emit_move_insn (addr, plus_constant (addr, size));

	mem = change_address (mem, GET_MODE (reg), NULL);
	if (REGNO (reg) == R0_REGNUM)
	  {
	    /* On thumb we have to use a write-back instruction.  */
	    emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
			TARGET_THUMB ? TRUE : FALSE, mem, &offset));
	    size = TARGET_ARM ? 16 : 0;
	  }
	else
	  {
	    emit_move_insn (mem, reg);
	    size = GET_MODE_SIZE (GET_MODE (reg));
	  }
      }

    /* The optimizer does not know that the call sets the function value
       registers we stored in the result block.  We avoid problems by
       claiming that all hard registers are used and clobbered at this
       point.  */
    emit_insn (gen_blockage ());

    DONE;
  }"
)

(define_expand "untyped_return"
  [(match_operand:BLK 0 "memory_operand" "")
   (match_operand 1 "" "")]
  "TARGET_EITHER"
  "
  {
    int i;
    rtx addr = gen_reg_rtx (Pmode);
    rtx mem;
    int size = 0;

    emit_move_insn (addr, XEXP (operands[0], 0));
    mem = change_address (operands[0], BLKmode, addr);

    for (i = 0; i < XVECLEN (operands[1], 0); i++)
      {
	HOST_WIDE_INT offset = 0;
	rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));

	if (size != 0)
	  emit_move_insn (addr, plus_constant (addr, size));

	mem = change_address (mem, GET_MODE (reg), NULL);
	if (REGNO (reg) == R0_REGNUM)
	  {
	    /* On thumb we have to use a write-back instruction.  */
	    emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
			TARGET_THUMB ? TRUE : FALSE, mem, &offset));
	    size = TARGET_ARM ? 16 : 0;
	  }
	else
	  {
	    emit_move_insn (reg, mem);
	    size = GET_MODE_SIZE (GET_MODE (reg));
	  }
      }

    /* Emit USE insns before the return.  */
    for (i = 0; i < XVECLEN (operands[1], 0); i++)
      emit_insn (gen_rtx_USE (VOIDmode,
			      SET_DEST (XVECEXP (operands[1], 0, i))));

    /* Construct the return.  */
    expand_naked_return ();

    DONE;
  }"
)

;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory.  This blocks insns from being moved across this point.

(define_insn "blockage"
  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
  "TARGET_EITHER"
  ""
  [(set_attr "length" "0")
   (set_attr "type" "block")]
)

(define_expand "casesi"
  [(match_operand:SI 0 "s_register_operand" "")	; index to jump on
   (match_operand:SI 1 "const_int_operand" "")	; lower bound
   (match_operand:SI 2 "const_int_operand" "")	; total range
   (match_operand:SI 3 "" "")			; table label
   (match_operand:SI 4 "" "")]			; Out of range label
;; APPLE LOCAL compact switch tables
  "TARGET_32BIT || TARGET_COMPACT_SWITCH_TABLES"
  "
  {
    rtx reg;
    if (operands[1] != const0_rtx)
      {
	reg = gen_reg_rtx (SImode);

	emit_insn (gen_addsi3 (reg, operands[0],
			       GEN_INT (-INTVAL (operands[1]))));
	operands[0] = reg;
      }

    /* APPLE LOCAL begin v7 support. Merge from mainline */
    /* APPLE LOCAL begin compact switch tables */
    if (TARGET_32BIT)
      {
    /* APPLE LOCAL end compact switch tables */
        if (!const_ok_for_arm (INTVAL (operands[2])))
          operands[2] = force_reg (SImode, operands[2]);

        if (TARGET_ARM)
          {
	    emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2], 
                                                     operands[3], operands[4]));
          }
	/* APPLE LOCAL begin 6152801 SImode thumb2 switch table dispatch */
	/* Removed specialized PIC handling */
	/* APPLE LOCAL end 6152801 SImode thumb2 switch table dispatch */
        else
          {
            emit_jump_insn (gen_thumb2_casesi_internal (operands[0], 
                operands[2], operands[3], operands[4]));
          }
	DONE;
    /* APPLE LOCAL end v7 support. Merge from mainline */
    /* APPLE LOCAL begin compact switch tables */
      }
    else
      {
	/* Containing function must be 4-byte aligned, else we won't know what the
	   various .align directives do, e.g. around constant tables. */
	cfun->needs_4byte_alignment = 1;
	/* This is a function call, but the semantics are not the same as a normal
	   function call, so we put the parameter in R0 explicitly and hide the
	   call as a casesi node.  The USE of R0 in the casesi_internal pattern
	   causes the value to be retained. */
	emit_move_insn (gen_rtx_REG (Pmode, 0), operands[0]);
	emit_jump_insn (gen_thumb_casesi_internal (operands[0], operands[2], operands[3],
						   operands[4]));
	DONE;
      }
    /* APPLE LOCAL end compact switch tables */
  }"
)

;; The USE in this pattern is needed to tell flow analysis that this is
;; a CASESI insn.  It has no other purpose.
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "arm_casesi_internal"
  [(parallel [(set (pc)
	       (if_then_else
		(leu (match_operand:SI 0 "s_register_operand" "r")
		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
				 (label_ref (match_operand 2 "" ""))))
		(label_ref (match_operand 3 "" ""))))
	      (clobber (reg:CC CC_REGNUM))
	      (use (label_ref (match_dup 2)))])]
  "TARGET_ARM"
  "*
    if (flag_pic)
      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

;; APPLE LOCAL begin compact switch tables
;; This pattern represents the library call for Thumb switch tables.
;; The functions' (sparse) register usage is recorded as clobbers.

(define_insn "thumb_casesi_internal"
  [(parallel [(set (pc)
	       (if_then_else
		(leu (match_operand:SI 0 "s_register_operand" "l")
		     (match_operand:SI 1 "const_int_operand" "i"))
		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 2))
				 (label_ref (match_operand 2 "" ""))))
		(label_ref (match_operand 3 "" ""))))
	      (clobber (reg:CC CC_REGNUM))
	      (clobber (reg:SI LR_REGNUM))
	      (clobber (reg:SI IP_REGNUM))
	      (use (reg:SI 0))
	      (use (label_ref (match_dup 2)))])]
  "TARGET_COMPACT_SWITCH_TABLES"
  "*
    {
      rtx body = PATTERN (next_real_insn (insn));
      static char buf[255];
      gcc_assert (GET_CODE (body) == ADDR_DIFF_VEC);
      strcpy(buf, \"bl\\t\");
      if (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
	  strcat(buf, \"L\");
      if (GET_MODE (body) == QImode
	  && ADDR_DIFF_VEC_FLAGS (body).offset_unsigned)
	{
	  register_switchu8_libfunc ();
	  strcat(buf, \"___switchu8\");
	}
      else if (GET_MODE (body) == QImode)
	{
	  register_switch8_libfunc ();
	  strcat(buf, \"___switch8\");
	}
      else if (GET_MODE (body) == HImode)
	{
	  register_switch16_libfunc ();
	  strcat(buf, \"___switch16\");
	}
      else
	{
	  register_switch32_libfunc ();
	  /* The table is 4-byte aligned, and the call should
	     immediately precede the table.  To do this, align
	     here; as it happens, 0x0000 is a NOP insn.  The
	     insn_length is still 4 even if a NOP is inserted;
	     however, the computation in shorten_branches
	     comes out right because that 4 is counted against
	     the following label, which is marked as 4-byte
	     aligned.  I.e. the shorten_branch code thinks it's
	     going to looks like
		      call
		      .align 2
		      zero padding
		   label:
	     when in fact it is
		      .align 2
		      NOP
		      call
		      .align 2
		      never any padding here
		    label:
	     and it gets the right address for the label.
	     Yes, this is overly tricky. */
	  assemble_align (32);
	  strcat(buf, \"___switch32\");
	}
      if (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
	  strcat(buf, \"$stub\");
      return buf;
    }
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "4")]
)
;; APPLE LOCAL end compact switch tables

;; APPLE LOCAL begin ARM setjmp/longjmp interworking
;; Indirect jump with possible change between ARM/Thumb state
(define_expand "indirect_jump_exchange"
  [(unspec:SI [(match_operand:SI 0 "s_register_operand" "")]
	      UNSPEC_JMP_XCHG)]
  "TARGET_EITHER"
  ""
)

(define_insn "*arm_indirect_jump_exchange"
  [(unspec:SI [(match_operand:SI 0 "s_register_operand" "r")]
	      UNSPEC_JMP_XCHG)]
  "TARGET_ARM && (arm_arch4t)"
  "bx\\t%0"
  [(set_attr "predicable" "yes")]
)

(define_insn "*thumb_indirect_jump_exchange"
  [(unspec:SI [(match_operand:SI 0 "s_register_operand" "l*r")]
	      UNSPEC_JMP_XCHG)]
  "TARGET_THUMB"
  "bx\\t%0"
  [(set_attr "conds" "clob")
   (set_attr "length" "2")]
)
;; APPLE LOCAL end ARM setjmp/longjmp interworking

(define_expand "indirect_jump"
  [(set (pc)
	(match_operand:SI 0 "s_register_operand" ""))]
  "TARGET_EITHER"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "
  /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
     address and use bx.  */
  if (TARGET_THUMB2)
    {
      rtx tmp;
      tmp = gen_reg_rtx (SImode);
      emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
      operands[0] = tmp;
    }
  "
;; APPLE LOCAL end v7 support. Merge from mainline
)

;; NB Never uses BX.
(define_insn "*arm_indirect_jump"
  [(set (pc)
	(match_operand:SI 0 "s_register_operand" "r"))]
  "TARGET_ARM"
  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
  [(set_attr "predicable" "yes")]
)

(define_insn "*load_indirect_jump"
  [(set (pc)
	(match_operand:SI 0 "memory_operand" "m"))]
  "TARGET_ARM"
  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
  [(set_attr "type" "load1")
   (set_attr "pool_range" "4096")
   (set_attr "neg_pool_range" "4084")
   (set_attr "predicable" "yes")]
)

;; NB Never uses BX.
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_indirect_jump"
  [(set (pc)
	(match_operand:SI 0 "register_operand" "l*r"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "mov\\tpc, %0"
  [(set_attr "conds" "clob")
   (set_attr "length" "2")]
)


;; Misc insns

(define_insn "nop"
  [(const_int 0)]
  "TARGET_EITHER"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "*
  if (TARGET_UNIFIED_ASM)
    return \"nop\";
  if (TARGET_ARM)
    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
  return  \"mov\\tr8, r8\";
  "
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set (attr "length")
	(if_then_else (eq_attr "is_thumb" "yes")
		      (const_int 2)
		      (const_int 4)))]
)


;; Patterns to allow combination of arithmetic, cond code and shifts

(define_insn "*arith_shiftsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (match_operator:SI 1 "shiftable_operator"
          [(match_operator:SI 3 "shift_operator"
             [(match_operand:SI 4 "s_register_operand" "r")
              (match_operand:SI 5 "reg_or_int_operand" "rI")])
           (match_operand:SI 2 "s_register_operand" "r")]))]
  "TARGET_ARM"
  "%i1%?\\t%0, %2, %4%S3"
  [(set_attr "predicable" "yes")
   (set_attr "shift" "4")
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(match_operator:SI 1 "shiftable_operator"
	 [(match_operator:SI 2 "shiftable_operator"
	   [(match_operator:SI 3 "shift_operator"
	     [(match_operand:SI 4 "s_register_operand" "")
	      (match_operand:SI 5 "reg_or_int_operand" "")])
	    (match_operand:SI 6 "s_register_operand" "")])
	  (match_operand:SI 7 "arm_rhs_operand" "")]))
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 8)
	(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
			 (match_dup 6)]))
   (set (match_dup 0)
	(match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
  "")

(define_insn "*arith_shiftsi_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
		          [(match_operator:SI 3 "shift_operator"
		            [(match_operand:SI 4 "s_register_operand" "r")
		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
		           (match_operand:SI 2 "s_register_operand" "r")])
			 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
			 (match_dup 2)]))]
  "TARGET_ARM"
;; APPLE LOCAL v7 support. Merge from mainline
  "%i1%.\\t%0, %2, %4%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "4")
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*arith_shiftsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
		          [(match_operator:SI 3 "shift_operator"
		            [(match_operand:SI 4 "s_register_operand" "r")
		             (match_operand:SI 5 "reg_or_int_operand" "rI")])
		           (match_operand:SI 2 "s_register_operand" "r")])
			 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
  "TARGET_ARM"
;; APPLE LOCAL v7 support. Merge from mainline
  "%i1%.\\t%0, %2, %4%S3"
  [(set_attr "conds" "set")
   (set_attr "shift" "4")
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*sub_shiftsi"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
		  (match_operator:SI 2 "shift_operator"
		   [(match_operand:SI 3 "s_register_operand" "r")
		    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
  "TARGET_ARM"
  "sub%?\\t%0, %1, %3%S2"
  [(set_attr "predicable" "yes")
   (set_attr "shift" "3")
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*sub_shiftsi_compare0"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
		   (match_operator:SI 2 "shift_operator"
		    [(match_operand:SI 3 "s_register_operand" "r")
		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
	 (const_int 0)))
   (set (match_operand:SI 0 "s_register_operand" "=r")
	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
						 (match_dup 4)])))]
  "TARGET_ARM"
;; APPLE LOCAL v7 support. Merge from mainline
  "sub%.\\t%0, %1, %3%S2"
  [(set_attr "conds" "set")
   (set_attr "shift" "3")
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*sub_shiftsi_compare0_scratch"
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV
	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
		   (match_operator:SI 2 "shift_operator"
		    [(match_operand:SI 3 "s_register_operand" "r")
		     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
	 (const_int 0)))
   (clobber (match_scratch:SI 0 "=r"))]
  "TARGET_ARM"
;; APPLE LOCAL v7 support. Merge from mainline
  "sub%.\\t%0, %1, %3%S2"
  [(set_attr "conds" "set")
   (set_attr "shift" "3")
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)



(define_insn "*and_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(and:SI (match_operator:SI 1 "arm_comparison_operator"
		 [(match_operand 3 "cc_register" "") (const_int 0)])
		(match_operand:SI 2 "s_register_operand" "r")))]
  "TARGET_ARM"
  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "8")]
)

(define_insn "*ior_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
		 [(match_operand 3 "cc_register" "") (const_int 0)])
		(match_operand:SI 1 "s_register_operand" "0,?r")))]
  "TARGET_ARM"
  "@
   orr%d2\\t%0, %1, #1
   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8")]
)

(define_insn "*compare_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(match_operator:SI 1 "arm_comparison_operator"
	 [(match_operand:SI 2 "s_register_operand" "r,r")
	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
    if (operands[3] == const0_rtx)
      {
	if (GET_CODE (operands[1]) == LT)
	  return \"mov\\t%0, %2, lsr #31\";

	if (GET_CODE (operands[1]) == GE)
	  return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";

	if (GET_CODE (operands[1]) == EQ)
	  return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
      }

    if (GET_CODE (operands[1]) == NE)
      {
        if (which_alternative == 1)
	  return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
      }
    if (which_alternative == 1)
      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
    else
      output_asm_insn (\"cmp\\t%2, %3\", operands);
    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*cond_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI (match_operator 3 "equality_operator"
			  [(match_operator 4 "arm_comparison_operator"
			    [(match_operand 5 "cc_register" "") (const_int 0)])
			   (const_int 0)])
			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
  "TARGET_ARM"
  "*
    if (GET_CODE (operands[3]) == NE)
      {
        if (which_alternative != 1)
	  output_asm_insn (\"mov%D4\\t%0, %2\", operands);
        if (which_alternative != 0)
	  output_asm_insn (\"mov%d4\\t%0, %1\", operands);
        return \"\";
      }
    if (which_alternative != 0)
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
    if (which_alternative != 1)
      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
    return \"\";
  "
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set_attr "length" "4,4,8")]
)

(define_insn "*cond_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
        (match_operator:SI 5 "shiftable_operator" 
	 [(match_operator:SI 4 "arm_comparison_operator"
           [(match_operand:SI 2 "s_register_operand" "r,r")
	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
          (match_operand:SI 1 "s_register_operand" "0,?r")]))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
      return \"%i5\\t%0, %1, %2, lsr #31\";

    output_asm_insn (\"cmp\\t%2, %3\", operands);
    if (GET_CODE (operands[5]) == AND)
      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
    else if (GET_CODE (operands[5]) == MINUS)
      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
    else if (which_alternative != 0)
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
    return \"%i5%d4\\t%0, %1, #1\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*cond_sub"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
		  (match_operator:SI 4 "arm_comparison_operator"
                   [(match_operand:SI 2 "s_register_operand" "r,r")
		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
    output_asm_insn (\"cmp\\t%2, %3\", operands);
    if (which_alternative != 0)
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
    return \"sub%d4\\t%0, %1, #1\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

;; APPLE LOCAL v7 support. Merge from mainline
;; ??? Is it worth using these conditional patterns in Thumb-2 mode?
(define_insn "*cmp_ite0"
  [(set (match_operand 6 "dominant_cc_register" "")
	(compare
	 (if_then_else:SI
	  (match_operator 4 "arm_comparison_operator"
	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
	  (match_operator:SI 5 "arm_comparison_operator"
	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
	  (const_int 0))
	 (const_int 0)))]
  "TARGET_ARM"
  "*
  {
    static const char * const opcodes[4][2] =
    {
      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
    };
    int swap =
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));

    return opcodes[which_alternative][swap];
  }"
  [(set_attr "conds" "set")
   (set_attr "length" "8")]
)

(define_insn "*cmp_ite1"
  [(set (match_operand 6 "dominant_cc_register" "")
	(compare
	 (if_then_else:SI
	  (match_operator 4 "arm_comparison_operator"
	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
	  (match_operator:SI 5 "arm_comparison_operator"
	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
	  (const_int 1))
	 (const_int 0)))]
  "TARGET_ARM"
  "*
  {
    static const char * const opcodes[4][2] =
    {
      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
    };
    int swap =
      comparison_dominates_p (GET_CODE (operands[5]),
			      reverse_condition (GET_CODE (operands[4])));

    return opcodes[which_alternative][swap];
  }"
  [(set_attr "conds" "set")
   (set_attr "length" "8")]
)

(define_insn "*cmp_and"
  [(set (match_operand 6 "dominant_cc_register" "")
	(compare
	 (and:SI
	  (match_operator 4 "arm_comparison_operator"
	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
	  (match_operator:SI 5 "arm_comparison_operator"
	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
	 (const_int 0)))]
  "TARGET_ARM"
  "*
  {
    static const char *const opcodes[4][2] =
    {
      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
    };
    int swap =
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));

    return opcodes[which_alternative][swap];
  }"
  [(set_attr "conds" "set")
   (set_attr "predicable" "no")
   (set_attr "length" "8")]
)

(define_insn "*cmp_ior"
  [(set (match_operand 6 "dominant_cc_register" "")
	(compare
	 (ior:SI
	  (match_operator 4 "arm_comparison_operator"
	   [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
	  (match_operator:SI 5 "arm_comparison_operator"
	   [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
	    (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
	 (const_int 0)))]
  "TARGET_ARM"
  "*
{
  static const char *const opcodes[4][2] =
  {
    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
  };
  int swap =
    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));

  return opcodes[which_alternative][swap];
}
"
  [(set_attr "conds" "set")
   (set_attr "length" "8")]
)

(define_insn_and_split "*ior_scc_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(ior:SI (match_operator:SI 3 "arm_comparison_operator"
		 [(match_operand:SI 1 "s_register_operand" "r")
		  (match_operand:SI 2 "arm_add_operand" "rIL")])
		(match_operator:SI 6 "arm_comparison_operator"
		 [(match_operand:SI 4 "s_register_operand" "r")
		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
       != CCmode)"
  "#"
  "TARGET_ARM && reload_completed"
  [(set (match_dup 7)
	(compare
	 (ior:SI
	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
	 (const_int 0)))
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
  "operands[7]
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
						  DOM_CC_X_OR_Y),
		    CC_REGNUM);"
  [(set_attr "conds" "clob")
   (set_attr "length" "16")])

; If the above pattern is followed by a CMP insn, then the compare is 
; redundant, since we can rework the conditional instruction that follows.
(define_insn_and_split "*ior_scc_scc_cmp"
  [(set (match_operand 0 "dominant_cc_register" "")
	(compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_add_operand" "rIL")])
			 (match_operator:SI 6 "arm_comparison_operator"
			  [(match_operand:SI 4 "s_register_operand" "r")
			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
		 (const_int 0)))
   (set (match_operand:SI 7 "s_register_operand" "=r")
	(ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM && reload_completed"
  [(set (match_dup 0)
	(compare
	 (ior:SI
	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
	 (const_int 0)))
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
  ""
  [(set_attr "conds" "set")
   (set_attr "length" "16")])

(define_insn_and_split "*and_scc_scc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(and:SI (match_operator:SI 3 "arm_comparison_operator"
		 [(match_operand:SI 1 "s_register_operand" "r")
		  (match_operand:SI 2 "arm_add_operand" "rIL")])
		(match_operator:SI 6 "arm_comparison_operator"
		 [(match_operand:SI 4 "s_register_operand" "r")
		  (match_operand:SI 5 "arm_add_operand" "rIL")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
       != CCmode)"
  "#"
  "TARGET_ARM && reload_completed
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
       != CCmode)"
  [(set (match_dup 7)
	(compare
	 (and:SI
	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
	 (const_int 0)))
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
  "operands[7]
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
						  DOM_CC_X_AND_Y),
		    CC_REGNUM);"
  [(set_attr "conds" "clob")
   (set_attr "length" "16")])

; If the above pattern is followed by a CMP insn, then the compare is 
; redundant, since we can rework the conditional instruction that follows.
(define_insn_and_split "*and_scc_scc_cmp"
  [(set (match_operand 0 "dominant_cc_register" "")
	(compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_add_operand" "rIL")])
			 (match_operator:SI 6 "arm_comparison_operator"
			  [(match_operand:SI 4 "s_register_operand" "r")
			   (match_operand:SI 5 "arm_add_operand" "rIL")]))
		 (const_int 0)))
   (set (match_operand:SI 7 "s_register_operand" "=r")
	(and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
		(match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM && reload_completed"
  [(set (match_dup 0)
	(compare
	 (and:SI
	  (match_op_dup 3 [(match_dup 1) (match_dup 2)])
	  (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
	 (const_int 0)))
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
  ""
  [(set_attr "conds" "set")
   (set_attr "length" "16")])

;; If there is no dominance in the comparison, then we can still save an
;; instruction in the AND case, since we can know that the second compare
;; need only zero the value if false (if true, then the value is already
;; correct).
(define_insn_and_split "*and_scc_scc_nodom"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
	(and:SI (match_operator:SI 3 "arm_comparison_operator"
		 [(match_operand:SI 1 "s_register_operand" "r,r,0")
		  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
		(match_operator:SI 6 "arm_comparison_operator"
		 [(match_operand:SI 4 "s_register_operand" "r,r,r")
		  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
       == CCmode)"
  "#"
  "TARGET_ARM && reload_completed"
  [(parallel [(set (match_dup 0)
		   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
	      (clobber (reg:CC CC_REGNUM))])
   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
   (set (match_dup 0)
	(if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
			 (match_dup 0)
			 (const_int 0)))]
  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
					      operands[4], operands[5]),
			      CC_REGNUM);
   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
				  operands[5]);"
  [(set_attr "conds" "clob")
   (set_attr "length" "20")])

(define_split
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (ior:SI
			  (and:SI (match_operand:SI 0 "s_register_operand" "")
				  (const_int 1))
			  (match_operator:SI 1 "comparison_operator"
			   [(match_operand:SI 2 "s_register_operand" "")
			    (match_operand:SI 3 "arm_add_operand" "")]))
			 (const_int 0)))
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 4)
	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
		(match_dup 0)))
   (set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
			 (const_int 0)))]
  "")

(define_split
  [(set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (ior:SI
			  (match_operator:SI 1 "comparison_operator"
			   [(match_operand:SI 2 "s_register_operand" "")
			    (match_operand:SI 3 "arm_add_operand" "")])
			  (and:SI (match_operand:SI 0 "s_register_operand" "")
				  (const_int 1)))
			 (const_int 0)))
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 4)
	(ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
		(match_dup 0)))
   (set (reg:CC_NOOV CC_REGNUM)
	(compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
			 (const_int 0)))]
  "")
;; APPLE LOCAL v7 support. Merge from mainline
;; ??? The conditional patterns above need checking for Thumb-2 usefulness

(define_insn "*negscc"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(neg:SI (match_operator 3 "arm_comparison_operator"
		 [(match_operand:SI 1 "s_register_operand" "r")
		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
    return \"mov\\t%0, %1, asr #31\";

  if (GET_CODE (operands[3]) == NE)
    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";

  if (GET_CODE (operands[3]) == GT)
    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";

  output_asm_insn (\"cmp\\t%1, %2\", operands);
  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
  return \"mvn%d3\\t%0, #0\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "movcond"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
  if (GET_CODE (operands[5]) == LT
      && (operands[4] == const0_rtx))
    {
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
	{
	  if (operands[2] == const0_rtx)
	    return \"and\\t%0, %1, %3, asr #31\";
	  return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
	}
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
	{
	  if (operands[1] == const0_rtx)
	    return \"bic\\t%0, %2, %3, asr #31\";
	  return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
	}
      /* The only case that falls through to here is when both ops 1 & 2
	 are constants.  */
    }

  if (GET_CODE (operands[5]) == GE
      && (operands[4] == const0_rtx))
    {
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
	{
	  if (operands[2] == const0_rtx)
	    return \"bic\\t%0, %1, %3, asr #31\";
	  return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
	}
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
	{
	  if (operands[1] == const0_rtx)
	    return \"and\\t%0, %2, %3, asr #31\";
	  return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
	}
      /* The only case that falls through to here is when both ops 1 & 2
	 are constants.  */
    }
  if (GET_CODE (operands[4]) == CONST_INT
      && !const_ok_for_arm (INTVAL (operands[4])))
    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
  else
    output_asm_insn (\"cmp\\t%3, %4\", operands);
  if (which_alternative != 0)
    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
  if (which_alternative != 1)
    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
  return \"\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8,8,12")]
)

;; APPLE LOCAL v7 support. Merge from mainline
;; ??? The patterns below need checking for Thumb-2 usefulness.
(define_insn "*ifcompare_plus_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
			  [(match_operand:SI 4 "s_register_operand" "r,r")
			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
			 (plus:SI
			  (match_operand:SI 2 "s_register_operand" "r,r")
			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_plus_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 5 "cc_register" "") (const_int 0)])
	 (plus:SI
	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
  "TARGET_ARM"
  "@
   add%d4\\t%0, %2, %3
   sub%d4\\t%0, %2, #%n3
   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,4,8,8")
   (set_attr "type" "*,*,*,*")]
)

(define_insn "*ifcompare_move_plus"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
			  [(match_operand:SI 4 "s_register_operand" "r,r")
			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
			 (plus:SI
			  (match_operand:SI 2 "s_register_operand" "r,r")
			  (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_move_plus"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 5 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
	 (plus:SI
	  (match_operand:SI 2 "s_register_operand" "r,r,r,r")
	  (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
  "TARGET_ARM"
  "@
   add%D4\\t%0, %2, %3
   sub%D4\\t%0, %2, #%n3
   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,4,8,8")
   (set_attr "type" "*,*,*,*")]
)

(define_insn "*ifcompare_arith_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI (match_operator 9 "arm_comparison_operator"
			  [(match_operand:SI 5 "s_register_operand" "r")
			   (match_operand:SI 6 "arm_add_operand" "rIL")])
			 (match_operator:SI 8 "shiftable_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
			 (match_operator:SI 7 "shiftable_operator"
			  [(match_operand:SI 3 "s_register_operand" "r")
			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*if_arith_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI (match_operator 5 "arm_comparison_operator"
			  [(match_operand 8 "cc_register" "") (const_int 0)])
			 (match_operator:SI 6 "shiftable_operator"
			  [(match_operand:SI 1 "s_register_operand" "r")
			   (match_operand:SI 2 "arm_rhs_operand" "rI")])
			 (match_operator:SI 7 "shiftable_operator"
			  [(match_operand:SI 3 "s_register_operand" "r")
			   (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
  "TARGET_ARM"
  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
  [(set_attr "conds" "use")
   (set_attr "length" "8")]
)

(define_insn "*ifcompare_arith_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
			  [(match_operand:SI 2 "s_register_operand" "r,r")
			   (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
			 (match_operator:SI 7 "shiftable_operator"
			  [(match_operand:SI 4 "s_register_operand" "r,r")
			   (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
  /* If we have an operation where (op x 0) is the identity operation and
     the conditional operator is LT or GE and we are comparing against zero and
     everything is in registers then we can do this in two instructions.  */
  if (operands[3] == const0_rtx
      && GET_CODE (operands[7]) != AND
      && GET_CODE (operands[5]) == REG
      && GET_CODE (operands[1]) == REG 
      && REGNO (operands[1]) == REGNO (operands[4])
      && REGNO (operands[4]) != REGNO (operands[0]))
    {
      if (GET_CODE (operands[6]) == LT)
	return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
      else if (GET_CODE (operands[6]) == GE)
	return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
    }
  if (GET_CODE (operands[3]) == CONST_INT
      && !const_ok_for_arm (INTVAL (operands[3])))
    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
  else
    output_asm_insn (\"cmp\\t%2, %3\", operands);
  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
  if (which_alternative != 0)
    return \"mov%D6\\t%0, %1\";
  return \"\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_arith_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
			  [(match_operand 6 "cc_register" "") (const_int 0)])
			 (match_operator:SI 5 "shiftable_operator"
			  [(match_operand:SI 2 "s_register_operand" "r,r")
			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
  "TARGET_ARM"
  "@
   %I5%d4\\t%0, %2, %3
   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8")
   (set_attr "type" "*,*")]
)

(define_insn "*ifcompare_move_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 6 "arm_comparison_operator"
			  [(match_operand:SI 4 "s_register_operand" "r,r")
			   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
			 (match_operator:SI 7 "shiftable_operator"
			  [(match_operand:SI 2 "s_register_operand" "r,r")
			   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
  /* If we have an operation where (op x 0) is the identity operation and
     the conditional operator is LT or GE and we are comparing against zero and
     everything is in registers then we can do this in two instructions */
  if (operands[5] == const0_rtx
      && GET_CODE (operands[7]) != AND
      && GET_CODE (operands[3]) == REG
      && GET_CODE (operands[1]) == REG 
      && REGNO (operands[1]) == REGNO (operands[2])
      && REGNO (operands[2]) != REGNO (operands[0]))
    {
      if (GET_CODE (operands[6]) == GE)
	return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
      else if (GET_CODE (operands[6]) == LT)
	return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
    }

  if (GET_CODE (operands[5]) == CONST_INT
      && !const_ok_for_arm (INTVAL (operands[5])))
    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
  else
    output_asm_insn (\"cmp\\t%4, %5\", operands);

  if (which_alternative != 0)
    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
  return \"%I7%D6\\t%0, %2, %3\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_move_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 6 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
	 (match_operator:SI 5 "shiftable_operator"
	  [(match_operand:SI 2 "s_register_operand" "r,r")
	   (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
  "TARGET_ARM"
  "@
   %I5%D4\\t%0, %2, %3
   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8")
   (set_attr "type" "*,*")]
)

(define_insn "*ifcompare_move_not"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand:SI 3 "s_register_operand" "r,r")
	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
	 (not:SI
	  (match_operand:SI 2 "s_register_operand" "r,r"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_move_not"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 3 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
  "TARGET_ARM"
  "@
   mvn%D4\\t%0, %2
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set_attr "length" "4,8,8")]
)

(define_insn "*ifcompare_not_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI 
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand:SI 3 "s_register_operand" "r,r")
	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
	 (not:SI
	  (match_operand:SI 2 "s_register_operand" "r,r"))
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_not_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 3 "cc_register" "") (const_int 0)])
	 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
  "TARGET_ARM"
  "@
   mvn%d4\\t%0, %2
   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set_attr "length" "4,8,8")]
)

(define_insn "*ifcompare_shift_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 6 "arm_comparison_operator"
	  [(match_operand:SI 4 "s_register_operand" "r,r")
	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
	 (match_operator:SI 7 "shift_operator"
	  [(match_operand:SI 2 "s_register_operand" "r,r")
	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_shift_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand 6 "cc_register" "") (const_int 0)])
	 (match_operator:SI 4 "shift_operator"
	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
  "TARGET_ARM"
  "@
   mov%d5\\t%0, %2%S4
   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
  [(set_attr "conds" "use")
   (set_attr "shift" "2")
   (set_attr "length" "4,8,8")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*ifcompare_move_shift"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 6 "arm_comparison_operator"
	  [(match_operand:SI 4 "s_register_operand" "r,r")
	   (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
	 (match_operator:SI 7 "shift_operator"
	  [(match_operand:SI 2 "s_register_operand" "r,r")
	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_move_shift"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand 6 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
	 (match_operator:SI 4 "shift_operator"
	  [(match_operand:SI 2 "s_register_operand" "r,r,r")
	   (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
  "TARGET_ARM"
  "@
   mov%D5\\t%0, %2%S4
   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
  [(set_attr "conds" "use")
   (set_attr "shift" "2")
   (set_attr "length" "4,8,8")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*ifcompare_shift_shift"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 7 "arm_comparison_operator"
	  [(match_operand:SI 5 "s_register_operand" "r")
	   (match_operand:SI 6 "arm_add_operand" "rIL")])
	 (match_operator:SI 8 "shift_operator"
	  [(match_operand:SI 1 "s_register_operand" "r")
	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
	 (match_operator:SI 9 "shift_operator"
	  [(match_operand:SI 3 "s_register_operand" "r")
	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*if_shift_shift"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand 8 "cc_register" "") (const_int 0)])
	 (match_operator:SI 6 "shift_operator"
	  [(match_operand:SI 1 "s_register_operand" "r")
	   (match_operand:SI 2 "arm_rhs_operand" "rM")])
	 (match_operator:SI 7 "shift_operator"
	  [(match_operand:SI 3 "s_register_operand" "r")
	   (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
  "TARGET_ARM"
  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
  [(set_attr "conds" "use")
   (set_attr "shift" "1")
   (set_attr "length" "8")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mov")
   (set (attr "type") (if_then_else
		        (and (match_operand 2 "const_int_operand" "")
                             (match_operand 4 "const_int_operand" ""))
		      (const_string "alu_shift")
		      (const_string "alu_shift_reg")))]
)

(define_insn "*ifcompare_not_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 6 "arm_comparison_operator"
	  [(match_operand:SI 4 "s_register_operand" "r")
	   (match_operand:SI 5 "arm_add_operand" "rIL")])
	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
	 (match_operator:SI 7 "shiftable_operator"
	  [(match_operand:SI 2 "s_register_operand" "r")
	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*if_not_arith"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand 4 "cc_register" "") (const_int 0)])
	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
	 (match_operator:SI 6 "shiftable_operator"
	  [(match_operand:SI 2 "s_register_operand" "r")
	   (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
  "TARGET_ARM"
  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set_attr "length" "8")]
)

(define_insn "*ifcompare_arith_not"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 6 "arm_comparison_operator"
	  [(match_operand:SI 4 "s_register_operand" "r")
	   (match_operand:SI 5 "arm_add_operand" "rIL")])
	 (match_operator:SI 7 "shiftable_operator"
	  [(match_operand:SI 2 "s_register_operand" "r")
	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)

(define_insn "*if_arith_not"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand 4 "cc_register" "") (const_int 0)])
	 (match_operator:SI 6 "shiftable_operator"
	  [(match_operand:SI 2 "s_register_operand" "r")
	   (match_operand:SI 3 "arm_rhs_operand" "rI")])
	 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
  "TARGET_ARM"
  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set_attr "length" "8")]
)

(define_insn "*ifcompare_neg_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand:SI 3 "s_register_operand" "r,r")
	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_neg_move"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 3 "cc_register" "") (const_int 0)])
	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
  "TARGET_ARM"
  "@
   rsb%d4\\t%0, %2, #0
   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8,8")]
)

(define_insn "*ifcompare_move_neg"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI
	 (match_operator 5 "arm_comparison_operator"
	  [(match_operand:SI 3 "s_register_operand" "r,r")
	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
	 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "#"
  [(set_attr "conds" "clob")
   (set_attr "length" "8,12")]
)

(define_insn "*if_move_neg"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
	(if_then_else:SI
	 (match_operator 4 "arm_comparison_operator"
	  [(match_operand 3 "cc_register" "") (const_int 0)])
	 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
	 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
  "TARGET_ARM"
  "@
   rsb%D4\\t%0, %2, #0
   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
  [(set_attr "conds" "use")
   (set_attr "length" "4,8,8")]
)

(define_insn "*arith_adjacentmem"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(match_operator:SI 1 "shiftable_operator"
	 [(match_operand:SI 2 "memory_operand" "m")
	  (match_operand:SI 3 "memory_operand" "m")]))
   (clobber (match_scratch:SI 4 "=r"))]
  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
  "*
  {
    rtx ldm[3];
    rtx arith[4];
    rtx base_reg;
    HOST_WIDE_INT val1 = 0, val2 = 0;

    if (REGNO (operands[0]) > REGNO (operands[4]))
      {
	ldm[1] = operands[4];
	ldm[2] = operands[0];
      }
    else
      {
	ldm[1] = operands[0];
	ldm[2] = operands[4];
      }

    base_reg = XEXP (operands[2], 0);

    if (!REG_P (base_reg))
      {
	val1 = INTVAL (XEXP (base_reg, 1));
	base_reg = XEXP (base_reg, 0);
      }

    if (!REG_P (XEXP (operands[3], 0)))
      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));

    arith[0] = operands[0];
    arith[3] = operands[1];

    if (val1 < val2)
      {
	arith[1] = ldm[1];
	arith[2] = ldm[2];
      }
    else
      {
	arith[1] = ldm[2];
	arith[2] = ldm[1];
      }

    ldm[0] = base_reg;
    if (val1 !=0 && val2 != 0)
      {
	rtx ops[3];

        /* APPLE LOCAL begin v7 support. Merge from mainline */
	if (val1 == 4 || val2 == 4)
	  /* Other val must be 8, since we know they are adjacent and neither
	     is zero.  */
	  output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
	else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
	  {
	    ldm[0] = ops[0] = operands[4];
	    ops[1] = base_reg;
	    ops[2] = GEN_INT (val1);
	    output_add_immediate (ops);
	    if (val1 < val2)
	      output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
	    else
	      output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
	  }
        /* APPLE LOCAL end v7 support. Merge from mainline */
	else
	  {
	    /* Offset is out of range for a single add, so use two ldr.  */
	    ops[0] = ldm[1];
	    ops[1] = base_reg;
	    ops[2] = GEN_INT (val1);
	    output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
	    ops[0] = ldm[2];
	    ops[2] = GEN_INT (val2);
	    output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
	  }
      }
    /* APPLE LOCAL begin v7 support. Merge from mainline */
    else if (val1 != 0)
      {
	if (val1 < val2)
	  output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
	else
	  output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
      }
    else
      {
	if (val1 < val2)
	  output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
	else
	  output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
      }
    /* APPLE LOCAL end v7 support. Merge from mainline */
    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
    return \"\";
  }"
  [(set_attr "length" "12")
   (set_attr "predicable" "yes")
   (set_attr "type" "load1")]
)

; This pattern is never tried by combine, so do it as a peephole

(define_peephole2
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
	(match_operand:SI 1 "arm_general_register_operand" ""))
   (set (reg:CC CC_REGNUM)
	(compare:CC (match_dup 1) (const_int 0)))]
  "TARGET_ARM"
  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
	      (set (match_dup 0) (match_dup 1))])]
  ""
)

; Peepholes to spot possible load- and store-multiples, if the ordering is
; reversed, check that the memory references aren't volatile.

(define_peephole
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (match_operand:SI 4 "memory_operand" "m"))
   (set (match_operand:SI 1 "s_register_operand" "=r")
        (match_operand:SI 5 "memory_operand" "m"))
   (set (match_operand:SI 2 "s_register_operand" "=r")
        (match_operand:SI 6 "memory_operand" "m"))
   (set (match_operand:SI 3 "s_register_operand" "=r")
        (match_operand:SI 7 "memory_operand" "m"))]
  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
  "*
  return emit_ldm_seq (operands, 4);
  "
)

(define_peephole
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (match_operand:SI 3 "memory_operand" "m"))
   (set (match_operand:SI 1 "s_register_operand" "=r")
        (match_operand:SI 4 "memory_operand" "m"))
   (set (match_operand:SI 2 "s_register_operand" "=r")
        (match_operand:SI 5 "memory_operand" "m"))]
  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
  "*
  return emit_ldm_seq (operands, 3);
  "
)

(define_peephole
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (match_operand:SI 2 "memory_operand" "m"))
   (set (match_operand:SI 1 "s_register_operand" "=r")
        (match_operand:SI 3 "memory_operand" "m"))]
  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
  "*
  return emit_ldm_seq (operands, 2);
  "
)

(define_peephole
  [(set (match_operand:SI 4 "memory_operand" "=m")
        (match_operand:SI 0 "s_register_operand" "r"))
   (set (match_operand:SI 5 "memory_operand" "=m")
        (match_operand:SI 1 "s_register_operand" "r"))
   (set (match_operand:SI 6 "memory_operand" "=m")
        (match_operand:SI 2 "s_register_operand" "r"))
   (set (match_operand:SI 7 "memory_operand" "=m")
        (match_operand:SI 3 "s_register_operand" "r"))]
  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
  "*
  return emit_stm_seq (operands, 4);
  "
)

(define_peephole
  [(set (match_operand:SI 3 "memory_operand" "=m")
        (match_operand:SI 0 "s_register_operand" "r"))
   (set (match_operand:SI 4 "memory_operand" "=m")
        (match_operand:SI 1 "s_register_operand" "r"))
   (set (match_operand:SI 5 "memory_operand" "=m")
        (match_operand:SI 2 "s_register_operand" "r"))]
  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
  "*
  return emit_stm_seq (operands, 3);
  "
)

(define_peephole
  [(set (match_operand:SI 2 "memory_operand" "=m")
        (match_operand:SI 0 "s_register_operand" "r"))
   (set (match_operand:SI 3 "memory_operand" "=m")
        (match_operand:SI 1 "s_register_operand" "r"))]
  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
  "*
  return emit_stm_seq (operands, 2);
  "
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
		       (const_int 0))
		(neg:SI (match_operator:SI 2 "arm_comparison_operator"
			 [(match_operand:SI 3 "s_register_operand" "")
			  (match_operand:SI 4 "arm_rhs_operand" "")]))))
   (clobber (match_operand:SI 5 "s_register_operand" ""))]
  "TARGET_ARM"
  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
			      (match_dup 5)))]
  ""
)

;; This split can be used because CC_Z mode implies that the following
;; branch will be an equality, or an unsigned inequality, so the sign
;; extension is not needed.

(define_split
  [(set (reg:CC_Z CC_REGNUM)
	(compare:CC_Z
	 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
		    (const_int 24))
	 (match_operand 1 "const_int_operand" "")))
   (clobber (match_scratch:SI 2 ""))]
  "TARGET_ARM
   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
  "
  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
  "
)
;; APPLE LOCAL v7 support. Merge from mainline
;; ??? Check the patterns above for Thumb-2 usefulness

(define_expand "prologue"
  [(clobber (const_int 0))]
  "TARGET_EITHER"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "if (TARGET_32BIT)
     arm_expand_prologue ();
   else
     thumb1_expand_prologue ();
  DONE;
  "
;; APPLE LOCAL end v7 support. Merge from mainline
)

(define_expand "epilogue"
  [(clobber (const_int 0))]
  "TARGET_EITHER"
  "
  if (current_function_calls_eh_return)
    emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
  /* APPLE LOCAL begin v7 support. Merge from mainline */
  if (TARGET_THUMB1)
    thumb1_expand_epilogue ();
  /* APPLE LOCAL end v7 support. Merge from mainline */
  else if (USE_RETURN_INSN (FALSE))
    {
      emit_jump_insn (gen_return ());
      DONE;
    }
  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
	gen_rtvec (1,
		gen_rtx_RETURN (VOIDmode)),
	VUNSPEC_EPILOGUE));
  DONE;
  "
)

;; Note - although unspec_volatile's USE all hard registers,
;; USEs are ignored after relaod has completed.  Thus we need
;; to add an unspec of the link register to ensure that flow
;; does not think that it is unused by the sibcall branch that
;; will replace the standard function epilogue.
(define_insn "sibcall_epilogue"
  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
    return output_return_instruction (const_true_rtx, FALSE, FALSE);
  return arm_output_epilogue (next_nonnote_insn (insn));
  "
;; Length is absolute worst case
  [(set_attr "length" "44")
   (set_attr "type" "block")
   ;; We don't clobber the conditions, but the potential length of this
   ;; operation is sufficient to make conditionalizing the sequence 
   ;; unlikely to be profitable.
   (set_attr "conds" "clob")]
)

(define_insn "*epilogue_insns"
  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
  "TARGET_EITHER"
;; APPLE LOCAL begin v7 support. Merge from mainline
  "*
  if (TARGET_32BIT)
    return arm_output_epilogue (NULL);
  else /* TARGET_THUMB1 */
    return thumb_unexpanded_epilogue ();
  "
;; APPLE LOCAL end v7 support. Merge from mainline
  ; Length is absolute worst case
  [(set_attr "length" "44")
   (set_attr "type" "block")
   ;; We don't clobber the conditions, but the potential length of this
   ;; operation is sufficient to make conditionalizing the sequence 
   ;; unlikely to be profitable.
   (set_attr "conds" "clob")]
)

(define_expand "eh_epilogue"
  [(use (match_operand:SI 0 "register_operand" ""))
   (use (match_operand:SI 1 "register_operand" ""))
   (use (match_operand:SI 2 "register_operand" ""))]
  "TARGET_EITHER"
  "
  {
    cfun->machine->eh_epilogue_sp_ofs = operands[1];
    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
      {
	rtx ra = gen_rtx_REG (Pmode, 2);

	emit_move_insn (ra, operands[2]);
	operands[2] = ra;
      }
    /* This is a hack -- we may have crystalized the function type too
       early.  */
    cfun->machine->func_type = 0;
  }"
)

;; This split is only used during output to reduce the number of patterns
;; that need assembler instructions adding to them.  We allowed the setting
;; of the conditions to be implicit during rtl generation so that
;; the conditional compare patterns would work.  However this conflicts to
;; some extent with the conditional data operations, so we have to split them
;; up again here.

;; APPLE LOCAL begin v7 support. Merge from mainline
;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
;; conditional execution sufficient?
;; APPLE LOCAL end v7 support. Merge from mainline

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
			  [(match_operand 2 "" "") (match_operand 3 "" "")])
			 (match_dup 0)
			 (match_operand 4 "" "")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM && reload_completed"
  [(set (match_dup 5) (match_dup 6))
   (cond_exec (match_dup 7)
	      (set (match_dup 0) (match_dup 4)))]
  "
  {
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
					     operands[2], operands[3]);
    enum rtx_code rc = GET_CODE (operands[1]);

    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
    if (mode == CCFPmode || mode == CCFPEmode)
      rc = reverse_condition_maybe_unordered (rc);
    else
      rc = reverse_condition (rc);

    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
  }"
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
			  [(match_operand 2 "" "") (match_operand 3 "" "")])
			 (match_operand 4 "" "")
			 (match_dup 0)))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM && reload_completed"
  [(set (match_dup 5) (match_dup 6))
   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
	      (set (match_dup 0) (match_dup 4)))]
  "
  {
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
					     operands[2], operands[3]);

    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
  }"
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
			  [(match_operand 2 "" "") (match_operand 3 "" "")])
			 (match_operand 4 "" "")
			 (match_operand 5 "" "")))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM && reload_completed"
  [(set (match_dup 6) (match_dup 7))
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
	      (set (match_dup 0) (match_dup 4)))
   (cond_exec (match_dup 8)
	      (set (match_dup 0) (match_dup 5)))]
  "
  {
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
					     operands[2], operands[3]);
    enum rtx_code rc = GET_CODE (operands[1]);

    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
    if (mode == CCFPmode || mode == CCFPEmode)
      rc = reverse_condition_maybe_unordered (rc);
    else
      rc = reverse_condition (rc);

    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
  }"
)

(define_split
  [(set (match_operand:SI 0 "s_register_operand" "")
	(if_then_else:SI (match_operator 1 "arm_comparison_operator"
			  [(match_operand:SI 2 "s_register_operand" "")
			   (match_operand:SI 3 "arm_add_operand" "")])
			 (match_operand:SI 4 "arm_rhs_operand" "")
			 (not:SI
			  (match_operand:SI 5 "s_register_operand" ""))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM && reload_completed"
  [(set (match_dup 6) (match_dup 7))
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
	      (set (match_dup 0) (match_dup 4)))
   (cond_exec (match_dup 8)
	      (set (match_dup 0) (not:SI (match_dup 5))))]
  "
  {
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
					     operands[2], operands[3]);
    enum rtx_code rc = GET_CODE (operands[1]);

    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
    if (mode == CCFPmode || mode == CCFPEmode)
      rc = reverse_condition_maybe_unordered (rc);
    else
      rc = reverse_condition (rc);

    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
  }"
)

(define_insn "*cond_move_not"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(if_then_else:SI (match_operator 4 "arm_comparison_operator"
			  [(match_operand 3 "cc_register" "") (const_int 0)])
			 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
			 (not:SI
			  (match_operand:SI 2 "s_register_operand" "r,r"))))]
  "TARGET_ARM"
  "@
   mvn%D4\\t%0, %2
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
  [(set_attr "conds" "use")
;; APPLE LOCAL v7 support. Merge from Codesourcery
   (set_attr "insn" "mvn")
   (set_attr "length" "4,8")]
)

;; The next two patterns occur when an AND operation is followed by a
;; scc insn sequence 

(define_insn "*sign_extract_onebit"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
			 (const_int 1)
			 (match_operand:SI 2 "const_int_operand" "n")))
    (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
    return \"mvnne\\t%0, #0\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

(define_insn "*not_signextract_onebit"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(not:SI
	 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
			  (const_int 1)
			  (match_operand:SI 2 "const_int_operand" "n"))))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_ARM"
  "*
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
    output_asm_insn (\"tst\\t%1, %2\", operands);
    output_asm_insn (\"mvneq\\t%0, #0\", operands);
    return \"movne\\t%0, #0\";
  "
  [(set_attr "conds" "clob")
   (set_attr "length" "12")]
)
;; APPLE LOCAL v7 support. Merge from mainline
;; ??? The above patterns need auditing for Thumb-2

;; Push multiple registers to the stack.  Registers are in parallel (use ...)
;; expressions.  For simplicity, the first register is also in the unspec
;; part.
(define_insn "*push_multi"
  [(match_parallel 2 "multi_register_push"
    [(set (match_operand:BLK 0 "memory_operand" "=m")
	  (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
		      UNSPEC_PUSH_MULT))])]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT"
  "*
  {
    int num_saves = XVECLEN (operands[2], 0);
     
    /* For the StrongARM at least it is faster to
       use STR to store only a single register.
       In Thumb mode always use push, and the assmebler will pick
       something approporiate.  */
    if (num_saves == 1 && TARGET_ARM)
      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
    else
      {
	int i;
	char pattern[100];

	if (TARGET_ARM)
	    strcpy (pattern, \"stmfd\\t%m0!, {%1\");
	else
	    strcpy (pattern, \"push\\t{%1\");

	for (i = 1; i < num_saves; i++)
	  {
	    strcat (pattern, \", %|\");
	    strcat (pattern,
		    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
	  }

	strcat (pattern, \"}\");
	output_asm_insn (pattern, operands);
      }

    return \"\";
  }"
;; APPLE LOCAL end v7 support. Merge from mainline
  [(set_attr "type" "store4")]
)

(define_insn "stack_tie"
  [(set (mem:BLK (scratch))
	(unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
		     (match_operand:SI 1 "s_register_operand" "r")]
		    UNSPEC_PRLG_STK))]
  ""
  ""
  [(set_attr "length" "0")]
)

;; Similarly for the floating point registers
(define_insn "*push_fp_multi"
  [(match_parallel 2 "multi_register_push"
    [(set (match_operand:BLK 0 "memory_operand" "=m")
	  (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
		      UNSPEC_PUSH_MULT))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
  "*
  {
    char pattern[100];

    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
    output_asm_insn (pattern, operands);
    return \"\";
  }"
  [(set_attr "type" "f_store")]
)

;; Special patterns for dealing with the constant pool

;; APPLE LOCAL begin ARM compact switch tables
(define_insn "align_4"
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
  "TARGET_EITHER"
  "*
  assemble_align (32);
  return \"\";
  "
  [(set (attr "length") (const_int 0))]
)

(define_insn "align_8"
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
  "TARGET_EITHER"
  "*
  assemble_align (64);
  return \"\";
  "
  [(set (attr "length") (const_int 0))]
)

(define_insn "consttable_end"
  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
  "TARGET_EITHER"
  "*
  making_const_table = FALSE;
  return \"\";
  "
  [(set_attr "length" "0")]
)
;; APPLE LOCAL end ARM compact switch tables

(define_insn "consttable_1"
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  making_const_table = TRUE;
  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
  assemble_zeros (3);
  return \"\";
  "
  [(set_attr "length" "4")]
)

(define_insn "consttable_2"
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "*
  making_const_table = TRUE;
  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
  assemble_zeros (2);
  return \"\";
  "
  [(set_attr "length" "4")]
)

(define_insn "consttable_4"
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
  "TARGET_EITHER"
  "*
  {
    making_const_table = TRUE;
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
      {
      case MODE_FLOAT:
      {
        REAL_VALUE_TYPE r;
        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
        break;
      }
      default:
        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
        break;
      }
    return \"\";
  }"
  [(set_attr "length" "4")]
)

(define_insn "consttable_8"
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
  "TARGET_EITHER"
  "*
  {
    making_const_table = TRUE;
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
      {
       case MODE_FLOAT:
        {
          REAL_VALUE_TYPE r;
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
          break;
        }
      default:
        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
        break;
      }
    return \"\";
  }"
  [(set_attr "length" "8")]
)

;; APPLE LOCAL begin v7 support. Merge from Codesourcery
(define_insn "consttable_16"
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
  "TARGET_EITHER"
  "*
  {
    making_const_table = TRUE;
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
      {
       case MODE_FLOAT:
        {
          REAL_VALUE_TYPE r;
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
          break;
        }
      default:
        assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
        break;
      }
    return \"\";
  }"
  [(set_attr "length" "16")]
)

;; APPLE LOCAL end v7 support. Merge from Codesourcery
;; Miscellaneous Thumb patterns

(define_expand "tablejump"
  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
	      (use (label_ref (match_operand 1 "" "")))])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "
  if (flag_pic)
    {
      /* Hopefully, CSE will eliminate this copy.  */
      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
      rtx reg2 = gen_reg_rtx (SImode);

      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
      operands[0] = reg2;
    }
  "
)

;; NB never uses BX.
;; APPLE LOCAL v7 support. Merge from mainline
(define_insn "*thumb1_tablejump"
  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
   (use (label_ref (match_operand 1 "" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "mov\\t%|pc, %0"
  [(set_attr "length" "2")]
)

;; V5 Instructions,

(define_insn "clzsi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
;; APPLE LOCAL begin v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch5"
  "clz%?\\t%0, %1"
  [(set_attr "predicable" "yes")
   (set_attr "insn" "clz")])
;; APPLE LOCAL end v7 support. Merge from mainline

(define_expand "ffssi2"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch5"
  "
  {
    rtx t1, t2, t3;

    t1 = gen_reg_rtx (SImode);
    t2 = gen_reg_rtx (SImode);
    t3 = gen_reg_rtx (SImode);

    emit_insn (gen_negsi2 (t1, operands[1]));
    emit_insn (gen_andsi3 (t2, operands[1], t1));
    emit_insn (gen_clzsi2 (t3, t2));
    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
    DONE;
  }"
)

(define_expand "ctzsi2"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch5"
  "
  {
    rtx t1, t2, t3;

    t1 = gen_reg_rtx (SImode);
    t2 = gen_reg_rtx (SImode);
    t3 = gen_reg_rtx (SImode);

    emit_insn (gen_negsi2 (t1, operands[1]));
    emit_insn (gen_andsi3 (t2, operands[1], t1));
    emit_insn (gen_clzsi2 (t3, t2));
    emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
    DONE;
  }"
)

;; V5E instructions.

(define_insn "prefetch"
  [(prefetch (match_operand:SI 0 "address_operand" "p")
	     (match_operand:SI 1 "" "")
	     (match_operand:SI 2 "" ""))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT && arm_arch5e"
  "pld\\t%a0")

;; General predication pattern

(define_cond_exec
  [(match_operator 0 "arm_comparison_operator"
    [(match_operand 1 "cc_register" "")
     (const_int 0)])]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_32BIT"
  ""
)

;; APPLE LOCAL begin ARM compact switch tables
(define_insn "prologue_use"
  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
  ""
  "%@ %0 needed for prologue"
  [(set_attr "length" "0")]
)
;; APPLE LOCAL end ARM compact switch tables


;; Patterns for exception handling

(define_expand "eh_return"
  [(use (match_operand 0 "general_operand" ""))]
  "TARGET_EITHER"
  "
  {
    /* APPLE LOCAL v7 support. Merge from mainline */
    if (TARGET_32BIT)
      emit_insn (gen_arm_eh_return (operands[0]));
    else
      emit_insn (gen_thumb_eh_return (operands[0]));
    DONE;
  }"
)
				   
;; We can't expand this before we know where the link register is stored.
(define_insn_and_split "arm_eh_return"
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
		    VUNSPEC_EH_RETURN)
   (clobber (match_scratch:SI 1 "=&r"))]
  "TARGET_ARM"
  "#"
  "&& reload_completed"
  [(const_int 0)]
  "
  {
    arm_set_return_address (operands[0], operands[1]);
    DONE;
  }"
)

(define_insn_and_split "thumb_eh_return"
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
		    VUNSPEC_EH_RETURN)
   (clobber (match_scratch:SI 1 "=&l"))]
;; APPLE LOCAL v7 support. Merge from mainline
  "TARGET_THUMB1"
  "#"
  "&& reload_completed"
  [(const_int 0)]
  "
  {
    thumb_set_return_address (operands[0], operands[1]);
    DONE;
  }"
)

;; APPLE LOCAL begin ARM 4382996 improve assignments of NE

;; Handle ((x op y) != 0)
(define_insn_and_split "*arm_binary_ne_0"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(ne:SI (match_operator:SI 3 "binary_cc_noclobber_operator"
		  [(match_operand:SI 1 "s_register_operand" "r,r")
	           (match_operand:SI 2 "arm_not_operand" "rI,K")])
	       (const_int 0)))
   (clobber (reg:CC_NOOV CC_REGNUM))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM && reload_completed"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		    (compare:CC_NOOV
		     (match_op_dup:SI 3 [(match_dup 1) (match_dup 2)])
		     (const_int 0)))
	       (set (match_dup 0) 
		     (match_op_dup:SI 3 [(match_dup 1) (match_dup 2)]))])
   (set (match_dup 0) 
	(if_then_else:SI
	 (ne:SI (reg:CC_NOOV CC_REGNUM) (const_int 0))
	 (const_int 1) (match_dup 0)))]
  ""
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

;; A special pattern for ADD, because compare_scc gets recognized first,
;; preventing the above form from being tried.

(define_insn_and_split "*arm_add_ne_0"
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
	(ne:SI (neg:SI (match_operand:SI 1 "s_register_operand" "r,r"))
	       (match_operand:SI 2 "arm_not_operand" "rI,K")))
   (clobber (reg:CC_NOOV CC_REGNUM))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM && reload_completed"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		    (compare:CC_NOOV
		     (plus:SI (match_dup 1) (match_dup 2))
		     (const_int 0)))
	       (set (match_dup 0) 
		     (plus:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 0) 
	(if_then_else:SI
	 (ne:SI (reg:CC_NOOV CC_REGNUM) (const_int 0))
	 (const_int 1) (match_dup 0)))]
  ""
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)

;; A special pattern for MULT, since it requires early clobber semantics.

(define_insn_and_split "*arm_mul_ne_0"
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,r,r")
	(ne:SI (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
			(match_operand:SI 1 "arm_not_operand" "%?r,0,I,K"))
	       (const_int 0)))
   (clobber (reg:CC_NOOV CC_REGNUM))]
  "TARGET_ARM"
  "#"
  "TARGET_ARM && reload_completed"
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
		    (compare:CC_NOOV
		     (mult:SI (match_dup 2) (match_dup 1))
		     (const_int 0)))
	       (set (match_dup 0) 
		     (mult:SI (match_dup 2) (match_dup 1)))])
   (set (match_dup 0) 
	(if_then_else:SI
	 (ne:SI (reg:CC_NOOV CC_REGNUM) (const_int 0))
	 (const_int 1) (match_dup 0)))]
  ""
  [(set_attr "conds" "clob")
   (set_attr "length" "8")]
)
;; APPLE LOCAL end ARM 4382996 improve assignments of NE

;; TLS support

(define_insn "load_tp_hard"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(const_int 0)] UNSPEC_TLS))]
  "TARGET_HARD_TP"
  "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
  [(set_attr "predicable" "yes")]
)

;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
(define_insn "load_tp_soft"
  [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
   (clobber (reg:SI LR_REGNUM))
   (clobber (reg:SI IP_REGNUM))
   (clobber (reg:CC CC_REGNUM))]
  "TARGET_SOFT_TP"
  "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
  [(set_attr "conds" "clob")]
)

;; APPLE LOCAL begin ARM builtin_trap

;; Darwin support

(define_insn "trap"
  [(trap_if (const_int 1) (const_int 0))]
  ""
  "trap")
;; APPLE LOCAL end ARM builtin_trap

;; APPLE LOCAL begin bswap UXTB16 support
(define_expand "bswapsi2"
  [(set (match_operand:SI 0 "s_register_operand" "")
	(bswap:SI (match_operand:SI 1 "s_register_operand" "")))]
  "TARGET_EITHER && arm_arch6"
  ""
)

(define_insn "*arm_bswapsi2"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
	(bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
  "TARGET_ARM && arm_arch6"
  "rev%?\\t%0, %1"
  [(set_attr "predicable" "yes")]
) 

(define_insn "*thumb_bswapsi2"
  [(set (match_operand:SI 0 "register_operand" "=l")
	(bswap:SI (match_operand:SI 1 "register_operand" "l")))]
  "TARGET_THUMB && arm_arch6"
  "rev\\t%0, %1"
  [(set_attr "length" "2")]
)

(define_expand "bswapdi2"
  [(set (match_operand:DI 0 "s_register_operand" "")
	(bswap:DI (match_operand:DI 1 "s_register_operand" "")))]
  "TARGET_EITHER && arm_arch6"
  ""
)

(define_insn "*arm_bswapdi2"
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
	(bswap:DI (match_operand:DI 1 "s_register_operand" "r")))]
  "TARGET_ARM && arm_arch6"
  "rev%?\\t%Q0, %R1\;rev%?\\t%R0, %Q1"
  [(set_attr "predicable" "yes")
   (set_attr "length" "8")]
) 

(define_insn "*thumb_bswapdi2"
  [(set (match_operand:DI 0 "register_operand" "=&l")
	(bswap:DI (match_operand:DI 1 "register_operand" "l")))]
  "TARGET_THUMB && arm_arch6"
  "rev\\t%Q0, %R1\;rev\\t%R0, %Q1"
  [(set_attr "length" "4")]
)

(define_insn "uxtb16"
  [(set (match_operand:SI 0 "s_register_operand" "=r")
        (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
                    (match_operand:SI 2 "const_int_operand" "M")] UNSPEC_UXTB16))]
  "TARGET_ARM && arm_arch6"
  "uxtb16%?\\t%0, %1, ror %2"
  [(set_attr "predicable" "yes")]
)
;; APPLE LOCAL end bswap UXTB16 support

;; Load the FPA co-processor patterns
(include "fpa.md")
;; Load the Maverick co-processor patterns
(include "cirrus.md")
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
;; Vector bits common to IWMMXT and Neon
(include "vec-common.md")
;; APPLE LOCAL end v7 support. Merge from Codesourcery
;; Load the Intel Wireless Multimedia Extension patterns
(include "iwmmxt.md")
;; Load the VFP co-processor patterns
(include "vfp.md")
;; APPLE LOCAL begin v7 support. Merge from mainline
;; Thumb-2 patterns
(include "thumb2.md")
;; APPLE LOCAL end v7 support. Merge from mainline
;; APPLE LOCAL begin v7 support. Merge from Codesourcery
;; Neon patterns
(include "neon.md")
;; APPLE LOCAL end v7 support. Merge from Codesourcery
;; APPLE LOCAL 6258536 atomic builtins
(include "sync.md")

