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 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).
8 ;; This file is part of GCC.
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.
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.
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.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
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
44 ;; 3rd operand to select_dominance_cc_mode
53 ;; Note: sin and cos are no-longer used.
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 ...)
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
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.
96 ;; UNSPEC_VOLATILE Usage:
99 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
101 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102 ; instruction epilogue sequence that isn't expanded
103 ; into normal RTL. Used for both normal and sibcall
105 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
106 ; for inlined constants.
107 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
109 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
111 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
113 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
115 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
117 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
118 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
119 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
120 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
121 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
128 ;;---------------------------------------------------------------------------
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code. This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted. Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit. If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns. (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151 (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed. If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168 [(set_attr "conds" "clob")
169 (set_attr "length" "4")
170 (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern. This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
177 "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"
178 (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu any alu instruction that doesn't hit memory or fp
187 ; regs or have a shifted source operand
188 ; alu_shift any data instruction that doesn't hit memory or fp
189 ; regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ; regs, but has a source operand shifted by a register value
192 ; mult a multiply instruction
193 ; block blockage insn, this blocks all functional units
194 ; float a floating point arithmetic operation (subject to expansion)
195 ; fdivd DFmode floating point division
196 ; fdivs SFmode floating point division
197 ; fmul Floating point multiply
198 ; ffmul Fast floating point multiply
199 ; farith Floating point arithmetic (4 cycle)
200 ; ffarith Fast floating point arithmetic (2 cycle)
201 ; float_em a floating point arithmetic operation that is normally emulated
202 ; even on a machine with an fpa.
203 ; f_load a floating point load from memory
204 ; f_store a floating point store to memory
205 ; f_load[sd] single/double load from memory
206 ; f_store[sd] single/double store to memory
207 ; f_flag a transfer of co-processor flags to the CPSR
208 ; f_mem_r a transfer of a floating point register to a real reg via mem
209 ; r_mem_f the reverse of f_mem_r
210 ; f_2_r fast transfer float to arm (no memory needed)
211 ; r_2_f fast transfer arm to float
212 ; f_cvt convert floating<->integral
214 ; call a subroutine call
215 ; load_byte load byte(s) from memory to arm registers
216 ; load1 load 1 word from memory to arm registers
217 ; load2 load 2 words from memory to arm registers
218 ; load3 load 3 words from memory to arm registers
219 ; load4 load 4 words from memory to arm registers
220 ; store store 1 word to memory from arm registers
221 ; store2 store 2 words
222 ; store3 store 3 words
223 ; store4 store 4 (or more) words
224 ; Additions for Cirrus Maverick co-processor:
225 ; mav_farith Floating point arithmetic (4 cycle)
226 ; mav_dmult Double multiplies (7 cycle)
229 "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"
231 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
232 (const_string "mult")
233 (const_string "alu")))
235 ; Load scheduling, set from the arm_ld_sched variable
236 ; initialized by arm_override_options()
237 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
239 ; condition codes: this one is used by final_prescan_insn to speed up
240 ; conditionalizing instructions. It saves having to scan the rtl to see if
241 ; it uses or alters the condition codes.
243 ; USE means that the condition codes are used by the insn in the process of
244 ; outputting code, this means (at present) that we can't use the insn in
247 ; SET means that the purpose of the insn is to set the condition codes in a
248 ; well defined manner.
250 ; CLOB means that the condition codes are altered in an undefined manner, if
251 ; they are altered at all
253 ; JUMP_CLOB is used when the condition cannot be represented by a single
254 ; instruction (UNEQ and LTGT). These cannot be predicated.
256 ; NOCOND means that the condition codes are neither altered nor affect the
257 ; output of this insn
259 (define_attr "conds" "use,set,clob,jump_clob,nocond"
260 (if_then_else (eq_attr "type" "call")
261 (const_string "clob")
262 (const_string "nocond")))
264 ; Predicable means that the insn can be conditionally executed based on
265 ; an automatically added predicate (additional patterns are generated by
266 ; gen...). We default to 'no' because no Thumb patterns match this rule
267 ; and not all ARM patterns do.
268 (define_attr "predicable" "no,yes" (const_string "no"))
270 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
271 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
272 ; suffer blockages enough to warrant modelling this (and it can adversely
273 ; affect the schedule).
274 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
276 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
277 ; to stall the processor. Used with model_wbuf above.
278 (define_attr "write_conflict" "no,yes"
279 (if_then_else (eq_attr "type"
280 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
282 (const_string "no")))
284 ; Classify the insns into those that take one cycle and those that take more
285 ; than one on the main cpu execution unit.
286 (define_attr "core_cycles" "single,multi"
287 (if_then_else (eq_attr "type"
288 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
289 (const_string "single")
290 (const_string "multi")))
292 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
293 ;; distant label. Only applicable to Thumb code.
294 (define_attr "far_jump" "yes,no" (const_string "no"))
297 ;;---------------------------------------------------------------------------
300 ; A list of modes that are exactly 64 bits in size. We use this to expand
301 ; some splits that are the same for all modes when operating on ARM
303 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
305 ;;---------------------------------------------------------------------------
308 (include "predicates.md")
310 ;;---------------------------------------------------------------------------
311 ;; Pipeline descriptions
313 ;; Processor type. This is created automatically from arm-cores.def.
314 (include "arm-tune.md")
316 ;; True if the generic scheduling description should be used.
318 (define_attr "generic_sched" "yes,no"
320 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
322 (const_string "yes"))))
324 (define_attr "generic_vfp" "yes,no"
326 (and (eq_attr "fpu" "vfp")
327 (eq_attr "tune" "!arm1020e,arm1022e"))
329 (const_string "no"))))
331 (include "arm-generic.md")
332 (include "arm926ejs.md")
333 (include "arm1020e.md")
334 (include "arm1026ejs.md")
335 (include "arm1136jfs.md")
338 ;;---------------------------------------------------------------------------
343 ;; Note: For DImode insns, there is normally no reason why operands should
344 ;; not be in the same register, what we don't want is for something being
345 ;; written to partially overlap something that is an input.
346 ;; Cirrus 64bit additions should not be split because we have a native
347 ;; 64bit addition instructions.
349 (define_expand "adddi3"
351 [(set (match_operand:DI 0 "s_register_operand" "")
352 (plus:DI (match_operand:DI 1 "s_register_operand" "")
353 (match_operand:DI 2 "s_register_operand" "")))
354 (clobber (reg:CC CC_REGNUM))])]
357 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
359 if (!cirrus_fp_register (operands[0], DImode))
360 operands[0] = force_reg (DImode, operands[0]);
361 if (!cirrus_fp_register (operands[1], DImode))
362 operands[1] = force_reg (DImode, operands[1]);
363 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
369 if (GET_CODE (operands[1]) != REG)
370 operands[1] = force_reg (SImode, operands[1]);
371 if (GET_CODE (operands[2]) != REG)
372 operands[2] = force_reg (SImode, operands[2]);
377 (define_insn "*thumb_adddi3"
378 [(set (match_operand:DI 0 "register_operand" "=l")
379 (plus:DI (match_operand:DI 1 "register_operand" "%0")
380 (match_operand:DI 2 "register_operand" "l")))
381 (clobber (reg:CC CC_REGNUM))
384 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
385 [(set_attr "length" "4")]
388 (define_insn_and_split "*arm_adddi3"
389 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
390 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
391 (match_operand:DI 2 "s_register_operand" "r, 0")))
392 (clobber (reg:CC CC_REGNUM))]
393 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
395 "TARGET_ARM && reload_completed"
396 [(parallel [(set (reg:CC_C CC_REGNUM)
397 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
399 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401 (plus:SI (match_dup 4) (match_dup 5))))]
404 operands[3] = gen_highpart (SImode, operands[0]);
405 operands[0] = gen_lowpart (SImode, operands[0]);
406 operands[4] = gen_highpart (SImode, operands[1]);
407 operands[1] = gen_lowpart (SImode, operands[1]);
408 operands[5] = gen_highpart (SImode, operands[2]);
409 operands[2] = gen_lowpart (SImode, operands[2]);
411 [(set_attr "conds" "clob")
412 (set_attr "length" "8")]
415 (define_insn_and_split "*adddi_sesidi_di"
416 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
417 (plus:DI (sign_extend:DI
418 (match_operand:SI 2 "s_register_operand" "r,r"))
419 (match_operand:DI 1 "s_register_operand" "r,0")))
420 (clobber (reg:CC CC_REGNUM))]
421 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
423 "TARGET_ARM && reload_completed"
424 [(parallel [(set (reg:CC_C CC_REGNUM)
425 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429 (plus:SI (ashiftrt:SI (match_dup 2)
434 operands[3] = gen_highpart (SImode, operands[0]);
435 operands[0] = gen_lowpart (SImode, operands[0]);
436 operands[4] = gen_highpart (SImode, operands[1]);
437 operands[1] = gen_lowpart (SImode, operands[1]);
438 operands[2] = gen_lowpart (SImode, operands[2]);
440 [(set_attr "conds" "clob")
441 (set_attr "length" "8")]
444 (define_insn_and_split "*adddi_zesidi_di"
445 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
446 (plus:DI (zero_extend:DI
447 (match_operand:SI 2 "s_register_operand" "r,r"))
448 (match_operand:DI 1 "s_register_operand" "r,0")))
449 (clobber (reg:CC CC_REGNUM))]
450 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
452 "TARGET_ARM && reload_completed"
453 [(parallel [(set (reg:CC_C CC_REGNUM)
454 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
456 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
457 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
458 (plus:SI (match_dup 4) (const_int 0))))]
461 operands[3] = gen_highpart (SImode, operands[0]);
462 operands[0] = gen_lowpart (SImode, operands[0]);
463 operands[4] = gen_highpart (SImode, operands[1]);
464 operands[1] = gen_lowpart (SImode, operands[1]);
465 operands[2] = gen_lowpart (SImode, operands[2]);
467 [(set_attr "conds" "clob")
468 (set_attr "length" "8")]
471 (define_expand "addsi3"
472 [(set (match_operand:SI 0 "s_register_operand" "")
473 (plus:SI (match_operand:SI 1 "s_register_operand" "")
474 (match_operand:SI 2 "reg_or_int_operand" "")))]
477 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
479 arm_split_constant (PLUS, SImode, NULL_RTX,
480 INTVAL (operands[2]), operands[0], operands[1],
481 optimize && !no_new_pseudos);
487 ; If there is a scratch available, this will be faster than synthesizing the
490 [(match_scratch:SI 3 "r")
491 (set (match_operand:SI 0 "arm_general_register_operand" "")
492 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
493 (match_operand:SI 2 "const_int_operand" "")))]
495 !(const_ok_for_arm (INTVAL (operands[2]))
496 || const_ok_for_arm (-INTVAL (operands[2])))
497 && const_ok_for_arm (~INTVAL (operands[2]))"
498 [(set (match_dup 3) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503 (define_insn_and_split "*arm_addsi3"
504 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
505 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
506 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
513 GET_CODE (operands[2]) == CONST_INT
514 && !(const_ok_for_arm (INTVAL (operands[2]))
515 || const_ok_for_arm (-INTVAL (operands[2])))"
516 [(clobber (const_int 0))]
518 arm_split_constant (PLUS, SImode, curr_insn,
519 INTVAL (operands[2]), operands[0],
523 [(set_attr "length" "4,4,16")
524 (set_attr "predicable" "yes")]
527 ;; Register group 'k' is a single register group containing only the stack
528 ;; register. Trying to reload it will always fail catastrophically,
529 ;; so never allow those alternatives to match if reloading is needed.
531 (define_insn "*thumb_addsi3"
532 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
533 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
534 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
537 static const char * const asms[] =
539 \"add\\t%0, %0, %2\",
540 \"sub\\t%0, %0, #%n2\",
541 \"add\\t%0, %1, %2\",
542 \"add\\t%0, %0, %2\",
543 \"add\\t%0, %0, %2\",
544 \"add\\t%0, %1, %2\",
547 if ((which_alternative == 2 || which_alternative == 6)
548 && GET_CODE (operands[2]) == CONST_INT
549 && INTVAL (operands[2]) < 0)
550 return \"sub\\t%0, %1, #%n2\";
551 return asms[which_alternative];
553 [(set_attr "length" "2")]
556 ;; Reloading and elimination of the frame pointer can
557 ;; sometimes cause this optimization to be missed.
559 [(set (match_operand:SI 0 "arm_general_register_operand" "")
560 (match_operand:SI 1 "const_int_operand" ""))
562 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
564 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
565 && (INTVAL (operands[1]) & 3) == 0"
566 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570 (define_insn "*addsi3_compare0"
571 [(set (reg:CC_NOOV CC_REGNUM)
573 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
574 (match_operand:SI 2 "arm_add_operand" "rI,L"))
576 (set (match_operand:SI 0 "s_register_operand" "=r,r")
577 (plus:SI (match_dup 1) (match_dup 2)))]
581 sub%?s\\t%0, %1, #%n2"
582 [(set_attr "conds" "set")]
585 (define_insn "*addsi3_compare0_scratch"
586 [(set (reg:CC_NOOV CC_REGNUM)
588 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
589 (match_operand:SI 1 "arm_add_operand" "rI,L"))
595 [(set_attr "conds" "set")]
598 (define_insn "*compare_negsi_si"
599 [(set (reg:CC_Z CC_REGNUM)
601 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
602 (match_operand:SI 1 "s_register_operand" "r")))]
605 [(set_attr "conds" "set")]
608 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
609 ;; addend is a constant.
610 (define_insn "*cmpsi2_addneg"
611 [(set (reg:CC CC_REGNUM)
613 (match_operand:SI 1 "s_register_operand" "r,r")
614 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
615 (set (match_operand:SI 0 "s_register_operand" "=r,r")
616 (plus:SI (match_dup 1)
617 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
618 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
621 add%?s\\t%0, %1, #%n2"
622 [(set_attr "conds" "set")]
625 ;; Convert the sequence
627 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
631 ;; bcs dest ((unsigned)rn >= 1)
632 ;; similarly for the beq variant using bcc.
633 ;; This is a common looping idiom (while (n--))
635 [(set (match_operand:SI 0 "arm_general_register_operand" "")
636 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
638 (set (match_operand 2 "cc_register" "")
639 (compare (match_dup 0) (const_int -1)))
641 (if_then_else (match_operator 3 "equality_operator"
642 [(match_dup 2) (const_int 0)])
643 (match_operand 4 "" "")
644 (match_operand 5 "" "")))]
645 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649 (match_dup 1) (const_int 1)))
650 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
652 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
655 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
656 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
659 operands[2], const0_rtx);"
662 ;; The next four insns work because they compare the result with one of
663 ;; the operands, and we know that the use of the condition code is
664 ;; either GEU or LTU, so we can use the carry flag from the addition
665 ;; instead of doing the compare a second time.
666 (define_insn "*addsi3_compare_op1"
667 [(set (reg:CC_C CC_REGNUM)
669 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
670 (match_operand:SI 2 "arm_add_operand" "rI,L"))
672 (set (match_operand:SI 0 "s_register_operand" "=r,r")
673 (plus:SI (match_dup 1) (match_dup 2)))]
677 sub%?s\\t%0, %1, #%n2"
678 [(set_attr "conds" "set")]
681 (define_insn "*addsi3_compare_op2"
682 [(set (reg:CC_C CC_REGNUM)
684 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
685 (match_operand:SI 2 "arm_add_operand" "rI,L"))
687 (set (match_operand:SI 0 "s_register_operand" "=r,r")
688 (plus:SI (match_dup 1) (match_dup 2)))]
692 sub%?s\\t%0, %1, #%n2"
693 [(set_attr "conds" "set")]
696 (define_insn "*compare_addsi2_op0"
697 [(set (reg:CC_C CC_REGNUM)
699 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
700 (match_operand:SI 1 "arm_add_operand" "rI,L"))
706 [(set_attr "conds" "set")]
709 (define_insn "*compare_addsi2_op1"
710 [(set (reg:CC_C CC_REGNUM)
712 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
713 (match_operand:SI 1 "arm_add_operand" "rI,L"))
719 [(set_attr "conds" "set")]
722 (define_insn "*addsi3_carryin"
723 [(set (match_operand:SI 0 "s_register_operand" "=r")
724 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
725 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
726 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
729 [(set_attr "conds" "use")]
732 (define_insn "*addsi3_carryin_shift"
733 [(set (match_operand:SI 0 "s_register_operand" "=r")
734 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736 (match_operator:SI 2 "shift_operator"
737 [(match_operand:SI 3 "s_register_operand" "r")
738 (match_operand:SI 4 "reg_or_int_operand" "rM")])
739 (match_operand:SI 1 "s_register_operand" "r"))))]
741 "adc%?\\t%0, %1, %3%S2"
742 [(set_attr "conds" "use")
743 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
744 (const_string "alu_shift")
745 (const_string "alu_shift_reg")))]
748 (define_insn "*addsi3_carryin_alt1"
749 [(set (match_operand:SI 0 "s_register_operand" "=r")
750 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751 (match_operand:SI 2 "arm_rhs_operand" "rI"))
752 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
755 [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt2"
759 [(set (match_operand:SI 0 "s_register_operand" "=r")
760 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761 (match_operand:SI 1 "s_register_operand" "r"))
762 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
765 [(set_attr "conds" "use")]
768 (define_insn "*addsi3_carryin_alt3"
769 [(set (match_operand:SI 0 "s_register_operand" "=r")
770 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771 (match_operand:SI 2 "arm_rhs_operand" "rI"))
772 (match_operand:SI 1 "s_register_operand" "r")))]
775 [(set_attr "conds" "use")]
778 (define_insn "incscc"
779 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782 (match_operand:SI 1 "s_register_operand" "0,?r")))]
786 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787 [(set_attr "conds" "use")
788 (set_attr "length" "4,8")]
791 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
793 [(set (match_operand:SI 0 "s_register_operand" "")
794 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
795 (match_operand:SI 2 "s_register_operand" ""))
797 (clobber (match_operand:SI 3 "s_register_operand" ""))]
799 [(set (match_dup 3) (match_dup 1))
800 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
802 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
805 (define_expand "addsf3"
806 [(set (match_operand:SF 0 "s_register_operand" "")
807 (plus:SF (match_operand:SF 1 "s_register_operand" "")
808 (match_operand:SF 2 "arm_float_add_operand" "")))]
809 "TARGET_ARM && TARGET_HARD_FLOAT"
812 && !cirrus_fp_register (operands[2], SFmode))
813 operands[2] = force_reg (SFmode, operands[2]);
816 (define_expand "adddf3"
817 [(set (match_operand:DF 0 "s_register_operand" "")
818 (plus:DF (match_operand:DF 1 "s_register_operand" "")
819 (match_operand:DF 2 "arm_float_add_operand" "")))]
820 "TARGET_ARM && TARGET_HARD_FLOAT"
823 && !cirrus_fp_register (operands[2], DFmode))
824 operands[2] = force_reg (DFmode, operands[2]);
827 (define_expand "subdi3"
829 [(set (match_operand:DI 0 "s_register_operand" "")
830 (minus:DI (match_operand:DI 1 "s_register_operand" "")
831 (match_operand:DI 2 "s_register_operand" "")))
832 (clobber (reg:CC CC_REGNUM))])]
835 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
837 && cirrus_fp_register (operands[0], DImode)
838 && cirrus_fp_register (operands[1], DImode))
840 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
846 if (GET_CODE (operands[1]) != REG)
847 operands[1] = force_reg (SImode, operands[1]);
848 if (GET_CODE (operands[2]) != REG)
849 operands[2] = force_reg (SImode, operands[2]);
854 (define_insn "*arm_subdi3"
855 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
856 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857 (match_operand:DI 2 "s_register_operand" "r,0,0")))
858 (clobber (reg:CC CC_REGNUM))]
860 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
861 [(set_attr "conds" "clob")
862 (set_attr "length" "8")]
865 (define_insn "*thumb_subdi3"
866 [(set (match_operand:DI 0 "register_operand" "=l")
867 (minus:DI (match_operand:DI 1 "register_operand" "0")
868 (match_operand:DI 2 "register_operand" "l")))
869 (clobber (reg:CC CC_REGNUM))]
871 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
872 [(set_attr "length" "4")]
875 (define_insn "*subdi_di_zesidi"
876 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
877 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
879 (match_operand:SI 2 "s_register_operand" "r,r"))))
880 (clobber (reg:CC CC_REGNUM))]
882 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
883 [(set_attr "conds" "clob")
884 (set_attr "length" "8")]
887 (define_insn "*subdi_di_sesidi"
888 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
889 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
891 (match_operand:SI 2 "s_register_operand" "r,r"))))
892 (clobber (reg:CC CC_REGNUM))]
894 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
895 [(set_attr "conds" "clob")
896 (set_attr "length" "8")]
899 (define_insn "*subdi_zesidi_di"
900 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
901 (minus:DI (zero_extend:DI
902 (match_operand:SI 2 "s_register_operand" "r,r"))
903 (match_operand:DI 1 "s_register_operand" "?r,0")))
904 (clobber (reg:CC CC_REGNUM))]
906 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
907 [(set_attr "conds" "clob")
908 (set_attr "length" "8")]
911 (define_insn "*subdi_sesidi_di"
912 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
913 (minus:DI (sign_extend:DI
914 (match_operand:SI 2 "s_register_operand" "r,r"))
915 (match_operand:DI 1 "s_register_operand" "?r,0")))
916 (clobber (reg:CC CC_REGNUM))]
918 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
919 [(set_attr "conds" "clob")
920 (set_attr "length" "8")]
923 (define_insn "*subdi_zesidi_zesidi"
924 [(set (match_operand:DI 0 "s_register_operand" "=r")
925 (minus:DI (zero_extend:DI
926 (match_operand:SI 1 "s_register_operand" "r"))
928 (match_operand:SI 2 "s_register_operand" "r"))))
929 (clobber (reg:CC CC_REGNUM))]
931 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
932 [(set_attr "conds" "clob")
933 (set_attr "length" "8")]
936 (define_expand "subsi3"
937 [(set (match_operand:SI 0 "s_register_operand" "")
938 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
939 (match_operand:SI 2 "s_register_operand" "")))]
942 if (GET_CODE (operands[1]) == CONST_INT)
946 arm_split_constant (MINUS, SImode, NULL_RTX,
947 INTVAL (operands[1]), operands[0],
948 operands[2], optimize && !no_new_pseudos);
951 else /* TARGET_THUMB */
952 operands[1] = force_reg (SImode, operands[1]);
957 (define_insn "*thumb_subsi3_insn"
958 [(set (match_operand:SI 0 "register_operand" "=l")
959 (minus:SI (match_operand:SI 1 "register_operand" "l")
960 (match_operand:SI 2 "register_operand" "l")))]
963 [(set_attr "length" "2")]
966 (define_insn_and_split "*arm_subsi3_insn"
967 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
968 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
969 (match_operand:SI 2 "s_register_operand" "r,r")))]
975 && GET_CODE (operands[1]) == CONST_INT
976 && !const_ok_for_arm (INTVAL (operands[1]))"
977 [(clobber (const_int 0))]
979 arm_split_constant (MINUS, SImode, curr_insn,
980 INTVAL (operands[1]), operands[0], operands[2], 0);
983 [(set_attr "length" "4,16")
984 (set_attr "predicable" "yes")]
988 [(match_scratch:SI 3 "r")
989 (set (match_operand:SI 0 "arm_general_register_operand" "")
990 (minus:SI (match_operand:SI 1 "const_int_operand" "")
991 (match_operand:SI 2 "arm_general_register_operand" "")))]
993 && !const_ok_for_arm (INTVAL (operands[1]))
994 && const_ok_for_arm (~INTVAL (operands[1]))"
995 [(set (match_dup 3) (match_dup 1))
996 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000 (define_insn "*subsi3_compare0"
1001 [(set (reg:CC_NOOV CC_REGNUM)
1003 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1004 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1006 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1007 (minus:SI (match_dup 1) (match_dup 2)))]
1011 rsb%?s\\t%0, %2, %1"
1012 [(set_attr "conds" "set")]
1015 (define_insn "decscc"
1016 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1017 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1018 (match_operator:SI 2 "arm_comparison_operator"
1019 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1023 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1024 [(set_attr "conds" "use")
1025 (set_attr "length" "*,8")]
1028 (define_expand "subsf3"
1029 [(set (match_operand:SF 0 "s_register_operand" "")
1030 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1031 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1032 "TARGET_ARM && TARGET_HARD_FLOAT"
1034 if (TARGET_MAVERICK)
1036 if (!cirrus_fp_register (operands[1], SFmode))
1037 operands[1] = force_reg (SFmode, operands[1]);
1038 if (!cirrus_fp_register (operands[2], SFmode))
1039 operands[2] = force_reg (SFmode, operands[2]);
1043 (define_expand "subdf3"
1044 [(set (match_operand:DF 0 "s_register_operand" "")
1045 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1046 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1047 "TARGET_ARM && TARGET_HARD_FLOAT"
1049 if (TARGET_MAVERICK)
1051 if (!cirrus_fp_register (operands[1], DFmode))
1052 operands[1] = force_reg (DFmode, operands[1]);
1053 if (!cirrus_fp_register (operands[2], DFmode))
1054 operands[2] = force_reg (DFmode, operands[2]);
1059 ;; Multiplication insns
1061 (define_expand "mulsi3"
1062 [(set (match_operand:SI 0 "s_register_operand" "")
1063 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1064 (match_operand:SI 1 "s_register_operand" "")))]
1069 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1070 (define_insn "*arm_mulsi3"
1071 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1072 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1073 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1075 "mul%?\\t%0, %2, %1"
1076 [(set_attr "insn" "mul")
1077 (set_attr "predicable" "yes")]
1080 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1081 ; 1 and 2; are the same, because reload will make operand 0 match
1082 ; operand 1 without realizing that this conflicts with operand 2. We fix
1083 ; this by adding another alternative to match this case, and then `reload'
1084 ; it ourselves. This alternative must come first.
1085 (define_insn "*thumb_mulsi3"
1086 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1087 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1088 (match_operand:SI 2 "register_operand" "l,l,l")))]
1091 if (which_alternative < 2)
1092 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1094 return \"mul\\t%0, %2\";
1096 [(set_attr "length" "4,4,2")
1097 (set_attr "insn" "mul")]
1100 (define_insn "*mulsi3_compare0"
1101 [(set (reg:CC_NOOV CC_REGNUM)
1102 (compare:CC_NOOV (mult:SI
1103 (match_operand:SI 2 "s_register_operand" "r,r")
1104 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1106 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1107 (mult:SI (match_dup 2) (match_dup 1)))]
1109 "mul%?s\\t%0, %2, %1"
1110 [(set_attr "conds" "set")
1111 (set_attr "insn" "muls")]
1114 (define_insn "*mulsi_compare0_scratch"
1115 [(set (reg:CC_NOOV CC_REGNUM)
1116 (compare:CC_NOOV (mult:SI
1117 (match_operand:SI 2 "s_register_operand" "r,r")
1118 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1120 (clobber (match_scratch:SI 0 "=&r,&r"))]
1122 "mul%?s\\t%0, %2, %1"
1123 [(set_attr "conds" "set")
1124 (set_attr "insn" "muls")]
1127 ;; Unnamed templates to match MLA instruction.
1129 (define_insn "*mulsi3addsi"
1130 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1132 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1133 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1134 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1136 "mla%?\\t%0, %2, %1, %3"
1137 [(set_attr "insn" "mla")
1138 (set_attr "predicable" "yes")]
1141 (define_insn "*mulsi3addsi_compare0"
1142 [(set (reg:CC_NOOV CC_REGNUM)
1145 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1146 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1147 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1149 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1150 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1153 "mla%?s\\t%0, %2, %1, %3"
1154 [(set_attr "conds" "set")
1155 (set_attr "insn" "mlas")]
1158 (define_insn "*mulsi3addsi_compare0_scratch"
1159 [(set (reg:CC_NOOV CC_REGNUM)
1162 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1163 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1164 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1166 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1168 "mla%?s\\t%0, %2, %1, %3"
1169 [(set_attr "conds" "set")
1170 (set_attr "insn" "mlas")]
1173 ;; Unnamed template to match long long multiply-accumulate (smlal)
1175 (define_insn "*mulsidi3adddi"
1176 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1179 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1180 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1181 (match_operand:DI 1 "s_register_operand" "0")))]
1182 "TARGET_ARM && arm_arch3m"
1183 "smlal%?\\t%Q0, %R0, %3, %2"
1184 [(set_attr "insn" "smlal")
1185 (set_attr "predicable" "yes")]
1188 (define_insn "mulsidi3"
1189 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1191 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1192 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1193 "TARGET_ARM && arm_arch3m"
1194 "smull%?\\t%Q0, %R0, %1, %2"
1195 [(set_attr "insn" "smull")
1196 (set_attr "predicable" "yes")]
1199 (define_insn "umulsidi3"
1200 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1202 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1203 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1204 "TARGET_ARM && arm_arch3m"
1205 "umull%?\\t%Q0, %R0, %1, %2"
1206 [(set_attr "insn" "umull")
1207 (set_attr "predicable" "yes")]
1210 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1212 (define_insn "*umulsidi3adddi"
1213 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1216 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1217 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1218 (match_operand:DI 1 "s_register_operand" "0")))]
1219 "TARGET_ARM && arm_arch3m"
1220 "umlal%?\\t%Q0, %R0, %3, %2"
1221 [(set_attr "insn" "umlal")
1222 (set_attr "predicable" "yes")]
1225 (define_insn "smulsi3_highpart"
1226 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1231 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1233 (clobber (match_scratch:SI 3 "=&r,&r"))]
1234 "TARGET_ARM && arm_arch3m"
1235 "smull%?\\t%3, %0, %2, %1"
1236 [(set_attr "insn" "smull")
1237 (set_attr "predicable" "yes")]
1240 (define_insn "umulsi3_highpart"
1241 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1246 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1248 (clobber (match_scratch:SI 3 "=&r,&r"))]
1249 "TARGET_ARM && arm_arch3m"
1250 "umull%?\\t%3, %0, %2, %1"
1251 [(set_attr "insn" "umull")
1252 (set_attr "predicable" "yes")]
1255 (define_insn "mulhisi3"
1256 [(set (match_operand:SI 0 "s_register_operand" "=r")
1257 (mult:SI (sign_extend:SI
1258 (match_operand:HI 1 "s_register_operand" "%r"))
1260 (match_operand:HI 2 "s_register_operand" "r"))))]
1261 "TARGET_ARM && arm_arch5e"
1262 "smulbb%?\\t%0, %1, %2"
1263 [(set_attr "insn" "smulxy")
1264 (set_attr "predicable" "yes")]
1267 (define_insn "*mulhisi3tb"
1268 [(set (match_operand:SI 0 "s_register_operand" "=r")
1269 (mult:SI (ashiftrt:SI
1270 (match_operand:SI 1 "s_register_operand" "r")
1273 (match_operand:HI 2 "s_register_operand" "r"))))]
1274 "TARGET_ARM && arm_arch5e"
1275 "smultb%?\\t%0, %1, %2"
1276 [(set_attr "insn" "smulxy")
1277 (set_attr "predicable" "yes")]
1280 (define_insn "*mulhisi3bt"
1281 [(set (match_operand:SI 0 "s_register_operand" "=r")
1282 (mult:SI (sign_extend:SI
1283 (match_operand:HI 1 "s_register_operand" "r"))
1285 (match_operand:SI 2 "s_register_operand" "r")
1287 "TARGET_ARM && arm_arch5e"
1288 "smulbt%?\\t%0, %1, %2"
1289 [(set_attr "insn" "smulxy")
1290 (set_attr "predicable" "yes")]
1293 (define_insn "*mulhisi3tt"
1294 [(set (match_operand:SI 0 "s_register_operand" "=r")
1295 (mult:SI (ashiftrt:SI
1296 (match_operand:SI 1 "s_register_operand" "r")
1299 (match_operand:SI 2 "s_register_operand" "r")
1301 "TARGET_ARM && arm_arch5e"
1302 "smultt%?\\t%0, %1, %2"
1303 [(set_attr "insn" "smulxy")
1304 (set_attr "predicable" "yes")]
1307 (define_insn "*mulhisi3addsi"
1308 [(set (match_operand:SI 0 "s_register_operand" "=r")
1309 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1310 (mult:SI (sign_extend:SI
1311 (match_operand:HI 2 "s_register_operand" "%r"))
1313 (match_operand:HI 3 "s_register_operand" "r")))))]
1314 "TARGET_ARM && arm_arch5e"
1315 "smlabb%?\\t%0, %2, %3, %1"
1316 [(set_attr "insn" "smlaxy")
1317 (set_attr "predicable" "yes")]
1320 (define_insn "*mulhidi3adddi"
1321 [(set (match_operand:DI 0 "s_register_operand" "=r")
1323 (match_operand:DI 1 "s_register_operand" "0")
1324 (mult:DI (sign_extend:DI
1325 (match_operand:HI 2 "s_register_operand" "%r"))
1327 (match_operand:HI 3 "s_register_operand" "r")))))]
1328 "TARGET_ARM && arm_arch5e"
1329 "smlalbb%?\\t%Q0, %R0, %2, %3"
1330 [(set_attr "insn" "smlalxy")
1331 (set_attr "predicable" "yes")])
1333 (define_expand "mulsf3"
1334 [(set (match_operand:SF 0 "s_register_operand" "")
1335 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1336 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1337 "TARGET_ARM && TARGET_HARD_FLOAT"
1340 && !cirrus_fp_register (operands[2], SFmode))
1341 operands[2] = force_reg (SFmode, operands[2]);
1344 (define_expand "muldf3"
1345 [(set (match_operand:DF 0 "s_register_operand" "")
1346 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1347 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1348 "TARGET_ARM && TARGET_HARD_FLOAT"
1351 && !cirrus_fp_register (operands[2], DFmode))
1352 operands[2] = force_reg (DFmode, operands[2]);
1357 (define_expand "divsf3"
1358 [(set (match_operand:SF 0 "s_register_operand" "")
1359 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1360 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1361 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1364 (define_expand "divdf3"
1365 [(set (match_operand:DF 0 "s_register_operand" "")
1366 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1367 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1368 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1373 (define_expand "modsf3"
1374 [(set (match_operand:SF 0 "s_register_operand" "")
1375 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1376 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1380 (define_expand "moddf3"
1381 [(set (match_operand:DF 0 "s_register_operand" "")
1382 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1383 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1384 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1387 ;; Boolean and,ior,xor insns
1389 ;; Split up double word logical operations
1391 ;; Split up simple DImode logical operations. Simply perform the logical
1392 ;; operation on the upper and lower halves of the registers.
1394 [(set (match_operand:DI 0 "s_register_operand" "")
1395 (match_operator:DI 6 "logical_binary_operator"
1396 [(match_operand:DI 1 "s_register_operand" "")
1397 (match_operand:DI 2 "s_register_operand" "")]))]
1398 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1399 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1400 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1403 operands[3] = gen_highpart (SImode, operands[0]);
1404 operands[0] = gen_lowpart (SImode, operands[0]);
1405 operands[4] = gen_highpart (SImode, operands[1]);
1406 operands[1] = gen_lowpart (SImode, operands[1]);
1407 operands[5] = gen_highpart (SImode, operands[2]);
1408 operands[2] = gen_lowpart (SImode, operands[2]);
1413 [(set (match_operand:DI 0 "s_register_operand" "")
1414 (match_operator:DI 6 "logical_binary_operator"
1415 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416 (match_operand:DI 1 "s_register_operand" "")]))]
1417 "TARGET_ARM && reload_completed"
1418 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1419 (set (match_dup 3) (match_op_dup:SI 6
1420 [(ashiftrt:SI (match_dup 2) (const_int 31))
1424 operands[3] = gen_highpart (SImode, operands[0]);
1425 operands[0] = gen_lowpart (SImode, operands[0]);
1426 operands[4] = gen_highpart (SImode, operands[1]);
1427 operands[1] = gen_lowpart (SImode, operands[1]);
1428 operands[5] = gen_highpart (SImode, operands[2]);
1429 operands[2] = gen_lowpart (SImode, operands[2]);
1433 ;; The zero extend of operand 2 means we can just copy the high part of
1434 ;; operand1 into operand0.
1436 [(set (match_operand:DI 0 "s_register_operand" "")
1438 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1439 (match_operand:DI 1 "s_register_operand" "")))]
1440 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1441 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1442 (set (match_dup 3) (match_dup 4))]
1445 operands[4] = gen_highpart (SImode, operands[1]);
1446 operands[3] = gen_highpart (SImode, operands[0]);
1447 operands[0] = gen_lowpart (SImode, operands[0]);
1448 operands[1] = gen_lowpart (SImode, operands[1]);
1452 ;; The zero extend of operand 2 means we can just copy the high part of
1453 ;; operand1 into operand0.
1455 [(set (match_operand:DI 0 "s_register_operand" "")
1457 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1458 (match_operand:DI 1 "s_register_operand" "")))]
1459 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1460 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1461 (set (match_dup 3) (match_dup 4))]
1464 operands[4] = gen_highpart (SImode, operands[1]);
1465 operands[3] = gen_highpart (SImode, operands[0]);
1466 operands[0] = gen_lowpart (SImode, operands[0]);
1467 operands[1] = gen_lowpart (SImode, operands[1]);
1471 (define_insn "anddi3"
1472 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1473 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1474 (match_operand:DI 2 "s_register_operand" "r,r")))]
1475 "TARGET_ARM && ! TARGET_IWMMXT"
1477 [(set_attr "length" "8")]
1480 (define_insn_and_split "*anddi_zesidi_di"
1481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482 (and:DI (zero_extend:DI
1483 (match_operand:SI 2 "s_register_operand" "r,r"))
1484 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1487 "TARGET_ARM && reload_completed"
1488 ; The zero extend of operand 2 clears the high word of the output
1490 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1491 (set (match_dup 3) (const_int 0))]
1494 operands[3] = gen_highpart (SImode, operands[0]);
1495 operands[0] = gen_lowpart (SImode, operands[0]);
1496 operands[1] = gen_lowpart (SImode, operands[1]);
1498 [(set_attr "length" "8")]
1501 (define_insn "*anddi_sesdi_di"
1502 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1503 (and:DI (sign_extend:DI
1504 (match_operand:SI 2 "s_register_operand" "r,r"))
1505 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1508 [(set_attr "length" "8")]
1511 (define_expand "andsi3"
1512 [(set (match_operand:SI 0 "s_register_operand" "")
1513 (and:SI (match_operand:SI 1 "s_register_operand" "")
1514 (match_operand:SI 2 "reg_or_int_operand" "")))]
1519 if (GET_CODE (operands[2]) == CONST_INT)
1521 arm_split_constant (AND, SImode, NULL_RTX,
1522 INTVAL (operands[2]), operands[0],
1523 operands[1], optimize && !no_new_pseudos);
1528 else /* TARGET_THUMB */
1530 if (GET_CODE (operands[2]) != CONST_INT)
1531 operands[2] = force_reg (SImode, operands[2]);
1536 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1538 operands[2] = force_reg (SImode,
1539 GEN_INT (~INTVAL (operands[2])));
1541 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1546 for (i = 9; i <= 31; i++)
1548 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1550 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554 else if ((((HOST_WIDE_INT) 1) << i) - 1
1555 == ~INTVAL (operands[2]))
1557 rtx shift = GEN_INT (i);
1558 rtx reg = gen_reg_rtx (SImode);
1560 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1561 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1567 operands[2] = force_reg (SImode, operands[2]);
1573 (define_insn_and_split "*arm_andsi3_insn"
1574 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1575 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1576 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580 bic%?\\t%0, %1, #%B2
1583 && GET_CODE (operands[2]) == CONST_INT
1584 && !(const_ok_for_arm (INTVAL (operands[2]))
1585 || const_ok_for_arm (~INTVAL (operands[2])))"
1586 [(clobber (const_int 0))]
1588 arm_split_constant (AND, SImode, curr_insn,
1589 INTVAL (operands[2]), operands[0], operands[1], 0);
1592 [(set_attr "length" "4,4,16")
1593 (set_attr "predicable" "yes")]
1596 (define_insn "*thumb_andsi3_insn"
1597 [(set (match_operand:SI 0 "register_operand" "=l")
1598 (and:SI (match_operand:SI 1 "register_operand" "%0")
1599 (match_operand:SI 2 "register_operand" "l")))]
1602 [(set_attr "length" "2")]
1605 (define_insn "*andsi3_compare0"
1606 [(set (reg:CC_NOOV CC_REGNUM)
1608 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1609 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1611 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1612 (and:SI (match_dup 1) (match_dup 2)))]
1616 bic%?s\\t%0, %1, #%B2"
1617 [(set_attr "conds" "set")]
1620 (define_insn "*andsi3_compare0_scratch"
1621 [(set (reg:CC_NOOV CC_REGNUM)
1623 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1624 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1626 (clobber (match_scratch:SI 2 "=X,r"))]
1630 bic%?s\\t%2, %0, #%B1"
1631 [(set_attr "conds" "set")]
1634 (define_insn "*zeroextractsi_compare0_scratch"
1635 [(set (reg:CC_NOOV CC_REGNUM)
1636 (compare:CC_NOOV (zero_extract:SI
1637 (match_operand:SI 0 "s_register_operand" "r")
1638 (match_operand 1 "const_int_operand" "n")
1639 (match_operand 2 "const_int_operand" "n"))
1642 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1643 && INTVAL (operands[1]) > 0
1644 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1645 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1647 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1648 << INTVAL (operands[2]));
1649 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1652 [(set_attr "conds" "set")]
1655 (define_insn_and_split "*ne_zeroextractsi"
1656 [(set (match_operand:SI 0 "s_register_operand" "=r")
1657 (ne:SI (zero_extract:SI
1658 (match_operand:SI 1 "s_register_operand" "r")
1659 (match_operand:SI 2 "const_int_operand" "n")
1660 (match_operand:SI 3 "const_int_operand" "n"))
1662 (clobber (reg:CC CC_REGNUM))]
1664 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1665 && INTVAL (operands[2]) > 0
1666 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1667 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1670 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1671 && INTVAL (operands[2]) > 0
1672 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1673 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1675 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1677 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1679 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1680 (match_dup 0) (const_int 1)))]
1682 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1683 << INTVAL (operands[3]));
1685 [(set_attr "conds" "clob")
1686 (set_attr "length" "8")]
1689 (define_insn_and_split "*ne_zeroextractsi_shifted"
1690 [(set (match_operand:SI 0 "s_register_operand" "=r")
1691 (ne:SI (zero_extract:SI
1692 (match_operand:SI 1 "s_register_operand" "r")
1693 (match_operand:SI 2 "const_int_operand" "n")
1696 (clobber (reg:CC CC_REGNUM))]
1700 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1701 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1703 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1705 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1706 (match_dup 0) (const_int 1)))]
1708 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1710 [(set_attr "conds" "clob")
1711 (set_attr "length" "8")]
1714 (define_insn_and_split "*ite_ne_zeroextractsi"
1715 [(set (match_operand:SI 0 "s_register_operand" "=r")
1716 (if_then_else:SI (ne (zero_extract:SI
1717 (match_operand:SI 1 "s_register_operand" "r")
1718 (match_operand:SI 2 "const_int_operand" "n")
1719 (match_operand:SI 3 "const_int_operand" "n"))
1721 (match_operand:SI 4 "arm_not_operand" "rIK")
1723 (clobber (reg:CC CC_REGNUM))]
1725 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1726 && INTVAL (operands[2]) > 0
1727 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1728 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1729 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1732 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1733 && INTVAL (operands[2]) > 0
1734 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1735 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1736 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1737 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1738 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1740 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1742 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1743 (match_dup 0) (match_dup 4)))]
1745 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1746 << INTVAL (operands[3]));
1748 [(set_attr "conds" "clob")
1749 (set_attr "length" "8")]
1752 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1753 [(set (match_operand:SI 0 "s_register_operand" "=r")
1754 (if_then_else:SI (ne (zero_extract:SI
1755 (match_operand:SI 1 "s_register_operand" "r")
1756 (match_operand:SI 2 "const_int_operand" "n")
1759 (match_operand:SI 3 "arm_not_operand" "rIK")
1761 (clobber (reg:CC CC_REGNUM))]
1762 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1764 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1766 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1768 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1770 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1771 (match_dup 0) (match_dup 3)))]
1773 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1775 [(set_attr "conds" "clob")
1776 (set_attr "length" "8")]
1780 [(set (match_operand:SI 0 "s_register_operand" "")
1781 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1782 (match_operand:SI 2 "const_int_operand" "")
1783 (match_operand:SI 3 "const_int_operand" "")))
1784 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1786 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1787 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1789 HOST_WIDE_INT temp = INTVAL (operands[2]);
1791 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1792 operands[3] = GEN_INT (32 - temp);
1797 [(set (match_operand:SI 0 "s_register_operand" "")
1798 (match_operator:SI 1 "shiftable_operator"
1799 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1800 (match_operand:SI 3 "const_int_operand" "")
1801 (match_operand:SI 4 "const_int_operand" ""))
1802 (match_operand:SI 5 "s_register_operand" "")]))
1803 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1805 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1808 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1811 HOST_WIDE_INT temp = INTVAL (operands[3]);
1813 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1814 operands[4] = GEN_INT (32 - temp);
1819 [(set (match_operand:SI 0 "s_register_operand" "")
1820 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1821 (match_operand:SI 2 "const_int_operand" "")
1822 (match_operand:SI 3 "const_int_operand" "")))]
1824 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1825 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1827 HOST_WIDE_INT temp = INTVAL (operands[2]);
1829 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1830 operands[3] = GEN_INT (32 - temp);
1835 [(set (match_operand:SI 0 "s_register_operand" "")
1836 (match_operator:SI 1 "shiftable_operator"
1837 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1838 (match_operand:SI 3 "const_int_operand" "")
1839 (match_operand:SI 4 "const_int_operand" ""))
1840 (match_operand:SI 5 "s_register_operand" "")]))
1841 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1843 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1846 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1849 HOST_WIDE_INT temp = INTVAL (operands[3]);
1851 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1852 operands[4] = GEN_INT (32 - temp);
1856 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1859 ;;; which have a real bit-field insert instruction, the truncation happens
1860 ;;; in the bit-field insert instruction itself. Since arm does not have a
1861 ;;; bit-field insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert. This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1865 (define_expand "insv"
1866 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867 (match_operand:SI 1 "general_operand" "")
1868 (match_operand:SI 2 "general_operand" ""))
1869 (match_operand:SI 3 "reg_or_int_operand" ""))]
1873 int start_bit = INTVAL (operands[2]);
1874 int width = INTVAL (operands[1]);
1875 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876 rtx target, subtarget;
1878 target = operands[0];
1879 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1880 subreg as the final target. */
1881 if (GET_CODE (target) == SUBREG)
1883 subtarget = gen_reg_rtx (SImode);
1884 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885 < GET_MODE_SIZE (SImode))
1886 target = SUBREG_REG (target);
1891 if (GET_CODE (operands[3]) == CONST_INT)
1893 /* Since we are inserting a known constant, we may be able to
1894 reduce the number of bits that we have to clear so that
1895 the mask becomes simple. */
1896 /* ??? This code does not check to see if the new mask is actually
1897 simpler. It may not be. */
1898 rtx op1 = gen_reg_rtx (SImode);
1899 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1900 start of this pattern. */
1901 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1904 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905 emit_insn (gen_iorsi3 (subtarget, op1,
1906 gen_int_mode (op3_value << start_bit, SImode)));
1908 else if (start_bit == 0
1909 && !(const_ok_for_arm (mask)
1910 || const_ok_for_arm (~mask)))
1912 /* A Trick, since we are setting the bottom bits in the word,
1913 we can shift operand[3] up, operand[0] down, OR them together
1914 and rotate the result back again. This takes 3 insns, and
1915 the third might be mergeable into another op. */
1916 /* The shift up copes with the possibility that operand[3] is
1917 wider than the bitfield. */
1918 rtx op0 = gen_reg_rtx (SImode);
1919 rtx op1 = gen_reg_rtx (SImode);
1921 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923 emit_insn (gen_iorsi3 (op1, op1, op0));
1924 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1926 else if ((width + start_bit == 32)
1927 && !(const_ok_for_arm (mask)
1928 || const_ok_for_arm (~mask)))
1930 /* Similar trick, but slightly less efficient. */
1932 rtx op0 = gen_reg_rtx (SImode);
1933 rtx op1 = gen_reg_rtx (SImode);
1935 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1942 rtx op0 = GEN_INT (mask);
1943 rtx op1 = gen_reg_rtx (SImode);
1944 rtx op2 = gen_reg_rtx (SImode);
1946 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1948 rtx tmp = gen_reg_rtx (SImode);
1950 emit_insn (gen_movsi (tmp, op0));
1954 /* Mask out any bits in operand[3] that are not needed. */
1955 emit_insn (gen_andsi3 (op1, operands[3], op0));
1957 if (GET_CODE (op0) == CONST_INT
1958 && (const_ok_for_arm (mask << start_bit)
1959 || const_ok_for_arm (~(mask << start_bit))))
1961 op0 = GEN_INT (~(mask << start_bit));
1962 emit_insn (gen_andsi3 (op2, operands[0], op0));
1966 if (GET_CODE (op0) == CONST_INT)
1968 rtx tmp = gen_reg_rtx (SImode);
1970 emit_insn (gen_movsi (tmp, op0));
1975 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1977 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1981 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1983 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1986 if (subtarget != target)
1988 /* If TARGET is still a SUBREG, then it must be wider than a word,
1989 so we must be careful only to set the subword we were asked to. */
1990 if (GET_CODE (target) == SUBREG)
1991 emit_move_insn (target, subtarget);
1993 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004 (match_operand:DI 2 "s_register_operand" "0,r")))]
2007 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2008 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2012 operands[3] = gen_highpart (SImode, operands[0]);
2013 operands[0] = gen_lowpart (SImode, operands[0]);
2014 operands[4] = gen_highpart (SImode, operands[1]);
2015 operands[1] = gen_lowpart (SImode, operands[1]);
2016 operands[5] = gen_highpart (SImode, operands[2]);
2017 operands[2] = gen_lowpart (SImode, operands[2]);
2019 [(set_attr "length" "8")
2020 (set_attr "predicable" "yes")]
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025 (and:DI (not:DI (zero_extend:DI
2026 (match_operand:SI 2 "s_register_operand" "r,r")))
2027 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2030 bic%?\\t%Q0, %Q1, %2
2032 ; (not (zero_extend ...)) allows us to just copy the high word from
2033 ; operand1 to operand0.
2036 && operands[0] != operands[1]"
2037 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2038 (set (match_dup 3) (match_dup 4))]
2041 operands[3] = gen_highpart (SImode, operands[0]);
2042 operands[0] = gen_lowpart (SImode, operands[0]);
2043 operands[4] = gen_highpart (SImode, operands[1]);
2044 operands[1] = gen_lowpart (SImode, operands[1]);
2046 [(set_attr "length" "4,8")
2047 (set_attr "predicable" "yes")]
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052 (and:DI (not:DI (sign_extend:DI
2053 (match_operand:SI 2 "s_register_operand" "r,r")))
2054 (match_operand:DI 1 "s_register_operand" "0,r")))]
2057 "TARGET_ARM && reload_completed"
2058 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2059 (set (match_dup 3) (and:SI (not:SI
2060 (ashiftrt:SI (match_dup 2) (const_int 31)))
2064 operands[3] = gen_highpart (SImode, operands[0]);
2065 operands[0] = gen_lowpart (SImode, operands[0]);
2066 operands[4] = gen_highpart (SImode, operands[1]);
2067 operands[1] = gen_lowpart (SImode, operands[1]);
2069 [(set_attr "length" "8")
2070 (set_attr "predicable" "yes")]
2073 (define_insn "andsi_notsi_si"
2074 [(set (match_operand:SI 0 "s_register_operand" "=r")
2075 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076 (match_operand:SI 1 "s_register_operand" "r")))]
2078 "bic%?\\t%0, %1, %2"
2079 [(set_attr "predicable" "yes")]
2082 (define_insn "bicsi3"
2083 [(set (match_operand:SI 0 "register_operand" "=l")
2084 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085 (match_operand:SI 2 "register_operand" "0")))]
2088 [(set_attr "length" "2")]
2091 (define_insn "andsi_not_shiftsi_si"
2092 [(set (match_operand:SI 0 "s_register_operand" "=r")
2093 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2094 [(match_operand:SI 2 "s_register_operand" "r")
2095 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2096 (match_operand:SI 1 "s_register_operand" "r")))]
2098 "bic%?\\t%0, %1, %2%S4"
2099 [(set_attr "predicable" "yes")
2100 (set_attr "shift" "2")
2101 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2102 (const_string "alu_shift")
2103 (const_string "alu_shift_reg")))]
2106 (define_insn "*andsi_notsi_si_compare0"
2107 [(set (reg:CC_NOOV CC_REGNUM)
2109 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2110 (match_operand:SI 1 "s_register_operand" "r"))
2112 (set (match_operand:SI 0 "s_register_operand" "=r")
2113 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2115 "bic%?s\\t%0, %1, %2"
2116 [(set_attr "conds" "set")]
2119 (define_insn "*andsi_notsi_si_compare0_scratch"
2120 [(set (reg:CC_NOOV CC_REGNUM)
2122 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2123 (match_operand:SI 1 "s_register_operand" "r"))
2125 (clobber (match_scratch:SI 0 "=r"))]
2127 "bic%?s\\t%0, %1, %2"
2128 [(set_attr "conds" "set")]
2131 (define_insn "iordi3"
2132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2134 (match_operand:DI 2 "s_register_operand" "r,r")))]
2135 "TARGET_ARM && ! TARGET_IWMMXT"
2137 [(set_attr "length" "8")
2138 (set_attr "predicable" "yes")]
2141 (define_insn "*iordi_zesidi_di"
2142 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2143 (ior:DI (zero_extend:DI
2144 (match_operand:SI 2 "s_register_operand" "r,r"))
2145 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2148 orr%?\\t%Q0, %Q1, %2
2150 [(set_attr "length" "4,8")
2151 (set_attr "predicable" "yes")]
2154 (define_insn "*iordi_sesidi_di"
2155 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2156 (ior:DI (sign_extend:DI
2157 (match_operand:SI 2 "s_register_operand" "r,r"))
2158 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2161 [(set_attr "length" "8")
2162 (set_attr "predicable" "yes")]
2165 (define_expand "iorsi3"
2166 [(set (match_operand:SI 0 "s_register_operand" "")
2167 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2168 (match_operand:SI 2 "reg_or_int_operand" "")))]
2171 if (GET_CODE (operands[2]) == CONST_INT)
2175 arm_split_constant (IOR, SImode, NULL_RTX,
2176 INTVAL (operands[2]), operands[0], operands[1],
2177 optimize && !no_new_pseudos);
2180 else /* TARGET_THUMB */
2181 operands [2] = force_reg (SImode, operands [2]);
2186 (define_insn_and_split "*arm_iorsi3"
2187 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2188 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2195 && GET_CODE (operands[2]) == CONST_INT
2196 && !const_ok_for_arm (INTVAL (operands[2]))"
2197 [(clobber (const_int 0))]
2199 arm_split_constant (IOR, SImode, curr_insn,
2200 INTVAL (operands[2]), operands[0], operands[1], 0);
2203 [(set_attr "length" "4,16")
2204 (set_attr "predicable" "yes")]
2207 (define_insn "*thumb_iorsi3"
2208 [(set (match_operand:SI 0 "register_operand" "=l")
2209 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210 (match_operand:SI 2 "register_operand" "l")))]
2213 [(set_attr "length" "2")]
2217 [(match_scratch:SI 3 "r")
2218 (set (match_operand:SI 0 "arm_general_register_operand" "")
2219 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2220 (match_operand:SI 2 "const_int_operand" "")))]
2222 && !const_ok_for_arm (INTVAL (operands[2]))
2223 && const_ok_for_arm (~INTVAL (operands[2]))"
2224 [(set (match_dup 3) (match_dup 2))
2225 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2229 (define_insn "*iorsi3_compare0"
2230 [(set (reg:CC_NOOV CC_REGNUM)
2231 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2234 (set (match_operand:SI 0 "s_register_operand" "=r")
2235 (ior:SI (match_dup 1) (match_dup 2)))]
2237 "orr%?s\\t%0, %1, %2"
2238 [(set_attr "conds" "set")]
2241 (define_insn "*iorsi3_compare0_scratch"
2242 [(set (reg:CC_NOOV CC_REGNUM)
2243 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2246 (clobber (match_scratch:SI 0 "=r"))]
2248 "orr%?s\\t%0, %1, %2"
2249 [(set_attr "conds" "set")]
2252 (define_insn "xordi3"
2253 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2254 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2255 (match_operand:DI 2 "s_register_operand" "r,r")))]
2256 "TARGET_ARM && !TARGET_IWMMXT"
2258 [(set_attr "length" "8")
2259 (set_attr "predicable" "yes")]
2262 (define_insn "*xordi_zesidi_di"
2263 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264 (xor:DI (zero_extend:DI
2265 (match_operand:SI 2 "s_register_operand" "r,r"))
2266 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2269 eor%?\\t%Q0, %Q1, %2
2271 [(set_attr "length" "4,8")
2272 (set_attr "predicable" "yes")]
2275 (define_insn "*xordi_sesidi_di"
2276 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277 (xor:DI (sign_extend:DI
2278 (match_operand:SI 2 "s_register_operand" "r,r"))
2279 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2282 [(set_attr "length" "8")
2283 (set_attr "predicable" "yes")]
2286 (define_expand "xorsi3"
2287 [(set (match_operand:SI 0 "s_register_operand" "")
2288 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289 (match_operand:SI 2 "arm_rhs_operand" "")))]
2292 if (GET_CODE (operands[2]) == CONST_INT)
2293 operands[2] = force_reg (SImode, operands[2]);
2297 (define_insn "*arm_xorsi3"
2298 [(set (match_operand:SI 0 "s_register_operand" "=r")
2299 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2302 "eor%?\\t%0, %1, %2"
2303 [(set_attr "predicable" "yes")]
2306 (define_insn "*thumb_xorsi3"
2307 [(set (match_operand:SI 0 "register_operand" "=l")
2308 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309 (match_operand:SI 2 "register_operand" "l")))]
2312 [(set_attr "length" "2")]
2315 (define_insn "*xorsi3_compare0"
2316 [(set (reg:CC_NOOV CC_REGNUM)
2317 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2320 (set (match_operand:SI 0 "s_register_operand" "=r")
2321 (xor:SI (match_dup 1) (match_dup 2)))]
2323 "eor%?s\\t%0, %1, %2"
2324 [(set_attr "conds" "set")]
2327 (define_insn "*xorsi3_compare0_scratch"
2328 [(set (reg:CC_NOOV CC_REGNUM)
2329 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2334 [(set_attr "conds" "set")]
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2342 [(set (match_operand:SI 0 "s_register_operand" "")
2343 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345 (match_operand:SI 3 "arm_rhs_operand" "")))
2346 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2348 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349 (not:SI (match_dup 3))))
2350 (set (match_dup 0) (not:SI (match_dup 4)))]
2354 (define_insn "*andsi_iorsi3_notsi"
2355 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2360 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361 [(set_attr "length" "8")
2362 (set_attr "predicable" "yes")]
2366 [(set (match_operand:SI 0 "s_register_operand" "")
2367 (match_operator:SI 1 "logical_binary_operator"
2368 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2369 (match_operand:SI 3 "const_int_operand" "")
2370 (match_operand:SI 4 "const_int_operand" ""))
2371 (match_operator:SI 9 "logical_binary_operator"
2372 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2373 (match_operand:SI 6 "const_int_operand" ""))
2374 (match_operand:SI 7 "s_register_operand" "")])]))
2375 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2377 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2378 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2381 [(ashift:SI (match_dup 2) (match_dup 4))
2385 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2388 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2392 [(set (match_operand:SI 0 "s_register_operand" "")
2393 (match_operator:SI 1 "logical_binary_operator"
2394 [(match_operator:SI 9 "logical_binary_operator"
2395 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2396 (match_operand:SI 6 "const_int_operand" ""))
2397 (match_operand:SI 7 "s_register_operand" "")])
2398 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2399 (match_operand:SI 3 "const_int_operand" "")
2400 (match_operand:SI 4 "const_int_operand" ""))]))
2401 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2403 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2404 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2407 [(ashift:SI (match_dup 2) (match_dup 4))
2411 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2414 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2418 [(set (match_operand:SI 0 "s_register_operand" "")
2419 (match_operator:SI 1 "logical_binary_operator"
2420 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421 (match_operand:SI 3 "const_int_operand" "")
2422 (match_operand:SI 4 "const_int_operand" ""))
2423 (match_operator:SI 9 "logical_binary_operator"
2424 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2425 (match_operand:SI 6 "const_int_operand" ""))
2426 (match_operand:SI 7 "s_register_operand" "")])]))
2427 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2429 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2430 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2433 [(ashift:SI (match_dup 2) (match_dup 4))
2437 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2440 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2444 [(set (match_operand:SI 0 "s_register_operand" "")
2445 (match_operator:SI 1 "logical_binary_operator"
2446 [(match_operator:SI 9 "logical_binary_operator"
2447 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2448 (match_operand:SI 6 "const_int_operand" ""))
2449 (match_operand:SI 7 "s_register_operand" "")])
2450 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2451 (match_operand:SI 3 "const_int_operand" "")
2452 (match_operand:SI 4 "const_int_operand" ""))]))
2453 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2455 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2456 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2459 [(ashift:SI (match_dup 2) (match_dup 4))
2463 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2466 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2470 ;; Minimum and maximum insns
2472 (define_insn "smaxsi3"
2473 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2476 (clobber (reg:CC CC_REGNUM))]
2479 cmp\\t%1, %2\;movlt\\t%0, %2
2480 cmp\\t%1, %2\;movge\\t%0, %1
2481 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2482 [(set_attr "conds" "clob")
2483 (set_attr "length" "8,8,12")]
2486 (define_insn "sminsi3"
2487 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2488 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2489 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2490 (clobber (reg:CC CC_REGNUM))]
2493 cmp\\t%1, %2\;movge\\t%0, %2
2494 cmp\\t%1, %2\;movlt\\t%0, %1
2495 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2496 [(set_attr "conds" "clob")
2497 (set_attr "length" "8,8,12")]
2500 (define_insn "umaxsi3"
2501 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2502 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2503 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2504 (clobber (reg:CC CC_REGNUM))]
2507 cmp\\t%1, %2\;movcc\\t%0, %2
2508 cmp\\t%1, %2\;movcs\\t%0, %1
2509 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2510 [(set_attr "conds" "clob")
2511 (set_attr "length" "8,8,12")]
2514 (define_insn "uminsi3"
2515 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2516 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2517 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2518 (clobber (reg:CC CC_REGNUM))]
2521 cmp\\t%1, %2\;movcs\\t%0, %2
2522 cmp\\t%1, %2\;movcc\\t%0, %1
2523 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2524 [(set_attr "conds" "clob")
2525 (set_attr "length" "8,8,12")]
2528 (define_insn "*store_minmaxsi"
2529 [(set (match_operand:SI 0 "memory_operand" "=m")
2530 (match_operator:SI 3 "minmax_operator"
2531 [(match_operand:SI 1 "s_register_operand" "r")
2532 (match_operand:SI 2 "s_register_operand" "r")]))
2533 (clobber (reg:CC CC_REGNUM))]
2536 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2537 operands[1], operands[2]);
2538 output_asm_insn (\"cmp\\t%1, %2\", operands);
2539 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2540 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2543 [(set_attr "conds" "clob")
2544 (set_attr "length" "12")
2545 (set_attr "type" "store1")]
2548 ; Reject the frame pointer in operand[1], since reloading this after
2549 ; it has been eliminated can cause carnage.
2550 (define_insn "*minmax_arithsi"
2551 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2552 (match_operator:SI 4 "shiftable_operator"
2553 [(match_operator:SI 5 "minmax_operator"
2554 [(match_operand:SI 2 "s_register_operand" "r,r")
2555 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2556 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2557 (clobber (reg:CC CC_REGNUM))]
2558 "TARGET_ARM && !arm_eliminable_register (operands[1])"
2561 enum rtx_code code = GET_CODE (operands[4]);
2563 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2564 operands[2], operands[3]);
2565 output_asm_insn (\"cmp\\t%2, %3\", operands);
2566 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2567 if (which_alternative != 0 || operands[3] != const0_rtx
2568 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2569 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2572 [(set_attr "conds" "clob")
2573 (set_attr "length" "12")]
2577 ;; Shift and rotation insns
2579 (define_expand "ashldi3"
2580 [(set (match_operand:DI 0 "s_register_operand" "")
2581 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2582 (match_operand:SI 2 "reg_or_int_operand" "")))]
2585 if (GET_CODE (operands[2]) == CONST_INT)
2587 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2589 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2592 /* Ideally we shouldn't fail here if we could know that operands[1]
2593 ends up already living in an iwmmxt register. Otherwise it's
2594 cheaper to have the alternate code being generated than moving
2595 values to iwmmxt regs and back. */
2598 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603 (define_insn "arm_ashldi3_1bit"
2604 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2605 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2607 (clobber (reg:CC CC_REGNUM))]
2609 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2610 [(set_attr "conds" "clob")
2611 (set_attr "length" "8")]
2614 (define_expand "ashlsi3"
2615 [(set (match_operand:SI 0 "s_register_operand" "")
2616 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2617 (match_operand:SI 2 "arm_rhs_operand" "")))]
2620 if (GET_CODE (operands[2]) == CONST_INT
2621 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2623 emit_insn (gen_movsi (operands[0], const0_rtx));
2629 (define_insn "*thumb_ashlsi3"
2630 [(set (match_operand:SI 0 "register_operand" "=l,l")
2631 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2632 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2635 [(set_attr "length" "2")]
2638 (define_expand "ashrdi3"
2639 [(set (match_operand:DI 0 "s_register_operand" "")
2640 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2641 (match_operand:SI 2 "reg_or_int_operand" "")))]
2644 if (GET_CODE (operands[2]) == CONST_INT)
2646 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2648 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2651 /* Ideally we shouldn't fail here if we could know that operands[1]
2652 ends up already living in an iwmmxt register. Otherwise it's
2653 cheaper to have the alternate code being generated than moving
2654 values to iwmmxt regs and back. */
2657 else if (!TARGET_REALLY_IWMMXT)
2662 (define_insn "arm_ashrdi3_1bit"
2663 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2664 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2666 (clobber (reg:CC CC_REGNUM))]
2668 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2669 [(set_attr "conds" "clob")
2670 (set_attr "length" "8")]
2673 (define_expand "ashrsi3"
2674 [(set (match_operand:SI 0 "s_register_operand" "")
2675 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2676 (match_operand:SI 2 "arm_rhs_operand" "")))]
2679 if (GET_CODE (operands[2]) == CONST_INT
2680 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2681 operands[2] = GEN_INT (31);
2685 (define_insn "*thumb_ashrsi3"
2686 [(set (match_operand:SI 0 "register_operand" "=l,l")
2687 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2688 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2691 [(set_attr "length" "2")]
2694 (define_expand "lshrdi3"
2695 [(set (match_operand:DI 0 "s_register_operand" "")
2696 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2697 (match_operand:SI 2 "reg_or_int_operand" "")))]
2700 if (GET_CODE (operands[2]) == CONST_INT)
2702 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2704 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2707 /* Ideally we shouldn't fail here if we could know that operands[1]
2708 ends up already living in an iwmmxt register. Otherwise it's
2709 cheaper to have the alternate code being generated than moving
2710 values to iwmmxt regs and back. */
2713 else if (!TARGET_REALLY_IWMMXT)
2718 (define_insn "arm_lshrdi3_1bit"
2719 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2720 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2722 (clobber (reg:CC CC_REGNUM))]
2724 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2725 [(set_attr "conds" "clob")
2726 (set_attr "length" "8")]
2729 (define_expand "lshrsi3"
2730 [(set (match_operand:SI 0 "s_register_operand" "")
2731 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2732 (match_operand:SI 2 "arm_rhs_operand" "")))]
2735 if (GET_CODE (operands[2]) == CONST_INT
2736 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2738 emit_insn (gen_movsi (operands[0], const0_rtx));
2744 (define_insn "*thumb_lshrsi3"
2745 [(set (match_operand:SI 0 "register_operand" "=l,l")
2746 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2747 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2750 [(set_attr "length" "2")]
2753 (define_expand "rotlsi3"
2754 [(set (match_operand:SI 0 "s_register_operand" "")
2755 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2756 (match_operand:SI 2 "reg_or_int_operand" "")))]
2759 if (GET_CODE (operands[2]) == CONST_INT)
2760 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2763 rtx reg = gen_reg_rtx (SImode);
2764 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2770 (define_expand "rotrsi3"
2771 [(set (match_operand:SI 0 "s_register_operand" "")
2772 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2773 (match_operand:SI 2 "arm_rhs_operand" "")))]
2778 if (GET_CODE (operands[2]) == CONST_INT
2779 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2780 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2782 else /* TARGET_THUMB */
2784 if (GET_CODE (operands [2]) == CONST_INT)
2785 operands [2] = force_reg (SImode, operands[2]);
2790 (define_insn "*thumb_rotrsi3"
2791 [(set (match_operand:SI 0 "register_operand" "=l")
2792 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2793 (match_operand:SI 2 "register_operand" "l")))]
2796 [(set_attr "length" "2")]
2799 (define_insn "*arm_shiftsi3"
2800 [(set (match_operand:SI 0 "s_register_operand" "=r")
2801 (match_operator:SI 3 "shift_operator"
2802 [(match_operand:SI 1 "s_register_operand" "r")
2803 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2806 [(set_attr "predicable" "yes")
2807 (set_attr "shift" "1")
2808 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2809 (const_string "alu_shift")
2810 (const_string "alu_shift_reg")))]
2813 (define_insn "*shiftsi3_compare0"
2814 [(set (reg:CC_NOOV CC_REGNUM)
2815 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2816 [(match_operand:SI 1 "s_register_operand" "r")
2817 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2819 (set (match_operand:SI 0 "s_register_operand" "=r")
2820 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2822 "mov%?s\\t%0, %1%S3"
2823 [(set_attr "conds" "set")
2824 (set_attr "shift" "1")
2825 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2826 (const_string "alu_shift")
2827 (const_string "alu_shift_reg")))]
2830 (define_insn "*shiftsi3_compare0_scratch"
2831 [(set (reg:CC_NOOV CC_REGNUM)
2832 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2833 [(match_operand:SI 1 "s_register_operand" "r")
2834 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2836 (clobber (match_scratch:SI 0 "=r"))]
2838 "mov%?s\\t%0, %1%S3"
2839 [(set_attr "conds" "set")
2840 (set_attr "shift" "1")]
2843 (define_insn "*notsi_shiftsi"
2844 [(set (match_operand:SI 0 "s_register_operand" "=r")
2845 (not:SI (match_operator:SI 3 "shift_operator"
2846 [(match_operand:SI 1 "s_register_operand" "r")
2847 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2850 [(set_attr "predicable" "yes")
2851 (set_attr "shift" "1")
2852 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2853 (const_string "alu_shift")
2854 (const_string "alu_shift_reg")))]
2857 (define_insn "*notsi_shiftsi_compare0"
2858 [(set (reg:CC_NOOV CC_REGNUM)
2859 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2860 [(match_operand:SI 1 "s_register_operand" "r")
2861 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2863 (set (match_operand:SI 0 "s_register_operand" "=r")
2864 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2866 "mvn%?s\\t%0, %1%S3"
2867 [(set_attr "conds" "set")
2868 (set_attr "shift" "1")
2869 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2870 (const_string "alu_shift")
2871 (const_string "alu_shift_reg")))]
2874 (define_insn "*not_shiftsi_compare0_scratch"
2875 [(set (reg:CC_NOOV CC_REGNUM)
2876 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2877 [(match_operand:SI 1 "s_register_operand" "r")
2878 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2880 (clobber (match_scratch:SI 0 "=r"))]
2882 "mvn%?s\\t%0, %1%S3"
2883 [(set_attr "conds" "set")
2884 (set_attr "shift" "1")
2885 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2886 (const_string "alu_shift")
2887 (const_string "alu_shift_reg")))]
2890 ;; We don't really have extzv, but defining this using shifts helps
2891 ;; to reduce register pressure later on.
2893 (define_expand "extzv"
2895 (ashift:SI (match_operand:SI 1 "register_operand" "")
2896 (match_operand:SI 2 "const_int_operand" "")))
2897 (set (match_operand:SI 0 "register_operand" "")
2898 (lshiftrt:SI (match_dup 4)
2899 (match_operand:SI 3 "const_int_operand" "")))]
2903 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2904 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2906 operands[3] = GEN_INT (rshift);
2910 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2914 operands[2] = GEN_INT (lshift);
2915 operands[4] = gen_reg_rtx (SImode);
2920 ;; Unary arithmetic insns
2922 (define_expand "negdi2"
2924 [(set (match_operand:DI 0 "s_register_operand" "")
2925 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2926 (clobber (reg:CC CC_REGNUM))])]
2931 if (GET_CODE (operands[1]) != REG)
2932 operands[1] = force_reg (SImode, operands[1]);
2937 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2938 ;; The second alternative is to allow the common case of a *full* overlap.
2939 (define_insn "*arm_negdi2"
2940 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2941 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2942 (clobber (reg:CC CC_REGNUM))]
2944 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2945 [(set_attr "conds" "clob")
2946 (set_attr "length" "8")]
2949 (define_insn "*thumb_negdi2"
2950 [(set (match_operand:DI 0 "register_operand" "=&l")
2951 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2952 (clobber (reg:CC CC_REGNUM))]
2954 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2955 [(set_attr "length" "6")]
2958 (define_expand "negsi2"
2959 [(set (match_operand:SI 0 "s_register_operand" "")
2960 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965 (define_insn "*arm_negsi2"
2966 [(set (match_operand:SI 0 "s_register_operand" "=r")
2967 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2969 "rsb%?\\t%0, %1, #0"
2970 [(set_attr "predicable" "yes")]
2973 (define_insn "*thumb_negsi2"
2974 [(set (match_operand:SI 0 "register_operand" "=l")
2975 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2978 [(set_attr "length" "2")]
2981 (define_expand "negsf2"
2982 [(set (match_operand:SF 0 "s_register_operand" "")
2983 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2984 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2988 (define_expand "negdf2"
2989 [(set (match_operand:DF 0 "s_register_operand" "")
2990 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2991 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2994 ;; abssi2 doesn't really clobber the condition codes if a different register
2995 ;; is being set. To keep things simple, assume during rtl manipulations that
2996 ;; it does, but tell the final scan operator the truth. Similarly for
2999 (define_expand "abssi2"
3001 [(set (match_operand:SI 0 "s_register_operand" "")
3002 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3003 (clobber (reg:CC CC_REGNUM))])]
3007 (define_insn "*arm_abssi2"
3008 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3009 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3010 (clobber (reg:CC CC_REGNUM))]
3013 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3014 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3015 [(set_attr "conds" "clob,*")
3016 (set_attr "shift" "1")
3017 ;; predicable can't be set based on the variant, so left as no
3018 (set_attr "length" "8")]
3021 (define_insn "*neg_abssi2"
3022 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3023 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3024 (clobber (reg:CC CC_REGNUM))]
3027 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3028 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3029 [(set_attr "conds" "clob,*")
3030 (set_attr "shift" "1")
3031 ;; predicable can't be set based on the variant, so left as no
3032 (set_attr "length" "8")]
3035 (define_expand "abssf2"
3036 [(set (match_operand:SF 0 "s_register_operand" "")
3037 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3038 "TARGET_ARM && TARGET_HARD_FLOAT"
3041 (define_expand "absdf2"
3042 [(set (match_operand:DF 0 "s_register_operand" "")
3043 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3044 "TARGET_ARM && TARGET_HARD_FLOAT"
3047 (define_expand "sqrtsf2"
3048 [(set (match_operand:SF 0 "s_register_operand" "")
3049 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3050 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3053 (define_expand "sqrtdf2"
3054 [(set (match_operand:DF 0 "s_register_operand" "")
3055 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3056 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3059 (define_insn_and_split "one_cmpldi2"
3060 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3061 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3064 "TARGET_ARM && reload_completed"
3065 [(set (match_dup 0) (not:SI (match_dup 1)))
3066 (set (match_dup 2) (not:SI (match_dup 3)))]
3069 operands[2] = gen_highpart (SImode, operands[0]);
3070 operands[0] = gen_lowpart (SImode, operands[0]);
3071 operands[3] = gen_highpart (SImode, operands[1]);
3072 operands[1] = gen_lowpart (SImode, operands[1]);
3074 [(set_attr "length" "8")
3075 (set_attr "predicable" "yes")]
3078 (define_expand "one_cmplsi2"
3079 [(set (match_operand:SI 0 "s_register_operand" "")
3080 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085 (define_insn "*arm_one_cmplsi2"
3086 [(set (match_operand:SI 0 "s_register_operand" "=r")
3087 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3090 [(set_attr "predicable" "yes")]
3093 (define_insn "*thumb_one_cmplsi2"
3094 [(set (match_operand:SI 0 "register_operand" "=l")
3095 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3098 [(set_attr "length" "2")]
3101 (define_insn "*notsi_compare0"
3102 [(set (reg:CC_NOOV CC_REGNUM)
3103 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3105 (set (match_operand:SI 0 "s_register_operand" "=r")
3106 (not:SI (match_dup 1)))]
3109 [(set_attr "conds" "set")]
3112 (define_insn "*notsi_compare0_scratch"
3113 [(set (reg:CC_NOOV CC_REGNUM)
3114 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3116 (clobber (match_scratch:SI 0 "=r"))]
3119 [(set_attr "conds" "set")]
3122 ;; Fixed <--> Floating conversion insns
3124 (define_expand "floatsisf2"
3125 [(set (match_operand:SF 0 "s_register_operand" "")
3126 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3127 "TARGET_ARM && TARGET_HARD_FLOAT"
3129 if (TARGET_MAVERICK)
3131 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136 (define_expand "floatsidf2"
3137 [(set (match_operand:DF 0 "s_register_operand" "")
3138 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3139 "TARGET_ARM && TARGET_HARD_FLOAT"
3141 if (TARGET_MAVERICK)
3143 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148 (define_expand "fix_truncsfsi2"
3149 [(set (match_operand:SI 0 "s_register_operand" "")
3150 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3151 "TARGET_ARM && TARGET_HARD_FLOAT"
3153 if (TARGET_MAVERICK)
3155 if (!cirrus_fp_register (operands[0], SImode))
3156 operands[0] = force_reg (SImode, operands[0]);
3157 if (!cirrus_fp_register (operands[1], SFmode))
3158 operands[1] = force_reg (SFmode, operands[0]);
3159 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164 (define_expand "fix_truncdfsi2"
3165 [(set (match_operand:SI 0 "s_register_operand" "")
3166 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3167 "TARGET_ARM && TARGET_HARD_FLOAT"
3169 if (TARGET_MAVERICK)
3171 if (!cirrus_fp_register (operands[1], DFmode))
3172 operands[1] = force_reg (DFmode, operands[0]);
3173 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3180 (define_expand "truncdfsf2"
3181 [(set (match_operand:SF 0 "s_register_operand" "")
3183 (match_operand:DF 1 "s_register_operand" "")))]
3184 "TARGET_ARM && TARGET_HARD_FLOAT"
3188 ;; Zero and sign extension instructions.
3190 (define_insn "zero_extendsidi2"
3191 [(set (match_operand:DI 0 "s_register_operand" "=r")
3192 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3195 if (REGNO (operands[1])
3196 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3197 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3198 return \"mov%?\\t%R0, #0\";
3200 [(set_attr "length" "8")
3201 (set_attr "predicable" "yes")]
3204 (define_insn "zero_extendqidi2"
3205 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3206 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3209 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3210 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3211 [(set_attr "length" "8")
3212 (set_attr "predicable" "yes")
3213 (set_attr "type" "*,load_byte")
3214 (set_attr "pool_range" "*,4092")
3215 (set_attr "neg_pool_range" "*,4084")]
3218 (define_insn "extendsidi2"
3219 [(set (match_operand:DI 0 "s_register_operand" "=r")
3220 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3223 if (REGNO (operands[1])
3224 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3225 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3226 return \"mov%?\\t%R0, %Q0, asr #31\";
3228 [(set_attr "length" "8")
3229 (set_attr "shift" "1")
3230 (set_attr "predicable" "yes")]
3233 (define_expand "zero_extendhisi2"
3235 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3237 (set (match_operand:SI 0 "s_register_operand" "")
3238 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3242 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3244 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3245 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3249 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3251 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3255 if (!s_register_operand (operands[1], HImode))
3256 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3260 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3261 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3265 operands[1] = gen_lowpart (SImode, operands[1]);
3266 operands[2] = gen_reg_rtx (SImode);
3270 (define_insn "*thumb_zero_extendhisi2"
3271 [(set (match_operand:SI 0 "register_operand" "=l")
3272 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3273 "TARGET_THUMB && !arm_arch6"
3275 rtx mem = XEXP (operands[1], 0);
3277 if (GET_CODE (mem) == CONST)
3278 mem = XEXP (mem, 0);
3280 if (GET_CODE (mem) == LABEL_REF)
3281 return \"ldr\\t%0, %1\";
3283 if (GET_CODE (mem) == PLUS)
3285 rtx a = XEXP (mem, 0);
3286 rtx b = XEXP (mem, 1);
3288 /* This can happen due to bugs in reload. */
3289 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3292 ops[0] = operands[0];
3295 output_asm_insn (\"mov %0, %1\", ops);
3297 XEXP (mem, 0) = operands[0];
3300 else if ( GET_CODE (a) == LABEL_REF
3301 && GET_CODE (b) == CONST_INT)
3302 return \"ldr\\t%0, %1\";
3305 return \"ldrh\\t%0, %1\";
3307 [(set_attr "length" "4")
3308 (set_attr "type" "load_byte")
3309 (set_attr "pool_range" "60")]
3312 (define_insn "*thumb_zero_extendhisi2_v6"
3313 [(set (match_operand:SI 0 "register_operand" "=l,l")
3314 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3315 "TARGET_THUMB && arm_arch6"
3319 if (which_alternative == 0)
3320 return \"uxth\\t%0, %1\";
3322 mem = XEXP (operands[1], 0);
3324 if (GET_CODE (mem) == CONST)
3325 mem = XEXP (mem, 0);
3327 if (GET_CODE (mem) == LABEL_REF)
3328 return \"ldr\\t%0, %1\";
3330 if (GET_CODE (mem) == PLUS)
3332 rtx a = XEXP (mem, 0);
3333 rtx b = XEXP (mem, 1);
3335 /* This can happen due to bugs in reload. */
3336 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3339 ops[0] = operands[0];
3342 output_asm_insn (\"mov %0, %1\", ops);
3344 XEXP (mem, 0) = operands[0];
3347 else if ( GET_CODE (a) == LABEL_REF
3348 && GET_CODE (b) == CONST_INT)
3349 return \"ldr\\t%0, %1\";
3352 return \"ldrh\\t%0, %1\";
3354 [(set_attr "length" "2,4")
3355 (set_attr "type" "alu_shift,load_byte")
3356 (set_attr "pool_range" "*,60")]
3359 (define_insn "*arm_zero_extendhisi2"
3360 [(set (match_operand:SI 0 "s_register_operand" "=r")
3361 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3362 "TARGET_ARM && arm_arch4 && !arm_arch6"
3364 [(set_attr "type" "load_byte")
3365 (set_attr "predicable" "yes")
3366 (set_attr "pool_range" "256")
3367 (set_attr "neg_pool_range" "244")]
3370 (define_insn "*arm_zero_extendhisi2_v6"
3371 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3372 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3373 "TARGET_ARM && arm_arch6"
3377 [(set_attr "type" "alu_shift,load_byte")
3378 (set_attr "predicable" "yes")
3379 (set_attr "pool_range" "*,256")
3380 (set_attr "neg_pool_range" "*,244")]
3383 (define_insn "*arm_zero_extendhisi2addsi"
3384 [(set (match_operand:SI 0 "s_register_operand" "=r")
3385 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3386 (match_operand:SI 2 "s_register_operand" "r")))]
3387 "TARGET_ARM && arm_arch6"
3388 "uxtah%?\\t%0, %2, %1"
3389 [(set_attr "type" "alu_shift")
3390 (set_attr "predicable" "yes")]
3394 [(set (match_operand:SI 0 "s_register_operand" "")
3395 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3396 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3397 "TARGET_ARM && (!arm_arch4)"
3398 [(set (match_dup 2) (match_dup 1))
3399 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3401 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3407 [(set (match_operand:SI 0 "s_register_operand" "")
3408 (match_operator:SI 3 "shiftable_operator"
3409 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3410 (match_operand:SI 4 "s_register_operand" "")]))
3411 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3412 "TARGET_ARM && (!arm_arch4)"
3413 [(set (match_dup 2) (match_dup 1))
3416 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3418 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3423 (define_expand "zero_extendqisi2"
3424 [(set (match_operand:SI 0 "s_register_operand" "")
3425 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3428 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3432 emit_insn (gen_andsi3 (operands[0],
3433 gen_lowpart (SImode, operands[1]),
3436 else /* TARGET_THUMB */
3438 rtx temp = gen_reg_rtx (SImode);
3441 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3442 operands[1] = gen_lowpart (SImode, operands[1]);
3445 ops[1] = operands[1];
3446 ops[2] = GEN_INT (24);
3448 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3451 ops[0] = operands[0];
3453 ops[2] = GEN_INT (24);
3455 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3463 (define_insn "*thumb_zero_extendqisi2"
3464 [(set (match_operand:SI 0 "register_operand" "=l")
3465 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3466 "TARGET_THUMB && !arm_arch6"
3468 [(set_attr "length" "2")
3469 (set_attr "type" "load_byte")
3470 (set_attr "pool_range" "32")]
3473 (define_insn "*thumb_zero_extendqisi2_v6"
3474 [(set (match_operand:SI 0 "register_operand" "=l,l")
3475 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3476 "TARGET_THUMB && arm_arch6"
3480 [(set_attr "length" "2,2")
3481 (set_attr "type" "alu_shift,load_byte")
3482 (set_attr "pool_range" "*,32")]
3485 (define_insn "*arm_zero_extendqisi2"
3486 [(set (match_operand:SI 0 "s_register_operand" "=r")
3487 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3488 "TARGET_ARM && !arm_arch6"
3489 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3490 [(set_attr "type" "load_byte")
3491 (set_attr "predicable" "yes")
3492 (set_attr "pool_range" "4096")
3493 (set_attr "neg_pool_range" "4084")]
3496 (define_insn "*arm_zero_extendqisi2_v6"
3497 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3498 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3499 "TARGET_ARM && arm_arch6"
3502 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3503 [(set_attr "type" "alu_shift,load_byte")
3504 (set_attr "predicable" "yes")
3505 (set_attr "pool_range" "*,4096")
3506 (set_attr "neg_pool_range" "*,4084")]
3509 (define_insn "*arm_zero_extendqisi2addsi"
3510 [(set (match_operand:SI 0 "s_register_operand" "=r")
3511 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3512 (match_operand:SI 2 "s_register_operand" "r")))]
3513 "TARGET_ARM && arm_arch6"
3514 "uxtab%?\\t%0, %2, %1"
3515 [(set_attr "predicable" "yes")
3516 (set_attr "type" "alu_shift")]
3520 [(set (match_operand:SI 0 "s_register_operand" "")
3521 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3522 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3523 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3524 [(set (match_dup 2) (match_dup 1))
3525 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3529 (define_insn "*compareqi_eq0"
3530 [(set (reg:CC_Z CC_REGNUM)
3531 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3535 [(set_attr "conds" "set")]
3538 (define_expand "extendhisi2"
3540 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3542 (set (match_operand:SI 0 "s_register_operand" "")
3543 (ashiftrt:SI (match_dup 2)
3548 if (GET_CODE (operands[1]) == MEM)
3552 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3557 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3558 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3563 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3565 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3569 if (!s_register_operand (operands[1], HImode))
3570 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3575 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3577 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3578 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3583 operands[1] = gen_lowpart (SImode, operands[1]);
3584 operands[2] = gen_reg_rtx (SImode);
3588 (define_insn "thumb_extendhisi2"
3589 [(set (match_operand:SI 0 "register_operand" "=l")
3590 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3591 (clobber (match_scratch:SI 2 "=&l"))]
3592 "TARGET_THUMB && !arm_arch6"
3596 rtx mem = XEXP (operands[1], 0);
3598 /* This code used to try to use 'V', and fix the address only if it was
3599 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3600 range of QImode offsets, and offsettable_address_p does a QImode
3603 if (GET_CODE (mem) == CONST)
3604 mem = XEXP (mem, 0);
3606 if (GET_CODE (mem) == LABEL_REF)
3607 return \"ldr\\t%0, %1\";
3609 if (GET_CODE (mem) == PLUS)
3611 rtx a = XEXP (mem, 0);
3612 rtx b = XEXP (mem, 1);
3614 if (GET_CODE (a) == LABEL_REF
3615 && GET_CODE (b) == CONST_INT)
3616 return \"ldr\\t%0, %1\";
3618 if (GET_CODE (b) == REG)
3619 return \"ldrsh\\t%0, %1\";
3627 ops[2] = const0_rtx;
3630 gcc_assert (GET_CODE (ops[1]) == REG);
3632 ops[0] = operands[0];
3633 ops[3] = operands[2];
3634 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3637 [(set_attr "length" "4")
3638 (set_attr "type" "load_byte")
3639 (set_attr "pool_range" "1020")]
3642 ;; We used to have an early-clobber on the scratch register here.
3643 ;; However, there's a bug somewhere in reload which means that this
3644 ;; can be partially ignored during spill allocation if the memory
3645 ;; address also needs reloading; this causes us to die later on when
3646 ;; we try to verify the operands. Fortunately, we don't really need
3647 ;; the early-clobber: we can always use operand 0 if operand 2
3648 ;; overlaps the address.
3649 (define_insn "*thumb_extendhisi2_insn_v6"
3650 [(set (match_operand:SI 0 "register_operand" "=l,l")
3651 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3652 (clobber (match_scratch:SI 2 "=X,l"))]
3653 "TARGET_THUMB && arm_arch6"
3659 if (which_alternative == 0)
3660 return \"sxth\\t%0, %1\";
3662 mem = XEXP (operands[1], 0);
3664 /* This code used to try to use 'V', and fix the address only if it was
3665 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3666 range of QImode offsets, and offsettable_address_p does a QImode
3669 if (GET_CODE (mem) == CONST)
3670 mem = XEXP (mem, 0);
3672 if (GET_CODE (mem) == LABEL_REF)
3673 return \"ldr\\t%0, %1\";
3675 if (GET_CODE (mem) == PLUS)
3677 rtx a = XEXP (mem, 0);
3678 rtx b = XEXP (mem, 1);
3680 if (GET_CODE (a) == LABEL_REF
3681 && GET_CODE (b) == CONST_INT)
3682 return \"ldr\\t%0, %1\";
3684 if (GET_CODE (b) == REG)
3685 return \"ldrsh\\t%0, %1\";
3693 ops[2] = const0_rtx;
3696 gcc_assert (GET_CODE (ops[1]) == REG);
3698 ops[0] = operands[0];
3699 if (reg_mentioned_p (operands[2], ops[1]))
3702 ops[3] = operands[2];
3703 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3706 [(set_attr "length" "2,4")
3707 (set_attr "type" "alu_shift,load_byte")
3708 (set_attr "pool_range" "*,1020")]
3711 (define_expand "extendhisi2_mem"
3712 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3714 (zero_extend:SI (match_dup 7)))
3715 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3716 (set (match_operand:SI 0 "" "")
3717 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3722 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3724 mem1 = gen_rtx_MEM (QImode, addr);
3725 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3726 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3727 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3728 operands[0] = gen_lowpart (SImode, operands[0]);
3730 operands[2] = gen_reg_rtx (SImode);
3731 operands[3] = gen_reg_rtx (SImode);
3732 operands[6] = gen_reg_rtx (SImode);
3735 if (BYTES_BIG_ENDIAN)
3737 operands[4] = operands[2];
3738 operands[5] = operands[3];
3742 operands[4] = operands[3];
3743 operands[5] = operands[2];
3748 (define_insn "*arm_extendhisi2"
3749 [(set (match_operand:SI 0 "s_register_operand" "=r")
3750 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3751 "TARGET_ARM && arm_arch4 && !arm_arch6"
3753 [(set_attr "type" "load_byte")
3754 (set_attr "predicable" "yes")
3755 (set_attr "pool_range" "256")
3756 (set_attr "neg_pool_range" "244")]
3759 (define_insn "*arm_extendhisi2_v6"
3760 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3761 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3762 "TARGET_ARM && arm_arch6"
3766 [(set_attr "type" "alu_shift,load_byte")
3767 (set_attr "predicable" "yes")
3768 (set_attr "pool_range" "*,256")
3769 (set_attr "neg_pool_range" "*,244")]
3772 (define_insn "*arm_extendhisi2addsi"
3773 [(set (match_operand:SI 0 "s_register_operand" "=r")
3774 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3775 (match_operand:SI 2 "s_register_operand" "r")))]
3776 "TARGET_ARM && arm_arch6"
3777 "sxtah%?\\t%0, %2, %1"
3781 [(set (match_operand:SI 0 "s_register_operand" "")
3782 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3783 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3784 "TARGET_ARM && (!arm_arch4)"
3785 [(set (match_dup 2) (match_dup 1))
3786 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3788 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3794 [(set (match_operand:SI 0 "s_register_operand" "")
3795 (match_operator:SI 3 "shiftable_operator"
3796 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3797 (match_operand:SI 4 "s_register_operand" "")]))
3798 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3799 "TARGET_ARM && (!arm_arch4)"
3800 [(set (match_dup 2) (match_dup 1))
3803 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3804 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3809 (define_expand "extendqihi2"
3811 (ashift:SI (match_operand:QI 1 "general_operand" "")
3813 (set (match_operand:HI 0 "s_register_operand" "")
3814 (ashiftrt:SI (match_dup 2)
3819 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3821 emit_insn (gen_rtx_SET (VOIDmode,
3823 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3826 if (!s_register_operand (operands[1], QImode))
3827 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3828 operands[0] = gen_lowpart (SImode, operands[0]);
3829 operands[1] = gen_lowpart (SImode, operands[1]);
3830 operands[2] = gen_reg_rtx (SImode);
3834 (define_insn "*extendqihi_insn"
3835 [(set (match_operand:HI 0 "s_register_operand" "=r")
3836 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3837 "TARGET_ARM && arm_arch4"
3839 [(set_attr "type" "load_byte")
3840 (set_attr "predicable" "yes")
3841 (set_attr "pool_range" "256")
3842 (set_attr "neg_pool_range" "244")]
3845 (define_expand "extendqisi2"
3847 (ashift:SI (match_operand:QI 1 "general_operand" "")
3849 (set (match_operand:SI 0 "s_register_operand" "")
3850 (ashiftrt:SI (match_dup 2)
3855 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3857 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3858 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3862 if (!s_register_operand (operands[1], QImode))
3863 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3867 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3868 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3872 operands[1] = gen_lowpart (SImode, operands[1]);
3873 operands[2] = gen_reg_rtx (SImode);
3877 (define_insn "*arm_extendqisi"
3878 [(set (match_operand:SI 0 "s_register_operand" "=r")
3879 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3880 "TARGET_ARM && arm_arch4 && !arm_arch6"
3882 [(set_attr "type" "load_byte")
3883 (set_attr "predicable" "yes")
3884 (set_attr "pool_range" "256")
3885 (set_attr "neg_pool_range" "244")]
3888 (define_insn "*arm_extendqisi_v6"
3889 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3890 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3891 "TARGET_ARM && arm_arch6"
3895 [(set_attr "type" "alu_shift,load_byte")
3896 (set_attr "predicable" "yes")
3897 (set_attr "pool_range" "*,256")
3898 (set_attr "neg_pool_range" "*,244")]
3901 (define_insn "*arm_extendqisi2addsi"
3902 [(set (match_operand:SI 0 "s_register_operand" "=r")
3903 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3904 (match_operand:SI 2 "s_register_operand" "r")))]
3905 "TARGET_ARM && arm_arch6"
3906 "sxtab%?\\t%0, %2, %1"
3907 [(set_attr "type" "alu_shift")
3908 (set_attr "predicable" "yes")]
3911 (define_insn "*thumb_extendqisi2"
3912 [(set (match_operand:SI 0 "register_operand" "=l,l")
3913 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3914 "TARGET_THUMB && !arm_arch6"
3918 rtx mem = XEXP (operands[1], 0);
3920 if (GET_CODE (mem) == CONST)
3921 mem = XEXP (mem, 0);
3923 if (GET_CODE (mem) == LABEL_REF)
3924 return \"ldr\\t%0, %1\";
3926 if (GET_CODE (mem) == PLUS
3927 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3928 return \"ldr\\t%0, %1\";
3930 if (which_alternative == 0)
3931 return \"ldrsb\\t%0, %1\";
3933 ops[0] = operands[0];
3935 if (GET_CODE (mem) == PLUS)
3937 rtx a = XEXP (mem, 0);
3938 rtx b = XEXP (mem, 1);
3943 if (GET_CODE (a) == REG)
3945 if (GET_CODE (b) == REG)
3946 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3947 else if (REGNO (a) == REGNO (ops[0]))
3949 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3950 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3951 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3954 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958 gcc_assert (GET_CODE (b) == REG);
3959 if (REGNO (b) == REGNO (ops[0]))
3961 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3962 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3963 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3966 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3971 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3972 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3973 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978 ops[2] = const0_rtx;
3980 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3984 [(set_attr "length" "2,6")
3985 (set_attr "type" "load_byte,load_byte")
3986 (set_attr "pool_range" "32,32")]
3989 (define_insn "*thumb_extendqisi2_v6"
3990 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3991 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3992 "TARGET_THUMB && arm_arch6"
3998 if (which_alternative == 0)
3999 return \"sxtb\\t%0, %1\";
4001 mem = XEXP (operands[1], 0);
4003 if (GET_CODE (mem) == CONST)
4004 mem = XEXP (mem, 0);
4006 if (GET_CODE (mem) == LABEL_REF)
4007 return \"ldr\\t%0, %1\";
4009 if (GET_CODE (mem) == PLUS
4010 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4011 return \"ldr\\t%0, %1\";
4013 if (which_alternative == 0)
4014 return \"ldrsb\\t%0, %1\";
4016 ops[0] = operands[0];
4018 if (GET_CODE (mem) == PLUS)
4020 rtx a = XEXP (mem, 0);
4021 rtx b = XEXP (mem, 1);
4026 if (GET_CODE (a) == REG)
4028 if (GET_CODE (b) == REG)
4029 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4030 else if (REGNO (a) == REGNO (ops[0]))
4032 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4033 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4036 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4040 gcc_assert (GET_CODE (b) == REG);
4041 if (REGNO (b) == REGNO (ops[0]))
4043 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4044 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4047 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4050 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4052 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4053 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4058 ops[2] = const0_rtx;
4060 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4064 [(set_attr "length" "2,2,4")
4065 (set_attr "type" "alu_shift,load_byte,load_byte")
4066 (set_attr "pool_range" "*,32,32")]
4069 (define_expand "extendsfdf2"
4070 [(set (match_operand:DF 0 "s_register_operand" "")
4071 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4072 "TARGET_ARM && TARGET_HARD_FLOAT"
4076 ;; Move insns (including loads and stores)
4078 ;; XXX Just some ideas about movti.
4079 ;; I don't think these are a good idea on the arm, there just aren't enough
4081 ;;(define_expand "loadti"
4082 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4083 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4086 ;;(define_expand "storeti"
4087 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4088 ;; (match_operand:TI 1 "s_register_operand" ""))]
4091 ;;(define_expand "movti"
4092 ;; [(set (match_operand:TI 0 "general_operand" "")
4093 ;; (match_operand:TI 1 "general_operand" ""))]
4099 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4100 ;; operands[1] = copy_to_reg (operands[1]);
4101 ;; if (GET_CODE (operands[0]) == MEM)
4102 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4103 ;; else if (GET_CODE (operands[1]) == MEM)
4104 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4108 ;; emit_insn (insn);
4112 ;; Recognize garbage generated above.
4115 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4116 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4120 ;; register mem = (which_alternative < 3);
4121 ;; register const char *template;
4123 ;; operands[mem] = XEXP (operands[mem], 0);
4124 ;; switch (which_alternative)
4126 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4127 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4128 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4129 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4130 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4131 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4133 ;; output_asm_insn (template, operands);
4137 (define_expand "movdi"
4138 [(set (match_operand:DI 0 "general_operand" "")
4139 (match_operand:DI 1 "general_operand" ""))]
4144 if (!no_new_pseudos)
4146 if (GET_CODE (operands[0]) != REG)
4147 operands[1] = force_reg (DImode, operands[1]);
4153 (define_insn "*arm_movdi"
4154 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4155 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4157 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4160 switch (which_alternative)
4167 return output_move_double (operands);
4170 [(set_attr "length" "8,12,16,8,8")
4171 (set_attr "type" "*,*,*,load2,store2")
4172 (set_attr "pool_range" "*,*,*,1020,*")
4173 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4177 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4178 (match_operand:ANY64 1 "const_double_operand" ""))]
4181 && (arm_const_double_inline_cost (operands[1])
4182 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4185 arm_split_constant (SET, SImode, curr_insn,
4186 INTVAL (gen_lowpart (SImode, operands[1])),
4187 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4188 arm_split_constant (SET, SImode, curr_insn,
4189 INTVAL (gen_highpart_mode (SImode,
4190 GET_MODE (operands[0]),
4192 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4197 ; If optimizing for size, or if we have load delay slots, then
4198 ; we want to split the constant into two separate operations.
4199 ; In both cases this may split a trivial part into a single data op
4200 ; leaving a single complex constant to load. We can also get longer
4201 ; offsets in a LDR which means we get better chances of sharing the pool
4202 ; entries. Finally, we can normally do a better job of scheduling
4203 ; LDR instructions than we can with LDM.
4204 ; This pattern will only match if the one above did not.
4206 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4207 (match_operand:ANY64 1 "const_double_operand" ""))]
4208 "TARGET_ARM && reload_completed
4209 && arm_const_double_by_parts (operands[1])"
4210 [(set (match_dup 0) (match_dup 1))
4211 (set (match_dup 2) (match_dup 3))]
4213 operands[2] = gen_highpart (SImode, operands[0]);
4214 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4216 operands[0] = gen_lowpart (SImode, operands[0]);
4217 operands[1] = gen_lowpart (SImode, operands[1]);
4222 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4223 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4224 "TARGET_EITHER && reload_completed"
4225 [(set (match_dup 0) (match_dup 1))
4226 (set (match_dup 2) (match_dup 3))]
4228 operands[2] = gen_highpart (SImode, operands[0]);
4229 operands[3] = gen_highpart (SImode, operands[1]);
4230 operands[0] = gen_lowpart (SImode, operands[0]);
4231 operands[1] = gen_lowpart (SImode, operands[1]);
4233 /* Handle a partial overlap. */
4234 if (rtx_equal_p (operands[0], operands[3]))
4236 rtx tmp0 = operands[0];
4237 rtx tmp1 = operands[1];
4239 operands[0] = operands[2];
4240 operands[1] = operands[3];
4247 ;; We can't actually do base+index doubleword loads if the index and
4248 ;; destination overlap. Split here so that we at least have chance to
4251 [(set (match_operand:DI 0 "s_register_operand" "")
4252 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4253 (match_operand:SI 2 "s_register_operand" ""))))]
4255 && reg_overlap_mentioned_p (operands[0], operands[1])
4256 && reg_overlap_mentioned_p (operands[0], operands[2])"
4258 (plus:SI (match_dup 1)
4261 (mem:DI (match_dup 4)))]
4263 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4267 ;;; ??? This should have alternatives for constants.
4268 ;;; ??? This was originally identical to the movdf_insn pattern.
4269 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4270 ;;; thumb_reorg with a memory reference.
4271 (define_insn "*thumb_movdi_insn"
4272 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4273 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4275 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4276 && ( register_operand (operands[0], DImode)
4277 || register_operand (operands[1], DImode))"
4280 switch (which_alternative)
4284 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4285 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4286 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4288 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4290 operands[1] = GEN_INT (- INTVAL (operands[1]));
4291 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4293 return \"ldmia\\t%1, {%0, %H0}\";
4295 return \"stmia\\t%0, {%1, %H1}\";
4297 return thumb_load_double_from_address (operands);
4299 operands[2] = gen_rtx_MEM (SImode,
4300 plus_constant (XEXP (operands[0], 0), 4));
4301 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4304 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4305 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4306 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4309 [(set_attr "length" "4,4,6,2,2,6,4,4")
4310 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4311 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4314 (define_expand "movsi"
4315 [(set (match_operand:SI 0 "general_operand" "")
4316 (match_operand:SI 1 "general_operand" ""))]
4321 /* Everything except mem = const or mem = mem can be done easily. */
4322 if (GET_CODE (operands[0]) == MEM)
4323 operands[1] = force_reg (SImode, operands[1]);
4324 if (arm_general_register_operand (operands[0], SImode)
4325 && GET_CODE (operands[1]) == CONST_INT
4326 && !(const_ok_for_arm (INTVAL (operands[1]))
4327 || const_ok_for_arm (~INTVAL (operands[1]))))
4329 arm_split_constant (SET, SImode, NULL_RTX,
4330 INTVAL (operands[1]), operands[0], NULL_RTX,
4331 optimize && !no_new_pseudos);
4335 else /* TARGET_THUMB.... */
4337 if (!no_new_pseudos)
4339 if (GET_CODE (operands[0]) != REG)
4340 operands[1] = force_reg (SImode, operands[1]);
4345 && (CONSTANT_P (operands[1])
4346 || symbol_mentioned_p (operands[1])
4347 || label_mentioned_p (operands[1])))
4348 operands[1] = legitimize_pic_address (operands[1], SImode,
4349 (no_new_pseudos ? operands[0] : 0));
4353 (define_insn "*arm_movsi_insn"
4354 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4355 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4356 "TARGET_ARM && ! TARGET_IWMMXT
4357 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4358 && ( register_operand (operands[0], SImode)
4359 || register_operand (operands[1], SImode))"
4365 [(set_attr "type" "*,*,load1,store1")
4366 (set_attr "predicable" "yes")
4367 (set_attr "pool_range" "*,*,4096,*")
4368 (set_attr "neg_pool_range" "*,*,4084,*")]
4372 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4373 (match_operand:SI 1 "const_int_operand" ""))]
4375 && (!(const_ok_for_arm (INTVAL (operands[1]))
4376 || const_ok_for_arm (~INTVAL (operands[1]))))"
4377 [(clobber (const_int 0))]
4379 arm_split_constant (SET, SImode, NULL_RTX,
4380 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4385 (define_insn "*thumb_movsi_insn"
4386 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4387 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4389 && ( register_operand (operands[0], SImode)
4390 || register_operand (operands[1], SImode))"
4401 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4402 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4403 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4407 [(set (match_operand:SI 0 "register_operand" "")
4408 (match_operand:SI 1 "const_int_operand" ""))]
4409 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4410 [(set (match_dup 0) (match_dup 1))
4411 (set (match_dup 0) (neg:SI (match_dup 0)))]
4412 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4416 [(set (match_operand:SI 0 "register_operand" "")
4417 (match_operand:SI 1 "const_int_operand" ""))]
4418 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4419 [(set (match_dup 0) (match_dup 1))
4420 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4423 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4424 unsigned HOST_WIDE_INT mask = 0xff;
4427 for (i = 0; i < 25; i++)
4428 if ((val & (mask << i)) == val)
4431 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4435 operands[1] = GEN_INT (val >> i);
4436 operands[2] = GEN_INT (i);
4440 ;; When generating pic, we need to load the symbol offset into a register.
4441 ;; So that the optimizer does not confuse this with a normal symbol load
4442 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4443 ;; since that is the only type of relocation we can use.
4445 ;; The rather odd constraints on the following are to force reload to leave
4446 ;; the insn alone, and to force the minipool generation pass to then move
4447 ;; the GOT symbol to memory.
4449 (define_insn "pic_load_addr_arm"
4450 [(set (match_operand:SI 0 "s_register_operand" "=r")
4451 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4452 "TARGET_ARM && flag_pic"
4454 [(set_attr "type" "load1")
4455 (set (attr "pool_range") (const_int 4096))
4456 (set (attr "neg_pool_range") (const_int 4084))]
4459 (define_insn "pic_load_addr_thumb"
4460 [(set (match_operand:SI 0 "s_register_operand" "=l")
4461 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4462 "TARGET_THUMB && flag_pic"
4464 [(set_attr "type" "load1")
4465 (set (attr "pool_range") (const_int 1024))]
4468 ;; This variant is used for AOF assembly, since it needs to mention the
4469 ;; pic register in the rtl.
4470 (define_expand "pic_load_addr_based"
4471 [(set (match_operand:SI 0 "s_register_operand" "")
4472 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4473 "TARGET_ARM && flag_pic"
4474 "operands[2] = pic_offset_table_rtx;"
4477 (define_insn "*pic_load_addr_based_insn"
4478 [(set (match_operand:SI 0 "s_register_operand" "=r")
4479 (unspec:SI [(match_operand 1 "" "")
4480 (match_operand 2 "s_register_operand" "r")]
4482 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4484 #ifdef AOF_ASSEMBLER
4485 operands[1] = aof_pic_entry (operands[1]);
4487 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4490 [(set_attr "type" "load1")
4491 (set (attr "pool_range")
4492 (if_then_else (eq_attr "is_thumb" "yes")
4495 (set (attr "neg_pool_range")
4496 (if_then_else (eq_attr "is_thumb" "yes")
4501 (define_insn "pic_add_dot_plus_four"
4502 [(set (match_operand:SI 0 "register_operand" "+r")
4503 (unspec:SI [(plus:SI (match_dup 0)
4504 (const (plus:SI (pc) (const_int 4))))]
4506 (use (label_ref (match_operand 1 "" "")))]
4507 "TARGET_THUMB && flag_pic"
4509 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4510 CODE_LABEL_NUMBER (operands[1]));
4511 return \"add\\t%0, %|pc\";
4513 [(set_attr "length" "2")]
4516 (define_insn "pic_add_dot_plus_eight"
4517 [(set (match_operand:SI 0 "register_operand" "+r")
4518 (unspec:SI [(plus:SI (match_dup 0)
4519 (const (plus:SI (pc) (const_int 8))))]
4521 (use (label_ref (match_operand 1 "" "")))]
4522 "TARGET_ARM && flag_pic"
4524 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4525 CODE_LABEL_NUMBER (operands[1]));
4526 return \"add%?\\t%0, %|pc, %0\";
4528 [(set_attr "predicable" "yes")]
4531 (define_expand "builtin_setjmp_receiver"
4532 [(label_ref (match_operand 0 "" ""))]
4536 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4538 arm_load_pic_register (3);
4542 ;; If copying one reg to another we can set the condition codes according to
4543 ;; its value. Such a move is common after a return from subroutine and the
4544 ;; result is being tested against zero.
4546 (define_insn "*movsi_compare0"
4547 [(set (reg:CC CC_REGNUM)
4548 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4550 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4555 sub%?s\\t%0, %1, #0"
4556 [(set_attr "conds" "set")]
4559 ;; Subroutine to store a half word from a register into memory.
4560 ;; Operand 0 is the source register (HImode)
4561 ;; Operand 1 is the destination address in a register (SImode)
4563 ;; In both this routine and the next, we must be careful not to spill
4564 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4565 ;; can generate unrecognizable rtl.
4567 (define_expand "storehi"
4568 [;; store the low byte
4569 (set (match_operand 1 "" "") (match_dup 3))
4570 ;; extract the high byte
4572 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4573 ;; store the high byte
4574 (set (match_dup 4) (match_dup 5))]
4578 rtx op1 = operands[1];
4579 rtx addr = XEXP (op1, 0);
4580 enum rtx_code code = GET_CODE (addr);
4582 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4584 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4586 operands[4] = adjust_address (op1, QImode, 1);
4587 operands[1] = adjust_address (operands[1], QImode, 0);
4588 operands[3] = gen_lowpart (QImode, operands[0]);
4589 operands[0] = gen_lowpart (SImode, operands[0]);
4590 operands[2] = gen_reg_rtx (SImode);
4591 operands[5] = gen_lowpart (QImode, operands[2]);
4595 (define_expand "storehi_bigend"
4596 [(set (match_dup 4) (match_dup 3))
4598 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4599 (set (match_operand 1 "" "") (match_dup 5))]
4603 rtx op1 = operands[1];
4604 rtx addr = XEXP (op1, 0);
4605 enum rtx_code code = GET_CODE (addr);
4607 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4609 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4611 operands[4] = adjust_address (op1, QImode, 1);
4612 operands[1] = adjust_address (operands[1], QImode, 0);
4613 operands[3] = gen_lowpart (QImode, operands[0]);
4614 operands[0] = gen_lowpart (SImode, operands[0]);
4615 operands[2] = gen_reg_rtx (SImode);
4616 operands[5] = gen_lowpart (QImode, operands[2]);
4620 ;; Subroutine to store a half word integer constant into memory.
4621 (define_expand "storeinthi"
4622 [(set (match_operand 0 "" "")
4623 (match_operand 1 "" ""))
4624 (set (match_dup 3) (match_dup 2))]
4628 HOST_WIDE_INT value = INTVAL (operands[1]);
4629 rtx addr = XEXP (operands[0], 0);
4630 rtx op0 = operands[0];
4631 enum rtx_code code = GET_CODE (addr);
4633 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4635 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4637 operands[1] = gen_reg_rtx (SImode);
4638 if (BYTES_BIG_ENDIAN)
4640 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4641 if ((value & 255) == ((value >> 8) & 255))
4642 operands[2] = operands[1];
4645 operands[2] = gen_reg_rtx (SImode);
4646 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4651 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4652 if ((value & 255) == ((value >> 8) & 255))
4653 operands[2] = operands[1];
4656 operands[2] = gen_reg_rtx (SImode);
4657 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4661 operands[3] = adjust_address (op0, QImode, 1);
4662 operands[0] = adjust_address (operands[0], QImode, 0);
4663 operands[2] = gen_lowpart (QImode, operands[2]);
4664 operands[1] = gen_lowpart (QImode, operands[1]);
4668 (define_expand "storehi_single_op"
4669 [(set (match_operand:HI 0 "memory_operand" "")
4670 (match_operand:HI 1 "general_operand" ""))]
4671 "TARGET_ARM && arm_arch4"
4673 if (!s_register_operand (operands[1], HImode))
4674 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4678 (define_expand "movhi"
4679 [(set (match_operand:HI 0 "general_operand" "")
4680 (match_operand:HI 1 "general_operand" ""))]
4685 if (!no_new_pseudos)
4687 if (GET_CODE (operands[0]) == MEM)
4691 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4694 if (GET_CODE (operands[1]) == CONST_INT)
4695 emit_insn (gen_storeinthi (operands[0], operands[1]));
4698 if (GET_CODE (operands[1]) == MEM)
4699 operands[1] = force_reg (HImode, operands[1]);
4700 if (BYTES_BIG_ENDIAN)
4701 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4703 emit_insn (gen_storehi (operands[1], operands[0]));
4707 /* Sign extend a constant, and keep it in an SImode reg. */
4708 else if (GET_CODE (operands[1]) == CONST_INT)
4710 rtx reg = gen_reg_rtx (SImode);
4711 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4713 /* If the constant is already valid, leave it alone. */
4714 if (!const_ok_for_arm (val))
4716 /* If setting all the top bits will make the constant
4717 loadable in a single instruction, then set them.
4718 Otherwise, sign extend the number. */
4720 if (const_ok_for_arm (~(val | ~0xffff)))
4722 else if (val & 0x8000)
4726 emit_insn (gen_movsi (reg, GEN_INT (val)));
4727 operands[1] = gen_lowpart (HImode, reg);
4729 else if (arm_arch4 && optimize && !no_new_pseudos
4730 && GET_CODE (operands[1]) == MEM)
4732 rtx reg = gen_reg_rtx (SImode);
4734 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4735 operands[1] = gen_lowpart (HImode, reg);
4737 else if (!arm_arch4)
4739 if (GET_CODE (operands[1]) == MEM)
4742 rtx offset = const0_rtx;
4743 rtx reg = gen_reg_rtx (SImode);
4745 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4746 || (GET_CODE (base) == PLUS
4747 && (GET_CODE (offset = XEXP (base, 1))
4749 && ((INTVAL(offset) & 1) != 1)
4750 && GET_CODE (base = XEXP (base, 0)) == REG))
4751 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4753 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4756 new = gen_rtx_MEM (SImode,
4757 plus_constant (base, new_offset));
4758 MEM_COPY_ATTRIBUTES (new, operands[1]);
4759 emit_insn (gen_movsi (reg, new));
4760 if (((INTVAL (offset) & 2) != 0)
4761 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4763 rtx reg2 = gen_reg_rtx (SImode);
4765 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4770 emit_insn (gen_movhi_bytes (reg, operands[1]));
4772 operands[1] = gen_lowpart (HImode, reg);
4776 /* Handle loading a large integer during reload. */
4777 else if (GET_CODE (operands[1]) == CONST_INT
4778 && !const_ok_for_arm (INTVAL (operands[1]))
4779 && !const_ok_for_arm (~INTVAL (operands[1])))
4781 /* Writing a constant to memory needs a scratch, which should
4782 be handled with SECONDARY_RELOADs. */
4783 gcc_assert (GET_CODE (operands[0]) == REG);
4785 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4786 emit_insn (gen_movsi (operands[0], operands[1]));
4790 else /* TARGET_THUMB */
4792 if (!no_new_pseudos)
4794 if (GET_CODE (operands[0]) != REG)
4795 operands[1] = force_reg (HImode, operands[1]);
4797 /* ??? We shouldn't really get invalid addresses here, but this can
4798 happen if we are passed a SP (never OK for HImode/QImode) or
4799 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4800 HImode/QImode) relative address. */
4801 /* ??? This should perhaps be fixed elsewhere, for instance, in
4802 fixup_stack_1, by checking for other kinds of invalid addresses,
4803 e.g. a bare reference to a virtual register. This may confuse the
4804 alpha though, which must handle this case differently. */
4805 if (GET_CODE (operands[0]) == MEM
4806 && !memory_address_p (GET_MODE (operands[0]),
4807 XEXP (operands[0], 0)))
4809 = replace_equiv_address (operands[0],
4810 copy_to_reg (XEXP (operands[0], 0)));
4812 if (GET_CODE (operands[1]) == MEM
4813 && !memory_address_p (GET_MODE (operands[1]),
4814 XEXP (operands[1], 0)))
4816 = replace_equiv_address (operands[1],
4817 copy_to_reg (XEXP (operands[1], 0)));
4819 /* Handle loading a large integer during reload. */
4820 else if (GET_CODE (operands[1]) == CONST_INT
4821 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4823 /* Writing a constant to memory needs a scratch, which should
4824 be handled with SECONDARY_RELOADs. */
4825 gcc_assert (GET_CODE (operands[0]) == REG);
4827 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4828 emit_insn (gen_movsi (operands[0], operands[1]));
4835 (define_insn "*thumb_movhi_insn"
4836 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4837 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4839 && ( register_operand (operands[0], HImode)
4840 || register_operand (operands[1], HImode))"
4842 switch (which_alternative)
4844 case 0: return \"add %0, %1, #0\";
4845 case 2: return \"strh %1, %0\";
4846 case 3: return \"mov %0, %1\";
4847 case 4: return \"mov %0, %1\";
4848 case 5: return \"mov %0, %1\";
4849 default: gcc_unreachable ();
4851 /* The stack pointer can end up being taken as an index register.
4852 Catch this case here and deal with it. */
4853 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4854 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4855 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4858 ops[0] = operands[0];
4859 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4861 output_asm_insn (\"mov %0, %1\", ops);
4863 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4866 return \"ldrh %0, %1\";
4868 [(set_attr "length" "2,4,2,2,2,2")
4869 (set_attr "type" "*,load1,store1,*,*,*")]
4873 (define_expand "movhi_bytes"
4874 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4876 (zero_extend:SI (match_dup 6)))
4877 (set (match_operand:SI 0 "" "")
4878 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4883 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4885 mem1 = gen_rtx_MEM (QImode, addr);
4886 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4887 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4888 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4889 operands[0] = gen_lowpart (SImode, operands[0]);
4891 operands[2] = gen_reg_rtx (SImode);
4892 operands[3] = gen_reg_rtx (SImode);
4895 if (BYTES_BIG_ENDIAN)
4897 operands[4] = operands[2];
4898 operands[5] = operands[3];
4902 operands[4] = operands[3];
4903 operands[5] = operands[2];
4908 (define_expand "movhi_bigend"
4910 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4913 (ashiftrt:SI (match_dup 2) (const_int 16)))
4914 (set (match_operand:HI 0 "s_register_operand" "")
4918 operands[2] = gen_reg_rtx (SImode);
4919 operands[3] = gen_reg_rtx (SImode);
4920 operands[4] = gen_lowpart (HImode, operands[3]);
4924 ;; Pattern to recognize insn generated default case above
4925 (define_insn "*movhi_insn_arch4"
4926 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4927 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4930 && (GET_CODE (operands[1]) != CONST_INT
4931 || const_ok_for_arm (INTVAL (operands[1]))
4932 || const_ok_for_arm (~INTVAL (operands[1])))"
4934 mov%?\\t%0, %1\\t%@ movhi
4935 mvn%?\\t%0, #%B1\\t%@ movhi
4936 str%?h\\t%1, %0\\t%@ movhi
4937 ldr%?h\\t%0, %1\\t%@ movhi"
4938 [(set_attr "type" "*,*,store1,load1")
4939 (set_attr "predicable" "yes")
4940 (set_attr "pool_range" "*,*,*,256")
4941 (set_attr "neg_pool_range" "*,*,*,244")]
4944 (define_insn "*movhi_bytes"
4945 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4946 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4949 mov%?\\t%0, %1\\t%@ movhi
4950 mvn%?\\t%0, #%B1\\t%@ movhi"
4951 [(set_attr "predicable" "yes")]
4954 (define_insn "thumb_movhi_clobber"
4955 [(set (match_operand:HI 0 "memory_operand" "=m")
4956 (match_operand:HI 1 "register_operand" "l"))
4957 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4960 gcc_unreachable ();"
4963 ;; We use a DImode scratch because we may occasionally need an additional
4964 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4965 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4966 (define_expand "reload_outhi"
4967 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4968 (match_operand:HI 1 "s_register_operand" "r")
4969 (match_operand:DI 2 "s_register_operand" "=&l")])]
4972 arm_reload_out_hi (operands);
4974 thumb_reload_out_hi (operands);
4979 (define_expand "reload_inhi"
4980 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4981 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4982 (match_operand:DI 2 "s_register_operand" "=&r")])]
4986 arm_reload_in_hi (operands);
4988 thumb_reload_out_hi (operands);
4992 (define_expand "movqi"
4993 [(set (match_operand:QI 0 "general_operand" "")
4994 (match_operand:QI 1 "general_operand" ""))]
4999 /* Everything except mem = const or mem = mem can be done easily */
5001 if (!no_new_pseudos)
5003 if (GET_CODE (operands[1]) == CONST_INT)
5005 rtx reg = gen_reg_rtx (SImode);
5007 emit_insn (gen_movsi (reg, operands[1]));
5008 operands[1] = gen_lowpart (QImode, reg);
5010 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5012 rtx reg = gen_reg_rtx (SImode);
5014 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5015 operands[1] = gen_lowpart (QImode, reg);
5017 if (GET_CODE (operands[0]) == MEM)
5018 operands[1] = force_reg (QImode, operands[1]);
5021 else /* TARGET_THUMB */
5023 if (!no_new_pseudos)
5025 if (GET_CODE (operands[0]) != REG)
5026 operands[1] = force_reg (QImode, operands[1]);
5028 /* ??? We shouldn't really get invalid addresses here, but this can
5029 happen if we are passed a SP (never OK for HImode/QImode) or
5030 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5031 HImode/QImode) relative address. */
5032 /* ??? This should perhaps be fixed elsewhere, for instance, in
5033 fixup_stack_1, by checking for other kinds of invalid addresses,
5034 e.g. a bare reference to a virtual register. This may confuse the
5035 alpha though, which must handle this case differently. */
5036 if (GET_CODE (operands[0]) == MEM
5037 && !memory_address_p (GET_MODE (operands[0]),
5038 XEXP (operands[0], 0)))
5040 = replace_equiv_address (operands[0],
5041 copy_to_reg (XEXP (operands[0], 0)));
5042 if (GET_CODE (operands[1]) == MEM
5043 && !memory_address_p (GET_MODE (operands[1]),
5044 XEXP (operands[1], 0)))
5046 = replace_equiv_address (operands[1],
5047 copy_to_reg (XEXP (operands[1], 0)));
5049 /* Handle loading a large integer during reload. */
5050 else if (GET_CODE (operands[1]) == CONST_INT
5051 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5053 /* Writing a constant to memory needs a scratch, which should
5054 be handled with SECONDARY_RELOADs. */
5055 gcc_assert (GET_CODE (operands[0]) == REG);
5057 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5058 emit_insn (gen_movsi (operands[0], operands[1]));
5066 (define_insn "*arm_movqi_insn"
5067 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5068 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5070 && ( register_operand (operands[0], QImode)
5071 || register_operand (operands[1], QImode))"
5077 [(set_attr "type" "*,*,load1,store1")
5078 (set_attr "predicable" "yes")]
5081 (define_insn "*thumb_movqi_insn"
5082 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5083 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5085 && ( register_operand (operands[0], QImode)
5086 || register_operand (operands[1], QImode))"
5094 [(set_attr "length" "2")
5095 (set_attr "type" "*,load1,store1,*,*,*")
5096 (set_attr "pool_range" "*,32,*,*,*,*")]
5099 (define_expand "movsf"
5100 [(set (match_operand:SF 0 "general_operand" "")
5101 (match_operand:SF 1 "general_operand" ""))]
5106 if (GET_CODE (operands[0]) == MEM)
5107 operands[1] = force_reg (SFmode, operands[1]);
5109 else /* TARGET_THUMB */
5111 if (!no_new_pseudos)
5113 if (GET_CODE (operands[0]) != REG)
5114 operands[1] = force_reg (SFmode, operands[1]);
5121 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5122 (match_operand:SF 1 "immediate_operand" ""))]
5124 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5126 && GET_CODE (operands[1]) == CONST_DOUBLE"
5127 [(set (match_dup 2) (match_dup 3))]
5129 operands[2] = gen_lowpart (SImode, operands[0]);
5130 operands[3] = gen_lowpart (SImode, operands[1]);
5131 if (operands[2] == 0 || operands[3] == 0)
5136 (define_insn "*arm_movsf_soft_insn"
5137 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5138 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5140 && TARGET_SOFT_FLOAT
5141 && (GET_CODE (operands[0]) != MEM
5142 || register_operand (operands[1], SFmode))"
5145 ldr%?\\t%0, %1\\t%@ float
5146 str%?\\t%1, %0\\t%@ float"
5147 [(set_attr "length" "4,4,4")
5148 (set_attr "predicable" "yes")
5149 (set_attr "type" "*,load1,store1")
5150 (set_attr "pool_range" "*,4096,*")
5151 (set_attr "neg_pool_range" "*,4084,*")]
5154 ;;; ??? This should have alternatives for constants.
5155 (define_insn "*thumb_movsf_insn"
5156 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5157 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5159 && ( register_operand (operands[0], SFmode)
5160 || register_operand (operands[1], SFmode))"
5169 [(set_attr "length" "2")
5170 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5171 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5174 (define_expand "movdf"
5175 [(set (match_operand:DF 0 "general_operand" "")
5176 (match_operand:DF 1 "general_operand" ""))]
5181 if (GET_CODE (operands[0]) == MEM)
5182 operands[1] = force_reg (DFmode, operands[1]);
5184 else /* TARGET_THUMB */
5186 if (!no_new_pseudos)
5188 if (GET_CODE (operands[0]) != REG)
5189 operands[1] = force_reg (DFmode, operands[1]);
5195 ;; Reloading a df mode value stored in integer regs to memory can require a
5197 (define_expand "reload_outdf"
5198 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5199 (match_operand:DF 1 "s_register_operand" "r")
5200 (match_operand:SI 2 "s_register_operand" "=&r")]
5204 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5207 operands[2] = XEXP (operands[0], 0);
5208 else if (code == POST_INC || code == PRE_DEC)
5210 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5211 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5212 emit_insn (gen_movdi (operands[0], operands[1]));
5215 else if (code == PRE_INC)
5217 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5219 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5222 else if (code == POST_DEC)
5223 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5225 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5226 XEXP (XEXP (operands[0], 0), 1)));
5228 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5231 if (code == POST_DEC)
5232 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5238 (define_insn "*movdf_soft_insn"
5239 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5240 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5241 "TARGET_ARM && TARGET_SOFT_FLOAT
5244 switch (which_alternative)
5251 return output_move_double (operands);
5254 [(set_attr "length" "8,12,16,8,8")
5255 (set_attr "type" "*,*,*,load2,store2")
5256 (set_attr "pool_range" "1020")
5257 (set_attr "neg_pool_range" "1008")]
5260 ;;; ??? This should have alternatives for constants.
5261 ;;; ??? This was originally identical to the movdi_insn pattern.
5262 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5263 ;;; thumb_reorg with a memory reference.
5264 (define_insn "*thumb_movdf_insn"
5265 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5266 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5268 && ( register_operand (operands[0], DFmode)
5269 || register_operand (operands[1], DFmode))"
5271 switch (which_alternative)
5275 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5276 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5277 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5279 return \"ldmia\\t%1, {%0, %H0}\";
5281 return \"stmia\\t%0, {%1, %H1}\";
5283 return thumb_load_double_from_address (operands);
5285 operands[2] = gen_rtx_MEM (SImode,
5286 plus_constant (XEXP (operands[0], 0), 4));
5287 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5290 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5291 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5292 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5295 [(set_attr "length" "4,2,2,6,4,4")
5296 (set_attr "type" "*,load2,store2,load2,store2,*")
5297 (set_attr "pool_range" "*,*,*,1020,*,*")]
5300 (define_expand "movxf"
5301 [(set (match_operand:XF 0 "general_operand" "")
5302 (match_operand:XF 1 "general_operand" ""))]
5303 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5305 if (GET_CODE (operands[0]) == MEM)
5306 operands[1] = force_reg (XFmode, operands[1]);
5311 (define_expand "movv2si"
5312 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5313 (match_operand:V2SI 1 "general_operand" ""))]
5314 "TARGET_REALLY_IWMMXT"
5318 (define_expand "movv4hi"
5319 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5320 (match_operand:V4HI 1 "general_operand" ""))]
5321 "TARGET_REALLY_IWMMXT"
5325 (define_expand "movv8qi"
5326 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5327 (match_operand:V8QI 1 "general_operand" ""))]
5328 "TARGET_REALLY_IWMMXT"
5333 ;; load- and store-multiple insns
5334 ;; The arm can load/store any set of registers, provided that they are in
5335 ;; ascending order; but that is beyond GCC so stick with what it knows.
5337 (define_expand "load_multiple"
5338 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5339 (match_operand:SI 1 "" ""))
5340 (use (match_operand:SI 2 "" ""))])]
5343 HOST_WIDE_INT offset = 0;
5345 /* Support only fixed point registers. */
5346 if (GET_CODE (operands[2]) != CONST_INT
5347 || INTVAL (operands[2]) > 14
5348 || INTVAL (operands[2]) < 2
5349 || GET_CODE (operands[1]) != MEM
5350 || GET_CODE (operands[0]) != REG
5351 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5352 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5356 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5357 force_reg (SImode, XEXP (operands[1], 0)),
5358 TRUE, FALSE, operands[1], &offset);
5361 ;; Load multiple with write-back
5363 (define_insn "*ldmsi_postinc4"
5364 [(match_parallel 0 "load_multiple_operation"
5365 [(set (match_operand:SI 1 "s_register_operand" "=r")
5366 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5368 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5369 (mem:SI (match_dup 2)))
5370 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5371 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5372 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5373 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5374 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5375 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5376 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5377 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5378 [(set_attr "type" "load4")
5379 (set_attr "predicable" "yes")]
5382 (define_insn "*ldmsi_postinc4_thumb"
5383 [(match_parallel 0 "load_multiple_operation"
5384 [(set (match_operand:SI 1 "s_register_operand" "=l")
5385 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388 (mem:SI (match_dup 2)))
5389 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5390 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5391 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5392 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5393 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5394 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5395 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5396 "ldmia\\t%1!, {%3, %4, %5, %6}"
5397 [(set_attr "type" "load4")]
5400 (define_insn "*ldmsi_postinc3"
5401 [(match_parallel 0 "load_multiple_operation"
5402 [(set (match_operand:SI 1 "s_register_operand" "=r")
5403 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5405 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5406 (mem:SI (match_dup 2)))
5407 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5408 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5409 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5410 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5411 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5412 "ldm%?ia\\t%1!, {%3, %4, %5}"
5413 [(set_attr "type" "load3")
5414 (set_attr "predicable" "yes")]
5417 (define_insn "*ldmsi_postinc2"
5418 [(match_parallel 0 "load_multiple_operation"
5419 [(set (match_operand:SI 1 "s_register_operand" "=r")
5420 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5422 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5423 (mem:SI (match_dup 2)))
5424 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5425 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5426 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5427 "ldm%?ia\\t%1!, {%3, %4}"
5428 [(set_attr "type" "load2")
5429 (set_attr "predicable" "yes")]
5432 ;; Ordinary load multiple
5434 (define_insn "*ldmsi4"
5435 [(match_parallel 0 "load_multiple_operation"
5436 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5437 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5438 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5440 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5442 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5444 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5446 [(set_attr "type" "load4")
5447 (set_attr "predicable" "yes")]
5450 (define_insn "*ldmsi3"
5451 [(match_parallel 0 "load_multiple_operation"
5452 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5453 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5454 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5455 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5456 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5457 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5458 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5459 "ldm%?ia\\t%1, {%2, %3, %4}"
5460 [(set_attr "type" "load3")
5461 (set_attr "predicable" "yes")]
5464 (define_insn "*ldmsi2"
5465 [(match_parallel 0 "load_multiple_operation"
5466 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5467 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5468 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5469 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5470 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5471 "ldm%?ia\\t%1, {%2, %3}"
5472 [(set_attr "type" "load2")
5473 (set_attr "predicable" "yes")]
5476 (define_expand "store_multiple"
5477 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5478 (match_operand:SI 1 "" ""))
5479 (use (match_operand:SI 2 "" ""))])]
5482 HOST_WIDE_INT offset = 0;
5484 /* Support only fixed point registers. */
5485 if (GET_CODE (operands[2]) != CONST_INT
5486 || INTVAL (operands[2]) > 14
5487 || INTVAL (operands[2]) < 2
5488 || GET_CODE (operands[1]) != REG
5489 || GET_CODE (operands[0]) != MEM
5490 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5491 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5495 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5496 force_reg (SImode, XEXP (operands[0], 0)),
5497 TRUE, FALSE, operands[0], &offset);
5500 ;; Store multiple with write-back
5502 (define_insn "*stmsi_postinc4"
5503 [(match_parallel 0 "store_multiple_operation"
5504 [(set (match_operand:SI 1 "s_register_operand" "=r")
5505 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5507 (set (mem:SI (match_dup 2))
5508 (match_operand:SI 3 "arm_hard_register_operand" ""))
5509 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5510 (match_operand:SI 4 "arm_hard_register_operand" ""))
5511 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5512 (match_operand:SI 5 "arm_hard_register_operand" ""))
5513 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5514 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5515 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5516 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5517 [(set_attr "predicable" "yes")
5518 (set_attr "type" "store4")]
5521 (define_insn "*stmsi_postinc4_thumb"
5522 [(match_parallel 0 "store_multiple_operation"
5523 [(set (match_operand:SI 1 "s_register_operand" "=l")
5524 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5526 (set (mem:SI (match_dup 2))
5527 (match_operand:SI 3 "arm_hard_register_operand" ""))
5528 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5529 (match_operand:SI 4 "arm_hard_register_operand" ""))
5530 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5531 (match_operand:SI 5 "arm_hard_register_operand" ""))
5532 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5533 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5534 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5535 "stmia\\t%1!, {%3, %4, %5, %6}"
5536 [(set_attr "type" "store4")]
5539 (define_insn "*stmsi_postinc3"
5540 [(match_parallel 0 "store_multiple_operation"
5541 [(set (match_operand:SI 1 "s_register_operand" "=r")
5542 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5544 (set (mem:SI (match_dup 2))
5545 (match_operand:SI 3 "arm_hard_register_operand" ""))
5546 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5547 (match_operand:SI 4 "arm_hard_register_operand" ""))
5548 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5549 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5550 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5551 "stm%?ia\\t%1!, {%3, %4, %5}"
5552 [(set_attr "predicable" "yes")
5553 (set_attr "type" "store3")]
5556 (define_insn "*stmsi_postinc2"
5557 [(match_parallel 0 "store_multiple_operation"
5558 [(set (match_operand:SI 1 "s_register_operand" "=r")
5559 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5561 (set (mem:SI (match_dup 2))
5562 (match_operand:SI 3 "arm_hard_register_operand" ""))
5563 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5564 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5565 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5566 "stm%?ia\\t%1!, {%3, %4}"
5567 [(set_attr "predicable" "yes")
5568 (set_attr "type" "store2")]
5571 ;; Ordinary store multiple
5573 (define_insn "*stmsi4"
5574 [(match_parallel 0 "store_multiple_operation"
5575 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5576 (match_operand:SI 2 "arm_hard_register_operand" ""))
5577 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5578 (match_operand:SI 3 "arm_hard_register_operand" ""))
5579 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5580 (match_operand:SI 4 "arm_hard_register_operand" ""))
5581 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5582 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5585 [(set_attr "predicable" "yes")
5586 (set_attr "type" "store4")]
5589 (define_insn "*stmsi3"
5590 [(match_parallel 0 "store_multiple_operation"
5591 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5592 (match_operand:SI 2 "arm_hard_register_operand" ""))
5593 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5594 (match_operand:SI 3 "arm_hard_register_operand" ""))
5595 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5596 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5597 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5598 "stm%?ia\\t%1, {%2, %3, %4}"
5599 [(set_attr "predicable" "yes")
5600 (set_attr "type" "store3")]
5603 (define_insn "*stmsi2"
5604 [(match_parallel 0 "store_multiple_operation"
5605 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5606 (match_operand:SI 2 "arm_hard_register_operand" ""))
5607 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5608 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5609 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5610 "stm%?ia\\t%1, {%2, %3}"
5611 [(set_attr "predicable" "yes")
5612 (set_attr "type" "store2")]
5615 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5616 ;; We could let this apply for blocks of less than this, but it clobbers so
5617 ;; many registers that there is then probably a better way.
5619 (define_expand "movmemqi"
5620 [(match_operand:BLK 0 "general_operand" "")
5621 (match_operand:BLK 1 "general_operand" "")
5622 (match_operand:SI 2 "const_int_operand" "")
5623 (match_operand:SI 3 "const_int_operand" "")]
5628 if (arm_gen_movmemqi (operands))
5632 else /* TARGET_THUMB */
5634 if ( INTVAL (operands[3]) != 4
5635 || INTVAL (operands[2]) > 48)
5638 thumb_expand_movmemqi (operands);
5644 ;; Thumb block-move insns
5646 (define_insn "movmem12b"
5647 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5648 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5649 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5650 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5651 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5652 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5653 (set (match_operand:SI 0 "register_operand" "=l")
5654 (plus:SI (match_dup 2) (const_int 12)))
5655 (set (match_operand:SI 1 "register_operand" "=l")
5656 (plus:SI (match_dup 3) (const_int 12)))
5657 (clobber (match_scratch:SI 4 "=&l"))
5658 (clobber (match_scratch:SI 5 "=&l"))
5659 (clobber (match_scratch:SI 6 "=&l"))]
5661 "* return thumb_output_move_mem_multiple (3, operands);"
5662 [(set_attr "length" "4")
5663 ; This isn't entirely accurate... It loads as well, but in terms of
5664 ; scheduling the following insn it is better to consider it as a store
5665 (set_attr "type" "store3")]
5668 (define_insn "movmem8b"
5669 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5670 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5671 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5672 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5673 (set (match_operand:SI 0 "register_operand" "=l")
5674 (plus:SI (match_dup 2) (const_int 8)))
5675 (set (match_operand:SI 1 "register_operand" "=l")
5676 (plus:SI (match_dup 3) (const_int 8)))
5677 (clobber (match_scratch:SI 4 "=&l"))
5678 (clobber (match_scratch:SI 5 "=&l"))]
5680 "* return thumb_output_move_mem_multiple (2, operands);"
5681 [(set_attr "length" "4")
5682 ; This isn't entirely accurate... It loads as well, but in terms of
5683 ; scheduling the following insn it is better to consider it as a store
5684 (set_attr "type" "store2")]
5689 ;; Compare & branch insns
5690 ;; The range calculations are based as follows:
5691 ;; For forward branches, the address calculation returns the address of
5692 ;; the next instruction. This is 2 beyond the branch instruction.
5693 ;; For backward branches, the address calculation returns the address of
5694 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5695 ;; instruction for the shortest sequence, and 4 before the branch instruction
5696 ;; if we have to jump around an unconditional branch.
5697 ;; To the basic branch range the PC offset must be added (this is +4).
5698 ;; So for forward branches we have
5699 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5700 ;; And for backward branches we have
5701 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5703 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5704 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5706 (define_expand "cbranchsi4"
5707 [(set (pc) (if_then_else
5708 (match_operator 0 "arm_comparison_operator"
5709 [(match_operand:SI 1 "s_register_operand" "")
5710 (match_operand:SI 2 "nonmemory_operand" "")])
5711 (label_ref (match_operand 3 "" ""))
5715 if (thumb_cmpneg_operand (operands[2], SImode))
5717 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5718 operands[3], operands[0]));
5721 if (!thumb_cmp_operand (operands[2], SImode))
5722 operands[2] = force_reg (SImode, operands[2]);
5725 (define_insn "*cbranchsi4_insn"
5726 [(set (pc) (if_then_else
5727 (match_operator 0 "arm_comparison_operator"
5728 [(match_operand:SI 1 "s_register_operand" "l,*h")
5729 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5730 (label_ref (match_operand 3 "" ""))
5734 output_asm_insn (\"cmp\\t%1, %2\", operands);
5736 switch (get_attr_length (insn))
5738 case 4: return \"b%d0\\t%l3\";
5739 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5740 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5743 [(set (attr "far_jump")
5745 (eq_attr "length" "8")
5746 (const_string "yes")
5747 (const_string "no")))
5748 (set (attr "length")
5750 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5751 (le (minus (match_dup 3) (pc)) (const_int 256)))
5754 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5755 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5760 (define_insn "cbranchsi4_scratch"
5761 [(set (pc) (if_then_else
5762 (match_operator 4 "arm_comparison_operator"
5763 [(match_operand:SI 1 "s_register_operand" "l,0")
5764 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5765 (label_ref (match_operand 3 "" ""))
5767 (clobber (match_scratch:SI 0 "=l,l"))]
5770 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5772 switch (get_attr_length (insn))
5774 case 4: return \"b%d4\\t%l3\";
5775 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5776 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5779 [(set (attr "far_jump")
5781 (eq_attr "length" "8")
5782 (const_string "yes")
5783 (const_string "no")))
5784 (set (attr "length")
5786 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5787 (le (minus (match_dup 3) (pc)) (const_int 256)))
5790 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5791 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5795 (define_insn "*movsi_cbranchsi4"
5798 (match_operator 3 "arm_comparison_operator"
5799 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5801 (label_ref (match_operand 2 "" ""))
5803 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5807 if (which_alternative == 0)
5808 output_asm_insn (\"cmp\t%0, #0\", operands);
5809 else if (which_alternative == 1)
5810 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5813 output_asm_insn (\"cmp\t%1, #0\", operands);
5814 if (which_alternative == 2)
5815 output_asm_insn (\"mov\t%0, %1\", operands);
5817 output_asm_insn (\"str\t%1, %0\", operands);
5819 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5821 case 4: return \"b%d3\\t%l2\";
5822 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5823 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5826 [(set (attr "far_jump")
5828 (ior (and (gt (symbol_ref ("which_alternative"))
5830 (eq_attr "length" "8"))
5831 (eq_attr "length" "10"))
5832 (const_string "yes")
5833 (const_string "no")))
5834 (set (attr "length")
5836 (le (symbol_ref ("which_alternative"))
5839 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5840 (le (minus (match_dup 2) (pc)) (const_int 256)))
5843 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5844 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5848 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5849 (le (minus (match_dup 2) (pc)) (const_int 256)))
5852 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5853 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5858 (define_insn "*negated_cbranchsi4"
5861 (match_operator 0 "equality_operator"
5862 [(match_operand:SI 1 "s_register_operand" "l")
5863 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5864 (label_ref (match_operand 3 "" ""))
5868 output_asm_insn (\"cmn\\t%1, %2\", operands);
5869 switch (get_attr_length (insn))
5871 case 4: return \"b%d0\\t%l3\";
5872 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5873 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5876 [(set (attr "far_jump")
5878 (eq_attr "length" "8")
5879 (const_string "yes")
5880 (const_string "no")))
5881 (set (attr "length")
5883 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5884 (le (minus (match_dup 3) (pc)) (const_int 256)))
5887 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5888 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5893 (define_insn "*tbit_cbranch"
5896 (match_operator 0 "equality_operator"
5897 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5899 (match_operand:SI 2 "const_int_operand" "i"))
5901 (label_ref (match_operand 3 "" ""))
5903 (clobber (match_scratch:SI 4 "=l"))]
5908 op[0] = operands[4];
5909 op[1] = operands[1];
5910 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5912 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5913 switch (get_attr_length (insn))
5915 case 4: return \"b%d0\\t%l3\";
5916 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5917 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5920 [(set (attr "far_jump")
5922 (eq_attr "length" "8")
5923 (const_string "yes")
5924 (const_string "no")))
5925 (set (attr "length")
5927 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5928 (le (minus (match_dup 3) (pc)) (const_int 256)))
5931 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5932 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5937 (define_insn "*tstsi3_cbranch"
5940 (match_operator 3 "equality_operator"
5941 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5942 (match_operand:SI 1 "s_register_operand" "l"))
5944 (label_ref (match_operand 2 "" ""))
5949 output_asm_insn (\"tst\\t%0, %1\", operands);
5950 switch (get_attr_length (insn))
5952 case 4: return \"b%d3\\t%l2\";
5953 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5954 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5957 [(set (attr "far_jump")
5959 (eq_attr "length" "8")
5960 (const_string "yes")
5961 (const_string "no")))
5962 (set (attr "length")
5964 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5965 (le (minus (match_dup 2) (pc)) (const_int 256)))
5968 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5969 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5974 (define_insn "*andsi3_cbranch"
5977 (match_operator 5 "equality_operator"
5978 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5979 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5981 (label_ref (match_operand 4 "" ""))
5983 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5984 (and:SI (match_dup 2) (match_dup 3)))
5985 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5989 if (which_alternative == 0)
5990 output_asm_insn (\"and\\t%0, %3\", operands);
5991 else if (which_alternative == 1)
5993 output_asm_insn (\"and\\t%1, %3\", operands);
5994 output_asm_insn (\"mov\\t%0, %1\", operands);
5998 output_asm_insn (\"and\\t%1, %3\", operands);
5999 output_asm_insn (\"str\\t%1, %0\", operands);
6002 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6004 case 4: return \"b%d5\\t%l4\";
6005 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6006 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6009 [(set (attr "far_jump")
6011 (ior (and (eq (symbol_ref ("which_alternative"))
6013 (eq_attr "length" "8"))
6014 (eq_attr "length" "10"))
6015 (const_string "yes")
6016 (const_string "no")))
6017 (set (attr "length")
6019 (eq (symbol_ref ("which_alternative"))
6022 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6023 (le (minus (match_dup 4) (pc)) (const_int 256)))
6026 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6027 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6031 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6032 (le (minus (match_dup 4) (pc)) (const_int 256)))
6035 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6036 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6041 (define_insn "*orrsi3_cbranch_scratch"
6044 (match_operator 4 "equality_operator"
6045 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6046 (match_operand:SI 2 "s_register_operand" "l"))
6048 (label_ref (match_operand 3 "" ""))
6050 (clobber (match_scratch:SI 0 "=l"))]
6054 output_asm_insn (\"orr\\t%0, %2\", operands);
6055 switch (get_attr_length (insn))
6057 case 4: return \"b%d4\\t%l3\";
6058 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6059 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6062 [(set (attr "far_jump")
6064 (eq_attr "length" "8")
6065 (const_string "yes")
6066 (const_string "no")))
6067 (set (attr "length")
6069 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6070 (le (minus (match_dup 3) (pc)) (const_int 256)))
6073 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6074 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6079 (define_insn "*orrsi3_cbranch"
6082 (match_operator 5 "equality_operator"
6083 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6084 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6086 (label_ref (match_operand 4 "" ""))
6088 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6089 (ior:SI (match_dup 2) (match_dup 3)))
6090 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6094 if (which_alternative == 0)
6095 output_asm_insn (\"orr\\t%0, %3\", operands);
6096 else if (which_alternative == 1)
6098 output_asm_insn (\"orr\\t%1, %3\", operands);
6099 output_asm_insn (\"mov\\t%0, %1\", operands);
6103 output_asm_insn (\"orr\\t%1, %3\", operands);
6104 output_asm_insn (\"str\\t%1, %0\", operands);
6107 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6109 case 4: return \"b%d5\\t%l4\";
6110 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6111 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6114 [(set (attr "far_jump")
6116 (ior (and (eq (symbol_ref ("which_alternative"))
6118 (eq_attr "length" "8"))
6119 (eq_attr "length" "10"))
6120 (const_string "yes")
6121 (const_string "no")))
6122 (set (attr "length")
6124 (eq (symbol_ref ("which_alternative"))
6127 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6128 (le (minus (match_dup 4) (pc)) (const_int 256)))
6131 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6132 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6136 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6137 (le (minus (match_dup 4) (pc)) (const_int 256)))
6140 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6141 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6146 (define_insn "*xorsi3_cbranch_scratch"
6149 (match_operator 4 "equality_operator"
6150 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6151 (match_operand:SI 2 "s_register_operand" "l"))
6153 (label_ref (match_operand 3 "" ""))
6155 (clobber (match_scratch:SI 0 "=l"))]
6159 output_asm_insn (\"eor\\t%0, %2\", operands);
6160 switch (get_attr_length (insn))
6162 case 4: return \"b%d4\\t%l3\";
6163 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6164 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6167 [(set (attr "far_jump")
6169 (eq_attr "length" "8")
6170 (const_string "yes")
6171 (const_string "no")))
6172 (set (attr "length")
6174 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6175 (le (minus (match_dup 3) (pc)) (const_int 256)))
6178 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6179 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6184 (define_insn "*xorsi3_cbranch"
6187 (match_operator 5 "equality_operator"
6188 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6189 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6191 (label_ref (match_operand 4 "" ""))
6193 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6194 (xor:SI (match_dup 2) (match_dup 3)))
6195 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6199 if (which_alternative == 0)
6200 output_asm_insn (\"eor\\t%0, %3\", operands);
6201 else if (which_alternative == 1)
6203 output_asm_insn (\"eor\\t%1, %3\", operands);
6204 output_asm_insn (\"mov\\t%0, %1\", operands);
6208 output_asm_insn (\"eor\\t%1, %3\", operands);
6209 output_asm_insn (\"str\\t%1, %0\", operands);
6212 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6214 case 4: return \"b%d5\\t%l4\";
6215 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6216 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6219 [(set (attr "far_jump")
6221 (ior (and (eq (symbol_ref ("which_alternative"))
6223 (eq_attr "length" "8"))
6224 (eq_attr "length" "10"))
6225 (const_string "yes")
6226 (const_string "no")))
6227 (set (attr "length")
6229 (eq (symbol_ref ("which_alternative"))
6232 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6233 (le (minus (match_dup 4) (pc)) (const_int 256)))
6236 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6237 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6241 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6242 (le (minus (match_dup 4) (pc)) (const_int 256)))
6245 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6246 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6251 (define_insn "*bicsi3_cbranch_scratch"
6254 (match_operator 4 "equality_operator"
6255 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6256 (match_operand:SI 1 "s_register_operand" "0"))
6258 (label_ref (match_operand 3 "" ""))
6260 (clobber (match_scratch:SI 0 "=l"))]
6264 output_asm_insn (\"bic\\t%0, %2\", operands);
6265 switch (get_attr_length (insn))
6267 case 4: return \"b%d4\\t%l3\";
6268 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6269 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6272 [(set (attr "far_jump")
6274 (eq_attr "length" "8")
6275 (const_string "yes")
6276 (const_string "no")))
6277 (set (attr "length")
6279 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6280 (le (minus (match_dup 3) (pc)) (const_int 256)))
6283 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6284 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6289 (define_insn "*bicsi3_cbranch"
6292 (match_operator 5 "equality_operator"
6293 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6294 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6296 (label_ref (match_operand 4 "" ""))
6298 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6299 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6300 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6304 if (which_alternative == 0)
6305 output_asm_insn (\"bic\\t%0, %3\", operands);
6306 else if (which_alternative <= 2)
6308 output_asm_insn (\"bic\\t%1, %3\", operands);
6309 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6310 conditions again, since we're only testing for equality. */
6311 output_asm_insn (\"mov\\t%0, %1\", operands);
6315 output_asm_insn (\"bic\\t%1, %3\", operands);
6316 output_asm_insn (\"str\\t%1, %0\", operands);
6319 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6321 case 4: return \"b%d5\\t%l4\";
6322 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6323 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6326 [(set (attr "far_jump")
6328 (ior (and (eq (symbol_ref ("which_alternative"))
6330 (eq_attr "length" "8"))
6331 (eq_attr "length" "10"))
6332 (const_string "yes")
6333 (const_string "no")))
6334 (set (attr "length")
6336 (eq (symbol_ref ("which_alternative"))
6339 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6340 (le (minus (match_dup 4) (pc)) (const_int 256)))
6343 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6344 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6348 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6349 (le (minus (match_dup 4) (pc)) (const_int 256)))
6352 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6353 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6358 (define_insn "*cbranchne_decr1"
6360 (if_then_else (match_operator 3 "equality_operator"
6361 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6363 (label_ref (match_operand 4 "" ""))
6365 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6366 (plus:SI (match_dup 2) (const_int -1)))
6367 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6372 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6374 VOIDmode, operands[2], const1_rtx);
6375 cond[1] = operands[4];
6377 if (which_alternative == 0)
6378 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6379 else if (which_alternative == 1)
6381 /* We must provide an alternative for a hi reg because reload
6382 cannot handle output reloads on a jump instruction, but we
6383 can't subtract into that. Fortunately a mov from lo to hi
6384 does not clobber the condition codes. */
6385 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6386 output_asm_insn (\"mov\\t%0, %1\", operands);
6390 /* Similarly, but the target is memory. */
6391 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6392 output_asm_insn (\"str\\t%1, %0\", operands);
6395 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6398 output_asm_insn (\"b%d0\\t%l1\", cond);
6401 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6402 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6404 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6405 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6409 [(set (attr "far_jump")
6411 (ior (and (eq (symbol_ref ("which_alternative"))
6413 (eq_attr "length" "8"))
6414 (eq_attr "length" "10"))
6415 (const_string "yes")
6416 (const_string "no")))
6417 (set_attr_alternative "length"
6421 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6422 (le (minus (match_dup 4) (pc)) (const_int 256)))
6425 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6426 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6431 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6432 (le (minus (match_dup 4) (pc)) (const_int 256)))
6435 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6436 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6441 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6442 (le (minus (match_dup 4) (pc)) (const_int 256)))
6445 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6446 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6451 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6452 (le (minus (match_dup 4) (pc)) (const_int 256)))
6455 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6456 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6461 (define_insn "*addsi3_cbranch"
6464 (match_operator 4 "comparison_operator"
6466 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6467 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6469 (label_ref (match_operand 5 "" ""))
6472 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6473 (plus:SI (match_dup 2) (match_dup 3)))
6474 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6476 && (GET_CODE (operands[4]) == EQ
6477 || GET_CODE (operands[4]) == NE
6478 || GET_CODE (operands[4]) == GE
6479 || GET_CODE (operands[4]) == LT)"
6485 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6486 cond[1] = operands[2];
6487 cond[2] = operands[3];
6489 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6490 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6492 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6494 if (which_alternative >= 3
6495 && which_alternative < 4)
6496 output_asm_insn (\"mov\\t%0, %1\", operands);
6497 else if (which_alternative >= 4)
6498 output_asm_insn (\"str\\t%1, %0\", operands);
6500 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6503 return \"b%d4\\t%l5\";
6505 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6507 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6511 [(set (attr "far_jump")
6513 (ior (and (lt (symbol_ref ("which_alternative"))
6515 (eq_attr "length" "8"))
6516 (eq_attr "length" "10"))
6517 (const_string "yes")
6518 (const_string "no")))
6519 (set (attr "length")
6521 (lt (symbol_ref ("which_alternative"))
6524 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6525 (le (minus (match_dup 5) (pc)) (const_int 256)))
6528 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6529 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6533 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6534 (le (minus (match_dup 5) (pc)) (const_int 256)))
6537 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6538 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6543 (define_insn "*addsi3_cbranch_scratch"
6546 (match_operator 3 "comparison_operator"
6548 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6549 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6551 (label_ref (match_operand 4 "" ""))
6553 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6555 && (GET_CODE (operands[3]) == EQ
6556 || GET_CODE (operands[3]) == NE
6557 || GET_CODE (operands[3]) == GE
6558 || GET_CODE (operands[3]) == LT)"
6561 switch (which_alternative)
6564 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6567 output_asm_insn (\"cmn\t%1, %2\", operands);
6570 if (INTVAL (operands[2]) < 0)
6571 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6573 output_asm_insn (\"add\t%0, %1, %2\", operands);
6576 if (INTVAL (operands[2]) < 0)
6577 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6579 output_asm_insn (\"add\t%0, %0, %2\", operands);
6583 switch (get_attr_length (insn))
6586 return \"b%d3\\t%l4\";
6588 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6590 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6594 [(set (attr "far_jump")
6596 (eq_attr "length" "8")
6597 (const_string "yes")
6598 (const_string "no")))
6599 (set (attr "length")
6601 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6602 (le (minus (match_dup 4) (pc)) (const_int 256)))
6605 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6606 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6611 (define_insn "*subsi3_cbranch"
6614 (match_operator 4 "comparison_operator"
6616 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6617 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6619 (label_ref (match_operand 5 "" ""))
6621 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6622 (minus:SI (match_dup 2) (match_dup 3)))
6623 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6625 && (GET_CODE (operands[4]) == EQ
6626 || GET_CODE (operands[4]) == NE
6627 || GET_CODE (operands[4]) == GE
6628 || GET_CODE (operands[4]) == LT)"
6631 if (which_alternative == 0)
6632 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6633 else if (which_alternative == 1)
6635 /* We must provide an alternative for a hi reg because reload
6636 cannot handle output reloads on a jump instruction, but we
6637 can't subtract into that. Fortunately a mov from lo to hi
6638 does not clobber the condition codes. */
6639 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6640 output_asm_insn (\"mov\\t%0, %1\", operands);
6644 /* Similarly, but the target is memory. */
6645 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6646 output_asm_insn (\"str\\t%1, %0\", operands);
6649 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6652 return \"b%d4\\t%l5\";
6654 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6656 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6660 [(set (attr "far_jump")
6662 (ior (and (eq (symbol_ref ("which_alternative"))
6664 (eq_attr "length" "8"))
6665 (eq_attr "length" "10"))
6666 (const_string "yes")
6667 (const_string "no")))
6668 (set (attr "length")
6670 (eq (symbol_ref ("which_alternative"))
6673 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6674 (le (minus (match_dup 5) (pc)) (const_int 256)))
6677 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6678 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6682 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6683 (le (minus (match_dup 5) (pc)) (const_int 256)))
6686 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6687 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6692 (define_insn "*subsi3_cbranch_scratch"
6695 (match_operator 0 "arm_comparison_operator"
6696 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6697 (match_operand:SI 2 "nonmemory_operand" "l"))
6699 (label_ref (match_operand 3 "" ""))
6702 && (GET_CODE (operands[0]) == EQ
6703 || GET_CODE (operands[0]) == NE
6704 || GET_CODE (operands[0]) == GE
6705 || GET_CODE (operands[0]) == LT)"
6707 output_asm_insn (\"cmp\\t%1, %2\", operands);
6708 switch (get_attr_length (insn))
6710 case 4: return \"b%d0\\t%l3\";
6711 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6712 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6715 [(set (attr "far_jump")
6717 (eq_attr "length" "8")
6718 (const_string "yes")
6719 (const_string "no")))
6720 (set (attr "length")
6722 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6723 (le (minus (match_dup 3) (pc)) (const_int 256)))
6726 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6727 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6732 ;; Comparison and test insns
6734 (define_expand "cmpsi"
6735 [(match_operand:SI 0 "s_register_operand" "")
6736 (match_operand:SI 1 "arm_add_operand" "")]
6739 arm_compare_op0 = operands[0];
6740 arm_compare_op1 = operands[1];
6745 (define_expand "cmpsf"
6746 [(match_operand:SF 0 "s_register_operand" "")
6747 (match_operand:SF 1 "arm_float_compare_operand" "")]
6748 "TARGET_ARM && TARGET_HARD_FLOAT"
6750 arm_compare_op0 = operands[0];
6751 arm_compare_op1 = operands[1];
6756 (define_expand "cmpdf"
6757 [(match_operand:DF 0 "s_register_operand" "")
6758 (match_operand:DF 1 "arm_float_compare_operand" "")]
6759 "TARGET_ARM && TARGET_HARD_FLOAT"
6761 arm_compare_op0 = operands[0];
6762 arm_compare_op1 = operands[1];
6767 (define_insn "*arm_cmpsi_insn"
6768 [(set (reg:CC CC_REGNUM)
6769 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6770 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6775 [(set_attr "conds" "set")]
6778 (define_insn "*cmpsi_shiftsi"
6779 [(set (reg:CC CC_REGNUM)
6780 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6781 (match_operator:SI 3 "shift_operator"
6782 [(match_operand:SI 1 "s_register_operand" "r")
6783 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6786 [(set_attr "conds" "set")
6787 (set_attr "shift" "1")
6788 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6789 (const_string "alu_shift")
6790 (const_string "alu_shift_reg")))]
6793 (define_insn "*cmpsi_shiftsi_swp"
6794 [(set (reg:CC_SWP CC_REGNUM)
6795 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6796 [(match_operand:SI 1 "s_register_operand" "r")
6797 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6798 (match_operand:SI 0 "s_register_operand" "r")))]
6801 [(set_attr "conds" "set")
6802 (set_attr "shift" "1")
6803 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6804 (const_string "alu_shift")
6805 (const_string "alu_shift_reg")))]
6808 (define_insn "*cmpsi_negshiftsi_si"
6809 [(set (reg:CC_Z CC_REGNUM)
6811 (neg:SI (match_operator:SI 1 "shift_operator"
6812 [(match_operand:SI 2 "s_register_operand" "r")
6813 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6814 (match_operand:SI 0 "s_register_operand" "r")))]
6817 [(set_attr "conds" "set")
6818 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6819 (const_string "alu_shift")
6820 (const_string "alu_shift_reg")))]
6823 ;; Cirrus SF compare instruction
6824 (define_insn "*cirrus_cmpsf"
6825 [(set (reg:CCFP CC_REGNUM)
6826 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6827 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6828 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6829 "cfcmps%?\\tr15, %V0, %V1"
6830 [(set_attr "type" "mav_farith")
6831 (set_attr "cirrus" "compare")]
6834 ;; Cirrus DF compare instruction
6835 (define_insn "*cirrus_cmpdf"
6836 [(set (reg:CCFP CC_REGNUM)
6837 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6838 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6839 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6840 "cfcmpd%?\\tr15, %V0, %V1"
6841 [(set_attr "type" "mav_farith")
6842 (set_attr "cirrus" "compare")]
6845 ;; Cirrus DI compare instruction
6846 (define_expand "cmpdi"
6847 [(match_operand:DI 0 "cirrus_fp_register" "")
6848 (match_operand:DI 1 "cirrus_fp_register" "")]
6849 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6851 arm_compare_op0 = operands[0];
6852 arm_compare_op1 = operands[1];
6856 (define_insn "*cirrus_cmpdi"
6857 [(set (reg:CC CC_REGNUM)
6858 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6859 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6860 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6861 "cfcmp64%?\\tr15, %V0, %V1"
6862 [(set_attr "type" "mav_farith")
6863 (set_attr "cirrus" "compare")]
6866 ; This insn allows redundant compares to be removed by cse, nothing should
6867 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6868 ; is deleted later on. The match_dup will match the mode here, so that
6869 ; mode changes of the condition codes aren't lost by this even though we don't
6870 ; specify what they are.
6872 (define_insn "*deleted_compare"
6873 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6875 "\\t%@ deleted compare"
6876 [(set_attr "conds" "set")
6877 (set_attr "length" "0")]
6881 ;; Conditional branch insns
6883 (define_expand "beq"
6885 (if_then_else (eq (match_dup 1) (const_int 0))
6886 (label_ref (match_operand 0 "" ""))
6889 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6892 (define_expand "bne"
6894 (if_then_else (ne (match_dup 1) (const_int 0))
6895 (label_ref (match_operand 0 "" ""))
6898 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6901 (define_expand "bgt"
6903 (if_then_else (gt (match_dup 1) (const_int 0))
6904 (label_ref (match_operand 0 "" ""))
6907 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6910 (define_expand "ble"
6912 (if_then_else (le (match_dup 1) (const_int 0))
6913 (label_ref (match_operand 0 "" ""))
6916 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6919 (define_expand "bge"
6921 (if_then_else (ge (match_dup 1) (const_int 0))
6922 (label_ref (match_operand 0 "" ""))
6925 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6928 (define_expand "blt"
6930 (if_then_else (lt (match_dup 1) (const_int 0))
6931 (label_ref (match_operand 0 "" ""))
6934 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6937 (define_expand "bgtu"
6939 (if_then_else (gtu (match_dup 1) (const_int 0))
6940 (label_ref (match_operand 0 "" ""))
6943 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6946 (define_expand "bleu"
6948 (if_then_else (leu (match_dup 1) (const_int 0))
6949 (label_ref (match_operand 0 "" ""))
6952 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6955 (define_expand "bgeu"
6957 (if_then_else (geu (match_dup 1) (const_int 0))
6958 (label_ref (match_operand 0 "" ""))
6961 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6964 (define_expand "bltu"
6966 (if_then_else (ltu (match_dup 1) (const_int 0))
6967 (label_ref (match_operand 0 "" ""))
6970 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6973 (define_expand "bunordered"
6975 (if_then_else (unordered (match_dup 1) (const_int 0))
6976 (label_ref (match_operand 0 "" ""))
6978 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6979 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6983 (define_expand "bordered"
6985 (if_then_else (ordered (match_dup 1) (const_int 0))
6986 (label_ref (match_operand 0 "" ""))
6988 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6989 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6993 (define_expand "bungt"
6995 (if_then_else (ungt (match_dup 1) (const_int 0))
6996 (label_ref (match_operand 0 "" ""))
6998 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6999 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7002 (define_expand "bunlt"
7004 (if_then_else (unlt (match_dup 1) (const_int 0))
7005 (label_ref (match_operand 0 "" ""))
7007 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7008 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7011 (define_expand "bunge"
7013 (if_then_else (unge (match_dup 1) (const_int 0))
7014 (label_ref (match_operand 0 "" ""))
7016 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7017 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7020 (define_expand "bunle"
7022 (if_then_else (unle (match_dup 1) (const_int 0))
7023 (label_ref (match_operand 0 "" ""))
7025 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7026 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7029 ;; The following two patterns need two branch instructions, since there is
7030 ;; no single instruction that will handle all cases.
7031 (define_expand "buneq"
7033 (if_then_else (uneq (match_dup 1) (const_int 0))
7034 (label_ref (match_operand 0 "" ""))
7036 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7037 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7040 (define_expand "bltgt"
7042 (if_then_else (ltgt (match_dup 1) (const_int 0))
7043 (label_ref (match_operand 0 "" ""))
7045 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7046 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7050 ;; Patterns to match conditional branch insns.
7053 ; Special pattern to match UNEQ.
7054 (define_insn "*arm_buneq"
7056 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7057 (label_ref (match_operand 0 "" ""))
7059 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7061 gcc_assert (!arm_ccfsm_state);
7063 return \"bvs\\t%l0\;beq\\t%l0\";
7065 [(set_attr "conds" "jump_clob")
7066 (set_attr "length" "8")]
7069 ; Special pattern to match LTGT.
7070 (define_insn "*arm_bltgt"
7072 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7073 (label_ref (match_operand 0 "" ""))
7075 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7077 gcc_assert (!arm_ccfsm_state);
7079 return \"bmi\\t%l0\;bgt\\t%l0\";
7081 [(set_attr "conds" "jump_clob")
7082 (set_attr "length" "8")]
7085 (define_insn "*arm_cond_branch"
7087 (if_then_else (match_operator 1 "arm_comparison_operator"
7088 [(match_operand 2 "cc_register" "") (const_int 0)])
7089 (label_ref (match_operand 0 "" ""))
7093 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7095 arm_ccfsm_state += 2;
7098 return \"b%d1\\t%l0\";
7100 [(set_attr "conds" "use")
7101 (set_attr "type" "branch")]
7104 ; Special pattern to match reversed UNEQ.
7105 (define_insn "*arm_buneq_reversed"
7107 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7109 (label_ref (match_operand 0 "" ""))))]
7110 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7112 gcc_assert (!arm_ccfsm_state);
7114 return \"bmi\\t%l0\;bgt\\t%l0\";
7116 [(set_attr "conds" "jump_clob")
7117 (set_attr "length" "8")]
7120 ; Special pattern to match reversed LTGT.
7121 (define_insn "*arm_bltgt_reversed"
7123 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7125 (label_ref (match_operand 0 "" ""))))]
7126 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7128 gcc_assert (!arm_ccfsm_state);
7130 return \"bvs\\t%l0\;beq\\t%l0\";
7132 [(set_attr "conds" "jump_clob")
7133 (set_attr "length" "8")]
7136 (define_insn "*arm_cond_branch_reversed"
7138 (if_then_else (match_operator 1 "arm_comparison_operator"
7139 [(match_operand 2 "cc_register" "") (const_int 0)])
7141 (label_ref (match_operand 0 "" ""))))]
7144 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7146 arm_ccfsm_state += 2;
7149 return \"b%D1\\t%l0\";
7151 [(set_attr "conds" "use")
7152 (set_attr "type" "branch")]
7159 (define_expand "seq"
7160 [(set (match_operand:SI 0 "s_register_operand" "")
7161 (eq:SI (match_dup 1) (const_int 0)))]
7163 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7166 (define_expand "sne"
7167 [(set (match_operand:SI 0 "s_register_operand" "")
7168 (ne:SI (match_dup 1) (const_int 0)))]
7170 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7173 (define_expand "sgt"
7174 [(set (match_operand:SI 0 "s_register_operand" "")
7175 (gt:SI (match_dup 1) (const_int 0)))]
7177 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7180 (define_expand "sle"
7181 [(set (match_operand:SI 0 "s_register_operand" "")
7182 (le:SI (match_dup 1) (const_int 0)))]
7184 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7187 (define_expand "sge"
7188 [(set (match_operand:SI 0 "s_register_operand" "")
7189 (ge:SI (match_dup 1) (const_int 0)))]
7191 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7194 (define_expand "slt"
7195 [(set (match_operand:SI 0 "s_register_operand" "")
7196 (lt:SI (match_dup 1) (const_int 0)))]
7198 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7201 (define_expand "sgtu"
7202 [(set (match_operand:SI 0 "s_register_operand" "")
7203 (gtu:SI (match_dup 1) (const_int 0)))]
7205 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7208 (define_expand "sleu"
7209 [(set (match_operand:SI 0 "s_register_operand" "")
7210 (leu:SI (match_dup 1) (const_int 0)))]
7212 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7215 (define_expand "sgeu"
7216 [(set (match_operand:SI 0 "s_register_operand" "")
7217 (geu:SI (match_dup 1) (const_int 0)))]
7219 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7222 (define_expand "sltu"
7223 [(set (match_operand:SI 0 "s_register_operand" "")
7224 (ltu:SI (match_dup 1) (const_int 0)))]
7226 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7229 (define_expand "sunordered"
7230 [(set (match_operand:SI 0 "s_register_operand" "")
7231 (unordered:SI (match_dup 1) (const_int 0)))]
7232 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7233 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7237 (define_expand "sordered"
7238 [(set (match_operand:SI 0 "s_register_operand" "")
7239 (ordered:SI (match_dup 1) (const_int 0)))]
7240 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7241 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7245 (define_expand "sungt"
7246 [(set (match_operand:SI 0 "s_register_operand" "")
7247 (ungt:SI (match_dup 1) (const_int 0)))]
7248 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7253 (define_expand "sunge"
7254 [(set (match_operand:SI 0 "s_register_operand" "")
7255 (unge:SI (match_dup 1) (const_int 0)))]
7256 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7257 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7261 (define_expand "sunlt"
7262 [(set (match_operand:SI 0 "s_register_operand" "")
7263 (unlt:SI (match_dup 1) (const_int 0)))]
7264 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7269 (define_expand "sunle"
7270 [(set (match_operand:SI 0 "s_register_operand" "")
7271 (unle:SI (match_dup 1) (const_int 0)))]
7272 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7273 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7277 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7278 ;;; simple ARM instructions.
7280 ; (define_expand "suneq"
7281 ; [(set (match_operand:SI 0 "s_register_operand" "")
7282 ; (uneq:SI (match_dup 1) (const_int 0)))]
7283 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7284 ; "gcc_unreachable ();"
7287 ; (define_expand "sltgt"
7288 ; [(set (match_operand:SI 0 "s_register_operand" "")
7289 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7290 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7291 ; "gcc_unreachable ();"
7294 (define_insn "*mov_scc"
7295 [(set (match_operand:SI 0 "s_register_operand" "=r")
7296 (match_operator:SI 1 "arm_comparison_operator"
7297 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7299 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7300 [(set_attr "conds" "use")
7301 (set_attr "length" "8")]
7304 (define_insn "*mov_negscc"
7305 [(set (match_operand:SI 0 "s_register_operand" "=r")
7306 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7307 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7309 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7310 [(set_attr "conds" "use")
7311 (set_attr "length" "8")]
7314 (define_insn "*mov_notscc"
7315 [(set (match_operand:SI 0 "s_register_operand" "=r")
7316 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7317 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7319 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7320 [(set_attr "conds" "use")
7321 (set_attr "length" "8")]
7325 ;; Conditional move insns
7327 (define_expand "movsicc"
7328 [(set (match_operand:SI 0 "s_register_operand" "")
7329 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7330 (match_operand:SI 2 "arm_not_operand" "")
7331 (match_operand:SI 3 "arm_not_operand" "")))]
7335 enum rtx_code code = GET_CODE (operands[1]);
7338 if (code == UNEQ || code == LTGT)
7341 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7342 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7346 (define_expand "movsfcc"
7347 [(set (match_operand:SF 0 "s_register_operand" "")
7348 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7349 (match_operand:SF 2 "s_register_operand" "")
7350 (match_operand:SF 3 "nonmemory_operand" "")))]
7354 enum rtx_code code = GET_CODE (operands[1]);
7357 if (code == UNEQ || code == LTGT)
7360 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7361 Otherwise, ensure it is a valid FP add operand */
7362 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7363 || (!arm_float_add_operand (operands[3], SFmode)))
7364 operands[3] = force_reg (SFmode, operands[3]);
7366 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7367 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7371 (define_expand "movdfcc"
7372 [(set (match_operand:DF 0 "s_register_operand" "")
7373 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7374 (match_operand:DF 2 "s_register_operand" "")
7375 (match_operand:DF 3 "arm_float_add_operand" "")))]
7376 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7379 enum rtx_code code = GET_CODE (operands[1]);
7382 if (code == UNEQ || code == LTGT)
7385 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7386 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7390 (define_insn "*movsicc_insn"
7391 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7393 (match_operator 3 "arm_comparison_operator"
7394 [(match_operand 4 "cc_register" "") (const_int 0)])
7395 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7396 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7403 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7404 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7405 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7406 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7407 [(set_attr "length" "4,4,4,4,8,8,8,8")
7408 (set_attr "conds" "use")]
7411 (define_insn "*movsfcc_soft_insn"
7412 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7413 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7414 [(match_operand 4 "cc_register" "") (const_int 0)])
7415 (match_operand:SF 1 "s_register_operand" "0,r")
7416 (match_operand:SF 2 "s_register_operand" "r,0")))]
7417 "TARGET_ARM && TARGET_SOFT_FLOAT"
7421 [(set_attr "conds" "use")]
7425 ;; Jump and linkage insns
7427 (define_expand "jump"
7429 (label_ref (match_operand 0 "" "")))]
7434 (define_insn "*arm_jump"
7436 (label_ref (match_operand 0 "" "")))]
7440 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7442 arm_ccfsm_state += 2;
7445 return \"b%?\\t%l0\";
7448 [(set_attr "predicable" "yes")]
7451 (define_insn "*thumb_jump"
7453 (label_ref (match_operand 0 "" "")))]
7456 if (get_attr_length (insn) == 2)
7458 return \"bl\\t%l0\\t%@ far jump\";
7460 [(set (attr "far_jump")
7462 (eq_attr "length" "4")
7463 (const_string "yes")
7464 (const_string "no")))
7465 (set (attr "length")
7467 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7468 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7473 (define_expand "call"
7474 [(parallel [(call (match_operand 0 "memory_operand" "")
7475 (match_operand 1 "general_operand" ""))
7476 (use (match_operand 2 "" ""))
7477 (clobber (reg:SI LR_REGNUM))])]
7483 /* In an untyped call, we can get NULL for operand 2. */
7484 if (operands[2] == NULL_RTX)
7485 operands[2] = const0_rtx;
7487 /* This is to decide if we should generate indirect calls by loading the
7488 32 bit address of the callee into a register before performing the
7489 branch and link. operand[2] encodes the long_call/short_call
7490 attribute of the function being called. This attribute is set whenever
7491 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7492 is used, and the short_call attribute can also be set if function is
7493 declared as static or if it has already been defined in the current
7494 compilation unit. See arm.c and arm.h for info about this. The third
7495 parameter to arm_is_longcall_p is used to tell it which pattern
7497 callee = XEXP (operands[0], 0);
7499 if (GET_CODE (callee) != REG
7500 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7501 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7505 (define_insn "*call_reg_armv5"
7506 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7507 (match_operand 1 "" ""))
7508 (use (match_operand 2 "" ""))
7509 (clobber (reg:SI LR_REGNUM))]
7510 "TARGET_ARM && arm_arch5"
7512 [(set_attr "type" "call")]
7515 (define_insn "*call_reg_arm"
7516 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7517 (match_operand 1 "" ""))
7518 (use (match_operand 2 "" ""))
7519 (clobber (reg:SI LR_REGNUM))]
7520 "TARGET_ARM && !arm_arch5"
7522 return output_call (operands);
7524 ;; length is worst case, normally it is only two
7525 [(set_attr "length" "12")
7526 (set_attr "type" "call")]
7529 (define_insn "*call_mem"
7530 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7531 (match_operand 1 "" ""))
7532 (use (match_operand 2 "" ""))
7533 (clobber (reg:SI LR_REGNUM))]
7536 return output_call_mem (operands);
7538 [(set_attr "length" "12")
7539 (set_attr "type" "call")]
7542 (define_insn "*call_reg_thumb_v5"
7543 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7544 (match_operand 1 "" ""))
7545 (use (match_operand 2 "" ""))
7546 (clobber (reg:SI LR_REGNUM))]
7547 "TARGET_THUMB && arm_arch5"
7549 [(set_attr "length" "2")
7550 (set_attr "type" "call")]
7553 (define_insn "*call_reg_thumb"
7554 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7555 (match_operand 1 "" ""))
7556 (use (match_operand 2 "" ""))
7557 (clobber (reg:SI LR_REGNUM))]
7558 "TARGET_THUMB && !arm_arch5"
7561 if (!TARGET_CALLER_INTERWORKING)
7562 return thumb_call_via_reg (operands[0]);
7563 else if (operands[1] == const0_rtx)
7564 return \"bl\\t%__interwork_call_via_%0\";
7565 else if (frame_pointer_needed)
7566 return \"bl\\t%__interwork_r7_call_via_%0\";
7568 return \"bl\\t%__interwork_r11_call_via_%0\";
7570 [(set_attr "type" "call")]
7573 (define_expand "call_value"
7574 [(parallel [(set (match_operand 0 "" "")
7575 (call (match_operand 1 "memory_operand" "")
7576 (match_operand 2 "general_operand" "")))
7577 (use (match_operand 3 "" ""))
7578 (clobber (reg:SI LR_REGNUM))])]
7582 rtx callee = XEXP (operands[1], 0);
7584 /* In an untyped call, we can get NULL for operand 2. */
7585 if (operands[3] == 0)
7586 operands[3] = const0_rtx;
7588 /* See the comment in define_expand \"call\". */
7589 if (GET_CODE (callee) != REG
7590 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7591 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7595 (define_insn "*call_value_reg_armv5"
7596 [(set (match_operand 0 "" "")
7597 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7598 (match_operand 2 "" "")))
7599 (use (match_operand 3 "" ""))
7600 (clobber (reg:SI LR_REGNUM))]
7601 "TARGET_ARM && arm_arch5"
7603 [(set_attr "type" "call")]
7606 (define_insn "*call_value_reg_arm"
7607 [(set (match_operand 0 "" "")
7608 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7609 (match_operand 2 "" "")))
7610 (use (match_operand 3 "" ""))
7611 (clobber (reg:SI LR_REGNUM))]
7612 "TARGET_ARM && !arm_arch5"
7614 return output_call (&operands[1]);
7616 [(set_attr "length" "12")
7617 (set_attr "type" "call")]
7620 (define_insn "*call_value_mem"
7621 [(set (match_operand 0 "" "")
7622 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7623 (match_operand 2 "" "")))
7624 (use (match_operand 3 "" ""))
7625 (clobber (reg:SI LR_REGNUM))]
7626 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7628 return output_call_mem (&operands[1]);
7630 [(set_attr "length" "12")
7631 (set_attr "type" "call")]
7634 (define_insn "*call_value_reg_thumb_v5"
7635 [(set (match_operand 0 "" "")
7636 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7637 (match_operand 2 "" "")))
7638 (use (match_operand 3 "" ""))
7639 (clobber (reg:SI LR_REGNUM))]
7640 "TARGET_THUMB && arm_arch5"
7642 [(set_attr "length" "2")
7643 (set_attr "type" "call")]
7646 (define_insn "*call_value_reg_thumb"
7647 [(set (match_operand 0 "" "")
7648 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7649 (match_operand 2 "" "")))
7650 (use (match_operand 3 "" ""))
7651 (clobber (reg:SI LR_REGNUM))]
7652 "TARGET_THUMB && !arm_arch5"
7655 if (!TARGET_CALLER_INTERWORKING)
7656 return thumb_call_via_reg (operands[1]);
7657 else if (operands[2] == const0_rtx)
7658 return \"bl\\t%__interwork_call_via_%1\";
7659 else if (frame_pointer_needed)
7660 return \"bl\\t%__interwork_r7_call_via_%1\";
7662 return \"bl\\t%__interwork_r11_call_via_%1\";
7664 [(set_attr "type" "call")]
7667 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7668 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7670 (define_insn "*call_symbol"
7671 [(call (mem:SI (match_operand:SI 0 "" ""))
7672 (match_operand 1 "" ""))
7673 (use (match_operand 2 "" ""))
7674 (clobber (reg:SI LR_REGNUM))]
7676 && (GET_CODE (operands[0]) == SYMBOL_REF)
7677 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7680 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7682 [(set_attr "type" "call")]
7685 (define_insn "*call_value_symbol"
7686 [(set (match_operand 0 "" "")
7687 (call (mem:SI (match_operand:SI 1 "" ""))
7688 (match_operand:SI 2 "" "")))
7689 (use (match_operand 3 "" ""))
7690 (clobber (reg:SI LR_REGNUM))]
7692 && (GET_CODE (operands[1]) == SYMBOL_REF)
7693 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7696 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7698 [(set_attr "type" "call")]
7701 (define_insn "*call_insn"
7702 [(call (mem:SI (match_operand:SI 0 "" ""))
7703 (match_operand:SI 1 "" ""))
7704 (use (match_operand 2 "" ""))
7705 (clobber (reg:SI LR_REGNUM))]
7707 && GET_CODE (operands[0]) == SYMBOL_REF
7708 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7710 [(set_attr "length" "4")
7711 (set_attr "type" "call")]
7714 (define_insn "*call_value_insn"
7715 [(set (match_operand 0 "" "")
7716 (call (mem:SI (match_operand 1 "" ""))
7717 (match_operand 2 "" "")))
7718 (use (match_operand 3 "" ""))
7719 (clobber (reg:SI LR_REGNUM))]
7721 && GET_CODE (operands[1]) == SYMBOL_REF
7722 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7724 [(set_attr "length" "4")
7725 (set_attr "type" "call")]
7728 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7729 (define_expand "sibcall"
7730 [(parallel [(call (match_operand 0 "memory_operand" "")
7731 (match_operand 1 "general_operand" ""))
7733 (use (match_operand 2 "" ""))])]
7737 if (operands[2] == NULL_RTX)
7738 operands[2] = const0_rtx;
7742 (define_expand "sibcall_value"
7743 [(parallel [(set (match_operand 0 "" "")
7744 (call (match_operand 1 "memory_operand" "")
7745 (match_operand 2 "general_operand" "")))
7747 (use (match_operand 3 "" ""))])]
7751 if (operands[3] == NULL_RTX)
7752 operands[3] = const0_rtx;
7756 (define_insn "*sibcall_insn"
7757 [(call (mem:SI (match_operand:SI 0 "" "X"))
7758 (match_operand 1 "" ""))
7760 (use (match_operand 2 "" ""))]
7761 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7763 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7765 [(set_attr "type" "call")]
7768 (define_insn "*sibcall_value_insn"
7769 [(set (match_operand 0 "" "")
7770 (call (mem:SI (match_operand:SI 1 "" "X"))
7771 (match_operand 2 "" "")))
7773 (use (match_operand 3 "" ""))]
7774 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7776 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7778 [(set_attr "type" "call")]
7781 ;; Often the return insn will be the same as loading from memory, so set attr
7782 (define_insn "return"
7784 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7787 if (arm_ccfsm_state == 2)
7789 arm_ccfsm_state += 2;
7792 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7794 [(set_attr "type" "load1")
7795 (set_attr "length" "12")
7796 (set_attr "predicable" "yes")]
7799 (define_insn "*cond_return"
7801 (if_then_else (match_operator 0 "arm_comparison_operator"
7802 [(match_operand 1 "cc_register" "") (const_int 0)])
7805 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7808 if (arm_ccfsm_state == 2)
7810 arm_ccfsm_state += 2;
7813 return output_return_instruction (operands[0], TRUE, FALSE);
7815 [(set_attr "conds" "use")
7816 (set_attr "length" "12")
7817 (set_attr "type" "load1")]
7820 (define_insn "*cond_return_inverted"
7822 (if_then_else (match_operator 0 "arm_comparison_operator"
7823 [(match_operand 1 "cc_register" "") (const_int 0)])
7826 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7829 if (arm_ccfsm_state == 2)
7831 arm_ccfsm_state += 2;
7834 return output_return_instruction (operands[0], TRUE, TRUE);
7836 [(set_attr "conds" "use")
7837 (set_attr "length" "12")
7838 (set_attr "type" "load1")]
7841 ;; Generate a sequence of instructions to determine if the processor is
7842 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7845 (define_expand "return_addr_mask"
7847 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7849 (set (match_operand:SI 0 "s_register_operand" "")
7850 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7852 (const_int 67108860)))] ; 0x03fffffc
7855 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7858 (define_insn "*check_arch2"
7859 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7860 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7863 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7864 [(set_attr "length" "8")
7865 (set_attr "conds" "set")]
7868 ;; Call subroutine returning any type.
7870 (define_expand "untyped_call"
7871 [(parallel [(call (match_operand 0 "" "")
7873 (match_operand 1 "" "")
7874 (match_operand 2 "" "")])]
7879 rtx par = gen_rtx_PARALLEL (VOIDmode,
7880 rtvec_alloc (XVECLEN (operands[2], 0)));
7881 rtx addr = gen_reg_rtx (Pmode);
7885 emit_move_insn (addr, XEXP (operands[1], 0));
7886 mem = change_address (operands[1], BLKmode, addr);
7888 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7890 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7892 /* Default code only uses r0 as a return value, but we could
7893 be using anything up to 4 registers. */
7894 if (REGNO (src) == R0_REGNUM)
7895 src = gen_rtx_REG (TImode, R0_REGNUM);
7897 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7899 size += GET_MODE_SIZE (GET_MODE (src));
7902 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7907 for (i = 0; i < XVECLEN (par, 0); i++)
7909 HOST_WIDE_INT offset = 0;
7910 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7913 emit_move_insn (addr, plus_constant (addr, size));
7915 mem = change_address (mem, GET_MODE (reg), NULL);
7916 if (REGNO (reg) == R0_REGNUM)
7918 /* On thumb we have to use a write-back instruction. */
7919 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7920 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7921 size = TARGET_ARM ? 16 : 0;
7925 emit_move_insn (mem, reg);
7926 size = GET_MODE_SIZE (GET_MODE (reg));
7930 /* The optimizer does not know that the call sets the function value
7931 registers we stored in the result block. We avoid problems by
7932 claiming that all hard registers are used and clobbered at this
7934 emit_insn (gen_blockage ());
7940 (define_expand "untyped_return"
7941 [(match_operand:BLK 0 "memory_operand" "")
7942 (match_operand 1 "" "")]
7947 rtx addr = gen_reg_rtx (Pmode);
7951 emit_move_insn (addr, XEXP (operands[0], 0));
7952 mem = change_address (operands[0], BLKmode, addr);
7954 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7956 HOST_WIDE_INT offset = 0;
7957 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7960 emit_move_insn (addr, plus_constant (addr, size));
7962 mem = change_address (mem, GET_MODE (reg), NULL);
7963 if (REGNO (reg) == R0_REGNUM)
7965 /* On thumb we have to use a write-back instruction. */
7966 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7967 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7968 size = TARGET_ARM ? 16 : 0;
7972 emit_move_insn (reg, mem);
7973 size = GET_MODE_SIZE (GET_MODE (reg));
7977 /* Emit USE insns before the return. */
7978 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7979 emit_insn (gen_rtx_USE (VOIDmode,
7980 SET_DEST (XVECEXP (operands[1], 0, i))));
7982 /* Construct the return. */
7983 expand_naked_return ();
7989 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7990 ;; all of memory. This blocks insns from being moved across this point.
7992 (define_insn "blockage"
7993 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7996 [(set_attr "length" "0")
7997 (set_attr "type" "block")]
8000 (define_expand "casesi"
8001 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8002 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8003 (match_operand:SI 2 "const_int_operand" "") ; total range
8004 (match_operand:SI 3 "" "") ; table label
8005 (match_operand:SI 4 "" "")] ; Out of range label
8010 if (operands[1] != const0_rtx)
8012 reg = gen_reg_rtx (SImode);
8014 emit_insn (gen_addsi3 (reg, operands[0],
8015 GEN_INT (-INTVAL (operands[1]))));
8019 if (!const_ok_for_arm (INTVAL (operands[2])))
8020 operands[2] = force_reg (SImode, operands[2]);
8022 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8028 ;; The USE in this pattern is needed to tell flow analysis that this is
8029 ;; a CASESI insn. It has no other purpose.
8030 (define_insn "casesi_internal"
8031 [(parallel [(set (pc)
8033 (leu (match_operand:SI 0 "s_register_operand" "r")
8034 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8035 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8036 (label_ref (match_operand 2 "" ""))))
8037 (label_ref (match_operand 3 "" ""))))
8038 (clobber (reg:CC CC_REGNUM))
8039 (use (label_ref (match_dup 2)))])]
8043 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8044 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8046 [(set_attr "conds" "clob")
8047 (set_attr "length" "12")]
8050 (define_expand "indirect_jump"
8052 (match_operand:SI 0 "s_register_operand" ""))]
8057 ;; NB Never uses BX.
8058 (define_insn "*arm_indirect_jump"
8060 (match_operand:SI 0 "s_register_operand" "r"))]
8062 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8063 [(set_attr "predicable" "yes")]
8066 (define_insn "*load_indirect_jump"
8068 (match_operand:SI 0 "memory_operand" "m"))]
8070 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8071 [(set_attr "type" "load1")
8072 (set_attr "pool_range" "4096")
8073 (set_attr "neg_pool_range" "4084")
8074 (set_attr "predicable" "yes")]
8077 ;; NB Never uses BX.
8078 (define_insn "*thumb_indirect_jump"
8080 (match_operand:SI 0 "register_operand" "l*r"))]
8083 [(set_attr "conds" "clob")
8084 (set_attr "length" "2")]
8095 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8096 return \"mov\\tr8, r8\";
8098 [(set (attr "length")
8099 (if_then_else (eq_attr "is_thumb" "yes")
8105 ;; Patterns to allow combination of arithmetic, cond code and shifts
8107 (define_insn "*arith_shiftsi"
8108 [(set (match_operand:SI 0 "s_register_operand" "=r")
8109 (match_operator:SI 1 "shiftable_operator"
8110 [(match_operator:SI 3 "shift_operator"
8111 [(match_operand:SI 4 "s_register_operand" "r")
8112 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8113 (match_operand:SI 2 "s_register_operand" "r")]))]
8115 "%i1%?\\t%0, %2, %4%S3"
8116 [(set_attr "predicable" "yes")
8117 (set_attr "shift" "4")
8118 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8119 (const_string "alu_shift")
8120 (const_string "alu_shift_reg")))]
8124 [(set (match_operand:SI 0 "s_register_operand" "")
8125 (match_operator:SI 1 "shiftable_operator"
8126 [(match_operator:SI 2 "shiftable_operator"
8127 [(match_operator:SI 3 "shift_operator"
8128 [(match_operand:SI 4 "s_register_operand" "")
8129 (match_operand:SI 5 "reg_or_int_operand" "")])
8130 (match_operand:SI 6 "s_register_operand" "")])
8131 (match_operand:SI 7 "arm_rhs_operand" "")]))
8132 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8135 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8138 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8141 (define_insn "*arith_shiftsi_compare0"
8142 [(set (reg:CC_NOOV CC_REGNUM)
8143 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8144 [(match_operator:SI 3 "shift_operator"
8145 [(match_operand:SI 4 "s_register_operand" "r")
8146 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8147 (match_operand:SI 2 "s_register_operand" "r")])
8149 (set (match_operand:SI 0 "s_register_operand" "=r")
8150 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8153 "%i1%?s\\t%0, %2, %4%S3"
8154 [(set_attr "conds" "set")
8155 (set_attr "shift" "4")
8156 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8157 (const_string "alu_shift")
8158 (const_string "alu_shift_reg")))]
8161 (define_insn "*arith_shiftsi_compare0_scratch"
8162 [(set (reg:CC_NOOV CC_REGNUM)
8163 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8164 [(match_operator:SI 3 "shift_operator"
8165 [(match_operand:SI 4 "s_register_operand" "r")
8166 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8167 (match_operand:SI 2 "s_register_operand" "r")])
8169 (clobber (match_scratch:SI 0 "=r"))]
8171 "%i1%?s\\t%0, %2, %4%S3"
8172 [(set_attr "conds" "set")
8173 (set_attr "shift" "4")
8174 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8175 (const_string "alu_shift")
8176 (const_string "alu_shift_reg")))]
8179 (define_insn "*sub_shiftsi"
8180 [(set (match_operand:SI 0 "s_register_operand" "=r")
8181 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8182 (match_operator:SI 2 "shift_operator"
8183 [(match_operand:SI 3 "s_register_operand" "r")
8184 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8186 "sub%?\\t%0, %1, %3%S2"
8187 [(set_attr "predicable" "yes")
8188 (set_attr "shift" "3")
8189 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8190 (const_string "alu_shift")
8191 (const_string "alu_shift_reg")))]
8194 (define_insn "*sub_shiftsi_compare0"
8195 [(set (reg:CC_NOOV CC_REGNUM)
8197 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8198 (match_operator:SI 2 "shift_operator"
8199 [(match_operand:SI 3 "s_register_operand" "r")
8200 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8202 (set (match_operand:SI 0 "s_register_operand" "=r")
8203 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8206 "sub%?s\\t%0, %1, %3%S2"
8207 [(set_attr "conds" "set")
8208 (set_attr "shift" "3")
8209 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8210 (const_string "alu_shift")
8211 (const_string "alu_shift_reg")))]
8214 (define_insn "*sub_shiftsi_compare0_scratch"
8215 [(set (reg:CC_NOOV CC_REGNUM)
8217 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8218 (match_operator:SI 2 "shift_operator"
8219 [(match_operand:SI 3 "s_register_operand" "r")
8220 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8222 (clobber (match_scratch:SI 0 "=r"))]
8224 "sub%?s\\t%0, %1, %3%S2"
8225 [(set_attr "conds" "set")
8226 (set_attr "shift" "3")
8227 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8228 (const_string "alu_shift")
8229 (const_string "alu_shift_reg")))]
8234 (define_insn "*and_scc"
8235 [(set (match_operand:SI 0 "s_register_operand" "=r")
8236 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8237 [(match_operand 3 "cc_register" "") (const_int 0)])
8238 (match_operand:SI 2 "s_register_operand" "r")))]
8240 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8241 [(set_attr "conds" "use")
8242 (set_attr "length" "8")]
8245 (define_insn "*ior_scc"
8246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8247 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8248 [(match_operand 3 "cc_register" "") (const_int 0)])
8249 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8253 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8254 [(set_attr "conds" "use")
8255 (set_attr "length" "4,8")]
8258 (define_insn "*compare_scc"
8259 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8260 (match_operator:SI 1 "arm_comparison_operator"
8261 [(match_operand:SI 2 "s_register_operand" "r,r")
8262 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8263 (clobber (reg:CC CC_REGNUM))]
8266 if (operands[3] == const0_rtx)
8268 if (GET_CODE (operands[1]) == LT)
8269 return \"mov\\t%0, %2, lsr #31\";
8271 if (GET_CODE (operands[1]) == GE)
8272 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8274 if (GET_CODE (operands[1]) == EQ)
8275 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8278 if (GET_CODE (operands[1]) == NE)
8280 if (which_alternative == 1)
8281 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8282 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8284 if (which_alternative == 1)
8285 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8287 output_asm_insn (\"cmp\\t%2, %3\", operands);
8288 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8290 [(set_attr "conds" "clob")
8291 (set_attr "length" "12")]
8294 (define_insn "*cond_move"
8295 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8296 (if_then_else:SI (match_operator 3 "equality_operator"
8297 [(match_operator 4 "arm_comparison_operator"
8298 [(match_operand 5 "cc_register" "") (const_int 0)])
8300 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8301 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8304 if (GET_CODE (operands[3]) == NE)
8306 if (which_alternative != 1)
8307 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8308 if (which_alternative != 0)
8309 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8312 if (which_alternative != 0)
8313 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8314 if (which_alternative != 1)
8315 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8318 [(set_attr "conds" "use")
8319 (set_attr "length" "4,4,8")]
8322 (define_insn "*cond_arith"
8323 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8324 (match_operator:SI 5 "shiftable_operator"
8325 [(match_operator:SI 4 "arm_comparison_operator"
8326 [(match_operand:SI 2 "s_register_operand" "r,r")
8327 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8328 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8329 (clobber (reg:CC CC_REGNUM))]
8332 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8333 return \"%i5\\t%0, %1, %2, lsr #31\";
8335 output_asm_insn (\"cmp\\t%2, %3\", operands);
8336 if (GET_CODE (operands[5]) == AND)
8337 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8338 else if (GET_CODE (operands[5]) == MINUS)
8339 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8340 else if (which_alternative != 0)
8341 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8342 return \"%i5%d4\\t%0, %1, #1\";
8344 [(set_attr "conds" "clob")
8345 (set_attr "length" "12")]
8348 (define_insn "*cond_sub"
8349 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8350 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8351 (match_operator:SI 4 "arm_comparison_operator"
8352 [(match_operand:SI 2 "s_register_operand" "r,r")
8353 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8354 (clobber (reg:CC CC_REGNUM))]
8357 output_asm_insn (\"cmp\\t%2, %3\", operands);
8358 if (which_alternative != 0)
8359 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8360 return \"sub%d4\\t%0, %1, #1\";
8362 [(set_attr "conds" "clob")
8363 (set_attr "length" "8,12")]
8366 (define_insn "*cmp_ite0"
8367 [(set (match_operand 6 "dominant_cc_register" "")
8370 (match_operator 4 "arm_comparison_operator"
8371 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8372 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8373 (match_operator:SI 5 "arm_comparison_operator"
8374 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8375 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8381 static const char * const opcodes[4][2] =
8383 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8384 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8385 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8386 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8387 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8388 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8389 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8390 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8393 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8395 return opcodes[which_alternative][swap];
8397 [(set_attr "conds" "set")
8398 (set_attr "length" "8")]
8401 (define_insn "*cmp_ite1"
8402 [(set (match_operand 6 "dominant_cc_register" "")
8405 (match_operator 4 "arm_comparison_operator"
8406 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8407 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8408 (match_operator:SI 5 "arm_comparison_operator"
8409 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8410 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8416 static const char * const opcodes[4][2] =
8418 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8419 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8420 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8421 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8422 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8423 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8424 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8425 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8428 comparison_dominates_p (GET_CODE (operands[5]),
8429 reverse_condition (GET_CODE (operands[4])));
8431 return opcodes[which_alternative][swap];
8433 [(set_attr "conds" "set")
8434 (set_attr "length" "8")]
8437 (define_insn "*cmp_and"
8438 [(set (match_operand 6 "dominant_cc_register" "")
8441 (match_operator 4 "arm_comparison_operator"
8442 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8443 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8444 (match_operator:SI 5 "arm_comparison_operator"
8445 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8446 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8451 static const char *const opcodes[4][2] =
8453 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8454 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8455 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8456 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8457 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8458 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8459 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8460 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8463 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8465 return opcodes[which_alternative][swap];
8467 [(set_attr "conds" "set")
8468 (set_attr "predicable" "no")
8469 (set_attr "length" "8")]
8472 (define_insn "*cmp_ior"
8473 [(set (match_operand 6 "dominant_cc_register" "")
8476 (match_operator 4 "arm_comparison_operator"
8477 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8478 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8479 (match_operator:SI 5 "arm_comparison_operator"
8480 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8481 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8486 static const char *const opcodes[4][2] =
8488 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8489 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8490 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8491 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8492 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8493 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8494 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8495 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8498 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8500 return opcodes[which_alternative][swap];
8503 [(set_attr "conds" "set")
8504 (set_attr "length" "8")]
8507 (define_insn_and_split "*ior_scc_scc"
8508 [(set (match_operand:SI 0 "s_register_operand" "=r")
8509 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8510 [(match_operand:SI 1 "s_register_operand" "r")
8511 (match_operand:SI 2 "arm_add_operand" "rIL")])
8512 (match_operator:SI 6 "arm_comparison_operator"
8513 [(match_operand:SI 4 "s_register_operand" "r")
8514 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8515 (clobber (reg:CC CC_REGNUM))]
8517 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8520 "TARGET_ARM && reload_completed"
8524 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8525 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8527 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8529 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8532 [(set_attr "conds" "clob")
8533 (set_attr "length" "16")])
8535 ; If the above pattern is followed by a CMP insn, then the compare is
8536 ; redundant, since we can rework the conditional instruction that follows.
8537 (define_insn_and_split "*ior_scc_scc_cmp"
8538 [(set (match_operand 0 "dominant_cc_register" "")
8539 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8540 [(match_operand:SI 1 "s_register_operand" "r")
8541 (match_operand:SI 2 "arm_add_operand" "rIL")])
8542 (match_operator:SI 6 "arm_comparison_operator"
8543 [(match_operand:SI 4 "s_register_operand" "r")
8544 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8546 (set (match_operand:SI 7 "s_register_operand" "=r")
8547 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8548 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8551 "TARGET_ARM && reload_completed"
8555 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8556 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8558 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8560 [(set_attr "conds" "set")
8561 (set_attr "length" "16")])
8563 (define_insn_and_split "*and_scc_scc"
8564 [(set (match_operand:SI 0 "s_register_operand" "=r")
8565 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8566 [(match_operand:SI 1 "s_register_operand" "r")
8567 (match_operand:SI 2 "arm_add_operand" "rIL")])
8568 (match_operator:SI 6 "arm_comparison_operator"
8569 [(match_operand:SI 4 "s_register_operand" "r")
8570 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8571 (clobber (reg:CC CC_REGNUM))]
8573 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8576 "TARGET_ARM && reload_completed
8577 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8582 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8583 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8585 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8587 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8590 [(set_attr "conds" "clob")
8591 (set_attr "length" "16")])
8593 ; If the above pattern is followed by a CMP insn, then the compare is
8594 ; redundant, since we can rework the conditional instruction that follows.
8595 (define_insn_and_split "*and_scc_scc_cmp"
8596 [(set (match_operand 0 "dominant_cc_register" "")
8597 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8598 [(match_operand:SI 1 "s_register_operand" "r")
8599 (match_operand:SI 2 "arm_add_operand" "rIL")])
8600 (match_operator:SI 6 "arm_comparison_operator"
8601 [(match_operand:SI 4 "s_register_operand" "r")
8602 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8604 (set (match_operand:SI 7 "s_register_operand" "=r")
8605 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8606 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8609 "TARGET_ARM && reload_completed"
8613 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8614 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8616 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8618 [(set_attr "conds" "set")
8619 (set_attr "length" "16")])
8621 ;; If there is no dominance in the comparison, then we can still save an
8622 ;; instruction in the AND case, since we can know that the second compare
8623 ;; need only zero the value if false (if true, then the value is already
8625 (define_insn_and_split "*and_scc_scc_nodom"
8626 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8627 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8628 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8629 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8630 (match_operator:SI 6 "arm_comparison_operator"
8631 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8632 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8633 (clobber (reg:CC CC_REGNUM))]
8635 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8638 "TARGET_ARM && reload_completed"
8639 [(parallel [(set (match_dup 0)
8640 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8641 (clobber (reg:CC CC_REGNUM))])
8642 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8644 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8647 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8648 operands[4], operands[5]),
8650 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8652 [(set_attr "conds" "clob")
8653 (set_attr "length" "20")])
8656 [(set (reg:CC_NOOV CC_REGNUM)
8657 (compare:CC_NOOV (ior:SI
8658 (and:SI (match_operand:SI 0 "s_register_operand" "")
8660 (match_operator:SI 1 "comparison_operator"
8661 [(match_operand:SI 2 "s_register_operand" "")
8662 (match_operand:SI 3 "arm_add_operand" "")]))
8664 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8667 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8669 (set (reg:CC_NOOV CC_REGNUM)
8670 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8675 [(set (reg:CC_NOOV CC_REGNUM)
8676 (compare:CC_NOOV (ior:SI
8677 (match_operator:SI 1 "comparison_operator"
8678 [(match_operand:SI 2 "s_register_operand" "")
8679 (match_operand:SI 3 "arm_add_operand" "")])
8680 (and:SI (match_operand:SI 0 "s_register_operand" "")
8683 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8686 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8688 (set (reg:CC_NOOV CC_REGNUM)
8689 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8693 (define_insn "*negscc"
8694 [(set (match_operand:SI 0 "s_register_operand" "=r")
8695 (neg:SI (match_operator 3 "arm_comparison_operator"
8696 [(match_operand:SI 1 "s_register_operand" "r")
8697 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8698 (clobber (reg:CC CC_REGNUM))]
8701 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8702 return \"mov\\t%0, %1, asr #31\";
8704 if (GET_CODE (operands[3]) == NE)
8705 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8707 if (GET_CODE (operands[3]) == GT)
8708 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8710 output_asm_insn (\"cmp\\t%1, %2\", operands);
8711 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8712 return \"mvn%d3\\t%0, #0\";
8714 [(set_attr "conds" "clob")
8715 (set_attr "length" "12")]
8718 (define_insn "movcond"
8719 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8721 (match_operator 5 "arm_comparison_operator"
8722 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8723 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8724 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8725 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8726 (clobber (reg:CC CC_REGNUM))]
8729 if (GET_CODE (operands[5]) == LT
8730 && (operands[4] == const0_rtx))
8732 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8734 if (operands[2] == const0_rtx)
8735 return \"and\\t%0, %1, %3, asr #31\";
8736 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8738 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8740 if (operands[1] == const0_rtx)
8741 return \"bic\\t%0, %2, %3, asr #31\";
8742 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8744 /* The only case that falls through to here is when both ops 1 & 2
8748 if (GET_CODE (operands[5]) == GE
8749 && (operands[4] == const0_rtx))
8751 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8753 if (operands[2] == const0_rtx)
8754 return \"bic\\t%0, %1, %3, asr #31\";
8755 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8757 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8759 if (operands[1] == const0_rtx)
8760 return \"and\\t%0, %2, %3, asr #31\";
8761 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8763 /* The only case that falls through to here is when both ops 1 & 2
8766 if (GET_CODE (operands[4]) == CONST_INT
8767 && !const_ok_for_arm (INTVAL (operands[4])))
8768 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8770 output_asm_insn (\"cmp\\t%3, %4\", operands);
8771 if (which_alternative != 0)
8772 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8773 if (which_alternative != 1)
8774 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8777 [(set_attr "conds" "clob")
8778 (set_attr "length" "8,8,12")]
8781 (define_insn "*ifcompare_plus_move"
8782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8783 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8784 [(match_operand:SI 4 "s_register_operand" "r,r")
8785 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8787 (match_operand:SI 2 "s_register_operand" "r,r")
8788 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8789 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8790 (clobber (reg:CC CC_REGNUM))]
8793 [(set_attr "conds" "clob")
8794 (set_attr "length" "8,12")]
8797 (define_insn "*if_plus_move"
8798 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8800 (match_operator 4 "arm_comparison_operator"
8801 [(match_operand 5 "cc_register" "") (const_int 0)])
8803 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8804 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8805 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8809 sub%d4\\t%0, %2, #%n3
8810 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8811 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8812 [(set_attr "conds" "use")
8813 (set_attr "length" "4,4,8,8")
8814 (set_attr "type" "*,*,*,*")]
8817 (define_insn "*ifcompare_move_plus"
8818 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8819 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8820 [(match_operand:SI 4 "s_register_operand" "r,r")
8821 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8822 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8824 (match_operand:SI 2 "s_register_operand" "r,r")
8825 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8826 (clobber (reg:CC CC_REGNUM))]
8829 [(set_attr "conds" "clob")
8830 (set_attr "length" "8,12")]
8833 (define_insn "*if_move_plus"
8834 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8836 (match_operator 4 "arm_comparison_operator"
8837 [(match_operand 5 "cc_register" "") (const_int 0)])
8838 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8840 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8845 sub%D4\\t%0, %2, #%n3
8846 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8847 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8848 [(set_attr "conds" "use")
8849 (set_attr "length" "4,4,8,8")
8850 (set_attr "type" "*,*,*,*")]
8853 (define_insn "*ifcompare_arith_arith"
8854 [(set (match_operand:SI 0 "s_register_operand" "=r")
8855 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8856 [(match_operand:SI 5 "s_register_operand" "r")
8857 (match_operand:SI 6 "arm_add_operand" "rIL")])
8858 (match_operator:SI 8 "shiftable_operator"
8859 [(match_operand:SI 1 "s_register_operand" "r")
8860 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8861 (match_operator:SI 7 "shiftable_operator"
8862 [(match_operand:SI 3 "s_register_operand" "r")
8863 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8864 (clobber (reg:CC CC_REGNUM))]
8867 [(set_attr "conds" "clob")
8868 (set_attr "length" "12")]
8871 (define_insn "*if_arith_arith"
8872 [(set (match_operand:SI 0 "s_register_operand" "=r")
8873 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8874 [(match_operand 8 "cc_register" "") (const_int 0)])
8875 (match_operator:SI 6 "shiftable_operator"
8876 [(match_operand:SI 1 "s_register_operand" "r")
8877 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8878 (match_operator:SI 7 "shiftable_operator"
8879 [(match_operand:SI 3 "s_register_operand" "r")
8880 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8882 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8883 [(set_attr "conds" "use")
8884 (set_attr "length" "8")]
8887 (define_insn "*ifcompare_arith_move"
8888 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8889 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8890 [(match_operand:SI 2 "s_register_operand" "r,r")
8891 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8892 (match_operator:SI 7 "shiftable_operator"
8893 [(match_operand:SI 4 "s_register_operand" "r,r")
8894 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8895 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8896 (clobber (reg:CC CC_REGNUM))]
8899 /* If we have an operation where (op x 0) is the identity operation and
8900 the conditional operator is LT or GE and we are comparing against zero and
8901 everything is in registers then we can do this in two instructions. */
8902 if (operands[3] == const0_rtx
8903 && GET_CODE (operands[7]) != AND
8904 && GET_CODE (operands[5]) == REG
8905 && GET_CODE (operands[1]) == REG
8906 && REGNO (operands[1]) == REGNO (operands[4])
8907 && REGNO (operands[4]) != REGNO (operands[0]))
8909 if (GET_CODE (operands[6]) == LT)
8910 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8911 else if (GET_CODE (operands[6]) == GE)
8912 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8914 if (GET_CODE (operands[3]) == CONST_INT
8915 && !const_ok_for_arm (INTVAL (operands[3])))
8916 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8918 output_asm_insn (\"cmp\\t%2, %3\", operands);
8919 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8920 if (which_alternative != 0)
8921 return \"mov%D6\\t%0, %1\";
8924 [(set_attr "conds" "clob")
8925 (set_attr "length" "8,12")]
8928 (define_insn "*if_arith_move"
8929 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8930 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8931 [(match_operand 6 "cc_register" "") (const_int 0)])
8932 (match_operator:SI 5 "shiftable_operator"
8933 [(match_operand:SI 2 "s_register_operand" "r,r")
8934 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8935 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8939 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8940 [(set_attr "conds" "use")
8941 (set_attr "length" "4,8")
8942 (set_attr "type" "*,*")]
8945 (define_insn "*ifcompare_move_arith"
8946 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8947 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8948 [(match_operand:SI 4 "s_register_operand" "r,r")
8949 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8950 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8951 (match_operator:SI 7 "shiftable_operator"
8952 [(match_operand:SI 2 "s_register_operand" "r,r")
8953 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8954 (clobber (reg:CC CC_REGNUM))]
8957 /* If we have an operation where (op x 0) is the identity operation and
8958 the conditional operator is LT or GE and we are comparing against zero and
8959 everything is in registers then we can do this in two instructions */
8960 if (operands[5] == const0_rtx
8961 && GET_CODE (operands[7]) != AND
8962 && GET_CODE (operands[3]) == REG
8963 && GET_CODE (operands[1]) == REG
8964 && REGNO (operands[1]) == REGNO (operands[2])
8965 && REGNO (operands[2]) != REGNO (operands[0]))
8967 if (GET_CODE (operands[6]) == GE)
8968 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8969 else if (GET_CODE (operands[6]) == LT)
8970 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8973 if (GET_CODE (operands[5]) == CONST_INT
8974 && !const_ok_for_arm (INTVAL (operands[5])))
8975 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8977 output_asm_insn (\"cmp\\t%4, %5\", operands);
8979 if (which_alternative != 0)
8980 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8981 return \"%I7%D6\\t%0, %2, %3\";
8983 [(set_attr "conds" "clob")
8984 (set_attr "length" "8,12")]
8987 (define_insn "*if_move_arith"
8988 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8990 (match_operator 4 "arm_comparison_operator"
8991 [(match_operand 6 "cc_register" "") (const_int 0)])
8992 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8993 (match_operator:SI 5 "shiftable_operator"
8994 [(match_operand:SI 2 "s_register_operand" "r,r")
8995 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8999 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9000 [(set_attr "conds" "use")
9001 (set_attr "length" "4,8")
9002 (set_attr "type" "*,*")]
9005 (define_insn "*ifcompare_move_not"
9006 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9008 (match_operator 5 "arm_comparison_operator"
9009 [(match_operand:SI 3 "s_register_operand" "r,r")
9010 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9011 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9013 (match_operand:SI 2 "s_register_operand" "r,r"))))
9014 (clobber (reg:CC CC_REGNUM))]
9017 [(set_attr "conds" "clob")
9018 (set_attr "length" "8,12")]
9021 (define_insn "*if_move_not"
9022 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9024 (match_operator 4 "arm_comparison_operator"
9025 [(match_operand 3 "cc_register" "") (const_int 0)])
9026 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9027 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9031 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9032 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9033 [(set_attr "conds" "use")
9034 (set_attr "length" "4,8,8")]
9037 (define_insn "*ifcompare_not_move"
9038 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9040 (match_operator 5 "arm_comparison_operator"
9041 [(match_operand:SI 3 "s_register_operand" "r,r")
9042 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9044 (match_operand:SI 2 "s_register_operand" "r,r"))
9045 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9046 (clobber (reg:CC CC_REGNUM))]
9049 [(set_attr "conds" "clob")
9050 (set_attr "length" "8,12")]
9053 (define_insn "*if_not_move"
9054 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9056 (match_operator 4 "arm_comparison_operator"
9057 [(match_operand 3 "cc_register" "") (const_int 0)])
9058 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9059 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9063 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9064 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9065 [(set_attr "conds" "use")
9066 (set_attr "length" "4,8,8")]
9069 (define_insn "*ifcompare_shift_move"
9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9072 (match_operator 6 "arm_comparison_operator"
9073 [(match_operand:SI 4 "s_register_operand" "r,r")
9074 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9075 (match_operator:SI 7 "shift_operator"
9076 [(match_operand:SI 2 "s_register_operand" "r,r")
9077 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9078 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9079 (clobber (reg:CC CC_REGNUM))]
9082 [(set_attr "conds" "clob")
9083 (set_attr "length" "8,12")]
9086 (define_insn "*if_shift_move"
9087 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9089 (match_operator 5 "arm_comparison_operator"
9090 [(match_operand 6 "cc_register" "") (const_int 0)])
9091 (match_operator:SI 4 "shift_operator"
9092 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9093 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9094 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9098 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9099 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9100 [(set_attr "conds" "use")
9101 (set_attr "shift" "2")
9102 (set_attr "length" "4,8,8")
9103 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9104 (const_string "alu_shift")
9105 (const_string "alu_shift_reg")))]
9108 (define_insn "*ifcompare_move_shift"
9109 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9111 (match_operator 6 "arm_comparison_operator"
9112 [(match_operand:SI 4 "s_register_operand" "r,r")
9113 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9114 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9115 (match_operator:SI 7 "shift_operator"
9116 [(match_operand:SI 2 "s_register_operand" "r,r")
9117 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9118 (clobber (reg:CC CC_REGNUM))]
9121 [(set_attr "conds" "clob")
9122 (set_attr "length" "8,12")]
9125 (define_insn "*if_move_shift"
9126 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9128 (match_operator 5 "arm_comparison_operator"
9129 [(match_operand 6 "cc_register" "") (const_int 0)])
9130 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9131 (match_operator:SI 4 "shift_operator"
9132 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9133 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9137 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9138 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9139 [(set_attr "conds" "use")
9140 (set_attr "shift" "2")
9141 (set_attr "length" "4,8,8")
9142 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9143 (const_string "alu_shift")
9144 (const_string "alu_shift_reg")))]
9147 (define_insn "*ifcompare_shift_shift"
9148 [(set (match_operand:SI 0 "s_register_operand" "=r")
9150 (match_operator 7 "arm_comparison_operator"
9151 [(match_operand:SI 5 "s_register_operand" "r")
9152 (match_operand:SI 6 "arm_add_operand" "rIL")])
9153 (match_operator:SI 8 "shift_operator"
9154 [(match_operand:SI 1 "s_register_operand" "r")
9155 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9156 (match_operator:SI 9 "shift_operator"
9157 [(match_operand:SI 3 "s_register_operand" "r")
9158 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9159 (clobber (reg:CC CC_REGNUM))]
9162 [(set_attr "conds" "clob")
9163 (set_attr "length" "12")]
9166 (define_insn "*if_shift_shift"
9167 [(set (match_operand:SI 0 "s_register_operand" "=r")
9169 (match_operator 5 "arm_comparison_operator"
9170 [(match_operand 8 "cc_register" "") (const_int 0)])
9171 (match_operator:SI 6 "shift_operator"
9172 [(match_operand:SI 1 "s_register_operand" "r")
9173 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9174 (match_operator:SI 7 "shift_operator"
9175 [(match_operand:SI 3 "s_register_operand" "r")
9176 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9178 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9179 [(set_attr "conds" "use")
9180 (set_attr "shift" "1")
9181 (set_attr "length" "8")
9182 (set (attr "type") (if_then_else
9183 (and (match_operand 2 "const_int_operand" "")
9184 (match_operand 4 "const_int_operand" ""))
9185 (const_string "alu_shift")
9186 (const_string "alu_shift_reg")))]
9189 (define_insn "*ifcompare_not_arith"
9190 [(set (match_operand:SI 0 "s_register_operand" "=r")
9192 (match_operator 6 "arm_comparison_operator"
9193 [(match_operand:SI 4 "s_register_operand" "r")
9194 (match_operand:SI 5 "arm_add_operand" "rIL")])
9195 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9196 (match_operator:SI 7 "shiftable_operator"
9197 [(match_operand:SI 2 "s_register_operand" "r")
9198 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9199 (clobber (reg:CC CC_REGNUM))]
9202 [(set_attr "conds" "clob")
9203 (set_attr "length" "12")]
9206 (define_insn "*if_not_arith"
9207 [(set (match_operand:SI 0 "s_register_operand" "=r")
9209 (match_operator 5 "arm_comparison_operator"
9210 [(match_operand 4 "cc_register" "") (const_int 0)])
9211 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9212 (match_operator:SI 6 "shiftable_operator"
9213 [(match_operand:SI 2 "s_register_operand" "r")
9214 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9216 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9217 [(set_attr "conds" "use")
9218 (set_attr "length" "8")]
9221 (define_insn "*ifcompare_arith_not"
9222 [(set (match_operand:SI 0 "s_register_operand" "=r")
9224 (match_operator 6 "arm_comparison_operator"
9225 [(match_operand:SI 4 "s_register_operand" "r")
9226 (match_operand:SI 5 "arm_add_operand" "rIL")])
9227 (match_operator:SI 7 "shiftable_operator"
9228 [(match_operand:SI 2 "s_register_operand" "r")
9229 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9230 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9231 (clobber (reg:CC CC_REGNUM))]
9234 [(set_attr "conds" "clob")
9235 (set_attr "length" "12")]
9238 (define_insn "*if_arith_not"
9239 [(set (match_operand:SI 0 "s_register_operand" "=r")
9241 (match_operator 5 "arm_comparison_operator"
9242 [(match_operand 4 "cc_register" "") (const_int 0)])
9243 (match_operator:SI 6 "shiftable_operator"
9244 [(match_operand:SI 2 "s_register_operand" "r")
9245 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9246 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9248 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9249 [(set_attr "conds" "use")
9250 (set_attr "length" "8")]
9253 (define_insn "*ifcompare_neg_move"
9254 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9256 (match_operator 5 "arm_comparison_operator"
9257 [(match_operand:SI 3 "s_register_operand" "r,r")
9258 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9259 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9260 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9261 (clobber (reg:CC CC_REGNUM))]
9264 [(set_attr "conds" "clob")
9265 (set_attr "length" "8,12")]
9268 (define_insn "*if_neg_move"
9269 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9271 (match_operator 4 "arm_comparison_operator"
9272 [(match_operand 3 "cc_register" "") (const_int 0)])
9273 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9274 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9278 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9279 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9280 [(set_attr "conds" "use")
9281 (set_attr "length" "4,8,8")]
9284 (define_insn "*ifcompare_move_neg"
9285 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9287 (match_operator 5 "arm_comparison_operator"
9288 [(match_operand:SI 3 "s_register_operand" "r,r")
9289 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9290 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9291 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9292 (clobber (reg:CC CC_REGNUM))]
9295 [(set_attr "conds" "clob")
9296 (set_attr "length" "8,12")]
9299 (define_insn "*if_move_neg"
9300 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9302 (match_operator 4 "arm_comparison_operator"
9303 [(match_operand 3 "cc_register" "") (const_int 0)])
9304 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9305 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9309 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9310 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9311 [(set_attr "conds" "use")
9312 (set_attr "length" "4,8,8")]
9315 (define_insn "*arith_adjacentmem"
9316 [(set (match_operand:SI 0 "s_register_operand" "=r")
9317 (match_operator:SI 1 "shiftable_operator"
9318 [(match_operand:SI 2 "memory_operand" "m")
9319 (match_operand:SI 3 "memory_operand" "m")]))
9320 (clobber (match_scratch:SI 4 "=r"))]
9321 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9327 HOST_WIDE_INT val1 = 0, val2 = 0;
9329 if (REGNO (operands[0]) > REGNO (operands[4]))
9331 ldm[1] = operands[4];
9332 ldm[2] = operands[0];
9336 ldm[1] = operands[0];
9337 ldm[2] = operands[4];
9340 base_reg = XEXP (operands[2], 0);
9342 if (!REG_P (base_reg))
9344 val1 = INTVAL (XEXP (base_reg, 1));
9345 base_reg = XEXP (base_reg, 0);
9348 if (!REG_P (XEXP (operands[3], 0)))
9349 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9351 arith[0] = operands[0];
9352 arith[3] = operands[1];
9366 if (val1 !=0 && val2 != 0)
9368 if (val1 == 4 || val2 == 4)
9369 /* Other val must be 8, since we know they are adjacent and neither
9371 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9376 ldm[0] = ops[0] = operands[4];
9378 ops[2] = GEN_INT (val1);
9379 output_add_immediate (ops);
9381 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9383 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9389 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9391 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9396 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9398 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9400 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9403 [(set_attr "length" "12")
9404 (set_attr "predicable" "yes")
9405 (set_attr "type" "load1")]
9408 ;; the arm can support extended pre-inc instructions
9410 ;; In all these cases, we use operands 0 and 1 for the register being
9411 ;; incremented because those are the operands that local-alloc will
9412 ;; tie and these are the pair most likely to be tieable (and the ones
9413 ;; that will benefit the most).
9415 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9416 ;; elimination will cause too many headaches.
9418 (define_insn "*strqi_preinc"
9419 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9420 (match_operand:SI 2 "index_operand" "rJ")))
9421 (match_operand:QI 3 "s_register_operand" "r"))
9422 (set (match_operand:SI 0 "s_register_operand" "=r")
9423 (plus:SI (match_dup 1) (match_dup 2)))]
9425 && !arm_eliminable_register (operands[0])
9426 && !arm_eliminable_register (operands[1])
9427 && !arm_eliminable_register (operands[2])"
9428 "str%?b\\t%3, [%0, %2]!"
9429 [(set_attr "type" "store1")
9430 (set_attr "predicable" "yes")]
9433 (define_insn "*strqi_predec"
9434 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9435 (match_operand:SI 2 "s_register_operand" "r")))
9436 (match_operand:QI 3 "s_register_operand" "r"))
9437 (set (match_operand:SI 0 "s_register_operand" "=r")
9438 (minus:SI (match_dup 1) (match_dup 2)))]
9440 && !arm_eliminable_register (operands[0])
9441 && !arm_eliminable_register (operands[1])
9442 && !arm_eliminable_register (operands[2])"
9443 "str%?b\\t%3, [%0, -%2]!"
9444 [(set_attr "type" "store1")
9445 (set_attr "predicable" "yes")]
9448 (define_insn "*loadqi_preinc"
9449 [(set (match_operand:QI 3 "s_register_operand" "=r")
9450 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9451 (match_operand:SI 2 "index_operand" "rJ"))))
9452 (set (match_operand:SI 0 "s_register_operand" "=r")
9453 (plus:SI (match_dup 1) (match_dup 2)))]
9455 && !arm_eliminable_register (operands[0])
9456 && !arm_eliminable_register (operands[1])
9457 && !arm_eliminable_register (operands[2])"
9458 "ldr%?b\\t%3, [%0, %2]!"
9459 [(set_attr "type" "load_byte")
9460 (set_attr "predicable" "yes")]
9463 (define_insn "*loadqi_predec"
9464 [(set (match_operand:QI 3 "s_register_operand" "=r")
9465 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9466 (match_operand:SI 2 "s_register_operand" "r"))))
9467 (set (match_operand:SI 0 "s_register_operand" "=r")
9468 (minus:SI (match_dup 1) (match_dup 2)))]
9470 && !arm_eliminable_register (operands[0])
9471 && !arm_eliminable_register (operands[1])
9472 && !arm_eliminable_register (operands[2])"
9473 "ldr%?b\\t%3, [%0, -%2]!"
9474 [(set_attr "type" "load_byte")
9475 (set_attr "predicable" "yes")]
9478 (define_insn "*loadqisi_preinc"
9479 [(set (match_operand:SI 3 "s_register_operand" "=r")
9481 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9482 (match_operand:SI 2 "index_operand" "rJ")))))
9483 (set (match_operand:SI 0 "s_register_operand" "=r")
9484 (plus:SI (match_dup 1) (match_dup 2)))]
9486 && !arm_eliminable_register (operands[0])
9487 && !arm_eliminable_register (operands[1])
9488 && !arm_eliminable_register (operands[2])"
9489 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9490 [(set_attr "type" "load_byte")
9491 (set_attr "predicable" "yes")]
9494 (define_insn "*loadqisi_predec"
9495 [(set (match_operand:SI 3 "s_register_operand" "=r")
9497 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9498 (match_operand:SI 2 "s_register_operand" "r")))))
9499 (set (match_operand:SI 0 "s_register_operand" "=r")
9500 (minus:SI (match_dup 1) (match_dup 2)))]
9502 && !arm_eliminable_register (operands[0])
9503 && !arm_eliminable_register (operands[1])
9504 && !arm_eliminable_register (operands[2])"
9505 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9506 [(set_attr "type" "load_byte")
9507 (set_attr "predicable" "yes")]
9510 (define_insn "*strsi_preinc"
9511 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9512 (match_operand:SI 2 "index_operand" "rJ")))
9513 (match_operand:SI 3 "s_register_operand" "r"))
9514 (set (match_operand:SI 0 "s_register_operand" "=r")
9515 (plus:SI (match_dup 1) (match_dup 2)))]
9517 && !arm_eliminable_register (operands[0])
9518 && !arm_eliminable_register (operands[1])
9519 && !arm_eliminable_register (operands[2])"
9520 "str%?\\t%3, [%0, %2]!"
9521 [(set_attr "type" "store1")
9522 (set_attr "predicable" "yes")]
9525 (define_insn "*strsi_predec"
9526 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9527 (match_operand:SI 2 "s_register_operand" "r")))
9528 (match_operand:SI 3 "s_register_operand" "r"))
9529 (set (match_operand:SI 0 "s_register_operand" "=r")
9530 (minus:SI (match_dup 1) (match_dup 2)))]
9532 && !arm_eliminable_register (operands[0])
9533 && !arm_eliminable_register (operands[1])
9534 && !arm_eliminable_register (operands[2])"
9535 "str%?\\t%3, [%0, -%2]!"
9536 [(set_attr "type" "store1")
9537 (set_attr "predicable" "yes")]
9540 (define_insn "*loadsi_preinc"
9541 [(set (match_operand:SI 3 "s_register_operand" "=r")
9542 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9543 (match_operand:SI 2 "index_operand" "rJ"))))
9544 (set (match_operand:SI 0 "s_register_operand" "=r")
9545 (plus:SI (match_dup 1) (match_dup 2)))]
9547 && !arm_eliminable_register (operands[0])
9548 && !arm_eliminable_register (operands[1])
9549 && !arm_eliminable_register (operands[2])"
9550 "ldr%?\\t%3, [%0, %2]!"
9551 [(set_attr "type" "load1")
9552 (set_attr "predicable" "yes")]
9555 (define_insn "*loadsi_predec"
9556 [(set (match_operand:SI 3 "s_register_operand" "=r")
9557 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9558 (match_operand:SI 2 "s_register_operand" "r"))))
9559 (set (match_operand:SI 0 "s_register_operand" "=r")
9560 (minus:SI (match_dup 1) (match_dup 2)))]
9562 && !arm_eliminable_register (operands[0])
9563 && !arm_eliminable_register (operands[1])
9564 && !arm_eliminable_register (operands[2])"
9565 "ldr%?\\t%3, [%0, -%2]!"
9566 [(set_attr "type" "load1")
9567 (set_attr "predicable" "yes")]
9570 (define_insn "*strqi_shiftpreinc"
9571 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9572 [(match_operand:SI 3 "s_register_operand" "r")
9573 (match_operand:SI 4 "const_shift_operand" "n")])
9574 (match_operand:SI 1 "s_register_operand" "0")))
9575 (match_operand:QI 5 "s_register_operand" "r"))
9576 (set (match_operand:SI 0 "s_register_operand" "=r")
9577 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9580 && !arm_eliminable_register (operands[0])
9581 && !arm_eliminable_register (operands[1])
9582 && !arm_eliminable_register (operands[3])"
9583 "str%?b\\t%5, [%0, %3%S2]!"
9584 [(set_attr "type" "store1")
9585 (set_attr "predicable" "yes")]
9588 (define_insn "*strqi_shiftpredec"
9589 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9590 (match_operator:SI 2 "shift_operator"
9591 [(match_operand:SI 3 "s_register_operand" "r")
9592 (match_operand:SI 4 "const_shift_operand" "n")])))
9593 (match_operand:QI 5 "s_register_operand" "r"))
9594 (set (match_operand:SI 0 "s_register_operand" "=r")
9595 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9598 && !arm_eliminable_register (operands[0])
9599 && !arm_eliminable_register (operands[1])
9600 && !arm_eliminable_register (operands[3])"
9601 "str%?b\\t%5, [%0, -%3%S2]!"
9602 [(set_attr "type" "store1")
9603 (set_attr "predicable" "yes")]
9606 (define_insn "*loadqi_shiftpreinc"
9607 [(set (match_operand:QI 5 "s_register_operand" "=r")
9608 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9609 [(match_operand:SI 3 "s_register_operand" "r")
9610 (match_operand:SI 4 "const_shift_operand" "n")])
9611 (match_operand:SI 1 "s_register_operand" "0"))))
9612 (set (match_operand:SI 0 "s_register_operand" "=r")
9613 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9616 && !arm_eliminable_register (operands[0])
9617 && !arm_eliminable_register (operands[1])
9618 && !arm_eliminable_register (operands[3])"
9619 "ldr%?b\\t%5, [%0, %3%S2]!"
9620 [(set_attr "type" "load_byte")
9621 (set_attr "predicable" "yes")]
9624 (define_insn "*loadqi_shiftpredec"
9625 [(set (match_operand:QI 5 "s_register_operand" "=r")
9626 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9627 (match_operator:SI 2 "shift_operator"
9628 [(match_operand:SI 3 "s_register_operand" "r")
9629 (match_operand:SI 4 "const_shift_operand" "n")]))))
9630 (set (match_operand:SI 0 "s_register_operand" "=r")
9631 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9634 && !arm_eliminable_register (operands[0])
9635 && !arm_eliminable_register (operands[1])
9636 && !arm_eliminable_register (operands[3])"
9637 "ldr%?b\\t%5, [%0, -%3%S2]!"
9638 [(set_attr "type" "load_byte")
9639 (set_attr "predicable" "yes")]
9642 (define_insn "*strsi_shiftpreinc"
9643 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9644 [(match_operand:SI 3 "s_register_operand" "r")
9645 (match_operand:SI 4 "const_shift_operand" "n")])
9646 (match_operand:SI 1 "s_register_operand" "0")))
9647 (match_operand:SI 5 "s_register_operand" "r"))
9648 (set (match_operand:SI 0 "s_register_operand" "=r")
9649 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9652 && !arm_eliminable_register (operands[0])
9653 && !arm_eliminable_register (operands[1])
9654 && !arm_eliminable_register (operands[3])"
9655 "str%?\\t%5, [%0, %3%S2]!"
9656 [(set_attr "type" "store1")
9657 (set_attr "predicable" "yes")]
9660 (define_insn "*strsi_shiftpredec"
9661 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9662 (match_operator:SI 2 "shift_operator"
9663 [(match_operand:SI 3 "s_register_operand" "r")
9664 (match_operand:SI 4 "const_shift_operand" "n")])))
9665 (match_operand:SI 5 "s_register_operand" "r"))
9666 (set (match_operand:SI 0 "s_register_operand" "=r")
9667 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9670 && !arm_eliminable_register (operands[0])
9671 && !arm_eliminable_register (operands[1])
9672 && !arm_eliminable_register (operands[3])"
9673 "str%?\\t%5, [%0, -%3%S2]!"
9674 [(set_attr "type" "store1")
9675 (set_attr "predicable" "yes")]
9678 (define_insn "*loadsi_shiftpreinc"
9679 [(set (match_operand:SI 5 "s_register_operand" "=r")
9680 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9681 [(match_operand:SI 3 "s_register_operand" "r")
9682 (match_operand:SI 4 "const_shift_operand" "n")])
9683 (match_operand:SI 1 "s_register_operand" "0"))))
9684 (set (match_operand:SI 0 "s_register_operand" "=r")
9685 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9688 && !arm_eliminable_register (operands[0])
9689 && !arm_eliminable_register (operands[1])
9690 && !arm_eliminable_register (operands[3])"
9691 "ldr%?\\t%5, [%0, %3%S2]!"
9692 [(set_attr "type" "load1")
9693 (set_attr "predicable" "yes")]
9696 (define_insn "*loadsi_shiftpredec"
9697 [(set (match_operand:SI 5 "s_register_operand" "=r")
9698 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9699 (match_operator:SI 2 "shift_operator"
9700 [(match_operand:SI 3 "s_register_operand" "r")
9701 (match_operand:SI 4 "const_shift_operand" "n")]))))
9702 (set (match_operand:SI 0 "s_register_operand" "=r")
9703 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9706 && !arm_eliminable_register (operands[0])
9707 && !arm_eliminable_register (operands[1])
9708 && !arm_eliminable_register (operands[3])"
9709 "ldr%?\\t%5, [%0, -%3%S2]!"
9710 [(set_attr "type" "load1")
9711 (set_attr "predicable" "yes")])
9713 ; It can also support extended post-inc expressions, but combine doesn't
9715 ; It doesn't seem worth adding peepholes for anything but the most common
9716 ; cases since, unlike combine, the increment must immediately follow the load
9717 ; for this pattern to match.
9718 ; We must watch to see that the source/destination register isn't also the
9719 ; same as the base address register, and that if the index is a register,
9720 ; that it is not the same as the base address register. In such cases the
9721 ; instruction that we would generate would have UNPREDICTABLE behavior so
9725 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9726 (match_operand:QI 2 "s_register_operand" "r"))
9728 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9730 && (REGNO (operands[2]) != REGNO (operands[0]))
9731 && (GET_CODE (operands[1]) != REG
9732 || (REGNO (operands[1]) != REGNO (operands[0])))"
9733 "str%?b\\t%2, [%0], %1"
9737 [(set (match_operand:QI 0 "s_register_operand" "=r")
9738 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9740 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9742 && REGNO (operands[0]) != REGNO(operands[1])
9743 && (GET_CODE (operands[2]) != REG
9744 || REGNO(operands[0]) != REGNO (operands[2]))"
9745 "ldr%?b\\t%0, [%1], %2"
9749 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9750 (match_operand:SI 2 "s_register_operand" "r"))
9752 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9754 && (REGNO (operands[2]) != REGNO (operands[0]))
9755 && (GET_CODE (operands[1]) != REG
9756 || (REGNO (operands[1]) != REGNO (operands[0])))"
9757 "str%?\\t%2, [%0], %1"
9761 [(set (match_operand:SI 0 "s_register_operand" "=r")
9762 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9764 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9766 && REGNO (operands[0]) != REGNO(operands[1])
9767 && (GET_CODE (operands[2]) != REG
9768 || REGNO(operands[0]) != REGNO (operands[2]))"
9769 "ldr%?\\t%0, [%1], %2"
9773 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9774 (match_operand:SI 1 "index_operand" "rJ")))
9775 (match_operand:QI 2 "s_register_operand" "r"))
9776 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9778 && (REGNO (operands[2]) != REGNO (operands[0]))
9779 && (GET_CODE (operands[1]) != REG
9780 || (REGNO (operands[1]) != REGNO (operands[0])))"
9781 "str%?b\\t%2, [%0, %1]!"
9785 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9786 [(match_operand:SI 0 "s_register_operand" "r")
9787 (match_operand:SI 1 "const_int_operand" "n")])
9788 (match_operand:SI 2 "s_register_operand" "+r")))
9789 (match_operand:QI 3 "s_register_operand" "r"))
9790 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9793 && (REGNO (operands[3]) != REGNO (operands[2]))
9794 && (REGNO (operands[0]) != REGNO (operands[2]))"
9795 "str%?b\\t%3, [%2, %0%S4]!"
9798 ; This pattern is never tried by combine, so do it as a peephole
9801 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9802 (match_operand:SI 1 "arm_general_register_operand" ""))
9803 (set (reg:CC CC_REGNUM)
9804 (compare:CC (match_dup 1) (const_int 0)))]
9806 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9807 (set (match_dup 0) (match_dup 1))])]
9811 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9812 ; reversed, check that the memory references aren't volatile.
9815 [(set (match_operand:SI 0 "s_register_operand" "=r")
9816 (match_operand:SI 4 "memory_operand" "m"))
9817 (set (match_operand:SI 1 "s_register_operand" "=r")
9818 (match_operand:SI 5 "memory_operand" "m"))
9819 (set (match_operand:SI 2 "s_register_operand" "=r")
9820 (match_operand:SI 6 "memory_operand" "m"))
9821 (set (match_operand:SI 3 "s_register_operand" "=r")
9822 (match_operand:SI 7 "memory_operand" "m"))]
9823 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9825 return emit_ldm_seq (operands, 4);
9830 [(set (match_operand:SI 0 "s_register_operand" "=r")
9831 (match_operand:SI 3 "memory_operand" "m"))
9832 (set (match_operand:SI 1 "s_register_operand" "=r")
9833 (match_operand:SI 4 "memory_operand" "m"))
9834 (set (match_operand:SI 2 "s_register_operand" "=r")
9835 (match_operand:SI 5 "memory_operand" "m"))]
9836 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9838 return emit_ldm_seq (operands, 3);
9843 [(set (match_operand:SI 0 "s_register_operand" "=r")
9844 (match_operand:SI 2 "memory_operand" "m"))
9845 (set (match_operand:SI 1 "s_register_operand" "=r")
9846 (match_operand:SI 3 "memory_operand" "m"))]
9847 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9849 return emit_ldm_seq (operands, 2);
9854 [(set (match_operand:SI 4 "memory_operand" "=m")
9855 (match_operand:SI 0 "s_register_operand" "r"))
9856 (set (match_operand:SI 5 "memory_operand" "=m")
9857 (match_operand:SI 1 "s_register_operand" "r"))
9858 (set (match_operand:SI 6 "memory_operand" "=m")
9859 (match_operand:SI 2 "s_register_operand" "r"))
9860 (set (match_operand:SI 7 "memory_operand" "=m")
9861 (match_operand:SI 3 "s_register_operand" "r"))]
9862 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9864 return emit_stm_seq (operands, 4);
9869 [(set (match_operand:SI 3 "memory_operand" "=m")
9870 (match_operand:SI 0 "s_register_operand" "r"))
9871 (set (match_operand:SI 4 "memory_operand" "=m")
9872 (match_operand:SI 1 "s_register_operand" "r"))
9873 (set (match_operand:SI 5 "memory_operand" "=m")
9874 (match_operand:SI 2 "s_register_operand" "r"))]
9875 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9877 return emit_stm_seq (operands, 3);
9882 [(set (match_operand:SI 2 "memory_operand" "=m")
9883 (match_operand:SI 0 "s_register_operand" "r"))
9884 (set (match_operand:SI 3 "memory_operand" "=m")
9885 (match_operand:SI 1 "s_register_operand" "r"))]
9886 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9888 return emit_stm_seq (operands, 2);
9893 [(set (match_operand:SI 0 "s_register_operand" "")
9894 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9896 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9897 [(match_operand:SI 3 "s_register_operand" "")
9898 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9899 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9901 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9902 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9907 ;; This split can be used because CC_Z mode implies that the following
9908 ;; branch will be an equality, or an unsigned inequality, so the sign
9909 ;; extension is not needed.
9912 [(set (reg:CC_Z CC_REGNUM)
9914 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9916 (match_operand 1 "const_int_operand" "")))
9917 (clobber (match_scratch:SI 2 ""))]
9919 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9920 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9921 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9922 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9924 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9928 (define_expand "prologue"
9929 [(clobber (const_int 0))]
9932 arm_expand_prologue ();
9934 thumb_expand_prologue ();
9939 (define_expand "epilogue"
9940 [(clobber (const_int 0))]
9943 if (current_function_calls_eh_return)
9944 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9946 thumb_expand_epilogue ();
9947 else if (USE_RETURN_INSN (FALSE))
9949 emit_jump_insn (gen_return ());
9952 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9954 gen_rtx_RETURN (VOIDmode)),
9960 ;; Note - although unspec_volatile's USE all hard registers,
9961 ;; USEs are ignored after relaod has completed. Thus we need
9962 ;; to add an unspec of the link register to ensure that flow
9963 ;; does not think that it is unused by the sibcall branch that
9964 ;; will replace the standard function epilogue.
9965 (define_insn "sibcall_epilogue"
9966 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9967 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9970 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9971 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9972 return arm_output_epilogue (next_nonnote_insn (insn));
9974 ;; Length is absolute worst case
9975 [(set_attr "length" "44")
9976 (set_attr "type" "block")
9977 ;; We don't clobber the conditions, but the potential length of this
9978 ;; operation is sufficient to make conditionalizing the sequence
9979 ;; unlikely to be profitable.
9980 (set_attr "conds" "clob")]
9983 (define_insn "*epilogue_insns"
9984 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9988 return arm_output_epilogue (NULL);
9989 else /* TARGET_THUMB */
9990 return thumb_unexpanded_epilogue ();
9992 ; Length is absolute worst case
9993 [(set_attr "length" "44")
9994 (set_attr "type" "block")
9995 ;; We don't clobber the conditions, but the potential length of this
9996 ;; operation is sufficient to make conditionalizing the sequence
9997 ;; unlikely to be profitable.
9998 (set_attr "conds" "clob")]
10001 (define_expand "eh_epilogue"
10002 [(use (match_operand:SI 0 "register_operand" ""))
10003 (use (match_operand:SI 1 "register_operand" ""))
10004 (use (match_operand:SI 2 "register_operand" ""))]
10008 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10009 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10011 rtx ra = gen_rtx_REG (Pmode, 2);
10013 emit_move_insn (ra, operands[2]);
10016 /* This is a hack -- we may have crystalized the function type too
10018 cfun->machine->func_type = 0;
10022 ;; This split is only used during output to reduce the number of patterns
10023 ;; that need assembler instructions adding to them. We allowed the setting
10024 ;; of the conditions to be implicit during rtl generation so that
10025 ;; the conditional compare patterns would work. However this conflicts to
10026 ;; some extent with the conditional data operations, so we have to split them
10030 [(set (match_operand:SI 0 "s_register_operand" "")
10031 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10032 [(match_operand 2 "" "") (match_operand 3 "" "")])
10034 (match_operand 4 "" "")))
10035 (clobber (reg:CC CC_REGNUM))]
10036 "TARGET_ARM && reload_completed"
10037 [(set (match_dup 5) (match_dup 6))
10038 (cond_exec (match_dup 7)
10039 (set (match_dup 0) (match_dup 4)))]
10042 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10043 operands[2], operands[3]);
10044 enum rtx_code rc = GET_CODE (operands[1]);
10046 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10047 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10048 if (mode == CCFPmode || mode == CCFPEmode)
10049 rc = reverse_condition_maybe_unordered (rc);
10051 rc = reverse_condition (rc);
10053 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10058 [(set (match_operand:SI 0 "s_register_operand" "")
10059 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10060 [(match_operand 2 "" "") (match_operand 3 "" "")])
10061 (match_operand 4 "" "")
10063 (clobber (reg:CC CC_REGNUM))]
10064 "TARGET_ARM && reload_completed"
10065 [(set (match_dup 5) (match_dup 6))
10066 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10067 (set (match_dup 0) (match_dup 4)))]
10070 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10071 operands[2], operands[3]);
10073 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10074 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10079 [(set (match_operand:SI 0 "s_register_operand" "")
10080 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10081 [(match_operand 2 "" "") (match_operand 3 "" "")])
10082 (match_operand 4 "" "")
10083 (match_operand 5 "" "")))
10084 (clobber (reg:CC CC_REGNUM))]
10085 "TARGET_ARM && reload_completed"
10086 [(set (match_dup 6) (match_dup 7))
10087 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10088 (set (match_dup 0) (match_dup 4)))
10089 (cond_exec (match_dup 8)
10090 (set (match_dup 0) (match_dup 5)))]
10093 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10094 operands[2], operands[3]);
10095 enum rtx_code rc = GET_CODE (operands[1]);
10097 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10098 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10099 if (mode == CCFPmode || mode == CCFPEmode)
10100 rc = reverse_condition_maybe_unordered (rc);
10102 rc = reverse_condition (rc);
10104 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10109 [(set (match_operand:SI 0 "s_register_operand" "")
10110 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10111 [(match_operand:SI 2 "s_register_operand" "")
10112 (match_operand:SI 3 "arm_add_operand" "")])
10113 (match_operand:SI 4 "arm_rhs_operand" "")
10115 (match_operand:SI 5 "s_register_operand" ""))))
10116 (clobber (reg:CC CC_REGNUM))]
10117 "TARGET_ARM && reload_completed"
10118 [(set (match_dup 6) (match_dup 7))
10119 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10120 (set (match_dup 0) (match_dup 4)))
10121 (cond_exec (match_dup 8)
10122 (set (match_dup 0) (not:SI (match_dup 5))))]
10125 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10126 operands[2], operands[3]);
10127 enum rtx_code rc = GET_CODE (operands[1]);
10129 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10130 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10131 if (mode == CCFPmode || mode == CCFPEmode)
10132 rc = reverse_condition_maybe_unordered (rc);
10134 rc = reverse_condition (rc);
10136 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10140 (define_insn "*cond_move_not"
10141 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10142 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10143 [(match_operand 3 "cc_register" "") (const_int 0)])
10144 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10146 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10150 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10151 [(set_attr "conds" "use")
10152 (set_attr "length" "4,8")]
10155 ;; The next two patterns occur when an AND operation is followed by a
10156 ;; scc insn sequence
10158 (define_insn "*sign_extract_onebit"
10159 [(set (match_operand:SI 0 "s_register_operand" "=r")
10160 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10162 (match_operand:SI 2 "const_int_operand" "n")))
10163 (clobber (reg:CC CC_REGNUM))]
10166 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10167 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10168 return \"mvnne\\t%0, #0\";
10170 [(set_attr "conds" "clob")
10171 (set_attr "length" "8")]
10174 (define_insn "*not_signextract_onebit"
10175 [(set (match_operand:SI 0 "s_register_operand" "=r")
10177 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10179 (match_operand:SI 2 "const_int_operand" "n"))))
10180 (clobber (reg:CC CC_REGNUM))]
10183 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10184 output_asm_insn (\"tst\\t%1, %2\", operands);
10185 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10186 return \"movne\\t%0, #0\";
10188 [(set_attr "conds" "clob")
10189 (set_attr "length" "12")]
10192 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10193 ;; expressions. For simplicity, the first register is also in the unspec
10195 (define_insn "*push_multi"
10196 [(match_parallel 2 "multi_register_push"
10197 [(set (match_operand:BLK 0 "memory_operand" "=m")
10198 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10199 UNSPEC_PUSH_MULT))])]
10203 int num_saves = XVECLEN (operands[2], 0);
10205 /* For the StrongARM at least it is faster to
10206 use STR to store only a single register. */
10207 if (num_saves == 1)
10208 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10214 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10216 for (i = 1; i < num_saves; i++)
10218 strcat (pattern, \", %|\");
10220 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10223 strcat (pattern, \"}\");
10224 output_asm_insn (pattern, operands);
10229 [(set_attr "type" "store4")]
10232 (define_insn "stack_tie"
10233 [(set (mem:BLK (scratch))
10234 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10235 (match_operand:SI 1 "s_register_operand" "r")]
10239 [(set_attr "length" "0")]
10242 ;; Similarly for the floating point registers
10243 (define_insn "*push_fp_multi"
10244 [(match_parallel 2 "multi_register_push"
10245 [(set (match_operand:BLK 0 "memory_operand" "=m")
10246 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10247 UNSPEC_PUSH_MULT))])]
10248 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10253 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10254 output_asm_insn (pattern, operands);
10257 [(set_attr "type" "f_store")]
10260 ;; Special patterns for dealing with the constant pool
10262 (define_insn "align_4"
10263 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10266 assemble_align (32);
10271 (define_insn "align_8"
10272 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10275 assemble_align (64);
10280 (define_insn "consttable_end"
10281 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10284 making_const_table = FALSE;
10289 (define_insn "consttable_1"
10290 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10293 making_const_table = TRUE;
10294 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10295 assemble_zeros (3);
10298 [(set_attr "length" "4")]
10301 (define_insn "consttable_2"
10302 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10305 making_const_table = TRUE;
10306 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10307 assemble_zeros (2);
10310 [(set_attr "length" "4")]
10313 (define_insn "consttable_4"
10314 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10318 making_const_table = TRUE;
10319 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10324 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10325 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10329 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10334 [(set_attr "length" "4")]
10337 (define_insn "consttable_8"
10338 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10342 making_const_table = TRUE;
10343 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10348 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10349 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10353 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10358 [(set_attr "length" "8")]
10361 ;; Miscellaneous Thumb patterns
10363 (define_expand "tablejump"
10364 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10365 (use (label_ref (match_operand 1 "" "")))])]
10370 /* Hopefully, CSE will eliminate this copy. */
10371 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10372 rtx reg2 = gen_reg_rtx (SImode);
10374 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10375 operands[0] = reg2;
10380 ;; NB never uses BX.
10381 (define_insn "*thumb_tablejump"
10382 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10383 (use (label_ref (match_operand 1 "" "")))]
10386 [(set_attr "length" "2")]
10389 ;; V5 Instructions,
10391 (define_insn "clzsi2"
10392 [(set (match_operand:SI 0 "s_register_operand" "=r")
10393 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10394 "TARGET_ARM && arm_arch5"
10396 [(set_attr "predicable" "yes")])
10398 (define_expand "ffssi2"
10399 [(set (match_operand:SI 0 "s_register_operand" "")
10400 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10401 "TARGET_ARM && arm_arch5"
10406 t1 = gen_reg_rtx (SImode);
10407 t2 = gen_reg_rtx (SImode);
10408 t3 = gen_reg_rtx (SImode);
10410 emit_insn (gen_negsi2 (t1, operands[1]));
10411 emit_insn (gen_andsi3 (t2, operands[1], t1));
10412 emit_insn (gen_clzsi2 (t3, t2));
10413 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10418 (define_expand "ctzsi2"
10419 [(set (match_operand:SI 0 "s_register_operand" "")
10420 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10421 "TARGET_ARM && arm_arch5"
10426 t1 = gen_reg_rtx (SImode);
10427 t2 = gen_reg_rtx (SImode);
10428 t3 = gen_reg_rtx (SImode);
10430 emit_insn (gen_negsi2 (t1, operands[1]));
10431 emit_insn (gen_andsi3 (t2, operands[1], t1));
10432 emit_insn (gen_clzsi2 (t3, t2));
10433 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10438 ;; V5E instructions.
10440 (define_insn "prefetch"
10441 [(prefetch (match_operand:SI 0 "address_operand" "p")
10442 (match_operand:SI 1 "" "")
10443 (match_operand:SI 2 "" ""))]
10444 "TARGET_ARM && arm_arch5e"
10447 ;; General predication pattern
10450 [(match_operator 0 "arm_comparison_operator"
10451 [(match_operand 1 "cc_register" "")
10457 (define_insn "prologue_use"
10458 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10460 "%@ %0 needed for prologue"
10464 ;; Patterns for exception handling
10466 (define_expand "eh_return"
10467 [(use (match_operand 0 "general_operand" ""))]
10472 emit_insn (gen_arm_eh_return (operands[0]));
10474 emit_insn (gen_thumb_eh_return (operands[0]));
10479 ;; We can't expand this before we know where the link register is stored.
10480 (define_insn_and_split "arm_eh_return"
10481 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10483 (clobber (match_scratch:SI 1 "=&r"))]
10486 "&& reload_completed"
10490 arm_set_return_address (operands[0], operands[1]);
10495 (define_insn_and_split "thumb_eh_return"
10496 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10498 (clobber (match_scratch:SI 1 "=&l"))]
10501 "&& reload_completed"
10505 thumb_set_return_address (operands[0], operands[1]);
10510 ;; Load the FPA co-processor patterns
10512 ;; Load the Maverick co-processor patterns
10513 (include "cirrus.md")
10514 ;; Load the Intel Wireless Multimedia Extension patterns
10515 (include "iwmmxt.md")
10516 ;; Load the VFP co-processor patterns