]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gcc/config/arm/arm.md
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
50 )
51
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
54
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93    (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
94    (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95                          ; instruction stream.
96   ]
97 )
98
99 ;; UNSPEC_VOLATILE Usage:
100
101 (define_constants
102   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103                         ;   insn in the code.
104    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105                         ;   instruction epilogue sequence that isn't expanded
106                         ;   into normal RTL.  Used for both normal and sibcall
107                         ;   epilogues.
108    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
109                         ;   for inlined constants.
110    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
111                         ;   table.
112    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
113                         ;   an 8-bit object.
114    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
115                         ;   a 16-bit object.
116    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
117                         ;   a 32-bit object.
118    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
119                         ;   a 64-bit object.
120    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
121    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
122    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
123    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
124    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
126    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
127                          ; handling.
128   ]
129 )
130 \f
131 ;;---------------------------------------------------------------------------
132 ;; Attributes
133
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code.  This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
138
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
142
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
145
146 ;; Operand number of an input operand that is shifted.  Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
149
150 ; Floating Point Unit.  If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns.  (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154   (const (symbol_ref "arm_fpu_attr")))
155
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
158
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed.  If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
166
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171  [(set_attr "conds" "clob")
172   (set_attr "length" "4")
173   (set_attr "pool_range" "250")])
174
175 ;; The instruction used to implement a particular pattern.  This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
178
179 (define_attr "insn"
180         "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,other"
181         (const_string "other"))
182
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
187
188 ; Classification of each insn
189 ; alu           any alu  instruction that doesn't hit memory or fp
190 ;               regs or have a shifted source operand
191 ; alu_shift     any data instruction that doesn't hit memory or fp
192 ;               regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ;               regs, but has a source operand shifted by a register value
195 ; mult          a multiply instruction
196 ; block         blockage insn, this blocks all functional units
197 ; float         a floating point arithmetic operation (subject to expansion)
198 ; fdivd         DFmode floating point division
199 ; fdivs         SFmode floating point division
200 ; fmul          Floating point multiply
201 ; ffmul         Fast floating point multiply
202 ; farith        Floating point arithmetic (4 cycle)
203 ; ffarith       Fast floating point arithmetic (2 cycle)
204 ; float_em      a floating point arithmetic operation that is normally emulated
205 ;               even on a machine with an fpa.
206 ; f_load        a floating point load from memory
207 ; f_store       a floating point store to memory
208 ; f_load[sd]    single/double load from memory
209 ; f_store[sd]   single/double store to memory
210 ; f_flag        a transfer of co-processor flags to the CPSR
211 ; f_mem_r       a transfer of a floating point register to a real reg via mem
212 ; r_mem_f       the reverse of f_mem_r
213 ; f_2_r         fast transfer float to arm (no memory needed)
214 ; r_2_f         fast transfer arm to float
215 ; f_cvt         convert floating<->integral
216 ; branch        a branch
217 ; call          a subroutine call
218 ; load_byte     load byte(s) from memory to arm registers
219 ; load1         load 1 word from memory to arm registers
220 ; load2         load 2 words from memory to arm registers
221 ; load3         load 3 words from memory to arm registers
222 ; load4         load 4 words from memory to arm registers
223 ; store         store 1 word to memory from arm registers
224 ; store2        store 2 words
225 ; store3        store 3 words
226 ; store4        store 4 (or more) words
227 ;  Additions for Cirrus Maverick co-processor:
228 ; mav_farith    Floating point arithmetic (4 cycle)
229 ; mav_dmult     Double multiplies (7 cycle)
230 ;
231 (define_attr "type"
232         "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" 
233         (if_then_else 
234          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235          (const_string "mult")
236          (const_string "alu")))
237
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options() 
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
241
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions.  It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
245
246 ; USE means that the condition codes are used by the insn in the process of
247 ;   outputting code, this means (at present) that we can't use the insn in
248 ;   inlined branches
249 ;
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ;   well defined manner.
252 ;
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ;   they are altered at all
255 ;
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
258 ;
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ;   output of this insn
261
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263         (if_then_else (eq_attr "type" "call")
264          (const_string "clob")
265          (const_string "nocond")))
266
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by 
269 ; gen...).  We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
272
273 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
274 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
278
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor.  Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282   (if_then_else (eq_attr "type"
283                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
284                 (const_string "yes")
285                 (const_string "no")))
286
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290   (if_then_else (eq_attr "type"
291                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292                 (const_string "single")
293                 (const_string "multi")))
294
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label.  Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
298
299
300 ;;---------------------------------------------------------------------------
301 ;; Mode macros
302
303 ; A list of modes that are exactly 64 bits in size.  We use this to expand
304 ; some splits that are the same for all modes when operating on ARM 
305 ; registers.
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
307
308 ;;---------------------------------------------------------------------------
309 ;; Predicates
310
311 (include "predicates.md")
312 (include "constraints.md")
313
314 ;;---------------------------------------------------------------------------
315 ;; Pipeline descriptions
316
317 ;; Processor type.  This is created automatically from arm-cores.def.
318 (include "arm-tune.md")
319
320 ;; True if the generic scheduling description should be used.
321
322 (define_attr "generic_sched" "yes,no"
323   (const (if_then_else 
324           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
325           (const_string "no")
326           (const_string "yes"))))
327
328 (define_attr "generic_vfp" "yes,no"
329   (const (if_then_else
330           (and (eq_attr "fpu" "vfp")
331                (eq_attr "tune" "!arm1020e,arm1022e"))
332           (const_string "yes")
333           (const_string "no"))))
334
335 (include "arm-generic.md")
336 (include "arm926ejs.md")
337 (include "arm1020e.md")
338 (include "arm1026ejs.md")
339 (include "arm1136jfs.md")
340
341 \f
342 ;;---------------------------------------------------------------------------
343 ;; Insn patterns
344 ;;
345 ;; Addition insns.
346
347 ;; Note: For DImode insns, there is normally no reason why operands should
348 ;; not be in the same register, what we don't want is for something being
349 ;; written to partially overlap something that is an input.
350 ;; Cirrus 64bit additions should not be split because we have a native
351 ;; 64bit addition instructions.
352
353 (define_expand "adddi3"
354  [(parallel
355    [(set (match_operand:DI           0 "s_register_operand" "")
356           (plus:DI (match_operand:DI 1 "s_register_operand" "")
357                    (match_operand:DI 2 "s_register_operand" "")))
358     (clobber (reg:CC CC_REGNUM))])]
359   "TARGET_EITHER"
360   "
361   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
362     {
363       if (!cirrus_fp_register (operands[0], DImode))
364         operands[0] = force_reg (DImode, operands[0]);
365       if (!cirrus_fp_register (operands[1], DImode))
366         operands[1] = force_reg (DImode, operands[1]);
367       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
368       DONE;
369     }
370
371   if (TARGET_THUMB)
372     {
373       if (GET_CODE (operands[1]) != REG)
374         operands[1] = force_reg (SImode, operands[1]);
375       if (GET_CODE (operands[2]) != REG)
376         operands[2] = force_reg (SImode, operands[2]);
377      }
378   "
379 )
380
381 (define_insn "*thumb_adddi3"
382   [(set (match_operand:DI          0 "register_operand" "=l")
383         (plus:DI (match_operand:DI 1 "register_operand" "%0")
384                  (match_operand:DI 2 "register_operand" "l")))
385    (clobber (reg:CC CC_REGNUM))
386   ]
387   "TARGET_THUMB"
388   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
389   [(set_attr "length" "4")]
390 )
391
392 (define_insn_and_split "*arm_adddi3"
393   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
394         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
395                  (match_operand:DI 2 "s_register_operand" "r,  0")))
396    (clobber (reg:CC CC_REGNUM))]
397   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398   "#"
399   "TARGET_ARM && reload_completed"
400   [(parallel [(set (reg:CC_C CC_REGNUM)
401                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402                                  (match_dup 1)))
403               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405                                (plus:SI (match_dup 4) (match_dup 5))))]
406   "
407   {
408     operands[3] = gen_highpart (SImode, operands[0]);
409     operands[0] = gen_lowpart (SImode, operands[0]);
410     operands[4] = gen_highpart (SImode, operands[1]);
411     operands[1] = gen_lowpart (SImode, operands[1]);
412     operands[5] = gen_highpart (SImode, operands[2]);
413     operands[2] = gen_lowpart (SImode, operands[2]);
414   }"
415   [(set_attr "conds" "clob")
416    (set_attr "length" "8")]
417 )
418
419 (define_insn_and_split "*adddi_sesidi_di"
420   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
421         (plus:DI (sign_extend:DI
422                   (match_operand:SI 2 "s_register_operand" "r,r"))
423                  (match_operand:DI 1 "s_register_operand" "r,0")))
424    (clobber (reg:CC CC_REGNUM))]
425   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
426   "#"
427   "TARGET_ARM && reload_completed"
428   [(parallel [(set (reg:CC_C CC_REGNUM)
429                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
430                                  (match_dup 1)))
431               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
432    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
433                                (plus:SI (ashiftrt:SI (match_dup 2)
434                                                      (const_int 31))
435                                         (match_dup 4))))]
436   "
437   {
438     operands[3] = gen_highpart (SImode, operands[0]);
439     operands[0] = gen_lowpart (SImode, operands[0]);
440     operands[4] = gen_highpart (SImode, operands[1]);
441     operands[1] = gen_lowpart (SImode, operands[1]);
442     operands[2] = gen_lowpart (SImode, operands[2]);
443   }"
444   [(set_attr "conds" "clob")
445    (set_attr "length" "8")]
446 )
447
448 (define_insn_and_split "*adddi_zesidi_di"
449   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
450         (plus:DI (zero_extend:DI
451                   (match_operand:SI 2 "s_register_operand" "r,r"))
452                  (match_operand:DI 1 "s_register_operand" "r,0")))
453    (clobber (reg:CC CC_REGNUM))]
454   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
455   "#"
456   "TARGET_ARM && reload_completed"
457   [(parallel [(set (reg:CC_C CC_REGNUM)
458                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459                                  (match_dup 1)))
460               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
461    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
462                                (plus:SI (match_dup 4) (const_int 0))))]
463   "
464   {
465     operands[3] = gen_highpart (SImode, operands[0]);
466     operands[0] = gen_lowpart (SImode, operands[0]);
467     operands[4] = gen_highpart (SImode, operands[1]);
468     operands[1] = gen_lowpart (SImode, operands[1]);
469     operands[2] = gen_lowpart (SImode, operands[2]);
470   }"
471   [(set_attr "conds" "clob")
472    (set_attr "length" "8")]
473 )
474
475 (define_expand "addsi3"
476   [(set (match_operand:SI          0 "s_register_operand" "")
477         (plus:SI (match_operand:SI 1 "s_register_operand" "")
478                  (match_operand:SI 2 "reg_or_int_operand" "")))]
479   "TARGET_EITHER"
480   "
481   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
482     {
483       arm_split_constant (PLUS, SImode, NULL_RTX,
484                           INTVAL (operands[2]), operands[0], operands[1],
485                           optimize && !no_new_pseudos);
486       DONE;
487     }
488   "
489 )
490
491 ; If there is a scratch available, this will be faster than synthesizing the
492 ; addition.
493 (define_peephole2
494   [(match_scratch:SI 3 "r")
495    (set (match_operand:SI          0 "arm_general_register_operand" "")
496         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
497                  (match_operand:SI 2 "const_int_operand"  "")))]
498   "TARGET_ARM &&
499    !(const_ok_for_arm (INTVAL (operands[2]))
500      || const_ok_for_arm (-INTVAL (operands[2])))
501     && const_ok_for_arm (~INTVAL (operands[2]))"
502   [(set (match_dup 3) (match_dup 2))
503    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
504   ""
505 )
506
507 (define_insn_and_split "*arm_addsi3"
508   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
509         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
510                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
511   "TARGET_ARM"
512   "@
513    add%?\\t%0, %1, %2
514    sub%?\\t%0, %1, #%n2
515    #"
516   "TARGET_ARM &&
517    GET_CODE (operands[2]) == CONST_INT
518    && !(const_ok_for_arm (INTVAL (operands[2]))
519         || const_ok_for_arm (-INTVAL (operands[2])))"
520   [(clobber (const_int 0))]
521   "
522   arm_split_constant (PLUS, SImode, curr_insn,
523                       INTVAL (operands[2]), operands[0],
524                       operands[1], 0);
525   DONE;
526   "
527   [(set_attr "length" "4,4,16")
528    (set_attr "predicable" "yes")]
529 )
530
531 ;; Register group 'k' is a single register group containing only the stack
532 ;; register.  Trying to reload it will always fail catastrophically,
533 ;; so never allow those alternatives to match if reloading is needed.
534
535 (define_insn "*thumb_addsi3"
536   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
537         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
538                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
539   "TARGET_THUMB"
540   "*
541    static const char * const asms[] = 
542    {
543      \"add\\t%0, %0, %2\",
544      \"sub\\t%0, %0, #%n2\",
545      \"add\\t%0, %1, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %0, %2\",
548      \"add\\t%0, %1, %2\",
549      \"add\\t%0, %1, %2\"
550    };
551    if ((which_alternative == 2 || which_alternative == 6)
552        && GET_CODE (operands[2]) == CONST_INT
553        && INTVAL (operands[2]) < 0)
554      return \"sub\\t%0, %1, #%n2\";
555    return asms[which_alternative];
556   "
557   [(set_attr "length" "2")]
558 )
559
560 ;; Reloading and elimination of the frame pointer can
561 ;; sometimes cause this optimization to be missed.
562 (define_peephole2
563   [(set (match_operand:SI 0 "arm_general_register_operand" "")
564         (match_operand:SI 1 "const_int_operand" ""))
565    (set (match_dup 0)
566         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
567   "TARGET_THUMB
568    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
569    && (INTVAL (operands[1]) & 3) == 0"
570   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
571   ""
572 )
573
574 (define_insn "*addsi3_compare0"
575   [(set (reg:CC_NOOV CC_REGNUM)
576         (compare:CC_NOOV
577          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
578                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
579          (const_int 0)))
580    (set (match_operand:SI 0 "s_register_operand" "=r,r")
581         (plus:SI (match_dup 1) (match_dup 2)))]
582   "TARGET_ARM"
583   "@
584    add%?s\\t%0, %1, %2
585    sub%?s\\t%0, %1, #%n2"
586   [(set_attr "conds" "set")]
587 )
588
589 (define_insn "*addsi3_compare0_scratch"
590   [(set (reg:CC_NOOV CC_REGNUM)
591         (compare:CC_NOOV
592          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
593                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
594          (const_int 0)))]
595   "TARGET_ARM"
596   "@
597    cmn%?\\t%0, %1
598    cmp%?\\t%0, #%n1"
599   [(set_attr "conds" "set")]
600 )
601
602 (define_insn "*compare_negsi_si"
603   [(set (reg:CC_Z CC_REGNUM)
604         (compare:CC_Z
605          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
606          (match_operand:SI 1 "s_register_operand" "r")))]
607   "TARGET_ARM"
608   "cmn%?\\t%1, %0"
609   [(set_attr "conds" "set")]
610 )
611
612 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
613 ;; addend is a constant.
614 (define_insn "*cmpsi2_addneg"
615   [(set (reg:CC CC_REGNUM)
616         (compare:CC
617          (match_operand:SI 1 "s_register_operand" "r,r")
618          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
619    (set (match_operand:SI 0 "s_register_operand" "=r,r")
620         (plus:SI (match_dup 1)
621                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
622   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
623   "@
624    sub%?s\\t%0, %1, %2
625    add%?s\\t%0, %1, #%n2"
626   [(set_attr "conds" "set")]
627 )
628
629 ;; Convert the sequence
630 ;;  sub  rd, rn, #1
631 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
632 ;;  bne  dest
633 ;; into
634 ;;  subs rd, rn, #1
635 ;;  bcs  dest   ((unsigned)rn >= 1)
636 ;; similarly for the beq variant using bcc.
637 ;; This is a common looping idiom (while (n--))
638 (define_peephole2
639   [(set (match_operand:SI 0 "arm_general_register_operand" "")
640         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
641                  (const_int -1)))
642    (set (match_operand 2 "cc_register" "")
643         (compare (match_dup 0) (const_int -1)))
644    (set (pc)
645         (if_then_else (match_operator 3 "equality_operator"
646                        [(match_dup 2) (const_int 0)])
647                       (match_operand 4 "" "")
648                       (match_operand 5 "" "")))]
649   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
650   [(parallel[
651     (set (match_dup 2)
652          (compare:CC
653           (match_dup 1) (const_int 1)))
654     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
655    (set (pc)
656         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
657                       (match_dup 4)
658                       (match_dup 5)))]
659   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
660    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
661                                   ? GEU : LTU),
662                                  VOIDmode, 
663                                  operands[2], const0_rtx);"
664 )
665
666 ;; The next four insns work because they compare the result with one of
667 ;; the operands, and we know that the use of the condition code is
668 ;; either GEU or LTU, so we can use the carry flag from the addition
669 ;; instead of doing the compare a second time.
670 (define_insn "*addsi3_compare_op1"
671   [(set (reg:CC_C CC_REGNUM)
672         (compare:CC_C
673          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
674                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
675          (match_dup 1)))
676    (set (match_operand:SI 0 "s_register_operand" "=r,r")
677         (plus:SI (match_dup 1) (match_dup 2)))]
678   "TARGET_ARM"
679   "@
680    add%?s\\t%0, %1, %2
681    sub%?s\\t%0, %1, #%n2"
682   [(set_attr "conds" "set")]
683 )
684
685 (define_insn "*addsi3_compare_op2"
686   [(set (reg:CC_C CC_REGNUM)
687         (compare:CC_C
688          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
689                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
690          (match_dup 2)))
691    (set (match_operand:SI 0 "s_register_operand" "=r,r")
692         (plus:SI (match_dup 1) (match_dup 2)))]
693   "TARGET_ARM"
694   "@
695    add%?s\\t%0, %1, %2
696    sub%?s\\t%0, %1, #%n2"
697   [(set_attr "conds" "set")]
698 )
699
700 (define_insn "*compare_addsi2_op0"
701   [(set (reg:CC_C CC_REGNUM)
702         (compare:CC_C
703          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
705          (match_dup 0)))]
706   "TARGET_ARM"
707   "@
708    cmn%?\\t%0, %1
709    cmp%?\\t%0, #%n1"
710   [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*compare_addsi2_op1"
714   [(set (reg:CC_C CC_REGNUM)
715         (compare:CC_C
716          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
717                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
718          (match_dup 1)))]
719   "TARGET_ARM"
720   "@
721    cmn%?\\t%0, %1
722    cmp%?\\t%0, #%n1"
723   [(set_attr "conds" "set")]
724 )
725
726 (define_insn "*addsi3_carryin"
727   [(set (match_operand:SI 0 "s_register_operand" "=r")
728         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
729                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
730                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
731   "TARGET_ARM"
732   "adc%?\\t%0, %1, %2"
733   [(set_attr "conds" "use")]
734 )
735
736 (define_insn "*addsi3_carryin_shift"
737   [(set (match_operand:SI 0 "s_register_operand" "=r")
738         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739                  (plus:SI
740                    (match_operator:SI 2 "shift_operator"
741                       [(match_operand:SI 3 "s_register_operand" "r")
742                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
743                     (match_operand:SI 1 "s_register_operand" "r"))))]
744   "TARGET_ARM"
745   "adc%?\\t%0, %1, %3%S2"
746   [(set_attr "conds" "use")
747    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
748                       (const_string "alu_shift")
749                       (const_string "alu_shift_reg")))]
750 )
751
752 (define_insn "*addsi3_carryin_alt1"
753   [(set (match_operand:SI 0 "s_register_operand" "=r")
754         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
755                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
756                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
757   "TARGET_ARM"
758   "adc%?\\t%0, %1, %2"
759   [(set_attr "conds" "use")]
760 )
761
762 (define_insn "*addsi3_carryin_alt2"
763   [(set (match_operand:SI 0 "s_register_operand" "=r")
764         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
765                           (match_operand:SI 1 "s_register_operand" "r"))
766                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
767   "TARGET_ARM"
768   "adc%?\\t%0, %1, %2"
769   [(set_attr "conds" "use")]
770 )
771
772 (define_insn "*addsi3_carryin_alt3"
773   [(set (match_operand:SI 0 "s_register_operand" "=r")
774         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
775                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
776                  (match_operand:SI 1 "s_register_operand" "r")))]
777   "TARGET_ARM"
778   "adc%?\\t%0, %1, %2"
779   [(set_attr "conds" "use")]
780 )
781
782 (define_insn "incscc"
783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
784         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
785                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
786                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
787   "TARGET_ARM"
788   "@
789   add%d2\\t%0, %1, #1
790   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
791   [(set_attr "conds" "use")
792    (set_attr "length" "4,8")]
793 )
794
795 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
796 (define_split
797   [(set (match_operand:SI 0 "s_register_operand" "")
798         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
799                             (match_operand:SI 2 "s_register_operand" ""))
800                  (const_int -1)))
801    (clobber (match_operand:SI 3 "s_register_operand" ""))]
802   "TARGET_ARM"
803   [(set (match_dup 3) (match_dup 1))
804    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
805   "
806   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
807 ")
808
809 (define_expand "addsf3"
810   [(set (match_operand:SF          0 "s_register_operand" "")
811         (plus:SF (match_operand:SF 1 "s_register_operand" "")
812                  (match_operand:SF 2 "arm_float_add_operand" "")))]
813   "TARGET_ARM && TARGET_HARD_FLOAT"
814   "
815   if (TARGET_MAVERICK
816       && !cirrus_fp_register (operands[2], SFmode))
817     operands[2] = force_reg (SFmode, operands[2]);
818 ")
819
820 (define_expand "adddf3"
821   [(set (match_operand:DF          0 "s_register_operand" "")
822         (plus:DF (match_operand:DF 1 "s_register_operand" "")
823                  (match_operand:DF 2 "arm_float_add_operand" "")))]
824   "TARGET_ARM && TARGET_HARD_FLOAT"
825   "
826   if (TARGET_MAVERICK
827       && !cirrus_fp_register (operands[2], DFmode))
828     operands[2] = force_reg (DFmode, operands[2]);
829 ")
830
831 (define_expand "subdi3"
832  [(parallel
833    [(set (match_operand:DI            0 "s_register_operand" "")
834           (minus:DI (match_operand:DI 1 "s_register_operand" "")
835                     (match_operand:DI 2 "s_register_operand" "")))
836     (clobber (reg:CC CC_REGNUM))])]
837   "TARGET_EITHER"
838   "
839   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
840       && TARGET_ARM
841       && cirrus_fp_register (operands[0], DImode)
842       && cirrus_fp_register (operands[1], DImode))
843     {
844       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
845       DONE;
846     }
847
848   if (TARGET_THUMB)
849     {
850       if (GET_CODE (operands[1]) != REG)
851         operands[1] = force_reg (SImode, operands[1]);
852       if (GET_CODE (operands[2]) != REG)
853         operands[2] = force_reg (SImode, operands[2]);
854      }  
855   "
856 )
857
858 (define_insn "*arm_subdi3"
859   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
860         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
861                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
862    (clobber (reg:CC CC_REGNUM))]
863   "TARGET_ARM"
864   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
865   [(set_attr "conds" "clob")
866    (set_attr "length" "8")]
867 )
868
869 (define_insn "*thumb_subdi3"
870   [(set (match_operand:DI           0 "register_operand" "=l")
871         (minus:DI (match_operand:DI 1 "register_operand"  "0")
872                   (match_operand:DI 2 "register_operand"  "l")))
873    (clobber (reg:CC CC_REGNUM))]
874   "TARGET_THUMB"
875   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
876   [(set_attr "length" "4")]
877 )
878
879 (define_insn "*subdi_di_zesidi"
880   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
882                   (zero_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
889 )
890
891 (define_insn "*subdi_di_sesidi"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
894                   (sign_extend:DI
895                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
901 )
902
903 (define_insn "*subdi_zesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (zero_extend:DI
906                    (match_operand:SI 2 "s_register_operand"  "r,r"))
907                   (match_operand:DI  1 "s_register_operand" "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
913 )
914
915 (define_insn "*subdi_sesidi_di"
916   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
917         (minus:DI (sign_extend:DI
918                    (match_operand:SI 2 "s_register_operand"   "r,r"))
919                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
920    (clobber (reg:CC CC_REGNUM))]
921   "TARGET_ARM"
922   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
923   [(set_attr "conds" "clob")
924    (set_attr "length" "8")]
925 )
926
927 (define_insn "*subdi_zesidi_zesidi"
928   [(set (match_operand:DI            0 "s_register_operand" "=r")
929         (minus:DI (zero_extend:DI
930                    (match_operand:SI 1 "s_register_operand"  "r"))
931                   (zero_extend:DI
932                    (match_operand:SI 2 "s_register_operand"  "r"))))
933    (clobber (reg:CC CC_REGNUM))]
934   "TARGET_ARM"
935   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
936   [(set_attr "conds" "clob")
937    (set_attr "length" "8")]
938 )
939
940 (define_expand "subsi3"
941   [(set (match_operand:SI           0 "s_register_operand" "")
942         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
943                   (match_operand:SI 2 "s_register_operand" "")))]
944   "TARGET_EITHER"
945   "
946   if (GET_CODE (operands[1]) == CONST_INT)
947     {
948       if (TARGET_ARM)
949         {
950           arm_split_constant (MINUS, SImode, NULL_RTX,
951                               INTVAL (operands[1]), operands[0],
952                               operands[2], optimize && !no_new_pseudos);
953           DONE;
954         }
955       else /* TARGET_THUMB */
956         operands[1] = force_reg (SImode, operands[1]);
957     }
958   "
959 )
960
961 (define_insn "*thumb_subsi3_insn"
962   [(set (match_operand:SI           0 "register_operand" "=l")
963         (minus:SI (match_operand:SI 1 "register_operand" "l")
964                   (match_operand:SI 2 "register_operand" "l")))]
965   "TARGET_THUMB"
966   "sub\\t%0, %1, %2"
967   [(set_attr "length" "2")]
968 )
969
970 (define_insn_and_split "*arm_subsi3_insn"
971   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
972         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
973                   (match_operand:SI 2 "s_register_operand" "r,r")))]
974   "TARGET_ARM"
975   "@
976    rsb%?\\t%0, %2, %1
977    #"
978   "TARGET_ARM
979    && GET_CODE (operands[1]) == CONST_INT
980    && !const_ok_for_arm (INTVAL (operands[1]))"
981   [(clobber (const_int 0))]
982   "
983   arm_split_constant (MINUS, SImode, curr_insn,
984                       INTVAL (operands[1]), operands[0], operands[2], 0);
985   DONE;
986   "
987   [(set_attr "length" "4,16")
988    (set_attr "predicable" "yes")]
989 )
990
991 (define_peephole2
992   [(match_scratch:SI 3 "r")
993    (set (match_operand:SI 0 "arm_general_register_operand" "")
994         (minus:SI (match_operand:SI 1 "const_int_operand" "")
995                   (match_operand:SI 2 "arm_general_register_operand" "")))]
996   "TARGET_ARM
997    && !const_ok_for_arm (INTVAL (operands[1]))
998    && const_ok_for_arm (~INTVAL (operands[1]))"
999   [(set (match_dup 3) (match_dup 1))
1000    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1001   ""
1002 )
1003
1004 (define_insn "*subsi3_compare0"
1005   [(set (reg:CC_NOOV CC_REGNUM)
1006         (compare:CC_NOOV
1007          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1008                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1009          (const_int 0)))
1010    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1011         (minus:SI (match_dup 1) (match_dup 2)))]
1012   "TARGET_ARM"
1013   "@
1014    sub%?s\\t%0, %1, %2
1015    rsb%?s\\t%0, %2, %1"
1016   [(set_attr "conds" "set")]
1017 )
1018
1019 (define_insn "decscc"
1020   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1021         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1022                   (match_operator:SI 2 "arm_comparison_operator"
1023                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1024   "TARGET_ARM"
1025   "@
1026    sub%d2\\t%0, %1, #1
1027    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1028   [(set_attr "conds" "use")
1029    (set_attr "length" "*,8")]
1030 )
1031
1032 (define_expand "subsf3"
1033   [(set (match_operand:SF           0 "s_register_operand" "")
1034         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1035                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1036   "TARGET_ARM && TARGET_HARD_FLOAT"
1037   "
1038   if (TARGET_MAVERICK)
1039     {
1040       if (!cirrus_fp_register (operands[1], SFmode))
1041         operands[1] = force_reg (SFmode, operands[1]);
1042       if (!cirrus_fp_register (operands[2], SFmode))
1043         operands[2] = force_reg (SFmode, operands[2]);
1044     }
1045 ")
1046
1047 (define_expand "subdf3"
1048   [(set (match_operand:DF           0 "s_register_operand" "")
1049         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1050                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1051   "TARGET_ARM && TARGET_HARD_FLOAT"
1052   "
1053   if (TARGET_MAVERICK)
1054     {
1055        if (!cirrus_fp_register (operands[1], DFmode))
1056          operands[1] = force_reg (DFmode, operands[1]);
1057        if (!cirrus_fp_register (operands[2], DFmode))
1058          operands[2] = force_reg (DFmode, operands[2]);
1059     }
1060 ")
1061
1062 \f
1063 ;; Multiplication insns
1064
1065 (define_expand "mulsi3"
1066   [(set (match_operand:SI          0 "s_register_operand" "")
1067         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1068                  (match_operand:SI 1 "s_register_operand" "")))]
1069   "TARGET_EITHER"
1070   ""
1071 )
1072
1073 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1074 (define_insn "*arm_mulsi3"
1075   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1076         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1077                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1078   "TARGET_ARM"
1079   "mul%?\\t%0, %2, %1"
1080   [(set_attr "insn" "mul")
1081    (set_attr "predicable" "yes")]
1082 )
1083
1084 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1085 ; 1 and 2; are the same, because reload will make operand 0 match 
1086 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1087 ; this by adding another alternative to match this case, and then `reload' 
1088 ; it ourselves.  This alternative must come first.
1089 (define_insn "*thumb_mulsi3"
1090   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1091         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1092                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1093   "TARGET_THUMB"
1094   "*
1095   if (which_alternative < 2)
1096     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1097   else
1098     return \"mul\\t%0, %2\";
1099   "
1100   [(set_attr "length" "4,4,2")
1101    (set_attr "insn" "mul")]
1102 )
1103
1104 (define_insn "*mulsi3_compare0"
1105   [(set (reg:CC_NOOV CC_REGNUM)
1106         (compare:CC_NOOV (mult:SI
1107                           (match_operand:SI 2 "s_register_operand" "r,r")
1108                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109                          (const_int 0)))
1110    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1111         (mult:SI (match_dup 2) (match_dup 1)))]
1112   "TARGET_ARM"
1113   "mul%?s\\t%0, %2, %1"
1114   [(set_attr "conds" "set")
1115    (set_attr "insn" "muls")]
1116 )
1117
1118 (define_insn "*mulsi_compare0_scratch"
1119   [(set (reg:CC_NOOV CC_REGNUM)
1120         (compare:CC_NOOV (mult:SI
1121                           (match_operand:SI 2 "s_register_operand" "r,r")
1122                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1123                          (const_int 0)))
1124    (clobber (match_scratch:SI 0 "=&r,&r"))]
1125   "TARGET_ARM"
1126   "mul%?s\\t%0, %2, %1"
1127   [(set_attr "conds" "set")
1128    (set_attr "insn" "muls")]
1129 )
1130
1131 ;; Unnamed templates to match MLA instruction.
1132
1133 (define_insn "*mulsi3addsi"
1134   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1135         (plus:SI
1136           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1137                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1138           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1139   "TARGET_ARM"
1140   "mla%?\\t%0, %2, %1, %3"
1141   [(set_attr "insn" "mla")
1142    (set_attr "predicable" "yes")]
1143 )
1144
1145 (define_insn "*mulsi3addsi_compare0"
1146   [(set (reg:CC_NOOV CC_REGNUM)
1147         (compare:CC_NOOV
1148          (plus:SI (mult:SI
1149                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1150                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1151                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1152          (const_int 0)))
1153    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1154         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1155                  (match_dup 3)))]
1156   "TARGET_ARM"
1157   "mla%?s\\t%0, %2, %1, %3"
1158   [(set_attr "conds" "set")
1159    (set_attr "insn" "mlas")]
1160 )
1161
1162 (define_insn "*mulsi3addsi_compare0_scratch"
1163   [(set (reg:CC_NOOV CC_REGNUM)
1164         (compare:CC_NOOV
1165          (plus:SI (mult:SI
1166                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1167                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1168                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1169          (const_int 0)))
1170    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1171   "TARGET_ARM"
1172   "mla%?s\\t%0, %2, %1, %3"
1173   [(set_attr "conds" "set")
1174    (set_attr "insn" "mlas")]
1175 )
1176
1177 ;; Unnamed template to match long long multiply-accumulate (smlal)
1178
1179 (define_insn "*mulsidi3adddi"
1180   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1181         (plus:DI
1182          (mult:DI
1183           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1184           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1185          (match_operand:DI 1 "s_register_operand" "0")))]
1186   "TARGET_ARM && arm_arch3m"
1187   "smlal%?\\t%Q0, %R0, %3, %2"
1188   [(set_attr "insn" "smlal")
1189    (set_attr "predicable" "yes")]
1190 )
1191
1192 (define_insn "mulsidi3"
1193   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194         (mult:DI
1195          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197   "TARGET_ARM && arm_arch3m"
1198   "smull%?\\t%Q0, %R0, %1, %2"
1199   [(set_attr "insn" "smull")
1200    (set_attr "predicable" "yes")]
1201 )
1202
1203 (define_insn "umulsidi3"
1204   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1205         (mult:DI
1206          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1207          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1208   "TARGET_ARM && arm_arch3m"
1209   "umull%?\\t%Q0, %R0, %1, %2"
1210   [(set_attr "insn" "umull")
1211    (set_attr "predicable" "yes")]
1212 )
1213
1214 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1215
1216 (define_insn "*umulsidi3adddi"
1217   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1218         (plus:DI
1219          (mult:DI
1220           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1221           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1222          (match_operand:DI 1 "s_register_operand" "0")))]
1223   "TARGET_ARM && arm_arch3m"
1224   "umlal%?\\t%Q0, %R0, %3, %2"
1225   [(set_attr "insn" "umlal")
1226    (set_attr "predicable" "yes")]
1227 )
1228
1229 (define_insn "smulsi3_highpart"
1230   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1231         (truncate:SI
1232          (lshiftrt:DI
1233           (mult:DI
1234            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1235            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1236           (const_int 32))))
1237    (clobber (match_scratch:SI 3 "=&r,&r"))]
1238   "TARGET_ARM && arm_arch3m"
1239   "smull%?\\t%3, %0, %2, %1"
1240   [(set_attr "insn" "smull")
1241    (set_attr "predicable" "yes")]
1242 )
1243
1244 (define_insn "umulsi3_highpart"
1245   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1246         (truncate:SI
1247          (lshiftrt:DI
1248           (mult:DI
1249            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1250            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1251           (const_int 32))))
1252    (clobber (match_scratch:SI 3 "=&r,&r"))]
1253   "TARGET_ARM && arm_arch3m"
1254   "umull%?\\t%3, %0, %2, %1"
1255   [(set_attr "insn" "umull")
1256    (set_attr "predicable" "yes")]
1257 )
1258
1259 (define_insn "mulhisi3"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (sign_extend:SI
1262                   (match_operand:HI 1 "s_register_operand" "%r"))
1263                  (sign_extend:SI
1264                   (match_operand:HI 2 "s_register_operand" "r"))))]
1265   "TARGET_ARM && arm_arch5e"
1266   "smulbb%?\\t%0, %1, %2"
1267   [(set_attr "insn" "smulxy")
1268    (set_attr "predicable" "yes")]
1269 )
1270
1271 (define_insn "*mulhisi3tb"
1272   [(set (match_operand:SI 0 "s_register_operand" "=r")
1273         (mult:SI (ashiftrt:SI
1274                   (match_operand:SI 1 "s_register_operand" "r")
1275                   (const_int 16))
1276                  (sign_extend:SI
1277                   (match_operand:HI 2 "s_register_operand" "r"))))]
1278   "TARGET_ARM && arm_arch5e"
1279   "smultb%?\\t%0, %1, %2"
1280   [(set_attr "insn" "smulxy")
1281    (set_attr "predicable" "yes")]
1282 )
1283
1284 (define_insn "*mulhisi3bt"
1285   [(set (match_operand:SI 0 "s_register_operand" "=r")
1286         (mult:SI (sign_extend:SI
1287                   (match_operand:HI 1 "s_register_operand" "r"))
1288                  (ashiftrt:SI
1289                   (match_operand:SI 2 "s_register_operand" "r")
1290                   (const_int 16))))]
1291   "TARGET_ARM && arm_arch5e"
1292   "smulbt%?\\t%0, %1, %2"
1293   [(set_attr "insn" "smulxy")
1294    (set_attr "predicable" "yes")]
1295 )
1296
1297 (define_insn "*mulhisi3tt"
1298   [(set (match_operand:SI 0 "s_register_operand" "=r")
1299         (mult:SI (ashiftrt:SI
1300                   (match_operand:SI 1 "s_register_operand" "r")
1301                   (const_int 16))
1302                  (ashiftrt:SI
1303                   (match_operand:SI 2 "s_register_operand" "r")
1304                   (const_int 16))))]
1305   "TARGET_ARM && arm_arch5e"
1306   "smultt%?\\t%0, %1, %2"
1307   [(set_attr "insn" "smulxy")
1308    (set_attr "predicable" "yes")]
1309 )
1310
1311 (define_insn "*mulhisi3addsi"
1312   [(set (match_operand:SI 0 "s_register_operand" "=r")
1313         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1314                  (mult:SI (sign_extend:SI
1315                            (match_operand:HI 2 "s_register_operand" "%r"))
1316                           (sign_extend:SI
1317                            (match_operand:HI 3 "s_register_operand" "r")))))]
1318   "TARGET_ARM && arm_arch5e"
1319   "smlabb%?\\t%0, %2, %3, %1"
1320   [(set_attr "insn" "smlaxy")
1321    (set_attr "predicable" "yes")]
1322 )
1323
1324 (define_insn "*mulhidi3adddi"
1325   [(set (match_operand:DI 0 "s_register_operand" "=r")
1326         (plus:DI
1327           (match_operand:DI 1 "s_register_operand" "0")
1328           (mult:DI (sign_extend:DI
1329                     (match_operand:HI 2 "s_register_operand" "%r"))
1330                    (sign_extend:DI
1331                     (match_operand:HI 3 "s_register_operand" "r")))))]
1332   "TARGET_ARM && arm_arch5e"
1333   "smlalbb%?\\t%Q0, %R0, %2, %3"
1334   [(set_attr "insn" "smlalxy")
1335    (set_attr "predicable" "yes")])
1336
1337 (define_expand "mulsf3"
1338   [(set (match_operand:SF          0 "s_register_operand" "")
1339         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1340                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1341   "TARGET_ARM && TARGET_HARD_FLOAT"
1342   "
1343   if (TARGET_MAVERICK
1344       && !cirrus_fp_register (operands[2], SFmode))
1345     operands[2] = force_reg (SFmode, operands[2]);
1346 ")
1347
1348 (define_expand "muldf3"
1349   [(set (match_operand:DF          0 "s_register_operand" "")
1350         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1351                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1352   "TARGET_ARM && TARGET_HARD_FLOAT"
1353   "
1354   if (TARGET_MAVERICK
1355       && !cirrus_fp_register (operands[2], DFmode))
1356     operands[2] = force_reg (DFmode, operands[2]);
1357 ")
1358 \f
1359 ;; Division insns
1360
1361 (define_expand "divsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "")
1363         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1364                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1366   "")
1367
1368 (define_expand "divdf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "")
1370         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1371                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1373   "")
1374 \f
1375 ;; Modulo insns
1376
1377 (define_expand "modsf3"
1378   [(set (match_operand:SF 0 "s_register_operand" "")
1379         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1380                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1381   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1382   "")
1383
1384 (define_expand "moddf3"
1385   [(set (match_operand:DF 0 "s_register_operand" "")
1386         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1387                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1388   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1389   "")
1390 \f
1391 ;; Boolean and,ior,xor insns
1392
1393 ;; Split up double word logical operations
1394
1395 ;; Split up simple DImode logical operations.  Simply perform the logical
1396 ;; operation on the upper and lower halves of the registers.
1397 (define_split
1398   [(set (match_operand:DI 0 "s_register_operand" "")
1399         (match_operator:DI 6 "logical_binary_operator"
1400           [(match_operand:DI 1 "s_register_operand" "")
1401            (match_operand:DI 2 "s_register_operand" "")]))]
1402   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1403   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1404    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1405   "
1406   {
1407     operands[3] = gen_highpart (SImode, operands[0]);
1408     operands[0] = gen_lowpart (SImode, operands[0]);
1409     operands[4] = gen_highpart (SImode, operands[1]);
1410     operands[1] = gen_lowpart (SImode, operands[1]);
1411     operands[5] = gen_highpart (SImode, operands[2]);
1412     operands[2] = gen_lowpart (SImode, operands[2]);
1413   }"
1414 )
1415
1416 (define_split
1417   [(set (match_operand:DI 0 "s_register_operand" "")
1418         (match_operator:DI 6 "logical_binary_operator"
1419           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1420            (match_operand:DI 1 "s_register_operand" "")]))]
1421   "TARGET_ARM && reload_completed"
1422   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1423    (set (match_dup 3) (match_op_dup:SI 6
1424                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1425                          (match_dup 4)]))]
1426   "
1427   {
1428     operands[3] = gen_highpart (SImode, operands[0]);
1429     operands[0] = gen_lowpart (SImode, operands[0]);
1430     operands[4] = gen_highpart (SImode, operands[1]);
1431     operands[1] = gen_lowpart (SImode, operands[1]);
1432     operands[5] = gen_highpart (SImode, operands[2]);
1433     operands[2] = gen_lowpart (SImode, operands[2]);
1434   }"
1435 )
1436
1437 ;; The zero extend of operand 2 means we can just copy the high part of
1438 ;; operand1 into operand0.
1439 (define_split
1440   [(set (match_operand:DI 0 "s_register_operand" "")
1441         (ior:DI
1442           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1443           (match_operand:DI 1 "s_register_operand" "")))]
1444   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1445   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1446    (set (match_dup 3) (match_dup 4))]
1447   "
1448   {
1449     operands[4] = gen_highpart (SImode, operands[1]);
1450     operands[3] = gen_highpart (SImode, operands[0]);
1451     operands[0] = gen_lowpart (SImode, operands[0]);
1452     operands[1] = gen_lowpart (SImode, operands[1]);
1453   }"
1454 )
1455
1456 ;; The zero extend of operand 2 means we can just copy the high part of
1457 ;; operand1 into operand0.
1458 (define_split
1459   [(set (match_operand:DI 0 "s_register_operand" "")
1460         (xor:DI
1461           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462           (match_operand:DI 1 "s_register_operand" "")))]
1463   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1464   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1465    (set (match_dup 3) (match_dup 4))]
1466   "
1467   {
1468     operands[4] = gen_highpart (SImode, operands[1]);
1469     operands[3] = gen_highpart (SImode, operands[0]);
1470     operands[0] = gen_lowpart (SImode, operands[0]);
1471     operands[1] = gen_lowpart (SImode, operands[1]);
1472   }"
1473 )
1474
1475 (define_insn "anddi3"
1476   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1477         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1478                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1479   "TARGET_ARM && ! TARGET_IWMMXT"
1480   "#"
1481   [(set_attr "length" "8")]
1482 )
1483
1484 (define_insn_and_split "*anddi_zesidi_di"
1485   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1486         (and:DI (zero_extend:DI
1487                  (match_operand:SI 2 "s_register_operand" "r,r"))
1488                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1489   "TARGET_ARM"
1490   "#"
1491   "TARGET_ARM && reload_completed"
1492   ; The zero extend of operand 2 clears the high word of the output
1493   ; operand.
1494   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1495    (set (match_dup 3) (const_int 0))]
1496   "
1497   {
1498     operands[3] = gen_highpart (SImode, operands[0]);
1499     operands[0] = gen_lowpart (SImode, operands[0]);
1500     operands[1] = gen_lowpart (SImode, operands[1]);
1501   }"
1502   [(set_attr "length" "8")]
1503 )
1504
1505 (define_insn "*anddi_sesdi_di"
1506   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1507         (and:DI (sign_extend:DI
1508                  (match_operand:SI 2 "s_register_operand" "r,r"))
1509                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1510   "TARGET_ARM"
1511   "#"
1512   [(set_attr "length" "8")]
1513 )
1514
1515 (define_expand "andsi3"
1516   [(set (match_operand:SI         0 "s_register_operand" "")
1517         (and:SI (match_operand:SI 1 "s_register_operand" "")
1518                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1519   "TARGET_EITHER"
1520   "
1521   if (TARGET_ARM)
1522     {
1523       if (GET_CODE (operands[2]) == CONST_INT)
1524         {
1525           arm_split_constant (AND, SImode, NULL_RTX,
1526                               INTVAL (operands[2]), operands[0],
1527                               operands[1], optimize && !no_new_pseudos);
1528
1529           DONE;
1530         }
1531     }
1532   else /* TARGET_THUMB */
1533     {
1534       if (GET_CODE (operands[2]) != CONST_INT)
1535         operands[2] = force_reg (SImode, operands[2]);
1536       else
1537         {
1538           int i;
1539           
1540           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1541             {
1542               operands[2] = force_reg (SImode,
1543                                        GEN_INT (~INTVAL (operands[2])));
1544               
1545               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1546               
1547               DONE;
1548             }
1549
1550           for (i = 9; i <= 31; i++)
1551             {
1552               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1553                 {
1554                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1555                                         const0_rtx));
1556                   DONE;
1557                 }
1558               else if ((((HOST_WIDE_INT) 1) << i) - 1
1559                        == ~INTVAL (operands[2]))
1560                 {
1561                   rtx shift = GEN_INT (i);
1562                   rtx reg = gen_reg_rtx (SImode);
1563                 
1564                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1565                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1566                   
1567                   DONE;
1568                 }
1569             }
1570
1571           operands[2] = force_reg (SImode, operands[2]);
1572         }
1573     }
1574   "
1575 )
1576
1577 (define_insn_and_split "*arm_andsi3_insn"
1578   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1579         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1580                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1581   "TARGET_ARM"
1582   "@
1583    and%?\\t%0, %1, %2
1584    bic%?\\t%0, %1, #%B2
1585    #"
1586   "TARGET_ARM
1587    && GET_CODE (operands[2]) == CONST_INT
1588    && !(const_ok_for_arm (INTVAL (operands[2]))
1589         || const_ok_for_arm (~INTVAL (operands[2])))"
1590   [(clobber (const_int 0))]
1591   "
1592   arm_split_constant  (AND, SImode, curr_insn, 
1593                        INTVAL (operands[2]), operands[0], operands[1], 0);
1594   DONE;
1595   "
1596   [(set_attr "length" "4,4,16")
1597    (set_attr "predicable" "yes")]
1598 )
1599
1600 (define_insn "*thumb_andsi3_insn"
1601   [(set (match_operand:SI         0 "register_operand" "=l")
1602         (and:SI (match_operand:SI 1 "register_operand" "%0")
1603                 (match_operand:SI 2 "register_operand" "l")))]
1604   "TARGET_THUMB"
1605   "and\\t%0, %0, %2"
1606   [(set_attr "length" "2")]
1607 )
1608
1609 (define_insn "*andsi3_compare0"
1610   [(set (reg:CC_NOOV CC_REGNUM)
1611         (compare:CC_NOOV
1612          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1613                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1614          (const_int 0)))
1615    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1616         (and:SI (match_dup 1) (match_dup 2)))]
1617   "TARGET_ARM"
1618   "@
1619    and%?s\\t%0, %1, %2
1620    bic%?s\\t%0, %1, #%B2"
1621   [(set_attr "conds" "set")]
1622 )
1623
1624 (define_insn "*andsi3_compare0_scratch"
1625   [(set (reg:CC_NOOV CC_REGNUM)
1626         (compare:CC_NOOV
1627          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1628                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1629          (const_int 0)))
1630    (clobber (match_scratch:SI 2 "=X,r"))]
1631   "TARGET_ARM"
1632   "@
1633    tst%?\\t%0, %1
1634    bic%?s\\t%2, %0, #%B1"
1635   [(set_attr "conds" "set")]
1636 )
1637
1638 (define_insn "*zeroextractsi_compare0_scratch"
1639   [(set (reg:CC_NOOV CC_REGNUM)
1640         (compare:CC_NOOV (zero_extract:SI
1641                           (match_operand:SI 0 "s_register_operand" "r")
1642                           (match_operand 1 "const_int_operand" "n")
1643                           (match_operand 2 "const_int_operand" "n"))
1644                          (const_int 0)))]
1645   "TARGET_ARM
1646   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1647       && INTVAL (operands[1]) > 0 
1648       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1649       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1650   "*
1651   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1652                          << INTVAL (operands[2]));
1653   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1654   return \"\";
1655   "
1656   [(set_attr "conds" "set")]
1657 )
1658
1659 (define_insn_and_split "*ne_zeroextractsi"
1660   [(set (match_operand:SI 0 "s_register_operand" "=r")
1661         (ne:SI (zero_extract:SI
1662                 (match_operand:SI 1 "s_register_operand" "r")
1663                 (match_operand:SI 2 "const_int_operand" "n")
1664                 (match_operand:SI 3 "const_int_operand" "n"))
1665                (const_int 0)))
1666    (clobber (reg:CC CC_REGNUM))]
1667   "TARGET_ARM
1668    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1669        && INTVAL (operands[2]) > 0 
1670        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1671        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1672   "#"
1673   "TARGET_ARM
1674    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1675        && INTVAL (operands[2]) > 0 
1676        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1677        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1678   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1679                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1680                                     (const_int 0)))
1681               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1682    (set (match_dup 0)
1683         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1684                          (match_dup 0) (const_int 1)))]
1685   "
1686   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1687                          << INTVAL (operands[3])); 
1688   "
1689   [(set_attr "conds" "clob")
1690    (set_attr "length" "8")]
1691 )
1692
1693 (define_insn_and_split "*ne_zeroextractsi_shifted"
1694   [(set (match_operand:SI 0 "s_register_operand" "=r")
1695         (ne:SI (zero_extract:SI
1696                 (match_operand:SI 1 "s_register_operand" "r")
1697                 (match_operand:SI 2 "const_int_operand" "n")
1698                 (const_int 0))
1699                (const_int 0)))
1700    (clobber (reg:CC CC_REGNUM))]
1701   "TARGET_ARM"
1702   "#"
1703   "TARGET_ARM"
1704   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1705                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1706                                     (const_int 0)))
1707               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1708    (set (match_dup 0)
1709         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1710                          (match_dup 0) (const_int 1)))]
1711   "
1712   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1713   "
1714   [(set_attr "conds" "clob")
1715    (set_attr "length" "8")]
1716 )
1717
1718 (define_insn_and_split "*ite_ne_zeroextractsi"
1719   [(set (match_operand:SI 0 "s_register_operand" "=r")
1720         (if_then_else:SI (ne (zero_extract:SI
1721                               (match_operand:SI 1 "s_register_operand" "r")
1722                               (match_operand:SI 2 "const_int_operand" "n")
1723                               (match_operand:SI 3 "const_int_operand" "n"))
1724                              (const_int 0))
1725                          (match_operand:SI 4 "arm_not_operand" "rIK")
1726                          (const_int 0)))
1727    (clobber (reg:CC CC_REGNUM))]
1728   "TARGET_ARM
1729    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1730        && INTVAL (operands[2]) > 0 
1731        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1732        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1733    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1734   "#"
1735   "TARGET_ARM
1736    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1737        && INTVAL (operands[2]) > 0 
1738        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1739        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1740    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1741   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1742                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1743                                     (const_int 0)))
1744               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1745    (set (match_dup 0)
1746         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1747                          (match_dup 0) (match_dup 4)))]
1748   "
1749   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1750                          << INTVAL (operands[3])); 
1751   "
1752   [(set_attr "conds" "clob")
1753    (set_attr "length" "8")]
1754 )
1755
1756 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1757   [(set (match_operand:SI 0 "s_register_operand" "=r")
1758         (if_then_else:SI (ne (zero_extract:SI
1759                               (match_operand:SI 1 "s_register_operand" "r")
1760                               (match_operand:SI 2 "const_int_operand" "n")
1761                               (const_int 0))
1762                              (const_int 0))
1763                          (match_operand:SI 3 "arm_not_operand" "rIK")
1764                          (const_int 0)))
1765    (clobber (reg:CC CC_REGNUM))]
1766   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1767   "#"
1768   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1769   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1770                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1771                                     (const_int 0)))
1772               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1773    (set (match_dup 0)
1774         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1775                          (match_dup 0) (match_dup 3)))]
1776   "
1777   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1778   "
1779   [(set_attr "conds" "clob")
1780    (set_attr "length" "8")]
1781 )
1782
1783 (define_split
1784   [(set (match_operand:SI 0 "s_register_operand" "")
1785         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1786                          (match_operand:SI 2 "const_int_operand" "")
1787                          (match_operand:SI 3 "const_int_operand" "")))
1788    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1789   "TARGET_THUMB"
1790   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1791    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1792   "{
1793      HOST_WIDE_INT temp = INTVAL (operands[2]);
1794
1795      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1796      operands[3] = GEN_INT (32 - temp);
1797    }"
1798 )
1799
1800 (define_split
1801   [(set (match_operand:SI 0 "s_register_operand" "")
1802         (match_operator:SI 1 "shiftable_operator"
1803          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1804                            (match_operand:SI 3 "const_int_operand" "")
1805                            (match_operand:SI 4 "const_int_operand" ""))
1806           (match_operand:SI 5 "s_register_operand" "")]))
1807    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1808   "TARGET_ARM"
1809   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1810    (set (match_dup 0)
1811         (match_op_dup 1
1812          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1813           (match_dup 5)]))]
1814   "{
1815      HOST_WIDE_INT temp = INTVAL (operands[3]);
1816
1817      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1818      operands[4] = GEN_INT (32 - temp);
1819    }"
1820 )
1821   
1822 (define_split
1823   [(set (match_operand:SI 0 "s_register_operand" "")
1824         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1825                          (match_operand:SI 2 "const_int_operand" "")
1826                          (match_operand:SI 3 "const_int_operand" "")))]
1827   "TARGET_THUMB"
1828   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1829    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1830   "{
1831      HOST_WIDE_INT temp = INTVAL (operands[2]);
1832
1833      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1834      operands[3] = GEN_INT (32 - temp);
1835    }"
1836 )
1837
1838 (define_split
1839   [(set (match_operand:SI 0 "s_register_operand" "")
1840         (match_operator:SI 1 "shiftable_operator"
1841          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1842                            (match_operand:SI 3 "const_int_operand" "")
1843                            (match_operand:SI 4 "const_int_operand" ""))
1844           (match_operand:SI 5 "s_register_operand" "")]))
1845    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1846   "TARGET_ARM"
1847   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1848    (set (match_dup 0)
1849         (match_op_dup 1
1850          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1851           (match_dup 5)]))]
1852   "{
1853      HOST_WIDE_INT temp = INTVAL (operands[3]);
1854
1855      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1856      operands[4] = GEN_INT (32 - temp);
1857    }"
1858 )
1859   
1860 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1861 ;;; represented by the bitfield, then this will produce incorrect results.
1862 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1863 ;;; which have a real bit-field insert instruction, the truncation happens
1864 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1865 ;;; bit-field insert instruction, we would have to emit code here to truncate
1866 ;;; the value before we insert.  This loses some of the advantage of having
1867 ;;; this insv pattern, so this pattern needs to be reevalutated.
1868
1869 (define_expand "insv"
1870   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1871                          (match_operand:SI 1 "general_operand" "")
1872                          (match_operand:SI 2 "general_operand" ""))
1873         (match_operand:SI 3 "reg_or_int_operand" ""))]
1874   "TARGET_ARM"
1875   "
1876   {
1877     int start_bit = INTVAL (operands[2]);
1878     int width = INTVAL (operands[1]);
1879     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1880     rtx target, subtarget;
1881
1882     target = operands[0];
1883     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1884        subreg as the final target.  */
1885     if (GET_CODE (target) == SUBREG)
1886       {
1887         subtarget = gen_reg_rtx (SImode);
1888         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1889             < GET_MODE_SIZE (SImode))
1890           target = SUBREG_REG (target);
1891       }
1892     else
1893       subtarget = target;    
1894
1895     if (GET_CODE (operands[3]) == CONST_INT)
1896       {
1897         /* Since we are inserting a known constant, we may be able to
1898            reduce the number of bits that we have to clear so that
1899            the mask becomes simple.  */
1900         /* ??? This code does not check to see if the new mask is actually
1901            simpler.  It may not be.  */
1902         rtx op1 = gen_reg_rtx (SImode);
1903         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1904            start of this pattern.  */
1905         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1906         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1907
1908         emit_insn (gen_andsi3 (op1, operands[0],
1909                                gen_int_mode (~mask2, SImode)));
1910         emit_insn (gen_iorsi3 (subtarget, op1,
1911                                gen_int_mode (op3_value << start_bit, SImode)));
1912       }
1913     else if (start_bit == 0
1914              && !(const_ok_for_arm (mask)
1915                   || const_ok_for_arm (~mask)))
1916       {
1917         /* A Trick, since we are setting the bottom bits in the word,
1918            we can shift operand[3] up, operand[0] down, OR them together
1919            and rotate the result back again.  This takes 3 insns, and
1920            the third might be mergeable into another op.  */
1921         /* The shift up copes with the possibility that operand[3] is
1922            wider than the bitfield.  */
1923         rtx op0 = gen_reg_rtx (SImode);
1924         rtx op1 = gen_reg_rtx (SImode);
1925
1926         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1927         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1928         emit_insn (gen_iorsi3  (op1, op1, op0));
1929         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1930       }
1931     else if ((width + start_bit == 32)
1932              && !(const_ok_for_arm (mask)
1933                   || const_ok_for_arm (~mask)))
1934       {
1935         /* Similar trick, but slightly less efficient.  */
1936
1937         rtx op0 = gen_reg_rtx (SImode);
1938         rtx op1 = gen_reg_rtx (SImode);
1939
1940         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1941         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1942         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1943         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1944       }
1945     else
1946       {
1947         rtx op0 = gen_int_mode (mask, SImode);
1948         rtx op1 = gen_reg_rtx (SImode);
1949         rtx op2 = gen_reg_rtx (SImode);
1950
1951         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1952           {
1953             rtx tmp = gen_reg_rtx (SImode);
1954
1955             emit_insn (gen_movsi (tmp, op0));
1956             op0 = tmp;
1957           }
1958
1959         /* Mask out any bits in operand[3] that are not needed.  */
1960            emit_insn (gen_andsi3 (op1, operands[3], op0));
1961
1962         if (GET_CODE (op0) == CONST_INT
1963             && (const_ok_for_arm (mask << start_bit)
1964                 || const_ok_for_arm (~(mask << start_bit))))
1965           {
1966             op0 = gen_int_mode (~(mask << start_bit), SImode);
1967             emit_insn (gen_andsi3 (op2, operands[0], op0));
1968           }
1969         else
1970           {
1971             if (GET_CODE (op0) == CONST_INT)
1972               {
1973                 rtx tmp = gen_reg_rtx (SImode);
1974
1975                 emit_insn (gen_movsi (tmp, op0));
1976                 op0 = tmp;
1977               }
1978
1979             if (start_bit != 0)
1980               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1981             
1982             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1983           }
1984
1985         if (start_bit != 0)
1986           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1987
1988         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1989       }
1990
1991     if (subtarget != target)
1992       {
1993         /* If TARGET is still a SUBREG, then it must be wider than a word,
1994            so we must be careful only to set the subword we were asked to.  */
1995         if (GET_CODE (target) == SUBREG)
1996           emit_move_insn (target, subtarget);
1997         else
1998           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1999       }
2000
2001     DONE;
2002   }"
2003 )
2004
2005 ; constants for op 2 will never be given to these patterns.
2006 (define_insn_and_split "*anddi_notdi_di"
2007   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2008         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2009                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2010   "TARGET_ARM"
2011   "#"
2012   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2013   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2014    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2015   "
2016   {
2017     operands[3] = gen_highpart (SImode, operands[0]);
2018     operands[0] = gen_lowpart (SImode, operands[0]);
2019     operands[4] = gen_highpart (SImode, operands[1]);
2020     operands[1] = gen_lowpart (SImode, operands[1]);
2021     operands[5] = gen_highpart (SImode, operands[2]);
2022     operands[2] = gen_lowpart (SImode, operands[2]);
2023   }"
2024   [(set_attr "length" "8")
2025    (set_attr "predicable" "yes")]
2026 )
2027   
2028 (define_insn_and_split "*anddi_notzesidi_di"
2029   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2030         (and:DI (not:DI (zero_extend:DI
2031                          (match_operand:SI 2 "s_register_operand" "r,r")))
2032                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2033   "TARGET_ARM"
2034   "@
2035    bic%?\\t%Q0, %Q1, %2
2036    #"
2037   ; (not (zero_extend ...)) allows us to just copy the high word from
2038   ; operand1 to operand0.
2039   "TARGET_ARM
2040    && reload_completed
2041    && operands[0] != operands[1]"
2042   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2043    (set (match_dup 3) (match_dup 4))]
2044   "
2045   {
2046     operands[3] = gen_highpart (SImode, operands[0]);
2047     operands[0] = gen_lowpart (SImode, operands[0]);
2048     operands[4] = gen_highpart (SImode, operands[1]);
2049     operands[1] = gen_lowpart (SImode, operands[1]);
2050   }"
2051   [(set_attr "length" "4,8")
2052    (set_attr "predicable" "yes")]
2053 )
2054   
2055 (define_insn_and_split "*anddi_notsesidi_di"
2056   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2057         (and:DI (not:DI (sign_extend:DI
2058                          (match_operand:SI 2 "s_register_operand" "r,r")))
2059                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2060   "TARGET_ARM"
2061   "#"
2062   "TARGET_ARM && reload_completed"
2063   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2064    (set (match_dup 3) (and:SI (not:SI
2065                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2066                                (match_dup 4)))]
2067   "
2068   {
2069     operands[3] = gen_highpart (SImode, operands[0]);
2070     operands[0] = gen_lowpart (SImode, operands[0]);
2071     operands[4] = gen_highpart (SImode, operands[1]);
2072     operands[1] = gen_lowpart (SImode, operands[1]);
2073   }"
2074   [(set_attr "length" "8")
2075    (set_attr "predicable" "yes")]
2076 )
2077   
2078 (define_insn "andsi_notsi_si"
2079   [(set (match_operand:SI 0 "s_register_operand" "=r")
2080         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2081                 (match_operand:SI 1 "s_register_operand" "r")))]
2082   "TARGET_ARM"
2083   "bic%?\\t%0, %1, %2"
2084   [(set_attr "predicable" "yes")]
2085 )
2086
2087 (define_insn "bicsi3"
2088   [(set (match_operand:SI                 0 "register_operand" "=l")
2089         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2090                 (match_operand:SI         2 "register_operand" "0")))]
2091   "TARGET_THUMB"
2092   "bic\\t%0, %0, %1"
2093   [(set_attr "length" "2")]
2094 )
2095
2096 (define_insn "andsi_not_shiftsi_si"
2097   [(set (match_operand:SI 0 "s_register_operand" "=r")
2098         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2099                          [(match_operand:SI 2 "s_register_operand" "r")
2100                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2101                 (match_operand:SI 1 "s_register_operand" "r")))]
2102   "TARGET_ARM"
2103   "bic%?\\t%0, %1, %2%S4"
2104   [(set_attr "predicable" "yes")
2105    (set_attr "shift" "2")
2106    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2107                       (const_string "alu_shift")
2108                       (const_string "alu_shift_reg")))]
2109 )
2110
2111 (define_insn "*andsi_notsi_si_compare0"
2112   [(set (reg:CC_NOOV CC_REGNUM)
2113         (compare:CC_NOOV
2114          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115                  (match_operand:SI 1 "s_register_operand" "r"))
2116          (const_int 0)))
2117    (set (match_operand:SI 0 "s_register_operand" "=r")
2118         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2119   "TARGET_ARM"
2120   "bic%?s\\t%0, %1, %2"
2121   [(set_attr "conds" "set")]
2122 )
2123
2124 (define_insn "*andsi_notsi_si_compare0_scratch"
2125   [(set (reg:CC_NOOV CC_REGNUM)
2126         (compare:CC_NOOV
2127          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2128                  (match_operand:SI 1 "s_register_operand" "r"))
2129          (const_int 0)))
2130    (clobber (match_scratch:SI 0 "=r"))]
2131   "TARGET_ARM"
2132   "bic%?s\\t%0, %1, %2"
2133   [(set_attr "conds" "set")]
2134 )
2135
2136 (define_insn "iordi3"
2137   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2138         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2139                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2140   "TARGET_ARM && ! TARGET_IWMMXT"
2141   "#"
2142   [(set_attr "length" "8")
2143    (set_attr "predicable" "yes")]
2144 )
2145
2146 (define_insn "*iordi_zesidi_di"
2147   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148         (ior:DI (zero_extend:DI
2149                  (match_operand:SI 2 "s_register_operand" "r,r"))
2150                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2151   "TARGET_ARM"
2152   "@
2153    orr%?\\t%Q0, %Q1, %2
2154    #"
2155   [(set_attr "length" "4,8")
2156    (set_attr "predicable" "yes")]
2157 )
2158
2159 (define_insn "*iordi_sesidi_di"
2160   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2161         (ior:DI (sign_extend:DI
2162                  (match_operand:SI 2 "s_register_operand" "r,r"))
2163                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2164   "TARGET_ARM"
2165   "#"
2166   [(set_attr "length" "8")
2167    (set_attr "predicable" "yes")]
2168 )
2169
2170 (define_expand "iorsi3"
2171   [(set (match_operand:SI         0 "s_register_operand" "")
2172         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2173                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2174   "TARGET_EITHER"
2175   "
2176   if (GET_CODE (operands[2]) == CONST_INT)
2177     {
2178       if (TARGET_ARM)
2179         {
2180           arm_split_constant (IOR, SImode, NULL_RTX,
2181                               INTVAL (operands[2]), operands[0], operands[1],
2182                               optimize && !no_new_pseudos);
2183           DONE;
2184         }
2185       else /* TARGET_THUMB */
2186         operands [2] = force_reg (SImode, operands [2]);
2187     }
2188   "
2189 )
2190
2191 (define_insn_and_split "*arm_iorsi3"
2192   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2193         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2194                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2195   "TARGET_ARM"
2196   "@
2197    orr%?\\t%0, %1, %2
2198    #"
2199   "TARGET_ARM
2200    && GET_CODE (operands[2]) == CONST_INT
2201    && !const_ok_for_arm (INTVAL (operands[2]))"
2202   [(clobber (const_int 0))]
2203   "
2204   arm_split_constant (IOR, SImode, curr_insn, 
2205                       INTVAL (operands[2]), operands[0], operands[1], 0);
2206   DONE;
2207   "
2208   [(set_attr "length" "4,16")
2209    (set_attr "predicable" "yes")]
2210 )
2211
2212 (define_insn "*thumb_iorsi3"
2213   [(set (match_operand:SI         0 "register_operand" "=l")
2214         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2215                 (match_operand:SI 2 "register_operand" "l")))]
2216   "TARGET_THUMB"
2217   "orr\\t%0, %0, %2"
2218   [(set_attr "length" "2")]
2219 )
2220
2221 (define_peephole2
2222   [(match_scratch:SI 3 "r")
2223    (set (match_operand:SI 0 "arm_general_register_operand" "")
2224         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2225                 (match_operand:SI 2 "const_int_operand" "")))]
2226   "TARGET_ARM
2227    && !const_ok_for_arm (INTVAL (operands[2]))
2228    && const_ok_for_arm (~INTVAL (operands[2]))"
2229   [(set (match_dup 3) (match_dup 2))
2230    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2231   ""
2232 )
2233
2234 (define_insn "*iorsi3_compare0"
2235   [(set (reg:CC_NOOV CC_REGNUM)
2236         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2237                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238                          (const_int 0)))
2239    (set (match_operand:SI 0 "s_register_operand" "=r")
2240         (ior:SI (match_dup 1) (match_dup 2)))]
2241   "TARGET_ARM"
2242   "orr%?s\\t%0, %1, %2"
2243   [(set_attr "conds" "set")]
2244 )
2245
2246 (define_insn "*iorsi3_compare0_scratch"
2247   [(set (reg:CC_NOOV CC_REGNUM)
2248         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2249                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2250                          (const_int 0)))
2251    (clobber (match_scratch:SI 0 "=r"))]
2252   "TARGET_ARM"
2253   "orr%?s\\t%0, %1, %2"
2254   [(set_attr "conds" "set")]
2255 )
2256
2257 (define_insn "xordi3"
2258   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2259         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2260                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2261   "TARGET_ARM && !TARGET_IWMMXT"
2262   "#"
2263   [(set_attr "length" "8")
2264    (set_attr "predicable" "yes")]
2265 )
2266
2267 (define_insn "*xordi_zesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (zero_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2272   "TARGET_ARM"
2273   "@
2274    eor%?\\t%Q0, %Q1, %2
2275    #"
2276   [(set_attr "length" "4,8")
2277    (set_attr "predicable" "yes")]
2278 )
2279
2280 (define_insn "*xordi_sesidi_di"
2281   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2282         (xor:DI (sign_extend:DI
2283                  (match_operand:SI 2 "s_register_operand" "r,r"))
2284                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2285   "TARGET_ARM"
2286   "#"
2287   [(set_attr "length" "8")
2288    (set_attr "predicable" "yes")]
2289 )
2290
2291 (define_expand "xorsi3"
2292   [(set (match_operand:SI         0 "s_register_operand" "")
2293         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2294                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2295   "TARGET_EITHER"
2296   "if (TARGET_THUMB)
2297      if (GET_CODE (operands[2]) == CONST_INT)
2298        operands[2] = force_reg (SImode, operands[2]);
2299   "
2300 )
2301
2302 (define_insn "*arm_xorsi3"
2303   [(set (match_operand:SI         0 "s_register_operand" "=r")
2304         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2305                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2306   "TARGET_ARM"
2307   "eor%?\\t%0, %1, %2"
2308   [(set_attr "predicable" "yes")]
2309 )
2310
2311 (define_insn "*thumb_xorsi3"
2312   [(set (match_operand:SI         0 "register_operand" "=l")
2313         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2314                 (match_operand:SI 2 "register_operand" "l")))]
2315   "TARGET_THUMB"
2316   "eor\\t%0, %0, %2"
2317   [(set_attr "length" "2")]
2318 )
2319
2320 (define_insn "*xorsi3_compare0"
2321   [(set (reg:CC_NOOV CC_REGNUM)
2322         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2323                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2324                          (const_int 0)))
2325    (set (match_operand:SI 0 "s_register_operand" "=r")
2326         (xor:SI (match_dup 1) (match_dup 2)))]
2327   "TARGET_ARM"
2328   "eor%?s\\t%0, %1, %2"
2329   [(set_attr "conds" "set")]
2330 )
2331
2332 (define_insn "*xorsi3_compare0_scratch"
2333   [(set (reg:CC_NOOV CC_REGNUM)
2334         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2335                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2336                          (const_int 0)))]
2337   "TARGET_ARM"
2338   "teq%?\\t%0, %1"
2339   [(set_attr "conds" "set")]
2340 )
2341
2342 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2343 ; (NOT D) we can sometimes merge the final NOT into one of the following
2344 ; insns.
2345
2346 (define_split
2347   [(set (match_operand:SI 0 "s_register_operand" "")
2348         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2349                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2350                 (match_operand:SI 3 "arm_rhs_operand" "")))
2351    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2352   "TARGET_ARM"
2353   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2354                               (not:SI (match_dup 3))))
2355    (set (match_dup 0) (not:SI (match_dup 4)))]
2356   ""
2357 )
2358
2359 (define_insn "*andsi_iorsi3_notsi"
2360   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2361         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2362                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2363                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2364   "TARGET_ARM"
2365   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2366   [(set_attr "length" "8")
2367    (set_attr "predicable" "yes")]
2368 )
2369
2370 (define_split
2371   [(set (match_operand:SI 0 "s_register_operand" "")
2372         (match_operator:SI 1 "logical_binary_operator"
2373          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2374                            (match_operand:SI 3 "const_int_operand" "")
2375                            (match_operand:SI 4 "const_int_operand" ""))
2376           (match_operator:SI 9 "logical_binary_operator"
2377            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2378                          (match_operand:SI 6 "const_int_operand" ""))
2379             (match_operand:SI 7 "s_register_operand" "")])]))
2380    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2381   "TARGET_ARM
2382    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2383    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2384   [(set (match_dup 8)
2385         (match_op_dup 1
2386          [(ashift:SI (match_dup 2) (match_dup 4))
2387           (match_dup 5)]))
2388    (set (match_dup 0)
2389         (match_op_dup 1
2390          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2391           (match_dup 7)]))]
2392   "
2393   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2394 ")
2395
2396 (define_split
2397   [(set (match_operand:SI 0 "s_register_operand" "")
2398         (match_operator:SI 1 "logical_binary_operator"
2399          [(match_operator:SI 9 "logical_binary_operator"
2400            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2401                          (match_operand:SI 6 "const_int_operand" ""))
2402             (match_operand:SI 7 "s_register_operand" "")])
2403           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2404                            (match_operand:SI 3 "const_int_operand" "")
2405                            (match_operand:SI 4 "const_int_operand" ""))]))
2406    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2407   "TARGET_ARM
2408    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2409    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2410   [(set (match_dup 8)
2411         (match_op_dup 1
2412          [(ashift:SI (match_dup 2) (match_dup 4))
2413           (match_dup 5)]))
2414    (set (match_dup 0)
2415         (match_op_dup 1
2416          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2417           (match_dup 7)]))]
2418   "
2419   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2420 ")
2421
2422 (define_split
2423   [(set (match_operand:SI 0 "s_register_operand" "")
2424         (match_operator:SI 1 "logical_binary_operator"
2425          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2426                            (match_operand:SI 3 "const_int_operand" "")
2427                            (match_operand:SI 4 "const_int_operand" ""))
2428           (match_operator:SI 9 "logical_binary_operator"
2429            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2430                          (match_operand:SI 6 "const_int_operand" ""))
2431             (match_operand:SI 7 "s_register_operand" "")])]))
2432    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2433   "TARGET_ARM
2434    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2435    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2436   [(set (match_dup 8)
2437         (match_op_dup 1
2438          [(ashift:SI (match_dup 2) (match_dup 4))
2439           (match_dup 5)]))
2440    (set (match_dup 0)
2441         (match_op_dup 1
2442          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2443           (match_dup 7)]))]
2444   "
2445   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2446 ")
2447
2448 (define_split
2449   [(set (match_operand:SI 0 "s_register_operand" "")
2450         (match_operator:SI 1 "logical_binary_operator"
2451          [(match_operator:SI 9 "logical_binary_operator"
2452            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2453                          (match_operand:SI 6 "const_int_operand" ""))
2454             (match_operand:SI 7 "s_register_operand" "")])
2455           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2456                            (match_operand:SI 3 "const_int_operand" "")
2457                            (match_operand:SI 4 "const_int_operand" ""))]))
2458    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2459   "TARGET_ARM
2460    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2461    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2462   [(set (match_dup 8)
2463         (match_op_dup 1
2464          [(ashift:SI (match_dup 2) (match_dup 4))
2465           (match_dup 5)]))
2466    (set (match_dup 0)
2467         (match_op_dup 1
2468          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2469           (match_dup 7)]))]
2470   "
2471   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2472 ")
2473 \f
2474
2475 ;; Minimum and maximum insns
2476
2477 (define_expand "smaxsi3"
2478   [(parallel [
2479     (set (match_operand:SI 0 "s_register_operand" "")
2480          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2481                   (match_operand:SI 2 "arm_rhs_operand" "")))
2482     (clobber (reg:CC CC_REGNUM))])]
2483   "TARGET_ARM"
2484   "
2485   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2486     {
2487       /* No need for a clobber of the condition code register here.  */
2488       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2489                               gen_rtx_SMAX (SImode, operands[1],
2490                                             operands[2])));
2491       DONE;
2492     }
2493 ")
2494
2495 (define_insn "*smax_0"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r")
2497         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2498                  (const_int 0)))]
2499   "TARGET_ARM"
2500   "bic%?\\t%0, %1, %1, asr #31"
2501   [(set_attr "predicable" "yes")]
2502 )
2503
2504 (define_insn "*smax_m1"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r")
2506         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2507                  (const_int -1)))]
2508   "TARGET_ARM"
2509   "orr%?\\t%0, %1, %1, asr #31"
2510   [(set_attr "predicable" "yes")]
2511 )
2512
2513 (define_insn "*smax_insn"
2514   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2515         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2516                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2517    (clobber (reg:CC CC_REGNUM))]
2518   "TARGET_ARM"
2519   "@
2520    cmp\\t%1, %2\;movlt\\t%0, %2
2521    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2522   [(set_attr "conds" "clob")
2523    (set_attr "length" "8,12")]
2524 )
2525
2526 (define_expand "sminsi3"
2527   [(parallel [
2528     (set (match_operand:SI 0 "s_register_operand" "")
2529          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2530                   (match_operand:SI 2 "arm_rhs_operand" "")))
2531     (clobber (reg:CC CC_REGNUM))])]
2532   "TARGET_ARM"
2533   "
2534   if (operands[2] == const0_rtx)
2535     {
2536       /* No need for a clobber of the condition code register here.  */
2537       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2538                               gen_rtx_SMIN (SImode, operands[1],
2539                                             operands[2])));
2540       DONE;
2541     }
2542 ")
2543
2544 (define_insn "*smin_0"
2545   [(set (match_operand:SI 0 "s_register_operand" "=r")
2546         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2547                  (const_int 0)))]
2548   "TARGET_ARM"
2549   "and%?\\t%0, %1, %1, asr #31"
2550   [(set_attr "predicable" "yes")]
2551 )
2552
2553 (define_insn "*smin_insn"
2554   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2555         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2556                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2557    (clobber (reg:CC CC_REGNUM))]
2558   "TARGET_ARM"
2559   "@
2560    cmp\\t%1, %2\;movge\\t%0, %2
2561    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2562   [(set_attr "conds" "clob")
2563    (set_attr "length" "8,12")]
2564 )
2565
2566 (define_insn "umaxsi3"
2567   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2568         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2569                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2570    (clobber (reg:CC CC_REGNUM))]
2571   "TARGET_ARM"
2572   "@
2573    cmp\\t%1, %2\;movcc\\t%0, %2
2574    cmp\\t%1, %2\;movcs\\t%0, %1
2575    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2576   [(set_attr "conds" "clob")
2577    (set_attr "length" "8,8,12")]
2578 )
2579
2580 (define_insn "uminsi3"
2581   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2582         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2583                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2584    (clobber (reg:CC CC_REGNUM))]
2585   "TARGET_ARM"
2586   "@
2587    cmp\\t%1, %2\;movcs\\t%0, %2
2588    cmp\\t%1, %2\;movcc\\t%0, %1
2589    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2590   [(set_attr "conds" "clob")
2591    (set_attr "length" "8,8,12")]
2592 )
2593
2594 (define_insn "*store_minmaxsi"
2595   [(set (match_operand:SI 0 "memory_operand" "=m")
2596         (match_operator:SI 3 "minmax_operator"
2597          [(match_operand:SI 1 "s_register_operand" "r")
2598           (match_operand:SI 2 "s_register_operand" "r")]))
2599    (clobber (reg:CC CC_REGNUM))]
2600   "TARGET_ARM"
2601   "*
2602   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2603                                 operands[1], operands[2]);
2604   output_asm_insn (\"cmp\\t%1, %2\", operands);
2605   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2606   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2607   return \"\";
2608   "
2609   [(set_attr "conds" "clob")
2610    (set_attr "length" "12")
2611    (set_attr "type" "store1")]
2612 )
2613
2614 ; Reject the frame pointer in operand[1], since reloading this after
2615 ; it has been eliminated can cause carnage.
2616 (define_insn "*minmax_arithsi"
2617   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2618         (match_operator:SI 4 "shiftable_operator"
2619          [(match_operator:SI 5 "minmax_operator"
2620            [(match_operand:SI 2 "s_register_operand" "r,r")
2621             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2622           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2623    (clobber (reg:CC CC_REGNUM))]
2624   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2625   "*
2626   {
2627     enum rtx_code code = GET_CODE (operands[4]);
2628
2629     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2630                                   operands[2], operands[3]);
2631     output_asm_insn (\"cmp\\t%2, %3\", operands);
2632     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2633     if (which_alternative != 0 || operands[3] != const0_rtx
2634         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2635       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2636     return \"\";
2637   }"
2638   [(set_attr "conds" "clob")
2639    (set_attr "length" "12")]
2640 )
2641
2642 \f
2643 ;; Shift and rotation insns
2644
2645 (define_expand "ashldi3"
2646   [(set (match_operand:DI            0 "s_register_operand" "")
2647         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2648                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2649   "TARGET_ARM"
2650   "
2651   if (GET_CODE (operands[2]) == CONST_INT)
2652     {
2653       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2654         {
2655           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2656           DONE;
2657         }
2658         /* Ideally we shouldn't fail here if we could know that operands[1] 
2659            ends up already living in an iwmmxt register. Otherwise it's
2660            cheaper to have the alternate code being generated than moving
2661            values to iwmmxt regs and back.  */
2662         FAIL;
2663     }
2664   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2665     FAIL;
2666   "
2667 )
2668
2669 (define_insn "arm_ashldi3_1bit"
2670   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2671         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2672                    (const_int 1)))
2673    (clobber (reg:CC CC_REGNUM))]
2674   "TARGET_ARM"
2675   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2676   [(set_attr "conds" "clob")
2677    (set_attr "length" "8")]
2678 )
2679
2680 (define_expand "ashlsi3"
2681   [(set (match_operand:SI            0 "s_register_operand" "")
2682         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2683                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2684   "TARGET_EITHER"
2685   "
2686   if (GET_CODE (operands[2]) == CONST_INT
2687       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2688     {
2689       emit_insn (gen_movsi (operands[0], const0_rtx));
2690       DONE;
2691     }
2692   "
2693 )
2694
2695 (define_insn "*thumb_ashlsi3"
2696   [(set (match_operand:SI            0 "register_operand" "=l,l")
2697         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2698                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2699   "TARGET_THUMB"
2700   "lsl\\t%0, %1, %2"
2701   [(set_attr "length" "2")]
2702 )
2703
2704 (define_expand "ashrdi3"
2705   [(set (match_operand:DI              0 "s_register_operand" "")
2706         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2707                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2708   "TARGET_ARM"
2709   "
2710   if (GET_CODE (operands[2]) == CONST_INT)
2711     {
2712       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2713         {
2714           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2715           DONE;
2716         }
2717         /* Ideally we shouldn't fail here if we could know that operands[1] 
2718            ends up already living in an iwmmxt register. Otherwise it's
2719            cheaper to have the alternate code being generated than moving
2720            values to iwmmxt regs and back.  */
2721         FAIL;
2722     }
2723   else if (!TARGET_REALLY_IWMMXT)
2724     FAIL;
2725   "
2726 )
2727
2728 (define_insn "arm_ashrdi3_1bit"
2729   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2730         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2731                      (const_int 1)))
2732    (clobber (reg:CC CC_REGNUM))]
2733   "TARGET_ARM"
2734   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2735   [(set_attr "conds" "clob")
2736    (set_attr "length" "8")]
2737 )
2738
2739 (define_expand "ashrsi3"
2740   [(set (match_operand:SI              0 "s_register_operand" "")
2741         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2742                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2743   "TARGET_EITHER"
2744   "
2745   if (GET_CODE (operands[2]) == CONST_INT
2746       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2747     operands[2] = GEN_INT (31);
2748   "
2749 )
2750
2751 (define_insn "*thumb_ashrsi3"
2752   [(set (match_operand:SI              0 "register_operand" "=l,l")
2753         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2754                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2755   "TARGET_THUMB"
2756   "asr\\t%0, %1, %2"
2757   [(set_attr "length" "2")]
2758 )
2759
2760 (define_expand "lshrdi3"
2761   [(set (match_operand:DI              0 "s_register_operand" "")
2762         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2763                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2764   "TARGET_ARM"
2765   "
2766   if (GET_CODE (operands[2]) == CONST_INT)
2767     {
2768       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2769         {
2770           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2771           DONE;
2772         }
2773         /* Ideally we shouldn't fail here if we could know that operands[1] 
2774            ends up already living in an iwmmxt register. Otherwise it's
2775            cheaper to have the alternate code being generated than moving
2776            values to iwmmxt regs and back.  */
2777         FAIL;
2778     }
2779   else if (!TARGET_REALLY_IWMMXT)
2780     FAIL;
2781   "
2782 )
2783
2784 (define_insn "arm_lshrdi3_1bit"
2785   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2786         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2787                      (const_int 1)))
2788    (clobber (reg:CC CC_REGNUM))]
2789   "TARGET_ARM"
2790   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2791   [(set_attr "conds" "clob")
2792    (set_attr "length" "8")]
2793 )
2794
2795 (define_expand "lshrsi3"
2796   [(set (match_operand:SI              0 "s_register_operand" "")
2797         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2798                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2799   "TARGET_EITHER"
2800   "
2801   if (GET_CODE (operands[2]) == CONST_INT
2802       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2803     {
2804       emit_insn (gen_movsi (operands[0], const0_rtx));
2805       DONE;
2806     }
2807   "
2808 )
2809
2810 (define_insn "*thumb_lshrsi3"
2811   [(set (match_operand:SI              0 "register_operand" "=l,l")
2812         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2813                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2814   "TARGET_THUMB"
2815   "lsr\\t%0, %1, %2"
2816   [(set_attr "length" "2")]
2817 )
2818
2819 (define_expand "rotlsi3"
2820   [(set (match_operand:SI              0 "s_register_operand" "")
2821         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2822                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2823   "TARGET_ARM"
2824   "
2825   if (GET_CODE (operands[2]) == CONST_INT)
2826     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2827   else
2828     {
2829       rtx reg = gen_reg_rtx (SImode);
2830       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2831       operands[2] = reg;
2832     }
2833   "
2834 )
2835
2836 (define_expand "rotrsi3"
2837   [(set (match_operand:SI              0 "s_register_operand" "")
2838         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2839                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2840   "TARGET_EITHER"
2841   "
2842   if (TARGET_ARM)
2843     {
2844       if (GET_CODE (operands[2]) == CONST_INT
2845           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2846         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2847     }
2848   else /* TARGET_THUMB */
2849     {
2850       if (GET_CODE (operands [2]) == CONST_INT)
2851         operands [2] = force_reg (SImode, operands[2]);
2852     }
2853   "
2854 )
2855
2856 (define_insn "*thumb_rotrsi3"
2857   [(set (match_operand:SI              0 "register_operand" "=l")
2858         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2859                      (match_operand:SI 2 "register_operand" "l")))]
2860   "TARGET_THUMB"
2861   "ror\\t%0, %0, %2"
2862   [(set_attr "length" "2")]
2863 )
2864
2865 (define_insn "*arm_shiftsi3"
2866   [(set (match_operand:SI   0 "s_register_operand" "=r")
2867         (match_operator:SI  3 "shift_operator"
2868          [(match_operand:SI 1 "s_register_operand"  "r")
2869           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2870   "TARGET_ARM"
2871   "mov%?\\t%0, %1%S3"
2872   [(set_attr "predicable" "yes")
2873    (set_attr "shift" "1")
2874    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2875                       (const_string "alu_shift")
2876                       (const_string "alu_shift_reg")))]
2877 )
2878
2879 (define_insn "*shiftsi3_compare0"
2880   [(set (reg:CC_NOOV CC_REGNUM)
2881         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2882                           [(match_operand:SI 1 "s_register_operand" "r")
2883                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2884                          (const_int 0)))
2885    (set (match_operand:SI 0 "s_register_operand" "=r")
2886         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2887   "TARGET_ARM"
2888   "mov%?s\\t%0, %1%S3"
2889   [(set_attr "conds" "set")
2890    (set_attr "shift" "1")
2891    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2892                       (const_string "alu_shift")
2893                       (const_string "alu_shift_reg")))]
2894 )
2895
2896 (define_insn "*shiftsi3_compare0_scratch"
2897   [(set (reg:CC_NOOV CC_REGNUM)
2898         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2899                           [(match_operand:SI 1 "s_register_operand" "r")
2900                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2901                          (const_int 0)))
2902    (clobber (match_scratch:SI 0 "=r"))]
2903   "TARGET_ARM"
2904   "mov%?s\\t%0, %1%S3"
2905   [(set_attr "conds" "set")
2906    (set_attr "shift" "1")]
2907 )
2908
2909 (define_insn "*notsi_shiftsi"
2910   [(set (match_operand:SI 0 "s_register_operand" "=r")
2911         (not:SI (match_operator:SI 3 "shift_operator"
2912                  [(match_operand:SI 1 "s_register_operand" "r")
2913                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2914   "TARGET_ARM"
2915   "mvn%?\\t%0, %1%S3"
2916   [(set_attr "predicable" "yes")
2917    (set_attr "shift" "1")
2918    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2919                       (const_string "alu_shift")
2920                       (const_string "alu_shift_reg")))]
2921 )
2922
2923 (define_insn "*notsi_shiftsi_compare0"
2924   [(set (reg:CC_NOOV CC_REGNUM)
2925         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2926                           [(match_operand:SI 1 "s_register_operand" "r")
2927                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2928                          (const_int 0)))
2929    (set (match_operand:SI 0 "s_register_operand" "=r")
2930         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2931   "TARGET_ARM"
2932   "mvn%?s\\t%0, %1%S3"
2933   [(set_attr "conds" "set")
2934    (set_attr "shift" "1")
2935    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2936                       (const_string "alu_shift")
2937                       (const_string "alu_shift_reg")))]
2938 )
2939
2940 (define_insn "*not_shiftsi_compare0_scratch"
2941   [(set (reg:CC_NOOV CC_REGNUM)
2942         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2943                           [(match_operand:SI 1 "s_register_operand" "r")
2944                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2945                          (const_int 0)))
2946    (clobber (match_scratch:SI 0 "=r"))]
2947   "TARGET_ARM"
2948   "mvn%?s\\t%0, %1%S3"
2949   [(set_attr "conds" "set")
2950    (set_attr "shift" "1")
2951    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2952                       (const_string "alu_shift")
2953                       (const_string "alu_shift_reg")))]
2954 )
2955
2956 ;; We don't really have extzv, but defining this using shifts helps
2957 ;; to reduce register pressure later on.
2958
2959 (define_expand "extzv"
2960   [(set (match_dup 4)
2961         (ashift:SI (match_operand:SI   1 "register_operand" "")
2962                    (match_operand:SI   2 "const_int_operand" "")))
2963    (set (match_operand:SI              0 "register_operand" "")
2964         (lshiftrt:SI (match_dup 4)
2965                      (match_operand:SI 3 "const_int_operand" "")))]
2966   "TARGET_THUMB"
2967   "
2968   {
2969     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2970     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2971     
2972     operands[3] = GEN_INT (rshift);
2973     
2974     if (lshift == 0)
2975       {
2976         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2977         DONE;
2978       }
2979       
2980     operands[2] = GEN_INT (lshift);
2981     operands[4] = gen_reg_rtx (SImode);
2982   }"
2983 )
2984
2985 \f
2986 ;; Unary arithmetic insns
2987
2988 (define_expand "negdi2"
2989  [(parallel
2990    [(set (match_operand:DI          0 "s_register_operand" "")
2991           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2992     (clobber (reg:CC CC_REGNUM))])]
2993   "TARGET_EITHER"
2994   "
2995   if (TARGET_THUMB)
2996     {
2997       if (GET_CODE (operands[1]) != REG)
2998         operands[1] = force_reg (SImode, operands[1]);
2999      }
3000   "
3001 )
3002
3003 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3004 ;; The second alternative is to allow the common case of a *full* overlap.
3005 (define_insn "*arm_negdi2"
3006   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3007         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3008    (clobber (reg:CC CC_REGNUM))]
3009   "TARGET_ARM"
3010   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3011   [(set_attr "conds" "clob")
3012    (set_attr "length" "8")]
3013 )
3014
3015 (define_insn "*thumb_negdi2"
3016   [(set (match_operand:DI         0 "register_operand" "=&l")
3017         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3018    (clobber (reg:CC CC_REGNUM))]
3019   "TARGET_THUMB"
3020   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3021   [(set_attr "length" "6")]
3022 )
3023
3024 (define_expand "negsi2"
3025   [(set (match_operand:SI         0 "s_register_operand" "")
3026         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3027   "TARGET_EITHER"
3028   ""
3029 )
3030
3031 (define_insn "*arm_negsi2"
3032   [(set (match_operand:SI         0 "s_register_operand" "=r")
3033         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3034   "TARGET_ARM"
3035   "rsb%?\\t%0, %1, #0"
3036   [(set_attr "predicable" "yes")]
3037 )
3038
3039 (define_insn "*thumb_negsi2"
3040   [(set (match_operand:SI         0 "register_operand" "=l")
3041         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3042   "TARGET_THUMB"
3043   "neg\\t%0, %1"
3044   [(set_attr "length" "2")]
3045 )
3046
3047 (define_expand "negsf2"
3048   [(set (match_operand:SF         0 "s_register_operand" "")
3049         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3050   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051   ""
3052 )
3053
3054 (define_expand "negdf2"
3055   [(set (match_operand:DF         0 "s_register_operand" "")
3056         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3057   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3058   "")
3059
3060 ;; abssi2 doesn't really clobber the condition codes if a different register
3061 ;; is being set.  To keep things simple, assume during rtl manipulations that
3062 ;; it does, but tell the final scan operator the truth.  Similarly for
3063 ;; (neg (abs...))
3064
3065 (define_expand "abssi2"
3066   [(parallel
3067     [(set (match_operand:SI         0 "s_register_operand" "")
3068           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3069      (clobber (reg:CC CC_REGNUM))])]
3070   "TARGET_ARM"
3071   "")
3072
3073 (define_insn "*arm_abssi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3075         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3076    (clobber (reg:CC CC_REGNUM))]
3077   "TARGET_ARM"
3078   "@
3079    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3080    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3081   [(set_attr "conds" "clob,*")
3082    (set_attr "shift" "1")
3083    ;; predicable can't be set based on the variant, so left as no
3084    (set_attr "length" "8")]
3085 )
3086
3087 (define_insn "*neg_abssi2"
3088   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3089         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3090    (clobber (reg:CC CC_REGNUM))]
3091   "TARGET_ARM"
3092   "@
3093    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3094    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3095   [(set_attr "conds" "clob,*")
3096    (set_attr "shift" "1")
3097    ;; predicable can't be set based on the variant, so left as no
3098    (set_attr "length" "8")]
3099 )
3100
3101 (define_expand "abssf2"
3102   [(set (match_operand:SF         0 "s_register_operand" "")
3103         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3104   "TARGET_ARM && TARGET_HARD_FLOAT"
3105   "")
3106
3107 (define_expand "absdf2"
3108   [(set (match_operand:DF         0 "s_register_operand" "")
3109         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3110   "TARGET_ARM && TARGET_HARD_FLOAT"
3111   "")
3112
3113 (define_expand "sqrtsf2"
3114   [(set (match_operand:SF 0 "s_register_operand" "")
3115         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3116   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3117   "")
3118
3119 (define_expand "sqrtdf2"
3120   [(set (match_operand:DF 0 "s_register_operand" "")
3121         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3122   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3123   "")
3124
3125 (define_insn_and_split "one_cmpldi2"
3126   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3127         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3128   "TARGET_ARM"
3129   "#"
3130   "TARGET_ARM && reload_completed"
3131   [(set (match_dup 0) (not:SI (match_dup 1)))
3132    (set (match_dup 2) (not:SI (match_dup 3)))]
3133   "
3134   {
3135     operands[2] = gen_highpart (SImode, operands[0]);
3136     operands[0] = gen_lowpart (SImode, operands[0]);
3137     operands[3] = gen_highpart (SImode, operands[1]);
3138     operands[1] = gen_lowpart (SImode, operands[1]);
3139   }"
3140   [(set_attr "length" "8")
3141    (set_attr "predicable" "yes")]
3142 )
3143
3144 (define_expand "one_cmplsi2"
3145   [(set (match_operand:SI         0 "s_register_operand" "")
3146         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3147   "TARGET_EITHER"
3148   ""
3149 )
3150
3151 (define_insn "*arm_one_cmplsi2"
3152   [(set (match_operand:SI         0 "s_register_operand" "=r")
3153         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3154   "TARGET_ARM"
3155   "mvn%?\\t%0, %1"
3156   [(set_attr "predicable" "yes")]
3157 )
3158
3159 (define_insn "*thumb_one_cmplsi2"
3160   [(set (match_operand:SI         0 "register_operand" "=l")
3161         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3162   "TARGET_THUMB"
3163   "mvn\\t%0, %1"
3164   [(set_attr "length" "2")]
3165 )
3166
3167 (define_insn "*notsi_compare0"
3168   [(set (reg:CC_NOOV CC_REGNUM)
3169         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3170                          (const_int 0)))
3171    (set (match_operand:SI 0 "s_register_operand" "=r")
3172         (not:SI (match_dup 1)))]
3173   "TARGET_ARM"
3174   "mvn%?s\\t%0, %1"
3175   [(set_attr "conds" "set")]
3176 )
3177
3178 (define_insn "*notsi_compare0_scratch"
3179   [(set (reg:CC_NOOV CC_REGNUM)
3180         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3181                          (const_int 0)))
3182    (clobber (match_scratch:SI 0 "=r"))]
3183   "TARGET_ARM"
3184   "mvn%?s\\t%0, %1"
3185   [(set_attr "conds" "set")]
3186 )
3187 \f
3188 ;; Fixed <--> Floating conversion insns
3189
3190 (define_expand "floatsisf2"
3191   [(set (match_operand:SF           0 "s_register_operand" "")
3192         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3193   "TARGET_ARM && TARGET_HARD_FLOAT"
3194   "
3195   if (TARGET_MAVERICK)
3196     {
3197       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3198       DONE;
3199     }
3200 ")
3201
3202 (define_expand "floatsidf2"
3203   [(set (match_operand:DF           0 "s_register_operand" "")
3204         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3205   "TARGET_ARM && TARGET_HARD_FLOAT"
3206   "
3207   if (TARGET_MAVERICK)
3208     {
3209       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3210       DONE;
3211     }
3212 ")
3213
3214 (define_expand "fix_truncsfsi2"
3215   [(set (match_operand:SI         0 "s_register_operand" "")
3216         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3217   "TARGET_ARM && TARGET_HARD_FLOAT"
3218   "
3219   if (TARGET_MAVERICK)
3220     {
3221       if (!cirrus_fp_register (operands[0], SImode))
3222         operands[0] = force_reg (SImode, operands[0]);
3223       if (!cirrus_fp_register (operands[1], SFmode))
3224         operands[1] = force_reg (SFmode, operands[0]);
3225       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3226       DONE;
3227     }
3228 ")
3229
3230 (define_expand "fix_truncdfsi2"
3231   [(set (match_operand:SI         0 "s_register_operand" "")
3232         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3233   "TARGET_ARM && TARGET_HARD_FLOAT"
3234   "
3235   if (TARGET_MAVERICK)
3236     {
3237       if (!cirrus_fp_register (operands[1], DFmode))
3238         operands[1] = force_reg (DFmode, operands[0]);
3239       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3240       DONE;
3241     }
3242 ")
3243
3244 ;; Truncation insns
3245
3246 (define_expand "truncdfsf2"
3247   [(set (match_operand:SF  0 "s_register_operand" "")
3248         (float_truncate:SF
3249          (match_operand:DF 1 "s_register_operand" "")))]
3250   "TARGET_ARM && TARGET_HARD_FLOAT"
3251   ""
3252 )
3253 \f
3254 ;; Zero and sign extension instructions.
3255
3256 (define_insn "zero_extendsidi2"
3257   [(set (match_operand:DI 0 "s_register_operand" "=r")
3258         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3259   "TARGET_ARM"
3260   "*
3261     if (REGNO (operands[1])
3262         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3263       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3264     return \"mov%?\\t%R0, #0\";
3265   "
3266   [(set_attr "length" "8")
3267    (set_attr "predicable" "yes")]
3268 )
3269
3270 (define_insn "zero_extendqidi2"
3271   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3272         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3273   "TARGET_ARM"
3274   "@
3275    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3276    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3277   [(set_attr "length" "8")
3278    (set_attr "predicable" "yes")
3279    (set_attr "type" "*,load_byte")
3280    (set_attr "pool_range" "*,4092")
3281    (set_attr "neg_pool_range" "*,4084")]
3282 )
3283
3284 (define_insn "extendsidi2"
3285   [(set (match_operand:DI 0 "s_register_operand" "=r")
3286         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3287   "TARGET_ARM"
3288   "*
3289     if (REGNO (operands[1])
3290         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3291       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3292     return \"mov%?\\t%R0, %Q0, asr #31\";
3293   "
3294   [(set_attr "length" "8")
3295    (set_attr "shift" "1")
3296    (set_attr "predicable" "yes")]
3297 )
3298
3299 (define_expand "zero_extendhisi2"
3300   [(set (match_dup 2)
3301         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3302                    (const_int 16)))
3303    (set (match_operand:SI 0 "s_register_operand" "")
3304         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3305   "TARGET_EITHER"
3306   "
3307   {
3308     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3309       {
3310         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3311                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3312         DONE;
3313       }
3314
3315     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3316       {
3317         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3318         DONE;
3319       }
3320
3321     if (!s_register_operand (operands[1], HImode))
3322       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3323
3324     if (arm_arch6)
3325       {
3326         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3327                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3328         DONE;
3329       }
3330
3331     operands[1] = gen_lowpart (SImode, operands[1]);
3332     operands[2] = gen_reg_rtx (SImode);
3333   }"
3334 )
3335
3336 (define_insn "*thumb_zero_extendhisi2"
3337   [(set (match_operand:SI 0 "register_operand" "=l")
3338         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3339   "TARGET_THUMB && !arm_arch6"
3340   "*
3341   rtx mem = XEXP (operands[1], 0);
3342
3343   if (GET_CODE (mem) == CONST)
3344     mem = XEXP (mem, 0);
3345     
3346   if (GET_CODE (mem) == LABEL_REF)
3347     return \"ldr\\t%0, %1\";
3348     
3349   if (GET_CODE (mem) == PLUS)
3350     {
3351       rtx a = XEXP (mem, 0);
3352       rtx b = XEXP (mem, 1);
3353
3354       /* This can happen due to bugs in reload.  */
3355       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3356         {
3357           rtx ops[2];
3358           ops[0] = operands[0];
3359           ops[1] = a;
3360       
3361           output_asm_insn (\"mov        %0, %1\", ops);
3362
3363           XEXP (mem, 0) = operands[0];
3364        }
3365
3366       else if (   GET_CODE (a) == LABEL_REF
3367                && GET_CODE (b) == CONST_INT)
3368         return \"ldr\\t%0, %1\";
3369     }
3370     
3371   return \"ldrh\\t%0, %1\";
3372   "
3373   [(set_attr "length" "4")
3374    (set_attr "type" "load_byte")
3375    (set_attr "pool_range" "60")]
3376 )
3377
3378 (define_insn "*thumb_zero_extendhisi2_v6"
3379   [(set (match_operand:SI 0 "register_operand" "=l,l")
3380         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3381   "TARGET_THUMB && arm_arch6"
3382   "*
3383   rtx mem;
3384
3385   if (which_alternative == 0)
3386     return \"uxth\\t%0, %1\";
3387
3388   mem = XEXP (operands[1], 0);
3389
3390   if (GET_CODE (mem) == CONST)
3391     mem = XEXP (mem, 0);
3392     
3393   if (GET_CODE (mem) == LABEL_REF)
3394     return \"ldr\\t%0, %1\";
3395     
3396   if (GET_CODE (mem) == PLUS)
3397     {
3398       rtx a = XEXP (mem, 0);
3399       rtx b = XEXP (mem, 1);
3400
3401       /* This can happen due to bugs in reload.  */
3402       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3403         {
3404           rtx ops[2];
3405           ops[0] = operands[0];
3406           ops[1] = a;
3407       
3408           output_asm_insn (\"mov        %0, %1\", ops);
3409
3410           XEXP (mem, 0) = operands[0];
3411        }
3412
3413       else if (   GET_CODE (a) == LABEL_REF
3414                && GET_CODE (b) == CONST_INT)
3415         return \"ldr\\t%0, %1\";
3416     }
3417     
3418   return \"ldrh\\t%0, %1\";
3419   "
3420   [(set_attr "length" "2,4")
3421    (set_attr "type" "alu_shift,load_byte")
3422    (set_attr "pool_range" "*,60")]
3423 )
3424
3425 (define_insn "*arm_zero_extendhisi2"
3426   [(set (match_operand:SI 0 "s_register_operand" "=r")
3427         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3428   "TARGET_ARM && arm_arch4 && !arm_arch6"
3429   "ldr%?h\\t%0, %1"
3430   [(set_attr "type" "load_byte")
3431    (set_attr "predicable" "yes")
3432    (set_attr "pool_range" "256")
3433    (set_attr "neg_pool_range" "244")]
3434 )
3435
3436 (define_insn "*arm_zero_extendhisi2_v6"
3437   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3438         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3439   "TARGET_ARM && arm_arch6"
3440   "@
3441    uxth%?\\t%0, %1
3442    ldr%?h\\t%0, %1"
3443   [(set_attr "type" "alu_shift,load_byte")
3444    (set_attr "predicable" "yes")
3445    (set_attr "pool_range" "*,256")
3446    (set_attr "neg_pool_range" "*,244")]
3447 )
3448
3449 (define_insn "*arm_zero_extendhisi2addsi"
3450   [(set (match_operand:SI 0 "s_register_operand" "=r")
3451         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3452                  (match_operand:SI 2 "s_register_operand" "r")))]
3453   "TARGET_ARM && arm_arch6"
3454   "uxtah%?\\t%0, %2, %1"
3455   [(set_attr "type" "alu_shift")
3456    (set_attr "predicable" "yes")]
3457 )
3458
3459 (define_expand "zero_extendqisi2"
3460   [(set (match_operand:SI 0 "s_register_operand" "")
3461         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3462   "TARGET_EITHER"
3463   "
3464   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3465     {
3466       if (TARGET_ARM)
3467         {
3468           emit_insn (gen_andsi3 (operands[0],
3469                                  gen_lowpart (SImode, operands[1]),
3470                                  GEN_INT (255)));
3471         }
3472       else /* TARGET_THUMB */
3473         {
3474           rtx temp = gen_reg_rtx (SImode);
3475           rtx ops[3];
3476           
3477           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3478           operands[1] = gen_lowpart (SImode, operands[1]);
3479
3480           ops[0] = temp;
3481           ops[1] = operands[1];
3482           ops[2] = GEN_INT (24);
3483
3484           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3485                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3486           
3487           ops[0] = operands[0];
3488           ops[1] = temp;
3489           ops[2] = GEN_INT (24);
3490
3491           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3492                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3493         }
3494       DONE;
3495     }
3496   "
3497 )
3498
3499 (define_insn "*thumb_zero_extendqisi2"
3500   [(set (match_operand:SI 0 "register_operand" "=l")
3501         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3502   "TARGET_THUMB && !arm_arch6"
3503   "ldrb\\t%0, %1"
3504   [(set_attr "length" "2")
3505    (set_attr "type" "load_byte")
3506    (set_attr "pool_range" "32")]
3507 )
3508
3509 (define_insn "*thumb_zero_extendqisi2_v6"
3510   [(set (match_operand:SI 0 "register_operand" "=l,l")
3511         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3512   "TARGET_THUMB && arm_arch6"
3513   "@
3514    uxtb\\t%0, %1
3515    ldrb\\t%0, %1"
3516   [(set_attr "length" "2,2")
3517    (set_attr "type" "alu_shift,load_byte")
3518    (set_attr "pool_range" "*,32")]
3519 )
3520
3521 (define_insn "*arm_zero_extendqisi2"
3522   [(set (match_operand:SI 0 "s_register_operand" "=r")
3523         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3524   "TARGET_ARM && !arm_arch6"
3525   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3526   [(set_attr "type" "load_byte")
3527    (set_attr "predicable" "yes")
3528    (set_attr "pool_range" "4096")
3529    (set_attr "neg_pool_range" "4084")]
3530 )
3531
3532 (define_insn "*arm_zero_extendqisi2_v6"
3533   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3534         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3535   "TARGET_ARM && arm_arch6"
3536   "@
3537    uxtb%?\\t%0, %1
3538    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3539   [(set_attr "type" "alu_shift,load_byte")
3540    (set_attr "predicable" "yes")
3541    (set_attr "pool_range" "*,4096")
3542    (set_attr "neg_pool_range" "*,4084")]
3543 )
3544
3545 (define_insn "*arm_zero_extendqisi2addsi"
3546   [(set (match_operand:SI 0 "s_register_operand" "=r")
3547         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3548                  (match_operand:SI 2 "s_register_operand" "r")))]
3549   "TARGET_ARM && arm_arch6"
3550   "uxtab%?\\t%0, %2, %1"
3551   [(set_attr "predicable" "yes")
3552    (set_attr "type" "alu_shift")]
3553 )
3554
3555 (define_split
3556   [(set (match_operand:SI 0 "s_register_operand" "")
3557         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3558    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3559   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3560   [(set (match_dup 2) (match_dup 1))
3561    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3562   ""
3563 )
3564
3565 (define_split
3566   [(set (match_operand:SI 0 "s_register_operand" "")
3567         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3568    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3569   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3570   [(set (match_dup 2) (match_dup 1))
3571    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3572   ""
3573 )
3574
3575 (define_insn "*compareqi_eq0"
3576   [(set (reg:CC_Z CC_REGNUM)
3577         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3578                          (const_int 0)))]
3579   "TARGET_ARM"
3580   "tst\\t%0, #255"
3581   [(set_attr "conds" "set")]
3582 )
3583
3584 (define_expand "extendhisi2"
3585   [(set (match_dup 2)
3586         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3587                    (const_int 16)))
3588    (set (match_operand:SI 0 "s_register_operand" "")
3589         (ashiftrt:SI (match_dup 2)
3590                      (const_int 16)))]
3591   "TARGET_EITHER"
3592   "
3593   {
3594     if (GET_CODE (operands[1]) == MEM)
3595       {
3596         if (TARGET_THUMB)
3597           {
3598             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3599             DONE;
3600           }
3601         else if (arm_arch4)
3602           {
3603             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3604                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3605             DONE;
3606           }
3607       }
3608
3609     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3610       {
3611         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3612         DONE;
3613       }
3614
3615     if (!s_register_operand (operands[1], HImode))
3616       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3617
3618     if (arm_arch6)
3619       {
3620         if (TARGET_THUMB)
3621           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3622         else
3623           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3624                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3625
3626         DONE;
3627       }
3628
3629     operands[1] = gen_lowpart (SImode, operands[1]);
3630     operands[2] = gen_reg_rtx (SImode);
3631   }"
3632 )
3633
3634 (define_insn "thumb_extendhisi2"
3635   [(set (match_operand:SI 0 "register_operand" "=l")
3636         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3637    (clobber (match_scratch:SI 2 "=&l"))]
3638   "TARGET_THUMB && !arm_arch6"
3639   "*
3640   {
3641     rtx ops[4];
3642     rtx mem = XEXP (operands[1], 0);
3643
3644     /* This code used to try to use 'V', and fix the address only if it was
3645        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3646        range of QImode offsets, and offsettable_address_p does a QImode
3647        address check.  */
3648        
3649     if (GET_CODE (mem) == CONST)
3650       mem = XEXP (mem, 0);
3651     
3652     if (GET_CODE (mem) == LABEL_REF)
3653       return \"ldr\\t%0, %1\";
3654     
3655     if (GET_CODE (mem) == PLUS)
3656       {
3657         rtx a = XEXP (mem, 0);
3658         rtx b = XEXP (mem, 1);
3659
3660         if (GET_CODE (a) == LABEL_REF
3661             && GET_CODE (b) == CONST_INT)
3662           return \"ldr\\t%0, %1\";
3663
3664         if (GET_CODE (b) == REG)
3665           return \"ldrsh\\t%0, %1\";
3666           
3667         ops[1] = a;
3668         ops[2] = b;
3669       }
3670     else
3671       {
3672         ops[1] = mem;
3673         ops[2] = const0_rtx;
3674       }
3675
3676     gcc_assert (GET_CODE (ops[1]) == REG);
3677
3678     ops[0] = operands[0];
3679     ops[3] = operands[2];
3680     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3681     return \"\";
3682   }"
3683   [(set_attr "length" "4")
3684    (set_attr "type" "load_byte")
3685    (set_attr "pool_range" "1020")]
3686 )
3687
3688 ;; We used to have an early-clobber on the scratch register here.
3689 ;; However, there's a bug somewhere in reload which means that this
3690 ;; can be partially ignored during spill allocation if the memory
3691 ;; address also needs reloading; this causes us to die later on when
3692 ;; we try to verify the operands.  Fortunately, we don't really need
3693 ;; the early-clobber: we can always use operand 0 if operand 2
3694 ;; overlaps the address.
3695 (define_insn "*thumb_extendhisi2_insn_v6"
3696   [(set (match_operand:SI 0 "register_operand" "=l,l")
3697         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3698    (clobber (match_scratch:SI 2 "=X,l"))]
3699   "TARGET_THUMB && arm_arch6"
3700   "*
3701   {
3702     rtx ops[4];
3703     rtx mem;
3704
3705     if (which_alternative == 0)
3706       return \"sxth\\t%0, %1\";
3707
3708     mem = XEXP (operands[1], 0);
3709
3710     /* This code used to try to use 'V', and fix the address only if it was
3711        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3712        range of QImode offsets, and offsettable_address_p does a QImode
3713        address check.  */
3714        
3715     if (GET_CODE (mem) == CONST)
3716       mem = XEXP (mem, 0);
3717     
3718     if (GET_CODE (mem) == LABEL_REF)
3719       return \"ldr\\t%0, %1\";
3720     
3721     if (GET_CODE (mem) == PLUS)
3722       {
3723         rtx a = XEXP (mem, 0);
3724         rtx b = XEXP (mem, 1);
3725
3726         if (GET_CODE (a) == LABEL_REF
3727             && GET_CODE (b) == CONST_INT)
3728           return \"ldr\\t%0, %1\";
3729
3730         if (GET_CODE (b) == REG)
3731           return \"ldrsh\\t%0, %1\";
3732           
3733         ops[1] = a;
3734         ops[2] = b;
3735       }
3736     else
3737       {
3738         ops[1] = mem;
3739         ops[2] = const0_rtx;
3740       }
3741       
3742     gcc_assert (GET_CODE (ops[1]) == REG);
3743
3744     ops[0] = operands[0];
3745     if (reg_mentioned_p (operands[2], ops[1]))
3746       ops[3] = ops[0];
3747     else
3748       ops[3] = operands[2];
3749     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3750     return \"\";
3751   }"
3752   [(set_attr "length" "2,4")
3753    (set_attr "type" "alu_shift,load_byte")
3754    (set_attr "pool_range" "*,1020")]
3755 )
3756
3757 (define_expand "extendhisi2_mem"
3758   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3759    (set (match_dup 3)
3760         (zero_extend:SI (match_dup 7)))
3761    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3762    (set (match_operand:SI 0 "" "")
3763         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3764   "TARGET_ARM"
3765   "
3766   {
3767     rtx mem1, mem2;
3768     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3769
3770     mem1 = change_address (operands[1], QImode, addr);
3771     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3772     operands[0] = gen_lowpart (SImode, operands[0]);
3773     operands[1] = mem1;
3774     operands[2] = gen_reg_rtx (SImode);
3775     operands[3] = gen_reg_rtx (SImode);
3776     operands[6] = gen_reg_rtx (SImode);
3777     operands[7] = mem2;
3778
3779     if (BYTES_BIG_ENDIAN)
3780       {
3781         operands[4] = operands[2];
3782         operands[5] = operands[3];
3783       }
3784     else
3785       {
3786         operands[4] = operands[3];
3787         operands[5] = operands[2];
3788       }
3789   }"
3790 )
3791
3792 (define_insn "*arm_extendhisi2"
3793   [(set (match_operand:SI 0 "s_register_operand" "=r")
3794         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3795   "TARGET_ARM && arm_arch4 && !arm_arch6"
3796   "ldr%?sh\\t%0, %1"
3797   [(set_attr "type" "load_byte")
3798    (set_attr "predicable" "yes")
3799    (set_attr "pool_range" "256")
3800    (set_attr "neg_pool_range" "244")]
3801 )
3802
3803 (define_insn "*arm_extendhisi2_v6"
3804   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3805         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3806   "TARGET_ARM && arm_arch6"
3807   "@
3808    sxth%?\\t%0, %1
3809    ldr%?sh\\t%0, %1"
3810   [(set_attr "type" "alu_shift,load_byte")
3811    (set_attr "predicable" "yes")
3812    (set_attr "pool_range" "*,256")
3813    (set_attr "neg_pool_range" "*,244")]
3814 )
3815
3816 (define_insn "*arm_extendhisi2addsi"
3817   [(set (match_operand:SI 0 "s_register_operand" "=r")
3818         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3819                  (match_operand:SI 2 "s_register_operand" "r")))]
3820   "TARGET_ARM && arm_arch6"
3821   "sxtah%?\\t%0, %2, %1"
3822 )
3823
3824 (define_expand "extendqihi2"
3825   [(set (match_dup 2)
3826         (ashift:SI (match_operand:QI 1 "general_operand" "")
3827                    (const_int 24)))
3828    (set (match_operand:HI 0 "s_register_operand" "")
3829         (ashiftrt:SI (match_dup 2)
3830                      (const_int 24)))]
3831   "TARGET_ARM"
3832   "
3833   {
3834     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3835       {
3836         emit_insn (gen_rtx_SET (VOIDmode,
3837                                 operands[0],
3838                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3839         DONE;
3840       }
3841     if (!s_register_operand (operands[1], QImode))
3842       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3843     operands[0] = gen_lowpart (SImode, operands[0]);
3844     operands[1] = gen_lowpart (SImode, operands[1]);
3845     operands[2] = gen_reg_rtx (SImode);
3846   }"
3847 )
3848
3849 (define_insn "*extendqihi_insn"
3850   [(set (match_operand:HI 0 "s_register_operand" "=r")
3851         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3852   "TARGET_ARM && arm_arch4"
3853   "ldr%?sb\\t%0, %1"
3854   [(set_attr "type" "load_byte")
3855    (set_attr "predicable" "yes")
3856    (set_attr "pool_range" "256")
3857    (set_attr "neg_pool_range" "244")]
3858 )
3859
3860 (define_expand "extendqisi2"
3861   [(set (match_dup 2)
3862         (ashift:SI (match_operand:QI 1 "general_operand" "")
3863                    (const_int 24)))
3864    (set (match_operand:SI 0 "s_register_operand" "")
3865         (ashiftrt:SI (match_dup 2)
3866                      (const_int 24)))]
3867   "TARGET_EITHER"
3868   "
3869   {
3870     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3871       {
3872         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3873                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3874         DONE;
3875       }
3876
3877     if (!s_register_operand (operands[1], QImode))
3878       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3879
3880     if (arm_arch6)
3881       {
3882         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3883                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3884         DONE;
3885       }
3886
3887     operands[1] = gen_lowpart (SImode, operands[1]);
3888     operands[2] = gen_reg_rtx (SImode);
3889   }"
3890 )
3891
3892 (define_insn "*arm_extendqisi"
3893   [(set (match_operand:SI 0 "s_register_operand" "=r")
3894         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3895   "TARGET_ARM && arm_arch4 && !arm_arch6"
3896   "ldr%?sb\\t%0, %1"
3897   [(set_attr "type" "load_byte")
3898    (set_attr "predicable" "yes")
3899    (set_attr "pool_range" "256")
3900    (set_attr "neg_pool_range" "244")]
3901 )
3902
3903 (define_insn "*arm_extendqisi_v6"
3904   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3905         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3906   "TARGET_ARM && arm_arch6"
3907   "@
3908    sxtb%?\\t%0, %1
3909    ldr%?sb\\t%0, %1"
3910   [(set_attr "type" "alu_shift,load_byte")
3911    (set_attr "predicable" "yes")
3912    (set_attr "pool_range" "*,256")
3913    (set_attr "neg_pool_range" "*,244")]
3914 )
3915
3916 (define_insn "*arm_extendqisi2addsi"
3917   [(set (match_operand:SI 0 "s_register_operand" "=r")
3918         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3919                  (match_operand:SI 2 "s_register_operand" "r")))]
3920   "TARGET_ARM && arm_arch6"
3921   "sxtab%?\\t%0, %2, %1"
3922   [(set_attr "type" "alu_shift")
3923    (set_attr "predicable" "yes")]
3924 )
3925
3926 (define_insn "*thumb_extendqisi2"
3927   [(set (match_operand:SI 0 "register_operand" "=l,l")
3928         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3929   "TARGET_THUMB && !arm_arch6"
3930   "*
3931   {
3932     rtx ops[3];
3933     rtx mem = XEXP (operands[1], 0);
3934     
3935     if (GET_CODE (mem) == CONST)
3936       mem = XEXP (mem, 0);
3937     
3938     if (GET_CODE (mem) == LABEL_REF)
3939       return \"ldr\\t%0, %1\";
3940
3941     if (GET_CODE (mem) == PLUS
3942         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3943       return \"ldr\\t%0, %1\";
3944       
3945     if (which_alternative == 0)
3946       return \"ldrsb\\t%0, %1\";
3947       
3948     ops[0] = operands[0];
3949     
3950     if (GET_CODE (mem) == PLUS)
3951       {
3952         rtx a = XEXP (mem, 0);
3953         rtx b = XEXP (mem, 1);
3954         
3955         ops[1] = a;
3956         ops[2] = b;
3957
3958         if (GET_CODE (a) == REG)
3959           {
3960             if (GET_CODE (b) == REG)
3961               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3962             else if (REGNO (a) == REGNO (ops[0]))
3963               {
3964                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3965                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3966                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3967               }
3968             else
3969               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3970           }
3971         else
3972           {
3973             gcc_assert (GET_CODE (b) == REG);
3974             if (REGNO (b) == REGNO (ops[0]))
3975               {
3976                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3977                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3978                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3979               }
3980             else
3981               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3982           }
3983       }
3984     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3985       {
3986         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3987         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3988         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3989       }
3990     else
3991       {
3992         ops[1] = mem;
3993         ops[2] = const0_rtx;
3994         
3995         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3996       }
3997     return \"\";
3998   }"
3999   [(set_attr "length" "2,6")
4000    (set_attr "type" "load_byte,load_byte")
4001    (set_attr "pool_range" "32,32")]
4002 )
4003
4004 (define_insn "*thumb_extendqisi2_v6"
4005   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4006         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4007   "TARGET_THUMB && arm_arch6"
4008   "*
4009   {
4010     rtx ops[3];
4011     rtx mem;
4012
4013     if (which_alternative == 0)
4014       return \"sxtb\\t%0, %1\";
4015
4016     mem = XEXP (operands[1], 0);
4017     
4018     if (GET_CODE (mem) == CONST)
4019       mem = XEXP (mem, 0);
4020     
4021     if (GET_CODE (mem) == LABEL_REF)
4022       return \"ldr\\t%0, %1\";
4023
4024     if (GET_CODE (mem) == PLUS
4025         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4026       return \"ldr\\t%0, %1\";
4027       
4028     if (which_alternative == 0)
4029       return \"ldrsb\\t%0, %1\";
4030       
4031     ops[0] = operands[0];
4032     
4033     if (GET_CODE (mem) == PLUS)
4034       {
4035         rtx a = XEXP (mem, 0);
4036         rtx b = XEXP (mem, 1);
4037         
4038         ops[1] = a;
4039         ops[2] = b;
4040
4041         if (GET_CODE (a) == REG)
4042           {
4043             if (GET_CODE (b) == REG)
4044               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4045             else if (REGNO (a) == REGNO (ops[0]))
4046               {
4047                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4048                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4049               }
4050             else
4051               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4052           }
4053         else
4054           {
4055             gcc_assert (GET_CODE (b) == REG);
4056             if (REGNO (b) == REGNO (ops[0]))
4057               {
4058                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4059                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4060               }
4061             else
4062               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4063           }
4064       }
4065     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4066       {
4067         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4068         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4069       }
4070     else
4071       {
4072         ops[1] = mem;
4073         ops[2] = const0_rtx;
4074         
4075         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4076       }
4077     return \"\";
4078   }"
4079   [(set_attr "length" "2,2,4")
4080    (set_attr "type" "alu_shift,load_byte,load_byte")
4081    (set_attr "pool_range" "*,32,32")]
4082 )
4083
4084 (define_expand "extendsfdf2"
4085   [(set (match_operand:DF                  0 "s_register_operand" "")
4086         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4087   "TARGET_ARM && TARGET_HARD_FLOAT"
4088   ""
4089 )
4090 \f
4091 ;; Move insns (including loads and stores)
4092
4093 ;; XXX Just some ideas about movti.
4094 ;; I don't think these are a good idea on the arm, there just aren't enough
4095 ;; registers
4096 ;;(define_expand "loadti"
4097 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4098 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4099 ;;  "" "")
4100
4101 ;;(define_expand "storeti"
4102 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4103 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4104 ;;  "" "")
4105
4106 ;;(define_expand "movti"
4107 ;;  [(set (match_operand:TI 0 "general_operand" "")
4108 ;;      (match_operand:TI 1 "general_operand" ""))]
4109 ;;  ""
4110 ;;  "
4111 ;;{
4112 ;;  rtx insn;
4113 ;;
4114 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4115 ;;    operands[1] = copy_to_reg (operands[1]);
4116 ;;  if (GET_CODE (operands[0]) == MEM)
4117 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4118 ;;  else if (GET_CODE (operands[1]) == MEM)
4119 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4120 ;;  else
4121 ;;    FAIL;
4122 ;;
4123 ;;  emit_insn (insn);
4124 ;;  DONE;
4125 ;;}")
4126
4127 ;; Recognize garbage generated above.
4128
4129 ;;(define_insn ""
4130 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4131 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4132 ;;  ""
4133 ;;  "*
4134 ;;  {
4135 ;;    register mem = (which_alternative < 3);
4136 ;;    register const char *template;
4137 ;;
4138 ;;    operands[mem] = XEXP (operands[mem], 0);
4139 ;;    switch (which_alternative)
4140 ;;      {
4141 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4142 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4143 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4144 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4145 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4146 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4147 ;;      }
4148 ;;    output_asm_insn (template, operands);
4149 ;;    return \"\";
4150 ;;  }")
4151
4152 (define_expand "movdi"
4153   [(set (match_operand:DI 0 "general_operand" "")
4154         (match_operand:DI 1 "general_operand" ""))]
4155   "TARGET_EITHER"
4156   "
4157   if (!no_new_pseudos)
4158     {
4159       if (GET_CODE (operands[0]) != REG)
4160         operands[1] = force_reg (DImode, operands[1]);
4161     }
4162   "
4163 )
4164
4165 (define_insn "*arm_movdi"
4166   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4167         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4168   "TARGET_ARM
4169    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4170    && !TARGET_IWMMXT
4171    && (   register_operand (operands[0], DImode)
4172        || register_operand (operands[1], DImode))"
4173   "*
4174   switch (which_alternative)
4175     {
4176     case 0:
4177     case 1:
4178     case 2:
4179       return \"#\";
4180     default:
4181       return output_move_double (operands);
4182     }
4183   "
4184   [(set_attr "length" "8,12,16,8,8")
4185    (set_attr "type" "*,*,*,load2,store2")
4186    (set_attr "pool_range" "*,*,*,1020,*")
4187    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4188 )
4189
4190 (define_split
4191   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4192         (match_operand:ANY64 1 "const_double_operand" ""))]
4193   "TARGET_ARM
4194    && reload_completed
4195    && (arm_const_double_inline_cost (operands[1])
4196        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4197   [(const_int 0)]
4198   "
4199   arm_split_constant (SET, SImode, curr_insn,
4200                       INTVAL (gen_lowpart (SImode, operands[1])),
4201                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4202   arm_split_constant (SET, SImode, curr_insn,
4203                       INTVAL (gen_highpart_mode (SImode,
4204                                                  GET_MODE (operands[0]),
4205                                                  operands[1])),
4206                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4207   DONE;
4208   "
4209 )
4210
4211 ; If optimizing for size, or if we have load delay slots, then 
4212 ; we want to split the constant into two separate operations. 
4213 ; In both cases this may split a trivial part into a single data op
4214 ; leaving a single complex constant to load.  We can also get longer
4215 ; offsets in a LDR which means we get better chances of sharing the pool
4216 ; entries.  Finally, we can normally do a better job of scheduling
4217 ; LDR instructions than we can with LDM.
4218 ; This pattern will only match if the one above did not.
4219 (define_split
4220   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4221         (match_operand:ANY64 1 "const_double_operand" ""))]
4222   "TARGET_ARM && reload_completed
4223    && arm_const_double_by_parts (operands[1])"
4224   [(set (match_dup 0) (match_dup 1))
4225    (set (match_dup 2) (match_dup 3))]
4226   "
4227   operands[2] = gen_highpart (SImode, operands[0]);
4228   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4229                                    operands[1]);
4230   operands[0] = gen_lowpart (SImode, operands[0]);
4231   operands[1] = gen_lowpart (SImode, operands[1]);
4232   "
4233 )
4234
4235 (define_split
4236   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4237         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4238   "TARGET_EITHER && reload_completed"
4239   [(set (match_dup 0) (match_dup 1))
4240    (set (match_dup 2) (match_dup 3))]
4241   "
4242   operands[2] = gen_highpart (SImode, operands[0]);
4243   operands[3] = gen_highpart (SImode, operands[1]);
4244   operands[0] = gen_lowpart (SImode, operands[0]);
4245   operands[1] = gen_lowpart (SImode, operands[1]);
4246
4247   /* Handle a partial overlap.  */
4248   if (rtx_equal_p (operands[0], operands[3]))
4249     {
4250       rtx tmp0 = operands[0];
4251       rtx tmp1 = operands[1];
4252
4253       operands[0] = operands[2];
4254       operands[1] = operands[3];
4255       operands[2] = tmp0;
4256       operands[3] = tmp1;
4257     }
4258   "
4259 )
4260
4261 ;; We can't actually do base+index doubleword loads if the index and
4262 ;; destination overlap.  Split here so that we at least have chance to
4263 ;; schedule.
4264 (define_split
4265   [(set (match_operand:DI 0 "s_register_operand" "")
4266         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4267                          (match_operand:SI 2 "s_register_operand" ""))))]
4268   "TARGET_LDRD
4269   && reg_overlap_mentioned_p (operands[0], operands[1])
4270   && reg_overlap_mentioned_p (operands[0], operands[2])"
4271   [(set (match_dup 4)
4272         (plus:SI (match_dup 1)
4273                  (match_dup 2)))
4274    (set (match_dup 0)
4275         (mem:DI (match_dup 4)))]
4276   "
4277   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4278   "
4279 )
4280
4281 ;;; ??? This should have alternatives for constants.
4282 ;;; ??? This was originally identical to the movdf_insn pattern.
4283 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4284 ;;; thumb_reorg with a memory reference.
4285 (define_insn "*thumb_movdi_insn"
4286   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4287         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4288   "TARGET_THUMB
4289    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4290    && (   register_operand (operands[0], DImode)
4291        || register_operand (operands[1], DImode))"
4292   "*
4293   {
4294   switch (which_alternative)
4295     {
4296     default:
4297     case 0:
4298       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4299         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4300       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4301     case 1:
4302       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4303     case 2:
4304       operands[1] = GEN_INT (- INTVAL (operands[1]));
4305       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4306     case 3:
4307       return \"ldmia\\t%1, {%0, %H0}\";
4308     case 4:
4309       return \"stmia\\t%0, {%1, %H1}\";
4310     case 5:
4311       return thumb_load_double_from_address (operands);
4312     case 6:
4313       operands[2] = gen_rtx_MEM (SImode,
4314                              plus_constant (XEXP (operands[0], 0), 4));
4315       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4316       return \"\";
4317     case 7:
4318       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4319         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4320       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4321     }
4322   }"
4323   [(set_attr "length" "4,4,6,2,2,6,4,4")
4324    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4325    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4326 )
4327
4328 (define_expand "movsi"
4329   [(set (match_operand:SI 0 "general_operand" "")
4330         (match_operand:SI 1 "general_operand" ""))]
4331   "TARGET_EITHER"
4332   "
4333   if (TARGET_ARM)
4334     {
4335       /* Everything except mem = const or mem = mem can be done easily.  */
4336       if (GET_CODE (operands[0]) == MEM)
4337         operands[1] = force_reg (SImode, operands[1]);
4338       if (arm_general_register_operand (operands[0], SImode)
4339           && GET_CODE (operands[1]) == CONST_INT
4340           && !(const_ok_for_arm (INTVAL (operands[1]))
4341                || const_ok_for_arm (~INTVAL (operands[1]))))
4342         {
4343            arm_split_constant (SET, SImode, NULL_RTX,
4344                                INTVAL (operands[1]), operands[0], NULL_RTX,
4345                                optimize && !no_new_pseudos);
4346           DONE;
4347         }
4348     }
4349   else /* TARGET_THUMB....  */
4350     {
4351       if (!no_new_pseudos)
4352         {
4353           if (GET_CODE (operands[0]) != REG)
4354             operands[1] = force_reg (SImode, operands[1]);
4355         }
4356     }
4357
4358   /* Recognize the case where operand[1] is a reference to thread-local
4359      data and load its address to a register.  */
4360   if (arm_tls_referenced_p (operands[1]))
4361     {
4362       rtx tmp = operands[1];
4363       rtx addend = NULL;
4364
4365       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4366         {
4367           addend = XEXP (XEXP (tmp, 0), 1);
4368           tmp = XEXP (XEXP (tmp, 0), 0);
4369         }
4370
4371       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4372       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4373
4374       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4375       if (addend)
4376         {
4377           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4378           tmp = force_operand (tmp, operands[0]);
4379         }
4380       operands[1] = tmp;
4381     }
4382   else if (flag_pic
4383            && (CONSTANT_P (operands[1])
4384                || symbol_mentioned_p (operands[1])
4385                || label_mentioned_p (operands[1])))
4386       operands[1] = legitimize_pic_address (operands[1], SImode,
4387                                             (no_new_pseudos ? operands[0] : 0));
4388   "
4389 )
4390
4391 (define_insn "*arm_movsi_insn"
4392   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4393         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4394   "TARGET_ARM && ! TARGET_IWMMXT
4395    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4396    && (   register_operand (operands[0], SImode)
4397        || register_operand (operands[1], SImode))"
4398   "@
4399    mov%?\\t%0, %1
4400    mvn%?\\t%0, #%B1
4401    ldr%?\\t%0, %1
4402    str%?\\t%1, %0"
4403   [(set_attr "type" "*,*,load1,store1")
4404    (set_attr "predicable" "yes")
4405    (set_attr "pool_range" "*,*,4096,*")
4406    (set_attr "neg_pool_range" "*,*,4084,*")]
4407 )
4408
4409 (define_split
4410   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4411         (match_operand:SI 1 "const_int_operand" ""))]
4412   "TARGET_ARM
4413   && (!(const_ok_for_arm (INTVAL (operands[1]))
4414         || const_ok_for_arm (~INTVAL (operands[1]))))"
4415   [(clobber (const_int 0))]
4416   "
4417   arm_split_constant (SET, SImode, NULL_RTX, 
4418                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4419   DONE;
4420   "
4421 )
4422
4423 (define_insn "*thumb_movsi_insn"
4424   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4425         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4426   "TARGET_THUMB
4427    && (   register_operand (operands[0], SImode) 
4428        || register_operand (operands[1], SImode))"
4429   "@
4430    mov  %0, %1
4431    mov  %0, %1
4432    #
4433    #
4434    ldmia\\t%1, {%0}
4435    stmia\\t%0, {%1}
4436    ldr\\t%0, %1
4437    str\\t%1, %0
4438    mov\\t%0, %1"
4439   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4440    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4441    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4442 )
4443
4444 (define_split 
4445   [(set (match_operand:SI 0 "register_operand" "")
4446         (match_operand:SI 1 "const_int_operand" ""))]
4447   "TARGET_THUMB && satisfies_constraint_J (operands[1])"
4448   [(set (match_dup 0) (match_dup 1))
4449    (set (match_dup 0) (neg:SI (match_dup 0)))]
4450   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4451 )
4452
4453 (define_split 
4454   [(set (match_operand:SI 0 "register_operand" "")
4455         (match_operand:SI 1 "const_int_operand" ""))]
4456   "TARGET_THUMB && satisfies_constraint_K (operands[1])"
4457   [(set (match_dup 0) (match_dup 1))
4458    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4459   "
4460   {
4461     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4462     unsigned HOST_WIDE_INT mask = 0xff;
4463     int i;
4464     
4465     for (i = 0; i < 25; i++)
4466       if ((val & (mask << i)) == val)
4467         break;
4468
4469     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4470     if (i == 0)
4471       FAIL;
4472
4473     operands[1] = GEN_INT (val >> i);
4474     operands[2] = GEN_INT (i);
4475   }"
4476 )
4477
4478 ;; When generating pic, we need to load the symbol offset into a register.
4479 ;; So that the optimizer does not confuse this with a normal symbol load
4480 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4481 ;; since that is the only type of relocation we can use.
4482
4483 ;; The rather odd constraints on the following are to force reload to leave
4484 ;; the insn alone, and to force the minipool generation pass to then move
4485 ;; the GOT symbol to memory.
4486
4487 (define_insn "pic_load_addr_arm"
4488   [(set (match_operand:SI 0 "s_register_operand" "=r")
4489         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4490   "TARGET_ARM && flag_pic"
4491   "ldr%?\\t%0, %1"
4492   [(set_attr "type" "load1")
4493    (set (attr "pool_range")     (const_int 4096))
4494    (set (attr "neg_pool_range") (const_int 4084))]
4495 )
4496
4497 (define_insn "pic_load_addr_thumb"
4498   [(set (match_operand:SI 0 "s_register_operand" "=l")
4499         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4500   "TARGET_THUMB && flag_pic"
4501   "ldr\\t%0, %1"
4502   [(set_attr "type" "load1")
4503    (set (attr "pool_range") (const_int 1024))]
4504 )
4505
4506 ;; This variant is used for AOF assembly, since it needs to mention the
4507 ;; pic register in the rtl.
4508 (define_expand "pic_load_addr_based"
4509   [(set (match_operand:SI 0 "s_register_operand" "")
4510         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4511   "TARGET_ARM && flag_pic"
4512   "operands[2] = cfun->machine->pic_reg;"
4513 )
4514
4515 (define_insn "*pic_load_addr_based_insn"
4516   [(set (match_operand:SI 0 "s_register_operand" "=r")
4517         (unspec:SI [(match_operand 1 "" "")
4518                     (match_operand 2 "s_register_operand" "r")]
4519                    UNSPEC_PIC_SYM))]
4520   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4521   "*
4522 #ifdef AOF_ASSEMBLER
4523   operands[1] = aof_pic_entry (operands[1]);
4524 #endif
4525   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4526   return \"\";
4527   "
4528   [(set_attr "type" "load1")
4529    (set (attr "pool_range")
4530         (if_then_else (eq_attr "is_thumb" "yes")
4531                       (const_int 1024)
4532                       (const_int 4096)))
4533    (set (attr "neg_pool_range")
4534         (if_then_else (eq_attr "is_thumb" "yes")
4535                       (const_int 0)
4536                       (const_int 4084)))]
4537 )
4538
4539 (define_insn "pic_add_dot_plus_four"
4540   [(set (match_operand:SI 0 "register_operand" "=r")
4541         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4542                              (const (plus:SI (pc) (const_int 4))))]
4543                    UNSPEC_PIC_BASE))
4544    (use (match_operand 2 "" ""))]
4545   "TARGET_THUMB"
4546   "*
4547   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4548                                      INTVAL (operands[2]));
4549   return \"add\\t%0, %|pc\";
4550   "
4551   [(set_attr "length" "2")]
4552 )
4553
4554 (define_insn "pic_add_dot_plus_eight"
4555   [(set (match_operand:SI 0 "register_operand" "=r")
4556         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4557                              (const (plus:SI (pc) (const_int 8))))]
4558                    UNSPEC_PIC_BASE))
4559    (use (match_operand 2 "" ""))]
4560   "TARGET_ARM"
4561   "*
4562     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4563                                        INTVAL (operands[2]));
4564     return \"add%?\\t%0, %|pc, %1\";
4565   "
4566   [(set_attr "predicable" "yes")]
4567 )
4568
4569 (define_insn "tls_load_dot_plus_eight"
4570   [(set (match_operand:SI 0 "register_operand" "+r")
4571         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4572                                      (const (plus:SI (pc) (const_int 8))))]
4573                            UNSPEC_PIC_BASE)))
4574    (use (match_operand 2 "" ""))]
4575   "TARGET_ARM"
4576   "*
4577     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4578                                        INTVAL (operands[2]));
4579     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4580   "
4581   [(set_attr "predicable" "yes")]
4582 )
4583
4584 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4585 ;; followed by a load.  These sequences can be crunched down to
4586 ;; tls_load_dot_plus_eight by a peephole.
4587
4588 (define_peephole2
4589   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4590                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4591                                         (const (plus:SI (pc) (const_int 8))))]
4592                               UNSPEC_PIC_BASE))
4593               (use (label_ref (match_operand 1 "" "")))])
4594    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4595   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4596   [(parallel [(set (match_dup 2)
4597                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4598                                                 (const (plus:SI (pc) (const_int 8))))]
4599                                       UNSPEC_PIC_BASE)))
4600               (use (label_ref (match_dup 1)))])]
4601   ""
4602 )
4603
4604 (define_expand "builtin_setjmp_receiver"
4605   [(label_ref (match_operand 0 "" ""))]
4606   "flag_pic"
4607   "
4608 {
4609   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4610      register.  */
4611   if (arm_pic_register != INVALID_REGNUM)
4612     arm_load_pic_register (1UL << 3);
4613   DONE;
4614 }")
4615
4616 ;; If copying one reg to another we can set the condition codes according to
4617 ;; its value.  Such a move is common after a return from subroutine and the
4618 ;; result is being tested against zero.
4619
4620 (define_insn "*movsi_compare0"
4621   [(set (reg:CC CC_REGNUM)
4622         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4623                     (const_int 0)))
4624    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4625         (match_dup 1))]
4626   "TARGET_ARM"
4627   "@
4628    cmp%?\\t%0, #0
4629    sub%?s\\t%0, %1, #0"
4630   [(set_attr "conds" "set")]
4631 )
4632
4633 ;; Subroutine to store a half word from a register into memory.
4634 ;; Operand 0 is the source register (HImode)
4635 ;; Operand 1 is the destination address in a register (SImode)
4636
4637 ;; In both this routine and the next, we must be careful not to spill
4638 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4639 ;; can generate unrecognizable rtl.
4640
4641 (define_expand "storehi"
4642   [;; store the low byte
4643    (set (match_operand 1 "" "") (match_dup 3))
4644    ;; extract the high byte
4645    (set (match_dup 2)
4646         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4647    ;; store the high byte
4648    (set (match_dup 4) (match_dup 5))]
4649   "TARGET_ARM"
4650   "
4651   {
4652     rtx op1 = operands[1];
4653     rtx addr = XEXP (op1, 0);
4654     enum rtx_code code = GET_CODE (addr);
4655
4656     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4657         || code == MINUS)
4658       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4659
4660     operands[4] = adjust_address (op1, QImode, 1);
4661     operands[1] = adjust_address (operands[1], QImode, 0);
4662     operands[3] = gen_lowpart (QImode, operands[0]);
4663     operands[0] = gen_lowpart (SImode, operands[0]);
4664     operands[2] = gen_reg_rtx (SImode);
4665     operands[5] = gen_lowpart (QImode, operands[2]);
4666   }"
4667 )
4668
4669 (define_expand "storehi_bigend"
4670   [(set (match_dup 4) (match_dup 3))
4671    (set (match_dup 2)
4672         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4673    (set (match_operand 1 "" "") (match_dup 5))]
4674   "TARGET_ARM"
4675   "
4676   {
4677     rtx op1 = operands[1];
4678     rtx addr = XEXP (op1, 0);
4679     enum rtx_code code = GET_CODE (addr);
4680
4681     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4682         || code == MINUS)
4683       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4684
4685     operands[4] = adjust_address (op1, QImode, 1);
4686     operands[1] = adjust_address (operands[1], QImode, 0);
4687     operands[3] = gen_lowpart (QImode, operands[0]);
4688     operands[0] = gen_lowpart (SImode, operands[0]);
4689     operands[2] = gen_reg_rtx (SImode);
4690     operands[5] = gen_lowpart (QImode, operands[2]);
4691   }"
4692 )
4693
4694 ;; Subroutine to store a half word integer constant into memory.
4695 (define_expand "storeinthi"
4696   [(set (match_operand 0 "" "")
4697         (match_operand 1 "" ""))
4698    (set (match_dup 3) (match_dup 2))]
4699   "TARGET_ARM"
4700   "
4701   {
4702     HOST_WIDE_INT value = INTVAL (operands[1]);
4703     rtx addr = XEXP (operands[0], 0);
4704     rtx op0 = operands[0];
4705     enum rtx_code code = GET_CODE (addr);
4706
4707     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4708         || code == MINUS)
4709       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4710
4711     operands[1] = gen_reg_rtx (SImode);
4712     if (BYTES_BIG_ENDIAN)
4713       {
4714         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4715         if ((value & 255) == ((value >> 8) & 255))
4716           operands[2] = operands[1];
4717         else
4718           {
4719             operands[2] = gen_reg_rtx (SImode);
4720             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4721           }
4722       }
4723     else
4724       {
4725         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4726         if ((value & 255) == ((value >> 8) & 255))
4727           operands[2] = operands[1];
4728         else
4729           {
4730             operands[2] = gen_reg_rtx (SImode);
4731             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4732           }
4733       }
4734
4735     operands[3] = adjust_address (op0, QImode, 1);
4736     operands[0] = adjust_address (operands[0], QImode, 0);
4737     operands[2] = gen_lowpart (QImode, operands[2]);
4738     operands[1] = gen_lowpart (QImode, operands[1]);
4739   }"
4740 )
4741
4742 (define_expand "storehi_single_op"
4743   [(set (match_operand:HI 0 "memory_operand" "")
4744         (match_operand:HI 1 "general_operand" ""))]
4745   "TARGET_ARM && arm_arch4"
4746   "
4747   if (!s_register_operand (operands[1], HImode))
4748     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4749   "
4750 )
4751
4752 (define_expand "movhi"
4753   [(set (match_operand:HI 0 "general_operand" "")
4754         (match_operand:HI 1 "general_operand" ""))]
4755   "TARGET_EITHER"
4756   "
4757   if (TARGET_ARM)
4758     {
4759       if (!no_new_pseudos)
4760         {
4761           if (GET_CODE (operands[0]) == MEM)
4762             {
4763               if (arm_arch4)
4764                 {
4765                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4766                   DONE;
4767                 }
4768               if (GET_CODE (operands[1]) == CONST_INT)
4769                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4770               else
4771                 {
4772                   if (GET_CODE (operands[1]) == MEM)
4773                     operands[1] = force_reg (HImode, operands[1]);
4774                   if (BYTES_BIG_ENDIAN)
4775                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4776                   else
4777                    emit_insn (gen_storehi (operands[1], operands[0]));
4778                 }
4779               DONE;
4780             }
4781           /* Sign extend a constant, and keep it in an SImode reg.  */
4782           else if (GET_CODE (operands[1]) == CONST_INT)
4783             {
4784               rtx reg = gen_reg_rtx (SImode);
4785               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4786
4787               /* If the constant is already valid, leave it alone.  */
4788               if (!const_ok_for_arm (val))
4789                 {
4790                   /* If setting all the top bits will make the constant 
4791                      loadable in a single instruction, then set them.  
4792                      Otherwise, sign extend the number.  */
4793
4794                   if (const_ok_for_arm (~(val | ~0xffff)))
4795                     val |= ~0xffff;
4796                   else if (val & 0x8000)
4797                     val |= ~0xffff;
4798                 }
4799
4800               emit_insn (gen_movsi (reg, GEN_INT (val)));
4801               operands[1] = gen_lowpart (HImode, reg);
4802             }
4803           else if (arm_arch4 && optimize && !no_new_pseudos
4804                    && GET_CODE (operands[1]) == MEM)
4805             {
4806               rtx reg = gen_reg_rtx (SImode);
4807
4808               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4809               operands[1] = gen_lowpart (HImode, reg);
4810             }
4811           else if (!arm_arch4)
4812             {
4813               if (GET_CODE (operands[1]) == MEM)
4814                 {
4815                   rtx base;
4816                   rtx offset = const0_rtx;
4817                   rtx reg = gen_reg_rtx (SImode);
4818
4819                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4820                        || (GET_CODE (base) == PLUS
4821                            && (GET_CODE (offset = XEXP (base, 1))
4822                                == CONST_INT)
4823                            && ((INTVAL(offset) & 1) != 1)
4824                            && GET_CODE (base = XEXP (base, 0)) == REG))
4825                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4826                     {
4827                       rtx new;
4828
4829                       new = widen_memory_access (operands[1], SImode,
4830                                                  ((INTVAL (offset) & ~3)
4831                                                   - INTVAL (offset)));
4832                       emit_insn (gen_movsi (reg, new));
4833                       if (((INTVAL (offset) & 2) != 0)
4834                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4835                         {
4836                           rtx reg2 = gen_reg_rtx (SImode);
4837
4838                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4839                           reg = reg2;
4840                         }
4841                     }
4842                   else
4843                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4844
4845                   operands[1] = gen_lowpart (HImode, reg);
4846                }
4847            }
4848         }
4849       /* Handle loading a large integer during reload.  */
4850       else if (GET_CODE (operands[1]) == CONST_INT
4851                && !const_ok_for_arm (INTVAL (operands[1]))
4852                && !const_ok_for_arm (~INTVAL (operands[1])))
4853         {
4854           /* Writing a constant to memory needs a scratch, which should
4855              be handled with SECONDARY_RELOADs.  */
4856           gcc_assert (GET_CODE (operands[0]) == REG);
4857
4858           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4859           emit_insn (gen_movsi (operands[0], operands[1]));
4860           DONE;
4861        }
4862     }
4863   else /* TARGET_THUMB */
4864     {
4865       if (!no_new_pseudos)
4866         {
4867           if (GET_CODE (operands[1]) == CONST_INT)
4868             {
4869               rtx reg = gen_reg_rtx (SImode);
4870
4871               emit_insn (gen_movsi (reg, operands[1]));
4872               operands[1] = gen_lowpart (HImode, reg);
4873             }
4874
4875           /* ??? We shouldn't really get invalid addresses here, but this can
4876              happen if we are passed a SP (never OK for HImode/QImode) or 
4877              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4878              HImode/QImode) relative address.  */
4879           /* ??? This should perhaps be fixed elsewhere, for instance, in
4880              fixup_stack_1, by checking for other kinds of invalid addresses,
4881              e.g. a bare reference to a virtual register.  This may confuse the
4882              alpha though, which must handle this case differently.  */
4883           if (GET_CODE (operands[0]) == MEM
4884               && !memory_address_p (GET_MODE (operands[0]),
4885                                     XEXP (operands[0], 0)))
4886             operands[0]
4887               = replace_equiv_address (operands[0],
4888                                        copy_to_reg (XEXP (operands[0], 0)));
4889    
4890           if (GET_CODE (operands[1]) == MEM
4891               && !memory_address_p (GET_MODE (operands[1]),
4892                                     XEXP (operands[1], 0)))
4893             operands[1]
4894               = replace_equiv_address (operands[1],
4895                                        copy_to_reg (XEXP (operands[1], 0)));
4896
4897           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4898             {
4899               rtx reg = gen_reg_rtx (SImode);
4900
4901               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4902               operands[1] = gen_lowpart (HImode, reg);
4903             }
4904
4905           if (GET_CODE (operands[0]) == MEM)
4906             operands[1] = force_reg (HImode, operands[1]);
4907         }
4908       else if (GET_CODE (operands[1]) == CONST_INT
4909                 && !satisfies_constraint_I (operands[1]))
4910         {
4911           /* Handle loading a large integer during reload.  */
4912
4913           /* Writing a constant to memory needs a scratch, which should
4914              be handled with SECONDARY_RELOADs.  */
4915           gcc_assert (GET_CODE (operands[0]) == REG);
4916
4917           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4918           emit_insn (gen_movsi (operands[0], operands[1]));
4919           DONE;
4920         }
4921     }
4922   "
4923 )
4924
4925 (define_insn "*thumb_movhi_insn"
4926   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4927         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4928   "TARGET_THUMB
4929    && (   register_operand (operands[0], HImode)
4930        || register_operand (operands[1], HImode))"
4931   "*
4932   switch (which_alternative)
4933     {
4934     case 0: return \"add        %0, %1, #0\";
4935     case 2: return \"strh       %1, %0\";
4936     case 3: return \"mov        %0, %1\";
4937     case 4: return \"mov        %0, %1\";
4938     case 5: return \"mov        %0, %1\";
4939     default: gcc_unreachable ();
4940     case 1:
4941       /* The stack pointer can end up being taken as an index register.
4942           Catch this case here and deal with it.  */
4943       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4944           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4945           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4946         {
4947           rtx ops[2];
4948           ops[0] = operands[0];
4949           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4950       
4951           output_asm_insn (\"mov        %0, %1\", ops);
4952
4953           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4954     
4955         }
4956       return \"ldrh     %0, %1\";
4957     }"
4958   [(set_attr "length" "2,4,2,2,2,2")
4959    (set_attr "type" "*,load1,store1,*,*,*")]
4960 )
4961
4962
4963 (define_expand "movhi_bytes"
4964   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4965    (set (match_dup 3)
4966         (zero_extend:SI (match_dup 6)))
4967    (set (match_operand:SI 0 "" "")
4968          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4969   "TARGET_ARM"
4970   "
4971   {
4972     rtx mem1, mem2;
4973     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4974
4975     mem1 = change_address (operands[1], QImode, addr);
4976     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4977     operands[0] = gen_lowpart (SImode, operands[0]);
4978     operands[1] = mem1;
4979     operands[2] = gen_reg_rtx (SImode);
4980     operands[3] = gen_reg_rtx (SImode);
4981     operands[6] = mem2;
4982
4983     if (BYTES_BIG_ENDIAN)
4984       {
4985         operands[4] = operands[2];
4986         operands[5] = operands[3];
4987       }
4988     else
4989       {
4990         operands[4] = operands[3];
4991         operands[5] = operands[2];
4992       }
4993   }"
4994 )
4995
4996 (define_expand "movhi_bigend"
4997   [(set (match_dup 2)
4998         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4999                    (const_int 16)))
5000    (set (match_dup 3)
5001         (ashiftrt:SI (match_dup 2) (const_int 16)))
5002    (set (match_operand:HI 0 "s_register_operand" "")
5003         (match_dup 4))]
5004   "TARGET_ARM"
5005   "
5006   operands[2] = gen_reg_rtx (SImode);
5007   operands[3] = gen_reg_rtx (SImode);
5008   operands[4] = gen_lowpart (HImode, operands[3]);
5009   "
5010 )
5011
5012 ;; Pattern to recognize insn generated default case above
5013 (define_insn "*movhi_insn_arch4"
5014   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5015         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5016   "TARGET_ARM
5017    && arm_arch4
5018    && (GET_CODE (operands[1]) != CONST_INT
5019        || const_ok_for_arm (INTVAL (operands[1]))
5020        || const_ok_for_arm (~INTVAL (operands[1])))"
5021   "@
5022    mov%?\\t%0, %1\\t%@ movhi
5023    mvn%?\\t%0, #%B1\\t%@ movhi
5024    str%?h\\t%1, %0\\t%@ movhi
5025    ldr%?h\\t%0, %1\\t%@ movhi"
5026   [(set_attr "type" "*,*,store1,load1")
5027    (set_attr "predicable" "yes")
5028    (set_attr "pool_range" "*,*,*,256")
5029    (set_attr "neg_pool_range" "*,*,*,244")]
5030 )
5031
5032 (define_insn "*movhi_bytes"
5033   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5034         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5035   "TARGET_ARM"
5036   "@
5037    mov%?\\t%0, %1\\t%@ movhi
5038    mvn%?\\t%0, #%B1\\t%@ movhi"
5039   [(set_attr "predicable" "yes")]
5040 )
5041
5042 (define_expand "thumb_movhi_clobber"
5043   [(set (match_operand:HI     0 "memory_operand"   "")
5044         (match_operand:HI     1 "register_operand" ""))
5045    (clobber (match_operand:DI 2 "register_operand" ""))]
5046   "TARGET_THUMB"
5047   "
5048   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5049       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5050     {
5051       emit_insn (gen_movhi (operands[0], operands[1]));
5052       DONE;
5053     }
5054   /* XXX Fixme, need to handle other cases here as well.  */
5055   gcc_unreachable ();
5056   "
5057 )
5058         
5059 ;; We use a DImode scratch because we may occasionally need an additional
5060 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5061 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5062 (define_expand "reload_outhi"
5063   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5064               (match_operand:HI 1 "s_register_operand"        "r")
5065               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5066   "TARGET_EITHER"
5067   "if (TARGET_ARM)
5068      arm_reload_out_hi (operands);
5069    else
5070      thumb_reload_out_hi (operands);
5071   DONE;
5072   "
5073 )
5074
5075 (define_expand "reload_inhi"
5076   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5077               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5078               (match_operand:DI 2 "s_register_operand" "=&r")])]
5079   "TARGET_EITHER"
5080   "
5081   if (TARGET_ARM)
5082     arm_reload_in_hi (operands);
5083   else
5084     thumb_reload_out_hi (operands);
5085   DONE;
5086 ")
5087
5088 (define_expand "movqi"
5089   [(set (match_operand:QI 0 "general_operand" "")
5090         (match_operand:QI 1 "general_operand" ""))]
5091   "TARGET_EITHER"
5092   "
5093   /* Everything except mem = const or mem = mem can be done easily */
5094
5095   if (!no_new_pseudos)
5096     {
5097       if (GET_CODE (operands[1]) == CONST_INT)
5098         {
5099           rtx reg = gen_reg_rtx (SImode);
5100
5101           emit_insn (gen_movsi (reg, operands[1]));
5102           operands[1] = gen_lowpart (QImode, reg);
5103         }
5104
5105       if (TARGET_THUMB)
5106         {
5107           /* ??? We shouldn't really get invalid addresses here, but this can
5108              happen if we are passed a SP (never OK for HImode/QImode) or
5109              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5110              HImode/QImode) relative address.  */
5111           /* ??? This should perhaps be fixed elsewhere, for instance, in
5112              fixup_stack_1, by checking for other kinds of invalid addresses,
5113              e.g. a bare reference to a virtual register.  This may confuse the
5114              alpha though, which must handle this case differently.  */
5115           if (GET_CODE (operands[0]) == MEM
5116               && !memory_address_p (GET_MODE (operands[0]),
5117                                      XEXP (operands[0], 0)))
5118             operands[0]
5119               = replace_equiv_address (operands[0],
5120                                        copy_to_reg (XEXP (operands[0], 0)));
5121           if (GET_CODE (operands[1]) == MEM
5122               && !memory_address_p (GET_MODE (operands[1]),
5123                                     XEXP (operands[1], 0)))
5124              operands[1]
5125                = replace_equiv_address (operands[1],
5126                                         copy_to_reg (XEXP (operands[1], 0)));
5127         }
5128
5129       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5130         {
5131           rtx reg = gen_reg_rtx (SImode);
5132
5133           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5134           operands[1] = gen_lowpart (QImode, reg);
5135         }
5136
5137       if (GET_CODE (operands[0]) == MEM)
5138         operands[1] = force_reg (QImode, operands[1]);
5139     }
5140   else if (TARGET_THUMB
5141            && GET_CODE (operands[1]) == CONST_INT
5142            && !satisfies_constraint_I (operands[1]))
5143     {
5144       /* Handle loading a large integer during reload.  */
5145
5146       /* Writing a constant to memory needs a scratch, which should
5147          be handled with SECONDARY_RELOADs.  */
5148       gcc_assert (GET_CODE (operands[0]) == REG);
5149
5150       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5151       emit_insn (gen_movsi (operands[0], operands[1]));
5152       DONE;
5153     }
5154   "
5155 )
5156
5157
5158 (define_insn "*arm_movqi_insn"
5159   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5160         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5161   "TARGET_ARM
5162    && (   register_operand (operands[0], QImode)
5163        || register_operand (operands[1], QImode))"
5164   "@
5165    mov%?\\t%0, %1
5166    mvn%?\\t%0, #%B1
5167    ldr%?b\\t%0, %1
5168    str%?b\\t%1, %0"
5169   [(set_attr "type" "*,*,load1,store1")
5170    (set_attr "predicable" "yes")]
5171 )
5172
5173 (define_insn "*thumb_movqi_insn"
5174   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5175         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5176   "TARGET_THUMB
5177    && (   register_operand (operands[0], QImode)
5178        || register_operand (operands[1], QImode))"
5179   "@
5180    add\\t%0, %1, #0
5181    ldrb\\t%0, %1
5182    strb\\t%1, %0
5183    mov\\t%0, %1
5184    mov\\t%0, %1
5185    mov\\t%0, %1"
5186   [(set_attr "length" "2")
5187    (set_attr "type" "*,load1,store1,*,*,*")
5188    (set_attr "pool_range" "*,32,*,*,*,*")]
5189 )
5190
5191 (define_expand "movsf"
5192   [(set (match_operand:SF 0 "general_operand" "")
5193         (match_operand:SF 1 "general_operand" ""))]
5194   "TARGET_EITHER"
5195   "
5196   if (TARGET_ARM)
5197     {
5198       if (GET_CODE (operands[0]) == MEM)
5199         operands[1] = force_reg (SFmode, operands[1]);
5200     }
5201   else /* TARGET_THUMB */
5202     {
5203       if (!no_new_pseudos)
5204         {
5205            if (GET_CODE (operands[0]) != REG)
5206              operands[1] = force_reg (SFmode, operands[1]);
5207         }
5208     }
5209   "
5210 )
5211
5212 ;; Transform a floating-point move of a constant into a core register into
5213 ;; an SImode operation.
5214 (define_split
5215   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5216         (match_operand:SF 1 "immediate_operand" ""))]
5217   "TARGET_ARM
5218    && reload_completed
5219    && GET_CODE (operands[1]) == CONST_DOUBLE"
5220   [(set (match_dup 2) (match_dup 3))]
5221   "
5222   operands[2] = gen_lowpart (SImode, operands[0]);
5223   operands[3] = gen_lowpart (SImode, operands[1]);
5224   if (operands[2] == 0 || operands[3] == 0)
5225     FAIL;
5226   "
5227 )
5228
5229 (define_insn "*arm_movsf_soft_insn"
5230   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5231         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5232   "TARGET_ARM
5233    && TARGET_SOFT_FLOAT
5234    && (GET_CODE (operands[0]) != MEM
5235        || register_operand (operands[1], SFmode))"
5236   "@
5237    mov%?\\t%0, %1
5238    ldr%?\\t%0, %1\\t%@ float
5239    str%?\\t%1, %0\\t%@ float"
5240   [(set_attr "length" "4,4,4")
5241    (set_attr "predicable" "yes")
5242    (set_attr "type" "*,load1,store1")
5243    (set_attr "pool_range" "*,4096,*")
5244    (set_attr "neg_pool_range" "*,4084,*")]
5245 )
5246
5247 ;;; ??? This should have alternatives for constants.
5248 (define_insn "*thumb_movsf_insn"
5249   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5250         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5251   "TARGET_THUMB
5252    && (   register_operand (operands[0], SFmode) 
5253        || register_operand (operands[1], SFmode))"
5254   "@
5255    add\\t%0, %1, #0
5256    ldmia\\t%1, {%0}
5257    stmia\\t%0, {%1}
5258    ldr\\t%0, %1
5259    str\\t%1, %0
5260    mov\\t%0, %1
5261    mov\\t%0, %1"
5262   [(set_attr "length" "2")
5263    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5264    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5265 )
5266
5267 (define_expand "movdf"
5268   [(set (match_operand:DF 0 "general_operand" "")
5269         (match_operand:DF 1 "general_operand" ""))]
5270   "TARGET_EITHER"
5271   "
5272   if (TARGET_ARM)
5273     {
5274       if (GET_CODE (operands[0]) == MEM)
5275         operands[1] = force_reg (DFmode, operands[1]);
5276     }
5277   else /* TARGET_THUMB */
5278     {
5279       if (!no_new_pseudos)
5280         {
5281           if (GET_CODE (operands[0]) != REG)
5282             operands[1] = force_reg (DFmode, operands[1]);
5283         }
5284     }
5285   "
5286 )
5287
5288 ;; Reloading a df mode value stored in integer regs to memory can require a
5289 ;; scratch reg.
5290 (define_expand "reload_outdf"
5291   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5292    (match_operand:DF 1 "s_register_operand" "r")
5293    (match_operand:SI 2 "s_register_operand" "=&r")]
5294   "TARGET_ARM"
5295   "
5296   {
5297     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5298
5299     if (code == REG)
5300       operands[2] = XEXP (operands[0], 0);
5301     else if (code == POST_INC || code == PRE_DEC)
5302       {
5303         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5304         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5305         emit_insn (gen_movdi (operands[0], operands[1]));
5306         DONE;
5307       }
5308     else if (code == PRE_INC)
5309       {
5310         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5311
5312         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5313         operands[2] = reg;
5314       }
5315     else if (code == POST_DEC)
5316       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5317     else
5318       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5319                              XEXP (XEXP (operands[0], 0), 1)));
5320
5321     emit_insn (gen_rtx_SET (VOIDmode,
5322                             replace_equiv_address (operands[0], operands[2]),
5323                             operands[1]));
5324
5325     if (code == POST_DEC)
5326       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5327
5328     DONE;
5329   }"
5330 )
5331
5332 (define_insn "*movdf_soft_insn"
5333   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5334         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5335   "TARGET_ARM && TARGET_SOFT_FLOAT
5336    && (   register_operand (operands[0], DFmode)
5337        || register_operand (operands[1], DFmode))"
5338   "*
5339   switch (which_alternative)
5340     {
5341     case 0:
5342     case 1:
5343     case 2:
5344       return \"#\";
5345     default:
5346       return output_move_double (operands);
5347     }
5348   "
5349   [(set_attr "length" "8,12,16,8,8")
5350    (set_attr "type" "*,*,*,load2,store2")
5351    (set_attr "pool_range" "1020")
5352    (set_attr "neg_pool_range" "1008")]
5353 )
5354
5355 ;;; ??? This should have alternatives for constants.
5356 ;;; ??? This was originally identical to the movdi_insn pattern.
5357 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5358 ;;; thumb_reorg with a memory reference.
5359 (define_insn "*thumb_movdf_insn"
5360   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5361         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5362   "TARGET_THUMB
5363    && (   register_operand (operands[0], DFmode)
5364        || register_operand (operands[1], DFmode))"
5365   "*
5366   switch (which_alternative)
5367     {
5368     default:
5369     case 0:
5370       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5371         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5372       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5373     case 1:
5374       return \"ldmia\\t%1, {%0, %H0}\";
5375     case 2:
5376       return \"stmia\\t%0, {%1, %H1}\";
5377     case 3:
5378       return thumb_load_double_from_address (operands);
5379     case 4:
5380       operands[2] = gen_rtx_MEM (SImode,
5381                                  plus_constant (XEXP (operands[0], 0), 4));
5382       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5383       return \"\";
5384     case 5:
5385       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5386         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5387       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5388     }
5389   "
5390   [(set_attr "length" "4,2,2,6,4,4")
5391    (set_attr "type" "*,load2,store2,load2,store2,*")
5392    (set_attr "pool_range" "*,*,*,1020,*,*")]
5393 )
5394
5395 (define_expand "movxf"
5396   [(set (match_operand:XF 0 "general_operand" "")
5397         (match_operand:XF 1 "general_operand" ""))]
5398   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5399   "
5400   if (GET_CODE (operands[0]) == MEM)
5401     operands[1] = force_reg (XFmode, operands[1]);
5402   "
5403 )
5404
5405 ;; Vector Moves
5406 (define_expand "movv2si"
5407   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5408         (match_operand:V2SI 1 "general_operand" ""))]
5409   "TARGET_REALLY_IWMMXT"
5410 {
5411 })
5412
5413 (define_expand "movv4hi"
5414   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5415         (match_operand:V4HI 1 "general_operand" ""))]
5416   "TARGET_REALLY_IWMMXT"
5417 {
5418 })
5419
5420 (define_expand "movv8qi"
5421   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5422         (match_operand:V8QI 1 "general_operand" ""))]
5423   "TARGET_REALLY_IWMMXT"
5424 {
5425 })
5426 \f
5427
5428 ;; load- and store-multiple insns
5429 ;; The arm can load/store any set of registers, provided that they are in
5430 ;; ascending order; but that is beyond GCC so stick with what it knows.
5431
5432 (define_expand "load_multiple"
5433   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5434                           (match_operand:SI 1 "" ""))
5435                      (use (match_operand:SI 2 "" ""))])]
5436   "TARGET_ARM"
5437 {
5438   HOST_WIDE_INT offset = 0;
5439
5440   /* Support only fixed point registers.  */
5441   if (GET_CODE (operands[2]) != CONST_INT
5442       || INTVAL (operands[2]) > 14
5443       || INTVAL (operands[2]) < 2
5444       || GET_CODE (operands[1]) != MEM
5445       || GET_CODE (operands[0]) != REG
5446       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5447       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5448     FAIL;
5449
5450   operands[3]
5451     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5452                              force_reg (SImode, XEXP (operands[1], 0)),
5453                              TRUE, FALSE, operands[1], &offset);
5454 })
5455
5456 ;; Load multiple with write-back
5457
5458 (define_insn "*ldmsi_postinc4"
5459   [(match_parallel 0 "load_multiple_operation"
5460     [(set (match_operand:SI 1 "s_register_operand" "=r")
5461           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5462                    (const_int 16)))
5463      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5464           (mem:SI (match_dup 2)))
5465      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5466           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5467      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5468           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5469      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5470           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5471   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5472   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5473   [(set_attr "type" "load4")
5474    (set_attr "predicable" "yes")]
5475 )
5476
5477 (define_insn "*ldmsi_postinc4_thumb"
5478   [(match_parallel 0 "load_multiple_operation"
5479     [(set (match_operand:SI 1 "s_register_operand" "=l")
5480           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5481                    (const_int 16)))
5482      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5483           (mem:SI (match_dup 2)))
5484      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5485           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5486      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5487           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5488      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5489           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5490   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5491   "ldmia\\t%1!, {%3, %4, %5, %6}"
5492   [(set_attr "type" "load4")]
5493 )
5494
5495 (define_insn "*ldmsi_postinc3"
5496   [(match_parallel 0 "load_multiple_operation"
5497     [(set (match_operand:SI 1 "s_register_operand" "=r")
5498           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5499                    (const_int 12)))
5500      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5501           (mem:SI (match_dup 2)))
5502      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5503           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5504      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5505           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5506   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5507   "ldm%?ia\\t%1!, {%3, %4, %5}"
5508   [(set_attr "type" "load3")
5509    (set_attr "predicable" "yes")]
5510 )
5511
5512 (define_insn "*ldmsi_postinc2"
5513   [(match_parallel 0 "load_multiple_operation"
5514     [(set (match_operand:SI 1 "s_register_operand" "=r")
5515           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5516                    (const_int 8)))
5517      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5518           (mem:SI (match_dup 2)))
5519      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5520           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5521   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5522   "ldm%?ia\\t%1!, {%3, %4}"
5523   [(set_attr "type" "load2")
5524    (set_attr "predicable" "yes")]
5525 )
5526
5527 ;; Ordinary load multiple
5528
5529 (define_insn "*ldmsi4"
5530   [(match_parallel 0 "load_multiple_operation"
5531     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5532           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5533      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5534           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5535      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5536           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5537      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5538           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5539   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5540   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5541   [(set_attr "type" "load4")
5542    (set_attr "predicable" "yes")]
5543 )
5544
5545 (define_insn "*ldmsi3"
5546   [(match_parallel 0 "load_multiple_operation"
5547     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5548           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5549      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5550           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5551      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5552           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5553   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5554   "ldm%?ia\\t%1, {%2, %3, %4}"
5555   [(set_attr "type" "load3")
5556    (set_attr "predicable" "yes")]
5557 )
5558
5559 (define_insn "*ldmsi2"
5560   [(match_parallel 0 "load_multiple_operation"
5561     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5562           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5563      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5564           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5565   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5566   "ldm%?ia\\t%1, {%2, %3}"
5567   [(set_attr "type" "load2")
5568    (set_attr "predicable" "yes")]
5569 )
5570
5571 (define_expand "store_multiple"
5572   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5573                           (match_operand:SI 1 "" ""))
5574                      (use (match_operand:SI 2 "" ""))])]
5575   "TARGET_ARM"
5576 {
5577   HOST_WIDE_INT offset = 0;
5578
5579   /* Support only fixed point registers.  */
5580   if (GET_CODE (operands[2]) != CONST_INT
5581       || INTVAL (operands[2]) > 14
5582       || INTVAL (operands[2]) < 2
5583       || GET_CODE (operands[1]) != REG
5584       || GET_CODE (operands[0]) != MEM
5585       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5586       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5587     FAIL;
5588
5589   operands[3]
5590     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5591                               force_reg (SImode, XEXP (operands[0], 0)),
5592                               TRUE, FALSE, operands[0], &offset);
5593 })
5594
5595 ;; Store multiple with write-back
5596
5597 (define_insn "*stmsi_postinc4"
5598   [(match_parallel 0 "store_multiple_operation"
5599     [(set (match_operand:SI 1 "s_register_operand" "=r")
5600           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5601                    (const_int 16)))
5602      (set (mem:SI (match_dup 2))
5603           (match_operand:SI 3 "arm_hard_register_operand" ""))
5604      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5605           (match_operand:SI 4 "arm_hard_register_operand" ""))
5606      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5607           (match_operand:SI 5 "arm_hard_register_operand" ""))
5608      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5609           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5610   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5611   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5612   [(set_attr "predicable" "yes")
5613    (set_attr "type" "store4")]
5614 )
5615
5616 (define_insn "*stmsi_postinc4_thumb"
5617   [(match_parallel 0 "store_multiple_operation"
5618     [(set (match_operand:SI 1 "s_register_operand" "=l")
5619           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5620                    (const_int 16)))
5621      (set (mem:SI (match_dup 2))
5622           (match_operand:SI 3 "arm_hard_register_operand" ""))
5623      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5624           (match_operand:SI 4 "arm_hard_register_operand" ""))
5625      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5626           (match_operand:SI 5 "arm_hard_register_operand" ""))
5627      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5628           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5629   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5630   "stmia\\t%1!, {%3, %4, %5, %6}"
5631   [(set_attr "type" "store4")]
5632 )
5633
5634 (define_insn "*stmsi_postinc3"
5635   [(match_parallel 0 "store_multiple_operation"
5636     [(set (match_operand:SI 1 "s_register_operand" "=r")
5637           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5638                    (const_int 12)))
5639      (set (mem:SI (match_dup 2))
5640           (match_operand:SI 3 "arm_hard_register_operand" ""))
5641      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5642           (match_operand:SI 4 "arm_hard_register_operand" ""))
5643      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5644           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5645   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5646   "stm%?ia\\t%1!, {%3, %4, %5}"
5647   [(set_attr "predicable" "yes")
5648    (set_attr "type" "store3")]
5649 )
5650
5651 (define_insn "*stmsi_postinc2"
5652   [(match_parallel 0 "store_multiple_operation"
5653     [(set (match_operand:SI 1 "s_register_operand" "=r")
5654           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5655                    (const_int 8)))
5656      (set (mem:SI (match_dup 2))
5657           (match_operand:SI 3 "arm_hard_register_operand" ""))
5658      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5659           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5660   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5661   "stm%?ia\\t%1!, {%3, %4}"
5662   [(set_attr "predicable" "yes")
5663    (set_attr "type" "store2")]
5664 )
5665
5666 ;; Ordinary store multiple
5667
5668 (define_insn "*stmsi4"
5669   [(match_parallel 0 "store_multiple_operation"
5670     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5671           (match_operand:SI 2 "arm_hard_register_operand" ""))
5672      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5673           (match_operand:SI 3 "arm_hard_register_operand" ""))
5674      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5675           (match_operand:SI 4 "arm_hard_register_operand" ""))
5676      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5677           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5678   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5679   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5680   [(set_attr "predicable" "yes")
5681    (set_attr "type" "store4")]
5682 )
5683
5684 (define_insn "*stmsi3"
5685   [(match_parallel 0 "store_multiple_operation"
5686     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5687           (match_operand:SI 2 "arm_hard_register_operand" ""))
5688      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5689           (match_operand:SI 3 "arm_hard_register_operand" ""))
5690      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5691           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5692   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5693   "stm%?ia\\t%1, {%2, %3, %4}"
5694   [(set_attr "predicable" "yes")
5695    (set_attr "type" "store3")]
5696 )
5697
5698 (define_insn "*stmsi2"
5699   [(match_parallel 0 "store_multiple_operation"
5700     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5701           (match_operand:SI 2 "arm_hard_register_operand" ""))
5702      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5703           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5704   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5705   "stm%?ia\\t%1, {%2, %3}"
5706   [(set_attr "predicable" "yes")
5707    (set_attr "type" "store2")]
5708 )
5709
5710 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5711 ;; We could let this apply for blocks of less than this, but it clobbers so
5712 ;; many registers that there is then probably a better way.
5713
5714 (define_expand "movmemqi"
5715   [(match_operand:BLK 0 "general_operand" "")
5716    (match_operand:BLK 1 "general_operand" "")
5717    (match_operand:SI 2 "const_int_operand" "")
5718    (match_operand:SI 3 "const_int_operand" "")]
5719   "TARGET_EITHER"
5720   "
5721   if (TARGET_ARM)
5722     {
5723       if (arm_gen_movmemqi (operands))
5724         DONE;
5725       FAIL;
5726     }
5727   else /* TARGET_THUMB */
5728     {
5729       if (   INTVAL (operands[3]) != 4
5730           || INTVAL (operands[2]) > 48)
5731         FAIL;
5732
5733       thumb_expand_movmemqi (operands);
5734       DONE;
5735     }
5736   "
5737 )
5738
5739 ;; Thumb block-move insns
5740
5741 (define_insn "movmem12b"
5742   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5743         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5744    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5745         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5746    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5747         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5748    (set (match_operand:SI 0 "register_operand" "=l")
5749         (plus:SI (match_dup 2) (const_int 12)))
5750    (set (match_operand:SI 1 "register_operand" "=l")
5751         (plus:SI (match_dup 3) (const_int 12)))
5752    (clobber (match_scratch:SI 4 "=&l"))
5753    (clobber (match_scratch:SI 5 "=&l"))
5754    (clobber (match_scratch:SI 6 "=&l"))]
5755   "TARGET_THUMB"
5756   "* return thumb_output_move_mem_multiple (3, operands);"
5757   [(set_attr "length" "4")
5758    ; This isn't entirely accurate...  It loads as well, but in terms of
5759    ; scheduling the following insn it is better to consider it as a store
5760    (set_attr "type" "store3")]
5761 )
5762
5763 (define_insn "movmem8b"
5764   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5765         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5766    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5767         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5768    (set (match_operand:SI 0 "register_operand" "=l")
5769         (plus:SI (match_dup 2) (const_int 8)))
5770    (set (match_operand:SI 1 "register_operand" "=l")
5771         (plus:SI (match_dup 3) (const_int 8)))
5772    (clobber (match_scratch:SI 4 "=&l"))
5773    (clobber (match_scratch:SI 5 "=&l"))]
5774   "TARGET_THUMB"
5775   "* return thumb_output_move_mem_multiple (2, operands);"
5776   [(set_attr "length" "4")
5777    ; This isn't entirely accurate...  It loads as well, but in terms of
5778    ; scheduling the following insn it is better to consider it as a store
5779    (set_attr "type" "store2")]
5780 )
5781
5782 \f
5783
5784 ;; Compare & branch insns
5785 ;; The range calculations are based as follows:
5786 ;; For forward branches, the address calculation returns the address of
5787 ;; the next instruction.  This is 2 beyond the branch instruction.
5788 ;; For backward branches, the address calculation returns the address of
5789 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5790 ;; instruction for the shortest sequence, and 4 before the branch instruction
5791 ;; if we have to jump around an unconditional branch.
5792 ;; To the basic branch range the PC offset must be added (this is +4).
5793 ;; So for forward branches we have 
5794 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5795 ;; And for backward branches we have 
5796 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5797 ;;
5798 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5799 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5800
5801 (define_expand "cbranchsi4"
5802   [(set (pc) (if_then_else
5803               (match_operator 0 "arm_comparison_operator"
5804                [(match_operand:SI 1 "s_register_operand" "")
5805                 (match_operand:SI 2 "nonmemory_operand" "")])
5806               (label_ref (match_operand 3 "" ""))
5807               (pc)))]
5808   "TARGET_THUMB"
5809   "
5810   if (thumb_cmpneg_operand (operands[2], SImode))
5811     {
5812       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5813                                               operands[3], operands[0]));
5814       DONE;
5815     }
5816   if (!thumb_cmp_operand (operands[2], SImode))
5817     operands[2] = force_reg (SImode, operands[2]);
5818   ")
5819
5820 (define_insn "*cbranchsi4_insn"
5821   [(set (pc) (if_then_else
5822               (match_operator 0 "arm_comparison_operator"
5823                [(match_operand:SI 1 "s_register_operand" "l,*h")
5824                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5825               (label_ref (match_operand 3 "" ""))
5826               (pc)))]
5827   "TARGET_THUMB"
5828   "*
5829   output_asm_insn (\"cmp\\t%1, %2\", operands);
5830
5831   switch (get_attr_length (insn))
5832     {
5833     case 4:  return \"b%d0\\t%l3\";
5834     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5835     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5836     }
5837   "
5838   [(set (attr "far_jump")
5839         (if_then_else
5840             (eq_attr "length" "8")
5841             (const_string "yes")
5842             (const_string "no")))
5843    (set (attr "length") 
5844         (if_then_else
5845             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5846                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5847             (const_int 4)
5848             (if_then_else
5849                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5850                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5851                 (const_int 6)
5852                 (const_int 8))))]
5853 )
5854
5855 (define_insn "cbranchsi4_scratch"
5856   [(set (pc) (if_then_else
5857               (match_operator 4 "arm_comparison_operator"
5858                [(match_operand:SI 1 "s_register_operand" "l,0")
5859                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5860               (label_ref (match_operand 3 "" ""))
5861               (pc)))
5862    (clobber (match_scratch:SI 0 "=l,l"))]
5863   "TARGET_THUMB"
5864   "*
5865   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5866
5867   switch (get_attr_length (insn))
5868     {
5869     case 4:  return \"b%d4\\t%l3\";
5870     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5871     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5872     }
5873   "
5874   [(set (attr "far_jump")
5875         (if_then_else
5876             (eq_attr "length" "8")
5877             (const_string "yes")
5878             (const_string "no")))
5879    (set (attr "length") 
5880         (if_then_else
5881             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5882                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5883             (const_int 4)
5884             (if_then_else
5885                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5886                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5887                 (const_int 6)
5888                 (const_int 8))))]
5889 )
5890 (define_insn "*movsi_cbranchsi4"
5891   [(set (pc)
5892         (if_then_else
5893          (match_operator 3 "arm_comparison_operator"
5894           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5895            (const_int 0)])
5896          (label_ref (match_operand 2 "" ""))
5897          (pc)))
5898    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5899         (match_dup 1))]
5900   "TARGET_THUMB"
5901   "*{
5902   if (which_alternative == 0)
5903     output_asm_insn (\"cmp\t%0, #0\", operands);
5904   else if (which_alternative == 1)
5905     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5906   else
5907     {
5908       output_asm_insn (\"cmp\t%1, #0\", operands);
5909       if (which_alternative == 2)
5910         output_asm_insn (\"mov\t%0, %1\", operands);
5911       else
5912         output_asm_insn (\"str\t%1, %0\", operands);
5913     }
5914   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5915     {
5916     case 4:  return \"b%d3\\t%l2\";
5917     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5918     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5919     }
5920   }"
5921   [(set (attr "far_jump")
5922         (if_then_else
5923             (ior (and (gt (symbol_ref ("which_alternative"))
5924                           (const_int 1))
5925                       (eq_attr "length" "8"))
5926                  (eq_attr "length" "10"))
5927             (const_string "yes")
5928             (const_string "no")))
5929    (set (attr "length")
5930      (if_then_else
5931        (le (symbol_ref ("which_alternative"))
5932                        (const_int 1))
5933        (if_then_else
5934          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5935               (le (minus (match_dup 2) (pc)) (const_int 256)))
5936          (const_int 4)
5937          (if_then_else
5938            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5939                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5940            (const_int 6)
5941            (const_int 8)))
5942        (if_then_else
5943          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5944               (le (minus (match_dup 2) (pc)) (const_int 256)))
5945          (const_int 6)
5946          (if_then_else
5947            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5948                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5949            (const_int 8)
5950            (const_int 10)))))]
5951 )
5952
5953 (define_insn "*negated_cbranchsi4"
5954   [(set (pc)
5955         (if_then_else
5956          (match_operator 0 "equality_operator"
5957           [(match_operand:SI 1 "s_register_operand" "l")
5958            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5959          (label_ref (match_operand 3 "" ""))
5960          (pc)))]
5961   "TARGET_THUMB"
5962   "*
5963   output_asm_insn (\"cmn\\t%1, %2\", operands);
5964   switch (get_attr_length (insn))
5965     {
5966     case 4:  return \"b%d0\\t%l3\";
5967     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5968     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5969     }
5970   "
5971   [(set (attr "far_jump")
5972         (if_then_else
5973             (eq_attr "length" "8")
5974             (const_string "yes")
5975             (const_string "no")))
5976    (set (attr "length") 
5977         (if_then_else
5978             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5979                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5980             (const_int 4)
5981             (if_then_else
5982                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5983                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5984                 (const_int 6)
5985                 (const_int 8))))]
5986 )
5987
5988 (define_insn "*tbit_cbranch"
5989   [(set (pc)
5990         (if_then_else
5991          (match_operator 0 "equality_operator"
5992           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5993                             (const_int 1)
5994                             (match_operand:SI 2 "const_int_operand" "i"))
5995            (const_int 0)])
5996          (label_ref (match_operand 3 "" ""))
5997          (pc)))
5998    (clobber (match_scratch:SI 4 "=l"))]
5999   "TARGET_THUMB"
6000   "*
6001   {
6002   rtx op[3];
6003   op[0] = operands[4];
6004   op[1] = operands[1];
6005   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6006
6007   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6008   switch (get_attr_length (insn))
6009     {
6010     case 4:  return \"b%d0\\t%l3\";
6011     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6012     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6013     }
6014   }"
6015   [(set (attr "far_jump")
6016         (if_then_else
6017             (eq_attr "length" "8")
6018             (const_string "yes")
6019             (const_string "no")))
6020    (set (attr "length") 
6021         (if_then_else
6022             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6023                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6024             (const_int 4)
6025             (if_then_else
6026                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6027                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6028                 (const_int 6)
6029                 (const_int 8))))]
6030 )
6031   
6032 (define_insn "*tlobits_cbranch"
6033   [(set (pc)
6034         (if_then_else
6035          (match_operator 0 "equality_operator"
6036           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6037                             (match_operand:SI 2 "const_int_operand" "i")
6038                             (const_int 0))
6039            (const_int 0)])
6040          (label_ref (match_operand 3 "" ""))
6041          (pc)))
6042    (clobber (match_scratch:SI 4 "=l"))]
6043   "TARGET_THUMB"
6044   "*
6045   {
6046   rtx op[3];
6047   op[0] = operands[4];
6048   op[1] = operands[1];
6049   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6050
6051   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6052   switch (get_attr_length (insn))
6053     {
6054     case 4:  return \"b%d0\\t%l3\";
6055     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6056     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6057     }
6058   }"
6059   [(set (attr "far_jump")
6060         (if_then_else
6061             (eq_attr "length" "8")
6062             (const_string "yes")
6063             (const_string "no")))
6064    (set (attr "length") 
6065         (if_then_else
6066             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6067                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6068             (const_int 4)
6069             (if_then_else
6070                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6071                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6072                 (const_int 6)
6073                 (const_int 8))))]
6074 )
6075   
6076 (define_insn "*tstsi3_cbranch"
6077   [(set (pc)
6078         (if_then_else
6079          (match_operator 3 "equality_operator"
6080           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6081                    (match_operand:SI 1 "s_register_operand" "l"))
6082            (const_int 0)])
6083          (label_ref (match_operand 2 "" ""))
6084          (pc)))]
6085   "TARGET_THUMB"
6086   "*
6087   {
6088   output_asm_insn (\"tst\\t%0, %1\", operands);
6089   switch (get_attr_length (insn))
6090     {
6091     case 4:  return \"b%d3\\t%l2\";
6092     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6093     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6094     }
6095   }"
6096   [(set (attr "far_jump")
6097         (if_then_else
6098             (eq_attr "length" "8")
6099             (const_string "yes")
6100             (const_string "no")))
6101    (set (attr "length") 
6102         (if_then_else
6103             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6104                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6105             (const_int 4)
6106             (if_then_else
6107                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6108                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6109                 (const_int 6)
6110                 (const_int 8))))]
6111 )
6112   
6113 (define_insn "*andsi3_cbranch"
6114   [(set (pc)
6115         (if_then_else
6116          (match_operator 5 "equality_operator"
6117           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6118                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6119            (const_int 0)])
6120          (label_ref (match_operand 4 "" ""))
6121          (pc)))
6122    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6123         (and:SI (match_dup 2) (match_dup 3)))
6124    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6125   "TARGET_THUMB"
6126   "*
6127   {
6128   if (which_alternative == 0)
6129     output_asm_insn (\"and\\t%0, %3\", operands);
6130   else if (which_alternative == 1)
6131     {
6132       output_asm_insn (\"and\\t%1, %3\", operands);
6133       output_asm_insn (\"mov\\t%0, %1\", operands);
6134     }
6135   else
6136     {
6137       output_asm_insn (\"and\\t%1, %3\", operands);
6138       output_asm_insn (\"str\\t%1, %0\", operands);
6139     }
6140
6141   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6142     {
6143     case 4:  return \"b%d5\\t%l4\";
6144     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6145     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6146     }
6147   }"
6148   [(set (attr "far_jump")
6149         (if_then_else
6150             (ior (and (eq (symbol_ref ("which_alternative"))
6151                           (const_int 0))
6152                       (eq_attr "length" "8"))
6153                  (eq_attr "length" "10"))
6154             (const_string "yes")
6155             (const_string "no")))
6156    (set (attr "length")
6157      (if_then_else
6158        (eq (symbol_ref ("which_alternative"))
6159                        (const_int 0))
6160        (if_then_else
6161          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6162               (le (minus (match_dup 4) (pc)) (const_int 256)))
6163          (const_int 4)
6164          (if_then_else
6165            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6166                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6167            (const_int 6)
6168            (const_int 8)))
6169        (if_then_else
6170          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6171               (le (minus (match_dup 4) (pc)) (const_int 256)))
6172          (const_int 6)
6173          (if_then_else
6174            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6175                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6176            (const_int 8)
6177            (const_int 10)))))]
6178 )
6179
6180 (define_insn "*orrsi3_cbranch_scratch"
6181   [(set (pc)
6182         (if_then_else
6183          (match_operator 4 "equality_operator"
6184           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6185                    (match_operand:SI 2 "s_register_operand" "l"))
6186            (const_int 0)])
6187          (label_ref (match_operand 3 "" ""))
6188          (pc)))
6189    (clobber (match_scratch:SI 0 "=l"))]
6190   "TARGET_THUMB"
6191   "*
6192   {
6193   output_asm_insn (\"orr\\t%0, %2\", operands);
6194   switch (get_attr_length (insn))
6195     {
6196     case 4:  return \"b%d4\\t%l3\";
6197     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6198     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6199     }
6200   }"
6201   [(set (attr "far_jump")
6202         (if_then_else
6203             (eq_attr "length" "8")
6204             (const_string "yes")
6205             (const_string "no")))
6206    (set (attr "length") 
6207         (if_then_else
6208             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6209                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6210             (const_int 4)
6211             (if_then_else
6212                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6213                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6214                 (const_int 6)
6215                 (const_int 8))))]
6216 )
6217   
6218 (define_insn "*orrsi3_cbranch"
6219   [(set (pc)
6220         (if_then_else
6221          (match_operator 5 "equality_operator"
6222           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6223                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6224            (const_int 0)])
6225          (label_ref (match_operand 4 "" ""))
6226          (pc)))
6227    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6228         (ior:SI (match_dup 2) (match_dup 3)))
6229    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6230   "TARGET_THUMB"
6231   "*
6232   {
6233   if (which_alternative == 0)
6234     output_asm_insn (\"orr\\t%0, %3\", operands);
6235   else if (which_alternative == 1)
6236     {
6237       output_asm_insn (\"orr\\t%1, %3\", operands);
6238       output_asm_insn (\"mov\\t%0, %1\", operands);
6239     }
6240   else
6241     {
6242       output_asm_insn (\"orr\\t%1, %3\", operands);
6243       output_asm_insn (\"str\\t%1, %0\", operands);
6244     }
6245
6246   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6247     {
6248     case 4:  return \"b%d5\\t%l4\";
6249     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6250     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6251     }
6252   }"
6253   [(set (attr "far_jump")
6254         (if_then_else
6255             (ior (and (eq (symbol_ref ("which_alternative"))
6256                           (const_int 0))
6257                       (eq_attr "length" "8"))
6258                  (eq_attr "length" "10"))
6259             (const_string "yes")
6260             (const_string "no")))
6261    (set (attr "length")
6262      (if_then_else
6263        (eq (symbol_ref ("which_alternative"))
6264                        (const_int 0))
6265        (if_then_else
6266          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6267               (le (minus (match_dup 4) (pc)) (const_int 256)))
6268          (const_int 4)
6269          (if_then_else
6270            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6271                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6272            (const_int 6)
6273            (const_int 8)))
6274        (if_then_else
6275          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6276               (le (minus (match_dup 4) (pc)) (const_int 256)))
6277          (const_int 6)
6278          (if_then_else
6279            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6280                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6281            (const_int 8)
6282            (const_int 10)))))]
6283 )
6284
6285 (define_insn "*xorsi3_cbranch_scratch"
6286   [(set (pc)
6287         (if_then_else
6288          (match_operator 4 "equality_operator"
6289           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6290                    (match_operand:SI 2 "s_register_operand" "l"))
6291            (const_int 0)])
6292          (label_ref (match_operand 3 "" ""))
6293          (pc)))
6294    (clobber (match_scratch:SI 0 "=l"))]
6295   "TARGET_THUMB"
6296   "*
6297   {
6298   output_asm_insn (\"eor\\t%0, %2\", operands);
6299   switch (get_attr_length (insn))
6300     {
6301     case 4:  return \"b%d4\\t%l3\";
6302     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6303     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6304     }
6305   }"
6306   [(set (attr "far_jump")
6307         (if_then_else
6308             (eq_attr "length" "8")
6309             (const_string "yes")
6310             (const_string "no")))
6311    (set (attr "length") 
6312         (if_then_else
6313             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6314                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6315             (const_int 4)
6316             (if_then_else
6317                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6318                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6319                 (const_int 6)
6320                 (const_int 8))))]
6321 )
6322   
6323 (define_insn "*xorsi3_cbranch"
6324   [(set (pc)
6325         (if_then_else
6326          (match_operator 5 "equality_operator"
6327           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6328                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6329            (const_int 0)])
6330          (label_ref (match_operand 4 "" ""))
6331          (pc)))
6332    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6333         (xor:SI (match_dup 2) (match_dup 3)))
6334    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6335   "TARGET_THUMB"
6336   "*
6337   {
6338   if (which_alternative == 0)
6339     output_asm_insn (\"eor\\t%0, %3\", operands);
6340   else if (which_alternative == 1)
6341     {
6342       output_asm_insn (\"eor\\t%1, %3\", operands);
6343       output_asm_insn (\"mov\\t%0, %1\", operands);
6344     }
6345   else
6346     {
6347       output_asm_insn (\"eor\\t%1, %3\", operands);
6348       output_asm_insn (\"str\\t%1, %0\", operands);
6349     }
6350
6351   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6352     {
6353     case 4:  return \"b%d5\\t%l4\";
6354     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6355     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6356     }
6357   }"
6358   [(set (attr "far_jump")
6359         (if_then_else
6360             (ior (and (eq (symbol_ref ("which_alternative"))
6361                           (const_int 0))
6362                       (eq_attr "length" "8"))
6363                  (eq_attr "length" "10"))
6364             (const_string "yes")
6365             (const_string "no")))
6366    (set (attr "length")
6367      (if_then_else
6368        (eq (symbol_ref ("which_alternative"))
6369                        (const_int 0))
6370        (if_then_else
6371          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6372               (le (minus (match_dup 4) (pc)) (const_int 256)))
6373          (const_int 4)
6374          (if_then_else
6375            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6376                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6377            (const_int 6)
6378            (const_int 8)))
6379        (if_then_else
6380          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6381               (le (minus (match_dup 4) (pc)) (const_int 256)))
6382          (const_int 6)
6383          (if_then_else
6384            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6385                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6386            (const_int 8)
6387            (const_int 10)))))]
6388 )
6389
6390 (define_insn "*bicsi3_cbranch_scratch"
6391   [(set (pc)
6392         (if_then_else
6393          (match_operator 4 "equality_operator"
6394           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6395                    (match_operand:SI 1 "s_register_operand" "0"))
6396            (const_int 0)])
6397          (label_ref (match_operand 3 "" ""))
6398          (pc)))
6399    (clobber (match_scratch:SI 0 "=l"))]
6400   "TARGET_THUMB"
6401   "*
6402   {
6403   output_asm_insn (\"bic\\t%0, %2\", operands);
6404   switch (get_attr_length (insn))
6405     {
6406     case 4:  return \"b%d4\\t%l3\";
6407     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6408     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6409     }
6410   }"
6411   [(set (attr "far_jump")
6412         (if_then_else
6413             (eq_attr "length" "8")
6414             (const_string "yes")
6415             (const_string "no")))
6416    (set (attr "length") 
6417         (if_then_else
6418             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6419                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6420             (const_int 4)
6421             (if_then_else
6422                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6423                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6424                 (const_int 6)
6425                 (const_int 8))))]
6426 )
6427   
6428 (define_insn "*bicsi3_cbranch"
6429   [(set (pc)
6430         (if_then_else
6431          (match_operator 5 "equality_operator"
6432           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6433                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6434            (const_int 0)])
6435          (label_ref (match_operand 4 "" ""))
6436          (pc)))
6437    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6438         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6439    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6440   "TARGET_THUMB"
6441   "*
6442   {
6443   if (which_alternative == 0)
6444     output_asm_insn (\"bic\\t%0, %3\", operands);
6445   else if (which_alternative <= 2)
6446     {
6447       output_asm_insn (\"bic\\t%1, %3\", operands);
6448       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6449          conditions again, since we're only testing for equality.  */
6450       output_asm_insn (\"mov\\t%0, %1\", operands);
6451     }
6452   else
6453     {
6454       output_asm_insn (\"bic\\t%1, %3\", operands);
6455       output_asm_insn (\"str\\t%1, %0\", operands);
6456     }
6457
6458   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6459     {
6460     case 4:  return \"b%d5\\t%l4\";
6461     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6462     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6463     }
6464   }"
6465   [(set (attr "far_jump")
6466         (if_then_else
6467             (ior (and (eq (symbol_ref ("which_alternative"))
6468                           (const_int 0))
6469                       (eq_attr "length" "8"))
6470                  (eq_attr "length" "10"))
6471             (const_string "yes")
6472             (const_string "no")))
6473    (set (attr "length")
6474      (if_then_else
6475        (eq (symbol_ref ("which_alternative"))
6476                        (const_int 0))
6477        (if_then_else
6478          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6479               (le (minus (match_dup 4) (pc)) (const_int 256)))
6480          (const_int 4)
6481          (if_then_else
6482            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6483                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6484            (const_int 6)
6485            (const_int 8)))
6486        (if_then_else
6487          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6488               (le (minus (match_dup 4) (pc)) (const_int 256)))
6489          (const_int 6)
6490          (if_then_else
6491            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6492                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6493            (const_int 8)
6494            (const_int 10)))))]
6495 )
6496
6497 (define_insn "*cbranchne_decr1"
6498   [(set (pc)
6499         (if_then_else (match_operator 3 "equality_operator"
6500                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6501                         (const_int 0)])
6502                       (label_ref (match_operand 4 "" ""))
6503                       (pc)))
6504    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6505         (plus:SI (match_dup 2) (const_int -1)))
6506    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6507   "TARGET_THUMB"
6508   "*
6509    {
6510      rtx cond[2];
6511      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6512                                 ? GEU : LTU),
6513                                VOIDmode, operands[2], const1_rtx);
6514      cond[1] = operands[4];
6515
6516      if (which_alternative == 0)
6517        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6518      else if (which_alternative == 1)
6519        {
6520          /* We must provide an alternative for a hi reg because reload 
6521             cannot handle output reloads on a jump instruction, but we
6522             can't subtract into that.  Fortunately a mov from lo to hi
6523             does not clobber the condition codes.  */
6524          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6525          output_asm_insn (\"mov\\t%0, %1\", operands);
6526        }
6527      else
6528        {
6529          /* Similarly, but the target is memory.  */
6530          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6531          output_asm_insn (\"str\\t%1, %0\", operands);
6532        }
6533
6534      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6535        {
6536          case 4:
6537            output_asm_insn (\"b%d0\\t%l1\", cond);
6538            return \"\";
6539          case 6:
6540            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6541            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6542          default:
6543            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6544            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6545        }
6546    }
6547   "
6548   [(set (attr "far_jump")
6549         (if_then_else
6550             (ior (and (eq (symbol_ref ("which_alternative"))
6551                           (const_int 0))
6552                       (eq_attr "length" "8"))
6553                  (eq_attr "length" "10"))
6554             (const_string "yes")
6555             (const_string "no")))
6556    (set_attr_alternative "length"
6557       [
6558        ;; Alternative 0
6559        (if_then_else
6560          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6561               (le (minus (match_dup 4) (pc)) (const_int 256)))
6562          (const_int 4)
6563          (if_then_else
6564            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6565                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6566            (const_int 6)
6567            (const_int 8)))
6568        ;; Alternative 1
6569        (if_then_else
6570          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6571               (le (minus (match_dup 4) (pc)) (const_int 256)))
6572          (const_int 6)
6573          (if_then_else
6574            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6575                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6576            (const_int 8)
6577            (const_int 10)))
6578        ;; Alternative 2
6579        (if_then_else
6580          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6581               (le (minus (match_dup 4) (pc)) (const_int 256)))
6582          (const_int 6)
6583          (if_then_else
6584            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6585                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6586            (const_int 8)
6587            (const_int 10)))
6588        ;; Alternative 3
6589        (if_then_else
6590          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6591               (le (minus (match_dup 4) (pc)) (const_int 256)))
6592          (const_int 6)
6593          (if_then_else
6594            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6595                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6596            (const_int 8)
6597            (const_int 10)))])]
6598 )
6599
6600 (define_insn "*addsi3_cbranch"
6601   [(set (pc)
6602         (if_then_else
6603          (match_operator 4 "comparison_operator"
6604           [(plus:SI
6605             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6606             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6607            (const_int 0)])
6608          (label_ref (match_operand 5 "" ""))
6609          (pc)))
6610    (set
6611     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6612     (plus:SI (match_dup 2) (match_dup 3)))
6613    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6614   "TARGET_THUMB
6615    && (GET_CODE (operands[4]) == EQ
6616        || GET_CODE (operands[4]) == NE
6617        || GET_CODE (operands[4]) == GE
6618        || GET_CODE (operands[4]) == LT)"
6619   "*
6620    {
6621      rtx cond[3];
6622
6623      
6624      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6625      cond[1] = operands[2];
6626      cond[2] = operands[3];
6627
6628      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6629        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6630      else
6631        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6632
6633      if (which_alternative >= 3
6634          && which_alternative < 4)
6635        output_asm_insn (\"mov\\t%0, %1\", operands);
6636      else if (which_alternative >= 4)
6637        output_asm_insn (\"str\\t%1, %0\", operands);
6638
6639      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6640        {
6641          case 4:
6642            return \"b%d4\\t%l5\";
6643          case 6:
6644            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6645          default:
6646            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6647        }
6648    }
6649   "
6650   [(set (attr "far_jump")
6651         (if_then_else
6652             (ior (and (lt (symbol_ref ("which_alternative"))
6653                           (const_int 3))
6654                       (eq_attr "length" "8"))
6655                  (eq_attr "length" "10"))
6656             (const_string "yes")
6657             (const_string "no")))
6658    (set (attr "length")
6659      (if_then_else
6660        (lt (symbol_ref ("which_alternative"))
6661                        (const_int 3))
6662        (if_then_else
6663          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6664               (le (minus (match_dup 5) (pc)) (const_int 256)))
6665          (const_int 4)
6666          (if_then_else
6667            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6668                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6669            (const_int 6)
6670            (const_int 8)))
6671        (if_then_else
6672          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6673               (le (minus (match_dup 5) (pc)) (const_int 256)))
6674          (const_int 6)
6675          (if_then_else
6676            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6677                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6678            (const_int 8)
6679            (const_int 10)))))]
6680 )
6681
6682 (define_insn "*addsi3_cbranch_scratch"
6683   [(set (pc)
6684         (if_then_else
6685          (match_operator 3 "comparison_operator"
6686           [(plus:SI
6687             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6688             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6689            (const_int 0)])
6690          (label_ref (match_operand 4 "" ""))
6691          (pc)))
6692    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6693   "TARGET_THUMB
6694    && (GET_CODE (operands[3]) == EQ
6695        || GET_CODE (operands[3]) == NE
6696        || GET_CODE (operands[3]) == GE
6697        || GET_CODE (operands[3]) == LT)"
6698   "*
6699    {
6700      switch (which_alternative)
6701        {
6702        case 0:
6703          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6704          break;
6705        case 1:
6706          output_asm_insn (\"cmn\t%1, %2\", operands);
6707          break;
6708        case 2:
6709          if (INTVAL (operands[2]) < 0)
6710            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6711          else
6712            output_asm_insn (\"add\t%0, %1, %2\", operands);
6713          break;
6714        case 3:
6715          if (INTVAL (operands[2]) < 0)
6716            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6717          else
6718            output_asm_insn (\"add\t%0, %0, %2\", operands);
6719          break;
6720        }
6721
6722      switch (get_attr_length (insn))
6723        {
6724          case 4:
6725            return \"b%d3\\t%l4\";
6726          case 6:
6727            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6728          default:
6729            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6730        }
6731    }
6732   "
6733   [(set (attr "far_jump")
6734         (if_then_else
6735             (eq_attr "length" "8")
6736             (const_string "yes")
6737             (const_string "no")))
6738    (set (attr "length")
6739        (if_then_else
6740          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6741               (le (minus (match_dup 4) (pc)) (const_int 256)))
6742          (const_int 4)
6743          (if_then_else
6744            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6745                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6746            (const_int 6)
6747            (const_int 8))))]
6748 )
6749
6750 (define_insn "*subsi3_cbranch"
6751   [(set (pc)
6752         (if_then_else
6753          (match_operator 4 "comparison_operator"
6754           [(minus:SI
6755             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6756             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6757            (const_int 0)])
6758          (label_ref (match_operand 5 "" ""))
6759          (pc)))
6760    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6761         (minus:SI (match_dup 2) (match_dup 3)))
6762    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6763   "TARGET_THUMB
6764    && (GET_CODE (operands[4]) == EQ
6765        || GET_CODE (operands[4]) == NE
6766        || GET_CODE (operands[4]) == GE
6767        || GET_CODE (operands[4]) == LT)"
6768   "*
6769    {
6770      if (which_alternative == 0)
6771        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6772      else if (which_alternative == 1)
6773        {
6774          /* We must provide an alternative for a hi reg because reload 
6775             cannot handle output reloads on a jump instruction, but we
6776             can't subtract into that.  Fortunately a mov from lo to hi
6777             does not clobber the condition codes.  */
6778          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6779          output_asm_insn (\"mov\\t%0, %1\", operands);
6780        }
6781      else
6782        {
6783          /* Similarly, but the target is memory.  */
6784          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6785          output_asm_insn (\"str\\t%1, %0\", operands);
6786        }
6787
6788      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6789        {
6790          case 4:
6791            return \"b%d4\\t%l5\";
6792          case 6:
6793            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6794          default:
6795            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6796        }
6797    }
6798   "
6799   [(set (attr "far_jump")
6800         (if_then_else
6801             (ior (and (eq (symbol_ref ("which_alternative"))
6802                           (const_int 0))
6803                       (eq_attr "length" "8"))
6804                  (eq_attr "length" "10"))
6805             (const_string "yes")
6806             (const_string "no")))
6807    (set (attr "length")
6808      (if_then_else
6809        (eq (symbol_ref ("which_alternative"))
6810                        (const_int 0))
6811        (if_then_else
6812          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6813               (le (minus (match_dup 5) (pc)) (const_int 256)))
6814          (const_int 4)
6815          (if_then_else
6816            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6817                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6818            (const_int 6)
6819            (const_int 8)))
6820        (if_then_else
6821          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6822               (le (minus (match_dup 5) (pc)) (const_int 256)))
6823          (const_int 6)
6824          (if_then_else
6825            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6826                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6827            (const_int 8)
6828            (const_int 10)))))]
6829 )
6830
6831 (define_insn "*subsi3_cbranch_scratch"
6832   [(set (pc)
6833         (if_then_else
6834          (match_operator 0 "arm_comparison_operator"
6835           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6836                      (match_operand:SI 2 "nonmemory_operand" "l"))
6837            (const_int 0)])
6838          (label_ref (match_operand 3 "" ""))
6839          (pc)))]
6840   "TARGET_THUMB
6841    && (GET_CODE (operands[0]) == EQ
6842        || GET_CODE (operands[0]) == NE
6843        || GET_CODE (operands[0]) == GE
6844        || GET_CODE (operands[0]) == LT)"
6845   "*
6846   output_asm_insn (\"cmp\\t%1, %2\", operands);
6847   switch (get_attr_length (insn))
6848     {
6849     case 4:  return \"b%d0\\t%l3\";
6850     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6851     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6852     }
6853   "
6854   [(set (attr "far_jump")
6855         (if_then_else
6856             (eq_attr "length" "8")
6857             (const_string "yes")
6858             (const_string "no")))
6859    (set (attr "length") 
6860         (if_then_else
6861             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6862                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6863             (const_int 4)
6864             (if_then_else
6865                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6866                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6867                 (const_int 6)
6868                 (const_int 8))))]
6869 )
6870
6871 ;; Comparison and test insns
6872
6873 (define_expand "cmpsi"
6874   [(match_operand:SI 0 "s_register_operand" "")
6875    (match_operand:SI 1 "arm_add_operand" "")]
6876   "TARGET_ARM"
6877   "{
6878     arm_compare_op0 = operands[0];
6879     arm_compare_op1 = operands[1];
6880     DONE;
6881   }"
6882 )
6883
6884 (define_expand "cmpsf"
6885   [(match_operand:SF 0 "s_register_operand" "")
6886    (match_operand:SF 1 "arm_float_compare_operand" "")]
6887   "TARGET_ARM && TARGET_HARD_FLOAT"
6888   "
6889   arm_compare_op0 = operands[0];
6890   arm_compare_op1 = operands[1];
6891   DONE;
6892   "
6893 )
6894
6895 (define_expand "cmpdf"
6896   [(match_operand:DF 0 "s_register_operand" "")
6897    (match_operand:DF 1 "arm_float_compare_operand" "")]
6898   "TARGET_ARM && TARGET_HARD_FLOAT"
6899   "
6900   arm_compare_op0 = operands[0];
6901   arm_compare_op1 = operands[1];
6902   DONE;
6903   "
6904 )
6905
6906 (define_insn "*arm_cmpsi_insn"
6907   [(set (reg:CC CC_REGNUM)
6908         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6909                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6910   "TARGET_ARM"
6911   "@
6912    cmp%?\\t%0, %1
6913    cmn%?\\t%0, #%n1"
6914   [(set_attr "conds" "set")]
6915 )
6916
6917 (define_insn "*cmpsi_shiftsi"
6918   [(set (reg:CC CC_REGNUM)
6919         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6920                     (match_operator:SI  3 "shift_operator"
6921                      [(match_operand:SI 1 "s_register_operand" "r")
6922                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6923   "TARGET_ARM"
6924   "cmp%?\\t%0, %1%S3"
6925   [(set_attr "conds" "set")
6926    (set_attr "shift" "1")
6927    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6928                       (const_string "alu_shift")
6929                       (const_string "alu_shift_reg")))]
6930 )
6931
6932 (define_insn "*cmpsi_shiftsi_swp"
6933   [(set (reg:CC_SWP CC_REGNUM)
6934         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6935                          [(match_operand:SI 1 "s_register_operand" "r")
6936                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6937                         (match_operand:SI 0 "s_register_operand" "r")))]
6938   "TARGET_ARM"
6939   "cmp%?\\t%0, %1%S3"
6940   [(set_attr "conds" "set")
6941    (set_attr "shift" "1")
6942    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6943                       (const_string "alu_shift")
6944                       (const_string "alu_shift_reg")))]
6945 )
6946
6947 (define_insn "*cmpsi_negshiftsi_si"
6948   [(set (reg:CC_Z CC_REGNUM)
6949         (compare:CC_Z
6950          (neg:SI (match_operator:SI 1 "shift_operator"
6951                     [(match_operand:SI 2 "s_register_operand" "r")
6952                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6953          (match_operand:SI 0 "s_register_operand" "r")))]
6954   "TARGET_ARM"
6955   "cmn%?\\t%0, %2%S1"
6956   [(set_attr "conds" "set")
6957    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6958                                     (const_string "alu_shift")
6959                                     (const_string "alu_shift_reg")))]
6960 )
6961
6962 ;; Cirrus SF compare instruction
6963 (define_insn "*cirrus_cmpsf"
6964   [(set (reg:CCFP CC_REGNUM)
6965         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6966                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6967   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6968   "cfcmps%?\\tr15, %V0, %V1"
6969   [(set_attr "type"   "mav_farith")
6970    (set_attr "cirrus" "compare")]
6971 )
6972
6973 ;; Cirrus DF compare instruction
6974 (define_insn "*cirrus_cmpdf"
6975   [(set (reg:CCFP CC_REGNUM)
6976         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6977                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6978   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6979   "cfcmpd%?\\tr15, %V0, %V1"
6980   [(set_attr "type"   "mav_farith")
6981    (set_attr "cirrus" "compare")]
6982 )
6983
6984 ;; Cirrus DI compare instruction
6985 (define_expand "cmpdi"
6986   [(match_operand:DI 0 "cirrus_fp_register" "")
6987    (match_operand:DI 1 "cirrus_fp_register" "")]
6988   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6989   "{
6990      arm_compare_op0 = operands[0];
6991      arm_compare_op1 = operands[1];
6992      DONE;
6993    }")
6994
6995 (define_insn "*cirrus_cmpdi"
6996   [(set (reg:CC CC_REGNUM)
6997         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6998                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6999   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7000   "cfcmp64%?\\tr15, %V0, %V1"
7001   [(set_attr "type"   "mav_farith")
7002    (set_attr "cirrus" "compare")]
7003 )
7004
7005 ; This insn allows redundant compares to be removed by cse, nothing should
7006 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7007 ; is deleted later on. The match_dup will match the mode here, so that
7008 ; mode changes of the condition codes aren't lost by this even though we don't
7009 ; specify what they are.
7010
7011 (define_insn "*deleted_compare"
7012   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7013   "TARGET_ARM"
7014   "\\t%@ deleted compare"
7015   [(set_attr "conds" "set")
7016    (set_attr "length" "0")]
7017 )
7018
7019 \f
7020 ;; Conditional branch insns
7021
7022 (define_expand "beq"
7023   [(set (pc)
7024         (if_then_else (eq (match_dup 1) (const_int 0))
7025                       (label_ref (match_operand 0 "" ""))
7026                       (pc)))]
7027   "TARGET_ARM"
7028   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7029 )
7030
7031 (define_expand "bne"
7032   [(set (pc)
7033         (if_then_else (ne (match_dup 1) (const_int 0))
7034                       (label_ref (match_operand 0 "" ""))
7035                       (pc)))]
7036   "TARGET_ARM"
7037   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7038 )
7039
7040 (define_expand "bgt"
7041   [(set (pc)
7042         (if_then_else (gt (match_dup 1) (const_int 0))
7043                       (label_ref (match_operand 0 "" ""))
7044                       (pc)))]
7045   "TARGET_ARM"
7046   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7047 )
7048
7049 (define_expand "ble"
7050   [(set (pc)
7051         (if_then_else (le (match_dup 1) (const_int 0))
7052                       (label_ref (match_operand 0 "" ""))
7053                       (pc)))]
7054   "TARGET_ARM"
7055   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7056 )
7057
7058 (define_expand "bge"
7059   [(set (pc)
7060         (if_then_else (ge (match_dup 1) (const_int 0))
7061                       (label_ref (match_operand 0 "" ""))
7062                       (pc)))]
7063   "TARGET_ARM"
7064   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7065 )
7066
7067 (define_expand "blt"
7068   [(set (pc)
7069         (if_then_else (lt (match_dup 1) (const_int 0))
7070                       (label_ref (match_operand 0 "" ""))
7071                       (pc)))]
7072   "TARGET_ARM"
7073   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7074 )
7075
7076 (define_expand "bgtu"
7077   [(set (pc)
7078         (if_then_else (gtu (match_dup 1) (const_int 0))
7079                       (label_ref (match_operand 0 "" ""))
7080                       (pc)))]
7081   "TARGET_ARM"
7082   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7083 )
7084
7085 (define_expand "bleu"
7086   [(set (pc)
7087         (if_then_else (leu (match_dup 1) (const_int 0))
7088                       (label_ref (match_operand 0 "" ""))
7089                       (pc)))]
7090   "TARGET_ARM"
7091   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7092 )
7093
7094 (define_expand "bgeu"
7095   [(set (pc)
7096         (if_then_else (geu (match_dup 1) (const_int 0))
7097                       (label_ref (match_operand 0 "" ""))
7098                       (pc)))]
7099   "TARGET_ARM"
7100   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7101 )
7102
7103 (define_expand "bltu"
7104   [(set (pc)
7105         (if_then_else (ltu (match_dup 1) (const_int 0))
7106                       (label_ref (match_operand 0 "" ""))
7107                       (pc)))]
7108   "TARGET_ARM"
7109   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7110 )
7111
7112 (define_expand "bunordered"
7113   [(set (pc)
7114         (if_then_else (unordered (match_dup 1) (const_int 0))
7115                       (label_ref (match_operand 0 "" ""))
7116                       (pc)))]
7117   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7118   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7119                                       arm_compare_op1);"
7120 )
7121
7122 (define_expand "bordered"
7123   [(set (pc)
7124         (if_then_else (ordered (match_dup 1) (const_int 0))
7125                       (label_ref (match_operand 0 "" ""))
7126                       (pc)))]
7127   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7128   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7129                                       arm_compare_op1);"
7130 )
7131
7132 (define_expand "bungt"
7133   [(set (pc)
7134         (if_then_else (ungt (match_dup 1) (const_int 0))
7135                       (label_ref (match_operand 0 "" ""))
7136                       (pc)))]
7137   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7138   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7139 )
7140
7141 (define_expand "bunlt"
7142   [(set (pc)
7143         (if_then_else (unlt (match_dup 1) (const_int 0))
7144                       (label_ref (match_operand 0 "" ""))
7145                       (pc)))]
7146   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7147   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7148 )
7149
7150 (define_expand "bunge"
7151   [(set (pc)
7152         (if_then_else (unge (match_dup 1) (const_int 0))
7153                       (label_ref (match_operand 0 "" ""))
7154                       (pc)))]
7155   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7156   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7157 )
7158
7159 (define_expand "bunle"
7160   [(set (pc)
7161         (if_then_else (unle (match_dup 1) (const_int 0))
7162                       (label_ref (match_operand 0 "" ""))
7163                       (pc)))]
7164   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7165   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7166 )
7167
7168 ;; The following two patterns need two branch instructions, since there is
7169 ;; no single instruction that will handle all cases.
7170 (define_expand "buneq"
7171   [(set (pc)
7172         (if_then_else (uneq (match_dup 1) (const_int 0))
7173                       (label_ref (match_operand 0 "" ""))
7174                       (pc)))]
7175   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7176   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7177 )
7178
7179 (define_expand "bltgt"
7180   [(set (pc)
7181         (if_then_else (ltgt (match_dup 1) (const_int 0))
7182                       (label_ref (match_operand 0 "" ""))
7183                       (pc)))]
7184   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7185   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7186 )
7187
7188 ;;
7189 ;; Patterns to match conditional branch insns.
7190 ;;
7191
7192 ; Special pattern to match UNEQ.
7193 (define_insn "*arm_buneq"
7194   [(set (pc)
7195         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7196                       (label_ref (match_operand 0 "" ""))
7197                       (pc)))]
7198   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7199   "*
7200   gcc_assert (!arm_ccfsm_state);
7201
7202   return \"bvs\\t%l0\;beq\\t%l0\";
7203   "
7204   [(set_attr "conds" "jump_clob")
7205    (set_attr "length" "8")]
7206 )
7207
7208 ; Special pattern to match LTGT.
7209 (define_insn "*arm_bltgt"
7210   [(set (pc)
7211         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7212                       (label_ref (match_operand 0 "" ""))
7213                       (pc)))]
7214   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7215   "*
7216   gcc_assert (!arm_ccfsm_state);
7217
7218   return \"bmi\\t%l0\;bgt\\t%l0\";
7219   "
7220   [(set_attr "conds" "jump_clob")
7221    (set_attr "length" "8")]
7222 )
7223
7224 (define_insn "*arm_cond_branch"
7225   [(set (pc)
7226         (if_then_else (match_operator 1 "arm_comparison_operator"
7227                        [(match_operand 2 "cc_register" "") (const_int 0)])
7228                       (label_ref (match_operand 0 "" ""))
7229                       (pc)))]
7230   "TARGET_ARM"
7231   "*
7232   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7233     {
7234       arm_ccfsm_state += 2;
7235       return \"\";
7236     }
7237   return \"b%d1\\t%l0\";
7238   "
7239   [(set_attr "conds" "use")
7240    (set_attr "type" "branch")]
7241 )
7242
7243 ; Special pattern to match reversed UNEQ.
7244 (define_insn "*arm_buneq_reversed"
7245   [(set (pc)
7246         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7247                       (pc)
7248                       (label_ref (match_operand 0 "" ""))))]
7249   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7250   "*
7251   gcc_assert (!arm_ccfsm_state);
7252
7253   return \"bmi\\t%l0\;bgt\\t%l0\";
7254   "
7255   [(set_attr "conds" "jump_clob")
7256    (set_attr "length" "8")]
7257 )
7258
7259 ; Special pattern to match reversed LTGT.
7260 (define_insn "*arm_bltgt_reversed"
7261   [(set (pc)
7262         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7263                       (pc)
7264                       (label_ref (match_operand 0 "" ""))))]
7265   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266   "*
7267   gcc_assert (!arm_ccfsm_state);
7268
7269   return \"bvs\\t%l0\;beq\\t%l0\";
7270   "
7271   [(set_attr "conds" "jump_clob")
7272    (set_attr "length" "8")]
7273 )
7274
7275 (define_insn "*arm_cond_branch_reversed"
7276   [(set (pc)
7277         (if_then_else (match_operator 1 "arm_comparison_operator"
7278                        [(match_operand 2 "cc_register" "") (const_int 0)])
7279                       (pc)
7280                       (label_ref (match_operand 0 "" ""))))]
7281   "TARGET_ARM"
7282   "*
7283   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7284     {
7285       arm_ccfsm_state += 2;
7286       return \"\";
7287     }
7288   return \"b%D1\\t%l0\";
7289   "
7290   [(set_attr "conds" "use")
7291    (set_attr "type" "branch")]
7292 )
7293
7294 \f
7295
7296 ; scc insns
7297
7298 (define_expand "seq"
7299   [(set (match_operand:SI 0 "s_register_operand" "")
7300         (eq:SI (match_dup 1) (const_int 0)))]
7301   "TARGET_ARM"
7302   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7303 )
7304
7305 (define_expand "sne"
7306   [(set (match_operand:SI 0 "s_register_operand" "")
7307         (ne:SI (match_dup 1) (const_int 0)))]
7308   "TARGET_ARM"
7309   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7310 )
7311
7312 (define_expand "sgt"
7313   [(set (match_operand:SI 0 "s_register_operand" "")
7314         (gt:SI (match_dup 1) (const_int 0)))]
7315   "TARGET_ARM"
7316   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7317 )
7318
7319 (define_expand "sle"
7320   [(set (match_operand:SI 0 "s_register_operand" "")
7321         (le:SI (match_dup 1) (const_int 0)))]
7322   "TARGET_ARM"
7323   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7324 )
7325
7326 (define_expand "sge"
7327   [(set (match_operand:SI 0 "s_register_operand" "")
7328         (ge:SI (match_dup 1) (const_int 0)))]
7329   "TARGET_ARM"
7330   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7331 )
7332
7333 (define_expand "slt"
7334   [(set (match_operand:SI 0 "s_register_operand" "")
7335         (lt:SI (match_dup 1) (const_int 0)))]
7336   "TARGET_ARM"
7337   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7338 )
7339
7340 (define_expand "sgtu"
7341   [(set (match_operand:SI 0 "s_register_operand" "")
7342         (gtu:SI (match_dup 1) (const_int 0)))]
7343   "TARGET_ARM"
7344   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7345 )
7346
7347 (define_expand "sleu"
7348   [(set (match_operand:SI 0 "s_register_operand" "")
7349         (leu:SI (match_dup 1) (const_int 0)))]
7350   "TARGET_ARM"
7351   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7352 )
7353
7354 (define_expand "sgeu"
7355   [(set (match_operand:SI 0 "s_register_operand" "")
7356         (geu:SI (match_dup 1) (const_int 0)))]
7357   "TARGET_ARM"
7358   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7359 )
7360
7361 (define_expand "sltu"
7362   [(set (match_operand:SI 0 "s_register_operand" "")
7363         (ltu:SI (match_dup 1) (const_int 0)))]
7364   "TARGET_ARM"
7365   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7366 )
7367
7368 (define_expand "sunordered"
7369   [(set (match_operand:SI 0 "s_register_operand" "")
7370         (unordered:SI (match_dup 1) (const_int 0)))]
7371   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7372   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7373                                       arm_compare_op1);"
7374 )
7375
7376 (define_expand "sordered"
7377   [(set (match_operand:SI 0 "s_register_operand" "")
7378         (ordered:SI (match_dup 1) (const_int 0)))]
7379   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7380   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7381                                       arm_compare_op1);"
7382 )
7383
7384 (define_expand "sungt"
7385   [(set (match_operand:SI 0 "s_register_operand" "")
7386         (ungt:SI (match_dup 1) (const_int 0)))]
7387   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7388   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7389                                       arm_compare_op1);"
7390 )
7391
7392 (define_expand "sunge"
7393   [(set (match_operand:SI 0 "s_register_operand" "")
7394         (unge:SI (match_dup 1) (const_int 0)))]
7395   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7396   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7397                                       arm_compare_op1);"
7398 )
7399
7400 (define_expand "sunlt"
7401   [(set (match_operand:SI 0 "s_register_operand" "")
7402         (unlt:SI (match_dup 1) (const_int 0)))]
7403   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7404   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7405                                       arm_compare_op1);"
7406 )
7407
7408 (define_expand "sunle"
7409   [(set (match_operand:SI 0 "s_register_operand" "")
7410         (unle:SI (match_dup 1) (const_int 0)))]
7411   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7412   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7413                                       arm_compare_op1);"
7414 )
7415
7416 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7417 ;;; simple ARM instructions. 
7418 ;
7419 ; (define_expand "suneq"
7420 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7421 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7422 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7423 ;   "gcc_unreachable ();"
7424 ; )
7425 ;
7426 ; (define_expand "sltgt"
7427 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7428 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7429 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7430 ;   "gcc_unreachable ();"
7431 ; )
7432
7433 (define_insn "*mov_scc"
7434   [(set (match_operand:SI 0 "s_register_operand" "=r")
7435         (match_operator:SI 1 "arm_comparison_operator"
7436          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7437   "TARGET_ARM"
7438   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7439   [(set_attr "conds" "use")
7440    (set_attr "length" "8")]
7441 )
7442
7443 (define_insn "*mov_negscc"
7444   [(set (match_operand:SI 0 "s_register_operand" "=r")
7445         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7446                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7447   "TARGET_ARM"
7448   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7449   [(set_attr "conds" "use")
7450    (set_attr "length" "8")]
7451 )
7452
7453 (define_insn "*mov_notscc"
7454   [(set (match_operand:SI 0 "s_register_operand" "=r")
7455         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7456                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7457   "TARGET_ARM"
7458   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7459   [(set_attr "conds" "use")
7460    (set_attr "length" "8")]
7461 )
7462
7463 \f
7464 ;; Conditional move insns
7465
7466 (define_expand "movsicc"
7467   [(set (match_operand:SI 0 "s_register_operand" "")
7468         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7469                          (match_operand:SI 2 "arm_not_operand" "")
7470                          (match_operand:SI 3 "arm_not_operand" "")))]
7471   "TARGET_ARM"
7472   "
7473   {
7474     enum rtx_code code = GET_CODE (operands[1]);
7475     rtx ccreg;
7476
7477     if (code == UNEQ || code == LTGT)
7478       FAIL;
7479
7480     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7481     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7482   }"
7483 )
7484
7485 (define_expand "movsfcc"
7486   [(set (match_operand:SF 0 "s_register_operand" "")
7487         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7488                          (match_operand:SF 2 "s_register_operand" "")
7489                          (match_operand:SF 3 "nonmemory_operand" "")))]
7490   "TARGET_ARM"
7491   "
7492   {
7493     enum rtx_code code = GET_CODE (operands[1]);
7494     rtx ccreg;
7495
7496     if (code == UNEQ || code == LTGT)
7497       FAIL;
7498
7499     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7500        Otherwise, ensure it is a valid FP add operand */
7501     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7502         || (!arm_float_add_operand (operands[3], SFmode)))
7503       operands[3] = force_reg (SFmode, operands[3]);
7504
7505     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7506     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7507   }"
7508 )
7509
7510 (define_expand "movdfcc"
7511   [(set (match_operand:DF 0 "s_register_operand" "")
7512         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7513                          (match_operand:DF 2 "s_register_operand" "")
7514                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7515   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7516   "
7517   {
7518     enum rtx_code code = GET_CODE (operands[1]);
7519     rtx ccreg;
7520
7521     if (code == UNEQ || code == LTGT)
7522       FAIL;
7523
7524     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7525     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7526   }"
7527 )
7528
7529 (define_insn "*movsicc_insn"
7530   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7531         (if_then_else:SI
7532          (match_operator 3 "arm_comparison_operator"
7533           [(match_operand 4 "cc_register" "") (const_int 0)])
7534          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7535          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7536   "TARGET_ARM"
7537   "@
7538    mov%D3\\t%0, %2
7539    mvn%D3\\t%0, #%B2
7540    mov%d3\\t%0, %1
7541    mvn%d3\\t%0, #%B1
7542    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7543    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7544    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7545    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7546   [(set_attr "length" "4,4,4,4,8,8,8,8")
7547    (set_attr "conds" "use")]
7548 )
7549
7550 (define_insn "*movsfcc_soft_insn"
7551   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7552         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7553                           [(match_operand 4 "cc_register" "") (const_int 0)])
7554                          (match_operand:SF 1 "s_register_operand" "0,r")
7555                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7556   "TARGET_ARM && TARGET_SOFT_FLOAT"
7557   "@
7558    mov%D3\\t%0, %2
7559    mov%d3\\t%0, %1"
7560   [(set_attr "conds" "use")]
7561 )
7562
7563 \f
7564 ;; Jump and linkage insns
7565
7566 (define_expand "jump"
7567   [(set (pc)
7568         (label_ref (match_operand 0 "" "")))]
7569   "TARGET_EITHER"
7570   ""
7571 )
7572
7573 (define_insn "*arm_jump"
7574   [(set (pc)
7575         (label_ref (match_operand 0 "" "")))]
7576   "TARGET_ARM"
7577   "*
7578   {
7579     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7580       {
7581         arm_ccfsm_state += 2;
7582         return \"\";
7583       }
7584     return \"b%?\\t%l0\";
7585   }
7586   "
7587   [(set_attr "predicable" "yes")]
7588 )
7589
7590 (define_insn "*thumb_jump"
7591   [(set (pc)
7592         (label_ref (match_operand 0 "" "")))]
7593   "TARGET_THUMB"
7594   "*
7595   if (get_attr_length (insn) == 2)
7596     return \"b\\t%l0\";
7597   return \"bl\\t%l0\\t%@ far jump\";
7598   "
7599   [(set (attr "far_jump")
7600         (if_then_else
7601             (eq_attr "length" "4")
7602             (const_string "yes")
7603             (const_string "no")))
7604    (set (attr "length") 
7605         (if_then_else
7606             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7607                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7608             (const_int 2)
7609             (const_int 4)))]
7610 )
7611
7612 (define_expand "call"
7613   [(parallel [(call (match_operand 0 "memory_operand" "")
7614                     (match_operand 1 "general_operand" ""))
7615               (use (match_operand 2 "" ""))
7616               (clobber (reg:SI LR_REGNUM))])]
7617   "TARGET_EITHER"
7618   "
7619   {
7620     rtx callee;
7621     
7622     /* In an untyped call, we can get NULL for operand 2.  */
7623     if (operands[2] == NULL_RTX)
7624       operands[2] = const0_rtx;
7625       
7626     /* This is to decide if we should generate indirect calls by loading the
7627        32 bit address of the callee into a register before performing the
7628        branch and link.  operand[2] encodes the long_call/short_call
7629        attribute of the function being called.  This attribute is set whenever
7630        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7631        is used, and the short_call attribute can also be set if function is
7632        declared as static or if it has already been defined in the current
7633        compilation unit.  See arm.c and arm.h for info about this.  The third
7634        parameter to arm_is_longcall_p is used to tell it which pattern
7635        invoked it.  */
7636     callee  = XEXP (operands[0], 0);
7637     
7638     if ((GET_CODE (callee) == SYMBOL_REF
7639          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7640         || (GET_CODE (callee) != SYMBOL_REF
7641             && GET_CODE (callee) != REG))
7642       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7643   }"
7644 )
7645
7646 (define_insn "*call_reg_armv5"
7647   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7648          (match_operand 1 "" ""))
7649    (use (match_operand 2 "" ""))
7650    (clobber (reg:SI LR_REGNUM))]
7651   "TARGET_ARM && arm_arch5"
7652   "blx%?\\t%0"
7653   [(set_attr "type" "call")]
7654 )
7655
7656 (define_insn "*call_reg_arm"
7657   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7658          (match_operand 1 "" ""))
7659    (use (match_operand 2 "" ""))
7660    (clobber (reg:SI LR_REGNUM))]
7661   "TARGET_ARM && !arm_arch5"
7662   "*
7663   return output_call (operands);
7664   "
7665   ;; length is worst case, normally it is only two
7666   [(set_attr "length" "12")
7667    (set_attr "type" "call")]
7668 )
7669
7670 (define_insn "*call_mem"
7671   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7672          (match_operand 1 "" ""))
7673    (use (match_operand 2 "" ""))
7674    (clobber (reg:SI LR_REGNUM))]
7675   "TARGET_ARM"
7676   "*
7677   return output_call_mem (operands);
7678   "
7679   [(set_attr "length" "12")
7680    (set_attr "type" "call")]
7681 )
7682
7683 (define_insn "*call_reg_thumb_v5"
7684   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7685          (match_operand 1 "" ""))
7686    (use (match_operand 2 "" ""))
7687    (clobber (reg:SI LR_REGNUM))]
7688   "TARGET_THUMB && arm_arch5"
7689   "blx\\t%0"
7690   [(set_attr "length" "2")
7691    (set_attr "type" "call")]
7692 )
7693
7694 (define_insn "*call_reg_thumb"
7695   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7696          (match_operand 1 "" ""))
7697    (use (match_operand 2 "" ""))
7698    (clobber (reg:SI LR_REGNUM))]
7699   "TARGET_THUMB && !arm_arch5"
7700   "*
7701   {
7702     if (!TARGET_CALLER_INTERWORKING)
7703       return thumb_call_via_reg (operands[0]);
7704     else if (operands[1] == const0_rtx)
7705       return \"bl\\t%__interwork_call_via_%0\";
7706     else if (frame_pointer_needed)
7707       return \"bl\\t%__interwork_r7_call_via_%0\";
7708     else
7709       return \"bl\\t%__interwork_r11_call_via_%0\";
7710   }"
7711   [(set_attr "type" "call")]
7712 )
7713
7714 (define_expand "call_value"
7715   [(parallel [(set (match_operand       0 "" "")
7716                    (call (match_operand 1 "memory_operand" "")
7717                          (match_operand 2 "general_operand" "")))
7718               (use (match_operand 3 "" ""))
7719               (clobber (reg:SI LR_REGNUM))])]
7720   "TARGET_EITHER"
7721   "
7722   {
7723     rtx callee = XEXP (operands[1], 0);
7724     
7725     /* In an untyped call, we can get NULL for operand 2.  */
7726     if (operands[3] == 0)
7727       operands[3] = const0_rtx;
7728       
7729     /* See the comment in define_expand \"call\".  */
7730     if ((GET_CODE (callee) == SYMBOL_REF
7731          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7732         || (GET_CODE (callee) != SYMBOL_REF
7733             && GET_CODE (callee) != REG))
7734       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7735   }"
7736 )
7737
7738 (define_insn "*call_value_reg_armv5"
7739   [(set (match_operand 0 "" "")
7740         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7741               (match_operand 2 "" "")))
7742    (use (match_operand 3 "" ""))
7743    (clobber (reg:SI LR_REGNUM))]
7744   "TARGET_ARM && arm_arch5"
7745   "blx%?\\t%1"
7746   [(set_attr "type" "call")]
7747 )
7748
7749 (define_insn "*call_value_reg_arm"
7750   [(set (match_operand 0 "" "")
7751         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7752               (match_operand 2 "" "")))
7753    (use (match_operand 3 "" ""))
7754    (clobber (reg:SI LR_REGNUM))]
7755   "TARGET_ARM && !arm_arch5"
7756   "*
7757   return output_call (&operands[1]);
7758   "
7759   [(set_attr "length" "12")
7760    (set_attr "type" "call")]
7761 )
7762
7763 (define_insn "*call_value_mem"
7764   [(set (match_operand 0 "" "")
7765         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7766               (match_operand 2 "" "")))
7767    (use (match_operand 3 "" ""))
7768    (clobber (reg:SI LR_REGNUM))]
7769   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7770   "*
7771   return output_call_mem (&operands[1]);
7772   "
7773   [(set_attr "length" "12")
7774    (set_attr "type" "call")]
7775 )
7776
7777 (define_insn "*call_value_reg_thumb_v5"
7778   [(set (match_operand 0 "" "")
7779         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7780               (match_operand 2 "" "")))
7781    (use (match_operand 3 "" ""))
7782    (clobber (reg:SI LR_REGNUM))]
7783   "TARGET_THUMB && arm_arch5"
7784   "blx\\t%1"
7785   [(set_attr "length" "2")
7786    (set_attr "type" "call")]
7787 )
7788
7789 (define_insn "*call_value_reg_thumb"
7790   [(set (match_operand 0 "" "")
7791         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7792               (match_operand 2 "" "")))
7793    (use (match_operand 3 "" ""))
7794    (clobber (reg:SI LR_REGNUM))]
7795   "TARGET_THUMB && !arm_arch5"
7796   "*
7797   {
7798     if (!TARGET_CALLER_INTERWORKING)
7799       return thumb_call_via_reg (operands[1]);
7800     else if (operands[2] == const0_rtx)
7801       return \"bl\\t%__interwork_call_via_%1\";
7802     else if (frame_pointer_needed)
7803       return \"bl\\t%__interwork_r7_call_via_%1\";
7804     else
7805       return \"bl\\t%__interwork_r11_call_via_%1\";
7806   }"
7807   [(set_attr "type" "call")]
7808 )
7809
7810 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7811 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7812
7813 (define_insn "*call_symbol"
7814   [(call (mem:SI (match_operand:SI 0 "" ""))
7815          (match_operand 1 "" ""))
7816    (use (match_operand 2 "" ""))
7817    (clobber (reg:SI LR_REGNUM))]
7818   "TARGET_ARM
7819    && (GET_CODE (operands[0]) == SYMBOL_REF)
7820    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7821   "*
7822   {
7823     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7824   }"
7825   [(set_attr "type" "call")]
7826 )
7827
7828 (define_insn "*call_value_symbol"
7829   [(set (match_operand 0 "" "")
7830         (call (mem:SI (match_operand:SI 1 "" ""))
7831         (match_operand:SI 2 "" "")))
7832    (use (match_operand 3 "" ""))
7833    (clobber (reg:SI LR_REGNUM))]
7834   "TARGET_ARM
7835    && (GET_CODE (operands[1]) == SYMBOL_REF)
7836    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7837   "*
7838   {
7839     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7840   }"
7841   [(set_attr "type" "call")]
7842 )
7843
7844 (define_insn "*call_insn"
7845   [(call (mem:SI (match_operand:SI 0 "" ""))
7846          (match_operand:SI 1 "" ""))
7847    (use (match_operand 2 "" ""))
7848    (clobber (reg:SI LR_REGNUM))]
7849   "TARGET_THUMB
7850    && GET_CODE (operands[0]) == SYMBOL_REF
7851    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7852   "bl\\t%a0"
7853   [(set_attr "length" "4")
7854    (set_attr "type" "call")]
7855 )
7856
7857 (define_insn "*call_value_insn"
7858   [(set (match_operand 0 "" "")
7859         (call (mem:SI (match_operand 1 "" ""))
7860               (match_operand 2 "" "")))
7861    (use (match_operand 3 "" ""))
7862    (clobber (reg:SI LR_REGNUM))]
7863   "TARGET_THUMB
7864    && GET_CODE (operands[1]) == SYMBOL_REF
7865    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7866   "bl\\t%a1"
7867   [(set_attr "length" "4")
7868    (set_attr "type" "call")]
7869 )
7870
7871 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7872 (define_expand "sibcall"
7873   [(parallel [(call (match_operand 0 "memory_operand" "")
7874                     (match_operand 1 "general_operand" ""))
7875               (return)
7876               (use (match_operand 2 "" ""))])]
7877   "TARGET_ARM"
7878   "
7879   {
7880     if (operands[2] == NULL_RTX)
7881       operands[2] = const0_rtx;
7882   }"
7883 )
7884
7885 (define_expand "sibcall_value"
7886   [(parallel [(set (match_operand 0 "" "")
7887                    (call (match_operand 1 "memory_operand" "")
7888                          (match_operand 2 "general_operand" "")))
7889               (return)
7890               (use (match_operand 3 "" ""))])]
7891   "TARGET_ARM"
7892   "
7893   {
7894     if (operands[3] == NULL_RTX)
7895       operands[3] = const0_rtx;
7896   }"
7897 )
7898
7899 (define_insn "*sibcall_insn"
7900  [(call (mem:SI (match_operand:SI 0 "" "X"))
7901         (match_operand 1 "" ""))
7902   (return)
7903   (use (match_operand 2 "" ""))]
7904   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7905   "*
7906   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7907   "
7908   [(set_attr "type" "call")]
7909 )
7910
7911 (define_insn "*sibcall_value_insn"
7912  [(set (match_operand 0 "" "")
7913        (call (mem:SI (match_operand:SI 1 "" "X"))
7914              (match_operand 2 "" "")))
7915   (return)
7916   (use (match_operand 3 "" ""))]
7917   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7918   "*
7919   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7920   "
7921   [(set_attr "type" "call")]
7922 )
7923
7924 ;; Often the return insn will be the same as loading from memory, so set attr
7925 (define_insn "return"
7926   [(return)]
7927   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7928   "*
7929   {
7930     if (arm_ccfsm_state == 2)
7931       {
7932         arm_ccfsm_state += 2;
7933         return \"\";
7934       }
7935     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7936   }"
7937   [(set_attr "type" "load1")
7938    (set_attr "length" "12")
7939    (set_attr "predicable" "yes")]
7940 )
7941
7942 (define_insn "*cond_return"
7943   [(set (pc)
7944         (if_then_else (match_operator 0 "arm_comparison_operator"
7945                        [(match_operand 1 "cc_register" "") (const_int 0)])
7946                       (return)
7947                       (pc)))]
7948   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7949   "*
7950   {
7951     if (arm_ccfsm_state == 2)
7952       {
7953         arm_ccfsm_state += 2;
7954         return \"\";
7955       }
7956     return output_return_instruction (operands[0], TRUE, FALSE);
7957   }"
7958   [(set_attr "conds" "use")
7959    (set_attr "length" "12")
7960    (set_attr "type" "load1")]
7961 )
7962
7963 (define_insn "*cond_return_inverted"
7964   [(set (pc)
7965         (if_then_else (match_operator 0 "arm_comparison_operator"
7966                        [(match_operand 1 "cc_register" "") (const_int 0)])
7967                       (pc)
7968                       (return)))]
7969   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7970   "*
7971   {
7972     if (arm_ccfsm_state == 2)
7973       {
7974         arm_ccfsm_state += 2;
7975         return \"\";
7976       }
7977     return output_return_instruction (operands[0], TRUE, TRUE);
7978   }"
7979   [(set_attr "conds" "use")
7980    (set_attr "length" "12")
7981    (set_attr "type" "load1")]
7982 )
7983
7984 ;; Generate a sequence of instructions to determine if the processor is
7985 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7986 ;; mask.
7987
7988 (define_expand "return_addr_mask"
7989   [(set (match_dup 1)
7990       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7991                        (const_int 0)))
7992    (set (match_operand:SI 0 "s_register_operand" "")
7993       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7994                        (const_int -1)
7995                        (const_int 67108860)))] ; 0x03fffffc
7996   "TARGET_ARM"
7997   "
7998   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7999   ")
8000
8001 (define_insn "*check_arch2"
8002   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8003       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8004                        (const_int 0)))]
8005   "TARGET_ARM"
8006   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8007   [(set_attr "length" "8")
8008    (set_attr "conds" "set")]
8009 )
8010
8011 ;; Call subroutine returning any type.
8012
8013 (define_expand "untyped_call"
8014   [(parallel [(call (match_operand 0 "" "")
8015                     (const_int 0))
8016               (match_operand 1 "" "")
8017               (match_operand 2 "" "")])]
8018   "TARGET_EITHER"
8019   "
8020   {
8021     int i;
8022     rtx par = gen_rtx_PARALLEL (VOIDmode,
8023                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8024     rtx addr = gen_reg_rtx (Pmode);
8025     rtx mem;
8026     int size = 0;
8027
8028     emit_move_insn (addr, XEXP (operands[1], 0));
8029     mem = change_address (operands[1], BLKmode, addr);
8030
8031     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8032       {
8033         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8034
8035         /* Default code only uses r0 as a return value, but we could
8036            be using anything up to 4 registers.  */
8037         if (REGNO (src) == R0_REGNUM)
8038           src = gen_rtx_REG (TImode, R0_REGNUM);
8039
8040         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8041                                                  GEN_INT (size));
8042         size += GET_MODE_SIZE (GET_MODE (src));
8043       }
8044
8045     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8046                                     const0_rtx));
8047
8048     size = 0;
8049
8050     for (i = 0; i < XVECLEN (par, 0); i++)
8051       {
8052         HOST_WIDE_INT offset = 0;
8053         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8054
8055         if (size != 0)
8056           emit_move_insn (addr, plus_constant (addr, size));
8057
8058         mem = change_address (mem, GET_MODE (reg), NULL);
8059         if (REGNO (reg) == R0_REGNUM)
8060           {
8061             /* On thumb we have to use a write-back instruction.  */
8062             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8063                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8064             size = TARGET_ARM ? 16 : 0;
8065           }
8066         else
8067           {
8068             emit_move_insn (mem, reg);
8069             size = GET_MODE_SIZE (GET_MODE (reg));
8070           }
8071       }
8072
8073     /* The optimizer does not know that the call sets the function value
8074        registers we stored in the result block.  We avoid problems by
8075        claiming that all hard registers are used and clobbered at this
8076        point.  */
8077     emit_insn (gen_blockage ());
8078
8079     DONE;
8080   }"
8081 )
8082
8083 (define_expand "untyped_return"
8084   [(match_operand:BLK 0 "memory_operand" "")
8085    (match_operand 1 "" "")]
8086   "TARGET_EITHER"
8087   "
8088   {
8089     int i;
8090     rtx addr = gen_reg_rtx (Pmode);
8091     rtx mem;
8092     int size = 0;
8093
8094     emit_move_insn (addr, XEXP (operands[0], 0));
8095     mem = change_address (operands[0], BLKmode, addr);
8096
8097     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8098       {
8099         HOST_WIDE_INT offset = 0;
8100         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8101
8102         if (size != 0)
8103           emit_move_insn (addr, plus_constant (addr, size));
8104
8105         mem = change_address (mem, GET_MODE (reg), NULL);
8106         if (REGNO (reg) == R0_REGNUM)
8107           {
8108             /* On thumb we have to use a write-back instruction.  */
8109             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8110                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8111             size = TARGET_ARM ? 16 : 0;
8112           }
8113         else
8114           {
8115             emit_move_insn (reg, mem);
8116             size = GET_MODE_SIZE (GET_MODE (reg));
8117           }
8118       }
8119
8120     /* Emit USE insns before the return.  */
8121     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8122       emit_insn (gen_rtx_USE (VOIDmode,
8123                               SET_DEST (XVECEXP (operands[1], 0, i))));
8124
8125     /* Construct the return.  */
8126     expand_naked_return ();
8127
8128     DONE;
8129   }"
8130 )
8131
8132 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8133 ;; all of memory.  This blocks insns from being moved across this point.
8134
8135 (define_insn "blockage"
8136   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8137   "TARGET_EITHER"
8138   ""
8139   [(set_attr "length" "0")
8140    (set_attr "type" "block")]
8141 )
8142
8143 (define_expand "casesi"
8144   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8145    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8146    (match_operand:SI 2 "const_int_operand" "")  ; total range
8147    (match_operand:SI 3 "" "")                   ; table label
8148    (match_operand:SI 4 "" "")]                  ; Out of range label
8149   "TARGET_ARM"
8150   "
8151   {
8152     rtx reg;
8153     if (operands[1] != const0_rtx)
8154       {
8155         reg = gen_reg_rtx (SImode);
8156
8157         emit_insn (gen_addsi3 (reg, operands[0],
8158                                GEN_INT (-INTVAL (operands[1]))));
8159         operands[0] = reg;
8160       }
8161
8162     if (!const_ok_for_arm (INTVAL (operands[2])))
8163       operands[2] = force_reg (SImode, operands[2]);
8164
8165     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8166                                          operands[4]));
8167     DONE;
8168   }"
8169 )
8170
8171 ;; The USE in this pattern is needed to tell flow analysis that this is
8172 ;; a CASESI insn.  It has no other purpose.
8173 (define_insn "casesi_internal"
8174   [(parallel [(set (pc)
8175                (if_then_else
8176                 (leu (match_operand:SI 0 "s_register_operand" "r")
8177                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8178                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8179                                  (label_ref (match_operand 2 "" ""))))
8180                 (label_ref (match_operand 3 "" ""))))
8181               (clobber (reg:CC CC_REGNUM))
8182               (use (label_ref (match_dup 2)))])]
8183   "TARGET_ARM"
8184   "*
8185     if (flag_pic)
8186       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8187     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8188   "
8189   [(set_attr "conds" "clob")
8190    (set_attr "length" "12")]
8191 )
8192
8193 (define_expand "indirect_jump"
8194   [(set (pc)
8195         (match_operand:SI 0 "s_register_operand" ""))]
8196   "TARGET_EITHER"
8197   ""
8198 )
8199
8200 ;; NB Never uses BX.
8201 (define_insn "*arm_indirect_jump"
8202   [(set (pc)
8203         (match_operand:SI 0 "s_register_operand" "r"))]
8204   "TARGET_ARM"
8205   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8206   [(set_attr "predicable" "yes")]
8207 )
8208
8209 (define_insn "*load_indirect_jump"
8210   [(set (pc)
8211         (match_operand:SI 0 "memory_operand" "m"))]
8212   "TARGET_ARM"
8213   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8214   [(set_attr "type" "load1")
8215    (set_attr "pool_range" "4096")
8216    (set_attr "neg_pool_range" "4084")
8217    (set_attr "predicable" "yes")]
8218 )
8219
8220 ;; NB Never uses BX.
8221 (define_insn "*thumb_indirect_jump"
8222   [(set (pc)
8223         (match_operand:SI 0 "register_operand" "l*r"))]
8224   "TARGET_THUMB"
8225   "mov\\tpc, %0"
8226   [(set_attr "conds" "clob")
8227    (set_attr "length" "2")]
8228 )
8229
8230 \f
8231 ;; Misc insns
8232
8233 (define_insn "nop"
8234   [(const_int 0)]
8235   "TARGET_EITHER"
8236   "*
8237   if (TARGET_ARM)
8238     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8239   return  \"mov\\tr8, r8\";
8240   "
8241   [(set (attr "length")
8242         (if_then_else (eq_attr "is_thumb" "yes")
8243                       (const_int 2)
8244                       (const_int 4)))]
8245 )
8246
8247 \f
8248 ;; Patterns to allow combination of arithmetic, cond code and shifts
8249
8250 (define_insn "*arith_shiftsi"
8251   [(set (match_operand:SI 0 "s_register_operand" "=r")
8252         (match_operator:SI 1 "shiftable_operator"
8253           [(match_operator:SI 3 "shift_operator"
8254              [(match_operand:SI 4 "s_register_operand" "r")
8255               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8256            (match_operand:SI 2 "s_register_operand" "r")]))]
8257   "TARGET_ARM"
8258   "%i1%?\\t%0, %2, %4%S3"
8259   [(set_attr "predicable" "yes")
8260    (set_attr "shift" "4")
8261    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8262                       (const_string "alu_shift")
8263                       (const_string "alu_shift_reg")))]
8264 )
8265
8266 (define_split
8267   [(set (match_operand:SI 0 "s_register_operand" "")
8268         (match_operator:SI 1 "shiftable_operator"
8269          [(match_operator:SI 2 "shiftable_operator"
8270            [(match_operator:SI 3 "shift_operator"
8271              [(match_operand:SI 4 "s_register_operand" "")
8272               (match_operand:SI 5 "reg_or_int_operand" "")])
8273             (match_operand:SI 6 "s_register_operand" "")])
8274           (match_operand:SI 7 "arm_rhs_operand" "")]))
8275    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8276   "TARGET_ARM"
8277   [(set (match_dup 8)
8278         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8279                          (match_dup 6)]))
8280    (set (match_dup 0)
8281         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8282   "")
8283
8284 (define_insn "*arith_shiftsi_compare0"
8285   [(set (reg:CC_NOOV CC_REGNUM)
8286         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8287                           [(match_operator:SI 3 "shift_operator"
8288                             [(match_operand:SI 4 "s_register_operand" "r")
8289                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8290                            (match_operand:SI 2 "s_register_operand" "r")])
8291                          (const_int 0)))
8292    (set (match_operand:SI 0 "s_register_operand" "=r")
8293         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8294                          (match_dup 2)]))]
8295   "TARGET_ARM"
8296   "%i1%?s\\t%0, %2, %4%S3"
8297   [(set_attr "conds" "set")
8298    (set_attr "shift" "4")
8299    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8300                       (const_string "alu_shift")
8301                       (const_string "alu_shift_reg")))]
8302 )
8303
8304 (define_insn "*arith_shiftsi_compare0_scratch"
8305   [(set (reg:CC_NOOV CC_REGNUM)
8306         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8307                           [(match_operator:SI 3 "shift_operator"
8308                             [(match_operand:SI 4 "s_register_operand" "r")
8309                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8310                            (match_operand:SI 2 "s_register_operand" "r")])
8311                          (const_int 0)))
8312    (clobber (match_scratch:SI 0 "=r"))]
8313   "TARGET_ARM"
8314   "%i1%?s\\t%0, %2, %4%S3"
8315   [(set_attr "conds" "set")
8316    (set_attr "shift" "4")
8317    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8318                       (const_string "alu_shift")
8319                       (const_string "alu_shift_reg")))]
8320 )
8321
8322 (define_insn "*sub_shiftsi"
8323   [(set (match_operand:SI 0 "s_register_operand" "=r")
8324         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8325                   (match_operator:SI 2 "shift_operator"
8326                    [(match_operand:SI 3 "s_register_operand" "r")
8327                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8328   "TARGET_ARM"
8329   "sub%?\\t%0, %1, %3%S2"
8330   [(set_attr "predicable" "yes")
8331    (set_attr "shift" "3")
8332    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8333                       (const_string "alu_shift")
8334                       (const_string "alu_shift_reg")))]
8335 )
8336
8337 (define_insn "*sub_shiftsi_compare0"
8338   [(set (reg:CC_NOOV CC_REGNUM)
8339         (compare:CC_NOOV
8340          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8341                    (match_operator:SI 2 "shift_operator"
8342                     [(match_operand:SI 3 "s_register_operand" "r")
8343                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8344          (const_int 0)))
8345    (set (match_operand:SI 0 "s_register_operand" "=r")
8346         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8347                                                  (match_dup 4)])))]
8348   "TARGET_ARM"
8349   "sub%?s\\t%0, %1, %3%S2"
8350   [(set_attr "conds" "set")
8351    (set_attr "shift" "3")
8352    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8353                       (const_string "alu_shift")
8354                       (const_string "alu_shift_reg")))]
8355 )
8356
8357 (define_insn "*sub_shiftsi_compare0_scratch"
8358   [(set (reg:CC_NOOV CC_REGNUM)
8359         (compare:CC_NOOV
8360          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8361                    (match_operator:SI 2 "shift_operator"
8362                     [(match_operand:SI 3 "s_register_operand" "r")
8363                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8364          (const_int 0)))
8365    (clobber (match_scratch:SI 0 "=r"))]
8366   "TARGET_ARM"
8367   "sub%?s\\t%0, %1, %3%S2"
8368   [(set_attr "conds" "set")
8369    (set_attr "shift" "3")
8370    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8371                       (const_string "alu_shift")
8372                       (const_string "alu_shift_reg")))]
8373 )
8374
8375 \f
8376
8377 (define_insn "*and_scc"
8378   [(set (match_operand:SI 0 "s_register_operand" "=r")
8379         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8380                  [(match_operand 3 "cc_register" "") (const_int 0)])
8381                 (match_operand:SI 2 "s_register_operand" "r")))]
8382   "TARGET_ARM"
8383   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8384   [(set_attr "conds" "use")
8385    (set_attr "length" "8")]
8386 )
8387
8388 (define_insn "*ior_scc"
8389   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8390         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8391                  [(match_operand 3 "cc_register" "") (const_int 0)])
8392                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8393   "TARGET_ARM"
8394   "@
8395    orr%d2\\t%0, %1, #1
8396    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8397   [(set_attr "conds" "use")
8398    (set_attr "length" "4,8")]
8399 )
8400
8401 (define_insn "*compare_scc"
8402   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8403         (match_operator:SI 1 "arm_comparison_operator"
8404          [(match_operand:SI 2 "s_register_operand" "r,r")
8405           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8406    (clobber (reg:CC CC_REGNUM))]
8407   "TARGET_ARM"
8408   "*
8409     if (operands[3] == const0_rtx)
8410       {
8411         if (GET_CODE (operands[1]) == LT)
8412           return \"mov\\t%0, %2, lsr #31\";
8413
8414         if (GET_CODE (operands[1]) == GE)
8415           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8416
8417         if (GET_CODE (operands[1]) == EQ)
8418           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8419       }
8420
8421     if (GET_CODE (operands[1]) == NE)
8422       {
8423         if (which_alternative == 1)
8424           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8425         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8426       }
8427     if (which_alternative == 1)
8428       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8429     else
8430       output_asm_insn (\"cmp\\t%2, %3\", operands);
8431     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8432   "
8433   [(set_attr "conds" "clob")
8434    (set_attr "length" "12")]
8435 )
8436
8437 (define_insn "*cond_move"
8438   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8439         (if_then_else:SI (match_operator 3 "equality_operator"
8440                           [(match_operator 4 "arm_comparison_operator"
8441                             [(match_operand 5 "cc_register" "") (const_int 0)])
8442                            (const_int 0)])
8443                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8444                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8445   "TARGET_ARM"
8446   "*
8447     if (GET_CODE (operands[3]) == NE)
8448       {
8449         if (which_alternative != 1)
8450           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8451         if (which_alternative != 0)
8452           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8453         return \"\";
8454       }
8455     if (which_alternative != 0)
8456       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8457     if (which_alternative != 1)
8458       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8459     return \"\";
8460   "
8461   [(set_attr "conds" "use")
8462    (set_attr "length" "4,4,8")]
8463 )
8464
8465 (define_insn "*cond_arith"
8466   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8467         (match_operator:SI 5 "shiftable_operator" 
8468          [(match_operator:SI 4 "arm_comparison_operator"
8469            [(match_operand:SI 2 "s_register_operand" "r,r")
8470             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8471           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8472    (clobber (reg:CC CC_REGNUM))]
8473   "TARGET_ARM"
8474   "*
8475     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8476       return \"%i5\\t%0, %1, %2, lsr #31\";
8477
8478     output_asm_insn (\"cmp\\t%2, %3\", operands);
8479     if (GET_CODE (operands[5]) == AND)
8480       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8481     else if (GET_CODE (operands[5]) == MINUS)
8482       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8483     else if (which_alternative != 0)
8484       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8485     return \"%i5%d4\\t%0, %1, #1\";
8486   "
8487   [(set_attr "conds" "clob")
8488    (set_attr "length" "12")]
8489 )
8490
8491 (define_insn "*cond_sub"
8492   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8493         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8494                   (match_operator:SI 4 "arm_comparison_operator"
8495                    [(match_operand:SI 2 "s_register_operand" "r,r")
8496                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8497    (clobber (reg:CC CC_REGNUM))]
8498   "TARGET_ARM"
8499   "*
8500     output_asm_insn (\"cmp\\t%2, %3\", operands);
8501     if (which_alternative != 0)
8502       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8503     return \"sub%d4\\t%0, %1, #1\";
8504   "
8505   [(set_attr "conds" "clob")
8506    (set_attr "length" "8,12")]
8507 )
8508
8509 (define_insn "*cmp_ite0"
8510   [(set (match_operand 6 "dominant_cc_register" "")
8511         (compare
8512          (if_then_else:SI
8513           (match_operator 4 "arm_comparison_operator"
8514            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8515             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8516           (match_operator:SI 5 "arm_comparison_operator"
8517            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8518             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8519           (const_int 0))
8520          (const_int 0)))]
8521   "TARGET_ARM"
8522   "*
8523   {
8524     static const char * const opcodes[4][2] =
8525     {
8526       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8527        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8528       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8529        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8530       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8531        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8532       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8533        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8534     };
8535     int swap =
8536       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8537
8538     return opcodes[which_alternative][swap];
8539   }"
8540   [(set_attr "conds" "set")
8541    (set_attr "length" "8")]
8542 )
8543
8544 (define_insn "*cmp_ite1"
8545   [(set (match_operand 6 "dominant_cc_register" "")
8546         (compare
8547          (if_then_else:SI
8548           (match_operator 4 "arm_comparison_operator"
8549            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8550             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8551           (match_operator:SI 5 "arm_comparison_operator"
8552            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8553             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8554           (const_int 1))
8555          (const_int 0)))]
8556   "TARGET_ARM"
8557   "*
8558   {
8559     static const char * const opcodes[4][2] =
8560     {
8561       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8562        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8563       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8564        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8565       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8566        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8567       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8568        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8569     };
8570     int swap =
8571       comparison_dominates_p (GET_CODE (operands[5]),
8572                               reverse_condition (GET_CODE (operands[4])));
8573
8574     return opcodes[which_alternative][swap];
8575   }"
8576   [(set_attr "conds" "set")
8577    (set_attr "length" "8")]
8578 )
8579
8580 (define_insn "*cmp_and"
8581   [(set (match_operand 6 "dominant_cc_register" "")
8582         (compare
8583          (and:SI
8584           (match_operator 4 "arm_comparison_operator"
8585            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8586             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8587           (match_operator:SI 5 "arm_comparison_operator"
8588            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8589             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8590          (const_int 0)))]
8591   "TARGET_ARM"
8592   "*
8593   {
8594     static const char *const opcodes[4][2] =
8595     {
8596       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8597        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8598       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8599        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8600       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8601        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8602       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8603        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8604     };
8605     int swap =
8606       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8607
8608     return opcodes[which_alternative][swap];
8609   }"
8610   [(set_attr "conds" "set")
8611    (set_attr "predicable" "no")
8612    (set_attr "length" "8")]
8613 )
8614
8615 (define_insn "*cmp_ior"
8616   [(set (match_operand 6 "dominant_cc_register" "")
8617         (compare
8618          (ior:SI
8619           (match_operator 4 "arm_comparison_operator"
8620            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8621             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8622           (match_operator:SI 5 "arm_comparison_operator"
8623            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8624             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8625          (const_int 0)))]
8626   "TARGET_ARM"
8627   "*
8628 {
8629   static const char *const opcodes[4][2] =
8630   {
8631     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8632      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8633     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8634      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8635     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8636      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8637     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8638      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8639   };
8640   int swap =
8641     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8642
8643   return opcodes[which_alternative][swap];
8644 }
8645 "
8646   [(set_attr "conds" "set")
8647    (set_attr "length" "8")]
8648 )
8649
8650 (define_insn_and_split "*ior_scc_scc"
8651   [(set (match_operand:SI 0 "s_register_operand" "=r")
8652         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8653                  [(match_operand:SI 1 "s_register_operand" "r")
8654                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8655                 (match_operator:SI 6 "arm_comparison_operator"
8656                  [(match_operand:SI 4 "s_register_operand" "r")
8657                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8658    (clobber (reg:CC CC_REGNUM))]
8659   "TARGET_ARM
8660    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8661        != CCmode)"
8662   "#"
8663   "TARGET_ARM && reload_completed"
8664   [(set (match_dup 7)
8665         (compare
8666          (ior:SI
8667           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8668           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8669          (const_int 0)))
8670    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8671   "operands[7]
8672      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8673                                                   DOM_CC_X_OR_Y),
8674                     CC_REGNUM);"
8675   [(set_attr "conds" "clob")
8676    (set_attr "length" "16")])
8677
8678 ; If the above pattern is followed by a CMP insn, then the compare is 
8679 ; redundant, since we can rework the conditional instruction that follows.
8680 (define_insn_and_split "*ior_scc_scc_cmp"
8681   [(set (match_operand 0 "dominant_cc_register" "")
8682         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8683                           [(match_operand:SI 1 "s_register_operand" "r")
8684                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8685                          (match_operator:SI 6 "arm_comparison_operator"
8686                           [(match_operand:SI 4 "s_register_operand" "r")
8687                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8688                  (const_int 0)))
8689    (set (match_operand:SI 7 "s_register_operand" "=r")
8690         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8691                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8692   "TARGET_ARM"
8693   "#"
8694   "TARGET_ARM && reload_completed"
8695   [(set (match_dup 0)
8696         (compare
8697          (ior:SI
8698           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8699           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8700          (const_int 0)))
8701    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8702   ""
8703   [(set_attr "conds" "set")
8704    (set_attr "length" "16")])
8705
8706 (define_insn_and_split "*and_scc_scc"
8707   [(set (match_operand:SI 0 "s_register_operand" "=r")
8708         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8709                  [(match_operand:SI 1 "s_register_operand" "r")
8710                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8711                 (match_operator:SI 6 "arm_comparison_operator"
8712                  [(match_operand:SI 4 "s_register_operand" "r")
8713                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8714    (clobber (reg:CC CC_REGNUM))]
8715   "TARGET_ARM
8716    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8717        != CCmode)"
8718   "#"
8719   "TARGET_ARM && reload_completed
8720    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8721        != CCmode)"
8722   [(set (match_dup 7)
8723         (compare
8724          (and:SI
8725           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8726           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8727          (const_int 0)))
8728    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8729   "operands[7]
8730      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8731                                                   DOM_CC_X_AND_Y),
8732                     CC_REGNUM);"
8733   [(set_attr "conds" "clob")
8734    (set_attr "length" "16")])
8735
8736 ; If the above pattern is followed by a CMP insn, then the compare is 
8737 ; redundant, since we can rework the conditional instruction that follows.
8738 (define_insn_and_split "*and_scc_scc_cmp"
8739   [(set (match_operand 0 "dominant_cc_register" "")
8740         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8741                           [(match_operand:SI 1 "s_register_operand" "r")
8742                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8743                          (match_operator:SI 6 "arm_comparison_operator"
8744                           [(match_operand:SI 4 "s_register_operand" "r")
8745                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8746                  (const_int 0)))
8747    (set (match_operand:SI 7 "s_register_operand" "=r")
8748         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8749                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8750   "TARGET_ARM"
8751   "#"
8752   "TARGET_ARM && reload_completed"
8753   [(set (match_dup 0)
8754         (compare
8755          (and:SI
8756           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8757           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8758          (const_int 0)))
8759    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8760   ""
8761   [(set_attr "conds" "set")
8762    (set_attr "length" "16")])
8763
8764 ;; If there is no dominance in the comparison, then we can still save an
8765 ;; instruction in the AND case, since we can know that the second compare
8766 ;; need only zero the value if false (if true, then the value is already
8767 ;; correct).
8768 (define_insn_and_split "*and_scc_scc_nodom"
8769   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8770         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8771                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8772                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8773                 (match_operator:SI 6 "arm_comparison_operator"
8774                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8775                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8776    (clobber (reg:CC CC_REGNUM))]
8777   "TARGET_ARM
8778    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8779        == CCmode)"
8780   "#"
8781   "TARGET_ARM && reload_completed"
8782   [(parallel [(set (match_dup 0)
8783                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8784               (clobber (reg:CC CC_REGNUM))])
8785    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8786    (set (match_dup 0)
8787         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8788                          (match_dup 0)
8789                          (const_int 0)))]
8790   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8791                                               operands[4], operands[5]),
8792                               CC_REGNUM);
8793    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8794                                   operands[5]);"
8795   [(set_attr "conds" "clob")
8796    (set_attr "length" "20")])
8797
8798 (define_split
8799   [(set (reg:CC_NOOV CC_REGNUM)
8800         (compare:CC_NOOV (ior:SI
8801                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8802                                   (const_int 1))
8803                           (match_operator:SI 1 "comparison_operator"
8804                            [(match_operand:SI 2 "s_register_operand" "")
8805                             (match_operand:SI 3 "arm_add_operand" "")]))
8806                          (const_int 0)))
8807    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8808   "TARGET_ARM"
8809   [(set (match_dup 4)
8810         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8811                 (match_dup 0)))
8812    (set (reg:CC_NOOV CC_REGNUM)
8813         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8814                          (const_int 0)))]
8815   "")
8816
8817 (define_split
8818   [(set (reg:CC_NOOV CC_REGNUM)
8819         (compare:CC_NOOV (ior:SI
8820                           (match_operator:SI 1 "comparison_operator"
8821                            [(match_operand:SI 2 "s_register_operand" "")
8822                             (match_operand:SI 3 "arm_add_operand" "")])
8823                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8824                                   (const_int 1)))
8825                          (const_int 0)))
8826    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8827   "TARGET_ARM"
8828   [(set (match_dup 4)
8829         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8830                 (match_dup 0)))
8831    (set (reg:CC_NOOV CC_REGNUM)
8832         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8833                          (const_int 0)))]
8834   "")
8835
8836 (define_insn "*negscc"
8837   [(set (match_operand:SI 0 "s_register_operand" "=r")
8838         (neg:SI (match_operator 3 "arm_comparison_operator"
8839                  [(match_operand:SI 1 "s_register_operand" "r")
8840                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8841    (clobber (reg:CC CC_REGNUM))]
8842   "TARGET_ARM"
8843   "*
8844   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8845     return \"mov\\t%0, %1, asr #31\";
8846
8847   if (GET_CODE (operands[3]) == NE)
8848     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8849
8850   if (GET_CODE (operands[3]) == GT)
8851     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8852
8853   output_asm_insn (\"cmp\\t%1, %2\", operands);
8854   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8855   return \"mvn%d3\\t%0, #0\";
8856   "
8857   [(set_attr "conds" "clob")
8858    (set_attr "length" "12")]
8859 )
8860
8861 (define_insn "movcond"
8862   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8863         (if_then_else:SI
8864          (match_operator 5 "arm_comparison_operator"
8865           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8866            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8867          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8868          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8869    (clobber (reg:CC CC_REGNUM))]
8870   "TARGET_ARM"
8871   "*
8872   if (GET_CODE (operands[5]) == LT
8873       && (operands[4] == const0_rtx))
8874     {
8875       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8876         {
8877           if (operands[2] == const0_rtx)
8878             return \"and\\t%0, %1, %3, asr #31\";
8879           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8880         }
8881       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8882         {
8883           if (operands[1] == const0_rtx)
8884             return \"bic\\t%0, %2, %3, asr #31\";
8885           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8886         }
8887       /* The only case that falls through to here is when both ops 1 & 2
8888          are constants.  */
8889     }
8890
8891   if (GET_CODE (operands[5]) == GE
8892       && (operands[4] == const0_rtx))
8893     {
8894       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8895         {
8896           if (operands[2] == const0_rtx)
8897             return \"bic\\t%0, %1, %3, asr #31\";
8898           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8899         }
8900       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8901         {
8902           if (operands[1] == const0_rtx)
8903             return \"and\\t%0, %2, %3, asr #31\";
8904           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8905         }
8906       /* The only case that falls through to here is when both ops 1 & 2
8907          are constants.  */
8908     }
8909   if (GET_CODE (operands[4]) == CONST_INT
8910       && !const_ok_for_arm (INTVAL (operands[4])))
8911     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8912   else
8913     output_asm_insn (\"cmp\\t%3, %4\", operands);
8914   if (which_alternative != 0)
8915     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8916   if (which_alternative != 1)
8917     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8918   return \"\";
8919   "
8920   [(set_attr "conds" "clob")
8921    (set_attr "length" "8,8,12")]
8922 )
8923
8924 (define_insn "*ifcompare_plus_move"
8925   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8926         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8927                           [(match_operand:SI 4 "s_register_operand" "r,r")
8928                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8929                          (plus:SI
8930                           (match_operand:SI 2 "s_register_operand" "r,r")
8931                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8932                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8933    (clobber (reg:CC CC_REGNUM))]
8934   "TARGET_ARM"
8935   "#"
8936   [(set_attr "conds" "clob")
8937    (set_attr "length" "8,12")]
8938 )
8939
8940 (define_insn "*if_plus_move"
8941   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8942         (if_then_else:SI
8943          (match_operator 4 "arm_comparison_operator"
8944           [(match_operand 5 "cc_register" "") (const_int 0)])
8945          (plus:SI
8946           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8947           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8948          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8949   "TARGET_ARM"
8950   "@
8951    add%d4\\t%0, %2, %3
8952    sub%d4\\t%0, %2, #%n3
8953    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8954    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8955   [(set_attr "conds" "use")
8956    (set_attr "length" "4,4,8,8")
8957    (set_attr "type" "*,*,*,*")]
8958 )
8959
8960 (define_insn "*ifcompare_move_plus"
8961   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8962         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8963                           [(match_operand:SI 4 "s_register_operand" "r,r")
8964                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8965                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8966                          (plus:SI
8967                           (match_operand:SI 2 "s_register_operand" "r,r")
8968                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8969    (clobber (reg:CC CC_REGNUM))]
8970   "TARGET_ARM"
8971   "#"
8972   [(set_attr "conds" "clob")
8973    (set_attr "length" "8,12")]
8974 )
8975
8976 (define_insn "*if_move_plus"
8977   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8978         (if_then_else:SI
8979          (match_operator 4 "arm_comparison_operator"
8980           [(match_operand 5 "cc_register" "") (const_int 0)])
8981          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8982          (plus:SI
8983           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8984           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8985   "TARGET_ARM"
8986   "@
8987    add%D4\\t%0, %2, %3
8988    sub%D4\\t%0, %2, #%n3
8989    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8990    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8991   [(set_attr "conds" "use")
8992    (set_attr "length" "4,4,8,8")
8993    (set_attr "type" "*,*,*,*")]
8994 )
8995
8996 (define_insn "*ifcompare_arith_arith"
8997   [(set (match_operand:SI 0 "s_register_operand" "=r")
8998         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8999                           [(match_operand:SI 5 "s_register_operand" "r")
9000                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9001                          (match_operator:SI 8 "shiftable_operator"
9002                           [(match_operand:SI 1 "s_register_operand" "r")
9003                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9004                          (match_operator:SI 7 "shiftable_operator"
9005                           [(match_operand:SI 3 "s_register_operand" "r")
9006                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9007    (clobber (reg:CC CC_REGNUM))]
9008   "TARGET_ARM"
9009   "#"
9010   [(set_attr "conds" "clob")
9011    (set_attr "length" "12")]
9012 )
9013
9014 (define_insn "*if_arith_arith"
9015   [(set (match_operand:SI 0 "s_register_operand" "=r")
9016         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9017                           [(match_operand 8 "cc_register" "") (const_int 0)])
9018                          (match_operator:SI 6 "shiftable_operator"
9019                           [(match_operand:SI 1 "s_register_operand" "r")
9020                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9021                          (match_operator:SI 7 "shiftable_operator"
9022                           [(match_operand:SI 3 "s_register_operand" "r")
9023                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9024   "TARGET_ARM"
9025   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9026   [(set_attr "conds" "use")
9027    (set_attr "length" "8")]
9028 )
9029
9030 (define_insn "*ifcompare_arith_move"
9031   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9032         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9033                           [(match_operand:SI 2 "s_register_operand" "r,r")
9034                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9035                          (match_operator:SI 7 "shiftable_operator"
9036                           [(match_operand:SI 4 "s_register_operand" "r,r")
9037                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9038                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9039    (clobber (reg:CC CC_REGNUM))]
9040   "TARGET_ARM"
9041   "*
9042   /* If we have an operation where (op x 0) is the identity operation and
9043      the conditional operator is LT or GE and we are comparing against zero and
9044      everything is in registers then we can do this in two instructions.  */
9045   if (operands[3] == const0_rtx
9046       && GET_CODE (operands[7]) != AND
9047       && GET_CODE (operands[5]) == REG
9048       && GET_CODE (operands[1]) == REG 
9049       && REGNO (operands[1]) == REGNO (operands[4])
9050       && REGNO (operands[4]) != REGNO (operands[0]))
9051     {
9052       if (GET_CODE (operands[6]) == LT)
9053         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9054       else if (GET_CODE (operands[6]) == GE)
9055         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9056     }
9057   if (GET_CODE (operands[3]) == CONST_INT
9058       && !const_ok_for_arm (INTVAL (operands[3])))
9059     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9060   else
9061     output_asm_insn (\"cmp\\t%2, %3\", operands);
9062   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9063   if (which_alternative != 0)
9064     return \"mov%D6\\t%0, %1\";
9065   return \"\";
9066   "
9067   [(set_attr "conds" "clob")
9068    (set_attr "length" "8,12")]
9069 )
9070
9071 (define_insn "*if_arith_move"
9072   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9073         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9074                           [(match_operand 6 "cc_register" "") (const_int 0)])
9075                          (match_operator:SI 5 "shiftable_operator"
9076                           [(match_operand:SI 2 "s_register_operand" "r,r")
9077                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9078                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9079   "TARGET_ARM"
9080   "@
9081    %I5%d4\\t%0, %2, %3
9082    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9083   [(set_attr "conds" "use")
9084    (set_attr "length" "4,8")
9085    (set_attr "type" "*,*")]
9086 )
9087
9088 (define_insn "*ifcompare_move_arith"
9089   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9090         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9091                           [(match_operand:SI 4 "s_register_operand" "r,r")
9092                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9093                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9094                          (match_operator:SI 7 "shiftable_operator"
9095                           [(match_operand:SI 2 "s_register_operand" "r,r")
9096                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9097    (clobber (reg:CC CC_REGNUM))]
9098   "TARGET_ARM"
9099   "*
9100   /* If we have an operation where (op x 0) is the identity operation and
9101      the conditional operator is LT or GE and we are comparing against zero and
9102      everything is in registers then we can do this in two instructions */
9103   if (operands[5] == const0_rtx
9104       && GET_CODE (operands[7]) != AND
9105       && GET_CODE (operands[3]) == REG
9106       && GET_CODE (operands[1]) == REG 
9107       && REGNO (operands[1]) == REGNO (operands[2])
9108       && REGNO (operands[2]) != REGNO (operands[0]))
9109     {
9110       if (GET_CODE (operands[6]) == GE)
9111         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9112       else if (GET_CODE (operands[6]) == LT)
9113         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9114     }
9115
9116   if (GET_CODE (operands[5]) == CONST_INT
9117       && !const_ok_for_arm (INTVAL (operands[5])))
9118     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9119   else
9120     output_asm_insn (\"cmp\\t%4, %5\", operands);
9121
9122   if (which_alternative != 0)
9123     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9124   return \"%I7%D6\\t%0, %2, %3\";
9125   "
9126   [(set_attr "conds" "clob")
9127    (set_attr "length" "8,12")]
9128 )
9129
9130 (define_insn "*if_move_arith"
9131   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9132         (if_then_else:SI
9133          (match_operator 4 "arm_comparison_operator"
9134           [(match_operand 6 "cc_register" "") (const_int 0)])
9135          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9136          (match_operator:SI 5 "shiftable_operator"
9137           [(match_operand:SI 2 "s_register_operand" "r,r")
9138            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9139   "TARGET_ARM"
9140   "@
9141    %I5%D4\\t%0, %2, %3
9142    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9143   [(set_attr "conds" "use")
9144    (set_attr "length" "4,8")
9145    (set_attr "type" "*,*")]
9146 )
9147
9148 (define_insn "*ifcompare_move_not"
9149   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9150         (if_then_else:SI
9151          (match_operator 5 "arm_comparison_operator"
9152           [(match_operand:SI 3 "s_register_operand" "r,r")
9153            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9154          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9155          (not:SI
9156           (match_operand:SI 2 "s_register_operand" "r,r"))))
9157    (clobber (reg:CC CC_REGNUM))]
9158   "TARGET_ARM"
9159   "#"
9160   [(set_attr "conds" "clob")
9161    (set_attr "length" "8,12")]
9162 )
9163
9164 (define_insn "*if_move_not"
9165   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9166         (if_then_else:SI
9167          (match_operator 4 "arm_comparison_operator"
9168           [(match_operand 3 "cc_register" "") (const_int 0)])
9169          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9170          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9171   "TARGET_ARM"
9172   "@
9173    mvn%D4\\t%0, %2
9174    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9175    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9176   [(set_attr "conds" "use")
9177    (set_attr "length" "4,8,8")]
9178 )
9179
9180 (define_insn "*ifcompare_not_move"
9181   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9182         (if_then_else:SI 
9183          (match_operator 5 "arm_comparison_operator"
9184           [(match_operand:SI 3 "s_register_operand" "r,r")
9185            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9186          (not:SI
9187           (match_operand:SI 2 "s_register_operand" "r,r"))
9188          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9189    (clobber (reg:CC CC_REGNUM))]
9190   "TARGET_ARM"
9191   "#"
9192   [(set_attr "conds" "clob")
9193    (set_attr "length" "8,12")]
9194 )
9195
9196 (define_insn "*if_not_move"
9197   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9198         (if_then_else:SI
9199          (match_operator 4 "arm_comparison_operator"
9200           [(match_operand 3 "cc_register" "") (const_int 0)])
9201          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9202          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9203   "TARGET_ARM"
9204   "@
9205    mvn%d4\\t%0, %2
9206    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9207    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9208   [(set_attr "conds" "use")
9209    (set_attr "length" "4,8,8")]
9210 )
9211
9212 (define_insn "*ifcompare_shift_move"
9213   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9214         (if_then_else:SI
9215          (match_operator 6 "arm_comparison_operator"
9216           [(match_operand:SI 4 "s_register_operand" "r,r")
9217            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9218          (match_operator:SI 7 "shift_operator"
9219           [(match_operand:SI 2 "s_register_operand" "r,r")
9220            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9221          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9222    (clobber (reg:CC CC_REGNUM))]
9223   "TARGET_ARM"
9224   "#"
9225   [(set_attr "conds" "clob")
9226    (set_attr "length" "8,12")]
9227 )
9228
9229 (define_insn "*if_shift_move"
9230   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9231         (if_then_else:SI
9232          (match_operator 5 "arm_comparison_operator"
9233           [(match_operand 6 "cc_register" "") (const_int 0)])
9234          (match_operator:SI 4 "shift_operator"
9235           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9236            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9237          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9238   "TARGET_ARM"
9239   "@
9240    mov%d5\\t%0, %2%S4
9241    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9242    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9243   [(set_attr "conds" "use")
9244    (set_attr "shift" "2")
9245    (set_attr "length" "4,8,8")
9246    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9247                       (const_string "alu_shift")
9248                       (const_string "alu_shift_reg")))]
9249 )
9250
9251 (define_insn "*ifcompare_move_shift"
9252   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9253         (if_then_else:SI
9254          (match_operator 6 "arm_comparison_operator"
9255           [(match_operand:SI 4 "s_register_operand" "r,r")
9256            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9257          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9258          (match_operator:SI 7 "shift_operator"
9259           [(match_operand:SI 2 "s_register_operand" "r,r")
9260            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9261    (clobber (reg:CC CC_REGNUM))]
9262   "TARGET_ARM"
9263   "#"
9264   [(set_attr "conds" "clob")
9265    (set_attr "length" "8,12")]
9266 )
9267
9268 (define_insn "*if_move_shift"
9269   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9270         (if_then_else:SI
9271          (match_operator 5 "arm_comparison_operator"
9272           [(match_operand 6 "cc_register" "") (const_int 0)])
9273          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9274          (match_operator:SI 4 "shift_operator"
9275           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9276            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9277   "TARGET_ARM"
9278   "@
9279    mov%D5\\t%0, %2%S4
9280    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9281    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9282   [(set_attr "conds" "use")
9283    (set_attr "shift" "2")
9284    (set_attr "length" "4,8,8")
9285    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9286                       (const_string "alu_shift")
9287                       (const_string "alu_shift_reg")))]
9288 )
9289
9290 (define_insn "*ifcompare_shift_shift"
9291   [(set (match_operand:SI 0 "s_register_operand" "=r")
9292         (if_then_else:SI
9293          (match_operator 7 "arm_comparison_operator"
9294           [(match_operand:SI 5 "s_register_operand" "r")
9295            (match_operand:SI 6 "arm_add_operand" "rIL")])
9296          (match_operator:SI 8 "shift_operator"
9297           [(match_operand:SI 1 "s_register_operand" "r")
9298            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9299          (match_operator:SI 9 "shift_operator"
9300           [(match_operand:SI 3 "s_register_operand" "r")
9301            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9302    (clobber (reg:CC CC_REGNUM))]
9303   "TARGET_ARM"
9304   "#"
9305   [(set_attr "conds" "clob")
9306    (set_attr "length" "12")]
9307 )
9308
9309 (define_insn "*if_shift_shift"
9310   [(set (match_operand:SI 0 "s_register_operand" "=r")
9311         (if_then_else:SI
9312          (match_operator 5 "arm_comparison_operator"
9313           [(match_operand 8 "cc_register" "") (const_int 0)])
9314          (match_operator:SI 6 "shift_operator"
9315           [(match_operand:SI 1 "s_register_operand" "r")
9316            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9317          (match_operator:SI 7 "shift_operator"
9318           [(match_operand:SI 3 "s_register_operand" "r")
9319            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9320   "TARGET_ARM"
9321   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9322   [(set_attr "conds" "use")
9323    (set_attr "shift" "1")
9324    (set_attr "length" "8")
9325    (set (attr "type") (if_then_else
9326                         (and (match_operand 2 "const_int_operand" "")
9327                              (match_operand 4 "const_int_operand" ""))
9328                       (const_string "alu_shift")
9329                       (const_string "alu_shift_reg")))]
9330 )
9331
9332 (define_insn "*ifcompare_not_arith"
9333   [(set (match_operand:SI 0 "s_register_operand" "=r")
9334         (if_then_else:SI
9335          (match_operator 6 "arm_comparison_operator"
9336           [(match_operand:SI 4 "s_register_operand" "r")
9337            (match_operand:SI 5 "arm_add_operand" "rIL")])
9338          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9339          (match_operator:SI 7 "shiftable_operator"
9340           [(match_operand:SI 2 "s_register_operand" "r")
9341            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9342    (clobber (reg:CC CC_REGNUM))]
9343   "TARGET_ARM"
9344   "#"
9345   [(set_attr "conds" "clob")
9346    (set_attr "length" "12")]
9347 )
9348
9349 (define_insn "*if_not_arith"
9350   [(set (match_operand:SI 0 "s_register_operand" "=r")
9351         (if_then_else:SI
9352          (match_operator 5 "arm_comparison_operator"
9353           [(match_operand 4 "cc_register" "") (const_int 0)])
9354          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9355          (match_operator:SI 6 "shiftable_operator"
9356           [(match_operand:SI 2 "s_register_operand" "r")
9357            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9358   "TARGET_ARM"
9359   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9360   [(set_attr "conds" "use")
9361    (set_attr "length" "8")]
9362 )
9363
9364 (define_insn "*ifcompare_arith_not"
9365   [(set (match_operand:SI 0 "s_register_operand" "=r")
9366         (if_then_else:SI
9367          (match_operator 6 "arm_comparison_operator"
9368           [(match_operand:SI 4 "s_register_operand" "r")
9369            (match_operand:SI 5 "arm_add_operand" "rIL")])
9370          (match_operator:SI 7 "shiftable_operator"
9371           [(match_operand:SI 2 "s_register_operand" "r")
9372            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9373          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9374    (clobber (reg:CC CC_REGNUM))]
9375   "TARGET_ARM"
9376   "#"
9377   [(set_attr "conds" "clob")
9378    (set_attr "length" "12")]
9379 )
9380
9381 (define_insn "*if_arith_not"
9382   [(set (match_operand:SI 0 "s_register_operand" "=r")
9383         (if_then_else:SI
9384          (match_operator 5 "arm_comparison_operator"
9385           [(match_operand 4 "cc_register" "") (const_int 0)])
9386          (match_operator:SI 6 "shiftable_operator"
9387           [(match_operand:SI 2 "s_register_operand" "r")
9388            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9389          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9390   "TARGET_ARM"
9391   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9392   [(set_attr "conds" "use")
9393    (set_attr "length" "8")]
9394 )
9395
9396 (define_insn "*ifcompare_neg_move"
9397   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9398         (if_then_else:SI
9399          (match_operator 5 "arm_comparison_operator"
9400           [(match_operand:SI 3 "s_register_operand" "r,r")
9401            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9402          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9403          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9404    (clobber (reg:CC CC_REGNUM))]
9405   "TARGET_ARM"
9406   "#"
9407   [(set_attr "conds" "clob")
9408    (set_attr "length" "8,12")]
9409 )
9410
9411 (define_insn "*if_neg_move"
9412   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9413         (if_then_else:SI
9414          (match_operator 4 "arm_comparison_operator"
9415           [(match_operand 3 "cc_register" "") (const_int 0)])
9416          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9417          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9418   "TARGET_ARM"
9419   "@
9420    rsb%d4\\t%0, %2, #0
9421    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9422    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9423   [(set_attr "conds" "use")
9424    (set_attr "length" "4,8,8")]
9425 )
9426
9427 (define_insn "*ifcompare_move_neg"
9428   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9429         (if_then_else:SI
9430          (match_operator 5 "arm_comparison_operator"
9431           [(match_operand:SI 3 "s_register_operand" "r,r")
9432            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9433          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9434          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9435    (clobber (reg:CC CC_REGNUM))]
9436   "TARGET_ARM"
9437   "#"
9438   [(set_attr "conds" "clob")
9439    (set_attr "length" "8,12")]
9440 )
9441
9442 (define_insn "*if_move_neg"
9443   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9444         (if_then_else:SI
9445          (match_operator 4 "arm_comparison_operator"
9446           [(match_operand 3 "cc_register" "") (const_int 0)])
9447          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9448          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9449   "TARGET_ARM"
9450   "@
9451    rsb%D4\\t%0, %2, #0
9452    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9453    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9454   [(set_attr "conds" "use")
9455    (set_attr "length" "4,8,8")]
9456 )
9457
9458 (define_insn "*arith_adjacentmem"
9459   [(set (match_operand:SI 0 "s_register_operand" "=r")
9460         (match_operator:SI 1 "shiftable_operator"
9461          [(match_operand:SI 2 "memory_operand" "m")
9462           (match_operand:SI 3 "memory_operand" "m")]))
9463    (clobber (match_scratch:SI 4 "=r"))]
9464   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9465   "*
9466   {
9467     rtx ldm[3];
9468     rtx arith[4];
9469     rtx base_reg;
9470     HOST_WIDE_INT val1 = 0, val2 = 0;
9471
9472     if (REGNO (operands[0]) > REGNO (operands[4]))
9473       {
9474         ldm[1] = operands[4];
9475         ldm[2] = operands[0];
9476       }
9477     else
9478       {
9479         ldm[1] = operands[0];
9480         ldm[2] = operands[4];
9481       }
9482
9483     base_reg = XEXP (operands[2], 0);
9484
9485     if (!REG_P (base_reg))
9486       {
9487         val1 = INTVAL (XEXP (base_reg, 1));
9488         base_reg = XEXP (base_reg, 0);
9489       }
9490
9491     if (!REG_P (XEXP (operands[3], 0)))
9492       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9493
9494     arith[0] = operands[0];
9495     arith[3] = operands[1];
9496
9497     if (val1 < val2)
9498       {
9499         arith[1] = ldm[1];
9500         arith[2] = ldm[2];
9501       }
9502     else
9503       {
9504         arith[1] = ldm[2];
9505         arith[2] = ldm[1];
9506       }
9507
9508     ldm[0] = base_reg;
9509     if (val1 !=0 && val2 != 0)
9510       {
9511         rtx ops[3];
9512
9513         if (val1 == 4 || val2 == 4)
9514           /* Other val must be 8, since we know they are adjacent and neither
9515              is zero.  */
9516           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9517         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9518           {
9519             ldm[0] = ops[0] = operands[4];
9520             ops[1] = base_reg;
9521             ops[2] = GEN_INT (val1);
9522             output_add_immediate (ops);
9523             if (val1 < val2)
9524               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9525             else
9526               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9527           }
9528         else
9529           {
9530             /* Offset is out of range for a single add, so use two ldr.  */
9531             ops[0] = ldm[1];
9532             ops[1] = base_reg;
9533             ops[2] = GEN_INT (val1);
9534             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9535             ops[0] = ldm[2];
9536             ops[2] = GEN_INT (val2);
9537             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9538           }
9539       }
9540     else if (val1 != 0)
9541       {
9542         if (val1 < val2)
9543           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9544         else
9545           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9546       }
9547     else
9548       {
9549         if (val1 < val2)
9550           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9551         else
9552           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9553       }
9554     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9555     return \"\";
9556   }"
9557   [(set_attr "length" "12")
9558    (set_attr "predicable" "yes")
9559    (set_attr "type" "load1")]
9560 )
9561
9562 ; This pattern is never tried by combine, so do it as a peephole
9563
9564 (define_peephole2
9565   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9566         (match_operand:SI 1 "arm_general_register_operand" ""))
9567    (set (reg:CC CC_REGNUM)
9568         (compare:CC (match_dup 1) (const_int 0)))]
9569   "TARGET_ARM"
9570   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9571               (set (match_dup 0) (match_dup 1))])]
9572   ""
9573 )
9574
9575 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9576 ; reversed, check that the memory references aren't volatile.
9577
9578 (define_peephole
9579   [(set (match_operand:SI 0 "s_register_operand" "=r")
9580         (match_operand:SI 4 "memory_operand" "m"))
9581    (set (match_operand:SI 1 "s_register_operand" "=r")
9582         (match_operand:SI 5 "memory_operand" "m"))
9583    (set (match_operand:SI 2 "s_register_operand" "=r")
9584         (match_operand:SI 6 "memory_operand" "m"))
9585    (set (match_operand:SI 3 "s_register_operand" "=r")
9586         (match_operand:SI 7 "memory_operand" "m"))]
9587   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9588   "*
9589   return emit_ldm_seq (operands, 4);
9590   "
9591 )
9592
9593 (define_peephole
9594   [(set (match_operand:SI 0 "s_register_operand" "=r")
9595         (match_operand:SI 3 "memory_operand" "m"))
9596    (set (match_operand:SI 1 "s_register_operand" "=r")
9597         (match_operand:SI 4 "memory_operand" "m"))
9598    (set (match_operand:SI 2 "s_register_operand" "=r")
9599         (match_operand:SI 5 "memory_operand" "m"))]
9600   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9601   "*
9602   return emit_ldm_seq (operands, 3);
9603   "
9604 )
9605
9606 (define_peephole
9607   [(set (match_operand:SI 0 "s_register_operand" "=r")
9608         (match_operand:SI 2 "memory_operand" "m"))
9609    (set (match_operand:SI 1 "s_register_operand" "=r")
9610         (match_operand:SI 3 "memory_operand" "m"))]
9611   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9612   "*
9613   return emit_ldm_seq (operands, 2);
9614   "
9615 )
9616
9617 (define_peephole
9618   [(set (match_operand:SI 4 "memory_operand" "=m")
9619         (match_operand:SI 0 "s_register_operand" "r"))
9620    (set (match_operand:SI 5 "memory_operand" "=m")
9621         (match_operand:SI 1 "s_register_operand" "r"))
9622    (set (match_operand:SI 6 "memory_operand" "=m")
9623         (match_operand:SI 2 "s_register_operand" "r"))
9624    (set (match_operand:SI 7 "memory_operand" "=m")
9625         (match_operand:SI 3 "s_register_operand" "r"))]
9626   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9627   "*
9628   return emit_stm_seq (operands, 4);
9629   "
9630 )
9631
9632 (define_peephole
9633   [(set (match_operand:SI 3 "memory_operand" "=m")
9634         (match_operand:SI 0 "s_register_operand" "r"))
9635    (set (match_operand:SI 4 "memory_operand" "=m")
9636         (match_operand:SI 1 "s_register_operand" "r"))
9637    (set (match_operand:SI 5 "memory_operand" "=m")
9638         (match_operand:SI 2 "s_register_operand" "r"))]
9639   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9640   "*
9641   return emit_stm_seq (operands, 3);
9642   "
9643 )
9644
9645 (define_peephole
9646   [(set (match_operand:SI 2 "memory_operand" "=m")
9647         (match_operand:SI 0 "s_register_operand" "r"))
9648    (set (match_operand:SI 3 "memory_operand" "=m")
9649         (match_operand:SI 1 "s_register_operand" "r"))]
9650   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9651   "*
9652   return emit_stm_seq (operands, 2);
9653   "
9654 )
9655
9656 (define_split
9657   [(set (match_operand:SI 0 "s_register_operand" "")
9658         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9659                        (const_int 0))
9660                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9661                          [(match_operand:SI 3 "s_register_operand" "")
9662                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9663    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9664   "TARGET_ARM"
9665   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9666    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9667                               (match_dup 5)))]
9668   ""
9669 )
9670
9671 ;; This split can be used because CC_Z mode implies that the following
9672 ;; branch will be an equality, or an unsigned inequality, so the sign
9673 ;; extension is not needed.
9674
9675 (define_split
9676   [(set (reg:CC_Z CC_REGNUM)
9677         (compare:CC_Z
9678          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9679                     (const_int 24))
9680          (match_operand 1 "const_int_operand" "")))
9681    (clobber (match_scratch:SI 2 ""))]
9682   "TARGET_ARM
9683    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9684        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9685   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9686    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9687   "
9688   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9689   "
9690 )
9691
9692 (define_expand "prologue"
9693   [(clobber (const_int 0))]
9694   "TARGET_EITHER"
9695   "if (TARGET_ARM)
9696      arm_expand_prologue ();
9697    else
9698      thumb_expand_prologue ();
9699   DONE;
9700   "
9701 )
9702
9703 (define_expand "epilogue"
9704   [(clobber (const_int 0))]
9705   "TARGET_EITHER"
9706   "
9707   if (current_function_calls_eh_return)
9708     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9709   if (TARGET_THUMB)
9710     thumb_expand_epilogue ();
9711   else if (USE_RETURN_INSN (FALSE))
9712     {
9713       emit_jump_insn (gen_return ());
9714       DONE;
9715     }
9716   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9717         gen_rtvec (1,
9718                 gen_rtx_RETURN (VOIDmode)),
9719         VUNSPEC_EPILOGUE));
9720   DONE;
9721   "
9722 )
9723
9724 ;; Note - although unspec_volatile's USE all hard registers,
9725 ;; USEs are ignored after relaod has completed.  Thus we need
9726 ;; to add an unspec of the link register to ensure that flow
9727 ;; does not think that it is unused by the sibcall branch that
9728 ;; will replace the standard function epilogue.
9729 (define_insn "sibcall_epilogue"
9730   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9731               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9732   "TARGET_ARM"
9733   "*
9734   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9735     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9736   return arm_output_epilogue (next_nonnote_insn (insn));
9737   "
9738 ;; Length is absolute worst case
9739   [(set_attr "length" "44")
9740    (set_attr "type" "block")
9741    ;; We don't clobber the conditions, but the potential length of this
9742    ;; operation is sufficient to make conditionalizing the sequence 
9743    ;; unlikely to be profitable.
9744    (set_attr "conds" "clob")]
9745 )
9746
9747 (define_insn "*epilogue_insns"
9748   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9749   "TARGET_EITHER"
9750   "*
9751   if (TARGET_ARM)
9752     return arm_output_epilogue (NULL);
9753   else /* TARGET_THUMB */
9754     return thumb_unexpanded_epilogue ();
9755   "
9756   ; Length is absolute worst case
9757   [(set_attr "length" "44")
9758    (set_attr "type" "block")
9759    ;; We don't clobber the conditions, but the potential length of this
9760    ;; operation is sufficient to make conditionalizing the sequence 
9761    ;; unlikely to be profitable.
9762    (set_attr "conds" "clob")]
9763 )
9764
9765 (define_expand "eh_epilogue"
9766   [(use (match_operand:SI 0 "register_operand" ""))
9767    (use (match_operand:SI 1 "register_operand" ""))
9768    (use (match_operand:SI 2 "register_operand" ""))]
9769   "TARGET_EITHER"
9770   "
9771   {
9772     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9773     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9774       {
9775         rtx ra = gen_rtx_REG (Pmode, 2);
9776
9777         emit_move_insn (ra, operands[2]);
9778         operands[2] = ra;
9779       }
9780     /* This is a hack -- we may have crystalized the function type too
9781        early.  */
9782     cfun->machine->func_type = 0;
9783   }"
9784 )
9785
9786 ;; This split is only used during output to reduce the number of patterns
9787 ;; that need assembler instructions adding to them.  We allowed the setting
9788 ;; of the conditions to be implicit during rtl generation so that
9789 ;; the conditional compare patterns would work.  However this conflicts to
9790 ;; some extent with the conditional data operations, so we have to split them
9791 ;; up again here.
9792
9793 (define_split
9794   [(set (match_operand:SI 0 "s_register_operand" "")
9795         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9796                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9797                          (match_dup 0)
9798                          (match_operand 4 "" "")))
9799    (clobber (reg:CC CC_REGNUM))]
9800   "TARGET_ARM && reload_completed"
9801   [(set (match_dup 5) (match_dup 6))
9802    (cond_exec (match_dup 7)
9803               (set (match_dup 0) (match_dup 4)))]
9804   "
9805   {
9806     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9807                                              operands[2], operands[3]);
9808     enum rtx_code rc = GET_CODE (operands[1]);
9809
9810     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9811     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9812     if (mode == CCFPmode || mode == CCFPEmode)
9813       rc = reverse_condition_maybe_unordered (rc);
9814     else
9815       rc = reverse_condition (rc);
9816
9817     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9818   }"
9819 )
9820
9821 (define_split
9822   [(set (match_operand:SI 0 "s_register_operand" "")
9823         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9824                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9825                          (match_operand 4 "" "")
9826                          (match_dup 0)))
9827    (clobber (reg:CC CC_REGNUM))]
9828   "TARGET_ARM && reload_completed"
9829   [(set (match_dup 5) (match_dup 6))
9830    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9831               (set (match_dup 0) (match_dup 4)))]
9832   "
9833   {
9834     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9835                                              operands[2], operands[3]);
9836
9837     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9838     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9839   }"
9840 )
9841
9842 (define_split
9843   [(set (match_operand:SI 0 "s_register_operand" "")
9844         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9845                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9846                          (match_operand 4 "" "")
9847                          (match_operand 5 "" "")))
9848    (clobber (reg:CC CC_REGNUM))]
9849   "TARGET_ARM && reload_completed"
9850   [(set (match_dup 6) (match_dup 7))
9851    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9852               (set (match_dup 0) (match_dup 4)))
9853    (cond_exec (match_dup 8)
9854               (set (match_dup 0) (match_dup 5)))]
9855   "
9856   {
9857     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9858                                              operands[2], operands[3]);
9859     enum rtx_code rc = GET_CODE (operands[1]);
9860
9861     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9862     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9863     if (mode == CCFPmode || mode == CCFPEmode)
9864       rc = reverse_condition_maybe_unordered (rc);
9865     else
9866       rc = reverse_condition (rc);
9867
9868     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9869   }"
9870 )
9871
9872 (define_split
9873   [(set (match_operand:SI 0 "s_register_operand" "")
9874         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9875                           [(match_operand:SI 2 "s_register_operand" "")
9876                            (match_operand:SI 3 "arm_add_operand" "")])
9877                          (match_operand:SI 4 "arm_rhs_operand" "")
9878                          (not:SI
9879                           (match_operand:SI 5 "s_register_operand" ""))))
9880    (clobber (reg:CC CC_REGNUM))]
9881   "TARGET_ARM && reload_completed"
9882   [(set (match_dup 6) (match_dup 7))
9883    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9884               (set (match_dup 0) (match_dup 4)))
9885    (cond_exec (match_dup 8)
9886               (set (match_dup 0) (not:SI (match_dup 5))))]
9887   "
9888   {
9889     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9890                                              operands[2], operands[3]);
9891     enum rtx_code rc = GET_CODE (operands[1]);
9892
9893     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9894     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9895     if (mode == CCFPmode || mode == CCFPEmode)
9896       rc = reverse_condition_maybe_unordered (rc);
9897     else
9898       rc = reverse_condition (rc);
9899
9900     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9901   }"
9902 )
9903
9904 (define_insn "*cond_move_not"
9905   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9906         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9907                           [(match_operand 3 "cc_register" "") (const_int 0)])
9908                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9909                          (not:SI
9910                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9911   "TARGET_ARM"
9912   "@
9913    mvn%D4\\t%0, %2
9914    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9915   [(set_attr "conds" "use")
9916    (set_attr "length" "4,8")]
9917 )
9918
9919 ;; The next two patterns occur when an AND operation is followed by a
9920 ;; scc insn sequence 
9921
9922 (define_insn "*sign_extract_onebit"
9923   [(set (match_operand:SI 0 "s_register_operand" "=r")
9924         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9925                          (const_int 1)
9926                          (match_operand:SI 2 "const_int_operand" "n")))
9927     (clobber (reg:CC CC_REGNUM))]
9928   "TARGET_ARM"
9929   "*
9930     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9931     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9932     return \"mvnne\\t%0, #0\";
9933   "
9934   [(set_attr "conds" "clob")
9935    (set_attr "length" "8")]
9936 )
9937
9938 (define_insn "*not_signextract_onebit"
9939   [(set (match_operand:SI 0 "s_register_operand" "=r")
9940         (not:SI
9941          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9942                           (const_int 1)
9943                           (match_operand:SI 2 "const_int_operand" "n"))))
9944    (clobber (reg:CC CC_REGNUM))]
9945   "TARGET_ARM"
9946   "*
9947     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9948     output_asm_insn (\"tst\\t%1, %2\", operands);
9949     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9950     return \"movne\\t%0, #0\";
9951   "
9952   [(set_attr "conds" "clob")
9953    (set_attr "length" "12")]
9954 )
9955
9956 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9957 ;; expressions.  For simplicity, the first register is also in the unspec
9958 ;; part.
9959 (define_insn "*push_multi"
9960   [(match_parallel 2 "multi_register_push"
9961     [(set (match_operand:BLK 0 "memory_operand" "=m")
9962           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9963                       UNSPEC_PUSH_MULT))])]
9964   "TARGET_ARM"
9965   "*
9966   {
9967     int num_saves = XVECLEN (operands[2], 0);
9968      
9969     /* For the StrongARM at least it is faster to
9970        use STR to store only a single register.  */
9971     if (num_saves == 1)
9972       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9973     else
9974       {
9975         int i;
9976         char pattern[100];
9977
9978         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9979
9980         for (i = 1; i < num_saves; i++)
9981           {
9982             strcat (pattern, \", %|\");
9983             strcat (pattern,
9984                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9985           }
9986
9987         strcat (pattern, \"}\");
9988         output_asm_insn (pattern, operands);
9989       }
9990
9991     return \"\";
9992   }"
9993   [(set_attr "type" "store4")]
9994 )
9995
9996 (define_insn "stack_tie"
9997   [(set (mem:BLK (scratch))
9998         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9999                      (match_operand:SI 1 "s_register_operand" "r")]
10000                     UNSPEC_PRLG_STK))]
10001   ""
10002   ""
10003   [(set_attr "length" "0")]
10004 )
10005
10006 ;; Similarly for the floating point registers
10007 (define_insn "*push_fp_multi"
10008   [(match_parallel 2 "multi_register_push"
10009     [(set (match_operand:BLK 0 "memory_operand" "=m")
10010           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10011                       UNSPEC_PUSH_MULT))])]
10012   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10013   "*
10014   {
10015     char pattern[100];
10016
10017     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10018     output_asm_insn (pattern, operands);
10019     return \"\";
10020   }"
10021   [(set_attr "type" "f_store")]
10022 )
10023
10024 ;; Special patterns for dealing with the constant pool
10025
10026 (define_insn "align_4"
10027   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10028   "TARGET_EITHER"
10029   "*
10030   assemble_align (32);
10031   return \"\";
10032   "
10033 )
10034
10035 (define_insn "align_8"
10036   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10037   "TARGET_EITHER"
10038   "*
10039   assemble_align (64);
10040   return \"\";
10041   "
10042 )
10043
10044 (define_insn "consttable_end"
10045   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10046   "TARGET_EITHER"
10047   "*
10048   making_const_table = FALSE;
10049   return \"\";
10050   "
10051 )
10052
10053 (define_insn "consttable_1"
10054   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10055   "TARGET_THUMB"
10056   "*
10057   making_const_table = TRUE;
10058   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10059   assemble_zeros (3);
10060   return \"\";
10061   "
10062   [(set_attr "length" "4")]
10063 )
10064
10065 (define_insn "consttable_2"
10066   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10067   "TARGET_THUMB"
10068   "*
10069   making_const_table = TRUE;
10070   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10071   assemble_zeros (2);
10072   return \"\";
10073   "
10074   [(set_attr "length" "4")]
10075 )
10076
10077 (define_insn "consttable_4"
10078   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10079   "TARGET_EITHER"
10080   "*
10081   {
10082     making_const_table = TRUE;
10083     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10084       {
10085       case MODE_FLOAT:
10086       {
10087         REAL_VALUE_TYPE r;
10088         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10089         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10090         break;
10091       }
10092       default:
10093         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10094         break;
10095       }
10096     return \"\";
10097   }"
10098   [(set_attr "length" "4")]
10099 )
10100
10101 (define_insn "consttable_8"
10102   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10103   "TARGET_EITHER"
10104   "*
10105   {
10106     making_const_table = TRUE;
10107     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10108       {
10109        case MODE_FLOAT:
10110         {
10111           REAL_VALUE_TYPE r;
10112           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10113           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10114           break;
10115         }
10116       default:
10117         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10118         break;
10119       }
10120     return \"\";
10121   }"
10122   [(set_attr "length" "8")]
10123 )
10124
10125 ;; Miscellaneous Thumb patterns
10126
10127 (define_expand "tablejump"
10128   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10129               (use (label_ref (match_operand 1 "" "")))])]
10130   "TARGET_THUMB"
10131   "
10132   if (flag_pic)
10133     {
10134       /* Hopefully, CSE will eliminate this copy.  */
10135       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10136       rtx reg2 = gen_reg_rtx (SImode);
10137
10138       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10139       operands[0] = reg2;
10140     }
10141   "
10142 )
10143
10144 ;; NB never uses BX.
10145 (define_insn "*thumb_tablejump"
10146   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10147    (use (label_ref (match_operand 1 "" "")))]
10148   "TARGET_THUMB"
10149   "mov\\t%|pc, %0"
10150   [(set_attr "length" "2")]
10151 )
10152
10153 ;; V5 Instructions,
10154
10155 (define_insn "clzsi2"
10156   [(set (match_operand:SI 0 "s_register_operand" "=r")
10157         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10158   "TARGET_ARM && arm_arch5"
10159   "clz%?\\t%0, %1"
10160   [(set_attr "predicable" "yes")])
10161
10162 (define_expand "ffssi2"
10163   [(set (match_operand:SI 0 "s_register_operand" "")
10164         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10165   "TARGET_ARM && arm_arch5"
10166   "
10167   {
10168     rtx t1, t2, t3;
10169
10170     t1 = gen_reg_rtx (SImode);
10171     t2 = gen_reg_rtx (SImode);
10172     t3 = gen_reg_rtx (SImode);
10173
10174     emit_insn (gen_negsi2 (t1, operands[1]));
10175     emit_insn (gen_andsi3 (t2, operands[1], t1));
10176     emit_insn (gen_clzsi2 (t3, t2));
10177     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10178     DONE;
10179   }"
10180 )
10181
10182 (define_expand "ctzsi2"
10183   [(set (match_operand:SI 0 "s_register_operand" "")
10184         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10185   "TARGET_ARM && arm_arch5"
10186   "
10187   {
10188     rtx t1, t2, t3;
10189
10190     t1 = gen_reg_rtx (SImode);
10191     t2 = gen_reg_rtx (SImode);
10192     t3 = gen_reg_rtx (SImode);
10193
10194     emit_insn (gen_negsi2 (t1, operands[1]));
10195     emit_insn (gen_andsi3 (t2, operands[1], t1));
10196     emit_insn (gen_clzsi2 (t3, t2));
10197     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10198     DONE;
10199   }"
10200 )
10201
10202 ;; V5E instructions.
10203
10204 (define_insn "prefetch"
10205   [(prefetch (match_operand:SI 0 "address_operand" "p")
10206              (match_operand:SI 1 "" "")
10207              (match_operand:SI 2 "" ""))]
10208   "TARGET_ARM && arm_arch5e"
10209   "pld\\t%a0")
10210
10211 ;; General predication pattern
10212
10213 (define_cond_exec
10214   [(match_operator 0 "arm_comparison_operator"
10215     [(match_operand 1 "cc_register" "")
10216      (const_int 0)])]
10217   "TARGET_ARM"
10218   ""
10219 )
10220
10221 (define_insn "prologue_use"
10222   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10223   ""
10224   "%@ %0 needed for prologue"
10225 )
10226
10227
10228 ;; Patterns for exception handling
10229
10230 (define_expand "eh_return"
10231   [(use (match_operand 0 "general_operand" ""))]
10232   "TARGET_EITHER"
10233   "
10234   {
10235     if (TARGET_ARM)
10236       emit_insn (gen_arm_eh_return (operands[0]));
10237     else
10238       emit_insn (gen_thumb_eh_return (operands[0]));
10239     DONE;
10240   }"
10241 )
10242                                    
10243 ;; We can't expand this before we know where the link register is stored.
10244 (define_insn_and_split "arm_eh_return"
10245   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10246                     VUNSPEC_EH_RETURN)
10247    (clobber (match_scratch:SI 1 "=&r"))]
10248   "TARGET_ARM"
10249   "#"
10250   "&& reload_completed"
10251   [(const_int 0)]
10252   "
10253   {
10254     arm_set_return_address (operands[0], operands[1]);
10255     DONE;
10256   }"
10257 )
10258
10259 (define_insn_and_split "thumb_eh_return"
10260   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10261                     VUNSPEC_EH_RETURN)
10262    (clobber (match_scratch:SI 1 "=&l"))]
10263   "TARGET_THUMB"
10264   "#"
10265   "&& reload_completed"
10266   [(const_int 0)]
10267   "
10268   {
10269     thumb_set_return_address (operands[0], operands[1]);
10270     DONE;
10271   }"
10272 )
10273
10274 \f
10275 ;; TLS support
10276
10277 (define_insn "load_tp_hard"
10278   [(set (match_operand:SI 0 "register_operand" "=r")
10279         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10280   "TARGET_HARD_TP"
10281   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10282   [(set_attr "predicable" "yes")]
10283 )
10284
10285 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10286 (define_insn "load_tp_soft"
10287   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10288    (clobber (reg:SI LR_REGNUM))
10289    (clobber (reg:SI IP_REGNUM))
10290    (clobber (reg:CC CC_REGNUM))]
10291   "TARGET_SOFT_TP"
10292   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10293   [(set_attr "conds" "clob")]
10294 )
10295
10296 ;; Load the FPA co-processor patterns
10297 (include "fpa.md")
10298 ;; Load the Maverick co-processor patterns
10299 (include "cirrus.md")
10300 ;; Load the Intel Wireless Multimedia Extension patterns
10301 (include "iwmmxt.md")
10302 ;; Load the VFP co-processor patterns
10303 (include "vfp.md")
10304