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_expand "thumb_movhi_clobber"
4955 [(set (match_operand:HI 0 "memory_operand" "")
4956 (match_operand:HI 1 "register_operand" ""))
4957 (clobber (match_operand:DI 2 "register_operand" ""))]
4960 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4961 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4963 emit_insn (gen_movhi (operands[0], operands[1]));
4966 /* XXX Fixme, need to handle other cases here as well. */
4971 ;; We use a DImode scratch because we may occasionally need an additional
4972 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4973 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4974 (define_expand "reload_outhi"
4975 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4976 (match_operand:HI 1 "s_register_operand" "r")
4977 (match_operand:DI 2 "s_register_operand" "=&l")])]
4980 arm_reload_out_hi (operands);
4982 thumb_reload_out_hi (operands);
4987 (define_expand "reload_inhi"
4988 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4989 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4990 (match_operand:DI 2 "s_register_operand" "=&r")])]
4994 arm_reload_in_hi (operands);
4996 thumb_reload_out_hi (operands);
5000 (define_expand "movqi"
5001 [(set (match_operand:QI 0 "general_operand" "")
5002 (match_operand:QI 1 "general_operand" ""))]
5007 /* Everything except mem = const or mem = mem can be done easily */
5009 if (!no_new_pseudos)
5011 if (GET_CODE (operands[1]) == CONST_INT)
5013 rtx reg = gen_reg_rtx (SImode);
5015 emit_insn (gen_movsi (reg, operands[1]));
5016 operands[1] = gen_lowpart (QImode, reg);
5018 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5020 rtx reg = gen_reg_rtx (SImode);
5022 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5023 operands[1] = gen_lowpart (QImode, reg);
5025 if (GET_CODE (operands[0]) == MEM)
5026 operands[1] = force_reg (QImode, operands[1]);
5029 else /* TARGET_THUMB */
5031 if (!no_new_pseudos)
5033 if (GET_CODE (operands[0]) != REG)
5034 operands[1] = force_reg (QImode, operands[1]);
5036 /* ??? We shouldn't really get invalid addresses here, but this can
5037 happen if we are passed a SP (never OK for HImode/QImode) or
5038 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5039 HImode/QImode) relative address. */
5040 /* ??? This should perhaps be fixed elsewhere, for instance, in
5041 fixup_stack_1, by checking for other kinds of invalid addresses,
5042 e.g. a bare reference to a virtual register. This may confuse the
5043 alpha though, which must handle this case differently. */
5044 if (GET_CODE (operands[0]) == MEM
5045 && !memory_address_p (GET_MODE (operands[0]),
5046 XEXP (operands[0], 0)))
5048 = replace_equiv_address (operands[0],
5049 copy_to_reg (XEXP (operands[0], 0)));
5050 if (GET_CODE (operands[1]) == MEM
5051 && !memory_address_p (GET_MODE (operands[1]),
5052 XEXP (operands[1], 0)))
5054 = replace_equiv_address (operands[1],
5055 copy_to_reg (XEXP (operands[1], 0)));
5057 /* Handle loading a large integer during reload. */
5058 else if (GET_CODE (operands[1]) == CONST_INT
5059 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5061 /* Writing a constant to memory needs a scratch, which should
5062 be handled with SECONDARY_RELOADs. */
5063 gcc_assert (GET_CODE (operands[0]) == REG);
5065 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5066 emit_insn (gen_movsi (operands[0], operands[1]));
5074 (define_insn "*arm_movqi_insn"
5075 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5076 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5078 && ( register_operand (operands[0], QImode)
5079 || register_operand (operands[1], QImode))"
5085 [(set_attr "type" "*,*,load1,store1")
5086 (set_attr "predicable" "yes")]
5089 (define_insn "*thumb_movqi_insn"
5090 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5091 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5093 && ( register_operand (operands[0], QImode)
5094 || register_operand (operands[1], QImode))"
5102 [(set_attr "length" "2")
5103 (set_attr "type" "*,load1,store1,*,*,*")
5104 (set_attr "pool_range" "*,32,*,*,*,*")]
5107 (define_expand "movsf"
5108 [(set (match_operand:SF 0 "general_operand" "")
5109 (match_operand:SF 1 "general_operand" ""))]
5114 if (GET_CODE (operands[0]) == MEM)
5115 operands[1] = force_reg (SFmode, operands[1]);
5117 else /* TARGET_THUMB */
5119 if (!no_new_pseudos)
5121 if (GET_CODE (operands[0]) != REG)
5122 operands[1] = force_reg (SFmode, operands[1]);
5129 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5130 (match_operand:SF 1 "immediate_operand" ""))]
5132 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5134 && GET_CODE (operands[1]) == CONST_DOUBLE"
5135 [(set (match_dup 2) (match_dup 3))]
5137 operands[2] = gen_lowpart (SImode, operands[0]);
5138 operands[3] = gen_lowpart (SImode, operands[1]);
5139 if (operands[2] == 0 || operands[3] == 0)
5144 (define_insn "*arm_movsf_soft_insn"
5145 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5146 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5148 && TARGET_SOFT_FLOAT
5149 && (GET_CODE (operands[0]) != MEM
5150 || register_operand (operands[1], SFmode))"
5153 ldr%?\\t%0, %1\\t%@ float
5154 str%?\\t%1, %0\\t%@ float"
5155 [(set_attr "length" "4,4,4")
5156 (set_attr "predicable" "yes")
5157 (set_attr "type" "*,load1,store1")
5158 (set_attr "pool_range" "*,4096,*")
5159 (set_attr "neg_pool_range" "*,4084,*")]
5162 ;;; ??? This should have alternatives for constants.
5163 (define_insn "*thumb_movsf_insn"
5164 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5165 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5167 && ( register_operand (operands[0], SFmode)
5168 || register_operand (operands[1], SFmode))"
5177 [(set_attr "length" "2")
5178 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5179 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5182 (define_expand "movdf"
5183 [(set (match_operand:DF 0 "general_operand" "")
5184 (match_operand:DF 1 "general_operand" ""))]
5189 if (GET_CODE (operands[0]) == MEM)
5190 operands[1] = force_reg (DFmode, operands[1]);
5192 else /* TARGET_THUMB */
5194 if (!no_new_pseudos)
5196 if (GET_CODE (operands[0]) != REG)
5197 operands[1] = force_reg (DFmode, operands[1]);
5203 ;; Reloading a df mode value stored in integer regs to memory can require a
5205 (define_expand "reload_outdf"
5206 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5207 (match_operand:DF 1 "s_register_operand" "r")
5208 (match_operand:SI 2 "s_register_operand" "=&r")]
5212 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5215 operands[2] = XEXP (operands[0], 0);
5216 else if (code == POST_INC || code == PRE_DEC)
5218 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5219 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5220 emit_insn (gen_movdi (operands[0], operands[1]));
5223 else if (code == PRE_INC)
5225 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5227 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5230 else if (code == POST_DEC)
5231 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5233 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5234 XEXP (XEXP (operands[0], 0), 1)));
5236 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5239 if (code == POST_DEC)
5240 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5246 (define_insn "*movdf_soft_insn"
5247 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5248 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5249 "TARGET_ARM && TARGET_SOFT_FLOAT
5252 switch (which_alternative)
5259 return output_move_double (operands);
5262 [(set_attr "length" "8,12,16,8,8")
5263 (set_attr "type" "*,*,*,load2,store2")
5264 (set_attr "pool_range" "1020")
5265 (set_attr "neg_pool_range" "1008")]
5268 ;;; ??? This should have alternatives for constants.
5269 ;;; ??? This was originally identical to the movdi_insn pattern.
5270 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5271 ;;; thumb_reorg with a memory reference.
5272 (define_insn "*thumb_movdf_insn"
5273 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5274 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5276 && ( register_operand (operands[0], DFmode)
5277 || register_operand (operands[1], DFmode))"
5279 switch (which_alternative)
5283 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5284 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5285 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5287 return \"ldmia\\t%1, {%0, %H0}\";
5289 return \"stmia\\t%0, {%1, %H1}\";
5291 return thumb_load_double_from_address (operands);
5293 operands[2] = gen_rtx_MEM (SImode,
5294 plus_constant (XEXP (operands[0], 0), 4));
5295 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5298 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5299 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5300 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5303 [(set_attr "length" "4,2,2,6,4,4")
5304 (set_attr "type" "*,load2,store2,load2,store2,*")
5305 (set_attr "pool_range" "*,*,*,1020,*,*")]
5308 (define_expand "movxf"
5309 [(set (match_operand:XF 0 "general_operand" "")
5310 (match_operand:XF 1 "general_operand" ""))]
5311 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5313 if (GET_CODE (operands[0]) == MEM)
5314 operands[1] = force_reg (XFmode, operands[1]);
5319 (define_expand "movv2si"
5320 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5321 (match_operand:V2SI 1 "general_operand" ""))]
5322 "TARGET_REALLY_IWMMXT"
5326 (define_expand "movv4hi"
5327 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5328 (match_operand:V4HI 1 "general_operand" ""))]
5329 "TARGET_REALLY_IWMMXT"
5333 (define_expand "movv8qi"
5334 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5335 (match_operand:V8QI 1 "general_operand" ""))]
5336 "TARGET_REALLY_IWMMXT"
5341 ;; load- and store-multiple insns
5342 ;; The arm can load/store any set of registers, provided that they are in
5343 ;; ascending order; but that is beyond GCC so stick with what it knows.
5345 (define_expand "load_multiple"
5346 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5347 (match_operand:SI 1 "" ""))
5348 (use (match_operand:SI 2 "" ""))])]
5351 HOST_WIDE_INT offset = 0;
5353 /* Support only fixed point registers. */
5354 if (GET_CODE (operands[2]) != CONST_INT
5355 || INTVAL (operands[2]) > 14
5356 || INTVAL (operands[2]) < 2
5357 || GET_CODE (operands[1]) != MEM
5358 || GET_CODE (operands[0]) != REG
5359 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5360 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5364 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5365 force_reg (SImode, XEXP (operands[1], 0)),
5366 TRUE, FALSE, operands[1], &offset);
5369 ;; Load multiple with write-back
5371 (define_insn "*ldmsi_postinc4"
5372 [(match_parallel 0 "load_multiple_operation"
5373 [(set (match_operand:SI 1 "s_register_operand" "=r")
5374 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5376 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5377 (mem:SI (match_dup 2)))
5378 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5379 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5380 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5381 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5382 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5383 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5384 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5385 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5386 [(set_attr "type" "load4")
5387 (set_attr "predicable" "yes")]
5390 (define_insn "*ldmsi_postinc4_thumb"
5391 [(match_parallel 0 "load_multiple_operation"
5392 [(set (match_operand:SI 1 "s_register_operand" "=l")
5393 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5396 (mem:SI (match_dup 2)))
5397 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5398 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5399 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5400 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5401 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5402 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5403 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5404 "ldmia\\t%1!, {%3, %4, %5, %6}"
5405 [(set_attr "type" "load4")]
5408 (define_insn "*ldmsi_postinc3"
5409 [(match_parallel 0 "load_multiple_operation"
5410 [(set (match_operand:SI 1 "s_register_operand" "=r")
5411 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5413 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5414 (mem:SI (match_dup 2)))
5415 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5416 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5417 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5418 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5419 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5420 "ldm%?ia\\t%1!, {%3, %4, %5}"
5421 [(set_attr "type" "load3")
5422 (set_attr "predicable" "yes")]
5425 (define_insn "*ldmsi_postinc2"
5426 [(match_parallel 0 "load_multiple_operation"
5427 [(set (match_operand:SI 1 "s_register_operand" "=r")
5428 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5430 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5431 (mem:SI (match_dup 2)))
5432 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5433 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5434 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5435 "ldm%?ia\\t%1!, {%3, %4}"
5436 [(set_attr "type" "load2")
5437 (set_attr "predicable" "yes")]
5440 ;; Ordinary load multiple
5442 (define_insn "*ldmsi4"
5443 [(match_parallel 0 "load_multiple_operation"
5444 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5445 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5446 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5447 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5448 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5449 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5450 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5451 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5452 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5453 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5454 [(set_attr "type" "load4")
5455 (set_attr "predicable" "yes")]
5458 (define_insn "*ldmsi3"
5459 [(match_parallel 0 "load_multiple_operation"
5460 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5461 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5462 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5463 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5464 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5465 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5466 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5467 "ldm%?ia\\t%1, {%2, %3, %4}"
5468 [(set_attr "type" "load3")
5469 (set_attr "predicable" "yes")]
5472 (define_insn "*ldmsi2"
5473 [(match_parallel 0 "load_multiple_operation"
5474 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5475 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5476 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5477 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5478 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5479 "ldm%?ia\\t%1, {%2, %3}"
5480 [(set_attr "type" "load2")
5481 (set_attr "predicable" "yes")]
5484 (define_expand "store_multiple"
5485 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5486 (match_operand:SI 1 "" ""))
5487 (use (match_operand:SI 2 "" ""))])]
5490 HOST_WIDE_INT offset = 0;
5492 /* Support only fixed point registers. */
5493 if (GET_CODE (operands[2]) != CONST_INT
5494 || INTVAL (operands[2]) > 14
5495 || INTVAL (operands[2]) < 2
5496 || GET_CODE (operands[1]) != REG
5497 || GET_CODE (operands[0]) != MEM
5498 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5499 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5503 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5504 force_reg (SImode, XEXP (operands[0], 0)),
5505 TRUE, FALSE, operands[0], &offset);
5508 ;; Store multiple with write-back
5510 (define_insn "*stmsi_postinc4"
5511 [(match_parallel 0 "store_multiple_operation"
5512 [(set (match_operand:SI 1 "s_register_operand" "=r")
5513 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5515 (set (mem:SI (match_dup 2))
5516 (match_operand:SI 3 "arm_hard_register_operand" ""))
5517 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5518 (match_operand:SI 4 "arm_hard_register_operand" ""))
5519 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5520 (match_operand:SI 5 "arm_hard_register_operand" ""))
5521 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5522 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5523 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5524 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5525 [(set_attr "predicable" "yes")
5526 (set_attr "type" "store4")]
5529 (define_insn "*stmsi_postinc4_thumb"
5530 [(match_parallel 0 "store_multiple_operation"
5531 [(set (match_operand:SI 1 "s_register_operand" "=l")
5532 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5534 (set (mem:SI (match_dup 2))
5535 (match_operand:SI 3 "arm_hard_register_operand" ""))
5536 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5537 (match_operand:SI 4 "arm_hard_register_operand" ""))
5538 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5539 (match_operand:SI 5 "arm_hard_register_operand" ""))
5540 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5541 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5542 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5543 "stmia\\t%1!, {%3, %4, %5, %6}"
5544 [(set_attr "type" "store4")]
5547 (define_insn "*stmsi_postinc3"
5548 [(match_parallel 0 "store_multiple_operation"
5549 [(set (match_operand:SI 1 "s_register_operand" "=r")
5550 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5552 (set (mem:SI (match_dup 2))
5553 (match_operand:SI 3 "arm_hard_register_operand" ""))
5554 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5555 (match_operand:SI 4 "arm_hard_register_operand" ""))
5556 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5557 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5558 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5559 "stm%?ia\\t%1!, {%3, %4, %5}"
5560 [(set_attr "predicable" "yes")
5561 (set_attr "type" "store3")]
5564 (define_insn "*stmsi_postinc2"
5565 [(match_parallel 0 "store_multiple_operation"
5566 [(set (match_operand:SI 1 "s_register_operand" "=r")
5567 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5569 (set (mem:SI (match_dup 2))
5570 (match_operand:SI 3 "arm_hard_register_operand" ""))
5571 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5572 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5573 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5574 "stm%?ia\\t%1!, {%3, %4}"
5575 [(set_attr "predicable" "yes")
5576 (set_attr "type" "store2")]
5579 ;; Ordinary store multiple
5581 (define_insn "*stmsi4"
5582 [(match_parallel 0 "store_multiple_operation"
5583 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5584 (match_operand:SI 2 "arm_hard_register_operand" ""))
5585 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5586 (match_operand:SI 3 "arm_hard_register_operand" ""))
5587 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5588 (match_operand:SI 4 "arm_hard_register_operand" ""))
5589 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5590 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5591 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5592 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5593 [(set_attr "predicable" "yes")
5594 (set_attr "type" "store4")]
5597 (define_insn "*stmsi3"
5598 [(match_parallel 0 "store_multiple_operation"
5599 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5600 (match_operand:SI 2 "arm_hard_register_operand" ""))
5601 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5602 (match_operand:SI 3 "arm_hard_register_operand" ""))
5603 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5604 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5605 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5606 "stm%?ia\\t%1, {%2, %3, %4}"
5607 [(set_attr "predicable" "yes")
5608 (set_attr "type" "store3")]
5611 (define_insn "*stmsi2"
5612 [(match_parallel 0 "store_multiple_operation"
5613 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5614 (match_operand:SI 2 "arm_hard_register_operand" ""))
5615 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5616 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5617 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5618 "stm%?ia\\t%1, {%2, %3}"
5619 [(set_attr "predicable" "yes")
5620 (set_attr "type" "store2")]
5623 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5624 ;; We could let this apply for blocks of less than this, but it clobbers so
5625 ;; many registers that there is then probably a better way.
5627 (define_expand "movmemqi"
5628 [(match_operand:BLK 0 "general_operand" "")
5629 (match_operand:BLK 1 "general_operand" "")
5630 (match_operand:SI 2 "const_int_operand" "")
5631 (match_operand:SI 3 "const_int_operand" "")]
5636 if (arm_gen_movmemqi (operands))
5640 else /* TARGET_THUMB */
5642 if ( INTVAL (operands[3]) != 4
5643 || INTVAL (operands[2]) > 48)
5646 thumb_expand_movmemqi (operands);
5652 ;; Thumb block-move insns
5654 (define_insn "movmem12b"
5655 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5656 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5657 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5658 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5659 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5660 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5661 (set (match_operand:SI 0 "register_operand" "=l")
5662 (plus:SI (match_dup 2) (const_int 12)))
5663 (set (match_operand:SI 1 "register_operand" "=l")
5664 (plus:SI (match_dup 3) (const_int 12)))
5665 (clobber (match_scratch:SI 4 "=&l"))
5666 (clobber (match_scratch:SI 5 "=&l"))
5667 (clobber (match_scratch:SI 6 "=&l"))]
5669 "* return thumb_output_move_mem_multiple (3, operands);"
5670 [(set_attr "length" "4")
5671 ; This isn't entirely accurate... It loads as well, but in terms of
5672 ; scheduling the following insn it is better to consider it as a store
5673 (set_attr "type" "store3")]
5676 (define_insn "movmem8b"
5677 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5678 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5679 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5680 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5681 (set (match_operand:SI 0 "register_operand" "=l")
5682 (plus:SI (match_dup 2) (const_int 8)))
5683 (set (match_operand:SI 1 "register_operand" "=l")
5684 (plus:SI (match_dup 3) (const_int 8)))
5685 (clobber (match_scratch:SI 4 "=&l"))
5686 (clobber (match_scratch:SI 5 "=&l"))]
5688 "* return thumb_output_move_mem_multiple (2, operands);"
5689 [(set_attr "length" "4")
5690 ; This isn't entirely accurate... It loads as well, but in terms of
5691 ; scheduling the following insn it is better to consider it as a store
5692 (set_attr "type" "store2")]
5697 ;; Compare & branch insns
5698 ;; The range calculations are based as follows:
5699 ;; For forward branches, the address calculation returns the address of
5700 ;; the next instruction. This is 2 beyond the branch instruction.
5701 ;; For backward branches, the address calculation returns the address of
5702 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5703 ;; instruction for the shortest sequence, and 4 before the branch instruction
5704 ;; if we have to jump around an unconditional branch.
5705 ;; To the basic branch range the PC offset must be added (this is +4).
5706 ;; So for forward branches we have
5707 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5708 ;; And for backward branches we have
5709 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5711 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5712 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5714 (define_expand "cbranchsi4"
5715 [(set (pc) (if_then_else
5716 (match_operator 0 "arm_comparison_operator"
5717 [(match_operand:SI 1 "s_register_operand" "")
5718 (match_operand:SI 2 "nonmemory_operand" "")])
5719 (label_ref (match_operand 3 "" ""))
5723 if (thumb_cmpneg_operand (operands[2], SImode))
5725 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5726 operands[3], operands[0]));
5729 if (!thumb_cmp_operand (operands[2], SImode))
5730 operands[2] = force_reg (SImode, operands[2]);
5733 (define_insn "*cbranchsi4_insn"
5734 [(set (pc) (if_then_else
5735 (match_operator 0 "arm_comparison_operator"
5736 [(match_operand:SI 1 "s_register_operand" "l,*h")
5737 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5738 (label_ref (match_operand 3 "" ""))
5742 output_asm_insn (\"cmp\\t%1, %2\", operands);
5744 switch (get_attr_length (insn))
5746 case 4: return \"b%d0\\t%l3\";
5747 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5748 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5751 [(set (attr "far_jump")
5753 (eq_attr "length" "8")
5754 (const_string "yes")
5755 (const_string "no")))
5756 (set (attr "length")
5758 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5759 (le (minus (match_dup 3) (pc)) (const_int 256)))
5762 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5763 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5768 (define_insn "cbranchsi4_scratch"
5769 [(set (pc) (if_then_else
5770 (match_operator 4 "arm_comparison_operator"
5771 [(match_operand:SI 1 "s_register_operand" "l,0")
5772 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5773 (label_ref (match_operand 3 "" ""))
5775 (clobber (match_scratch:SI 0 "=l,l"))]
5778 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5780 switch (get_attr_length (insn))
5782 case 4: return \"b%d4\\t%l3\";
5783 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5784 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5787 [(set (attr "far_jump")
5789 (eq_attr "length" "8")
5790 (const_string "yes")
5791 (const_string "no")))
5792 (set (attr "length")
5794 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5795 (le (minus (match_dup 3) (pc)) (const_int 256)))
5798 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5799 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5803 (define_insn "*movsi_cbranchsi4"
5806 (match_operator 3 "arm_comparison_operator"
5807 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5809 (label_ref (match_operand 2 "" ""))
5811 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5815 if (which_alternative == 0)
5816 output_asm_insn (\"cmp\t%0, #0\", operands);
5817 else if (which_alternative == 1)
5818 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5821 output_asm_insn (\"cmp\t%1, #0\", operands);
5822 if (which_alternative == 2)
5823 output_asm_insn (\"mov\t%0, %1\", operands);
5825 output_asm_insn (\"str\t%1, %0\", operands);
5827 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5829 case 4: return \"b%d3\\t%l2\";
5830 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5831 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5834 [(set (attr "far_jump")
5836 (ior (and (gt (symbol_ref ("which_alternative"))
5838 (eq_attr "length" "8"))
5839 (eq_attr "length" "10"))
5840 (const_string "yes")
5841 (const_string "no")))
5842 (set (attr "length")
5844 (le (symbol_ref ("which_alternative"))
5847 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5848 (le (minus (match_dup 2) (pc)) (const_int 256)))
5851 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5852 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5856 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5857 (le (minus (match_dup 2) (pc)) (const_int 256)))
5860 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5861 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5866 (define_insn "*negated_cbranchsi4"
5869 (match_operator 0 "equality_operator"
5870 [(match_operand:SI 1 "s_register_operand" "l")
5871 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5872 (label_ref (match_operand 3 "" ""))
5876 output_asm_insn (\"cmn\\t%1, %2\", operands);
5877 switch (get_attr_length (insn))
5879 case 4: return \"b%d0\\t%l3\";
5880 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5881 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5884 [(set (attr "far_jump")
5886 (eq_attr "length" "8")
5887 (const_string "yes")
5888 (const_string "no")))
5889 (set (attr "length")
5891 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5892 (le (minus (match_dup 3) (pc)) (const_int 256)))
5895 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5896 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5901 (define_insn "*tbit_cbranch"
5904 (match_operator 0 "equality_operator"
5905 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5907 (match_operand:SI 2 "const_int_operand" "i"))
5909 (label_ref (match_operand 3 "" ""))
5911 (clobber (match_scratch:SI 4 "=l"))]
5916 op[0] = operands[4];
5917 op[1] = operands[1];
5918 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5920 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5921 switch (get_attr_length (insn))
5923 case 4: return \"b%d0\\t%l3\";
5924 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5925 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5928 [(set (attr "far_jump")
5930 (eq_attr "length" "8")
5931 (const_string "yes")
5932 (const_string "no")))
5933 (set (attr "length")
5935 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5936 (le (minus (match_dup 3) (pc)) (const_int 256)))
5939 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5940 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5945 (define_insn "*tstsi3_cbranch"
5948 (match_operator 3 "equality_operator"
5949 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5950 (match_operand:SI 1 "s_register_operand" "l"))
5952 (label_ref (match_operand 2 "" ""))
5957 output_asm_insn (\"tst\\t%0, %1\", operands);
5958 switch (get_attr_length (insn))
5960 case 4: return \"b%d3\\t%l2\";
5961 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5962 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5965 [(set (attr "far_jump")
5967 (eq_attr "length" "8")
5968 (const_string "yes")
5969 (const_string "no")))
5970 (set (attr "length")
5972 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5973 (le (minus (match_dup 2) (pc)) (const_int 256)))
5976 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5977 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5982 (define_insn "*andsi3_cbranch"
5985 (match_operator 5 "equality_operator"
5986 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5987 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5989 (label_ref (match_operand 4 "" ""))
5991 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5992 (and:SI (match_dup 2) (match_dup 3)))
5993 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5997 if (which_alternative == 0)
5998 output_asm_insn (\"and\\t%0, %3\", operands);
5999 else if (which_alternative == 1)
6001 output_asm_insn (\"and\\t%1, %3\", operands);
6002 output_asm_insn (\"mov\\t%0, %1\", operands);
6006 output_asm_insn (\"and\\t%1, %3\", operands);
6007 output_asm_insn (\"str\\t%1, %0\", operands);
6010 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6012 case 4: return \"b%d5\\t%l4\";
6013 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6014 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6017 [(set (attr "far_jump")
6019 (ior (and (eq (symbol_ref ("which_alternative"))
6021 (eq_attr "length" "8"))
6022 (eq_attr "length" "10"))
6023 (const_string "yes")
6024 (const_string "no")))
6025 (set (attr "length")
6027 (eq (symbol_ref ("which_alternative"))
6030 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6031 (le (minus (match_dup 4) (pc)) (const_int 256)))
6034 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6035 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6039 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6040 (le (minus (match_dup 4) (pc)) (const_int 256)))
6043 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6044 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6049 (define_insn "*orrsi3_cbranch_scratch"
6052 (match_operator 4 "equality_operator"
6053 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6054 (match_operand:SI 2 "s_register_operand" "l"))
6056 (label_ref (match_operand 3 "" ""))
6058 (clobber (match_scratch:SI 0 "=l"))]
6062 output_asm_insn (\"orr\\t%0, %2\", operands);
6063 switch (get_attr_length (insn))
6065 case 4: return \"b%d4\\t%l3\";
6066 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6067 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6070 [(set (attr "far_jump")
6072 (eq_attr "length" "8")
6073 (const_string "yes")
6074 (const_string "no")))
6075 (set (attr "length")
6077 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6078 (le (minus (match_dup 3) (pc)) (const_int 256)))
6081 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6082 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6087 (define_insn "*orrsi3_cbranch"
6090 (match_operator 5 "equality_operator"
6091 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6092 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6094 (label_ref (match_operand 4 "" ""))
6096 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6097 (ior:SI (match_dup 2) (match_dup 3)))
6098 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6102 if (which_alternative == 0)
6103 output_asm_insn (\"orr\\t%0, %3\", operands);
6104 else if (which_alternative == 1)
6106 output_asm_insn (\"orr\\t%1, %3\", operands);
6107 output_asm_insn (\"mov\\t%0, %1\", operands);
6111 output_asm_insn (\"orr\\t%1, %3\", operands);
6112 output_asm_insn (\"str\\t%1, %0\", operands);
6115 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6117 case 4: return \"b%d5\\t%l4\";
6118 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6119 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6122 [(set (attr "far_jump")
6124 (ior (and (eq (symbol_ref ("which_alternative"))
6126 (eq_attr "length" "8"))
6127 (eq_attr "length" "10"))
6128 (const_string "yes")
6129 (const_string "no")))
6130 (set (attr "length")
6132 (eq (symbol_ref ("which_alternative"))
6135 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6136 (le (minus (match_dup 4) (pc)) (const_int 256)))
6139 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6140 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6144 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6145 (le (minus (match_dup 4) (pc)) (const_int 256)))
6148 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6149 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6154 (define_insn "*xorsi3_cbranch_scratch"
6157 (match_operator 4 "equality_operator"
6158 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6159 (match_operand:SI 2 "s_register_operand" "l"))
6161 (label_ref (match_operand 3 "" ""))
6163 (clobber (match_scratch:SI 0 "=l"))]
6167 output_asm_insn (\"eor\\t%0, %2\", operands);
6168 switch (get_attr_length (insn))
6170 case 4: return \"b%d4\\t%l3\";
6171 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6172 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6175 [(set (attr "far_jump")
6177 (eq_attr "length" "8")
6178 (const_string "yes")
6179 (const_string "no")))
6180 (set (attr "length")
6182 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6183 (le (minus (match_dup 3) (pc)) (const_int 256)))
6186 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6187 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6192 (define_insn "*xorsi3_cbranch"
6195 (match_operator 5 "equality_operator"
6196 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6197 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6199 (label_ref (match_operand 4 "" ""))
6201 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6202 (xor:SI (match_dup 2) (match_dup 3)))
6203 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6207 if (which_alternative == 0)
6208 output_asm_insn (\"eor\\t%0, %3\", operands);
6209 else if (which_alternative == 1)
6211 output_asm_insn (\"eor\\t%1, %3\", operands);
6212 output_asm_insn (\"mov\\t%0, %1\", operands);
6216 output_asm_insn (\"eor\\t%1, %3\", operands);
6217 output_asm_insn (\"str\\t%1, %0\", operands);
6220 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6222 case 4: return \"b%d5\\t%l4\";
6223 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6224 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6227 [(set (attr "far_jump")
6229 (ior (and (eq (symbol_ref ("which_alternative"))
6231 (eq_attr "length" "8"))
6232 (eq_attr "length" "10"))
6233 (const_string "yes")
6234 (const_string "no")))
6235 (set (attr "length")
6237 (eq (symbol_ref ("which_alternative"))
6240 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6241 (le (minus (match_dup 4) (pc)) (const_int 256)))
6244 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6245 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6249 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6250 (le (minus (match_dup 4) (pc)) (const_int 256)))
6253 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6254 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6259 (define_insn "*bicsi3_cbranch_scratch"
6262 (match_operator 4 "equality_operator"
6263 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6264 (match_operand:SI 1 "s_register_operand" "0"))
6266 (label_ref (match_operand 3 "" ""))
6268 (clobber (match_scratch:SI 0 "=l"))]
6272 output_asm_insn (\"bic\\t%0, %2\", operands);
6273 switch (get_attr_length (insn))
6275 case 4: return \"b%d4\\t%l3\";
6276 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6277 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6280 [(set (attr "far_jump")
6282 (eq_attr "length" "8")
6283 (const_string "yes")
6284 (const_string "no")))
6285 (set (attr "length")
6287 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6288 (le (minus (match_dup 3) (pc)) (const_int 256)))
6291 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6292 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6297 (define_insn "*bicsi3_cbranch"
6300 (match_operator 5 "equality_operator"
6301 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6302 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6304 (label_ref (match_operand 4 "" ""))
6306 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6307 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6308 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6312 if (which_alternative == 0)
6313 output_asm_insn (\"bic\\t%0, %3\", operands);
6314 else if (which_alternative <= 2)
6316 output_asm_insn (\"bic\\t%1, %3\", operands);
6317 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6318 conditions again, since we're only testing for equality. */
6319 output_asm_insn (\"mov\\t%0, %1\", operands);
6323 output_asm_insn (\"bic\\t%1, %3\", operands);
6324 output_asm_insn (\"str\\t%1, %0\", operands);
6327 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6329 case 4: return \"b%d5\\t%l4\";
6330 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6331 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6334 [(set (attr "far_jump")
6336 (ior (and (eq (symbol_ref ("which_alternative"))
6338 (eq_attr "length" "8"))
6339 (eq_attr "length" "10"))
6340 (const_string "yes")
6341 (const_string "no")))
6342 (set (attr "length")
6344 (eq (symbol_ref ("which_alternative"))
6347 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6348 (le (minus (match_dup 4) (pc)) (const_int 256)))
6351 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6352 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6356 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6357 (le (minus (match_dup 4) (pc)) (const_int 256)))
6360 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6361 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6366 (define_insn "*cbranchne_decr1"
6368 (if_then_else (match_operator 3 "equality_operator"
6369 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6371 (label_ref (match_operand 4 "" ""))
6373 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6374 (plus:SI (match_dup 2) (const_int -1)))
6375 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6380 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6382 VOIDmode, operands[2], const1_rtx);
6383 cond[1] = operands[4];
6385 if (which_alternative == 0)
6386 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6387 else if (which_alternative == 1)
6389 /* We must provide an alternative for a hi reg because reload
6390 cannot handle output reloads on a jump instruction, but we
6391 can't subtract into that. Fortunately a mov from lo to hi
6392 does not clobber the condition codes. */
6393 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6394 output_asm_insn (\"mov\\t%0, %1\", operands);
6398 /* Similarly, but the target is memory. */
6399 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6400 output_asm_insn (\"str\\t%1, %0\", operands);
6403 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6406 output_asm_insn (\"b%d0\\t%l1\", cond);
6409 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6410 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6412 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6413 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6417 [(set (attr "far_jump")
6419 (ior (and (eq (symbol_ref ("which_alternative"))
6421 (eq_attr "length" "8"))
6422 (eq_attr "length" "10"))
6423 (const_string "yes")
6424 (const_string "no")))
6425 (set_attr_alternative "length"
6429 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6430 (le (minus (match_dup 4) (pc)) (const_int 256)))
6433 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6434 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6439 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6440 (le (minus (match_dup 4) (pc)) (const_int 256)))
6443 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6444 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6449 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6450 (le (minus (match_dup 4) (pc)) (const_int 256)))
6453 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6454 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6459 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6460 (le (minus (match_dup 4) (pc)) (const_int 256)))
6463 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6464 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6469 (define_insn "*addsi3_cbranch"
6472 (match_operator 4 "comparison_operator"
6474 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6475 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6477 (label_ref (match_operand 5 "" ""))
6480 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6481 (plus:SI (match_dup 2) (match_dup 3)))
6482 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6484 && (GET_CODE (operands[4]) == EQ
6485 || GET_CODE (operands[4]) == NE
6486 || GET_CODE (operands[4]) == GE
6487 || GET_CODE (operands[4]) == LT)"
6493 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6494 cond[1] = operands[2];
6495 cond[2] = operands[3];
6497 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6498 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6500 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6502 if (which_alternative >= 3
6503 && which_alternative < 4)
6504 output_asm_insn (\"mov\\t%0, %1\", operands);
6505 else if (which_alternative >= 4)
6506 output_asm_insn (\"str\\t%1, %0\", operands);
6508 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6511 return \"b%d4\\t%l5\";
6513 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6515 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6519 [(set (attr "far_jump")
6521 (ior (and (lt (symbol_ref ("which_alternative"))
6523 (eq_attr "length" "8"))
6524 (eq_attr "length" "10"))
6525 (const_string "yes")
6526 (const_string "no")))
6527 (set (attr "length")
6529 (lt (symbol_ref ("which_alternative"))
6532 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6533 (le (minus (match_dup 5) (pc)) (const_int 256)))
6536 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6537 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6541 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6542 (le (minus (match_dup 5) (pc)) (const_int 256)))
6545 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6546 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6551 (define_insn "*addsi3_cbranch_scratch"
6554 (match_operator 3 "comparison_operator"
6556 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6557 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6559 (label_ref (match_operand 4 "" ""))
6561 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6563 && (GET_CODE (operands[3]) == EQ
6564 || GET_CODE (operands[3]) == NE
6565 || GET_CODE (operands[3]) == GE
6566 || GET_CODE (operands[3]) == LT)"
6569 switch (which_alternative)
6572 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6575 output_asm_insn (\"cmn\t%1, %2\", operands);
6578 if (INTVAL (operands[2]) < 0)
6579 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6581 output_asm_insn (\"add\t%0, %1, %2\", operands);
6584 if (INTVAL (operands[2]) < 0)
6585 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6587 output_asm_insn (\"add\t%0, %0, %2\", operands);
6591 switch (get_attr_length (insn))
6594 return \"b%d3\\t%l4\";
6596 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6598 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6602 [(set (attr "far_jump")
6604 (eq_attr "length" "8")
6605 (const_string "yes")
6606 (const_string "no")))
6607 (set (attr "length")
6609 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6610 (le (minus (match_dup 4) (pc)) (const_int 256)))
6613 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6614 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6619 (define_insn "*subsi3_cbranch"
6622 (match_operator 4 "comparison_operator"
6624 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6625 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6627 (label_ref (match_operand 5 "" ""))
6629 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6630 (minus:SI (match_dup 2) (match_dup 3)))
6631 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6633 && (GET_CODE (operands[4]) == EQ
6634 || GET_CODE (operands[4]) == NE
6635 || GET_CODE (operands[4]) == GE
6636 || GET_CODE (operands[4]) == LT)"
6639 if (which_alternative == 0)
6640 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6641 else if (which_alternative == 1)
6643 /* We must provide an alternative for a hi reg because reload
6644 cannot handle output reloads on a jump instruction, but we
6645 can't subtract into that. Fortunately a mov from lo to hi
6646 does not clobber the condition codes. */
6647 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6648 output_asm_insn (\"mov\\t%0, %1\", operands);
6652 /* Similarly, but the target is memory. */
6653 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6654 output_asm_insn (\"str\\t%1, %0\", operands);
6657 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6660 return \"b%d4\\t%l5\";
6662 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6664 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6668 [(set (attr "far_jump")
6670 (ior (and (eq (symbol_ref ("which_alternative"))
6672 (eq_attr "length" "8"))
6673 (eq_attr "length" "10"))
6674 (const_string "yes")
6675 (const_string "no")))
6676 (set (attr "length")
6678 (eq (symbol_ref ("which_alternative"))
6681 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6682 (le (minus (match_dup 5) (pc)) (const_int 256)))
6685 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6686 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6690 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6691 (le (minus (match_dup 5) (pc)) (const_int 256)))
6694 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6695 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6700 (define_insn "*subsi3_cbranch_scratch"
6703 (match_operator 0 "arm_comparison_operator"
6704 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6705 (match_operand:SI 2 "nonmemory_operand" "l"))
6707 (label_ref (match_operand 3 "" ""))
6710 && (GET_CODE (operands[0]) == EQ
6711 || GET_CODE (operands[0]) == NE
6712 || GET_CODE (operands[0]) == GE
6713 || GET_CODE (operands[0]) == LT)"
6715 output_asm_insn (\"cmp\\t%1, %2\", operands);
6716 switch (get_attr_length (insn))
6718 case 4: return \"b%d0\\t%l3\";
6719 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6720 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6723 [(set (attr "far_jump")
6725 (eq_attr "length" "8")
6726 (const_string "yes")
6727 (const_string "no")))
6728 (set (attr "length")
6730 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6731 (le (minus (match_dup 3) (pc)) (const_int 256)))
6734 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6735 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6740 ;; Comparison and test insns
6742 (define_expand "cmpsi"
6743 [(match_operand:SI 0 "s_register_operand" "")
6744 (match_operand:SI 1 "arm_add_operand" "")]
6747 arm_compare_op0 = operands[0];
6748 arm_compare_op1 = operands[1];
6753 (define_expand "cmpsf"
6754 [(match_operand:SF 0 "s_register_operand" "")
6755 (match_operand:SF 1 "arm_float_compare_operand" "")]
6756 "TARGET_ARM && TARGET_HARD_FLOAT"
6758 arm_compare_op0 = operands[0];
6759 arm_compare_op1 = operands[1];
6764 (define_expand "cmpdf"
6765 [(match_operand:DF 0 "s_register_operand" "")
6766 (match_operand:DF 1 "arm_float_compare_operand" "")]
6767 "TARGET_ARM && TARGET_HARD_FLOAT"
6769 arm_compare_op0 = operands[0];
6770 arm_compare_op1 = operands[1];
6775 (define_insn "*arm_cmpsi_insn"
6776 [(set (reg:CC CC_REGNUM)
6777 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6778 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6783 [(set_attr "conds" "set")]
6786 (define_insn "*cmpsi_shiftsi"
6787 [(set (reg:CC CC_REGNUM)
6788 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6789 (match_operator:SI 3 "shift_operator"
6790 [(match_operand:SI 1 "s_register_operand" "r")
6791 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6794 [(set_attr "conds" "set")
6795 (set_attr "shift" "1")
6796 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6797 (const_string "alu_shift")
6798 (const_string "alu_shift_reg")))]
6801 (define_insn "*cmpsi_shiftsi_swp"
6802 [(set (reg:CC_SWP CC_REGNUM)
6803 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6804 [(match_operand:SI 1 "s_register_operand" "r")
6805 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6806 (match_operand:SI 0 "s_register_operand" "r")))]
6809 [(set_attr "conds" "set")
6810 (set_attr "shift" "1")
6811 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6812 (const_string "alu_shift")
6813 (const_string "alu_shift_reg")))]
6816 (define_insn "*cmpsi_negshiftsi_si"
6817 [(set (reg:CC_Z CC_REGNUM)
6819 (neg:SI (match_operator:SI 1 "shift_operator"
6820 [(match_operand:SI 2 "s_register_operand" "r")
6821 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6822 (match_operand:SI 0 "s_register_operand" "r")))]
6825 [(set_attr "conds" "set")
6826 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6827 (const_string "alu_shift")
6828 (const_string "alu_shift_reg")))]
6831 ;; Cirrus SF compare instruction
6832 (define_insn "*cirrus_cmpsf"
6833 [(set (reg:CCFP CC_REGNUM)
6834 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6835 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6836 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6837 "cfcmps%?\\tr15, %V0, %V1"
6838 [(set_attr "type" "mav_farith")
6839 (set_attr "cirrus" "compare")]
6842 ;; Cirrus DF compare instruction
6843 (define_insn "*cirrus_cmpdf"
6844 [(set (reg:CCFP CC_REGNUM)
6845 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6846 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6847 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6848 "cfcmpd%?\\tr15, %V0, %V1"
6849 [(set_attr "type" "mav_farith")
6850 (set_attr "cirrus" "compare")]
6853 ;; Cirrus DI compare instruction
6854 (define_expand "cmpdi"
6855 [(match_operand:DI 0 "cirrus_fp_register" "")
6856 (match_operand:DI 1 "cirrus_fp_register" "")]
6857 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6859 arm_compare_op0 = operands[0];
6860 arm_compare_op1 = operands[1];
6864 (define_insn "*cirrus_cmpdi"
6865 [(set (reg:CC CC_REGNUM)
6866 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6867 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6868 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6869 "cfcmp64%?\\tr15, %V0, %V1"
6870 [(set_attr "type" "mav_farith")
6871 (set_attr "cirrus" "compare")]
6874 ; This insn allows redundant compares to be removed by cse, nothing should
6875 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6876 ; is deleted later on. The match_dup will match the mode here, so that
6877 ; mode changes of the condition codes aren't lost by this even though we don't
6878 ; specify what they are.
6880 (define_insn "*deleted_compare"
6881 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6883 "\\t%@ deleted compare"
6884 [(set_attr "conds" "set")
6885 (set_attr "length" "0")]
6889 ;; Conditional branch insns
6891 (define_expand "beq"
6893 (if_then_else (eq (match_dup 1) (const_int 0))
6894 (label_ref (match_operand 0 "" ""))
6897 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6900 (define_expand "bne"
6902 (if_then_else (ne (match_dup 1) (const_int 0))
6903 (label_ref (match_operand 0 "" ""))
6906 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6909 (define_expand "bgt"
6911 (if_then_else (gt (match_dup 1) (const_int 0))
6912 (label_ref (match_operand 0 "" ""))
6915 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6918 (define_expand "ble"
6920 (if_then_else (le (match_dup 1) (const_int 0))
6921 (label_ref (match_operand 0 "" ""))
6924 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6927 (define_expand "bge"
6929 (if_then_else (ge (match_dup 1) (const_int 0))
6930 (label_ref (match_operand 0 "" ""))
6933 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6936 (define_expand "blt"
6938 (if_then_else (lt (match_dup 1) (const_int 0))
6939 (label_ref (match_operand 0 "" ""))
6942 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6945 (define_expand "bgtu"
6947 (if_then_else (gtu (match_dup 1) (const_int 0))
6948 (label_ref (match_operand 0 "" ""))
6951 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6954 (define_expand "bleu"
6956 (if_then_else (leu (match_dup 1) (const_int 0))
6957 (label_ref (match_operand 0 "" ""))
6960 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6963 (define_expand "bgeu"
6965 (if_then_else (geu (match_dup 1) (const_int 0))
6966 (label_ref (match_operand 0 "" ""))
6969 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6972 (define_expand "bltu"
6974 (if_then_else (ltu (match_dup 1) (const_int 0))
6975 (label_ref (match_operand 0 "" ""))
6978 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6981 (define_expand "bunordered"
6983 (if_then_else (unordered (match_dup 1) (const_int 0))
6984 (label_ref (match_operand 0 "" ""))
6986 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6987 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6991 (define_expand "bordered"
6993 (if_then_else (ordered (match_dup 1) (const_int 0))
6994 (label_ref (match_operand 0 "" ""))
6996 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6997 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7001 (define_expand "bungt"
7003 (if_then_else (ungt (match_dup 1) (const_int 0))
7004 (label_ref (match_operand 0 "" ""))
7006 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7007 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7010 (define_expand "bunlt"
7012 (if_then_else (unlt (match_dup 1) (const_int 0))
7013 (label_ref (match_operand 0 "" ""))
7015 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7016 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7019 (define_expand "bunge"
7021 (if_then_else (unge (match_dup 1) (const_int 0))
7022 (label_ref (match_operand 0 "" ""))
7024 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7025 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7028 (define_expand "bunle"
7030 (if_then_else (unle (match_dup 1) (const_int 0))
7031 (label_ref (match_operand 0 "" ""))
7033 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7034 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7037 ;; The following two patterns need two branch instructions, since there is
7038 ;; no single instruction that will handle all cases.
7039 (define_expand "buneq"
7041 (if_then_else (uneq (match_dup 1) (const_int 0))
7042 (label_ref (match_operand 0 "" ""))
7044 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7045 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7048 (define_expand "bltgt"
7050 (if_then_else (ltgt (match_dup 1) (const_int 0))
7051 (label_ref (match_operand 0 "" ""))
7053 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7054 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7058 ;; Patterns to match conditional branch insns.
7061 ; Special pattern to match UNEQ.
7062 (define_insn "*arm_buneq"
7064 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7065 (label_ref (match_operand 0 "" ""))
7067 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7069 gcc_assert (!arm_ccfsm_state);
7071 return \"bvs\\t%l0\;beq\\t%l0\";
7073 [(set_attr "conds" "jump_clob")
7074 (set_attr "length" "8")]
7077 ; Special pattern to match LTGT.
7078 (define_insn "*arm_bltgt"
7080 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7081 (label_ref (match_operand 0 "" ""))
7083 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7085 gcc_assert (!arm_ccfsm_state);
7087 return \"bmi\\t%l0\;bgt\\t%l0\";
7089 [(set_attr "conds" "jump_clob")
7090 (set_attr "length" "8")]
7093 (define_insn "*arm_cond_branch"
7095 (if_then_else (match_operator 1 "arm_comparison_operator"
7096 [(match_operand 2 "cc_register" "") (const_int 0)])
7097 (label_ref (match_operand 0 "" ""))
7101 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7103 arm_ccfsm_state += 2;
7106 return \"b%d1\\t%l0\";
7108 [(set_attr "conds" "use")
7109 (set_attr "type" "branch")]
7112 ; Special pattern to match reversed UNEQ.
7113 (define_insn "*arm_buneq_reversed"
7115 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7117 (label_ref (match_operand 0 "" ""))))]
7118 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7120 gcc_assert (!arm_ccfsm_state);
7122 return \"bmi\\t%l0\;bgt\\t%l0\";
7124 [(set_attr "conds" "jump_clob")
7125 (set_attr "length" "8")]
7128 ; Special pattern to match reversed LTGT.
7129 (define_insn "*arm_bltgt_reversed"
7131 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7133 (label_ref (match_operand 0 "" ""))))]
7134 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7136 gcc_assert (!arm_ccfsm_state);
7138 return \"bvs\\t%l0\;beq\\t%l0\";
7140 [(set_attr "conds" "jump_clob")
7141 (set_attr "length" "8")]
7144 (define_insn "*arm_cond_branch_reversed"
7146 (if_then_else (match_operator 1 "arm_comparison_operator"
7147 [(match_operand 2 "cc_register" "") (const_int 0)])
7149 (label_ref (match_operand 0 "" ""))))]
7152 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7154 arm_ccfsm_state += 2;
7157 return \"b%D1\\t%l0\";
7159 [(set_attr "conds" "use")
7160 (set_attr "type" "branch")]
7167 (define_expand "seq"
7168 [(set (match_operand:SI 0 "s_register_operand" "")
7169 (eq:SI (match_dup 1) (const_int 0)))]
7171 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7174 (define_expand "sne"
7175 [(set (match_operand:SI 0 "s_register_operand" "")
7176 (ne:SI (match_dup 1) (const_int 0)))]
7178 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7181 (define_expand "sgt"
7182 [(set (match_operand:SI 0 "s_register_operand" "")
7183 (gt:SI (match_dup 1) (const_int 0)))]
7185 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7188 (define_expand "sle"
7189 [(set (match_operand:SI 0 "s_register_operand" "")
7190 (le:SI (match_dup 1) (const_int 0)))]
7192 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7195 (define_expand "sge"
7196 [(set (match_operand:SI 0 "s_register_operand" "")
7197 (ge:SI (match_dup 1) (const_int 0)))]
7199 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7202 (define_expand "slt"
7203 [(set (match_operand:SI 0 "s_register_operand" "")
7204 (lt:SI (match_dup 1) (const_int 0)))]
7206 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7209 (define_expand "sgtu"
7210 [(set (match_operand:SI 0 "s_register_operand" "")
7211 (gtu:SI (match_dup 1) (const_int 0)))]
7213 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7216 (define_expand "sleu"
7217 [(set (match_operand:SI 0 "s_register_operand" "")
7218 (leu:SI (match_dup 1) (const_int 0)))]
7220 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7223 (define_expand "sgeu"
7224 [(set (match_operand:SI 0 "s_register_operand" "")
7225 (geu:SI (match_dup 1) (const_int 0)))]
7227 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7230 (define_expand "sltu"
7231 [(set (match_operand:SI 0 "s_register_operand" "")
7232 (ltu:SI (match_dup 1) (const_int 0)))]
7234 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7237 (define_expand "sunordered"
7238 [(set (match_operand:SI 0 "s_register_operand" "")
7239 (unordered:SI (match_dup 1) (const_int 0)))]
7240 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7241 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7245 (define_expand "sordered"
7246 [(set (match_operand:SI 0 "s_register_operand" "")
7247 (ordered:SI (match_dup 1) (const_int 0)))]
7248 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7253 (define_expand "sungt"
7254 [(set (match_operand:SI 0 "s_register_operand" "")
7255 (ungt:SI (match_dup 1) (const_int 0)))]
7256 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7257 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7261 (define_expand "sunge"
7262 [(set (match_operand:SI 0 "s_register_operand" "")
7263 (unge:SI (match_dup 1) (const_int 0)))]
7264 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7269 (define_expand "sunlt"
7270 [(set (match_operand:SI 0 "s_register_operand" "")
7271 (unlt:SI (match_dup 1) (const_int 0)))]
7272 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7273 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7277 (define_expand "sunle"
7278 [(set (match_operand:SI 0 "s_register_operand" "")
7279 (unle:SI (match_dup 1) (const_int 0)))]
7280 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7281 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7285 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7286 ;;; simple ARM instructions.
7288 ; (define_expand "suneq"
7289 ; [(set (match_operand:SI 0 "s_register_operand" "")
7290 ; (uneq:SI (match_dup 1) (const_int 0)))]
7291 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7292 ; "gcc_unreachable ();"
7295 ; (define_expand "sltgt"
7296 ; [(set (match_operand:SI 0 "s_register_operand" "")
7297 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7298 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7299 ; "gcc_unreachable ();"
7302 (define_insn "*mov_scc"
7303 [(set (match_operand:SI 0 "s_register_operand" "=r")
7304 (match_operator:SI 1 "arm_comparison_operator"
7305 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7307 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7308 [(set_attr "conds" "use")
7309 (set_attr "length" "8")]
7312 (define_insn "*mov_negscc"
7313 [(set (match_operand:SI 0 "s_register_operand" "=r")
7314 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7315 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7317 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7318 [(set_attr "conds" "use")
7319 (set_attr "length" "8")]
7322 (define_insn "*mov_notscc"
7323 [(set (match_operand:SI 0 "s_register_operand" "=r")
7324 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7325 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7327 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7328 [(set_attr "conds" "use")
7329 (set_attr "length" "8")]
7333 ;; Conditional move insns
7335 (define_expand "movsicc"
7336 [(set (match_operand:SI 0 "s_register_operand" "")
7337 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7338 (match_operand:SI 2 "arm_not_operand" "")
7339 (match_operand:SI 3 "arm_not_operand" "")))]
7343 enum rtx_code code = GET_CODE (operands[1]);
7346 if (code == UNEQ || code == LTGT)
7349 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7350 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7354 (define_expand "movsfcc"
7355 [(set (match_operand:SF 0 "s_register_operand" "")
7356 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7357 (match_operand:SF 2 "s_register_operand" "")
7358 (match_operand:SF 3 "nonmemory_operand" "")))]
7362 enum rtx_code code = GET_CODE (operands[1]);
7365 if (code == UNEQ || code == LTGT)
7368 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7369 Otherwise, ensure it is a valid FP add operand */
7370 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7371 || (!arm_float_add_operand (operands[3], SFmode)))
7372 operands[3] = force_reg (SFmode, operands[3]);
7374 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7375 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7379 (define_expand "movdfcc"
7380 [(set (match_operand:DF 0 "s_register_operand" "")
7381 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7382 (match_operand:DF 2 "s_register_operand" "")
7383 (match_operand:DF 3 "arm_float_add_operand" "")))]
7384 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7387 enum rtx_code code = GET_CODE (operands[1]);
7390 if (code == UNEQ || code == LTGT)
7393 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7394 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7398 (define_insn "*movsicc_insn"
7399 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7401 (match_operator 3 "arm_comparison_operator"
7402 [(match_operand 4 "cc_register" "") (const_int 0)])
7403 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7404 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7411 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7412 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7413 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7414 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7415 [(set_attr "length" "4,4,4,4,8,8,8,8")
7416 (set_attr "conds" "use")]
7419 (define_insn "*movsfcc_soft_insn"
7420 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7421 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7422 [(match_operand 4 "cc_register" "") (const_int 0)])
7423 (match_operand:SF 1 "s_register_operand" "0,r")
7424 (match_operand:SF 2 "s_register_operand" "r,0")))]
7425 "TARGET_ARM && TARGET_SOFT_FLOAT"
7429 [(set_attr "conds" "use")]
7433 ;; Jump and linkage insns
7435 (define_expand "jump"
7437 (label_ref (match_operand 0 "" "")))]
7442 (define_insn "*arm_jump"
7444 (label_ref (match_operand 0 "" "")))]
7448 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7450 arm_ccfsm_state += 2;
7453 return \"b%?\\t%l0\";
7456 [(set_attr "predicable" "yes")]
7459 (define_insn "*thumb_jump"
7461 (label_ref (match_operand 0 "" "")))]
7464 if (get_attr_length (insn) == 2)
7466 return \"bl\\t%l0\\t%@ far jump\";
7468 [(set (attr "far_jump")
7470 (eq_attr "length" "4")
7471 (const_string "yes")
7472 (const_string "no")))
7473 (set (attr "length")
7475 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7476 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7481 (define_expand "call"
7482 [(parallel [(call (match_operand 0 "memory_operand" "")
7483 (match_operand 1 "general_operand" ""))
7484 (use (match_operand 2 "" ""))
7485 (clobber (reg:SI LR_REGNUM))])]
7491 /* In an untyped call, we can get NULL for operand 2. */
7492 if (operands[2] == NULL_RTX)
7493 operands[2] = const0_rtx;
7495 /* This is to decide if we should generate indirect calls by loading the
7496 32 bit address of the callee into a register before performing the
7497 branch and link. operand[2] encodes the long_call/short_call
7498 attribute of the function being called. This attribute is set whenever
7499 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7500 is used, and the short_call attribute can also be set if function is
7501 declared as static or if it has already been defined in the current
7502 compilation unit. See arm.c and arm.h for info about this. The third
7503 parameter to arm_is_longcall_p is used to tell it which pattern
7505 callee = XEXP (operands[0], 0);
7507 if (GET_CODE (callee) != REG
7508 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7509 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7513 (define_insn "*call_reg_armv5"
7514 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7515 (match_operand 1 "" ""))
7516 (use (match_operand 2 "" ""))
7517 (clobber (reg:SI LR_REGNUM))]
7518 "TARGET_ARM && arm_arch5"
7520 [(set_attr "type" "call")]
7523 (define_insn "*call_reg_arm"
7524 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7525 (match_operand 1 "" ""))
7526 (use (match_operand 2 "" ""))
7527 (clobber (reg:SI LR_REGNUM))]
7528 "TARGET_ARM && !arm_arch5"
7530 return output_call (operands);
7532 ;; length is worst case, normally it is only two
7533 [(set_attr "length" "12")
7534 (set_attr "type" "call")]
7537 (define_insn "*call_mem"
7538 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7539 (match_operand 1 "" ""))
7540 (use (match_operand 2 "" ""))
7541 (clobber (reg:SI LR_REGNUM))]
7544 return output_call_mem (operands);
7546 [(set_attr "length" "12")
7547 (set_attr "type" "call")]
7550 (define_insn "*call_reg_thumb_v5"
7551 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7552 (match_operand 1 "" ""))
7553 (use (match_operand 2 "" ""))
7554 (clobber (reg:SI LR_REGNUM))]
7555 "TARGET_THUMB && arm_arch5"
7557 [(set_attr "length" "2")
7558 (set_attr "type" "call")]
7561 (define_insn "*call_reg_thumb"
7562 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7563 (match_operand 1 "" ""))
7564 (use (match_operand 2 "" ""))
7565 (clobber (reg:SI LR_REGNUM))]
7566 "TARGET_THUMB && !arm_arch5"
7569 if (!TARGET_CALLER_INTERWORKING)
7570 return thumb_call_via_reg (operands[0]);
7571 else if (operands[1] == const0_rtx)
7572 return \"bl\\t%__interwork_call_via_%0\";
7573 else if (frame_pointer_needed)
7574 return \"bl\\t%__interwork_r7_call_via_%0\";
7576 return \"bl\\t%__interwork_r11_call_via_%0\";
7578 [(set_attr "type" "call")]
7581 (define_expand "call_value"
7582 [(parallel [(set (match_operand 0 "" "")
7583 (call (match_operand 1 "memory_operand" "")
7584 (match_operand 2 "general_operand" "")))
7585 (use (match_operand 3 "" ""))
7586 (clobber (reg:SI LR_REGNUM))])]
7590 rtx callee = XEXP (operands[1], 0);
7592 /* In an untyped call, we can get NULL for operand 2. */
7593 if (operands[3] == 0)
7594 operands[3] = const0_rtx;
7596 /* See the comment in define_expand \"call\". */
7597 if (GET_CODE (callee) != REG
7598 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7599 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7603 (define_insn "*call_value_reg_armv5"
7604 [(set (match_operand 0 "" "")
7605 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7606 (match_operand 2 "" "")))
7607 (use (match_operand 3 "" ""))
7608 (clobber (reg:SI LR_REGNUM))]
7609 "TARGET_ARM && arm_arch5"
7611 [(set_attr "type" "call")]
7614 (define_insn "*call_value_reg_arm"
7615 [(set (match_operand 0 "" "")
7616 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7617 (match_operand 2 "" "")))
7618 (use (match_operand 3 "" ""))
7619 (clobber (reg:SI LR_REGNUM))]
7620 "TARGET_ARM && !arm_arch5"
7622 return output_call (&operands[1]);
7624 [(set_attr "length" "12")
7625 (set_attr "type" "call")]
7628 (define_insn "*call_value_mem"
7629 [(set (match_operand 0 "" "")
7630 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7631 (match_operand 2 "" "")))
7632 (use (match_operand 3 "" ""))
7633 (clobber (reg:SI LR_REGNUM))]
7634 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7636 return output_call_mem (&operands[1]);
7638 [(set_attr "length" "12")
7639 (set_attr "type" "call")]
7642 (define_insn "*call_value_reg_thumb_v5"
7643 [(set (match_operand 0 "" "")
7644 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7645 (match_operand 2 "" "")))
7646 (use (match_operand 3 "" ""))
7647 (clobber (reg:SI LR_REGNUM))]
7648 "TARGET_THUMB && arm_arch5"
7650 [(set_attr "length" "2")
7651 (set_attr "type" "call")]
7654 (define_insn "*call_value_reg_thumb"
7655 [(set (match_operand 0 "" "")
7656 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7657 (match_operand 2 "" "")))
7658 (use (match_operand 3 "" ""))
7659 (clobber (reg:SI LR_REGNUM))]
7660 "TARGET_THUMB && !arm_arch5"
7663 if (!TARGET_CALLER_INTERWORKING)
7664 return thumb_call_via_reg (operands[1]);
7665 else if (operands[2] == const0_rtx)
7666 return \"bl\\t%__interwork_call_via_%1\";
7667 else if (frame_pointer_needed)
7668 return \"bl\\t%__interwork_r7_call_via_%1\";
7670 return \"bl\\t%__interwork_r11_call_via_%1\";
7672 [(set_attr "type" "call")]
7675 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7676 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7678 (define_insn "*call_symbol"
7679 [(call (mem:SI (match_operand:SI 0 "" ""))
7680 (match_operand 1 "" ""))
7681 (use (match_operand 2 "" ""))
7682 (clobber (reg:SI LR_REGNUM))]
7684 && (GET_CODE (operands[0]) == SYMBOL_REF)
7685 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7688 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7690 [(set_attr "type" "call")]
7693 (define_insn "*call_value_symbol"
7694 [(set (match_operand 0 "" "")
7695 (call (mem:SI (match_operand:SI 1 "" ""))
7696 (match_operand:SI 2 "" "")))
7697 (use (match_operand 3 "" ""))
7698 (clobber (reg:SI LR_REGNUM))]
7700 && (GET_CODE (operands[1]) == SYMBOL_REF)
7701 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7704 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7706 [(set_attr "type" "call")]
7709 (define_insn "*call_insn"
7710 [(call (mem:SI (match_operand:SI 0 "" ""))
7711 (match_operand:SI 1 "" ""))
7712 (use (match_operand 2 "" ""))
7713 (clobber (reg:SI LR_REGNUM))]
7715 && GET_CODE (operands[0]) == SYMBOL_REF
7716 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7718 [(set_attr "length" "4")
7719 (set_attr "type" "call")]
7722 (define_insn "*call_value_insn"
7723 [(set (match_operand 0 "" "")
7724 (call (mem:SI (match_operand 1 "" ""))
7725 (match_operand 2 "" "")))
7726 (use (match_operand 3 "" ""))
7727 (clobber (reg:SI LR_REGNUM))]
7729 && GET_CODE (operands[1]) == SYMBOL_REF
7730 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7732 [(set_attr "length" "4")
7733 (set_attr "type" "call")]
7736 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7737 (define_expand "sibcall"
7738 [(parallel [(call (match_operand 0 "memory_operand" "")
7739 (match_operand 1 "general_operand" ""))
7741 (use (match_operand 2 "" ""))])]
7745 if (operands[2] == NULL_RTX)
7746 operands[2] = const0_rtx;
7750 (define_expand "sibcall_value"
7751 [(parallel [(set (match_operand 0 "" "")
7752 (call (match_operand 1 "memory_operand" "")
7753 (match_operand 2 "general_operand" "")))
7755 (use (match_operand 3 "" ""))])]
7759 if (operands[3] == NULL_RTX)
7760 operands[3] = const0_rtx;
7764 (define_insn "*sibcall_insn"
7765 [(call (mem:SI (match_operand:SI 0 "" "X"))
7766 (match_operand 1 "" ""))
7768 (use (match_operand 2 "" ""))]
7769 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7771 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7773 [(set_attr "type" "call")]
7776 (define_insn "*sibcall_value_insn"
7777 [(set (match_operand 0 "" "")
7778 (call (mem:SI (match_operand:SI 1 "" "X"))
7779 (match_operand 2 "" "")))
7781 (use (match_operand 3 "" ""))]
7782 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7784 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7786 [(set_attr "type" "call")]
7789 ;; Often the return insn will be the same as loading from memory, so set attr
7790 (define_insn "return"
7792 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7795 if (arm_ccfsm_state == 2)
7797 arm_ccfsm_state += 2;
7800 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7802 [(set_attr "type" "load1")
7803 (set_attr "length" "12")
7804 (set_attr "predicable" "yes")]
7807 (define_insn "*cond_return"
7809 (if_then_else (match_operator 0 "arm_comparison_operator"
7810 [(match_operand 1 "cc_register" "") (const_int 0)])
7813 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7816 if (arm_ccfsm_state == 2)
7818 arm_ccfsm_state += 2;
7821 return output_return_instruction (operands[0], TRUE, FALSE);
7823 [(set_attr "conds" "use")
7824 (set_attr "length" "12")
7825 (set_attr "type" "load1")]
7828 (define_insn "*cond_return_inverted"
7830 (if_then_else (match_operator 0 "arm_comparison_operator"
7831 [(match_operand 1 "cc_register" "") (const_int 0)])
7834 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7837 if (arm_ccfsm_state == 2)
7839 arm_ccfsm_state += 2;
7842 return output_return_instruction (operands[0], TRUE, TRUE);
7844 [(set_attr "conds" "use")
7845 (set_attr "length" "12")
7846 (set_attr "type" "load1")]
7849 ;; Generate a sequence of instructions to determine if the processor is
7850 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7853 (define_expand "return_addr_mask"
7855 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7857 (set (match_operand:SI 0 "s_register_operand" "")
7858 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7860 (const_int 67108860)))] ; 0x03fffffc
7863 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7866 (define_insn "*check_arch2"
7867 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7868 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7871 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7872 [(set_attr "length" "8")
7873 (set_attr "conds" "set")]
7876 ;; Call subroutine returning any type.
7878 (define_expand "untyped_call"
7879 [(parallel [(call (match_operand 0 "" "")
7881 (match_operand 1 "" "")
7882 (match_operand 2 "" "")])]
7887 rtx par = gen_rtx_PARALLEL (VOIDmode,
7888 rtvec_alloc (XVECLEN (operands[2], 0)));
7889 rtx addr = gen_reg_rtx (Pmode);
7893 emit_move_insn (addr, XEXP (operands[1], 0));
7894 mem = change_address (operands[1], BLKmode, addr);
7896 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7898 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7900 /* Default code only uses r0 as a return value, but we could
7901 be using anything up to 4 registers. */
7902 if (REGNO (src) == R0_REGNUM)
7903 src = gen_rtx_REG (TImode, R0_REGNUM);
7905 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7907 size += GET_MODE_SIZE (GET_MODE (src));
7910 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7915 for (i = 0; i < XVECLEN (par, 0); i++)
7917 HOST_WIDE_INT offset = 0;
7918 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7921 emit_move_insn (addr, plus_constant (addr, size));
7923 mem = change_address (mem, GET_MODE (reg), NULL);
7924 if (REGNO (reg) == R0_REGNUM)
7926 /* On thumb we have to use a write-back instruction. */
7927 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7928 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7929 size = TARGET_ARM ? 16 : 0;
7933 emit_move_insn (mem, reg);
7934 size = GET_MODE_SIZE (GET_MODE (reg));
7938 /* The optimizer does not know that the call sets the function value
7939 registers we stored in the result block. We avoid problems by
7940 claiming that all hard registers are used and clobbered at this
7942 emit_insn (gen_blockage ());
7948 (define_expand "untyped_return"
7949 [(match_operand:BLK 0 "memory_operand" "")
7950 (match_operand 1 "" "")]
7955 rtx addr = gen_reg_rtx (Pmode);
7959 emit_move_insn (addr, XEXP (operands[0], 0));
7960 mem = change_address (operands[0], BLKmode, addr);
7962 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7964 HOST_WIDE_INT offset = 0;
7965 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7968 emit_move_insn (addr, plus_constant (addr, size));
7970 mem = change_address (mem, GET_MODE (reg), NULL);
7971 if (REGNO (reg) == R0_REGNUM)
7973 /* On thumb we have to use a write-back instruction. */
7974 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7975 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7976 size = TARGET_ARM ? 16 : 0;
7980 emit_move_insn (reg, mem);
7981 size = GET_MODE_SIZE (GET_MODE (reg));
7985 /* Emit USE insns before the return. */
7986 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7987 emit_insn (gen_rtx_USE (VOIDmode,
7988 SET_DEST (XVECEXP (operands[1], 0, i))));
7990 /* Construct the return. */
7991 expand_naked_return ();
7997 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7998 ;; all of memory. This blocks insns from being moved across this point.
8000 (define_insn "blockage"
8001 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8004 [(set_attr "length" "0")
8005 (set_attr "type" "block")]
8008 (define_expand "casesi"
8009 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8010 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8011 (match_operand:SI 2 "const_int_operand" "") ; total range
8012 (match_operand:SI 3 "" "") ; table label
8013 (match_operand:SI 4 "" "")] ; Out of range label
8018 if (operands[1] != const0_rtx)
8020 reg = gen_reg_rtx (SImode);
8022 emit_insn (gen_addsi3 (reg, operands[0],
8023 GEN_INT (-INTVAL (operands[1]))));
8027 if (!const_ok_for_arm (INTVAL (operands[2])))
8028 operands[2] = force_reg (SImode, operands[2]);
8030 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8036 ;; The USE in this pattern is needed to tell flow analysis that this is
8037 ;; a CASESI insn. It has no other purpose.
8038 (define_insn "casesi_internal"
8039 [(parallel [(set (pc)
8041 (leu (match_operand:SI 0 "s_register_operand" "r")
8042 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8043 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8044 (label_ref (match_operand 2 "" ""))))
8045 (label_ref (match_operand 3 "" ""))))
8046 (clobber (reg:CC CC_REGNUM))
8047 (use (label_ref (match_dup 2)))])]
8051 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8052 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8054 [(set_attr "conds" "clob")
8055 (set_attr "length" "12")]
8058 (define_expand "indirect_jump"
8060 (match_operand:SI 0 "s_register_operand" ""))]
8065 ;; NB Never uses BX.
8066 (define_insn "*arm_indirect_jump"
8068 (match_operand:SI 0 "s_register_operand" "r"))]
8070 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8071 [(set_attr "predicable" "yes")]
8074 (define_insn "*load_indirect_jump"
8076 (match_operand:SI 0 "memory_operand" "m"))]
8078 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8079 [(set_attr "type" "load1")
8080 (set_attr "pool_range" "4096")
8081 (set_attr "neg_pool_range" "4084")
8082 (set_attr "predicable" "yes")]
8085 ;; NB Never uses BX.
8086 (define_insn "*thumb_indirect_jump"
8088 (match_operand:SI 0 "register_operand" "l*r"))]
8091 [(set_attr "conds" "clob")
8092 (set_attr "length" "2")]
8103 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8104 return \"mov\\tr8, r8\";
8106 [(set (attr "length")
8107 (if_then_else (eq_attr "is_thumb" "yes")
8113 ;; Patterns to allow combination of arithmetic, cond code and shifts
8115 (define_insn "*arith_shiftsi"
8116 [(set (match_operand:SI 0 "s_register_operand" "=r")
8117 (match_operator:SI 1 "shiftable_operator"
8118 [(match_operator:SI 3 "shift_operator"
8119 [(match_operand:SI 4 "s_register_operand" "r")
8120 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8121 (match_operand:SI 2 "s_register_operand" "r")]))]
8123 "%i1%?\\t%0, %2, %4%S3"
8124 [(set_attr "predicable" "yes")
8125 (set_attr "shift" "4")
8126 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8127 (const_string "alu_shift")
8128 (const_string "alu_shift_reg")))]
8132 [(set (match_operand:SI 0 "s_register_operand" "")
8133 (match_operator:SI 1 "shiftable_operator"
8134 [(match_operator:SI 2 "shiftable_operator"
8135 [(match_operator:SI 3 "shift_operator"
8136 [(match_operand:SI 4 "s_register_operand" "")
8137 (match_operand:SI 5 "reg_or_int_operand" "")])
8138 (match_operand:SI 6 "s_register_operand" "")])
8139 (match_operand:SI 7 "arm_rhs_operand" "")]))
8140 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8143 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8146 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8149 (define_insn "*arith_shiftsi_compare0"
8150 [(set (reg:CC_NOOV CC_REGNUM)
8151 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8152 [(match_operator:SI 3 "shift_operator"
8153 [(match_operand:SI 4 "s_register_operand" "r")
8154 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8155 (match_operand:SI 2 "s_register_operand" "r")])
8157 (set (match_operand:SI 0 "s_register_operand" "=r")
8158 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8161 "%i1%?s\\t%0, %2, %4%S3"
8162 [(set_attr "conds" "set")
8163 (set_attr "shift" "4")
8164 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8165 (const_string "alu_shift")
8166 (const_string "alu_shift_reg")))]
8169 (define_insn "*arith_shiftsi_compare0_scratch"
8170 [(set (reg:CC_NOOV CC_REGNUM)
8171 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8172 [(match_operator:SI 3 "shift_operator"
8173 [(match_operand:SI 4 "s_register_operand" "r")
8174 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8175 (match_operand:SI 2 "s_register_operand" "r")])
8177 (clobber (match_scratch:SI 0 "=r"))]
8179 "%i1%?s\\t%0, %2, %4%S3"
8180 [(set_attr "conds" "set")
8181 (set_attr "shift" "4")
8182 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8183 (const_string "alu_shift")
8184 (const_string "alu_shift_reg")))]
8187 (define_insn "*sub_shiftsi"
8188 [(set (match_operand:SI 0 "s_register_operand" "=r")
8189 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8190 (match_operator:SI 2 "shift_operator"
8191 [(match_operand:SI 3 "s_register_operand" "r")
8192 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8194 "sub%?\\t%0, %1, %3%S2"
8195 [(set_attr "predicable" "yes")
8196 (set_attr "shift" "3")
8197 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8198 (const_string "alu_shift")
8199 (const_string "alu_shift_reg")))]
8202 (define_insn "*sub_shiftsi_compare0"
8203 [(set (reg:CC_NOOV CC_REGNUM)
8205 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8206 (match_operator:SI 2 "shift_operator"
8207 [(match_operand:SI 3 "s_register_operand" "r")
8208 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8210 (set (match_operand:SI 0 "s_register_operand" "=r")
8211 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8214 "sub%?s\\t%0, %1, %3%S2"
8215 [(set_attr "conds" "set")
8216 (set_attr "shift" "3")
8217 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8218 (const_string "alu_shift")
8219 (const_string "alu_shift_reg")))]
8222 (define_insn "*sub_shiftsi_compare0_scratch"
8223 [(set (reg:CC_NOOV CC_REGNUM)
8225 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8226 (match_operator:SI 2 "shift_operator"
8227 [(match_operand:SI 3 "s_register_operand" "r")
8228 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8230 (clobber (match_scratch:SI 0 "=r"))]
8232 "sub%?s\\t%0, %1, %3%S2"
8233 [(set_attr "conds" "set")
8234 (set_attr "shift" "3")
8235 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8236 (const_string "alu_shift")
8237 (const_string "alu_shift_reg")))]
8242 (define_insn "*and_scc"
8243 [(set (match_operand:SI 0 "s_register_operand" "=r")
8244 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8245 [(match_operand 3 "cc_register" "") (const_int 0)])
8246 (match_operand:SI 2 "s_register_operand" "r")))]
8248 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8249 [(set_attr "conds" "use")
8250 (set_attr "length" "8")]
8253 (define_insn "*ior_scc"
8254 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8255 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8256 [(match_operand 3 "cc_register" "") (const_int 0)])
8257 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8261 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8262 [(set_attr "conds" "use")
8263 (set_attr "length" "4,8")]
8266 (define_insn "*compare_scc"
8267 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8268 (match_operator:SI 1 "arm_comparison_operator"
8269 [(match_operand:SI 2 "s_register_operand" "r,r")
8270 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8271 (clobber (reg:CC CC_REGNUM))]
8274 if (operands[3] == const0_rtx)
8276 if (GET_CODE (operands[1]) == LT)
8277 return \"mov\\t%0, %2, lsr #31\";
8279 if (GET_CODE (operands[1]) == GE)
8280 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8282 if (GET_CODE (operands[1]) == EQ)
8283 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8286 if (GET_CODE (operands[1]) == NE)
8288 if (which_alternative == 1)
8289 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8290 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8292 if (which_alternative == 1)
8293 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8295 output_asm_insn (\"cmp\\t%2, %3\", operands);
8296 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8298 [(set_attr "conds" "clob")
8299 (set_attr "length" "12")]
8302 (define_insn "*cond_move"
8303 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8304 (if_then_else:SI (match_operator 3 "equality_operator"
8305 [(match_operator 4 "arm_comparison_operator"
8306 [(match_operand 5 "cc_register" "") (const_int 0)])
8308 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8309 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8312 if (GET_CODE (operands[3]) == NE)
8314 if (which_alternative != 1)
8315 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8316 if (which_alternative != 0)
8317 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8320 if (which_alternative != 0)
8321 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8322 if (which_alternative != 1)
8323 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8326 [(set_attr "conds" "use")
8327 (set_attr "length" "4,4,8")]
8330 (define_insn "*cond_arith"
8331 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8332 (match_operator:SI 5 "shiftable_operator"
8333 [(match_operator:SI 4 "arm_comparison_operator"
8334 [(match_operand:SI 2 "s_register_operand" "r,r")
8335 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8336 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8337 (clobber (reg:CC CC_REGNUM))]
8340 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8341 return \"%i5\\t%0, %1, %2, lsr #31\";
8343 output_asm_insn (\"cmp\\t%2, %3\", operands);
8344 if (GET_CODE (operands[5]) == AND)
8345 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8346 else if (GET_CODE (operands[5]) == MINUS)
8347 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8348 else if (which_alternative != 0)
8349 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8350 return \"%i5%d4\\t%0, %1, #1\";
8352 [(set_attr "conds" "clob")
8353 (set_attr "length" "12")]
8356 (define_insn "*cond_sub"
8357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8358 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8359 (match_operator:SI 4 "arm_comparison_operator"
8360 [(match_operand:SI 2 "s_register_operand" "r,r")
8361 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8362 (clobber (reg:CC CC_REGNUM))]
8365 output_asm_insn (\"cmp\\t%2, %3\", operands);
8366 if (which_alternative != 0)
8367 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8368 return \"sub%d4\\t%0, %1, #1\";
8370 [(set_attr "conds" "clob")
8371 (set_attr "length" "8,12")]
8374 (define_insn "*cmp_ite0"
8375 [(set (match_operand 6 "dominant_cc_register" "")
8378 (match_operator 4 "arm_comparison_operator"
8379 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8380 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8381 (match_operator:SI 5 "arm_comparison_operator"
8382 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8383 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8389 static const char * const opcodes[4][2] =
8391 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8392 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8393 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8394 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8395 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8396 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8397 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8398 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8401 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8403 return opcodes[which_alternative][swap];
8405 [(set_attr "conds" "set")
8406 (set_attr "length" "8")]
8409 (define_insn "*cmp_ite1"
8410 [(set (match_operand 6 "dominant_cc_register" "")
8413 (match_operator 4 "arm_comparison_operator"
8414 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8415 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8416 (match_operator:SI 5 "arm_comparison_operator"
8417 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8418 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8424 static const char * const opcodes[4][2] =
8426 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8427 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8428 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8429 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8430 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8431 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8432 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8433 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8436 comparison_dominates_p (GET_CODE (operands[5]),
8437 reverse_condition (GET_CODE (operands[4])));
8439 return opcodes[which_alternative][swap];
8441 [(set_attr "conds" "set")
8442 (set_attr "length" "8")]
8445 (define_insn "*cmp_and"
8446 [(set (match_operand 6 "dominant_cc_register" "")
8449 (match_operator 4 "arm_comparison_operator"
8450 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8451 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8452 (match_operator:SI 5 "arm_comparison_operator"
8453 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8454 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8459 static const char *const opcodes[4][2] =
8461 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8462 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8463 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8464 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8465 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8466 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8467 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8468 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8471 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8473 return opcodes[which_alternative][swap];
8475 [(set_attr "conds" "set")
8476 (set_attr "predicable" "no")
8477 (set_attr "length" "8")]
8480 (define_insn "*cmp_ior"
8481 [(set (match_operand 6 "dominant_cc_register" "")
8484 (match_operator 4 "arm_comparison_operator"
8485 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8486 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8487 (match_operator:SI 5 "arm_comparison_operator"
8488 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8489 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8494 static const char *const opcodes[4][2] =
8496 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8497 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8498 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8499 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8500 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8501 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8502 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8503 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8506 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8508 return opcodes[which_alternative][swap];
8511 [(set_attr "conds" "set")
8512 (set_attr "length" "8")]
8515 (define_insn_and_split "*ior_scc_scc"
8516 [(set (match_operand:SI 0 "s_register_operand" "=r")
8517 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8518 [(match_operand:SI 1 "s_register_operand" "r")
8519 (match_operand:SI 2 "arm_add_operand" "rIL")])
8520 (match_operator:SI 6 "arm_comparison_operator"
8521 [(match_operand:SI 4 "s_register_operand" "r")
8522 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8523 (clobber (reg:CC CC_REGNUM))]
8525 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8528 "TARGET_ARM && reload_completed"
8532 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8533 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8535 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8537 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8540 [(set_attr "conds" "clob")
8541 (set_attr "length" "16")])
8543 ; If the above pattern is followed by a CMP insn, then the compare is
8544 ; redundant, since we can rework the conditional instruction that follows.
8545 (define_insn_and_split "*ior_scc_scc_cmp"
8546 [(set (match_operand 0 "dominant_cc_register" "")
8547 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8548 [(match_operand:SI 1 "s_register_operand" "r")
8549 (match_operand:SI 2 "arm_add_operand" "rIL")])
8550 (match_operator:SI 6 "arm_comparison_operator"
8551 [(match_operand:SI 4 "s_register_operand" "r")
8552 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8554 (set (match_operand:SI 7 "s_register_operand" "=r")
8555 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8556 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8559 "TARGET_ARM && reload_completed"
8563 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8564 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8566 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8568 [(set_attr "conds" "set")
8569 (set_attr "length" "16")])
8571 (define_insn_and_split "*and_scc_scc"
8572 [(set (match_operand:SI 0 "s_register_operand" "=r")
8573 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8574 [(match_operand:SI 1 "s_register_operand" "r")
8575 (match_operand:SI 2 "arm_add_operand" "rIL")])
8576 (match_operator:SI 6 "arm_comparison_operator"
8577 [(match_operand:SI 4 "s_register_operand" "r")
8578 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8579 (clobber (reg:CC CC_REGNUM))]
8581 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8584 "TARGET_ARM && reload_completed
8585 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8590 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8591 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8593 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8595 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8598 [(set_attr "conds" "clob")
8599 (set_attr "length" "16")])
8601 ; If the above pattern is followed by a CMP insn, then the compare is
8602 ; redundant, since we can rework the conditional instruction that follows.
8603 (define_insn_and_split "*and_scc_scc_cmp"
8604 [(set (match_operand 0 "dominant_cc_register" "")
8605 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8606 [(match_operand:SI 1 "s_register_operand" "r")
8607 (match_operand:SI 2 "arm_add_operand" "rIL")])
8608 (match_operator:SI 6 "arm_comparison_operator"
8609 [(match_operand:SI 4 "s_register_operand" "r")
8610 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8612 (set (match_operand:SI 7 "s_register_operand" "=r")
8613 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8614 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8617 "TARGET_ARM && reload_completed"
8621 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8622 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8624 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8626 [(set_attr "conds" "set")
8627 (set_attr "length" "16")])
8629 ;; If there is no dominance in the comparison, then we can still save an
8630 ;; instruction in the AND case, since we can know that the second compare
8631 ;; need only zero the value if false (if true, then the value is already
8633 (define_insn_and_split "*and_scc_scc_nodom"
8634 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8635 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8636 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8637 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8638 (match_operator:SI 6 "arm_comparison_operator"
8639 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8640 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8641 (clobber (reg:CC CC_REGNUM))]
8643 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8646 "TARGET_ARM && reload_completed"
8647 [(parallel [(set (match_dup 0)
8648 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8649 (clobber (reg:CC CC_REGNUM))])
8650 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8652 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8655 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8656 operands[4], operands[5]),
8658 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8660 [(set_attr "conds" "clob")
8661 (set_attr "length" "20")])
8664 [(set (reg:CC_NOOV CC_REGNUM)
8665 (compare:CC_NOOV (ior:SI
8666 (and:SI (match_operand:SI 0 "s_register_operand" "")
8668 (match_operator:SI 1 "comparison_operator"
8669 [(match_operand:SI 2 "s_register_operand" "")
8670 (match_operand:SI 3 "arm_add_operand" "")]))
8672 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8675 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8677 (set (reg:CC_NOOV CC_REGNUM)
8678 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8683 [(set (reg:CC_NOOV CC_REGNUM)
8684 (compare:CC_NOOV (ior:SI
8685 (match_operator:SI 1 "comparison_operator"
8686 [(match_operand:SI 2 "s_register_operand" "")
8687 (match_operand:SI 3 "arm_add_operand" "")])
8688 (and:SI (match_operand:SI 0 "s_register_operand" "")
8691 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8694 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8696 (set (reg:CC_NOOV CC_REGNUM)
8697 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8701 (define_insn "*negscc"
8702 [(set (match_operand:SI 0 "s_register_operand" "=r")
8703 (neg:SI (match_operator 3 "arm_comparison_operator"
8704 [(match_operand:SI 1 "s_register_operand" "r")
8705 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8706 (clobber (reg:CC CC_REGNUM))]
8709 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8710 return \"mov\\t%0, %1, asr #31\";
8712 if (GET_CODE (operands[3]) == NE)
8713 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8715 if (GET_CODE (operands[3]) == GT)
8716 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8718 output_asm_insn (\"cmp\\t%1, %2\", operands);
8719 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8720 return \"mvn%d3\\t%0, #0\";
8722 [(set_attr "conds" "clob")
8723 (set_attr "length" "12")]
8726 (define_insn "movcond"
8727 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8729 (match_operator 5 "arm_comparison_operator"
8730 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8731 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8732 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8733 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8734 (clobber (reg:CC CC_REGNUM))]
8737 if (GET_CODE (operands[5]) == LT
8738 && (operands[4] == const0_rtx))
8740 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8742 if (operands[2] == const0_rtx)
8743 return \"and\\t%0, %1, %3, asr #31\";
8744 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8746 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8748 if (operands[1] == const0_rtx)
8749 return \"bic\\t%0, %2, %3, asr #31\";
8750 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8752 /* The only case that falls through to here is when both ops 1 & 2
8756 if (GET_CODE (operands[5]) == GE
8757 && (operands[4] == const0_rtx))
8759 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8761 if (operands[2] == const0_rtx)
8762 return \"bic\\t%0, %1, %3, asr #31\";
8763 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8765 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8767 if (operands[1] == const0_rtx)
8768 return \"and\\t%0, %2, %3, asr #31\";
8769 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8771 /* The only case that falls through to here is when both ops 1 & 2
8774 if (GET_CODE (operands[4]) == CONST_INT
8775 && !const_ok_for_arm (INTVAL (operands[4])))
8776 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8778 output_asm_insn (\"cmp\\t%3, %4\", operands);
8779 if (which_alternative != 0)
8780 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8781 if (which_alternative != 1)
8782 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8785 [(set_attr "conds" "clob")
8786 (set_attr "length" "8,8,12")]
8789 (define_insn "*ifcompare_plus_move"
8790 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8791 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8792 [(match_operand:SI 4 "s_register_operand" "r,r")
8793 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8795 (match_operand:SI 2 "s_register_operand" "r,r")
8796 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8797 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8798 (clobber (reg:CC CC_REGNUM))]
8801 [(set_attr "conds" "clob")
8802 (set_attr "length" "8,12")]
8805 (define_insn "*if_plus_move"
8806 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8808 (match_operator 4 "arm_comparison_operator"
8809 [(match_operand 5 "cc_register" "") (const_int 0)])
8811 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8812 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8813 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8817 sub%d4\\t%0, %2, #%n3
8818 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8819 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8820 [(set_attr "conds" "use")
8821 (set_attr "length" "4,4,8,8")
8822 (set_attr "type" "*,*,*,*")]
8825 (define_insn "*ifcompare_move_plus"
8826 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8827 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8828 [(match_operand:SI 4 "s_register_operand" "r,r")
8829 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8830 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8832 (match_operand:SI 2 "s_register_operand" "r,r")
8833 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8834 (clobber (reg:CC CC_REGNUM))]
8837 [(set_attr "conds" "clob")
8838 (set_attr "length" "8,12")]
8841 (define_insn "*if_move_plus"
8842 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8844 (match_operator 4 "arm_comparison_operator"
8845 [(match_operand 5 "cc_register" "") (const_int 0)])
8846 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8848 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8849 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8853 sub%D4\\t%0, %2, #%n3
8854 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8855 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8856 [(set_attr "conds" "use")
8857 (set_attr "length" "4,4,8,8")
8858 (set_attr "type" "*,*,*,*")]
8861 (define_insn "*ifcompare_arith_arith"
8862 [(set (match_operand:SI 0 "s_register_operand" "=r")
8863 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8864 [(match_operand:SI 5 "s_register_operand" "r")
8865 (match_operand:SI 6 "arm_add_operand" "rIL")])
8866 (match_operator:SI 8 "shiftable_operator"
8867 [(match_operand:SI 1 "s_register_operand" "r")
8868 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8869 (match_operator:SI 7 "shiftable_operator"
8870 [(match_operand:SI 3 "s_register_operand" "r")
8871 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8872 (clobber (reg:CC CC_REGNUM))]
8875 [(set_attr "conds" "clob")
8876 (set_attr "length" "12")]
8879 (define_insn "*if_arith_arith"
8880 [(set (match_operand:SI 0 "s_register_operand" "=r")
8881 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8882 [(match_operand 8 "cc_register" "") (const_int 0)])
8883 (match_operator:SI 6 "shiftable_operator"
8884 [(match_operand:SI 1 "s_register_operand" "r")
8885 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8886 (match_operator:SI 7 "shiftable_operator"
8887 [(match_operand:SI 3 "s_register_operand" "r")
8888 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8890 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8891 [(set_attr "conds" "use")
8892 (set_attr "length" "8")]
8895 (define_insn "*ifcompare_arith_move"
8896 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8897 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8898 [(match_operand:SI 2 "s_register_operand" "r,r")
8899 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8900 (match_operator:SI 7 "shiftable_operator"
8901 [(match_operand:SI 4 "s_register_operand" "r,r")
8902 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8903 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8904 (clobber (reg:CC CC_REGNUM))]
8907 /* If we have an operation where (op x 0) is the identity operation and
8908 the conditional operator is LT or GE and we are comparing against zero and
8909 everything is in registers then we can do this in two instructions. */
8910 if (operands[3] == const0_rtx
8911 && GET_CODE (operands[7]) != AND
8912 && GET_CODE (operands[5]) == REG
8913 && GET_CODE (operands[1]) == REG
8914 && REGNO (operands[1]) == REGNO (operands[4])
8915 && REGNO (operands[4]) != REGNO (operands[0]))
8917 if (GET_CODE (operands[6]) == LT)
8918 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8919 else if (GET_CODE (operands[6]) == GE)
8920 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8922 if (GET_CODE (operands[3]) == CONST_INT
8923 && !const_ok_for_arm (INTVAL (operands[3])))
8924 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8926 output_asm_insn (\"cmp\\t%2, %3\", operands);
8927 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8928 if (which_alternative != 0)
8929 return \"mov%D6\\t%0, %1\";
8932 [(set_attr "conds" "clob")
8933 (set_attr "length" "8,12")]
8936 (define_insn "*if_arith_move"
8937 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8938 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8939 [(match_operand 6 "cc_register" "") (const_int 0)])
8940 (match_operator:SI 5 "shiftable_operator"
8941 [(match_operand:SI 2 "s_register_operand" "r,r")
8942 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8943 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8947 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8948 [(set_attr "conds" "use")
8949 (set_attr "length" "4,8")
8950 (set_attr "type" "*,*")]
8953 (define_insn "*ifcompare_move_arith"
8954 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8955 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8956 [(match_operand:SI 4 "s_register_operand" "r,r")
8957 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8958 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8959 (match_operator:SI 7 "shiftable_operator"
8960 [(match_operand:SI 2 "s_register_operand" "r,r")
8961 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8962 (clobber (reg:CC CC_REGNUM))]
8965 /* If we have an operation where (op x 0) is the identity operation and
8966 the conditional operator is LT or GE and we are comparing against zero and
8967 everything is in registers then we can do this in two instructions */
8968 if (operands[5] == const0_rtx
8969 && GET_CODE (operands[7]) != AND
8970 && GET_CODE (operands[3]) == REG
8971 && GET_CODE (operands[1]) == REG
8972 && REGNO (operands[1]) == REGNO (operands[2])
8973 && REGNO (operands[2]) != REGNO (operands[0]))
8975 if (GET_CODE (operands[6]) == GE)
8976 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8977 else if (GET_CODE (operands[6]) == LT)
8978 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8981 if (GET_CODE (operands[5]) == CONST_INT
8982 && !const_ok_for_arm (INTVAL (operands[5])))
8983 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8985 output_asm_insn (\"cmp\\t%4, %5\", operands);
8987 if (which_alternative != 0)
8988 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8989 return \"%I7%D6\\t%0, %2, %3\";
8991 [(set_attr "conds" "clob")
8992 (set_attr "length" "8,12")]
8995 (define_insn "*if_move_arith"
8996 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8998 (match_operator 4 "arm_comparison_operator"
8999 [(match_operand 6 "cc_register" "") (const_int 0)])
9000 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9001 (match_operator:SI 5 "shiftable_operator"
9002 [(match_operand:SI 2 "s_register_operand" "r,r")
9003 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9007 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9008 [(set_attr "conds" "use")
9009 (set_attr "length" "4,8")
9010 (set_attr "type" "*,*")]
9013 (define_insn "*ifcompare_move_not"
9014 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9016 (match_operator 5 "arm_comparison_operator"
9017 [(match_operand:SI 3 "s_register_operand" "r,r")
9018 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9019 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9021 (match_operand:SI 2 "s_register_operand" "r,r"))))
9022 (clobber (reg:CC CC_REGNUM))]
9025 [(set_attr "conds" "clob")
9026 (set_attr "length" "8,12")]
9029 (define_insn "*if_move_not"
9030 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9032 (match_operator 4 "arm_comparison_operator"
9033 [(match_operand 3 "cc_register" "") (const_int 0)])
9034 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9035 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9039 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9040 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9041 [(set_attr "conds" "use")
9042 (set_attr "length" "4,8,8")]
9045 (define_insn "*ifcompare_not_move"
9046 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9048 (match_operator 5 "arm_comparison_operator"
9049 [(match_operand:SI 3 "s_register_operand" "r,r")
9050 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9052 (match_operand:SI 2 "s_register_operand" "r,r"))
9053 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9054 (clobber (reg:CC CC_REGNUM))]
9057 [(set_attr "conds" "clob")
9058 (set_attr "length" "8,12")]
9061 (define_insn "*if_not_move"
9062 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9064 (match_operator 4 "arm_comparison_operator"
9065 [(match_operand 3 "cc_register" "") (const_int 0)])
9066 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9067 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9071 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9072 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9073 [(set_attr "conds" "use")
9074 (set_attr "length" "4,8,8")]
9077 (define_insn "*ifcompare_shift_move"
9078 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9080 (match_operator 6 "arm_comparison_operator"
9081 [(match_operand:SI 4 "s_register_operand" "r,r")
9082 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9083 (match_operator:SI 7 "shift_operator"
9084 [(match_operand:SI 2 "s_register_operand" "r,r")
9085 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9086 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9087 (clobber (reg:CC CC_REGNUM))]
9090 [(set_attr "conds" "clob")
9091 (set_attr "length" "8,12")]
9094 (define_insn "*if_shift_move"
9095 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9097 (match_operator 5 "arm_comparison_operator"
9098 [(match_operand 6 "cc_register" "") (const_int 0)])
9099 (match_operator:SI 4 "shift_operator"
9100 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9101 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9102 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9106 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9107 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9108 [(set_attr "conds" "use")
9109 (set_attr "shift" "2")
9110 (set_attr "length" "4,8,8")
9111 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9112 (const_string "alu_shift")
9113 (const_string "alu_shift_reg")))]
9116 (define_insn "*ifcompare_move_shift"
9117 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9119 (match_operator 6 "arm_comparison_operator"
9120 [(match_operand:SI 4 "s_register_operand" "r,r")
9121 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9122 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9123 (match_operator:SI 7 "shift_operator"
9124 [(match_operand:SI 2 "s_register_operand" "r,r")
9125 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9126 (clobber (reg:CC CC_REGNUM))]
9129 [(set_attr "conds" "clob")
9130 (set_attr "length" "8,12")]
9133 (define_insn "*if_move_shift"
9134 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9136 (match_operator 5 "arm_comparison_operator"
9137 [(match_operand 6 "cc_register" "") (const_int 0)])
9138 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9139 (match_operator:SI 4 "shift_operator"
9140 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9141 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9145 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9146 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9147 [(set_attr "conds" "use")
9148 (set_attr "shift" "2")
9149 (set_attr "length" "4,8,8")
9150 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9151 (const_string "alu_shift")
9152 (const_string "alu_shift_reg")))]
9155 (define_insn "*ifcompare_shift_shift"
9156 [(set (match_operand:SI 0 "s_register_operand" "=r")
9158 (match_operator 7 "arm_comparison_operator"
9159 [(match_operand:SI 5 "s_register_operand" "r")
9160 (match_operand:SI 6 "arm_add_operand" "rIL")])
9161 (match_operator:SI 8 "shift_operator"
9162 [(match_operand:SI 1 "s_register_operand" "r")
9163 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9164 (match_operator:SI 9 "shift_operator"
9165 [(match_operand:SI 3 "s_register_operand" "r")
9166 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9167 (clobber (reg:CC CC_REGNUM))]
9170 [(set_attr "conds" "clob")
9171 (set_attr "length" "12")]
9174 (define_insn "*if_shift_shift"
9175 [(set (match_operand:SI 0 "s_register_operand" "=r")
9177 (match_operator 5 "arm_comparison_operator"
9178 [(match_operand 8 "cc_register" "") (const_int 0)])
9179 (match_operator:SI 6 "shift_operator"
9180 [(match_operand:SI 1 "s_register_operand" "r")
9181 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9182 (match_operator:SI 7 "shift_operator"
9183 [(match_operand:SI 3 "s_register_operand" "r")
9184 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9186 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9187 [(set_attr "conds" "use")
9188 (set_attr "shift" "1")
9189 (set_attr "length" "8")
9190 (set (attr "type") (if_then_else
9191 (and (match_operand 2 "const_int_operand" "")
9192 (match_operand 4 "const_int_operand" ""))
9193 (const_string "alu_shift")
9194 (const_string "alu_shift_reg")))]
9197 (define_insn "*ifcompare_not_arith"
9198 [(set (match_operand:SI 0 "s_register_operand" "=r")
9200 (match_operator 6 "arm_comparison_operator"
9201 [(match_operand:SI 4 "s_register_operand" "r")
9202 (match_operand:SI 5 "arm_add_operand" "rIL")])
9203 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9204 (match_operator:SI 7 "shiftable_operator"
9205 [(match_operand:SI 2 "s_register_operand" "r")
9206 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9207 (clobber (reg:CC CC_REGNUM))]
9210 [(set_attr "conds" "clob")
9211 (set_attr "length" "12")]
9214 (define_insn "*if_not_arith"
9215 [(set (match_operand:SI 0 "s_register_operand" "=r")
9217 (match_operator 5 "arm_comparison_operator"
9218 [(match_operand 4 "cc_register" "") (const_int 0)])
9219 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9220 (match_operator:SI 6 "shiftable_operator"
9221 [(match_operand:SI 2 "s_register_operand" "r")
9222 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9224 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9225 [(set_attr "conds" "use")
9226 (set_attr "length" "8")]
9229 (define_insn "*ifcompare_arith_not"
9230 [(set (match_operand:SI 0 "s_register_operand" "=r")
9232 (match_operator 6 "arm_comparison_operator"
9233 [(match_operand:SI 4 "s_register_operand" "r")
9234 (match_operand:SI 5 "arm_add_operand" "rIL")])
9235 (match_operator:SI 7 "shiftable_operator"
9236 [(match_operand:SI 2 "s_register_operand" "r")
9237 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9238 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9239 (clobber (reg:CC CC_REGNUM))]
9242 [(set_attr "conds" "clob")
9243 (set_attr "length" "12")]
9246 (define_insn "*if_arith_not"
9247 [(set (match_operand:SI 0 "s_register_operand" "=r")
9249 (match_operator 5 "arm_comparison_operator"
9250 [(match_operand 4 "cc_register" "") (const_int 0)])
9251 (match_operator:SI 6 "shiftable_operator"
9252 [(match_operand:SI 2 "s_register_operand" "r")
9253 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9254 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9256 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9257 [(set_attr "conds" "use")
9258 (set_attr "length" "8")]
9261 (define_insn "*ifcompare_neg_move"
9262 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9264 (match_operator 5 "arm_comparison_operator"
9265 [(match_operand:SI 3 "s_register_operand" "r,r")
9266 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9267 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9268 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9269 (clobber (reg:CC CC_REGNUM))]
9272 [(set_attr "conds" "clob")
9273 (set_attr "length" "8,12")]
9276 (define_insn "*if_neg_move"
9277 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9279 (match_operator 4 "arm_comparison_operator"
9280 [(match_operand 3 "cc_register" "") (const_int 0)])
9281 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9282 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9286 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9287 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9288 [(set_attr "conds" "use")
9289 (set_attr "length" "4,8,8")]
9292 (define_insn "*ifcompare_move_neg"
9293 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9295 (match_operator 5 "arm_comparison_operator"
9296 [(match_operand:SI 3 "s_register_operand" "r,r")
9297 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9298 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9299 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9300 (clobber (reg:CC CC_REGNUM))]
9303 [(set_attr "conds" "clob")
9304 (set_attr "length" "8,12")]
9307 (define_insn "*if_move_neg"
9308 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9310 (match_operator 4 "arm_comparison_operator"
9311 [(match_operand 3 "cc_register" "") (const_int 0)])
9312 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9313 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9317 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9318 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9319 [(set_attr "conds" "use")
9320 (set_attr "length" "4,8,8")]
9323 (define_insn "*arith_adjacentmem"
9324 [(set (match_operand:SI 0 "s_register_operand" "=r")
9325 (match_operator:SI 1 "shiftable_operator"
9326 [(match_operand:SI 2 "memory_operand" "m")
9327 (match_operand:SI 3 "memory_operand" "m")]))
9328 (clobber (match_scratch:SI 4 "=r"))]
9329 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9335 HOST_WIDE_INT val1 = 0, val2 = 0;
9337 if (REGNO (operands[0]) > REGNO (operands[4]))
9339 ldm[1] = operands[4];
9340 ldm[2] = operands[0];
9344 ldm[1] = operands[0];
9345 ldm[2] = operands[4];
9348 base_reg = XEXP (operands[2], 0);
9350 if (!REG_P (base_reg))
9352 val1 = INTVAL (XEXP (base_reg, 1));
9353 base_reg = XEXP (base_reg, 0);
9356 if (!REG_P (XEXP (operands[3], 0)))
9357 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9359 arith[0] = operands[0];
9360 arith[3] = operands[1];
9374 if (val1 !=0 && val2 != 0)
9376 if (val1 == 4 || val2 == 4)
9377 /* Other val must be 8, since we know they are adjacent and neither
9379 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9384 ldm[0] = ops[0] = operands[4];
9386 ops[2] = GEN_INT (val1);
9387 output_add_immediate (ops);
9389 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9391 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9397 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9399 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9404 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9406 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9408 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9411 [(set_attr "length" "12")
9412 (set_attr "predicable" "yes")
9413 (set_attr "type" "load1")]
9416 ; This pattern is never tried by combine, so do it as a peephole
9419 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9420 (match_operand:SI 1 "arm_general_register_operand" ""))
9421 (set (reg:CC CC_REGNUM)
9422 (compare:CC (match_dup 1) (const_int 0)))]
9424 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9425 (set (match_dup 0) (match_dup 1))])]
9429 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9430 ; reversed, check that the memory references aren't volatile.
9433 [(set (match_operand:SI 0 "s_register_operand" "=r")
9434 (match_operand:SI 4 "memory_operand" "m"))
9435 (set (match_operand:SI 1 "s_register_operand" "=r")
9436 (match_operand:SI 5 "memory_operand" "m"))
9437 (set (match_operand:SI 2 "s_register_operand" "=r")
9438 (match_operand:SI 6 "memory_operand" "m"))
9439 (set (match_operand:SI 3 "s_register_operand" "=r")
9440 (match_operand:SI 7 "memory_operand" "m"))]
9441 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9443 return emit_ldm_seq (operands, 4);
9448 [(set (match_operand:SI 0 "s_register_operand" "=r")
9449 (match_operand:SI 3 "memory_operand" "m"))
9450 (set (match_operand:SI 1 "s_register_operand" "=r")
9451 (match_operand:SI 4 "memory_operand" "m"))
9452 (set (match_operand:SI 2 "s_register_operand" "=r")
9453 (match_operand:SI 5 "memory_operand" "m"))]
9454 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9456 return emit_ldm_seq (operands, 3);
9461 [(set (match_operand:SI 0 "s_register_operand" "=r")
9462 (match_operand:SI 2 "memory_operand" "m"))
9463 (set (match_operand:SI 1 "s_register_operand" "=r")
9464 (match_operand:SI 3 "memory_operand" "m"))]
9465 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9467 return emit_ldm_seq (operands, 2);
9472 [(set (match_operand:SI 4 "memory_operand" "=m")
9473 (match_operand:SI 0 "s_register_operand" "r"))
9474 (set (match_operand:SI 5 "memory_operand" "=m")
9475 (match_operand:SI 1 "s_register_operand" "r"))
9476 (set (match_operand:SI 6 "memory_operand" "=m")
9477 (match_operand:SI 2 "s_register_operand" "r"))
9478 (set (match_operand:SI 7 "memory_operand" "=m")
9479 (match_operand:SI 3 "s_register_operand" "r"))]
9480 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9482 return emit_stm_seq (operands, 4);
9487 [(set (match_operand:SI 3 "memory_operand" "=m")
9488 (match_operand:SI 0 "s_register_operand" "r"))
9489 (set (match_operand:SI 4 "memory_operand" "=m")
9490 (match_operand:SI 1 "s_register_operand" "r"))
9491 (set (match_operand:SI 5 "memory_operand" "=m")
9492 (match_operand:SI 2 "s_register_operand" "r"))]
9493 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9495 return emit_stm_seq (operands, 3);
9500 [(set (match_operand:SI 2 "memory_operand" "=m")
9501 (match_operand:SI 0 "s_register_operand" "r"))
9502 (set (match_operand:SI 3 "memory_operand" "=m")
9503 (match_operand:SI 1 "s_register_operand" "r"))]
9504 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9506 return emit_stm_seq (operands, 2);
9511 [(set (match_operand:SI 0 "s_register_operand" "")
9512 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9514 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9515 [(match_operand:SI 3 "s_register_operand" "")
9516 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9517 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9519 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9520 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9525 ;; This split can be used because CC_Z mode implies that the following
9526 ;; branch will be an equality, or an unsigned inequality, so the sign
9527 ;; extension is not needed.
9530 [(set (reg:CC_Z CC_REGNUM)
9532 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9534 (match_operand 1 "const_int_operand" "")))
9535 (clobber (match_scratch:SI 2 ""))]
9537 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9538 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9539 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9540 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9542 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9546 (define_expand "prologue"
9547 [(clobber (const_int 0))]
9550 arm_expand_prologue ();
9552 thumb_expand_prologue ();
9557 (define_expand "epilogue"
9558 [(clobber (const_int 0))]
9561 if (current_function_calls_eh_return)
9562 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9564 thumb_expand_epilogue ();
9565 else if (USE_RETURN_INSN (FALSE))
9567 emit_jump_insn (gen_return ());
9570 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9572 gen_rtx_RETURN (VOIDmode)),
9578 ;; Note - although unspec_volatile's USE all hard registers,
9579 ;; USEs are ignored after relaod has completed. Thus we need
9580 ;; to add an unspec of the link register to ensure that flow
9581 ;; does not think that it is unused by the sibcall branch that
9582 ;; will replace the standard function epilogue.
9583 (define_insn "sibcall_epilogue"
9584 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9585 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9588 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9589 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9590 return arm_output_epilogue (next_nonnote_insn (insn));
9592 ;; Length is absolute worst case
9593 [(set_attr "length" "44")
9594 (set_attr "type" "block")
9595 ;; We don't clobber the conditions, but the potential length of this
9596 ;; operation is sufficient to make conditionalizing the sequence
9597 ;; unlikely to be profitable.
9598 (set_attr "conds" "clob")]
9601 (define_insn "*epilogue_insns"
9602 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9606 return arm_output_epilogue (NULL);
9607 else /* TARGET_THUMB */
9608 return thumb_unexpanded_epilogue ();
9610 ; Length is absolute worst case
9611 [(set_attr "length" "44")
9612 (set_attr "type" "block")
9613 ;; We don't clobber the conditions, but the potential length of this
9614 ;; operation is sufficient to make conditionalizing the sequence
9615 ;; unlikely to be profitable.
9616 (set_attr "conds" "clob")]
9619 (define_expand "eh_epilogue"
9620 [(use (match_operand:SI 0 "register_operand" ""))
9621 (use (match_operand:SI 1 "register_operand" ""))
9622 (use (match_operand:SI 2 "register_operand" ""))]
9626 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9627 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9629 rtx ra = gen_rtx_REG (Pmode, 2);
9631 emit_move_insn (ra, operands[2]);
9634 /* This is a hack -- we may have crystalized the function type too
9636 cfun->machine->func_type = 0;
9640 ;; This split is only used during output to reduce the number of patterns
9641 ;; that need assembler instructions adding to them. We allowed the setting
9642 ;; of the conditions to be implicit during rtl generation so that
9643 ;; the conditional compare patterns would work. However this conflicts to
9644 ;; some extent with the conditional data operations, so we have to split them
9648 [(set (match_operand:SI 0 "s_register_operand" "")
9649 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9650 [(match_operand 2 "" "") (match_operand 3 "" "")])
9652 (match_operand 4 "" "")))
9653 (clobber (reg:CC CC_REGNUM))]
9654 "TARGET_ARM && reload_completed"
9655 [(set (match_dup 5) (match_dup 6))
9656 (cond_exec (match_dup 7)
9657 (set (match_dup 0) (match_dup 4)))]
9660 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9661 operands[2], operands[3]);
9662 enum rtx_code rc = GET_CODE (operands[1]);
9664 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9665 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9666 if (mode == CCFPmode || mode == CCFPEmode)
9667 rc = reverse_condition_maybe_unordered (rc);
9669 rc = reverse_condition (rc);
9671 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9676 [(set (match_operand:SI 0 "s_register_operand" "")
9677 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9678 [(match_operand 2 "" "") (match_operand 3 "" "")])
9679 (match_operand 4 "" "")
9681 (clobber (reg:CC CC_REGNUM))]
9682 "TARGET_ARM && reload_completed"
9683 [(set (match_dup 5) (match_dup 6))
9684 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9685 (set (match_dup 0) (match_dup 4)))]
9688 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9689 operands[2], operands[3]);
9691 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9692 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9697 [(set (match_operand:SI 0 "s_register_operand" "")
9698 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9699 [(match_operand 2 "" "") (match_operand 3 "" "")])
9700 (match_operand 4 "" "")
9701 (match_operand 5 "" "")))
9702 (clobber (reg:CC CC_REGNUM))]
9703 "TARGET_ARM && reload_completed"
9704 [(set (match_dup 6) (match_dup 7))
9705 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9706 (set (match_dup 0) (match_dup 4)))
9707 (cond_exec (match_dup 8)
9708 (set (match_dup 0) (match_dup 5)))]
9711 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9712 operands[2], operands[3]);
9713 enum rtx_code rc = GET_CODE (operands[1]);
9715 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9716 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9717 if (mode == CCFPmode || mode == CCFPEmode)
9718 rc = reverse_condition_maybe_unordered (rc);
9720 rc = reverse_condition (rc);
9722 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9727 [(set (match_operand:SI 0 "s_register_operand" "")
9728 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9729 [(match_operand:SI 2 "s_register_operand" "")
9730 (match_operand:SI 3 "arm_add_operand" "")])
9731 (match_operand:SI 4 "arm_rhs_operand" "")
9733 (match_operand:SI 5 "s_register_operand" ""))))
9734 (clobber (reg:CC CC_REGNUM))]
9735 "TARGET_ARM && reload_completed"
9736 [(set (match_dup 6) (match_dup 7))
9737 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9738 (set (match_dup 0) (match_dup 4)))
9739 (cond_exec (match_dup 8)
9740 (set (match_dup 0) (not:SI (match_dup 5))))]
9743 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9744 operands[2], operands[3]);
9745 enum rtx_code rc = GET_CODE (operands[1]);
9747 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9748 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9749 if (mode == CCFPmode || mode == CCFPEmode)
9750 rc = reverse_condition_maybe_unordered (rc);
9752 rc = reverse_condition (rc);
9754 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9758 (define_insn "*cond_move_not"
9759 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9760 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9761 [(match_operand 3 "cc_register" "") (const_int 0)])
9762 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9764 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9768 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9769 [(set_attr "conds" "use")
9770 (set_attr "length" "4,8")]
9773 ;; The next two patterns occur when an AND operation is followed by a
9774 ;; scc insn sequence
9776 (define_insn "*sign_extract_onebit"
9777 [(set (match_operand:SI 0 "s_register_operand" "=r")
9778 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9780 (match_operand:SI 2 "const_int_operand" "n")))
9781 (clobber (reg:CC CC_REGNUM))]
9784 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9785 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9786 return \"mvnne\\t%0, #0\";
9788 [(set_attr "conds" "clob")
9789 (set_attr "length" "8")]
9792 (define_insn "*not_signextract_onebit"
9793 [(set (match_operand:SI 0 "s_register_operand" "=r")
9795 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9797 (match_operand:SI 2 "const_int_operand" "n"))))
9798 (clobber (reg:CC CC_REGNUM))]
9801 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9802 output_asm_insn (\"tst\\t%1, %2\", operands);
9803 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9804 return \"movne\\t%0, #0\";
9806 [(set_attr "conds" "clob")
9807 (set_attr "length" "12")]
9810 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9811 ;; expressions. For simplicity, the first register is also in the unspec
9813 (define_insn "*push_multi"
9814 [(match_parallel 2 "multi_register_push"
9815 [(set (match_operand:BLK 0 "memory_operand" "=m")
9816 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9817 UNSPEC_PUSH_MULT))])]
9821 int num_saves = XVECLEN (operands[2], 0);
9823 /* For the StrongARM at least it is faster to
9824 use STR to store only a single register. */
9826 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9832 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9834 for (i = 1; i < num_saves; i++)
9836 strcat (pattern, \", %|\");
9838 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9841 strcat (pattern, \"}\");
9842 output_asm_insn (pattern, operands);
9847 [(set_attr "type" "store4")]
9850 (define_insn "stack_tie"
9851 [(set (mem:BLK (scratch))
9852 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9853 (match_operand:SI 1 "s_register_operand" "r")]
9857 [(set_attr "length" "0")]
9860 ;; Similarly for the floating point registers
9861 (define_insn "*push_fp_multi"
9862 [(match_parallel 2 "multi_register_push"
9863 [(set (match_operand:BLK 0 "memory_operand" "=m")
9864 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9865 UNSPEC_PUSH_MULT))])]
9866 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9871 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9872 output_asm_insn (pattern, operands);
9875 [(set_attr "type" "f_store")]
9878 ;; Special patterns for dealing with the constant pool
9880 (define_insn "align_4"
9881 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9884 assemble_align (32);
9889 (define_insn "align_8"
9890 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9893 assemble_align (64);
9898 (define_insn "consttable_end"
9899 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9902 making_const_table = FALSE;
9907 (define_insn "consttable_1"
9908 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9911 making_const_table = TRUE;
9912 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9916 [(set_attr "length" "4")]
9919 (define_insn "consttable_2"
9920 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9923 making_const_table = TRUE;
9924 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9928 [(set_attr "length" "4")]
9931 (define_insn "consttable_4"
9932 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9936 making_const_table = TRUE;
9937 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9942 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9943 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9947 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9952 [(set_attr "length" "4")]
9955 (define_insn "consttable_8"
9956 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9960 making_const_table = TRUE;
9961 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9966 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9967 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9971 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9976 [(set_attr "length" "8")]
9979 ;; Miscellaneous Thumb patterns
9981 (define_expand "tablejump"
9982 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9983 (use (label_ref (match_operand 1 "" "")))])]
9988 /* Hopefully, CSE will eliminate this copy. */
9989 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9990 rtx reg2 = gen_reg_rtx (SImode);
9992 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9998 ;; NB never uses BX.
9999 (define_insn "*thumb_tablejump"
10000 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10001 (use (label_ref (match_operand 1 "" "")))]
10004 [(set_attr "length" "2")]
10007 ;; V5 Instructions,
10009 (define_insn "clzsi2"
10010 [(set (match_operand:SI 0 "s_register_operand" "=r")
10011 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10012 "TARGET_ARM && arm_arch5"
10014 [(set_attr "predicable" "yes")])
10016 (define_expand "ffssi2"
10017 [(set (match_operand:SI 0 "s_register_operand" "")
10018 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10019 "TARGET_ARM && arm_arch5"
10024 t1 = gen_reg_rtx (SImode);
10025 t2 = gen_reg_rtx (SImode);
10026 t3 = gen_reg_rtx (SImode);
10028 emit_insn (gen_negsi2 (t1, operands[1]));
10029 emit_insn (gen_andsi3 (t2, operands[1], t1));
10030 emit_insn (gen_clzsi2 (t3, t2));
10031 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10036 (define_expand "ctzsi2"
10037 [(set (match_operand:SI 0 "s_register_operand" "")
10038 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10039 "TARGET_ARM && arm_arch5"
10044 t1 = gen_reg_rtx (SImode);
10045 t2 = gen_reg_rtx (SImode);
10046 t3 = gen_reg_rtx (SImode);
10048 emit_insn (gen_negsi2 (t1, operands[1]));
10049 emit_insn (gen_andsi3 (t2, operands[1], t1));
10050 emit_insn (gen_clzsi2 (t3, t2));
10051 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10056 ;; V5E instructions.
10058 (define_insn "prefetch"
10059 [(prefetch (match_operand:SI 0 "address_operand" "p")
10060 (match_operand:SI 1 "" "")
10061 (match_operand:SI 2 "" ""))]
10062 "TARGET_ARM && arm_arch5e"
10065 ;; General predication pattern
10068 [(match_operator 0 "arm_comparison_operator"
10069 [(match_operand 1 "cc_register" "")
10075 (define_insn "prologue_use"
10076 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10078 "%@ %0 needed for prologue"
10082 ;; Patterns for exception handling
10084 (define_expand "eh_return"
10085 [(use (match_operand 0 "general_operand" ""))]
10090 emit_insn (gen_arm_eh_return (operands[0]));
10092 emit_insn (gen_thumb_eh_return (operands[0]));
10097 ;; We can't expand this before we know where the link register is stored.
10098 (define_insn_and_split "arm_eh_return"
10099 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10101 (clobber (match_scratch:SI 1 "=&r"))]
10104 "&& reload_completed"
10108 arm_set_return_address (operands[0], operands[1]);
10113 (define_insn_and_split "thumb_eh_return"
10114 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10116 (clobber (match_scratch:SI 1 "=&l"))]
10119 "&& reload_completed"
10123 thumb_set_return_address (operands[0], operands[1]);
10128 ;; Load the FPA co-processor patterns
10130 ;; Load the Maverick co-processor patterns
10131 (include "cirrus.md")
10132 ;; Load the Intel Wireless Multimedia Extension patterns
10133 (include "iwmmxt.md")
10134 ;; Load the VFP co-processor patterns