1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
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.
93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
99 ;; UNSPEC_VOLATILE Usage:
102 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
104 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105 ; instruction epilogue sequence that isn't expanded
106 ; into normal RTL. Used for both normal and sibcall
108 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
109 ; for inlined constants.
110 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
112 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
114 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
116 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
118 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
120 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
121 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
122 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
123 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
124 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
126 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
131 ;;---------------------------------------------------------------------------
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code. This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
146 ;; Operand number of an input operand that is shifted. Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
150 ; Floating Point Unit. If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns. (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154 (const (symbol_ref "arm_fpu_attr")))
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed. If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171 [(set_attr "conds" "clob")
172 (set_attr "length" "4")
173 (set_attr "pool_range" "250")])
175 ;; The instruction used to implement a particular pattern. This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
180 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
181 (const_string "other"))
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
188 ; Classification of each insn
189 ; alu any alu instruction that doesn't hit memory or fp
190 ; regs or have a shifted source operand
191 ; alu_shift any data instruction that doesn't hit memory or fp
192 ; regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ; regs, but has a source operand shifted by a register value
195 ; mult a multiply instruction
196 ; block blockage insn, this blocks all functional units
197 ; float a floating point arithmetic operation (subject to expansion)
198 ; fdivd DFmode floating point division
199 ; fdivs SFmode floating point division
200 ; fmul Floating point multiply
201 ; ffmul Fast floating point multiply
202 ; farith Floating point arithmetic (4 cycle)
203 ; ffarith Fast floating point arithmetic (2 cycle)
204 ; float_em a floating point arithmetic operation that is normally emulated
205 ; even on a machine with an fpa.
206 ; f_load a floating point load from memory
207 ; f_store a floating point store to memory
208 ; f_load[sd] single/double load from memory
209 ; f_store[sd] single/double store to memory
210 ; f_flag a transfer of co-processor flags to the CPSR
211 ; f_mem_r a transfer of a floating point register to a real reg via mem
212 ; r_mem_f the reverse of f_mem_r
213 ; f_2_r fast transfer float to arm (no memory needed)
214 ; r_2_f fast transfer arm to float
215 ; f_cvt convert floating<->integral
217 ; call a subroutine call
218 ; load_byte load byte(s) from memory to arm registers
219 ; load1 load 1 word from memory to arm registers
220 ; load2 load 2 words from memory to arm registers
221 ; load3 load 3 words from memory to arm registers
222 ; load4 load 4 words from memory to arm registers
223 ; store store 1 word to memory from arm registers
224 ; store2 store 2 words
225 ; store3 store 3 words
226 ; store4 store 4 (or more) words
227 ; Additions for Cirrus Maverick co-processor:
228 ; mav_farith Floating point arithmetic (4 cycle)
229 ; mav_dmult Double multiplies (7 cycle)
232 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
234 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235 (const_string "mult")
236 (const_string "alu")))
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options()
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions. It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
246 ; USE means that the condition codes are used by the insn in the process of
247 ; outputting code, this means (at present) that we can't use the insn in
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ; well defined manner.
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ; they are altered at all
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ; instruction (UNEQ and LTGT). These cannot be predicated.
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ; output of this insn
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263 (if_then_else (eq_attr "type" "call")
264 (const_string "clob")
265 (const_string "nocond")))
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by
269 ; gen...). We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
273 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
274 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor. Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282 (if_then_else (eq_attr "type"
283 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
285 (const_string "no")))
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290 (if_then_else (eq_attr "type"
291 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292 (const_string "single")
293 (const_string "multi")))
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label. Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
300 ;;---------------------------------------------------------------------------
303 ; A list of modes that are exactly 64 bits in size. We use this to expand
304 ; some splits that are the same for all modes when operating on ARM
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
308 ;;---------------------------------------------------------------------------
311 (include "predicates.md")
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
316 ;; Processor type. This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
319 ;; True if the generic scheduling description should be used.
321 (define_attr "generic_sched" "yes,no"
323 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
325 (const_string "yes"))))
327 (define_attr "generic_vfp" "yes,no"
329 (and (eq_attr "fpu" "vfp")
330 (eq_attr "tune" "!arm1020e,arm1022e"))
332 (const_string "no"))))
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
341 ;;---------------------------------------------------------------------------
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
352 (define_expand "adddi3"
354 [(set (match_operand:DI 0 "s_register_operand" "")
355 (plus:DI (match_operand:DI 1 "s_register_operand" "")
356 (match_operand:DI 2 "s_register_operand" "")))
357 (clobber (reg:CC CC_REGNUM))])]
360 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
362 if (!cirrus_fp_register (operands[0], DImode))
363 operands[0] = force_reg (DImode, operands[0]);
364 if (!cirrus_fp_register (operands[1], DImode))
365 operands[1] = force_reg (DImode, operands[1]);
366 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
372 if (GET_CODE (operands[1]) != REG)
373 operands[1] = force_reg (SImode, operands[1]);
374 if (GET_CODE (operands[2]) != REG)
375 operands[2] = force_reg (SImode, operands[2]);
380 (define_insn "*thumb_adddi3"
381 [(set (match_operand:DI 0 "register_operand" "=l")
382 (plus:DI (match_operand:DI 1 "register_operand" "%0")
383 (match_operand:DI 2 "register_operand" "l")))
384 (clobber (reg:CC CC_REGNUM))
387 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388 [(set_attr "length" "4")]
391 (define_insn_and_split "*arm_adddi3"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394 (match_operand:DI 2 "s_register_operand" "r, 0")))
395 (clobber (reg:CC CC_REGNUM))]
396 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398 "TARGET_ARM && reload_completed"
399 [(parallel [(set (reg:CC_C CC_REGNUM)
400 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404 (plus:SI (match_dup 4) (match_dup 5))))]
407 operands[3] = gen_highpart (SImode, operands[0]);
408 operands[0] = gen_lowpart (SImode, operands[0]);
409 operands[4] = gen_highpart (SImode, operands[1]);
410 operands[1] = gen_lowpart (SImode, operands[1]);
411 operands[5] = gen_highpart (SImode, operands[2]);
412 operands[2] = gen_lowpart (SImode, operands[2]);
414 [(set_attr "conds" "clob")
415 (set_attr "length" "8")]
418 (define_insn_and_split "*adddi_sesidi_di"
419 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420 (plus:DI (sign_extend:DI
421 (match_operand:SI 2 "s_register_operand" "r,r"))
422 (match_operand:DI 1 "s_register_operand" "r,0")))
423 (clobber (reg:CC CC_REGNUM))]
424 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
426 "TARGET_ARM && reload_completed"
427 [(parallel [(set (reg:CC_C CC_REGNUM)
428 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
430 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432 (plus:SI (ashiftrt:SI (match_dup 2)
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
447 (define_insn_and_split "*adddi_zesidi_di"
448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449 (plus:DI (zero_extend:DI
450 (match_operand:SI 2 "s_register_operand" "r,r"))
451 (match_operand:DI 1 "s_register_operand" "r,0")))
452 (clobber (reg:CC CC_REGNUM))]
453 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
455 "TARGET_ARM && reload_completed"
456 [(parallel [(set (reg:CC_C CC_REGNUM)
457 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461 (plus:SI (match_dup 4) (const_int 0))))]
464 operands[3] = gen_highpart (SImode, operands[0]);
465 operands[0] = gen_lowpart (SImode, operands[0]);
466 operands[4] = gen_highpart (SImode, operands[1]);
467 operands[1] = gen_lowpart (SImode, operands[1]);
468 operands[2] = gen_lowpart (SImode, operands[2]);
470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")]
474 (define_expand "addsi3"
475 [(set (match_operand:SI 0 "s_register_operand" "")
476 (plus:SI (match_operand:SI 1 "s_register_operand" "")
477 (match_operand:SI 2 "reg_or_int_operand" "")))]
480 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
482 arm_split_constant (PLUS, SImode, NULL_RTX,
483 INTVAL (operands[2]), operands[0], operands[1],
484 optimize && !no_new_pseudos);
490 ; If there is a scratch available, this will be faster than synthesizing the
493 [(match_scratch:SI 3 "r")
494 (set (match_operand:SI 0 "arm_general_register_operand" "")
495 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496 (match_operand:SI 2 "const_int_operand" "")))]
498 !(const_ok_for_arm (INTVAL (operands[2]))
499 || const_ok_for_arm (-INTVAL (operands[2])))
500 && const_ok_for_arm (~INTVAL (operands[2]))"
501 [(set (match_dup 3) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
506 (define_insn_and_split "*arm_addsi3"
507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
508 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
516 GET_CODE (operands[2]) == CONST_INT
517 && !(const_ok_for_arm (INTVAL (operands[2]))
518 || const_ok_for_arm (-INTVAL (operands[2])))"
519 [(clobber (const_int 0))]
521 arm_split_constant (PLUS, SImode, curr_insn,
522 INTVAL (operands[2]), operands[0],
526 [(set_attr "length" "4,4,16")
527 (set_attr "predicable" "yes")]
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register. Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
534 (define_insn "*thumb_addsi3"
535 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
536 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
540 static const char * const asms[] =
542 \"add\\t%0, %0, %2\",
543 \"sub\\t%0, %0, #%n2\",
544 \"add\\t%0, %1, %2\",
545 \"add\\t%0, %0, %2\",
546 \"add\\t%0, %0, %2\",
547 \"add\\t%0, %1, %2\",
550 if ((which_alternative == 2 || which_alternative == 6)
551 && GET_CODE (operands[2]) == CONST_INT
552 && INTVAL (operands[2]) < 0)
553 return \"sub\\t%0, %1, #%n2\";
554 return asms[which_alternative];
556 [(set_attr "length" "2")]
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
562 [(set (match_operand:SI 0 "arm_general_register_operand" "")
563 (match_operand:SI 1 "const_int_operand" ""))
565 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
567 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568 && (INTVAL (operands[1]) & 3) == 0"
569 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
573 (define_insn "*addsi3_compare0"
574 [(set (reg:CC_NOOV CC_REGNUM)
576 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577 (match_operand:SI 2 "arm_add_operand" "rI,L"))
579 (set (match_operand:SI 0 "s_register_operand" "=r,r")
580 (plus:SI (match_dup 1) (match_dup 2)))]
584 sub%?s\\t%0, %1, #%n2"
585 [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch"
589 [(set (reg:CC_NOOV CC_REGNUM)
591 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592 (match_operand:SI 1 "arm_add_operand" "rI,L"))
598 [(set_attr "conds" "set")]
601 (define_insn "*compare_negsi_si"
602 [(set (reg:CC_Z CC_REGNUM)
604 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605 (match_operand:SI 1 "s_register_operand" "r")))]
608 [(set_attr "conds" "set")]
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614 [(set (reg:CC CC_REGNUM)
616 (match_operand:SI 1 "s_register_operand" "r,r")
617 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618 (set (match_operand:SI 0 "s_register_operand" "=r,r")
619 (plus:SI (match_dup 1)
620 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
624 add%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 ;; Convert the sequence
630 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
634 ;; bcs dest ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
639 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
641 (set (match_operand 2 "cc_register" "")
642 (compare (match_dup 0) (const_int -1)))
644 (if_then_else (match_operator 3 "equality_operator"
645 [(match_dup 2) (const_int 0)])
646 (match_operand 4 "" "")
647 (match_operand 5 "" "")))]
648 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
652 (match_dup 1) (const_int 1)))
653 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
655 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
658 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
662 operands[2], const0_rtx);"
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670 [(set (reg:CC_C CC_REGNUM)
672 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673 (match_operand:SI 2 "arm_add_operand" "rI,L"))
675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
676 (plus:SI (match_dup 1) (match_dup 2)))]
680 sub%?s\\t%0, %1, #%n2"
681 [(set_attr "conds" "set")]
684 (define_insn "*addsi3_compare_op2"
685 [(set (reg:CC_C CC_REGNUM)
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
691 (plus:SI (match_dup 1) (match_dup 2)))]
695 sub%?s\\t%0, %1, #%n2"
696 [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op0"
700 [(set (reg:CC_C CC_REGNUM)
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
709 [(set_attr "conds" "set")]
712 (define_insn "*compare_addsi2_op1"
713 [(set (reg:CC_C CC_REGNUM)
715 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
722 [(set_attr "conds" "set")]
725 (define_insn "*addsi3_carryin"
726 [(set (match_operand:SI 0 "s_register_operand" "=r")
727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
732 [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_shift"
736 [(set (match_operand:SI 0 "s_register_operand" "=r")
737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739 (match_operator:SI 2 "shift_operator"
740 [(match_operand:SI 3 "s_register_operand" "r")
741 (match_operand:SI 4 "reg_or_int_operand" "rM")])
742 (match_operand:SI 1 "s_register_operand" "r"))))]
744 "adc%?\\t%0, %1, %3%S2"
745 [(set_attr "conds" "use")
746 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747 (const_string "alu_shift")
748 (const_string "alu_shift_reg")))]
751 (define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
758 [(set_attr "conds" "use")]
761 (define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
768 [(set_attr "conds" "use")]
771 (define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
778 [(set_attr "conds" "use")]
781 (define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,8")]
794 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
796 [(set (match_operand:SI 0 "s_register_operand" "")
797 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798 (match_operand:SI 2 "s_register_operand" ""))
800 (clobber (match_operand:SI 3 "s_register_operand" ""))]
802 [(set (match_dup 3) (match_dup 1))
803 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
805 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
808 (define_expand "addsf3"
809 [(set (match_operand:SF 0 "s_register_operand" "")
810 (plus:SF (match_operand:SF 1 "s_register_operand" "")
811 (match_operand:SF 2 "arm_float_add_operand" "")))]
812 "TARGET_ARM && TARGET_HARD_FLOAT"
815 && !cirrus_fp_register (operands[2], SFmode))
816 operands[2] = force_reg (SFmode, operands[2]);
819 (define_expand "adddf3"
820 [(set (match_operand:DF 0 "s_register_operand" "")
821 (plus:DF (match_operand:DF 1 "s_register_operand" "")
822 (match_operand:DF 2 "arm_float_add_operand" "")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
826 && !cirrus_fp_register (operands[2], DFmode))
827 operands[2] = force_reg (DFmode, operands[2]);
830 (define_expand "subdi3"
832 [(set (match_operand:DI 0 "s_register_operand" "")
833 (minus:DI (match_operand:DI 1 "s_register_operand" "")
834 (match_operand:DI 2 "s_register_operand" "")))
835 (clobber (reg:CC CC_REGNUM))])]
838 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
840 && cirrus_fp_register (operands[0], DImode)
841 && cirrus_fp_register (operands[1], DImode))
843 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
849 if (GET_CODE (operands[1]) != REG)
850 operands[1] = force_reg (SImode, operands[1]);
851 if (GET_CODE (operands[2]) != REG)
852 operands[2] = force_reg (SImode, operands[2]);
857 (define_insn "*arm_subdi3"
858 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
859 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860 (match_operand:DI 2 "s_register_operand" "r,0,0")))
861 (clobber (reg:CC CC_REGNUM))]
863 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864 [(set_attr "conds" "clob")
865 (set_attr "length" "8")]
868 (define_insn "*thumb_subdi3"
869 [(set (match_operand:DI 0 "register_operand" "=l")
870 (minus:DI (match_operand:DI 1 "register_operand" "0")
871 (match_operand:DI 2 "register_operand" "l")))
872 (clobber (reg:CC CC_REGNUM))]
874 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875 [(set_attr "length" "4")]
878 (define_insn "*subdi_di_zesidi"
879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
882 (match_operand:SI 2 "s_register_operand" "r,r"))))
883 (clobber (reg:CC CC_REGNUM))]
885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
890 (define_insn "*subdi_di_sesidi"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
894 (match_operand:SI 2 "s_register_operand" "r,r"))))
895 (clobber (reg:CC CC_REGNUM))]
897 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
902 (define_insn "*subdi_zesidi_di"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (zero_extend:DI
905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
907 (clobber (reg:CC CC_REGNUM))]
909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
914 (define_insn "*subdi_sesidi_di"
915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
916 (minus:DI (sign_extend:DI
917 (match_operand:SI 2 "s_register_operand" "r,r"))
918 (match_operand:DI 1 "s_register_operand" "?r,0")))
919 (clobber (reg:CC CC_REGNUM))]
921 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
926 (define_insn "*subdi_zesidi_zesidi"
927 [(set (match_operand:DI 0 "s_register_operand" "=r")
928 (minus:DI (zero_extend:DI
929 (match_operand:SI 1 "s_register_operand" "r"))
931 (match_operand:SI 2 "s_register_operand" "r"))))
932 (clobber (reg:CC CC_REGNUM))]
934 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935 [(set_attr "conds" "clob")
936 (set_attr "length" "8")]
939 (define_expand "subsi3"
940 [(set (match_operand:SI 0 "s_register_operand" "")
941 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942 (match_operand:SI 2 "s_register_operand" "")))]
945 if (GET_CODE (operands[1]) == CONST_INT)
949 arm_split_constant (MINUS, SImode, NULL_RTX,
950 INTVAL (operands[1]), operands[0],
951 operands[2], optimize && !no_new_pseudos);
954 else /* TARGET_THUMB */
955 operands[1] = force_reg (SImode, operands[1]);
960 (define_insn "*thumb_subsi3_insn"
961 [(set (match_operand:SI 0 "register_operand" "=l")
962 (minus:SI (match_operand:SI 1 "register_operand" "l")
963 (match_operand:SI 2 "register_operand" "l")))]
966 [(set_attr "length" "2")]
969 (define_insn_and_split "*arm_subsi3_insn"
970 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
971 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972 (match_operand:SI 2 "s_register_operand" "r,r")))]
978 && GET_CODE (operands[1]) == CONST_INT
979 && !const_ok_for_arm (INTVAL (operands[1]))"
980 [(clobber (const_int 0))]
982 arm_split_constant (MINUS, SImode, curr_insn,
983 INTVAL (operands[1]), operands[0], operands[2], 0);
986 [(set_attr "length" "4,16")
987 (set_attr "predicable" "yes")]
991 [(match_scratch:SI 3 "r")
992 (set (match_operand:SI 0 "arm_general_register_operand" "")
993 (minus:SI (match_operand:SI 1 "const_int_operand" "")
994 (match_operand:SI 2 "arm_general_register_operand" "")))]
996 && !const_ok_for_arm (INTVAL (operands[1]))
997 && const_ok_for_arm (~INTVAL (operands[1]))"
998 [(set (match_dup 3) (match_dup 1))
999 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1003 (define_insn "*subsi3_compare0"
1004 [(set (reg:CC_NOOV CC_REGNUM)
1006 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1009 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_dup 1) (match_dup 2)))]
1014 rsb%?s\\t%0, %2, %1"
1015 [(set_attr "conds" "set")]
1018 (define_insn "decscc"
1019 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1020 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1021 (match_operator:SI 2 "arm_comparison_operator"
1022 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1026 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027 [(set_attr "conds" "use")
1028 (set_attr "length" "*,8")]
1031 (define_expand "subsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "")
1033 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035 "TARGET_ARM && TARGET_HARD_FLOAT"
1037 if (TARGET_MAVERICK)
1039 if (!cirrus_fp_register (operands[1], SFmode))
1040 operands[1] = force_reg (SFmode, operands[1]);
1041 if (!cirrus_fp_register (operands[2], SFmode))
1042 operands[2] = force_reg (SFmode, operands[2]);
1046 (define_expand "subdf3"
1047 [(set (match_operand:DF 0 "s_register_operand" "")
1048 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050 "TARGET_ARM && TARGET_HARD_FLOAT"
1052 if (TARGET_MAVERICK)
1054 if (!cirrus_fp_register (operands[1], DFmode))
1055 operands[1] = force_reg (DFmode, operands[1]);
1056 if (!cirrus_fp_register (operands[2], DFmode))
1057 operands[2] = force_reg (DFmode, operands[2]);
1062 ;; Multiplication insns
1064 (define_expand "mulsi3"
1065 [(set (match_operand:SI 0 "s_register_operand" "")
1066 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067 (match_operand:SI 1 "s_register_operand" "")))]
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1075 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1078 "mul%?\\t%0, %2, %1"
1079 [(set_attr "insn" "mul")
1080 (set_attr "predicable" "yes")]
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1084 ; 1 and 2; are the same, because reload will make operand 0 match
1085 ; operand 1 without realizing that this conflicts with operand 2. We fix
1086 ; this by adding another alternative to match this case, and then `reload'
1087 ; it ourselves. This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1090 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091 (match_operand:SI 2 "register_operand" "l,l,l")))]
1094 if (which_alternative < 2)
1095 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1097 return \"mul\\t%0, %2\";
1099 [(set_attr "length" "4,4,2")
1100 (set_attr "insn" "mul")]
1103 (define_insn "*mulsi3_compare0"
1104 [(set (reg:CC_NOOV CC_REGNUM)
1105 (compare:CC_NOOV (mult:SI
1106 (match_operand:SI 2 "s_register_operand" "r,r")
1107 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110 (mult:SI (match_dup 2) (match_dup 1)))]
1112 "mul%?s\\t%0, %2, %1"
1113 [(set_attr "conds" "set")
1114 (set_attr "insn" "muls")]
1117 (define_insn "*mulsi_compare0_scratch"
1118 [(set (reg:CC_NOOV CC_REGNUM)
1119 (compare:CC_NOOV (mult:SI
1120 (match_operand:SI 2 "s_register_operand" "r,r")
1121 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1123 (clobber (match_scratch:SI 0 "=&r,&r"))]
1125 "mul%?s\\t%0, %2, %1"
1126 [(set_attr "conds" "set")
1127 (set_attr "insn" "muls")]
1130 ;; Unnamed templates to match MLA instruction.
1132 (define_insn "*mulsi3addsi"
1133 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1135 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1139 "mla%?\\t%0, %2, %1, %3"
1140 [(set_attr "insn" "mla")
1141 (set_attr "predicable" "yes")]
1144 (define_insn "*mulsi3addsi_compare0"
1145 [(set (reg:CC_NOOV CC_REGNUM)
1148 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1156 "mla%?s\\t%0, %2, %1, %3"
1157 [(set_attr "conds" "set")
1158 (set_attr "insn" "mlas")]
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162 [(set (reg:CC_NOOV CC_REGNUM)
1165 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1169 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1171 "mla%?s\\t%0, %2, %1, %3"
1172 [(set_attr "conds" "set")
1173 (set_attr "insn" "mlas")]
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1178 (define_insn "*mulsidi3adddi"
1179 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184 (match_operand:DI 1 "s_register_operand" "0")))]
1185 "TARGET_ARM && arm_arch3m"
1186 "smlal%?\\t%Q0, %R0, %3, %2"
1187 [(set_attr "insn" "smlal")
1188 (set_attr "predicable" "yes")]
1191 (define_insn "mulsidi3"
1192 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196 "TARGET_ARM && arm_arch3m"
1197 "smull%?\\t%Q0, %R0, %1, %2"
1198 [(set_attr "insn" "smull")
1199 (set_attr "predicable" "yes")]
1202 (define_insn "umulsidi3"
1203 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1205 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207 "TARGET_ARM && arm_arch3m"
1208 "umull%?\\t%Q0, %R0, %1, %2"
1209 [(set_attr "insn" "umull")
1210 (set_attr "predicable" "yes")]
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1215 (define_insn "*umulsidi3adddi"
1216 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1219 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221 (match_operand:DI 1 "s_register_operand" "0")))]
1222 "TARGET_ARM && arm_arch3m"
1223 "umlal%?\\t%Q0, %R0, %3, %2"
1224 [(set_attr "insn" "umlal")
1225 (set_attr "predicable" "yes")]
1228 (define_insn "smulsi3_highpart"
1229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1233 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1236 (clobber (match_scratch:SI 3 "=&r,&r"))]
1237 "TARGET_ARM && arm_arch3m"
1238 "smull%?\\t%3, %0, %2, %1"
1239 [(set_attr "insn" "smull")
1240 (set_attr "predicable" "yes")]
1243 (define_insn "umulsi3_highpart"
1244 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1251 (clobber (match_scratch:SI 3 "=&r,&r"))]
1252 "TARGET_ARM && arm_arch3m"
1253 "umull%?\\t%3, %0, %2, %1"
1254 [(set_attr "insn" "umull")
1255 (set_attr "predicable" "yes")]
1258 (define_insn "mulhisi3"
1259 [(set (match_operand:SI 0 "s_register_operand" "=r")
1260 (mult:SI (sign_extend:SI
1261 (match_operand:HI 1 "s_register_operand" "%r"))
1263 (match_operand:HI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_arch5e"
1265 "smulbb%?\\t%0, %1, %2"
1266 [(set_attr "insn" "smulxy")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3tb"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (mult:SI (ashiftrt:SI
1273 (match_operand:SI 1 "s_register_operand" "r")
1276 (match_operand:HI 2 "s_register_operand" "r"))))]
1277 "TARGET_ARM && arm_arch5e"
1278 "smultb%?\\t%0, %1, %2"
1279 [(set_attr "insn" "smulxy")
1280 (set_attr "predicable" "yes")]
1283 (define_insn "*mulhisi3bt"
1284 [(set (match_operand:SI 0 "s_register_operand" "=r")
1285 (mult:SI (sign_extend:SI
1286 (match_operand:HI 1 "s_register_operand" "r"))
1288 (match_operand:SI 2 "s_register_operand" "r")
1290 "TARGET_ARM && arm_arch5e"
1291 "smulbt%?\\t%0, %1, %2"
1292 [(set_attr "insn" "smulxy")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "*mulhisi3tt"
1297 [(set (match_operand:SI 0 "s_register_operand" "=r")
1298 (mult:SI (ashiftrt:SI
1299 (match_operand:SI 1 "s_register_operand" "r")
1302 (match_operand:SI 2 "s_register_operand" "r")
1304 "TARGET_ARM && arm_arch5e"
1305 "smultt%?\\t%0, %1, %2"
1306 [(set_attr "insn" "smulxy")
1307 (set_attr "predicable" "yes")]
1310 (define_insn "*mulhisi3addsi"
1311 [(set (match_operand:SI 0 "s_register_operand" "=r")
1312 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313 (mult:SI (sign_extend:SI
1314 (match_operand:HI 2 "s_register_operand" "%r"))
1316 (match_operand:HI 3 "s_register_operand" "r")))))]
1317 "TARGET_ARM && arm_arch5e"
1318 "smlabb%?\\t%0, %2, %3, %1"
1319 [(set_attr "insn" "smlaxy")
1320 (set_attr "predicable" "yes")]
1323 (define_insn "*mulhidi3adddi"
1324 [(set (match_operand:DI 0 "s_register_operand" "=r")
1326 (match_operand:DI 1 "s_register_operand" "0")
1327 (mult:DI (sign_extend:DI
1328 (match_operand:HI 2 "s_register_operand" "%r"))
1330 (match_operand:HI 3 "s_register_operand" "r")))))]
1331 "TARGET_ARM && arm_arch5e"
1332 "smlalbb%?\\t%Q0, %R0, %2, %3"
1333 [(set_attr "insn" "smlalxy")
1334 (set_attr "predicable" "yes")])
1336 (define_expand "mulsf3"
1337 [(set (match_operand:SF 0 "s_register_operand" "")
1338 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340 "TARGET_ARM && TARGET_HARD_FLOAT"
1343 && !cirrus_fp_register (operands[2], SFmode))
1344 operands[2] = force_reg (SFmode, operands[2]);
1347 (define_expand "muldf3"
1348 [(set (match_operand:DF 0 "s_register_operand" "")
1349 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351 "TARGET_ARM && TARGET_HARD_FLOAT"
1354 && !cirrus_fp_register (operands[2], DFmode))
1355 operands[2] = force_reg (DFmode, operands[2]);
1360 (define_expand "divsf3"
1361 [(set (match_operand:SF 0 "s_register_operand" "")
1362 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1367 (define_expand "divdf3"
1368 [(set (match_operand:DF 0 "s_register_operand" "")
1369 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1376 (define_expand "modsf3"
1377 [(set (match_operand:SF 0 "s_register_operand" "")
1378 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1383 (define_expand "moddf3"
1384 [(set (match_operand:DF 0 "s_register_operand" "")
1385 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1390 ;; Boolean and,ior,xor insns
1392 ;; Split up double word logical operations
1394 ;; Split up simple DImode logical operations. Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1397 [(set (match_operand:DI 0 "s_register_operand" "")
1398 (match_operator:DI 6 "logical_binary_operator"
1399 [(match_operand:DI 1 "s_register_operand" "")
1400 (match_operand:DI 2 "s_register_operand" "")]))]
1401 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1406 operands[3] = gen_highpart (SImode, operands[0]);
1407 operands[0] = gen_lowpart (SImode, operands[0]);
1408 operands[4] = gen_highpart (SImode, operands[1]);
1409 operands[1] = gen_lowpart (SImode, operands[1]);
1410 operands[5] = gen_highpart (SImode, operands[2]);
1411 operands[2] = gen_lowpart (SImode, operands[2]);
1416 [(set (match_operand:DI 0 "s_register_operand" "")
1417 (match_operator:DI 6 "logical_binary_operator"
1418 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419 (match_operand:DI 1 "s_register_operand" "")]))]
1420 "TARGET_ARM && reload_completed"
1421 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422 (set (match_dup 3) (match_op_dup:SI 6
1423 [(ashiftrt:SI (match_dup 2) (const_int 31))
1427 operands[3] = gen_highpart (SImode, operands[0]);
1428 operands[0] = gen_lowpart (SImode, operands[0]);
1429 operands[4] = gen_highpart (SImode, operands[1]);
1430 operands[1] = gen_lowpart (SImode, operands[1]);
1431 operands[5] = gen_highpart (SImode, operands[2]);
1432 operands[2] = gen_lowpart (SImode, operands[2]);
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1439 [(set (match_operand:DI 0 "s_register_operand" "")
1441 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442 (match_operand:DI 1 "s_register_operand" "")))]
1443 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445 (set (match_dup 3) (match_dup 4))]
1448 operands[4] = gen_highpart (SImode, operands[1]);
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[1] = gen_lowpart (SImode, operands[1]);
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1458 [(set (match_operand:DI 0 "s_register_operand" "")
1460 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461 (match_operand:DI 1 "s_register_operand" "")))]
1462 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464 (set (match_dup 3) (match_dup 4))]
1467 operands[4] = gen_highpart (SImode, operands[1]);
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 operands[1] = gen_lowpart (SImode, operands[1]);
1474 (define_insn "anddi3"
1475 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1476 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1477 (match_operand:DI 2 "s_register_operand" "r,r")))]
1478 "TARGET_ARM && ! TARGET_IWMMXT"
1480 [(set_attr "length" "8")]
1483 (define_insn_and_split "*anddi_zesidi_di"
1484 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485 (and:DI (zero_extend:DI
1486 (match_operand:SI 2 "s_register_operand" "r,r"))
1487 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1490 "TARGET_ARM && reload_completed"
1491 ; The zero extend of operand 2 clears the high word of the output
1493 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494 (set (match_dup 3) (const_int 0))]
1497 operands[3] = gen_highpart (SImode, operands[0]);
1498 operands[0] = gen_lowpart (SImode, operands[0]);
1499 operands[1] = gen_lowpart (SImode, operands[1]);
1501 [(set_attr "length" "8")]
1504 (define_insn "*anddi_sesdi_di"
1505 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1506 (and:DI (sign_extend:DI
1507 (match_operand:SI 2 "s_register_operand" "r,r"))
1508 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1511 [(set_attr "length" "8")]
1514 (define_expand "andsi3"
1515 [(set (match_operand:SI 0 "s_register_operand" "")
1516 (and:SI (match_operand:SI 1 "s_register_operand" "")
1517 (match_operand:SI 2 "reg_or_int_operand" "")))]
1522 if (GET_CODE (operands[2]) == CONST_INT)
1524 arm_split_constant (AND, SImode, NULL_RTX,
1525 INTVAL (operands[2]), operands[0],
1526 operands[1], optimize && !no_new_pseudos);
1531 else /* TARGET_THUMB */
1533 if (GET_CODE (operands[2]) != CONST_INT)
1534 operands[2] = force_reg (SImode, operands[2]);
1539 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1541 operands[2] = force_reg (SImode,
1542 GEN_INT (~INTVAL (operands[2])));
1544 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1549 for (i = 9; i <= 31; i++)
1551 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1553 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1557 else if ((((HOST_WIDE_INT) 1) << i) - 1
1558 == ~INTVAL (operands[2]))
1560 rtx shift = GEN_INT (i);
1561 rtx reg = gen_reg_rtx (SImode);
1563 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1570 operands[2] = force_reg (SImode, operands[2]);
1576 (define_insn_and_split "*arm_andsi3_insn"
1577 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1578 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1583 bic%?\\t%0, %1, #%B2
1586 && GET_CODE (operands[2]) == CONST_INT
1587 && !(const_ok_for_arm (INTVAL (operands[2]))
1588 || const_ok_for_arm (~INTVAL (operands[2])))"
1589 [(clobber (const_int 0))]
1591 arm_split_constant (AND, SImode, curr_insn,
1592 INTVAL (operands[2]), operands[0], operands[1], 0);
1595 [(set_attr "length" "4,4,16")
1596 (set_attr "predicable" "yes")]
1599 (define_insn "*thumb_andsi3_insn"
1600 [(set (match_operand:SI 0 "register_operand" "=l")
1601 (and:SI (match_operand:SI 1 "register_operand" "%0")
1602 (match_operand:SI 2 "register_operand" "l")))]
1605 [(set_attr "length" "2")]
1608 (define_insn "*andsi3_compare0"
1609 [(set (reg:CC_NOOV CC_REGNUM)
1611 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1614 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1615 (and:SI (match_dup 1) (match_dup 2)))]
1619 bic%?s\\t%0, %1, #%B2"
1620 [(set_attr "conds" "set")]
1623 (define_insn "*andsi3_compare0_scratch"
1624 [(set (reg:CC_NOOV CC_REGNUM)
1626 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1629 (clobber (match_scratch:SI 2 "=X,r"))]
1633 bic%?s\\t%2, %0, #%B1"
1634 [(set_attr "conds" "set")]
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638 [(set (reg:CC_NOOV CC_REGNUM)
1639 (compare:CC_NOOV (zero_extract:SI
1640 (match_operand:SI 0 "s_register_operand" "r")
1641 (match_operand 1 "const_int_operand" "n")
1642 (match_operand 2 "const_int_operand" "n"))
1645 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646 && INTVAL (operands[1]) > 0
1647 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1650 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651 << INTVAL (operands[2]));
1652 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1655 [(set_attr "conds" "set")]
1658 (define_insn_and_split "*ne_zeroextractsi"
1659 [(set (match_operand:SI 0 "s_register_operand" "=r")
1660 (ne:SI (zero_extract:SI
1661 (match_operand:SI 1 "s_register_operand" "r")
1662 (match_operand:SI 2 "const_int_operand" "n")
1663 (match_operand:SI 3 "const_int_operand" "n"))
1665 (clobber (reg:CC CC_REGNUM))]
1667 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668 && INTVAL (operands[2]) > 0
1669 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1673 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674 && INTVAL (operands[2]) > 0
1675 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1680 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1682 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683 (match_dup 0) (const_int 1)))]
1685 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686 << INTVAL (operands[3]));
1688 [(set_attr "conds" "clob")
1689 (set_attr "length" "8")]
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693 [(set (match_operand:SI 0 "s_register_operand" "=r")
1694 (ne:SI (zero_extract:SI
1695 (match_operand:SI 1 "s_register_operand" "r")
1696 (match_operand:SI 2 "const_int_operand" "n")
1699 (clobber (reg:CC CC_REGNUM))]
1703 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1706 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1708 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709 (match_dup 0) (const_int 1)))]
1711 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1713 [(set_attr "conds" "clob")
1714 (set_attr "length" "8")]
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (if_then_else:SI (ne (zero_extract:SI
1720 (match_operand:SI 1 "s_register_operand" "r")
1721 (match_operand:SI 2 "const_int_operand" "n")
1722 (match_operand:SI 3 "const_int_operand" "n"))
1724 (match_operand:SI 4 "arm_not_operand" "rIK")
1726 (clobber (reg:CC CC_REGNUM))]
1728 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729 && INTVAL (operands[2]) > 0
1730 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1735 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736 && INTVAL (operands[2]) > 0
1737 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1743 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1745 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746 (match_dup 0) (match_dup 4)))]
1748 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749 << INTVAL (operands[3]));
1751 [(set_attr "conds" "clob")
1752 (set_attr "length" "8")]
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (if_then_else:SI (ne (zero_extract:SI
1758 (match_operand:SI 1 "s_register_operand" "r")
1759 (match_operand:SI 2 "const_int_operand" "n")
1762 (match_operand:SI 3 "arm_not_operand" "rIK")
1764 (clobber (reg:CC CC_REGNUM))]
1765 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1767 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1771 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1773 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774 (match_dup 0) (match_dup 3)))]
1776 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1778 [(set_attr "conds" "clob")
1779 (set_attr "length" "8")]
1783 [(set (match_operand:SI 0 "s_register_operand" "")
1784 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785 (match_operand:SI 2 "const_int_operand" "")
1786 (match_operand:SI 3 "const_int_operand" "")))
1787 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1789 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1792 HOST_WIDE_INT temp = INTVAL (operands[2]);
1794 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795 operands[3] = GEN_INT (32 - temp);
1800 [(set (match_operand:SI 0 "s_register_operand" "")
1801 (match_operator:SI 1 "shiftable_operator"
1802 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803 (match_operand:SI 3 "const_int_operand" "")
1804 (match_operand:SI 4 "const_int_operand" ""))
1805 (match_operand:SI 5 "s_register_operand" "")]))
1806 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1808 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1811 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1814 HOST_WIDE_INT temp = INTVAL (operands[3]);
1816 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817 operands[4] = GEN_INT (32 - temp);
1822 [(set (match_operand:SI 0 "s_register_operand" "")
1823 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824 (match_operand:SI 2 "const_int_operand" "")
1825 (match_operand:SI 3 "const_int_operand" "")))]
1827 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1830 HOST_WIDE_INT temp = INTVAL (operands[2]);
1832 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833 operands[3] = GEN_INT (32 - temp);
1838 [(set (match_operand:SI 0 "s_register_operand" "")
1839 (match_operator:SI 1 "shiftable_operator"
1840 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841 (match_operand:SI 3 "const_int_operand" "")
1842 (match_operand:SI 4 "const_int_operand" ""))
1843 (match_operand:SI 5 "s_register_operand" "")]))
1844 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1846 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1849 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1852 HOST_WIDE_INT temp = INTVAL (operands[3]);
1854 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855 operands[4] = GEN_INT (32 - temp);
1859 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself. Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert. This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1868 (define_expand "insv"
1869 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870 (match_operand:SI 1 "general_operand" "")
1871 (match_operand:SI 2 "general_operand" ""))
1872 (match_operand:SI 3 "reg_or_int_operand" ""))]
1876 int start_bit = INTVAL (operands[2]);
1877 int width = INTVAL (operands[1]);
1878 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879 rtx target, subtarget;
1881 target = operands[0];
1882 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1883 subreg as the final target. */
1884 if (GET_CODE (target) == SUBREG)
1886 subtarget = gen_reg_rtx (SImode);
1887 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888 < GET_MODE_SIZE (SImode))
1889 target = SUBREG_REG (target);
1894 if (GET_CODE (operands[3]) == CONST_INT)
1896 /* Since we are inserting a known constant, we may be able to
1897 reduce the number of bits that we have to clear so that
1898 the mask becomes simple. */
1899 /* ??? This code does not check to see if the new mask is actually
1900 simpler. It may not be. */
1901 rtx op1 = gen_reg_rtx (SImode);
1902 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1903 start of this pattern. */
1904 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1907 emit_insn (gen_andsi3 (op1, operands[0],
1908 gen_int_mode (~mask2, SImode)));
1909 emit_insn (gen_iorsi3 (subtarget, op1,
1910 gen_int_mode (op3_value << start_bit, SImode)));
1912 else if (start_bit == 0
1913 && !(const_ok_for_arm (mask)
1914 || const_ok_for_arm (~mask)))
1916 /* A Trick, since we are setting the bottom bits in the word,
1917 we can shift operand[3] up, operand[0] down, OR them together
1918 and rotate the result back again. This takes 3 insns, and
1919 the third might be mergeable into another op. */
1920 /* The shift up copes with the possibility that operand[3] is
1921 wider than the bitfield. */
1922 rtx op0 = gen_reg_rtx (SImode);
1923 rtx op1 = gen_reg_rtx (SImode);
1925 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927 emit_insn (gen_iorsi3 (op1, op1, op0));
1928 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1930 else if ((width + start_bit == 32)
1931 && !(const_ok_for_arm (mask)
1932 || const_ok_for_arm (~mask)))
1934 /* Similar trick, but slightly less efficient. */
1936 rtx op0 = gen_reg_rtx (SImode);
1937 rtx op1 = gen_reg_rtx (SImode);
1939 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1946 rtx op0 = gen_int_mode (mask, SImode);
1947 rtx op1 = gen_reg_rtx (SImode);
1948 rtx op2 = gen_reg_rtx (SImode);
1950 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1952 rtx tmp = gen_reg_rtx (SImode);
1954 emit_insn (gen_movsi (tmp, op0));
1958 /* Mask out any bits in operand[3] that are not needed. */
1959 emit_insn (gen_andsi3 (op1, operands[3], op0));
1961 if (GET_CODE (op0) == CONST_INT
1962 && (const_ok_for_arm (mask << start_bit)
1963 || const_ok_for_arm (~(mask << start_bit))))
1965 op0 = gen_int_mode (~(mask << start_bit), SImode);
1966 emit_insn (gen_andsi3 (op2, operands[0], op0));
1970 if (GET_CODE (op0) == CONST_INT)
1972 rtx tmp = gen_reg_rtx (SImode);
1974 emit_insn (gen_movsi (tmp, op0));
1979 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1981 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1985 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1987 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1990 if (subtarget != target)
1992 /* If TARGET is still a SUBREG, then it must be wider than a word,
1993 so we must be careful only to set the subword we were asked to. */
1994 if (GET_CODE (target) == SUBREG)
1995 emit_move_insn (target, subtarget);
1997 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008 (match_operand:DI 2 "s_register_operand" "0,r")))]
2011 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2016 operands[3] = gen_highpart (SImode, operands[0]);
2017 operands[0] = gen_lowpart (SImode, operands[0]);
2018 operands[4] = gen_highpart (SImode, operands[1]);
2019 operands[1] = gen_lowpart (SImode, operands[1]);
2020 operands[5] = gen_highpart (SImode, operands[2]);
2021 operands[2] = gen_lowpart (SImode, operands[2]);
2023 [(set_attr "length" "8")
2024 (set_attr "predicable" "yes")]
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029 (and:DI (not:DI (zero_extend:DI
2030 (match_operand:SI 2 "s_register_operand" "r,r")))
2031 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2034 bic%?\\t%Q0, %Q1, %2
2036 ; (not (zero_extend ...)) allows us to just copy the high word from
2037 ; operand1 to operand0.
2040 && operands[0] != operands[1]"
2041 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042 (set (match_dup 3) (match_dup 4))]
2045 operands[3] = gen_highpart (SImode, operands[0]);
2046 operands[0] = gen_lowpart (SImode, operands[0]);
2047 operands[4] = gen_highpart (SImode, operands[1]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2050 [(set_attr "length" "4,8")
2051 (set_attr "predicable" "yes")]
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056 (and:DI (not:DI (sign_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r")))
2058 (match_operand:DI 1 "s_register_operand" "0,r")))]
2061 "TARGET_ARM && reload_completed"
2062 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063 (set (match_dup 3) (and:SI (not:SI
2064 (ashiftrt:SI (match_dup 2) (const_int 31)))
2068 operands[3] = gen_highpart (SImode, operands[0]);
2069 operands[0] = gen_lowpart (SImode, operands[0]);
2070 operands[4] = gen_highpart (SImode, operands[1]);
2071 operands[1] = gen_lowpart (SImode, operands[1]);
2073 [(set_attr "length" "8")
2074 (set_attr "predicable" "yes")]
2077 (define_insn "andsi_notsi_si"
2078 [(set (match_operand:SI 0 "s_register_operand" "=r")
2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080 (match_operand:SI 1 "s_register_operand" "r")))]
2082 "bic%?\\t%0, %1, %2"
2083 [(set_attr "predicable" "yes")]
2086 (define_insn "bicsi3"
2087 [(set (match_operand:SI 0 "register_operand" "=l")
2088 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089 (match_operand:SI 2 "register_operand" "0")))]
2092 [(set_attr "length" "2")]
2095 (define_insn "andsi_not_shiftsi_si"
2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098 [(match_operand:SI 2 "s_register_operand" "r")
2099 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100 (match_operand:SI 1 "s_register_operand" "r")))]
2102 "bic%?\\t%0, %1, %2%S4"
2103 [(set_attr "predicable" "yes")
2104 (set_attr "shift" "2")
2105 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106 (const_string "alu_shift")
2107 (const_string "alu_shift_reg")))]
2110 (define_insn "*andsi_notsi_si_compare0"
2111 [(set (reg:CC_NOOV CC_REGNUM)
2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114 (match_operand:SI 1 "s_register_operand" "r"))
2116 (set (match_operand:SI 0 "s_register_operand" "=r")
2117 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2119 "bic%?s\\t%0, %1, %2"
2120 [(set_attr "conds" "set")]
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124 [(set (reg:CC_NOOV CC_REGNUM)
2126 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127 (match_operand:SI 1 "s_register_operand" "r"))
2129 (clobber (match_scratch:SI 0 "=r"))]
2131 "bic%?s\\t%0, %1, %2"
2132 [(set_attr "conds" "set")]
2135 (define_insn "iordi3"
2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2138 (match_operand:DI 2 "s_register_operand" "r,r")))]
2139 "TARGET_ARM && ! TARGET_IWMMXT"
2141 [(set_attr "length" "8")
2142 (set_attr "predicable" "yes")]
2145 (define_insn "*iordi_zesidi_di"
2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147 (ior:DI (zero_extend:DI
2148 (match_operand:SI 2 "s_register_operand" "r,r"))
2149 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2152 orr%?\\t%Q0, %Q1, %2
2154 [(set_attr "length" "4,8")
2155 (set_attr "predicable" "yes")]
2158 (define_insn "*iordi_sesidi_di"
2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (ior:DI (sign_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
2162 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2165 [(set_attr "length" "8")
2166 (set_attr "predicable" "yes")]
2169 (define_expand "iorsi3"
2170 [(set (match_operand:SI 0 "s_register_operand" "")
2171 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172 (match_operand:SI 2 "reg_or_int_operand" "")))]
2175 if (GET_CODE (operands[2]) == CONST_INT)
2179 arm_split_constant (IOR, SImode, NULL_RTX,
2180 INTVAL (operands[2]), operands[0], operands[1],
2181 optimize && !no_new_pseudos);
2184 else /* TARGET_THUMB */
2185 operands [2] = force_reg (SImode, operands [2]);
2190 (define_insn_and_split "*arm_iorsi3"
2191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2192 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2199 && GET_CODE (operands[2]) == CONST_INT
2200 && !const_ok_for_arm (INTVAL (operands[2]))"
2201 [(clobber (const_int 0))]
2203 arm_split_constant (IOR, SImode, curr_insn,
2204 INTVAL (operands[2]), operands[0], operands[1], 0);
2207 [(set_attr "length" "4,16")
2208 (set_attr "predicable" "yes")]
2211 (define_insn "*thumb_iorsi3"
2212 [(set (match_operand:SI 0 "register_operand" "=l")
2213 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214 (match_operand:SI 2 "register_operand" "l")))]
2217 [(set_attr "length" "2")]
2221 [(match_scratch:SI 3 "r")
2222 (set (match_operand:SI 0 "arm_general_register_operand" "")
2223 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224 (match_operand:SI 2 "const_int_operand" "")))]
2226 && !const_ok_for_arm (INTVAL (operands[2]))
2227 && const_ok_for_arm (~INTVAL (operands[2]))"
2228 [(set (match_dup 3) (match_dup 2))
2229 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2233 (define_insn "*iorsi3_compare0"
2234 [(set (reg:CC_NOOV CC_REGNUM)
2235 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238 (set (match_operand:SI 0 "s_register_operand" "=r")
2239 (ior:SI (match_dup 1) (match_dup 2)))]
2241 "orr%?s\\t%0, %1, %2"
2242 [(set_attr "conds" "set")]
2245 (define_insn "*iorsi3_compare0_scratch"
2246 [(set (reg:CC_NOOV CC_REGNUM)
2247 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2250 (clobber (match_scratch:SI 0 "=r"))]
2252 "orr%?s\\t%0, %1, %2"
2253 [(set_attr "conds" "set")]
2256 (define_insn "xordi3"
2257 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2258 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2259 (match_operand:DI 2 "s_register_operand" "r,r")))]
2260 "TARGET_ARM && !TARGET_IWMMXT"
2262 [(set_attr "length" "8")
2263 (set_attr "predicable" "yes")]
2266 (define_insn "*xordi_zesidi_di"
2267 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268 (xor:DI (zero_extend:DI
2269 (match_operand:SI 2 "s_register_operand" "r,r"))
2270 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2273 eor%?\\t%Q0, %Q1, %2
2275 [(set_attr "length" "4,8")
2276 (set_attr "predicable" "yes")]
2279 (define_insn "*xordi_sesidi_di"
2280 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281 (xor:DI (sign_extend:DI
2282 (match_operand:SI 2 "s_register_operand" "r,r"))
2283 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2286 [(set_attr "length" "8")
2287 (set_attr "predicable" "yes")]
2290 (define_expand "xorsi3"
2291 [(set (match_operand:SI 0 "s_register_operand" "")
2292 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293 (match_operand:SI 2 "arm_rhs_operand" "")))]
2296 if (GET_CODE (operands[2]) == CONST_INT)
2297 operands[2] = force_reg (SImode, operands[2]);
2301 (define_insn "*arm_xorsi3"
2302 [(set (match_operand:SI 0 "s_register_operand" "=r")
2303 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2306 "eor%?\\t%0, %1, %2"
2307 [(set_attr "predicable" "yes")]
2310 (define_insn "*thumb_xorsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l")
2312 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313 (match_operand:SI 2 "register_operand" "l")))]
2316 [(set_attr "length" "2")]
2319 (define_insn "*xorsi3_compare0"
2320 [(set (reg:CC_NOOV CC_REGNUM)
2321 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2324 (set (match_operand:SI 0 "s_register_operand" "=r")
2325 (xor:SI (match_dup 1) (match_dup 2)))]
2327 "eor%?s\\t%0, %1, %2"
2328 [(set_attr "conds" "set")]
2331 (define_insn "*xorsi3_compare0_scratch"
2332 [(set (reg:CC_NOOV CC_REGNUM)
2333 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2338 [(set_attr "conds" "set")]
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2346 [(set (match_operand:SI 0 "s_register_operand" "")
2347 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349 (match_operand:SI 3 "arm_rhs_operand" "")))
2350 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2352 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353 (not:SI (match_dup 3))))
2354 (set (match_dup 0) (not:SI (match_dup 4)))]
2358 (define_insn "*andsi_iorsi3_notsi"
2359 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2364 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365 [(set_attr "length" "8")
2366 (set_attr "predicable" "yes")]
2370 [(set (match_operand:SI 0 "s_register_operand" "")
2371 (match_operator:SI 1 "logical_binary_operator"
2372 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373 (match_operand:SI 3 "const_int_operand" "")
2374 (match_operand:SI 4 "const_int_operand" ""))
2375 (match_operator:SI 9 "logical_binary_operator"
2376 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377 (match_operand:SI 6 "const_int_operand" ""))
2378 (match_operand:SI 7 "s_register_operand" "")])]))
2379 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2381 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2385 [(ashift:SI (match_dup 2) (match_dup 4))
2389 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2392 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2396 [(set (match_operand:SI 0 "s_register_operand" "")
2397 (match_operator:SI 1 "logical_binary_operator"
2398 [(match_operator:SI 9 "logical_binary_operator"
2399 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400 (match_operand:SI 6 "const_int_operand" ""))
2401 (match_operand:SI 7 "s_register_operand" "")])
2402 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403 (match_operand:SI 3 "const_int_operand" "")
2404 (match_operand:SI 4 "const_int_operand" ""))]))
2405 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2407 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2411 [(ashift:SI (match_dup 2) (match_dup 4))
2415 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2418 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2422 [(set (match_operand:SI 0 "s_register_operand" "")
2423 (match_operator:SI 1 "logical_binary_operator"
2424 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425 (match_operand:SI 3 "const_int_operand" "")
2426 (match_operand:SI 4 "const_int_operand" ""))
2427 (match_operator:SI 9 "logical_binary_operator"
2428 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429 (match_operand:SI 6 "const_int_operand" ""))
2430 (match_operand:SI 7 "s_register_operand" "")])]))
2431 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2433 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2437 [(ashift:SI (match_dup 2) (match_dup 4))
2441 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2444 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2448 [(set (match_operand:SI 0 "s_register_operand" "")
2449 (match_operator:SI 1 "logical_binary_operator"
2450 [(match_operator:SI 9 "logical_binary_operator"
2451 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452 (match_operand:SI 6 "const_int_operand" ""))
2453 (match_operand:SI 7 "s_register_operand" "")])
2454 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455 (match_operand:SI 3 "const_int_operand" "")
2456 (match_operand:SI 4 "const_int_operand" ""))]))
2457 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2459 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2463 [(ashift:SI (match_dup 2) (match_dup 4))
2467 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2470 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2474 ;; Minimum and maximum insns
2476 (define_expand "smaxsi3"
2478 (set (match_operand:SI 0 "s_register_operand" "")
2479 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2480 (match_operand:SI 2 "arm_rhs_operand" "")))
2481 (clobber (reg:CC CC_REGNUM))])]
2484 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2486 /* No need for a clobber of the condition code register here. */
2487 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2488 gen_rtx_SMAX (SImode, operands[1],
2494 (define_insn "*smax_0"
2495 [(set (match_operand:SI 0 "s_register_operand" "=r")
2496 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2499 "bic%?\\t%0, %1, %1, asr #31"
2500 [(set_attr "predicable" "yes")]
2503 (define_insn "*smax_m1"
2504 [(set (match_operand:SI 0 "s_register_operand" "=r")
2505 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2508 "orr%?\\t%0, %1, %1, asr #31"
2509 [(set_attr "predicable" "yes")]
2512 (define_insn "*smax_insn"
2513 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2514 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2515 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2516 (clobber (reg:CC CC_REGNUM))]
2519 cmp\\t%1, %2\;movlt\\t%0, %2
2520 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2521 [(set_attr "conds" "clob")
2522 (set_attr "length" "8,12")]
2525 (define_expand "sminsi3"
2527 (set (match_operand:SI 0 "s_register_operand" "")
2528 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2529 (match_operand:SI 2 "arm_rhs_operand" "")))
2530 (clobber (reg:CC CC_REGNUM))])]
2533 if (operands[2] == const0_rtx)
2535 /* No need for a clobber of the condition code register here. */
2536 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2537 gen_rtx_SMIN (SImode, operands[1],
2543 (define_insn "*smin_0"
2544 [(set (match_operand:SI 0 "s_register_operand" "=r")
2545 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2548 "and%?\\t%0, %1, %1, asr #31"
2549 [(set_attr "predicable" "yes")]
2552 (define_insn "*smin_insn"
2553 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2554 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2555 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2556 (clobber (reg:CC CC_REGNUM))]
2559 cmp\\t%1, %2\;movge\\t%0, %2
2560 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2561 [(set_attr "conds" "clob")
2562 (set_attr "length" "8,12")]
2565 (define_insn "umaxsi3"
2566 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2567 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2568 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2569 (clobber (reg:CC CC_REGNUM))]
2572 cmp\\t%1, %2\;movcc\\t%0, %2
2573 cmp\\t%1, %2\;movcs\\t%0, %1
2574 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2575 [(set_attr "conds" "clob")
2576 (set_attr "length" "8,8,12")]
2579 (define_insn "uminsi3"
2580 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2581 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2582 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2583 (clobber (reg:CC CC_REGNUM))]
2586 cmp\\t%1, %2\;movcs\\t%0, %2
2587 cmp\\t%1, %2\;movcc\\t%0, %1
2588 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2589 [(set_attr "conds" "clob")
2590 (set_attr "length" "8,8,12")]
2593 (define_insn "*store_minmaxsi"
2594 [(set (match_operand:SI 0 "memory_operand" "=m")
2595 (match_operator:SI 3 "minmax_operator"
2596 [(match_operand:SI 1 "s_register_operand" "r")
2597 (match_operand:SI 2 "s_register_operand" "r")]))
2598 (clobber (reg:CC CC_REGNUM))]
2601 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2602 operands[1], operands[2]);
2603 output_asm_insn (\"cmp\\t%1, %2\", operands);
2604 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2605 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2608 [(set_attr "conds" "clob")
2609 (set_attr "length" "12")
2610 (set_attr "type" "store1")]
2613 ; Reject the frame pointer in operand[1], since reloading this after
2614 ; it has been eliminated can cause carnage.
2615 (define_insn "*minmax_arithsi"
2616 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2617 (match_operator:SI 4 "shiftable_operator"
2618 [(match_operator:SI 5 "minmax_operator"
2619 [(match_operand:SI 2 "s_register_operand" "r,r")
2620 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2621 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2622 (clobber (reg:CC CC_REGNUM))]
2623 "TARGET_ARM && !arm_eliminable_register (operands[1])"
2626 enum rtx_code code = GET_CODE (operands[4]);
2628 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2629 operands[2], operands[3]);
2630 output_asm_insn (\"cmp\\t%2, %3\", operands);
2631 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2632 if (which_alternative != 0 || operands[3] != const0_rtx
2633 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2634 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2637 [(set_attr "conds" "clob")
2638 (set_attr "length" "12")]
2642 ;; Shift and rotation insns
2644 (define_expand "ashldi3"
2645 [(set (match_operand:DI 0 "s_register_operand" "")
2646 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2647 (match_operand:SI 2 "reg_or_int_operand" "")))]
2650 if (GET_CODE (operands[2]) == CONST_INT)
2652 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2654 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2657 /* Ideally we shouldn't fail here if we could know that operands[1]
2658 ends up already living in an iwmmxt register. Otherwise it's
2659 cheaper to have the alternate code being generated than moving
2660 values to iwmmxt regs and back. */
2663 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2668 (define_insn "arm_ashldi3_1bit"
2669 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2670 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2672 (clobber (reg:CC CC_REGNUM))]
2674 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2675 [(set_attr "conds" "clob")
2676 (set_attr "length" "8")]
2679 (define_expand "ashlsi3"
2680 [(set (match_operand:SI 0 "s_register_operand" "")
2681 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2682 (match_operand:SI 2 "arm_rhs_operand" "")))]
2685 if (GET_CODE (operands[2]) == CONST_INT
2686 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2688 emit_insn (gen_movsi (operands[0], const0_rtx));
2694 (define_insn "*thumb_ashlsi3"
2695 [(set (match_operand:SI 0 "register_operand" "=l,l")
2696 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2697 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2700 [(set_attr "length" "2")]
2703 (define_expand "ashrdi3"
2704 [(set (match_operand:DI 0 "s_register_operand" "")
2705 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2706 (match_operand:SI 2 "reg_or_int_operand" "")))]
2709 if (GET_CODE (operands[2]) == CONST_INT)
2711 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2713 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2716 /* Ideally we shouldn't fail here if we could know that operands[1]
2717 ends up already living in an iwmmxt register. Otherwise it's
2718 cheaper to have the alternate code being generated than moving
2719 values to iwmmxt regs and back. */
2722 else if (!TARGET_REALLY_IWMMXT)
2727 (define_insn "arm_ashrdi3_1bit"
2728 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2729 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2731 (clobber (reg:CC CC_REGNUM))]
2733 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2734 [(set_attr "conds" "clob")
2735 (set_attr "length" "8")]
2738 (define_expand "ashrsi3"
2739 [(set (match_operand:SI 0 "s_register_operand" "")
2740 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2741 (match_operand:SI 2 "arm_rhs_operand" "")))]
2744 if (GET_CODE (operands[2]) == CONST_INT
2745 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2746 operands[2] = GEN_INT (31);
2750 (define_insn "*thumb_ashrsi3"
2751 [(set (match_operand:SI 0 "register_operand" "=l,l")
2752 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2753 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2756 [(set_attr "length" "2")]
2759 (define_expand "lshrdi3"
2760 [(set (match_operand:DI 0 "s_register_operand" "")
2761 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2762 (match_operand:SI 2 "reg_or_int_operand" "")))]
2765 if (GET_CODE (operands[2]) == CONST_INT)
2767 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2769 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2772 /* Ideally we shouldn't fail here if we could know that operands[1]
2773 ends up already living in an iwmmxt register. Otherwise it's
2774 cheaper to have the alternate code being generated than moving
2775 values to iwmmxt regs and back. */
2778 else if (!TARGET_REALLY_IWMMXT)
2783 (define_insn "arm_lshrdi3_1bit"
2784 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2785 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2787 (clobber (reg:CC CC_REGNUM))]
2789 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2790 [(set_attr "conds" "clob")
2791 (set_attr "length" "8")]
2794 (define_expand "lshrsi3"
2795 [(set (match_operand:SI 0 "s_register_operand" "")
2796 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2797 (match_operand:SI 2 "arm_rhs_operand" "")))]
2800 if (GET_CODE (operands[2]) == CONST_INT
2801 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2803 emit_insn (gen_movsi (operands[0], const0_rtx));
2809 (define_insn "*thumb_lshrsi3"
2810 [(set (match_operand:SI 0 "register_operand" "=l,l")
2811 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2812 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2815 [(set_attr "length" "2")]
2818 (define_expand "rotlsi3"
2819 [(set (match_operand:SI 0 "s_register_operand" "")
2820 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2821 (match_operand:SI 2 "reg_or_int_operand" "")))]
2824 if (GET_CODE (operands[2]) == CONST_INT)
2825 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2828 rtx reg = gen_reg_rtx (SImode);
2829 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2835 (define_expand "rotrsi3"
2836 [(set (match_operand:SI 0 "s_register_operand" "")
2837 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2838 (match_operand:SI 2 "arm_rhs_operand" "")))]
2843 if (GET_CODE (operands[2]) == CONST_INT
2844 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2845 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2847 else /* TARGET_THUMB */
2849 if (GET_CODE (operands [2]) == CONST_INT)
2850 operands [2] = force_reg (SImode, operands[2]);
2855 (define_insn "*thumb_rotrsi3"
2856 [(set (match_operand:SI 0 "register_operand" "=l")
2857 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2858 (match_operand:SI 2 "register_operand" "l")))]
2861 [(set_attr "length" "2")]
2864 (define_insn "*arm_shiftsi3"
2865 [(set (match_operand:SI 0 "s_register_operand" "=r")
2866 (match_operator:SI 3 "shift_operator"
2867 [(match_operand:SI 1 "s_register_operand" "r")
2868 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2871 [(set_attr "predicable" "yes")
2872 (set_attr "shift" "1")
2873 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874 (const_string "alu_shift")
2875 (const_string "alu_shift_reg")))]
2878 (define_insn "*shiftsi3_compare0"
2879 [(set (reg:CC_NOOV CC_REGNUM)
2880 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2881 [(match_operand:SI 1 "s_register_operand" "r")
2882 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2884 (set (match_operand:SI 0 "s_register_operand" "=r")
2885 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2887 "mov%?s\\t%0, %1%S3"
2888 [(set_attr "conds" "set")
2889 (set_attr "shift" "1")
2890 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2891 (const_string "alu_shift")
2892 (const_string "alu_shift_reg")))]
2895 (define_insn "*shiftsi3_compare0_scratch"
2896 [(set (reg:CC_NOOV CC_REGNUM)
2897 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2898 [(match_operand:SI 1 "s_register_operand" "r")
2899 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2901 (clobber (match_scratch:SI 0 "=r"))]
2903 "mov%?s\\t%0, %1%S3"
2904 [(set_attr "conds" "set")
2905 (set_attr "shift" "1")]
2908 (define_insn "*notsi_shiftsi"
2909 [(set (match_operand:SI 0 "s_register_operand" "=r")
2910 (not:SI (match_operator:SI 3 "shift_operator"
2911 [(match_operand:SI 1 "s_register_operand" "r")
2912 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2915 [(set_attr "predicable" "yes")
2916 (set_attr "shift" "1")
2917 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2918 (const_string "alu_shift")
2919 (const_string "alu_shift_reg")))]
2922 (define_insn "*notsi_shiftsi_compare0"
2923 [(set (reg:CC_NOOV CC_REGNUM)
2924 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2925 [(match_operand:SI 1 "s_register_operand" "r")
2926 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2928 (set (match_operand:SI 0 "s_register_operand" "=r")
2929 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2931 "mvn%?s\\t%0, %1%S3"
2932 [(set_attr "conds" "set")
2933 (set_attr "shift" "1")
2934 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2935 (const_string "alu_shift")
2936 (const_string "alu_shift_reg")))]
2939 (define_insn "*not_shiftsi_compare0_scratch"
2940 [(set (reg:CC_NOOV CC_REGNUM)
2941 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2942 [(match_operand:SI 1 "s_register_operand" "r")
2943 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2945 (clobber (match_scratch:SI 0 "=r"))]
2947 "mvn%?s\\t%0, %1%S3"
2948 [(set_attr "conds" "set")
2949 (set_attr "shift" "1")
2950 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2951 (const_string "alu_shift")
2952 (const_string "alu_shift_reg")))]
2955 ;; We don't really have extzv, but defining this using shifts helps
2956 ;; to reduce register pressure later on.
2958 (define_expand "extzv"
2960 (ashift:SI (match_operand:SI 1 "register_operand" "")
2961 (match_operand:SI 2 "const_int_operand" "")))
2962 (set (match_operand:SI 0 "register_operand" "")
2963 (lshiftrt:SI (match_dup 4)
2964 (match_operand:SI 3 "const_int_operand" "")))]
2968 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2969 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2971 operands[3] = GEN_INT (rshift);
2975 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2979 operands[2] = GEN_INT (lshift);
2980 operands[4] = gen_reg_rtx (SImode);
2985 ;; Unary arithmetic insns
2987 (define_expand "negdi2"
2989 [(set (match_operand:DI 0 "s_register_operand" "")
2990 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2991 (clobber (reg:CC CC_REGNUM))])]
2996 if (GET_CODE (operands[1]) != REG)
2997 operands[1] = force_reg (SImode, operands[1]);
3002 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3003 ;; The second alternative is to allow the common case of a *full* overlap.
3004 (define_insn "*arm_negdi2"
3005 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3006 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
3007 (clobber (reg:CC CC_REGNUM))]
3009 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3010 [(set_attr "conds" "clob")
3011 (set_attr "length" "8")]
3014 (define_insn "*thumb_negdi2"
3015 [(set (match_operand:DI 0 "register_operand" "=&l")
3016 (neg:DI (match_operand:DI 1 "register_operand" "l")))
3017 (clobber (reg:CC CC_REGNUM))]
3019 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3020 [(set_attr "length" "6")]
3023 (define_expand "negsi2"
3024 [(set (match_operand:SI 0 "s_register_operand" "")
3025 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3030 (define_insn "*arm_negsi2"
3031 [(set (match_operand:SI 0 "s_register_operand" "=r")
3032 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3034 "rsb%?\\t%0, %1, #0"
3035 [(set_attr "predicable" "yes")]
3038 (define_insn "*thumb_negsi2"
3039 [(set (match_operand:SI 0 "register_operand" "=l")
3040 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3043 [(set_attr "length" "2")]
3046 (define_expand "negsf2"
3047 [(set (match_operand:SF 0 "s_register_operand" "")
3048 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3049 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3053 (define_expand "negdf2"
3054 [(set (match_operand:DF 0 "s_register_operand" "")
3055 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3056 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3059 ;; abssi2 doesn't really clobber the condition codes if a different register
3060 ;; is being set. To keep things simple, assume during rtl manipulations that
3061 ;; it does, but tell the final scan operator the truth. Similarly for
3064 (define_expand "abssi2"
3066 [(set (match_operand:SI 0 "s_register_operand" "")
3067 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3068 (clobber (reg:CC CC_REGNUM))])]
3072 (define_insn "*arm_abssi2"
3073 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3074 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3075 (clobber (reg:CC CC_REGNUM))]
3078 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3079 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3080 [(set_attr "conds" "clob,*")
3081 (set_attr "shift" "1")
3082 ;; predicable can't be set based on the variant, so left as no
3083 (set_attr "length" "8")]
3086 (define_insn "*neg_abssi2"
3087 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3088 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3089 (clobber (reg:CC CC_REGNUM))]
3092 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3093 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3094 [(set_attr "conds" "clob,*")
3095 (set_attr "shift" "1")
3096 ;; predicable can't be set based on the variant, so left as no
3097 (set_attr "length" "8")]
3100 (define_expand "abssf2"
3101 [(set (match_operand:SF 0 "s_register_operand" "")
3102 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3103 "TARGET_ARM && TARGET_HARD_FLOAT"
3106 (define_expand "absdf2"
3107 [(set (match_operand:DF 0 "s_register_operand" "")
3108 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3109 "TARGET_ARM && TARGET_HARD_FLOAT"
3112 (define_expand "sqrtsf2"
3113 [(set (match_operand:SF 0 "s_register_operand" "")
3114 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3115 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3118 (define_expand "sqrtdf2"
3119 [(set (match_operand:DF 0 "s_register_operand" "")
3120 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3121 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3124 (define_insn_and_split "one_cmpldi2"
3125 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3126 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3129 "TARGET_ARM && reload_completed"
3130 [(set (match_dup 0) (not:SI (match_dup 1)))
3131 (set (match_dup 2) (not:SI (match_dup 3)))]
3134 operands[2] = gen_highpart (SImode, operands[0]);
3135 operands[0] = gen_lowpart (SImode, operands[0]);
3136 operands[3] = gen_highpart (SImode, operands[1]);
3137 operands[1] = gen_lowpart (SImode, operands[1]);
3139 [(set_attr "length" "8")
3140 (set_attr "predicable" "yes")]
3143 (define_expand "one_cmplsi2"
3144 [(set (match_operand:SI 0 "s_register_operand" "")
3145 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3150 (define_insn "*arm_one_cmplsi2"
3151 [(set (match_operand:SI 0 "s_register_operand" "=r")
3152 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3155 [(set_attr "predicable" "yes")]
3158 (define_insn "*thumb_one_cmplsi2"
3159 [(set (match_operand:SI 0 "register_operand" "=l")
3160 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3163 [(set_attr "length" "2")]
3166 (define_insn "*notsi_compare0"
3167 [(set (reg:CC_NOOV CC_REGNUM)
3168 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3170 (set (match_operand:SI 0 "s_register_operand" "=r")
3171 (not:SI (match_dup 1)))]
3174 [(set_attr "conds" "set")]
3177 (define_insn "*notsi_compare0_scratch"
3178 [(set (reg:CC_NOOV CC_REGNUM)
3179 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3181 (clobber (match_scratch:SI 0 "=r"))]
3184 [(set_attr "conds" "set")]
3187 ;; Fixed <--> Floating conversion insns
3189 (define_expand "floatsisf2"
3190 [(set (match_operand:SF 0 "s_register_operand" "")
3191 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3192 "TARGET_ARM && TARGET_HARD_FLOAT"
3194 if (TARGET_MAVERICK)
3196 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3201 (define_expand "floatsidf2"
3202 [(set (match_operand:DF 0 "s_register_operand" "")
3203 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3204 "TARGET_ARM && TARGET_HARD_FLOAT"
3206 if (TARGET_MAVERICK)
3208 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3213 (define_expand "fix_truncsfsi2"
3214 [(set (match_operand:SI 0 "s_register_operand" "")
3215 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3216 "TARGET_ARM && TARGET_HARD_FLOAT"
3218 if (TARGET_MAVERICK)
3220 if (!cirrus_fp_register (operands[0], SImode))
3221 operands[0] = force_reg (SImode, operands[0]);
3222 if (!cirrus_fp_register (operands[1], SFmode))
3223 operands[1] = force_reg (SFmode, operands[0]);
3224 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3229 (define_expand "fix_truncdfsi2"
3230 [(set (match_operand:SI 0 "s_register_operand" "")
3231 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3232 "TARGET_ARM && TARGET_HARD_FLOAT"
3234 if (TARGET_MAVERICK)
3236 if (!cirrus_fp_register (operands[1], DFmode))
3237 operands[1] = force_reg (DFmode, operands[0]);
3238 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3245 (define_expand "truncdfsf2"
3246 [(set (match_operand:SF 0 "s_register_operand" "")
3248 (match_operand:DF 1 "s_register_operand" "")))]
3249 "TARGET_ARM && TARGET_HARD_FLOAT"
3253 ;; Zero and sign extension instructions.
3255 (define_insn "zero_extendsidi2"
3256 [(set (match_operand:DI 0 "s_register_operand" "=r")
3257 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3260 if (REGNO (operands[1])
3261 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3262 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3263 return \"mov%?\\t%R0, #0\";
3265 [(set_attr "length" "8")
3266 (set_attr "predicable" "yes")]
3269 (define_insn "zero_extendqidi2"
3270 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3271 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3274 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3275 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3276 [(set_attr "length" "8")
3277 (set_attr "predicable" "yes")
3278 (set_attr "type" "*,load_byte")
3279 (set_attr "pool_range" "*,4092")
3280 (set_attr "neg_pool_range" "*,4084")]
3283 (define_insn "extendsidi2"
3284 [(set (match_operand:DI 0 "s_register_operand" "=r")
3285 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3288 if (REGNO (operands[1])
3289 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3290 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3291 return \"mov%?\\t%R0, %Q0, asr #31\";
3293 [(set_attr "length" "8")
3294 (set_attr "shift" "1")
3295 (set_attr "predicable" "yes")]
3298 (define_expand "zero_extendhisi2"
3300 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3302 (set (match_operand:SI 0 "s_register_operand" "")
3303 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3307 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3309 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3310 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3314 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3316 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3320 if (!s_register_operand (operands[1], HImode))
3321 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3325 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3326 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3330 operands[1] = gen_lowpart (SImode, operands[1]);
3331 operands[2] = gen_reg_rtx (SImode);
3335 (define_insn "*thumb_zero_extendhisi2"
3336 [(set (match_operand:SI 0 "register_operand" "=l")
3337 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3338 "TARGET_THUMB && !arm_arch6"
3340 rtx mem = XEXP (operands[1], 0);
3342 if (GET_CODE (mem) == CONST)
3343 mem = XEXP (mem, 0);
3345 if (GET_CODE (mem) == LABEL_REF)
3346 return \"ldr\\t%0, %1\";
3348 if (GET_CODE (mem) == PLUS)
3350 rtx a = XEXP (mem, 0);
3351 rtx b = XEXP (mem, 1);
3353 /* This can happen due to bugs in reload. */
3354 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3357 ops[0] = operands[0];
3360 output_asm_insn (\"mov %0, %1\", ops);
3362 XEXP (mem, 0) = operands[0];
3365 else if ( GET_CODE (a) == LABEL_REF
3366 && GET_CODE (b) == CONST_INT)
3367 return \"ldr\\t%0, %1\";
3370 return \"ldrh\\t%0, %1\";
3372 [(set_attr "length" "4")
3373 (set_attr "type" "load_byte")
3374 (set_attr "pool_range" "60")]
3377 (define_insn "*thumb_zero_extendhisi2_v6"
3378 [(set (match_operand:SI 0 "register_operand" "=l,l")
3379 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3380 "TARGET_THUMB && arm_arch6"
3384 if (which_alternative == 0)
3385 return \"uxth\\t%0, %1\";
3387 mem = XEXP (operands[1], 0);
3389 if (GET_CODE (mem) == CONST)
3390 mem = XEXP (mem, 0);
3392 if (GET_CODE (mem) == LABEL_REF)
3393 return \"ldr\\t%0, %1\";
3395 if (GET_CODE (mem) == PLUS)
3397 rtx a = XEXP (mem, 0);
3398 rtx b = XEXP (mem, 1);
3400 /* This can happen due to bugs in reload. */
3401 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3404 ops[0] = operands[0];
3407 output_asm_insn (\"mov %0, %1\", ops);
3409 XEXP (mem, 0) = operands[0];
3412 else if ( GET_CODE (a) == LABEL_REF
3413 && GET_CODE (b) == CONST_INT)
3414 return \"ldr\\t%0, %1\";
3417 return \"ldrh\\t%0, %1\";
3419 [(set_attr "length" "2,4")
3420 (set_attr "type" "alu_shift,load_byte")
3421 (set_attr "pool_range" "*,60")]
3424 (define_insn "*arm_zero_extendhisi2"
3425 [(set (match_operand:SI 0 "s_register_operand" "=r")
3426 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3427 "TARGET_ARM && arm_arch4 && !arm_arch6"
3429 [(set_attr "type" "load_byte")
3430 (set_attr "predicable" "yes")
3431 (set_attr "pool_range" "256")
3432 (set_attr "neg_pool_range" "244")]
3435 (define_insn "*arm_zero_extendhisi2_v6"
3436 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3437 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3438 "TARGET_ARM && arm_arch6"
3442 [(set_attr "type" "alu_shift,load_byte")
3443 (set_attr "predicable" "yes")
3444 (set_attr "pool_range" "*,256")
3445 (set_attr "neg_pool_range" "*,244")]
3448 (define_insn "*arm_zero_extendhisi2addsi"
3449 [(set (match_operand:SI 0 "s_register_operand" "=r")
3450 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3451 (match_operand:SI 2 "s_register_operand" "r")))]
3452 "TARGET_ARM && arm_arch6"
3453 "uxtah%?\\t%0, %2, %1"
3454 [(set_attr "type" "alu_shift")
3455 (set_attr "predicable" "yes")]
3458 (define_expand "zero_extendqisi2"
3459 [(set (match_operand:SI 0 "s_register_operand" "")
3460 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3463 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3467 emit_insn (gen_andsi3 (operands[0],
3468 gen_lowpart (SImode, operands[1]),
3471 else /* TARGET_THUMB */
3473 rtx temp = gen_reg_rtx (SImode);
3476 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3477 operands[1] = gen_lowpart (SImode, operands[1]);
3480 ops[1] = operands[1];
3481 ops[2] = GEN_INT (24);
3483 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3484 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3486 ops[0] = operands[0];
3488 ops[2] = GEN_INT (24);
3490 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3491 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3498 (define_insn "*thumb_zero_extendqisi2"
3499 [(set (match_operand:SI 0 "register_operand" "=l")
3500 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3501 "TARGET_THUMB && !arm_arch6"
3503 [(set_attr "length" "2")
3504 (set_attr "type" "load_byte")
3505 (set_attr "pool_range" "32")]
3508 (define_insn "*thumb_zero_extendqisi2_v6"
3509 [(set (match_operand:SI 0 "register_operand" "=l,l")
3510 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3511 "TARGET_THUMB && arm_arch6"
3515 [(set_attr "length" "2,2")
3516 (set_attr "type" "alu_shift,load_byte")
3517 (set_attr "pool_range" "*,32")]
3520 (define_insn "*arm_zero_extendqisi2"
3521 [(set (match_operand:SI 0 "s_register_operand" "=r")
3522 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3523 "TARGET_ARM && !arm_arch6"
3524 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3525 [(set_attr "type" "load_byte")
3526 (set_attr "predicable" "yes")
3527 (set_attr "pool_range" "4096")
3528 (set_attr "neg_pool_range" "4084")]
3531 (define_insn "*arm_zero_extendqisi2_v6"
3532 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3533 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3534 "TARGET_ARM && arm_arch6"
3537 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3538 [(set_attr "type" "alu_shift,load_byte")
3539 (set_attr "predicable" "yes")
3540 (set_attr "pool_range" "*,4096")
3541 (set_attr "neg_pool_range" "*,4084")]
3544 (define_insn "*arm_zero_extendqisi2addsi"
3545 [(set (match_operand:SI 0 "s_register_operand" "=r")
3546 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3547 (match_operand:SI 2 "s_register_operand" "r")))]
3548 "TARGET_ARM && arm_arch6"
3549 "uxtab%?\\t%0, %2, %1"
3550 [(set_attr "predicable" "yes")
3551 (set_attr "type" "alu_shift")]
3555 [(set (match_operand:SI 0 "s_register_operand" "")
3556 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3557 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3558 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3559 [(set (match_dup 2) (match_dup 1))
3560 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3565 [(set (match_operand:SI 0 "s_register_operand" "")
3566 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3567 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3569 [(set (match_dup 2) (match_dup 1))
3570 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3574 (define_insn "*compareqi_eq0"
3575 [(set (reg:CC_Z CC_REGNUM)
3576 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3580 [(set_attr "conds" "set")]
3583 (define_expand "extendhisi2"
3585 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3587 (set (match_operand:SI 0 "s_register_operand" "")
3588 (ashiftrt:SI (match_dup 2)
3593 if (GET_CODE (operands[1]) == MEM)
3597 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3602 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3603 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3608 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3610 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3614 if (!s_register_operand (operands[1], HImode))
3615 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3620 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3622 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3623 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3628 operands[1] = gen_lowpart (SImode, operands[1]);
3629 operands[2] = gen_reg_rtx (SImode);
3633 (define_insn "thumb_extendhisi2"
3634 [(set (match_operand:SI 0 "register_operand" "=l")
3635 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3636 (clobber (match_scratch:SI 2 "=&l"))]
3637 "TARGET_THUMB && !arm_arch6"
3641 rtx mem = XEXP (operands[1], 0);
3643 /* This code used to try to use 'V', and fix the address only if it was
3644 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3645 range of QImode offsets, and offsettable_address_p does a QImode
3648 if (GET_CODE (mem) == CONST)
3649 mem = XEXP (mem, 0);
3651 if (GET_CODE (mem) == LABEL_REF)
3652 return \"ldr\\t%0, %1\";
3654 if (GET_CODE (mem) == PLUS)
3656 rtx a = XEXP (mem, 0);
3657 rtx b = XEXP (mem, 1);
3659 if (GET_CODE (a) == LABEL_REF
3660 && GET_CODE (b) == CONST_INT)
3661 return \"ldr\\t%0, %1\";
3663 if (GET_CODE (b) == REG)
3664 return \"ldrsh\\t%0, %1\";
3672 ops[2] = const0_rtx;
3675 gcc_assert (GET_CODE (ops[1]) == REG);
3677 ops[0] = operands[0];
3678 ops[3] = operands[2];
3679 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3682 [(set_attr "length" "4")
3683 (set_attr "type" "load_byte")
3684 (set_attr "pool_range" "1020")]
3687 ;; We used to have an early-clobber on the scratch register here.
3688 ;; However, there's a bug somewhere in reload which means that this
3689 ;; can be partially ignored during spill allocation if the memory
3690 ;; address also needs reloading; this causes us to die later on when
3691 ;; we try to verify the operands. Fortunately, we don't really need
3692 ;; the early-clobber: we can always use operand 0 if operand 2
3693 ;; overlaps the address.
3694 (define_insn "*thumb_extendhisi2_insn_v6"
3695 [(set (match_operand:SI 0 "register_operand" "=l,l")
3696 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3697 (clobber (match_scratch:SI 2 "=X,l"))]
3698 "TARGET_THUMB && arm_arch6"
3704 if (which_alternative == 0)
3705 return \"sxth\\t%0, %1\";
3707 mem = XEXP (operands[1], 0);
3709 /* This code used to try to use 'V', and fix the address only if it was
3710 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3711 range of QImode offsets, and offsettable_address_p does a QImode
3714 if (GET_CODE (mem) == CONST)
3715 mem = XEXP (mem, 0);
3717 if (GET_CODE (mem) == LABEL_REF)
3718 return \"ldr\\t%0, %1\";
3720 if (GET_CODE (mem) == PLUS)
3722 rtx a = XEXP (mem, 0);
3723 rtx b = XEXP (mem, 1);
3725 if (GET_CODE (a) == LABEL_REF
3726 && GET_CODE (b) == CONST_INT)
3727 return \"ldr\\t%0, %1\";
3729 if (GET_CODE (b) == REG)
3730 return \"ldrsh\\t%0, %1\";
3738 ops[2] = const0_rtx;
3741 gcc_assert (GET_CODE (ops[1]) == REG);
3743 ops[0] = operands[0];
3744 if (reg_mentioned_p (operands[2], ops[1]))
3747 ops[3] = operands[2];
3748 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3751 [(set_attr "length" "2,4")
3752 (set_attr "type" "alu_shift,load_byte")
3753 (set_attr "pool_range" "*,1020")]
3756 (define_expand "extendhisi2_mem"
3757 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3759 (zero_extend:SI (match_dup 7)))
3760 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3761 (set (match_operand:SI 0 "" "")
3762 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3767 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3769 mem1 = change_address (operands[1], QImode, addr);
3770 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3771 operands[0] = gen_lowpart (SImode, operands[0]);
3773 operands[2] = gen_reg_rtx (SImode);
3774 operands[3] = gen_reg_rtx (SImode);
3775 operands[6] = gen_reg_rtx (SImode);
3778 if (BYTES_BIG_ENDIAN)
3780 operands[4] = operands[2];
3781 operands[5] = operands[3];
3785 operands[4] = operands[3];
3786 operands[5] = operands[2];
3791 (define_insn "*arm_extendhisi2"
3792 [(set (match_operand:SI 0 "s_register_operand" "=r")
3793 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3794 "TARGET_ARM && arm_arch4 && !arm_arch6"
3796 [(set_attr "type" "load_byte")
3797 (set_attr "predicable" "yes")
3798 (set_attr "pool_range" "256")
3799 (set_attr "neg_pool_range" "244")]
3802 (define_insn "*arm_extendhisi2_v6"
3803 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3804 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3805 "TARGET_ARM && arm_arch6"
3809 [(set_attr "type" "alu_shift,load_byte")
3810 (set_attr "predicable" "yes")
3811 (set_attr "pool_range" "*,256")
3812 (set_attr "neg_pool_range" "*,244")]
3815 (define_insn "*arm_extendhisi2addsi"
3816 [(set (match_operand:SI 0 "s_register_operand" "=r")
3817 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3818 (match_operand:SI 2 "s_register_operand" "r")))]
3819 "TARGET_ARM && arm_arch6"
3820 "sxtah%?\\t%0, %2, %1"
3823 (define_expand "extendqihi2"
3825 (ashift:SI (match_operand:QI 1 "general_operand" "")
3827 (set (match_operand:HI 0 "s_register_operand" "")
3828 (ashiftrt:SI (match_dup 2)
3833 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3835 emit_insn (gen_rtx_SET (VOIDmode,
3837 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3840 if (!s_register_operand (operands[1], QImode))
3841 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3842 operands[0] = gen_lowpart (SImode, operands[0]);
3843 operands[1] = gen_lowpart (SImode, operands[1]);
3844 operands[2] = gen_reg_rtx (SImode);
3848 (define_insn "*extendqihi_insn"
3849 [(set (match_operand:HI 0 "s_register_operand" "=r")
3850 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3851 "TARGET_ARM && arm_arch4"
3853 [(set_attr "type" "load_byte")
3854 (set_attr "predicable" "yes")
3855 (set_attr "pool_range" "256")
3856 (set_attr "neg_pool_range" "244")]
3859 (define_expand "extendqisi2"
3861 (ashift:SI (match_operand:QI 1 "general_operand" "")
3863 (set (match_operand:SI 0 "s_register_operand" "")
3864 (ashiftrt:SI (match_dup 2)
3869 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3871 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3872 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3876 if (!s_register_operand (operands[1], QImode))
3877 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3881 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3882 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3886 operands[1] = gen_lowpart (SImode, operands[1]);
3887 operands[2] = gen_reg_rtx (SImode);
3891 (define_insn "*arm_extendqisi"
3892 [(set (match_operand:SI 0 "s_register_operand" "=r")
3893 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3894 "TARGET_ARM && arm_arch4 && !arm_arch6"
3896 [(set_attr "type" "load_byte")
3897 (set_attr "predicable" "yes")
3898 (set_attr "pool_range" "256")
3899 (set_attr "neg_pool_range" "244")]
3902 (define_insn "*arm_extendqisi_v6"
3903 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3904 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3905 "TARGET_ARM && arm_arch6"
3909 [(set_attr "type" "alu_shift,load_byte")
3910 (set_attr "predicable" "yes")
3911 (set_attr "pool_range" "*,256")
3912 (set_attr "neg_pool_range" "*,244")]
3915 (define_insn "*arm_extendqisi2addsi"
3916 [(set (match_operand:SI 0 "s_register_operand" "=r")
3917 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3918 (match_operand:SI 2 "s_register_operand" "r")))]
3919 "TARGET_ARM && arm_arch6"
3920 "sxtab%?\\t%0, %2, %1"
3921 [(set_attr "type" "alu_shift")
3922 (set_attr "predicable" "yes")]
3925 (define_insn "*thumb_extendqisi2"
3926 [(set (match_operand:SI 0 "register_operand" "=l,l")
3927 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3928 "TARGET_THUMB && !arm_arch6"
3932 rtx mem = XEXP (operands[1], 0);
3934 if (GET_CODE (mem) == CONST)
3935 mem = XEXP (mem, 0);
3937 if (GET_CODE (mem) == LABEL_REF)
3938 return \"ldr\\t%0, %1\";
3940 if (GET_CODE (mem) == PLUS
3941 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3942 return \"ldr\\t%0, %1\";
3944 if (which_alternative == 0)
3945 return \"ldrsb\\t%0, %1\";
3947 ops[0] = operands[0];
3949 if (GET_CODE (mem) == PLUS)
3951 rtx a = XEXP (mem, 0);
3952 rtx b = XEXP (mem, 1);
3957 if (GET_CODE (a) == REG)
3959 if (GET_CODE (b) == REG)
3960 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3961 else if (REGNO (a) == REGNO (ops[0]))
3963 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3964 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3968 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3972 gcc_assert (GET_CODE (b) == REG);
3973 if (REGNO (b) == REGNO (ops[0]))
3975 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3976 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3980 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3983 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3985 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3986 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3987 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3992 ops[2] = const0_rtx;
3994 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3998 [(set_attr "length" "2,6")
3999 (set_attr "type" "load_byte,load_byte")
4000 (set_attr "pool_range" "32,32")]
4003 (define_insn "*thumb_extendqisi2_v6"
4004 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4005 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4006 "TARGET_THUMB && arm_arch6"
4012 if (which_alternative == 0)
4013 return \"sxtb\\t%0, %1\";
4015 mem = XEXP (operands[1], 0);
4017 if (GET_CODE (mem) == CONST)
4018 mem = XEXP (mem, 0);
4020 if (GET_CODE (mem) == LABEL_REF)
4021 return \"ldr\\t%0, %1\";
4023 if (GET_CODE (mem) == PLUS
4024 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4025 return \"ldr\\t%0, %1\";
4027 if (which_alternative == 0)
4028 return \"ldrsb\\t%0, %1\";
4030 ops[0] = operands[0];
4032 if (GET_CODE (mem) == PLUS)
4034 rtx a = XEXP (mem, 0);
4035 rtx b = XEXP (mem, 1);
4040 if (GET_CODE (a) == REG)
4042 if (GET_CODE (b) == REG)
4043 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4044 else if (REGNO (a) == REGNO (ops[0]))
4046 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4047 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4050 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4054 gcc_assert (GET_CODE (b) == REG);
4055 if (REGNO (b) == REGNO (ops[0]))
4057 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4058 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4061 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4064 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4066 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4067 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4072 ops[2] = const0_rtx;
4074 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4078 [(set_attr "length" "2,2,4")
4079 (set_attr "type" "alu_shift,load_byte,load_byte")
4080 (set_attr "pool_range" "*,32,32")]
4083 (define_expand "extendsfdf2"
4084 [(set (match_operand:DF 0 "s_register_operand" "")
4085 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4086 "TARGET_ARM && TARGET_HARD_FLOAT"
4090 ;; Move insns (including loads and stores)
4092 ;; XXX Just some ideas about movti.
4093 ;; I don't think these are a good idea on the arm, there just aren't enough
4095 ;;(define_expand "loadti"
4096 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4097 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4100 ;;(define_expand "storeti"
4101 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4102 ;; (match_operand:TI 1 "s_register_operand" ""))]
4105 ;;(define_expand "movti"
4106 ;; [(set (match_operand:TI 0 "general_operand" "")
4107 ;; (match_operand:TI 1 "general_operand" ""))]
4113 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4114 ;; operands[1] = copy_to_reg (operands[1]);
4115 ;; if (GET_CODE (operands[0]) == MEM)
4116 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4117 ;; else if (GET_CODE (operands[1]) == MEM)
4118 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4122 ;; emit_insn (insn);
4126 ;; Recognize garbage generated above.
4129 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4130 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4134 ;; register mem = (which_alternative < 3);
4135 ;; register const char *template;
4137 ;; operands[mem] = XEXP (operands[mem], 0);
4138 ;; switch (which_alternative)
4140 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4141 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4142 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4143 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4144 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4145 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4147 ;; output_asm_insn (template, operands);
4151 (define_expand "movdi"
4152 [(set (match_operand:DI 0 "general_operand" "")
4153 (match_operand:DI 1 "general_operand" ""))]
4156 if (!no_new_pseudos)
4158 if (GET_CODE (operands[0]) != REG)
4159 operands[1] = force_reg (DImode, operands[1]);
4164 (define_insn "*arm_movdi"
4165 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4166 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4168 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4170 && ( register_operand (operands[0], DImode)
4171 || register_operand (operands[1], DImode))"
4173 switch (which_alternative)
4180 return output_move_double (operands);
4183 [(set_attr "length" "8,12,16,8,8")
4184 (set_attr "type" "*,*,*,load2,store2")
4185 (set_attr "pool_range" "*,*,*,1020,*")
4186 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4190 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4191 (match_operand:ANY64 1 "const_double_operand" ""))]
4194 && (arm_const_double_inline_cost (operands[1])
4195 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4198 arm_split_constant (SET, SImode, curr_insn,
4199 INTVAL (gen_lowpart (SImode, operands[1])),
4200 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4201 arm_split_constant (SET, SImode, curr_insn,
4202 INTVAL (gen_highpart_mode (SImode,
4203 GET_MODE (operands[0]),
4205 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4210 ; If optimizing for size, or if we have load delay slots, then
4211 ; we want to split the constant into two separate operations.
4212 ; In both cases this may split a trivial part into a single data op
4213 ; leaving a single complex constant to load. We can also get longer
4214 ; offsets in a LDR which means we get better chances of sharing the pool
4215 ; entries. Finally, we can normally do a better job of scheduling
4216 ; LDR instructions than we can with LDM.
4217 ; This pattern will only match if the one above did not.
4219 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4220 (match_operand:ANY64 1 "const_double_operand" ""))]
4221 "TARGET_ARM && reload_completed
4222 && arm_const_double_by_parts (operands[1])"
4223 [(set (match_dup 0) (match_dup 1))
4224 (set (match_dup 2) (match_dup 3))]
4226 operands[2] = gen_highpart (SImode, operands[0]);
4227 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4229 operands[0] = gen_lowpart (SImode, operands[0]);
4230 operands[1] = gen_lowpart (SImode, operands[1]);
4235 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4236 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4237 "TARGET_EITHER && reload_completed"
4238 [(set (match_dup 0) (match_dup 1))
4239 (set (match_dup 2) (match_dup 3))]
4241 operands[2] = gen_highpart (SImode, operands[0]);
4242 operands[3] = gen_highpart (SImode, operands[1]);
4243 operands[0] = gen_lowpart (SImode, operands[0]);
4244 operands[1] = gen_lowpart (SImode, operands[1]);
4246 /* Handle a partial overlap. */
4247 if (rtx_equal_p (operands[0], operands[3]))
4249 rtx tmp0 = operands[0];
4250 rtx tmp1 = operands[1];
4252 operands[0] = operands[2];
4253 operands[1] = operands[3];
4260 ;; We can't actually do base+index doubleword loads if the index and
4261 ;; destination overlap. Split here so that we at least have chance to
4264 [(set (match_operand:DI 0 "s_register_operand" "")
4265 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4266 (match_operand:SI 2 "s_register_operand" ""))))]
4268 && reg_overlap_mentioned_p (operands[0], operands[1])
4269 && reg_overlap_mentioned_p (operands[0], operands[2])"
4271 (plus:SI (match_dup 1)
4274 (mem:DI (match_dup 4)))]
4276 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4280 ;;; ??? This should have alternatives for constants.
4281 ;;; ??? This was originally identical to the movdf_insn pattern.
4282 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4283 ;;; thumb_reorg with a memory reference.
4284 (define_insn "*thumb_movdi_insn"
4285 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4286 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4288 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4289 && ( register_operand (operands[0], DImode)
4290 || register_operand (operands[1], DImode))"
4293 switch (which_alternative)
4297 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4298 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4299 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4301 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4303 operands[1] = GEN_INT (- INTVAL (operands[1]));
4304 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4306 return \"ldmia\\t%1, {%0, %H0}\";
4308 return \"stmia\\t%0, {%1, %H1}\";
4310 return thumb_load_double_from_address (operands);
4312 operands[2] = gen_rtx_MEM (SImode,
4313 plus_constant (XEXP (operands[0], 0), 4));
4314 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4317 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4318 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4319 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4322 [(set_attr "length" "4,4,6,2,2,6,4,4")
4323 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4324 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4327 (define_expand "movsi"
4328 [(set (match_operand:SI 0 "general_operand" "")
4329 (match_operand:SI 1 "general_operand" ""))]
4334 /* Everything except mem = const or mem = mem can be done easily. */
4335 if (GET_CODE (operands[0]) == MEM)
4336 operands[1] = force_reg (SImode, operands[1]);
4337 if (arm_general_register_operand (operands[0], SImode)
4338 && GET_CODE (operands[1]) == CONST_INT
4339 && !(const_ok_for_arm (INTVAL (operands[1]))
4340 || const_ok_for_arm (~INTVAL (operands[1]))))
4342 arm_split_constant (SET, SImode, NULL_RTX,
4343 INTVAL (operands[1]), operands[0], NULL_RTX,
4344 optimize && !no_new_pseudos);
4348 else /* TARGET_THUMB.... */
4350 if (!no_new_pseudos)
4352 if (GET_CODE (operands[0]) != REG)
4353 operands[1] = force_reg (SImode, operands[1]);
4357 /* Recognize the case where operand[1] is a reference to thread-local
4358 data and load its address to a register. */
4359 if (arm_tls_referenced_p (operands[1]))
4361 rtx tmp = operands[1];
4364 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4366 addend = XEXP (XEXP (tmp, 0), 1);
4367 tmp = XEXP (XEXP (tmp, 0), 0);
4370 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4371 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4373 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4376 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4377 tmp = force_operand (tmp, operands[0]);
4382 && (CONSTANT_P (operands[1])
4383 || symbol_mentioned_p (operands[1])
4384 || label_mentioned_p (operands[1])))
4385 operands[1] = legitimize_pic_address (operands[1], SImode,
4386 (no_new_pseudos ? operands[0] : 0));
4390 (define_insn "*arm_movsi_insn"
4391 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4392 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4393 "TARGET_ARM && ! TARGET_IWMMXT
4394 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4395 && ( register_operand (operands[0], SImode)
4396 || register_operand (operands[1], SImode))"
4402 [(set_attr "type" "*,*,load1,store1")
4403 (set_attr "predicable" "yes")
4404 (set_attr "pool_range" "*,*,4096,*")
4405 (set_attr "neg_pool_range" "*,*,4084,*")]
4409 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4410 (match_operand:SI 1 "const_int_operand" ""))]
4412 && (!(const_ok_for_arm (INTVAL (operands[1]))
4413 || const_ok_for_arm (~INTVAL (operands[1]))))"
4414 [(clobber (const_int 0))]
4416 arm_split_constant (SET, SImode, NULL_RTX,
4417 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4422 (define_insn "*thumb_movsi_insn"
4423 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4424 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4426 && ( register_operand (operands[0], SImode)
4427 || register_operand (operands[1], SImode))"
4438 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4439 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4440 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4444 [(set (match_operand:SI 0 "register_operand" "")
4445 (match_operand:SI 1 "const_int_operand" ""))]
4446 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4447 [(set (match_dup 0) (match_dup 1))
4448 (set (match_dup 0) (neg:SI (match_dup 0)))]
4449 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4453 [(set (match_operand:SI 0 "register_operand" "")
4454 (match_operand:SI 1 "const_int_operand" ""))]
4455 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4456 [(set (match_dup 0) (match_dup 1))
4457 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4460 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4461 unsigned HOST_WIDE_INT mask = 0xff;
4464 for (i = 0; i < 25; i++)
4465 if ((val & (mask << i)) == val)
4468 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4472 operands[1] = GEN_INT (val >> i);
4473 operands[2] = GEN_INT (i);
4477 ;; When generating pic, we need to load the symbol offset into a register.
4478 ;; So that the optimizer does not confuse this with a normal symbol load
4479 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4480 ;; since that is the only type of relocation we can use.
4482 ;; The rather odd constraints on the following are to force reload to leave
4483 ;; the insn alone, and to force the minipool generation pass to then move
4484 ;; the GOT symbol to memory.
4486 (define_insn "pic_load_addr_arm"
4487 [(set (match_operand:SI 0 "s_register_operand" "=r")
4488 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4489 "TARGET_ARM && flag_pic"
4491 [(set_attr "type" "load1")
4492 (set (attr "pool_range") (const_int 4096))
4493 (set (attr "neg_pool_range") (const_int 4084))]
4496 (define_insn "pic_load_addr_thumb"
4497 [(set (match_operand:SI 0 "s_register_operand" "=l")
4498 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4499 "TARGET_THUMB && flag_pic"
4501 [(set_attr "type" "load1")
4502 (set (attr "pool_range") (const_int 1024))]
4505 ;; This variant is used for AOF assembly, since it needs to mention the
4506 ;; pic register in the rtl.
4507 (define_expand "pic_load_addr_based"
4508 [(set (match_operand:SI 0 "s_register_operand" "")
4509 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4510 "TARGET_ARM && flag_pic"
4511 "operands[2] = cfun->machine->pic_reg;"
4514 (define_insn "*pic_load_addr_based_insn"
4515 [(set (match_operand:SI 0 "s_register_operand" "=r")
4516 (unspec:SI [(match_operand 1 "" "")
4517 (match_operand 2 "s_register_operand" "r")]
4519 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4521 #ifdef AOF_ASSEMBLER
4522 operands[1] = aof_pic_entry (operands[1]);
4524 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4527 [(set_attr "type" "load1")
4528 (set (attr "pool_range")
4529 (if_then_else (eq_attr "is_thumb" "yes")
4532 (set (attr "neg_pool_range")
4533 (if_then_else (eq_attr "is_thumb" "yes")
4538 (define_insn "pic_add_dot_plus_four"
4539 [(set (match_operand:SI 0 "register_operand" "=r")
4540 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4541 (const (plus:SI (pc) (const_int 4))))]
4543 (use (match_operand 2 "" ""))]
4546 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4547 INTVAL (operands[2]));
4548 return \"add\\t%0, %|pc\";
4550 [(set_attr "length" "2")]
4553 (define_insn "pic_add_dot_plus_eight"
4554 [(set (match_operand:SI 0 "register_operand" "=r")
4555 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4556 (const (plus:SI (pc) (const_int 8))))]
4558 (use (match_operand 2 "" ""))]
4561 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4562 INTVAL (operands[2]));
4563 return \"add%?\\t%0, %|pc, %1\";
4565 [(set_attr "predicable" "yes")]
4568 (define_insn "tls_load_dot_plus_eight"
4569 [(set (match_operand:SI 0 "register_operand" "+r")
4570 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4571 (const (plus:SI (pc) (const_int 8))))]
4573 (use (match_operand 2 "" ""))]
4576 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4577 INTVAL (operands[2]));
4578 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4580 [(set_attr "predicable" "yes")]
4583 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4584 ;; followed by a load. These sequences can be crunched down to
4585 ;; tls_load_dot_plus_eight by a peephole.
4588 [(parallel [(set (match_operand:SI 0 "register_operand" "")
4589 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4590 (const (plus:SI (pc) (const_int 8))))]
4592 (use (label_ref (match_operand 1 "" "")))])
4593 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4594 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4595 [(parallel [(set (match_dup 2)
4596 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4597 (const (plus:SI (pc) (const_int 8))))]
4599 (use (label_ref (match_dup 1)))])]
4603 (define_expand "builtin_setjmp_receiver"
4604 [(label_ref (match_operand 0 "" ""))]
4608 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4610 if (arm_pic_register != INVALID_REGNUM)
4611 arm_load_pic_register (1UL << 3);
4615 ;; If copying one reg to another we can set the condition codes according to
4616 ;; its value. Such a move is common after a return from subroutine and the
4617 ;; result is being tested against zero.
4619 (define_insn "*movsi_compare0"
4620 [(set (reg:CC CC_REGNUM)
4621 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4623 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4628 sub%?s\\t%0, %1, #0"
4629 [(set_attr "conds" "set")]
4632 ;; Subroutine to store a half word from a register into memory.
4633 ;; Operand 0 is the source register (HImode)
4634 ;; Operand 1 is the destination address in a register (SImode)
4636 ;; In both this routine and the next, we must be careful not to spill
4637 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4638 ;; can generate unrecognizable rtl.
4640 (define_expand "storehi"
4641 [;; store the low byte
4642 (set (match_operand 1 "" "") (match_dup 3))
4643 ;; extract the high byte
4645 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4646 ;; store the high byte
4647 (set (match_dup 4) (match_dup 5))]
4651 rtx op1 = operands[1];
4652 rtx addr = XEXP (op1, 0);
4653 enum rtx_code code = GET_CODE (addr);
4655 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4657 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4659 operands[4] = adjust_address (op1, QImode, 1);
4660 operands[1] = adjust_address (operands[1], QImode, 0);
4661 operands[3] = gen_lowpart (QImode, operands[0]);
4662 operands[0] = gen_lowpart (SImode, operands[0]);
4663 operands[2] = gen_reg_rtx (SImode);
4664 operands[5] = gen_lowpart (QImode, operands[2]);
4668 (define_expand "storehi_bigend"
4669 [(set (match_dup 4) (match_dup 3))
4671 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4672 (set (match_operand 1 "" "") (match_dup 5))]
4676 rtx op1 = operands[1];
4677 rtx addr = XEXP (op1, 0);
4678 enum rtx_code code = GET_CODE (addr);
4680 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4682 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4684 operands[4] = adjust_address (op1, QImode, 1);
4685 operands[1] = adjust_address (operands[1], QImode, 0);
4686 operands[3] = gen_lowpart (QImode, operands[0]);
4687 operands[0] = gen_lowpart (SImode, operands[0]);
4688 operands[2] = gen_reg_rtx (SImode);
4689 operands[5] = gen_lowpart (QImode, operands[2]);
4693 ;; Subroutine to store a half word integer constant into memory.
4694 (define_expand "storeinthi"
4695 [(set (match_operand 0 "" "")
4696 (match_operand 1 "" ""))
4697 (set (match_dup 3) (match_dup 2))]
4701 HOST_WIDE_INT value = INTVAL (operands[1]);
4702 rtx addr = XEXP (operands[0], 0);
4703 rtx op0 = operands[0];
4704 enum rtx_code code = GET_CODE (addr);
4706 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4708 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4710 operands[1] = gen_reg_rtx (SImode);
4711 if (BYTES_BIG_ENDIAN)
4713 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4714 if ((value & 255) == ((value >> 8) & 255))
4715 operands[2] = operands[1];
4718 operands[2] = gen_reg_rtx (SImode);
4719 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4724 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4725 if ((value & 255) == ((value >> 8) & 255))
4726 operands[2] = operands[1];
4729 operands[2] = gen_reg_rtx (SImode);
4730 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4734 operands[3] = adjust_address (op0, QImode, 1);
4735 operands[0] = adjust_address (operands[0], QImode, 0);
4736 operands[2] = gen_lowpart (QImode, operands[2]);
4737 operands[1] = gen_lowpart (QImode, operands[1]);
4741 (define_expand "storehi_single_op"
4742 [(set (match_operand:HI 0 "memory_operand" "")
4743 (match_operand:HI 1 "general_operand" ""))]
4744 "TARGET_ARM && arm_arch4"
4746 if (!s_register_operand (operands[1], HImode))
4747 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4751 (define_expand "movhi"
4752 [(set (match_operand:HI 0 "general_operand" "")
4753 (match_operand:HI 1 "general_operand" ""))]
4758 if (!no_new_pseudos)
4760 if (GET_CODE (operands[0]) == MEM)
4764 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4767 if (GET_CODE (operands[1]) == CONST_INT)
4768 emit_insn (gen_storeinthi (operands[0], operands[1]));
4771 if (GET_CODE (operands[1]) == MEM)
4772 operands[1] = force_reg (HImode, operands[1]);
4773 if (BYTES_BIG_ENDIAN)
4774 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4776 emit_insn (gen_storehi (operands[1], operands[0]));
4780 /* Sign extend a constant, and keep it in an SImode reg. */
4781 else if (GET_CODE (operands[1]) == CONST_INT)
4783 rtx reg = gen_reg_rtx (SImode);
4784 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4786 /* If the constant is already valid, leave it alone. */
4787 if (!const_ok_for_arm (val))
4789 /* If setting all the top bits will make the constant
4790 loadable in a single instruction, then set them.
4791 Otherwise, sign extend the number. */
4793 if (const_ok_for_arm (~(val | ~0xffff)))
4795 else if (val & 0x8000)
4799 emit_insn (gen_movsi (reg, GEN_INT (val)));
4800 operands[1] = gen_lowpart (HImode, reg);
4802 else if (arm_arch4 && optimize && !no_new_pseudos
4803 && GET_CODE (operands[1]) == MEM)
4805 rtx reg = gen_reg_rtx (SImode);
4807 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4808 operands[1] = gen_lowpart (HImode, reg);
4810 else if (!arm_arch4)
4812 if (GET_CODE (operands[1]) == MEM)
4815 rtx offset = const0_rtx;
4816 rtx reg = gen_reg_rtx (SImode);
4818 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4819 || (GET_CODE (base) == PLUS
4820 && (GET_CODE (offset = XEXP (base, 1))
4822 && ((INTVAL(offset) & 1) != 1)
4823 && GET_CODE (base = XEXP (base, 0)) == REG))
4824 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4828 new = widen_memory_access (operands[1], SImode,
4829 ((INTVAL (offset) & ~3)
4830 - INTVAL (offset)));
4831 emit_insn (gen_movsi (reg, new));
4832 if (((INTVAL (offset) & 2) != 0)
4833 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4835 rtx reg2 = gen_reg_rtx (SImode);
4837 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4842 emit_insn (gen_movhi_bytes (reg, operands[1]));
4844 operands[1] = gen_lowpart (HImode, reg);
4848 /* Handle loading a large integer during reload. */
4849 else if (GET_CODE (operands[1]) == CONST_INT
4850 && !const_ok_for_arm (INTVAL (operands[1]))
4851 && !const_ok_for_arm (~INTVAL (operands[1])))
4853 /* Writing a constant to memory needs a scratch, which should
4854 be handled with SECONDARY_RELOADs. */
4855 gcc_assert (GET_CODE (operands[0]) == REG);
4857 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4858 emit_insn (gen_movsi (operands[0], operands[1]));
4862 else /* TARGET_THUMB */
4864 if (!no_new_pseudos)
4866 if (GET_CODE (operands[1]) == CONST_INT)
4868 rtx reg = gen_reg_rtx (SImode);
4870 emit_insn (gen_movsi (reg, operands[1]));
4871 operands[1] = gen_lowpart (HImode, reg);
4874 /* ??? We shouldn't really get invalid addresses here, but this can
4875 happen if we are passed a SP (never OK for HImode/QImode) or
4876 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4877 HImode/QImode) relative address. */
4878 /* ??? This should perhaps be fixed elsewhere, for instance, in
4879 fixup_stack_1, by checking for other kinds of invalid addresses,
4880 e.g. a bare reference to a virtual register. This may confuse the
4881 alpha though, which must handle this case differently. */
4882 if (GET_CODE (operands[0]) == MEM
4883 && !memory_address_p (GET_MODE (operands[0]),
4884 XEXP (operands[0], 0)))
4886 = replace_equiv_address (operands[0],
4887 copy_to_reg (XEXP (operands[0], 0)));
4889 if (GET_CODE (operands[1]) == MEM
4890 && !memory_address_p (GET_MODE (operands[1]),
4891 XEXP (operands[1], 0)))
4893 = replace_equiv_address (operands[1],
4894 copy_to_reg (XEXP (operands[1], 0)));
4896 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4898 rtx reg = gen_reg_rtx (SImode);
4900 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4901 operands[1] = gen_lowpart (HImode, reg);
4904 if (GET_CODE (operands[0]) == MEM)
4905 operands[1] = force_reg (HImode, operands[1]);
4907 else if (GET_CODE (operands[1]) == CONST_INT
4908 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4910 /* Handle loading a large integer during reload. */
4912 /* Writing a constant to memory needs a scratch, which should
4913 be handled with SECONDARY_RELOADs. */
4914 gcc_assert (GET_CODE (operands[0]) == REG);
4916 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4917 emit_insn (gen_movsi (operands[0], operands[1]));
4924 (define_insn "*thumb_movhi_insn"
4925 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4926 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4928 && ( register_operand (operands[0], HImode)
4929 || register_operand (operands[1], HImode))"
4931 switch (which_alternative)
4933 case 0: return \"add %0, %1, #0\";
4934 case 2: return \"strh %1, %0\";
4935 case 3: return \"mov %0, %1\";
4936 case 4: return \"mov %0, %1\";
4937 case 5: return \"mov %0, %1\";
4938 default: gcc_unreachable ();
4940 /* The stack pointer can end up being taken as an index register.
4941 Catch this case here and deal with it. */
4942 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4943 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4944 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4947 ops[0] = operands[0];
4948 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4950 output_asm_insn (\"mov %0, %1\", ops);
4952 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4955 return \"ldrh %0, %1\";
4957 [(set_attr "length" "2,4,2,2,2,2")
4958 (set_attr "type" "*,load1,store1,*,*,*")]
4962 (define_expand "movhi_bytes"
4963 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4965 (zero_extend:SI (match_dup 6)))
4966 (set (match_operand:SI 0 "" "")
4967 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4972 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4974 mem1 = change_address (operands[1], QImode, addr);
4975 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4976 operands[0] = gen_lowpart (SImode, operands[0]);
4978 operands[2] = gen_reg_rtx (SImode);
4979 operands[3] = gen_reg_rtx (SImode);
4982 if (BYTES_BIG_ENDIAN)
4984 operands[4] = operands[2];
4985 operands[5] = operands[3];
4989 operands[4] = operands[3];
4990 operands[5] = operands[2];
4995 (define_expand "movhi_bigend"
4997 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5000 (ashiftrt:SI (match_dup 2) (const_int 16)))
5001 (set (match_operand:HI 0 "s_register_operand" "")
5005 operands[2] = gen_reg_rtx (SImode);
5006 operands[3] = gen_reg_rtx (SImode);
5007 operands[4] = gen_lowpart (HImode, operands[3]);
5011 ;; Pattern to recognize insn generated default case above
5012 (define_insn "*movhi_insn_arch4"
5013 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5014 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
5017 && (GET_CODE (operands[1]) != CONST_INT
5018 || const_ok_for_arm (INTVAL (operands[1]))
5019 || const_ok_for_arm (~INTVAL (operands[1])))"
5021 mov%?\\t%0, %1\\t%@ movhi
5022 mvn%?\\t%0, #%B1\\t%@ movhi
5023 str%?h\\t%1, %0\\t%@ movhi
5024 ldr%?h\\t%0, %1\\t%@ movhi"
5025 [(set_attr "type" "*,*,store1,load1")
5026 (set_attr "predicable" "yes")
5027 (set_attr "pool_range" "*,*,*,256")
5028 (set_attr "neg_pool_range" "*,*,*,244")]
5031 (define_insn "*movhi_bytes"
5032 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5033 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
5036 mov%?\\t%0, %1\\t%@ movhi
5037 mvn%?\\t%0, #%B1\\t%@ movhi"
5038 [(set_attr "predicable" "yes")]
5041 (define_expand "thumb_movhi_clobber"
5042 [(set (match_operand:HI 0 "memory_operand" "")
5043 (match_operand:HI 1 "register_operand" ""))
5044 (clobber (match_operand:DI 2 "register_operand" ""))]
5047 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5048 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5050 emit_insn (gen_movhi (operands[0], operands[1]));
5053 /* XXX Fixme, need to handle other cases here as well. */
5058 ;; We use a DImode scratch because we may occasionally need an additional
5059 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5060 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5061 (define_expand "reload_outhi"
5062 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5063 (match_operand:HI 1 "s_register_operand" "r")
5064 (match_operand:DI 2 "s_register_operand" "=&l")])]
5067 arm_reload_out_hi (operands);
5069 thumb_reload_out_hi (operands);
5074 (define_expand "reload_inhi"
5075 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5076 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5077 (match_operand:DI 2 "s_register_operand" "=&r")])]
5081 arm_reload_in_hi (operands);
5083 thumb_reload_out_hi (operands);
5087 (define_expand "movqi"
5088 [(set (match_operand:QI 0 "general_operand" "")
5089 (match_operand:QI 1 "general_operand" ""))]
5092 /* Everything except mem = const or mem = mem can be done easily */
5094 if (!no_new_pseudos)
5096 if (GET_CODE (operands[1]) == CONST_INT)
5098 rtx reg = gen_reg_rtx (SImode);
5100 emit_insn (gen_movsi (reg, operands[1]));
5101 operands[1] = gen_lowpart (QImode, reg);
5106 /* ??? We shouldn't really get invalid addresses here, but this can
5107 happen if we are passed a SP (never OK for HImode/QImode) or
5108 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5109 HImode/QImode) relative address. */
5110 /* ??? This should perhaps be fixed elsewhere, for instance, in
5111 fixup_stack_1, by checking for other kinds of invalid addresses,
5112 e.g. a bare reference to a virtual register. This may confuse the
5113 alpha though, which must handle this case differently. */
5114 if (GET_CODE (operands[0]) == MEM
5115 && !memory_address_p (GET_MODE (operands[0]),
5116 XEXP (operands[0], 0)))
5118 = replace_equiv_address (operands[0],
5119 copy_to_reg (XEXP (operands[0], 0)));
5120 if (GET_CODE (operands[1]) == MEM
5121 && !memory_address_p (GET_MODE (operands[1]),
5122 XEXP (operands[1], 0)))
5124 = replace_equiv_address (operands[1],
5125 copy_to_reg (XEXP (operands[1], 0)));
5128 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5130 rtx reg = gen_reg_rtx (SImode);
5132 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5133 operands[1] = gen_lowpart (QImode, reg);
5136 if (GET_CODE (operands[0]) == MEM)
5137 operands[1] = force_reg (QImode, operands[1]);
5139 else if (TARGET_THUMB
5140 && GET_CODE (operands[1]) == CONST_INT
5141 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5143 /* Handle loading a large integer during reload. */
5145 /* Writing a constant to memory needs a scratch, which should
5146 be handled with SECONDARY_RELOADs. */
5147 gcc_assert (GET_CODE (operands[0]) == REG);
5149 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5150 emit_insn (gen_movsi (operands[0], operands[1]));
5157 (define_insn "*arm_movqi_insn"
5158 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5159 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5161 && ( register_operand (operands[0], QImode)
5162 || register_operand (operands[1], QImode))"
5168 [(set_attr "type" "*,*,load1,store1")
5169 (set_attr "predicable" "yes")]
5172 (define_insn "*thumb_movqi_insn"
5173 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5174 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5176 && ( register_operand (operands[0], QImode)
5177 || register_operand (operands[1], QImode))"
5185 [(set_attr "length" "2")
5186 (set_attr "type" "*,load1,store1,*,*,*")
5187 (set_attr "pool_range" "*,32,*,*,*,*")]
5190 (define_expand "movsf"
5191 [(set (match_operand:SF 0 "general_operand" "")
5192 (match_operand:SF 1 "general_operand" ""))]
5197 if (GET_CODE (operands[0]) == MEM)
5198 operands[1] = force_reg (SFmode, operands[1]);
5200 else /* TARGET_THUMB */
5202 if (!no_new_pseudos)
5204 if (GET_CODE (operands[0]) != REG)
5205 operands[1] = force_reg (SFmode, operands[1]);
5211 ;; Transform a floating-point move of a constant into a core register into
5212 ;; an SImode operation.
5214 [(set (match_operand:SF 0 "arm_general_register_operand" "")
5215 (match_operand:SF 1 "immediate_operand" ""))]
5218 && GET_CODE (operands[1]) == CONST_DOUBLE"
5219 [(set (match_dup 2) (match_dup 3))]
5221 operands[2] = gen_lowpart (SImode, operands[0]);
5222 operands[3] = gen_lowpart (SImode, operands[1]);
5223 if (operands[2] == 0 || operands[3] == 0)
5228 (define_insn "*arm_movsf_soft_insn"
5229 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5230 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5232 && TARGET_SOFT_FLOAT
5233 && (GET_CODE (operands[0]) != MEM
5234 || register_operand (operands[1], SFmode))"
5237 ldr%?\\t%0, %1\\t%@ float
5238 str%?\\t%1, %0\\t%@ float"
5239 [(set_attr "length" "4,4,4")
5240 (set_attr "predicable" "yes")
5241 (set_attr "type" "*,load1,store1")
5242 (set_attr "pool_range" "*,4096,*")
5243 (set_attr "neg_pool_range" "*,4084,*")]
5246 ;;; ??? This should have alternatives for constants.
5247 (define_insn "*thumb_movsf_insn"
5248 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5249 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5251 && ( register_operand (operands[0], SFmode)
5252 || register_operand (operands[1], SFmode))"
5261 [(set_attr "length" "2")
5262 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5263 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5266 (define_expand "movdf"
5267 [(set (match_operand:DF 0 "general_operand" "")
5268 (match_operand:DF 1 "general_operand" ""))]
5273 if (GET_CODE (operands[0]) == MEM)
5274 operands[1] = force_reg (DFmode, operands[1]);
5276 else /* TARGET_THUMB */
5278 if (!no_new_pseudos)
5280 if (GET_CODE (operands[0]) != REG)
5281 operands[1] = force_reg (DFmode, operands[1]);
5287 ;; Reloading a df mode value stored in integer regs to memory can require a
5289 (define_expand "reload_outdf"
5290 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5291 (match_operand:DF 1 "s_register_operand" "r")
5292 (match_operand:SI 2 "s_register_operand" "=&r")]
5296 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5299 operands[2] = XEXP (operands[0], 0);
5300 else if (code == POST_INC || code == PRE_DEC)
5302 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5303 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5304 emit_insn (gen_movdi (operands[0], operands[1]));
5307 else if (code == PRE_INC)
5309 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5311 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5314 else if (code == POST_DEC)
5315 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5317 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5318 XEXP (XEXP (operands[0], 0), 1)));
5320 emit_insn (gen_rtx_SET (VOIDmode,
5321 replace_equiv_address (operands[0], operands[2]),
5324 if (code == POST_DEC)
5325 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5331 (define_insn "*movdf_soft_insn"
5332 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5333 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5334 "TARGET_ARM && TARGET_SOFT_FLOAT
5335 && ( register_operand (operands[0], DFmode)
5336 || register_operand (operands[1], DFmode))"
5338 switch (which_alternative)
5345 return output_move_double (operands);
5348 [(set_attr "length" "8,12,16,8,8")
5349 (set_attr "type" "*,*,*,load2,store2")
5350 (set_attr "pool_range" "1020")
5351 (set_attr "neg_pool_range" "1008")]
5354 ;;; ??? This should have alternatives for constants.
5355 ;;; ??? This was originally identical to the movdi_insn pattern.
5356 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5357 ;;; thumb_reorg with a memory reference.
5358 (define_insn "*thumb_movdf_insn"
5359 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5360 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5362 && ( register_operand (operands[0], DFmode)
5363 || register_operand (operands[1], DFmode))"
5365 switch (which_alternative)
5369 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5370 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5371 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5373 return \"ldmia\\t%1, {%0, %H0}\";
5375 return \"stmia\\t%0, {%1, %H1}\";
5377 return thumb_load_double_from_address (operands);
5379 operands[2] = gen_rtx_MEM (SImode,
5380 plus_constant (XEXP (operands[0], 0), 4));
5381 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5384 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5385 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5386 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5389 [(set_attr "length" "4,2,2,6,4,4")
5390 (set_attr "type" "*,load2,store2,load2,store2,*")
5391 (set_attr "pool_range" "*,*,*,1020,*,*")]
5394 (define_expand "movxf"
5395 [(set (match_operand:XF 0 "general_operand" "")
5396 (match_operand:XF 1 "general_operand" ""))]
5397 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5399 if (GET_CODE (operands[0]) == MEM)
5400 operands[1] = force_reg (XFmode, operands[1]);
5405 (define_expand "movv2si"
5406 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5407 (match_operand:V2SI 1 "general_operand" ""))]
5408 "TARGET_REALLY_IWMMXT"
5412 (define_expand "movv4hi"
5413 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5414 (match_operand:V4HI 1 "general_operand" ""))]
5415 "TARGET_REALLY_IWMMXT"
5419 (define_expand "movv8qi"
5420 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5421 (match_operand:V8QI 1 "general_operand" ""))]
5422 "TARGET_REALLY_IWMMXT"
5427 ;; load- and store-multiple insns
5428 ;; The arm can load/store any set of registers, provided that they are in
5429 ;; ascending order; but that is beyond GCC so stick with what it knows.
5431 (define_expand "load_multiple"
5432 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5433 (match_operand:SI 1 "" ""))
5434 (use (match_operand:SI 2 "" ""))])]
5437 HOST_WIDE_INT offset = 0;
5439 /* Support only fixed point registers. */
5440 if (GET_CODE (operands[2]) != CONST_INT
5441 || INTVAL (operands[2]) > 14
5442 || INTVAL (operands[2]) < 2
5443 || GET_CODE (operands[1]) != MEM
5444 || GET_CODE (operands[0]) != REG
5445 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5446 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5450 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5451 force_reg (SImode, XEXP (operands[1], 0)),
5452 TRUE, FALSE, operands[1], &offset);
5455 ;; Load multiple with write-back
5457 (define_insn "*ldmsi_postinc4"
5458 [(match_parallel 0 "load_multiple_operation"
5459 [(set (match_operand:SI 1 "s_register_operand" "=r")
5460 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5462 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5463 (mem:SI (match_dup 2)))
5464 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5465 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5466 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5467 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5468 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5469 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5470 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5471 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5472 [(set_attr "type" "load4")
5473 (set_attr "predicable" "yes")]
5476 (define_insn "*ldmsi_postinc4_thumb"
5477 [(match_parallel 0 "load_multiple_operation"
5478 [(set (match_operand:SI 1 "s_register_operand" "=l")
5479 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5481 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5482 (mem:SI (match_dup 2)))
5483 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5484 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5485 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5486 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5487 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5488 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5489 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5490 "ldmia\\t%1!, {%3, %4, %5, %6}"
5491 [(set_attr "type" "load4")]
5494 (define_insn "*ldmsi_postinc3"
5495 [(match_parallel 0 "load_multiple_operation"
5496 [(set (match_operand:SI 1 "s_register_operand" "=r")
5497 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5499 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5500 (mem:SI (match_dup 2)))
5501 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5502 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5503 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5504 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5505 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5506 "ldm%?ia\\t%1!, {%3, %4, %5}"
5507 [(set_attr "type" "load3")
5508 (set_attr "predicable" "yes")]
5511 (define_insn "*ldmsi_postinc2"
5512 [(match_parallel 0 "load_multiple_operation"
5513 [(set (match_operand:SI 1 "s_register_operand" "=r")
5514 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5516 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5517 (mem:SI (match_dup 2)))
5518 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5519 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5520 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5521 "ldm%?ia\\t%1!, {%3, %4}"
5522 [(set_attr "type" "load2")
5523 (set_attr "predicable" "yes")]
5526 ;; Ordinary load multiple
5528 (define_insn "*ldmsi4"
5529 [(match_parallel 0 "load_multiple_operation"
5530 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5531 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5532 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5533 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5534 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5535 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5536 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5537 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5538 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5539 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5540 [(set_attr "type" "load4")
5541 (set_attr "predicable" "yes")]
5544 (define_insn "*ldmsi3"
5545 [(match_parallel 0 "load_multiple_operation"
5546 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5547 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5548 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5549 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5550 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5551 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5552 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5553 "ldm%?ia\\t%1, {%2, %3, %4}"
5554 [(set_attr "type" "load3")
5555 (set_attr "predicable" "yes")]
5558 (define_insn "*ldmsi2"
5559 [(match_parallel 0 "load_multiple_operation"
5560 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5561 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5562 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5563 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5564 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5565 "ldm%?ia\\t%1, {%2, %3}"
5566 [(set_attr "type" "load2")
5567 (set_attr "predicable" "yes")]
5570 (define_expand "store_multiple"
5571 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5572 (match_operand:SI 1 "" ""))
5573 (use (match_operand:SI 2 "" ""))])]
5576 HOST_WIDE_INT offset = 0;
5578 /* Support only fixed point registers. */
5579 if (GET_CODE (operands[2]) != CONST_INT
5580 || INTVAL (operands[2]) > 14
5581 || INTVAL (operands[2]) < 2
5582 || GET_CODE (operands[1]) != REG
5583 || GET_CODE (operands[0]) != MEM
5584 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5585 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5589 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5590 force_reg (SImode, XEXP (operands[0], 0)),
5591 TRUE, FALSE, operands[0], &offset);
5594 ;; Store multiple with write-back
5596 (define_insn "*stmsi_postinc4"
5597 [(match_parallel 0 "store_multiple_operation"
5598 [(set (match_operand:SI 1 "s_register_operand" "=r")
5599 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5601 (set (mem:SI (match_dup 2))
5602 (match_operand:SI 3 "arm_hard_register_operand" ""))
5603 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5604 (match_operand:SI 4 "arm_hard_register_operand" ""))
5605 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5606 (match_operand:SI 5 "arm_hard_register_operand" ""))
5607 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5608 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5609 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5610 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5611 [(set_attr "predicable" "yes")
5612 (set_attr "type" "store4")]
5615 (define_insn "*stmsi_postinc4_thumb"
5616 [(match_parallel 0 "store_multiple_operation"
5617 [(set (match_operand:SI 1 "s_register_operand" "=l")
5618 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5620 (set (mem:SI (match_dup 2))
5621 (match_operand:SI 3 "arm_hard_register_operand" ""))
5622 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5623 (match_operand:SI 4 "arm_hard_register_operand" ""))
5624 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5625 (match_operand:SI 5 "arm_hard_register_operand" ""))
5626 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5627 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5628 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5629 "stmia\\t%1!, {%3, %4, %5, %6}"
5630 [(set_attr "type" "store4")]
5633 (define_insn "*stmsi_postinc3"
5634 [(match_parallel 0 "store_multiple_operation"
5635 [(set (match_operand:SI 1 "s_register_operand" "=r")
5636 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5638 (set (mem:SI (match_dup 2))
5639 (match_operand:SI 3 "arm_hard_register_operand" ""))
5640 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5641 (match_operand:SI 4 "arm_hard_register_operand" ""))
5642 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5643 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5644 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5645 "stm%?ia\\t%1!, {%3, %4, %5}"
5646 [(set_attr "predicable" "yes")
5647 (set_attr "type" "store3")]
5650 (define_insn "*stmsi_postinc2"
5651 [(match_parallel 0 "store_multiple_operation"
5652 [(set (match_operand:SI 1 "s_register_operand" "=r")
5653 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5655 (set (mem:SI (match_dup 2))
5656 (match_operand:SI 3 "arm_hard_register_operand" ""))
5657 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5658 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5659 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5660 "stm%?ia\\t%1!, {%3, %4}"
5661 [(set_attr "predicable" "yes")
5662 (set_attr "type" "store2")]
5665 ;; Ordinary store multiple
5667 (define_insn "*stmsi4"
5668 [(match_parallel 0 "store_multiple_operation"
5669 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5670 (match_operand:SI 2 "arm_hard_register_operand" ""))
5671 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5672 (match_operand:SI 3 "arm_hard_register_operand" ""))
5673 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5674 (match_operand:SI 4 "arm_hard_register_operand" ""))
5675 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5676 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5677 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5678 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5679 [(set_attr "predicable" "yes")
5680 (set_attr "type" "store4")]
5683 (define_insn "*stmsi3"
5684 [(match_parallel 0 "store_multiple_operation"
5685 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5686 (match_operand:SI 2 "arm_hard_register_operand" ""))
5687 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5688 (match_operand:SI 3 "arm_hard_register_operand" ""))
5689 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5690 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5691 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5692 "stm%?ia\\t%1, {%2, %3, %4}"
5693 [(set_attr "predicable" "yes")
5694 (set_attr "type" "store3")]
5697 (define_insn "*stmsi2"
5698 [(match_parallel 0 "store_multiple_operation"
5699 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5700 (match_operand:SI 2 "arm_hard_register_operand" ""))
5701 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5702 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5703 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5704 "stm%?ia\\t%1, {%2, %3}"
5705 [(set_attr "predicable" "yes")
5706 (set_attr "type" "store2")]
5709 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5710 ;; We could let this apply for blocks of less than this, but it clobbers so
5711 ;; many registers that there is then probably a better way.
5713 (define_expand "movmemqi"
5714 [(match_operand:BLK 0 "general_operand" "")
5715 (match_operand:BLK 1 "general_operand" "")
5716 (match_operand:SI 2 "const_int_operand" "")
5717 (match_operand:SI 3 "const_int_operand" "")]
5722 if (arm_gen_movmemqi (operands))
5726 else /* TARGET_THUMB */
5728 if ( INTVAL (operands[3]) != 4
5729 || INTVAL (operands[2]) > 48)
5732 thumb_expand_movmemqi (operands);
5738 ;; Thumb block-move insns
5740 (define_insn "movmem12b"
5741 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5742 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5743 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5744 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5745 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5746 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5747 (set (match_operand:SI 0 "register_operand" "=l")
5748 (plus:SI (match_dup 2) (const_int 12)))
5749 (set (match_operand:SI 1 "register_operand" "=l")
5750 (plus:SI (match_dup 3) (const_int 12)))
5751 (clobber (match_scratch:SI 4 "=&l"))
5752 (clobber (match_scratch:SI 5 "=&l"))
5753 (clobber (match_scratch:SI 6 "=&l"))]
5755 "* return thumb_output_move_mem_multiple (3, operands);"
5756 [(set_attr "length" "4")
5757 ; This isn't entirely accurate... It loads as well, but in terms of
5758 ; scheduling the following insn it is better to consider it as a store
5759 (set_attr "type" "store3")]
5762 (define_insn "movmem8b"
5763 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5764 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5765 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5766 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5767 (set (match_operand:SI 0 "register_operand" "=l")
5768 (plus:SI (match_dup 2) (const_int 8)))
5769 (set (match_operand:SI 1 "register_operand" "=l")
5770 (plus:SI (match_dup 3) (const_int 8)))
5771 (clobber (match_scratch:SI 4 "=&l"))
5772 (clobber (match_scratch:SI 5 "=&l"))]
5774 "* return thumb_output_move_mem_multiple (2, operands);"
5775 [(set_attr "length" "4")
5776 ; This isn't entirely accurate... It loads as well, but in terms of
5777 ; scheduling the following insn it is better to consider it as a store
5778 (set_attr "type" "store2")]
5783 ;; Compare & branch insns
5784 ;; The range calculations are based as follows:
5785 ;; For forward branches, the address calculation returns the address of
5786 ;; the next instruction. This is 2 beyond the branch instruction.
5787 ;; For backward branches, the address calculation returns the address of
5788 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5789 ;; instruction for the shortest sequence, and 4 before the branch instruction
5790 ;; if we have to jump around an unconditional branch.
5791 ;; To the basic branch range the PC offset must be added (this is +4).
5792 ;; So for forward branches we have
5793 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5794 ;; And for backward branches we have
5795 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5797 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5798 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5800 (define_expand "cbranchsi4"
5801 [(set (pc) (if_then_else
5802 (match_operator 0 "arm_comparison_operator"
5803 [(match_operand:SI 1 "s_register_operand" "")
5804 (match_operand:SI 2 "nonmemory_operand" "")])
5805 (label_ref (match_operand 3 "" ""))
5809 if (thumb_cmpneg_operand (operands[2], SImode))
5811 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5812 operands[3], operands[0]));
5815 if (!thumb_cmp_operand (operands[2], SImode))
5816 operands[2] = force_reg (SImode, operands[2]);
5819 (define_insn "*cbranchsi4_insn"
5820 [(set (pc) (if_then_else
5821 (match_operator 0 "arm_comparison_operator"
5822 [(match_operand:SI 1 "s_register_operand" "l,*h")
5823 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5824 (label_ref (match_operand 3 "" ""))
5828 output_asm_insn (\"cmp\\t%1, %2\", operands);
5830 switch (get_attr_length (insn))
5832 case 4: return \"b%d0\\t%l3\";
5833 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5837 [(set (attr "far_jump")
5839 (eq_attr "length" "8")
5840 (const_string "yes")
5841 (const_string "no")))
5842 (set (attr "length")
5844 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845 (le (minus (match_dup 3) (pc)) (const_int 256)))
5848 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5854 (define_insn "cbranchsi4_scratch"
5855 [(set (pc) (if_then_else
5856 (match_operator 4 "arm_comparison_operator"
5857 [(match_operand:SI 1 "s_register_operand" "l,0")
5858 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5859 (label_ref (match_operand 3 "" ""))
5861 (clobber (match_scratch:SI 0 "=l,l"))]
5864 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5866 switch (get_attr_length (insn))
5868 case 4: return \"b%d4\\t%l3\";
5869 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5870 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5873 [(set (attr "far_jump")
5875 (eq_attr "length" "8")
5876 (const_string "yes")
5877 (const_string "no")))
5878 (set (attr "length")
5880 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5881 (le (minus (match_dup 3) (pc)) (const_int 256)))
5884 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5885 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5889 (define_insn "*movsi_cbranchsi4"
5892 (match_operator 3 "arm_comparison_operator"
5893 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5895 (label_ref (match_operand 2 "" ""))
5897 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5901 if (which_alternative == 0)
5902 output_asm_insn (\"cmp\t%0, #0\", operands);
5903 else if (which_alternative == 1)
5904 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5907 output_asm_insn (\"cmp\t%1, #0\", operands);
5908 if (which_alternative == 2)
5909 output_asm_insn (\"mov\t%0, %1\", operands);
5911 output_asm_insn (\"str\t%1, %0\", operands);
5913 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5915 case 4: return \"b%d3\\t%l2\";
5916 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5917 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5920 [(set (attr "far_jump")
5922 (ior (and (gt (symbol_ref ("which_alternative"))
5924 (eq_attr "length" "8"))
5925 (eq_attr "length" "10"))
5926 (const_string "yes")
5927 (const_string "no")))
5928 (set (attr "length")
5930 (le (symbol_ref ("which_alternative"))
5933 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5934 (le (minus (match_dup 2) (pc)) (const_int 256)))
5937 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5938 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5942 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5943 (le (minus (match_dup 2) (pc)) (const_int 256)))
5946 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5947 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5952 (define_insn "*negated_cbranchsi4"
5955 (match_operator 0 "equality_operator"
5956 [(match_operand:SI 1 "s_register_operand" "l")
5957 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5958 (label_ref (match_operand 3 "" ""))
5962 output_asm_insn (\"cmn\\t%1, %2\", operands);
5963 switch (get_attr_length (insn))
5965 case 4: return \"b%d0\\t%l3\";
5966 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5967 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5970 [(set (attr "far_jump")
5972 (eq_attr "length" "8")
5973 (const_string "yes")
5974 (const_string "no")))
5975 (set (attr "length")
5977 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5978 (le (minus (match_dup 3) (pc)) (const_int 256)))
5981 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5982 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5987 (define_insn "*tbit_cbranch"
5990 (match_operator 0 "equality_operator"
5991 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5993 (match_operand:SI 2 "const_int_operand" "i"))
5995 (label_ref (match_operand 3 "" ""))
5997 (clobber (match_scratch:SI 4 "=l"))]
6002 op[0] = operands[4];
6003 op[1] = operands[1];
6004 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6006 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6007 switch (get_attr_length (insn))
6009 case 4: return \"b%d0\\t%l3\";
6010 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6011 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6014 [(set (attr "far_jump")
6016 (eq_attr "length" "8")
6017 (const_string "yes")
6018 (const_string "no")))
6019 (set (attr "length")
6021 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6022 (le (minus (match_dup 3) (pc)) (const_int 256)))
6025 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6026 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6031 (define_insn "*tlobits_cbranch"
6034 (match_operator 0 "equality_operator"
6035 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6036 (match_operand:SI 2 "const_int_operand" "i")
6039 (label_ref (match_operand 3 "" ""))
6041 (clobber (match_scratch:SI 4 "=l"))]
6046 op[0] = operands[4];
6047 op[1] = operands[1];
6048 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6050 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6051 switch (get_attr_length (insn))
6053 case 4: return \"b%d0\\t%l3\";
6054 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6055 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6058 [(set (attr "far_jump")
6060 (eq_attr "length" "8")
6061 (const_string "yes")
6062 (const_string "no")))
6063 (set (attr "length")
6065 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6066 (le (minus (match_dup 3) (pc)) (const_int 256)))
6069 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6070 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6075 (define_insn "*tstsi3_cbranch"
6078 (match_operator 3 "equality_operator"
6079 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6080 (match_operand:SI 1 "s_register_operand" "l"))
6082 (label_ref (match_operand 2 "" ""))
6087 output_asm_insn (\"tst\\t%0, %1\", operands);
6088 switch (get_attr_length (insn))
6090 case 4: return \"b%d3\\t%l2\";
6091 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6092 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6095 [(set (attr "far_jump")
6097 (eq_attr "length" "8")
6098 (const_string "yes")
6099 (const_string "no")))
6100 (set (attr "length")
6102 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6103 (le (minus (match_dup 2) (pc)) (const_int 256)))
6106 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6107 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6112 (define_insn "*andsi3_cbranch"
6115 (match_operator 5 "equality_operator"
6116 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6119 (label_ref (match_operand 4 "" ""))
6121 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6122 (and:SI (match_dup 2) (match_dup 3)))
6123 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6127 if (which_alternative == 0)
6128 output_asm_insn (\"and\\t%0, %3\", operands);
6129 else if (which_alternative == 1)
6131 output_asm_insn (\"and\\t%1, %3\", operands);
6132 output_asm_insn (\"mov\\t%0, %1\", operands);
6136 output_asm_insn (\"and\\t%1, %3\", operands);
6137 output_asm_insn (\"str\\t%1, %0\", operands);
6140 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6142 case 4: return \"b%d5\\t%l4\";
6143 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6147 [(set (attr "far_jump")
6149 (ior (and (eq (symbol_ref ("which_alternative"))
6151 (eq_attr "length" "8"))
6152 (eq_attr "length" "10"))
6153 (const_string "yes")
6154 (const_string "no")))
6155 (set (attr "length")
6157 (eq (symbol_ref ("which_alternative"))
6160 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161 (le (minus (match_dup 4) (pc)) (const_int 256)))
6164 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6169 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170 (le (minus (match_dup 4) (pc)) (const_int 256)))
6173 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6179 (define_insn "*orrsi3_cbranch_scratch"
6182 (match_operator 4 "equality_operator"
6183 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6184 (match_operand:SI 2 "s_register_operand" "l"))
6186 (label_ref (match_operand 3 "" ""))
6188 (clobber (match_scratch:SI 0 "=l"))]
6192 output_asm_insn (\"orr\\t%0, %2\", operands);
6193 switch (get_attr_length (insn))
6195 case 4: return \"b%d4\\t%l3\";
6196 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6200 [(set (attr "far_jump")
6202 (eq_attr "length" "8")
6203 (const_string "yes")
6204 (const_string "no")))
6205 (set (attr "length")
6207 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208 (le (minus (match_dup 3) (pc)) (const_int 256)))
6211 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6217 (define_insn "*orrsi3_cbranch"
6220 (match_operator 5 "equality_operator"
6221 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6224 (label_ref (match_operand 4 "" ""))
6226 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6227 (ior:SI (match_dup 2) (match_dup 3)))
6228 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6232 if (which_alternative == 0)
6233 output_asm_insn (\"orr\\t%0, %3\", operands);
6234 else if (which_alternative == 1)
6236 output_asm_insn (\"orr\\t%1, %3\", operands);
6237 output_asm_insn (\"mov\\t%0, %1\", operands);
6241 output_asm_insn (\"orr\\t%1, %3\", operands);
6242 output_asm_insn (\"str\\t%1, %0\", operands);
6245 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6247 case 4: return \"b%d5\\t%l4\";
6248 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6252 [(set (attr "far_jump")
6254 (ior (and (eq (symbol_ref ("which_alternative"))
6256 (eq_attr "length" "8"))
6257 (eq_attr "length" "10"))
6258 (const_string "yes")
6259 (const_string "no")))
6260 (set (attr "length")
6262 (eq (symbol_ref ("which_alternative"))
6265 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266 (le (minus (match_dup 4) (pc)) (const_int 256)))
6269 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6274 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275 (le (minus (match_dup 4) (pc)) (const_int 256)))
6278 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6284 (define_insn "*xorsi3_cbranch_scratch"
6287 (match_operator 4 "equality_operator"
6288 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6289 (match_operand:SI 2 "s_register_operand" "l"))
6291 (label_ref (match_operand 3 "" ""))
6293 (clobber (match_scratch:SI 0 "=l"))]
6297 output_asm_insn (\"eor\\t%0, %2\", operands);
6298 switch (get_attr_length (insn))
6300 case 4: return \"b%d4\\t%l3\";
6301 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6305 [(set (attr "far_jump")
6307 (eq_attr "length" "8")
6308 (const_string "yes")
6309 (const_string "no")))
6310 (set (attr "length")
6312 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313 (le (minus (match_dup 3) (pc)) (const_int 256)))
6316 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6322 (define_insn "*xorsi3_cbranch"
6325 (match_operator 5 "equality_operator"
6326 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6327 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6329 (label_ref (match_operand 4 "" ""))
6331 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6332 (xor:SI (match_dup 2) (match_dup 3)))
6333 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6337 if (which_alternative == 0)
6338 output_asm_insn (\"eor\\t%0, %3\", operands);
6339 else if (which_alternative == 1)
6341 output_asm_insn (\"eor\\t%1, %3\", operands);
6342 output_asm_insn (\"mov\\t%0, %1\", operands);
6346 output_asm_insn (\"eor\\t%1, %3\", operands);
6347 output_asm_insn (\"str\\t%1, %0\", operands);
6350 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6352 case 4: return \"b%d5\\t%l4\";
6353 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6354 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6357 [(set (attr "far_jump")
6359 (ior (and (eq (symbol_ref ("which_alternative"))
6361 (eq_attr "length" "8"))
6362 (eq_attr "length" "10"))
6363 (const_string "yes")
6364 (const_string "no")))
6365 (set (attr "length")
6367 (eq (symbol_ref ("which_alternative"))
6370 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6371 (le (minus (match_dup 4) (pc)) (const_int 256)))
6374 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6375 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6379 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6380 (le (minus (match_dup 4) (pc)) (const_int 256)))
6383 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6384 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6389 (define_insn "*bicsi3_cbranch_scratch"
6392 (match_operator 4 "equality_operator"
6393 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6394 (match_operand:SI 1 "s_register_operand" "0"))
6396 (label_ref (match_operand 3 "" ""))
6398 (clobber (match_scratch:SI 0 "=l"))]
6402 output_asm_insn (\"bic\\t%0, %2\", operands);
6403 switch (get_attr_length (insn))
6405 case 4: return \"b%d4\\t%l3\";
6406 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6407 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6410 [(set (attr "far_jump")
6412 (eq_attr "length" "8")
6413 (const_string "yes")
6414 (const_string "no")))
6415 (set (attr "length")
6417 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6418 (le (minus (match_dup 3) (pc)) (const_int 256)))
6421 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6422 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6427 (define_insn "*bicsi3_cbranch"
6430 (match_operator 5 "equality_operator"
6431 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6432 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6434 (label_ref (match_operand 4 "" ""))
6436 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6437 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6438 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6442 if (which_alternative == 0)
6443 output_asm_insn (\"bic\\t%0, %3\", operands);
6444 else if (which_alternative <= 2)
6446 output_asm_insn (\"bic\\t%1, %3\", operands);
6447 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6448 conditions again, since we're only testing for equality. */
6449 output_asm_insn (\"mov\\t%0, %1\", operands);
6453 output_asm_insn (\"bic\\t%1, %3\", operands);
6454 output_asm_insn (\"str\\t%1, %0\", operands);
6457 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6459 case 4: return \"b%d5\\t%l4\";
6460 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6461 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6464 [(set (attr "far_jump")
6466 (ior (and (eq (symbol_ref ("which_alternative"))
6468 (eq_attr "length" "8"))
6469 (eq_attr "length" "10"))
6470 (const_string "yes")
6471 (const_string "no")))
6472 (set (attr "length")
6474 (eq (symbol_ref ("which_alternative"))
6477 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6478 (le (minus (match_dup 4) (pc)) (const_int 256)))
6481 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6482 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6486 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6487 (le (minus (match_dup 4) (pc)) (const_int 256)))
6490 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6491 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6496 (define_insn "*cbranchne_decr1"
6498 (if_then_else (match_operator 3 "equality_operator"
6499 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6501 (label_ref (match_operand 4 "" ""))
6503 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6504 (plus:SI (match_dup 2) (const_int -1)))
6505 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6510 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6512 VOIDmode, operands[2], const1_rtx);
6513 cond[1] = operands[4];
6515 if (which_alternative == 0)
6516 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6517 else if (which_alternative == 1)
6519 /* We must provide an alternative for a hi reg because reload
6520 cannot handle output reloads on a jump instruction, but we
6521 can't subtract into that. Fortunately a mov from lo to hi
6522 does not clobber the condition codes. */
6523 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6524 output_asm_insn (\"mov\\t%0, %1\", operands);
6528 /* Similarly, but the target is memory. */
6529 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6530 output_asm_insn (\"str\\t%1, %0\", operands);
6533 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6536 output_asm_insn (\"b%d0\\t%l1\", cond);
6539 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6540 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6542 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6543 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6547 [(set (attr "far_jump")
6549 (ior (and (eq (symbol_ref ("which_alternative"))
6551 (eq_attr "length" "8"))
6552 (eq_attr "length" "10"))
6553 (const_string "yes")
6554 (const_string "no")))
6555 (set_attr_alternative "length"
6559 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6560 (le (minus (match_dup 4) (pc)) (const_int 256)))
6563 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6564 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6569 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6570 (le (minus (match_dup 4) (pc)) (const_int 256)))
6573 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6574 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6579 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6580 (le (minus (match_dup 4) (pc)) (const_int 256)))
6583 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6584 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6589 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6590 (le (minus (match_dup 4) (pc)) (const_int 256)))
6593 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6594 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6599 (define_insn "*addsi3_cbranch"
6602 (match_operator 4 "comparison_operator"
6604 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6605 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6607 (label_ref (match_operand 5 "" ""))
6610 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6611 (plus:SI (match_dup 2) (match_dup 3)))
6612 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6614 && (GET_CODE (operands[4]) == EQ
6615 || GET_CODE (operands[4]) == NE
6616 || GET_CODE (operands[4]) == GE
6617 || GET_CODE (operands[4]) == LT)"
6623 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6624 cond[1] = operands[2];
6625 cond[2] = operands[3];
6627 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6628 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6630 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6632 if (which_alternative >= 3
6633 && which_alternative < 4)
6634 output_asm_insn (\"mov\\t%0, %1\", operands);
6635 else if (which_alternative >= 4)
6636 output_asm_insn (\"str\\t%1, %0\", operands);
6638 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6641 return \"b%d4\\t%l5\";
6643 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6645 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6649 [(set (attr "far_jump")
6651 (ior (and (lt (symbol_ref ("which_alternative"))
6653 (eq_attr "length" "8"))
6654 (eq_attr "length" "10"))
6655 (const_string "yes")
6656 (const_string "no")))
6657 (set (attr "length")
6659 (lt (symbol_ref ("which_alternative"))
6662 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6663 (le (minus (match_dup 5) (pc)) (const_int 256)))
6666 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6667 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6671 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6672 (le (minus (match_dup 5) (pc)) (const_int 256)))
6675 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6676 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6681 (define_insn "*addsi3_cbranch_scratch"
6684 (match_operator 3 "comparison_operator"
6686 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6687 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6689 (label_ref (match_operand 4 "" ""))
6691 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6693 && (GET_CODE (operands[3]) == EQ
6694 || GET_CODE (operands[3]) == NE
6695 || GET_CODE (operands[3]) == GE
6696 || GET_CODE (operands[3]) == LT)"
6699 switch (which_alternative)
6702 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6705 output_asm_insn (\"cmn\t%1, %2\", operands);
6708 if (INTVAL (operands[2]) < 0)
6709 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6711 output_asm_insn (\"add\t%0, %1, %2\", operands);
6714 if (INTVAL (operands[2]) < 0)
6715 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6717 output_asm_insn (\"add\t%0, %0, %2\", operands);
6721 switch (get_attr_length (insn))
6724 return \"b%d3\\t%l4\";
6726 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6728 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6732 [(set (attr "far_jump")
6734 (eq_attr "length" "8")
6735 (const_string "yes")
6736 (const_string "no")))
6737 (set (attr "length")
6739 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6740 (le (minus (match_dup 4) (pc)) (const_int 256)))
6743 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6744 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6749 (define_insn "*subsi3_cbranch"
6752 (match_operator 4 "comparison_operator"
6754 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6755 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6757 (label_ref (match_operand 5 "" ""))
6759 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6760 (minus:SI (match_dup 2) (match_dup 3)))
6761 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6763 && (GET_CODE (operands[4]) == EQ
6764 || GET_CODE (operands[4]) == NE
6765 || GET_CODE (operands[4]) == GE
6766 || GET_CODE (operands[4]) == LT)"
6769 if (which_alternative == 0)
6770 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6771 else if (which_alternative == 1)
6773 /* We must provide an alternative for a hi reg because reload
6774 cannot handle output reloads on a jump instruction, but we
6775 can't subtract into that. Fortunately a mov from lo to hi
6776 does not clobber the condition codes. */
6777 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6778 output_asm_insn (\"mov\\t%0, %1\", operands);
6782 /* Similarly, but the target is memory. */
6783 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6784 output_asm_insn (\"str\\t%1, %0\", operands);
6787 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6790 return \"b%d4\\t%l5\";
6792 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6794 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6798 [(set (attr "far_jump")
6800 (ior (and (eq (symbol_ref ("which_alternative"))
6802 (eq_attr "length" "8"))
6803 (eq_attr "length" "10"))
6804 (const_string "yes")
6805 (const_string "no")))
6806 (set (attr "length")
6808 (eq (symbol_ref ("which_alternative"))
6811 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6812 (le (minus (match_dup 5) (pc)) (const_int 256)))
6815 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6816 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6820 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6821 (le (minus (match_dup 5) (pc)) (const_int 256)))
6824 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6825 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6830 (define_insn "*subsi3_cbranch_scratch"
6833 (match_operator 0 "arm_comparison_operator"
6834 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6835 (match_operand:SI 2 "nonmemory_operand" "l"))
6837 (label_ref (match_operand 3 "" ""))
6840 && (GET_CODE (operands[0]) == EQ
6841 || GET_CODE (operands[0]) == NE
6842 || GET_CODE (operands[0]) == GE
6843 || GET_CODE (operands[0]) == LT)"
6845 output_asm_insn (\"cmp\\t%1, %2\", operands);
6846 switch (get_attr_length (insn))
6848 case 4: return \"b%d0\\t%l3\";
6849 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6850 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6853 [(set (attr "far_jump")
6855 (eq_attr "length" "8")
6856 (const_string "yes")
6857 (const_string "no")))
6858 (set (attr "length")
6860 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6861 (le (minus (match_dup 3) (pc)) (const_int 256)))
6864 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6865 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6870 ;; Comparison and test insns
6872 (define_expand "cmpsi"
6873 [(match_operand:SI 0 "s_register_operand" "")
6874 (match_operand:SI 1 "arm_add_operand" "")]
6877 arm_compare_op0 = operands[0];
6878 arm_compare_op1 = operands[1];
6883 (define_expand "cmpsf"
6884 [(match_operand:SF 0 "s_register_operand" "")
6885 (match_operand:SF 1 "arm_float_compare_operand" "")]
6886 "TARGET_ARM && TARGET_HARD_FLOAT"
6888 arm_compare_op0 = operands[0];
6889 arm_compare_op1 = operands[1];
6894 (define_expand "cmpdf"
6895 [(match_operand:DF 0 "s_register_operand" "")
6896 (match_operand:DF 1 "arm_float_compare_operand" "")]
6897 "TARGET_ARM && TARGET_HARD_FLOAT"
6899 arm_compare_op0 = operands[0];
6900 arm_compare_op1 = operands[1];
6905 (define_insn "*arm_cmpsi_insn"
6906 [(set (reg:CC CC_REGNUM)
6907 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6908 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6913 [(set_attr "conds" "set")]
6916 (define_insn "*cmpsi_shiftsi"
6917 [(set (reg:CC CC_REGNUM)
6918 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6919 (match_operator:SI 3 "shift_operator"
6920 [(match_operand:SI 1 "s_register_operand" "r")
6921 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6924 [(set_attr "conds" "set")
6925 (set_attr "shift" "1")
6926 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6927 (const_string "alu_shift")
6928 (const_string "alu_shift_reg")))]
6931 (define_insn "*cmpsi_shiftsi_swp"
6932 [(set (reg:CC_SWP CC_REGNUM)
6933 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6934 [(match_operand:SI 1 "s_register_operand" "r")
6935 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6936 (match_operand:SI 0 "s_register_operand" "r")))]
6939 [(set_attr "conds" "set")
6940 (set_attr "shift" "1")
6941 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6942 (const_string "alu_shift")
6943 (const_string "alu_shift_reg")))]
6946 (define_insn "*cmpsi_negshiftsi_si"
6947 [(set (reg:CC_Z CC_REGNUM)
6949 (neg:SI (match_operator:SI 1 "shift_operator"
6950 [(match_operand:SI 2 "s_register_operand" "r")
6951 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6952 (match_operand:SI 0 "s_register_operand" "r")))]
6955 [(set_attr "conds" "set")
6956 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6957 (const_string "alu_shift")
6958 (const_string "alu_shift_reg")))]
6961 ;; Cirrus SF compare instruction
6962 (define_insn "*cirrus_cmpsf"
6963 [(set (reg:CCFP CC_REGNUM)
6964 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6965 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6966 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6967 "cfcmps%?\\tr15, %V0, %V1"
6968 [(set_attr "type" "mav_farith")
6969 (set_attr "cirrus" "compare")]
6972 ;; Cirrus DF compare instruction
6973 (define_insn "*cirrus_cmpdf"
6974 [(set (reg:CCFP CC_REGNUM)
6975 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6976 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6977 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6978 "cfcmpd%?\\tr15, %V0, %V1"
6979 [(set_attr "type" "mav_farith")
6980 (set_attr "cirrus" "compare")]
6983 ;; Cirrus DI compare instruction
6984 (define_expand "cmpdi"
6985 [(match_operand:DI 0 "cirrus_fp_register" "")
6986 (match_operand:DI 1 "cirrus_fp_register" "")]
6987 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6989 arm_compare_op0 = operands[0];
6990 arm_compare_op1 = operands[1];
6994 (define_insn "*cirrus_cmpdi"
6995 [(set (reg:CC CC_REGNUM)
6996 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6997 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6998 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6999 "cfcmp64%?\\tr15, %V0, %V1"
7000 [(set_attr "type" "mav_farith")
7001 (set_attr "cirrus" "compare")]
7004 ; This insn allows redundant compares to be removed by cse, nothing should
7005 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7006 ; is deleted later on. The match_dup will match the mode here, so that
7007 ; mode changes of the condition codes aren't lost by this even though we don't
7008 ; specify what they are.
7010 (define_insn "*deleted_compare"
7011 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7013 "\\t%@ deleted compare"
7014 [(set_attr "conds" "set")
7015 (set_attr "length" "0")]
7019 ;; Conditional branch insns
7021 (define_expand "beq"
7023 (if_then_else (eq (match_dup 1) (const_int 0))
7024 (label_ref (match_operand 0 "" ""))
7027 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7030 (define_expand "bne"
7032 (if_then_else (ne (match_dup 1) (const_int 0))
7033 (label_ref (match_operand 0 "" ""))
7036 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7039 (define_expand "bgt"
7041 (if_then_else (gt (match_dup 1) (const_int 0))
7042 (label_ref (match_operand 0 "" ""))
7045 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7048 (define_expand "ble"
7050 (if_then_else (le (match_dup 1) (const_int 0))
7051 (label_ref (match_operand 0 "" ""))
7054 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7057 (define_expand "bge"
7059 (if_then_else (ge (match_dup 1) (const_int 0))
7060 (label_ref (match_operand 0 "" ""))
7063 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7066 (define_expand "blt"
7068 (if_then_else (lt (match_dup 1) (const_int 0))
7069 (label_ref (match_operand 0 "" ""))
7072 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7075 (define_expand "bgtu"
7077 (if_then_else (gtu (match_dup 1) (const_int 0))
7078 (label_ref (match_operand 0 "" ""))
7081 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7084 (define_expand "bleu"
7086 (if_then_else (leu (match_dup 1) (const_int 0))
7087 (label_ref (match_operand 0 "" ""))
7090 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7093 (define_expand "bgeu"
7095 (if_then_else (geu (match_dup 1) (const_int 0))
7096 (label_ref (match_operand 0 "" ""))
7099 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7102 (define_expand "bltu"
7104 (if_then_else (ltu (match_dup 1) (const_int 0))
7105 (label_ref (match_operand 0 "" ""))
7108 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7111 (define_expand "bunordered"
7113 (if_then_else (unordered (match_dup 1) (const_int 0))
7114 (label_ref (match_operand 0 "" ""))
7116 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7117 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7121 (define_expand "bordered"
7123 (if_then_else (ordered (match_dup 1) (const_int 0))
7124 (label_ref (match_operand 0 "" ""))
7126 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7127 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7131 (define_expand "bungt"
7133 (if_then_else (ungt (match_dup 1) (const_int 0))
7134 (label_ref (match_operand 0 "" ""))
7136 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7137 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7140 (define_expand "bunlt"
7142 (if_then_else (unlt (match_dup 1) (const_int 0))
7143 (label_ref (match_operand 0 "" ""))
7145 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7146 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7149 (define_expand "bunge"
7151 (if_then_else (unge (match_dup 1) (const_int 0))
7152 (label_ref (match_operand 0 "" ""))
7154 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7155 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7158 (define_expand "bunle"
7160 (if_then_else (unle (match_dup 1) (const_int 0))
7161 (label_ref (match_operand 0 "" ""))
7163 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7164 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7167 ;; The following two patterns need two branch instructions, since there is
7168 ;; no single instruction that will handle all cases.
7169 (define_expand "buneq"
7171 (if_then_else (uneq (match_dup 1) (const_int 0))
7172 (label_ref (match_operand 0 "" ""))
7174 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7175 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7178 (define_expand "bltgt"
7180 (if_then_else (ltgt (match_dup 1) (const_int 0))
7181 (label_ref (match_operand 0 "" ""))
7183 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7184 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7188 ;; Patterns to match conditional branch insns.
7191 ; Special pattern to match UNEQ.
7192 (define_insn "*arm_buneq"
7194 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7195 (label_ref (match_operand 0 "" ""))
7197 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7199 gcc_assert (!arm_ccfsm_state);
7201 return \"bvs\\t%l0\;beq\\t%l0\";
7203 [(set_attr "conds" "jump_clob")
7204 (set_attr "length" "8")]
7207 ; Special pattern to match LTGT.
7208 (define_insn "*arm_bltgt"
7210 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7211 (label_ref (match_operand 0 "" ""))
7213 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7215 gcc_assert (!arm_ccfsm_state);
7217 return \"bmi\\t%l0\;bgt\\t%l0\";
7219 [(set_attr "conds" "jump_clob")
7220 (set_attr "length" "8")]
7223 (define_insn "*arm_cond_branch"
7225 (if_then_else (match_operator 1 "arm_comparison_operator"
7226 [(match_operand 2 "cc_register" "") (const_int 0)])
7227 (label_ref (match_operand 0 "" ""))
7231 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7233 arm_ccfsm_state += 2;
7236 return \"b%d1\\t%l0\";
7238 [(set_attr "conds" "use")
7239 (set_attr "type" "branch")]
7242 ; Special pattern to match reversed UNEQ.
7243 (define_insn "*arm_buneq_reversed"
7245 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7247 (label_ref (match_operand 0 "" ""))))]
7248 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7250 gcc_assert (!arm_ccfsm_state);
7252 return \"bmi\\t%l0\;bgt\\t%l0\";
7254 [(set_attr "conds" "jump_clob")
7255 (set_attr "length" "8")]
7258 ; Special pattern to match reversed LTGT.
7259 (define_insn "*arm_bltgt_reversed"
7261 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7263 (label_ref (match_operand 0 "" ""))))]
7264 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266 gcc_assert (!arm_ccfsm_state);
7268 return \"bvs\\t%l0\;beq\\t%l0\";
7270 [(set_attr "conds" "jump_clob")
7271 (set_attr "length" "8")]
7274 (define_insn "*arm_cond_branch_reversed"
7276 (if_then_else (match_operator 1 "arm_comparison_operator"
7277 [(match_operand 2 "cc_register" "") (const_int 0)])
7279 (label_ref (match_operand 0 "" ""))))]
7282 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7284 arm_ccfsm_state += 2;
7287 return \"b%D1\\t%l0\";
7289 [(set_attr "conds" "use")
7290 (set_attr "type" "branch")]
7297 (define_expand "seq"
7298 [(set (match_operand:SI 0 "s_register_operand" "")
7299 (eq:SI (match_dup 1) (const_int 0)))]
7301 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7304 (define_expand "sne"
7305 [(set (match_operand:SI 0 "s_register_operand" "")
7306 (ne:SI (match_dup 1) (const_int 0)))]
7308 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7311 (define_expand "sgt"
7312 [(set (match_operand:SI 0 "s_register_operand" "")
7313 (gt:SI (match_dup 1) (const_int 0)))]
7315 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7318 (define_expand "sle"
7319 [(set (match_operand:SI 0 "s_register_operand" "")
7320 (le:SI (match_dup 1) (const_int 0)))]
7322 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7325 (define_expand "sge"
7326 [(set (match_operand:SI 0 "s_register_operand" "")
7327 (ge:SI (match_dup 1) (const_int 0)))]
7329 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7332 (define_expand "slt"
7333 [(set (match_operand:SI 0 "s_register_operand" "")
7334 (lt:SI (match_dup 1) (const_int 0)))]
7336 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7339 (define_expand "sgtu"
7340 [(set (match_operand:SI 0 "s_register_operand" "")
7341 (gtu:SI (match_dup 1) (const_int 0)))]
7343 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7346 (define_expand "sleu"
7347 [(set (match_operand:SI 0 "s_register_operand" "")
7348 (leu:SI (match_dup 1) (const_int 0)))]
7350 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7353 (define_expand "sgeu"
7354 [(set (match_operand:SI 0 "s_register_operand" "")
7355 (geu:SI (match_dup 1) (const_int 0)))]
7357 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7360 (define_expand "sltu"
7361 [(set (match_operand:SI 0 "s_register_operand" "")
7362 (ltu:SI (match_dup 1) (const_int 0)))]
7364 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7367 (define_expand "sunordered"
7368 [(set (match_operand:SI 0 "s_register_operand" "")
7369 (unordered:SI (match_dup 1) (const_int 0)))]
7370 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7371 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7375 (define_expand "sordered"
7376 [(set (match_operand:SI 0 "s_register_operand" "")
7377 (ordered:SI (match_dup 1) (const_int 0)))]
7378 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7379 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7383 (define_expand "sungt"
7384 [(set (match_operand:SI 0 "s_register_operand" "")
7385 (ungt:SI (match_dup 1) (const_int 0)))]
7386 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7387 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7391 (define_expand "sunge"
7392 [(set (match_operand:SI 0 "s_register_operand" "")
7393 (unge:SI (match_dup 1) (const_int 0)))]
7394 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7395 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7399 (define_expand "sunlt"
7400 [(set (match_operand:SI 0 "s_register_operand" "")
7401 (unlt:SI (match_dup 1) (const_int 0)))]
7402 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7403 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7407 (define_expand "sunle"
7408 [(set (match_operand:SI 0 "s_register_operand" "")
7409 (unle:SI (match_dup 1) (const_int 0)))]
7410 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7411 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7415 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7416 ;;; simple ARM instructions.
7418 ; (define_expand "suneq"
7419 ; [(set (match_operand:SI 0 "s_register_operand" "")
7420 ; (uneq:SI (match_dup 1) (const_int 0)))]
7421 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7422 ; "gcc_unreachable ();"
7425 ; (define_expand "sltgt"
7426 ; [(set (match_operand:SI 0 "s_register_operand" "")
7427 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7428 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7429 ; "gcc_unreachable ();"
7432 (define_insn "*mov_scc"
7433 [(set (match_operand:SI 0 "s_register_operand" "=r")
7434 (match_operator:SI 1 "arm_comparison_operator"
7435 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7437 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7438 [(set_attr "conds" "use")
7439 (set_attr "length" "8")]
7442 (define_insn "*mov_negscc"
7443 [(set (match_operand:SI 0 "s_register_operand" "=r")
7444 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7445 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7447 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7448 [(set_attr "conds" "use")
7449 (set_attr "length" "8")]
7452 (define_insn "*mov_notscc"
7453 [(set (match_operand:SI 0 "s_register_operand" "=r")
7454 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7455 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7457 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7458 [(set_attr "conds" "use")
7459 (set_attr "length" "8")]
7463 ;; Conditional move insns
7465 (define_expand "movsicc"
7466 [(set (match_operand:SI 0 "s_register_operand" "")
7467 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7468 (match_operand:SI 2 "arm_not_operand" "")
7469 (match_operand:SI 3 "arm_not_operand" "")))]
7473 enum rtx_code code = GET_CODE (operands[1]);
7476 if (code == UNEQ || code == LTGT)
7479 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7480 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7484 (define_expand "movsfcc"
7485 [(set (match_operand:SF 0 "s_register_operand" "")
7486 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7487 (match_operand:SF 2 "s_register_operand" "")
7488 (match_operand:SF 3 "nonmemory_operand" "")))]
7492 enum rtx_code code = GET_CODE (operands[1]);
7495 if (code == UNEQ || code == LTGT)
7498 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7499 Otherwise, ensure it is a valid FP add operand */
7500 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7501 || (!arm_float_add_operand (operands[3], SFmode)))
7502 operands[3] = force_reg (SFmode, operands[3]);
7504 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7505 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7509 (define_expand "movdfcc"
7510 [(set (match_operand:DF 0 "s_register_operand" "")
7511 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7512 (match_operand:DF 2 "s_register_operand" "")
7513 (match_operand:DF 3 "arm_float_add_operand" "")))]
7514 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7517 enum rtx_code code = GET_CODE (operands[1]);
7520 if (code == UNEQ || code == LTGT)
7523 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7524 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7528 (define_insn "*movsicc_insn"
7529 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7531 (match_operator 3 "arm_comparison_operator"
7532 [(match_operand 4 "cc_register" "") (const_int 0)])
7533 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7534 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7541 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7542 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7543 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7544 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7545 [(set_attr "length" "4,4,4,4,8,8,8,8")
7546 (set_attr "conds" "use")]
7549 (define_insn "*movsfcc_soft_insn"
7550 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7551 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7552 [(match_operand 4 "cc_register" "") (const_int 0)])
7553 (match_operand:SF 1 "s_register_operand" "0,r")
7554 (match_operand:SF 2 "s_register_operand" "r,0")))]
7555 "TARGET_ARM && TARGET_SOFT_FLOAT"
7559 [(set_attr "conds" "use")]
7563 ;; Jump and linkage insns
7565 (define_expand "jump"
7567 (label_ref (match_operand 0 "" "")))]
7572 (define_insn "*arm_jump"
7574 (label_ref (match_operand 0 "" "")))]
7578 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7580 arm_ccfsm_state += 2;
7583 return \"b%?\\t%l0\";
7586 [(set_attr "predicable" "yes")]
7589 (define_insn "*thumb_jump"
7591 (label_ref (match_operand 0 "" "")))]
7594 if (get_attr_length (insn) == 2)
7596 return \"bl\\t%l0\\t%@ far jump\";
7598 [(set (attr "far_jump")
7600 (eq_attr "length" "4")
7601 (const_string "yes")
7602 (const_string "no")))
7603 (set (attr "length")
7605 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7606 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7611 (define_expand "call"
7612 [(parallel [(call (match_operand 0 "memory_operand" "")
7613 (match_operand 1 "general_operand" ""))
7614 (use (match_operand 2 "" ""))
7615 (clobber (reg:SI LR_REGNUM))])]
7621 /* In an untyped call, we can get NULL for operand 2. */
7622 if (operands[2] == NULL_RTX)
7623 operands[2] = const0_rtx;
7625 /* This is to decide if we should generate indirect calls by loading the
7626 32 bit address of the callee into a register before performing the
7627 branch and link. operand[2] encodes the long_call/short_call
7628 attribute of the function being called. This attribute is set whenever
7629 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7630 is used, and the short_call attribute can also be set if function is
7631 declared as static or if it has already been defined in the current
7632 compilation unit. See arm.c and arm.h for info about this. The third
7633 parameter to arm_is_longcall_p is used to tell it which pattern
7635 callee = XEXP (operands[0], 0);
7637 if ((GET_CODE (callee) == SYMBOL_REF
7638 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7639 || (GET_CODE (callee) != SYMBOL_REF
7640 && GET_CODE (callee) != REG))
7641 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7645 (define_insn "*call_reg_armv5"
7646 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7647 (match_operand 1 "" ""))
7648 (use (match_operand 2 "" ""))
7649 (clobber (reg:SI LR_REGNUM))]
7650 "TARGET_ARM && arm_arch5"
7652 [(set_attr "type" "call")]
7655 (define_insn "*call_reg_arm"
7656 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7657 (match_operand 1 "" ""))
7658 (use (match_operand 2 "" ""))
7659 (clobber (reg:SI LR_REGNUM))]
7660 "TARGET_ARM && !arm_arch5"
7662 return output_call (operands);
7664 ;; length is worst case, normally it is only two
7665 [(set_attr "length" "12")
7666 (set_attr "type" "call")]
7669 (define_insn "*call_mem"
7670 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7671 (match_operand 1 "" ""))
7672 (use (match_operand 2 "" ""))
7673 (clobber (reg:SI LR_REGNUM))]
7676 return output_call_mem (operands);
7678 [(set_attr "length" "12")
7679 (set_attr "type" "call")]
7682 (define_insn "*call_reg_thumb_v5"
7683 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7684 (match_operand 1 "" ""))
7685 (use (match_operand 2 "" ""))
7686 (clobber (reg:SI LR_REGNUM))]
7687 "TARGET_THUMB && arm_arch5"
7689 [(set_attr "length" "2")
7690 (set_attr "type" "call")]
7693 (define_insn "*call_reg_thumb"
7694 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7695 (match_operand 1 "" ""))
7696 (use (match_operand 2 "" ""))
7697 (clobber (reg:SI LR_REGNUM))]
7698 "TARGET_THUMB && !arm_arch5"
7701 if (!TARGET_CALLER_INTERWORKING)
7702 return thumb_call_via_reg (operands[0]);
7703 else if (operands[1] == const0_rtx)
7704 return \"bl\\t%__interwork_call_via_%0\";
7705 else if (frame_pointer_needed)
7706 return \"bl\\t%__interwork_r7_call_via_%0\";
7708 return \"bl\\t%__interwork_r11_call_via_%0\";
7710 [(set_attr "type" "call")]
7713 (define_expand "call_value"
7714 [(parallel [(set (match_operand 0 "" "")
7715 (call (match_operand 1 "memory_operand" "")
7716 (match_operand 2 "general_operand" "")))
7717 (use (match_operand 3 "" ""))
7718 (clobber (reg:SI LR_REGNUM))])]
7722 rtx callee = XEXP (operands[1], 0);
7724 /* In an untyped call, we can get NULL for operand 2. */
7725 if (operands[3] == 0)
7726 operands[3] = const0_rtx;
7728 /* See the comment in define_expand \"call\". */
7729 if ((GET_CODE (callee) == SYMBOL_REF
7730 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7731 || (GET_CODE (callee) != SYMBOL_REF
7732 && GET_CODE (callee) != REG))
7733 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7737 (define_insn "*call_value_reg_armv5"
7738 [(set (match_operand 0 "" "")
7739 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7740 (match_operand 2 "" "")))
7741 (use (match_operand 3 "" ""))
7742 (clobber (reg:SI LR_REGNUM))]
7743 "TARGET_ARM && arm_arch5"
7745 [(set_attr "type" "call")]
7748 (define_insn "*call_value_reg_arm"
7749 [(set (match_operand 0 "" "")
7750 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7751 (match_operand 2 "" "")))
7752 (use (match_operand 3 "" ""))
7753 (clobber (reg:SI LR_REGNUM))]
7754 "TARGET_ARM && !arm_arch5"
7756 return output_call (&operands[1]);
7758 [(set_attr "length" "12")
7759 (set_attr "type" "call")]
7762 (define_insn "*call_value_mem"
7763 [(set (match_operand 0 "" "")
7764 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7765 (match_operand 2 "" "")))
7766 (use (match_operand 3 "" ""))
7767 (clobber (reg:SI LR_REGNUM))]
7768 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7770 return output_call_mem (&operands[1]);
7772 [(set_attr "length" "12")
7773 (set_attr "type" "call")]
7776 (define_insn "*call_value_reg_thumb_v5"
7777 [(set (match_operand 0 "" "")
7778 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7779 (match_operand 2 "" "")))
7780 (use (match_operand 3 "" ""))
7781 (clobber (reg:SI LR_REGNUM))]
7782 "TARGET_THUMB && arm_arch5"
7784 [(set_attr "length" "2")
7785 (set_attr "type" "call")]
7788 (define_insn "*call_value_reg_thumb"
7789 [(set (match_operand 0 "" "")
7790 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7791 (match_operand 2 "" "")))
7792 (use (match_operand 3 "" ""))
7793 (clobber (reg:SI LR_REGNUM))]
7794 "TARGET_THUMB && !arm_arch5"
7797 if (!TARGET_CALLER_INTERWORKING)
7798 return thumb_call_via_reg (operands[1]);
7799 else if (operands[2] == const0_rtx)
7800 return \"bl\\t%__interwork_call_via_%1\";
7801 else if (frame_pointer_needed)
7802 return \"bl\\t%__interwork_r7_call_via_%1\";
7804 return \"bl\\t%__interwork_r11_call_via_%1\";
7806 [(set_attr "type" "call")]
7809 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7810 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7812 (define_insn "*call_symbol"
7813 [(call (mem:SI (match_operand:SI 0 "" ""))
7814 (match_operand 1 "" ""))
7815 (use (match_operand 2 "" ""))
7816 (clobber (reg:SI LR_REGNUM))]
7818 && (GET_CODE (operands[0]) == SYMBOL_REF)
7819 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7822 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7824 [(set_attr "type" "call")]
7827 (define_insn "*call_value_symbol"
7828 [(set (match_operand 0 "" "")
7829 (call (mem:SI (match_operand:SI 1 "" ""))
7830 (match_operand:SI 2 "" "")))
7831 (use (match_operand 3 "" ""))
7832 (clobber (reg:SI LR_REGNUM))]
7834 && (GET_CODE (operands[1]) == SYMBOL_REF)
7835 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7838 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7840 [(set_attr "type" "call")]
7843 (define_insn "*call_insn"
7844 [(call (mem:SI (match_operand:SI 0 "" ""))
7845 (match_operand:SI 1 "" ""))
7846 (use (match_operand 2 "" ""))
7847 (clobber (reg:SI LR_REGNUM))]
7849 && GET_CODE (operands[0]) == SYMBOL_REF
7850 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7852 [(set_attr "length" "4")
7853 (set_attr "type" "call")]
7856 (define_insn "*call_value_insn"
7857 [(set (match_operand 0 "" "")
7858 (call (mem:SI (match_operand 1 "" ""))
7859 (match_operand 2 "" "")))
7860 (use (match_operand 3 "" ""))
7861 (clobber (reg:SI LR_REGNUM))]
7863 && GET_CODE (operands[1]) == SYMBOL_REF
7864 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7866 [(set_attr "length" "4")
7867 (set_attr "type" "call")]
7870 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7871 (define_expand "sibcall"
7872 [(parallel [(call (match_operand 0 "memory_operand" "")
7873 (match_operand 1 "general_operand" ""))
7875 (use (match_operand 2 "" ""))])]
7879 if (operands[2] == NULL_RTX)
7880 operands[2] = const0_rtx;
7884 (define_expand "sibcall_value"
7885 [(parallel [(set (match_operand 0 "" "")
7886 (call (match_operand 1 "memory_operand" "")
7887 (match_operand 2 "general_operand" "")))
7889 (use (match_operand 3 "" ""))])]
7893 if (operands[3] == NULL_RTX)
7894 operands[3] = const0_rtx;
7898 (define_insn "*sibcall_insn"
7899 [(call (mem:SI (match_operand:SI 0 "" "X"))
7900 (match_operand 1 "" ""))
7902 (use (match_operand 2 "" ""))]
7903 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7905 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7907 [(set_attr "type" "call")]
7910 (define_insn "*sibcall_value_insn"
7911 [(set (match_operand 0 "" "")
7912 (call (mem:SI (match_operand:SI 1 "" "X"))
7913 (match_operand 2 "" "")))
7915 (use (match_operand 3 "" ""))]
7916 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7918 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7920 [(set_attr "type" "call")]
7923 ;; Often the return insn will be the same as loading from memory, so set attr
7924 (define_insn "return"
7926 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7929 if (arm_ccfsm_state == 2)
7931 arm_ccfsm_state += 2;
7934 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7936 [(set_attr "type" "load1")
7937 (set_attr "length" "12")
7938 (set_attr "predicable" "yes")]
7941 (define_insn "*cond_return"
7943 (if_then_else (match_operator 0 "arm_comparison_operator"
7944 [(match_operand 1 "cc_register" "") (const_int 0)])
7947 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7950 if (arm_ccfsm_state == 2)
7952 arm_ccfsm_state += 2;
7955 return output_return_instruction (operands[0], TRUE, FALSE);
7957 [(set_attr "conds" "use")
7958 (set_attr "length" "12")
7959 (set_attr "type" "load1")]
7962 (define_insn "*cond_return_inverted"
7964 (if_then_else (match_operator 0 "arm_comparison_operator"
7965 [(match_operand 1 "cc_register" "") (const_int 0)])
7968 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7971 if (arm_ccfsm_state == 2)
7973 arm_ccfsm_state += 2;
7976 return output_return_instruction (operands[0], TRUE, TRUE);
7978 [(set_attr "conds" "use")
7979 (set_attr "length" "12")
7980 (set_attr "type" "load1")]
7983 ;; Generate a sequence of instructions to determine if the processor is
7984 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7987 (define_expand "return_addr_mask"
7989 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7991 (set (match_operand:SI 0 "s_register_operand" "")
7992 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7994 (const_int 67108860)))] ; 0x03fffffc
7997 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8000 (define_insn "*check_arch2"
8001 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8002 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8005 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8006 [(set_attr "length" "8")
8007 (set_attr "conds" "set")]
8010 ;; Call subroutine returning any type.
8012 (define_expand "untyped_call"
8013 [(parallel [(call (match_operand 0 "" "")
8015 (match_operand 1 "" "")
8016 (match_operand 2 "" "")])]
8021 rtx par = gen_rtx_PARALLEL (VOIDmode,
8022 rtvec_alloc (XVECLEN (operands[2], 0)));
8023 rtx addr = gen_reg_rtx (Pmode);
8027 emit_move_insn (addr, XEXP (operands[1], 0));
8028 mem = change_address (operands[1], BLKmode, addr);
8030 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8032 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8034 /* Default code only uses r0 as a return value, but we could
8035 be using anything up to 4 registers. */
8036 if (REGNO (src) == R0_REGNUM)
8037 src = gen_rtx_REG (TImode, R0_REGNUM);
8039 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8041 size += GET_MODE_SIZE (GET_MODE (src));
8044 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8049 for (i = 0; i < XVECLEN (par, 0); i++)
8051 HOST_WIDE_INT offset = 0;
8052 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8055 emit_move_insn (addr, plus_constant (addr, size));
8057 mem = change_address (mem, GET_MODE (reg), NULL);
8058 if (REGNO (reg) == R0_REGNUM)
8060 /* On thumb we have to use a write-back instruction. */
8061 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8062 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8063 size = TARGET_ARM ? 16 : 0;
8067 emit_move_insn (mem, reg);
8068 size = GET_MODE_SIZE (GET_MODE (reg));
8072 /* The optimizer does not know that the call sets the function value
8073 registers we stored in the result block. We avoid problems by
8074 claiming that all hard registers are used and clobbered at this
8076 emit_insn (gen_blockage ());
8082 (define_expand "untyped_return"
8083 [(match_operand:BLK 0 "memory_operand" "")
8084 (match_operand 1 "" "")]
8089 rtx addr = gen_reg_rtx (Pmode);
8093 emit_move_insn (addr, XEXP (operands[0], 0));
8094 mem = change_address (operands[0], BLKmode, addr);
8096 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8098 HOST_WIDE_INT offset = 0;
8099 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8102 emit_move_insn (addr, plus_constant (addr, size));
8104 mem = change_address (mem, GET_MODE (reg), NULL);
8105 if (REGNO (reg) == R0_REGNUM)
8107 /* On thumb we have to use a write-back instruction. */
8108 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8109 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8110 size = TARGET_ARM ? 16 : 0;
8114 emit_move_insn (reg, mem);
8115 size = GET_MODE_SIZE (GET_MODE (reg));
8119 /* Emit USE insns before the return. */
8120 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8121 emit_insn (gen_rtx_USE (VOIDmode,
8122 SET_DEST (XVECEXP (operands[1], 0, i))));
8124 /* Construct the return. */
8125 expand_naked_return ();
8131 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8132 ;; all of memory. This blocks insns from being moved across this point.
8134 (define_insn "blockage"
8135 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8138 [(set_attr "length" "0")
8139 (set_attr "type" "block")]
8142 (define_expand "casesi"
8143 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8144 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8145 (match_operand:SI 2 "const_int_operand" "") ; total range
8146 (match_operand:SI 3 "" "") ; table label
8147 (match_operand:SI 4 "" "")] ; Out of range label
8152 if (operands[1] != const0_rtx)
8154 reg = gen_reg_rtx (SImode);
8156 emit_insn (gen_addsi3 (reg, operands[0],
8157 GEN_INT (-INTVAL (operands[1]))));
8161 if (!const_ok_for_arm (INTVAL (operands[2])))
8162 operands[2] = force_reg (SImode, operands[2]);
8164 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8170 ;; The USE in this pattern is needed to tell flow analysis that this is
8171 ;; a CASESI insn. It has no other purpose.
8172 (define_insn "casesi_internal"
8173 [(parallel [(set (pc)
8175 (leu (match_operand:SI 0 "s_register_operand" "r")
8176 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8177 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8178 (label_ref (match_operand 2 "" ""))))
8179 (label_ref (match_operand 3 "" ""))))
8180 (clobber (reg:CC CC_REGNUM))
8181 (use (label_ref (match_dup 2)))])]
8185 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8186 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8188 [(set_attr "conds" "clob")
8189 (set_attr "length" "12")]
8192 (define_expand "indirect_jump"
8194 (match_operand:SI 0 "s_register_operand" ""))]
8199 ;; NB Never uses BX.
8200 (define_insn "*arm_indirect_jump"
8202 (match_operand:SI 0 "s_register_operand" "r"))]
8204 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8205 [(set_attr "predicable" "yes")]
8208 (define_insn "*load_indirect_jump"
8210 (match_operand:SI 0 "memory_operand" "m"))]
8212 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8213 [(set_attr "type" "load1")
8214 (set_attr "pool_range" "4096")
8215 (set_attr "neg_pool_range" "4084")
8216 (set_attr "predicable" "yes")]
8219 ;; NB Never uses BX.
8220 (define_insn "*thumb_indirect_jump"
8222 (match_operand:SI 0 "register_operand" "l*r"))]
8225 [(set_attr "conds" "clob")
8226 (set_attr "length" "2")]
8237 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8238 return \"mov\\tr8, r8\";
8240 [(set (attr "length")
8241 (if_then_else (eq_attr "is_thumb" "yes")
8247 ;; Patterns to allow combination of arithmetic, cond code and shifts
8249 (define_insn "*arith_shiftsi"
8250 [(set (match_operand:SI 0 "s_register_operand" "=r")
8251 (match_operator:SI 1 "shiftable_operator"
8252 [(match_operator:SI 3 "shift_operator"
8253 [(match_operand:SI 4 "s_register_operand" "r")
8254 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8255 (match_operand:SI 2 "s_register_operand" "r")]))]
8257 "%i1%?\\t%0, %2, %4%S3"
8258 [(set_attr "predicable" "yes")
8259 (set_attr "shift" "4")
8260 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8261 (const_string "alu_shift")
8262 (const_string "alu_shift_reg")))]
8266 [(set (match_operand:SI 0 "s_register_operand" "")
8267 (match_operator:SI 1 "shiftable_operator"
8268 [(match_operator:SI 2 "shiftable_operator"
8269 [(match_operator:SI 3 "shift_operator"
8270 [(match_operand:SI 4 "s_register_operand" "")
8271 (match_operand:SI 5 "reg_or_int_operand" "")])
8272 (match_operand:SI 6 "s_register_operand" "")])
8273 (match_operand:SI 7 "arm_rhs_operand" "")]))
8274 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8277 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8280 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8283 (define_insn "*arith_shiftsi_compare0"
8284 [(set (reg:CC_NOOV CC_REGNUM)
8285 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8286 [(match_operator:SI 3 "shift_operator"
8287 [(match_operand:SI 4 "s_register_operand" "r")
8288 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8289 (match_operand:SI 2 "s_register_operand" "r")])
8291 (set (match_operand:SI 0 "s_register_operand" "=r")
8292 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8295 "%i1%?s\\t%0, %2, %4%S3"
8296 [(set_attr "conds" "set")
8297 (set_attr "shift" "4")
8298 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8299 (const_string "alu_shift")
8300 (const_string "alu_shift_reg")))]
8303 (define_insn "*arith_shiftsi_compare0_scratch"
8304 [(set (reg:CC_NOOV CC_REGNUM)
8305 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8306 [(match_operator:SI 3 "shift_operator"
8307 [(match_operand:SI 4 "s_register_operand" "r")
8308 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8309 (match_operand:SI 2 "s_register_operand" "r")])
8311 (clobber (match_scratch:SI 0 "=r"))]
8313 "%i1%?s\\t%0, %2, %4%S3"
8314 [(set_attr "conds" "set")
8315 (set_attr "shift" "4")
8316 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8317 (const_string "alu_shift")
8318 (const_string "alu_shift_reg")))]
8321 (define_insn "*sub_shiftsi"
8322 [(set (match_operand:SI 0 "s_register_operand" "=r")
8323 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8324 (match_operator:SI 2 "shift_operator"
8325 [(match_operand:SI 3 "s_register_operand" "r")
8326 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8328 "sub%?\\t%0, %1, %3%S2"
8329 [(set_attr "predicable" "yes")
8330 (set_attr "shift" "3")
8331 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8332 (const_string "alu_shift")
8333 (const_string "alu_shift_reg")))]
8336 (define_insn "*sub_shiftsi_compare0"
8337 [(set (reg:CC_NOOV CC_REGNUM)
8339 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8340 (match_operator:SI 2 "shift_operator"
8341 [(match_operand:SI 3 "s_register_operand" "r")
8342 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8344 (set (match_operand:SI 0 "s_register_operand" "=r")
8345 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8348 "sub%?s\\t%0, %1, %3%S2"
8349 [(set_attr "conds" "set")
8350 (set_attr "shift" "3")
8351 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8352 (const_string "alu_shift")
8353 (const_string "alu_shift_reg")))]
8356 (define_insn "*sub_shiftsi_compare0_scratch"
8357 [(set (reg:CC_NOOV CC_REGNUM)
8359 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8360 (match_operator:SI 2 "shift_operator"
8361 [(match_operand:SI 3 "s_register_operand" "r")
8362 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8364 (clobber (match_scratch:SI 0 "=r"))]
8366 "sub%?s\\t%0, %1, %3%S2"
8367 [(set_attr "conds" "set")
8368 (set_attr "shift" "3")
8369 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8370 (const_string "alu_shift")
8371 (const_string "alu_shift_reg")))]
8376 (define_insn "*and_scc"
8377 [(set (match_operand:SI 0 "s_register_operand" "=r")
8378 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8379 [(match_operand 3 "cc_register" "") (const_int 0)])
8380 (match_operand:SI 2 "s_register_operand" "r")))]
8382 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8383 [(set_attr "conds" "use")
8384 (set_attr "length" "8")]
8387 (define_insn "*ior_scc"
8388 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8389 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8390 [(match_operand 3 "cc_register" "") (const_int 0)])
8391 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8395 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8396 [(set_attr "conds" "use")
8397 (set_attr "length" "4,8")]
8400 (define_insn "*compare_scc"
8401 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8402 (match_operator:SI 1 "arm_comparison_operator"
8403 [(match_operand:SI 2 "s_register_operand" "r,r")
8404 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8405 (clobber (reg:CC CC_REGNUM))]
8408 if (operands[3] == const0_rtx)
8410 if (GET_CODE (operands[1]) == LT)
8411 return \"mov\\t%0, %2, lsr #31\";
8413 if (GET_CODE (operands[1]) == GE)
8414 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8416 if (GET_CODE (operands[1]) == EQ)
8417 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8420 if (GET_CODE (operands[1]) == NE)
8422 if (which_alternative == 1)
8423 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8424 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8426 if (which_alternative == 1)
8427 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8429 output_asm_insn (\"cmp\\t%2, %3\", operands);
8430 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8432 [(set_attr "conds" "clob")
8433 (set_attr "length" "12")]
8436 (define_insn "*cond_move"
8437 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8438 (if_then_else:SI (match_operator 3 "equality_operator"
8439 [(match_operator 4 "arm_comparison_operator"
8440 [(match_operand 5 "cc_register" "") (const_int 0)])
8442 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8443 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8446 if (GET_CODE (operands[3]) == NE)
8448 if (which_alternative != 1)
8449 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8450 if (which_alternative != 0)
8451 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8454 if (which_alternative != 0)
8455 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8456 if (which_alternative != 1)
8457 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8460 [(set_attr "conds" "use")
8461 (set_attr "length" "4,4,8")]
8464 (define_insn "*cond_arith"
8465 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8466 (match_operator:SI 5 "shiftable_operator"
8467 [(match_operator:SI 4 "arm_comparison_operator"
8468 [(match_operand:SI 2 "s_register_operand" "r,r")
8469 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8470 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8471 (clobber (reg:CC CC_REGNUM))]
8474 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8475 return \"%i5\\t%0, %1, %2, lsr #31\";
8477 output_asm_insn (\"cmp\\t%2, %3\", operands);
8478 if (GET_CODE (operands[5]) == AND)
8479 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8480 else if (GET_CODE (operands[5]) == MINUS)
8481 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8482 else if (which_alternative != 0)
8483 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8484 return \"%i5%d4\\t%0, %1, #1\";
8486 [(set_attr "conds" "clob")
8487 (set_attr "length" "12")]
8490 (define_insn "*cond_sub"
8491 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8492 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8493 (match_operator:SI 4 "arm_comparison_operator"
8494 [(match_operand:SI 2 "s_register_operand" "r,r")
8495 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8496 (clobber (reg:CC CC_REGNUM))]
8499 output_asm_insn (\"cmp\\t%2, %3\", operands);
8500 if (which_alternative != 0)
8501 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8502 return \"sub%d4\\t%0, %1, #1\";
8504 [(set_attr "conds" "clob")
8505 (set_attr "length" "8,12")]
8508 (define_insn "*cmp_ite0"
8509 [(set (match_operand 6 "dominant_cc_register" "")
8512 (match_operator 4 "arm_comparison_operator"
8513 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8514 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8515 (match_operator:SI 5 "arm_comparison_operator"
8516 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8517 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8523 static const char * const opcodes[4][2] =
8525 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8526 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8527 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8528 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8529 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8530 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8531 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8532 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8535 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8537 return opcodes[which_alternative][swap];
8539 [(set_attr "conds" "set")
8540 (set_attr "length" "8")]
8543 (define_insn "*cmp_ite1"
8544 [(set (match_operand 6 "dominant_cc_register" "")
8547 (match_operator 4 "arm_comparison_operator"
8548 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8549 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8550 (match_operator:SI 5 "arm_comparison_operator"
8551 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8552 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8558 static const char * const opcodes[4][2] =
8560 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8561 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8562 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8563 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8564 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8565 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8566 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8567 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8570 comparison_dominates_p (GET_CODE (operands[5]),
8571 reverse_condition (GET_CODE (operands[4])));
8573 return opcodes[which_alternative][swap];
8575 [(set_attr "conds" "set")
8576 (set_attr "length" "8")]
8579 (define_insn "*cmp_and"
8580 [(set (match_operand 6 "dominant_cc_register" "")
8583 (match_operator 4 "arm_comparison_operator"
8584 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8585 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8586 (match_operator:SI 5 "arm_comparison_operator"
8587 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8588 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8593 static const char *const opcodes[4][2] =
8595 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8596 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8597 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8598 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8599 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8600 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8601 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8602 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8605 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8607 return opcodes[which_alternative][swap];
8609 [(set_attr "conds" "set")
8610 (set_attr "predicable" "no")
8611 (set_attr "length" "8")]
8614 (define_insn "*cmp_ior"
8615 [(set (match_operand 6 "dominant_cc_register" "")
8618 (match_operator 4 "arm_comparison_operator"
8619 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8620 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8621 (match_operator:SI 5 "arm_comparison_operator"
8622 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8623 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8628 static const char *const opcodes[4][2] =
8630 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8631 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8632 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8633 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8634 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8635 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8636 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8637 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8640 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8642 return opcodes[which_alternative][swap];
8645 [(set_attr "conds" "set")
8646 (set_attr "length" "8")]
8649 (define_insn_and_split "*ior_scc_scc"
8650 [(set (match_operand:SI 0 "s_register_operand" "=r")
8651 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8652 [(match_operand:SI 1 "s_register_operand" "r")
8653 (match_operand:SI 2 "arm_add_operand" "rIL")])
8654 (match_operator:SI 6 "arm_comparison_operator"
8655 [(match_operand:SI 4 "s_register_operand" "r")
8656 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8657 (clobber (reg:CC CC_REGNUM))]
8659 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8662 "TARGET_ARM && reload_completed"
8666 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8667 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8669 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8671 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8674 [(set_attr "conds" "clob")
8675 (set_attr "length" "16")])
8677 ; If the above pattern is followed by a CMP insn, then the compare is
8678 ; redundant, since we can rework the conditional instruction that follows.
8679 (define_insn_and_split "*ior_scc_scc_cmp"
8680 [(set (match_operand 0 "dominant_cc_register" "")
8681 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8682 [(match_operand:SI 1 "s_register_operand" "r")
8683 (match_operand:SI 2 "arm_add_operand" "rIL")])
8684 (match_operator:SI 6 "arm_comparison_operator"
8685 [(match_operand:SI 4 "s_register_operand" "r")
8686 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8688 (set (match_operand:SI 7 "s_register_operand" "=r")
8689 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8690 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8693 "TARGET_ARM && reload_completed"
8697 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8698 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8700 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8702 [(set_attr "conds" "set")
8703 (set_attr "length" "16")])
8705 (define_insn_and_split "*and_scc_scc"
8706 [(set (match_operand:SI 0 "s_register_operand" "=r")
8707 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8708 [(match_operand:SI 1 "s_register_operand" "r")
8709 (match_operand:SI 2 "arm_add_operand" "rIL")])
8710 (match_operator:SI 6 "arm_comparison_operator"
8711 [(match_operand:SI 4 "s_register_operand" "r")
8712 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8713 (clobber (reg:CC CC_REGNUM))]
8715 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8718 "TARGET_ARM && reload_completed
8719 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8724 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8725 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8727 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8729 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8732 [(set_attr "conds" "clob")
8733 (set_attr "length" "16")])
8735 ; If the above pattern is followed by a CMP insn, then the compare is
8736 ; redundant, since we can rework the conditional instruction that follows.
8737 (define_insn_and_split "*and_scc_scc_cmp"
8738 [(set (match_operand 0 "dominant_cc_register" "")
8739 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8740 [(match_operand:SI 1 "s_register_operand" "r")
8741 (match_operand:SI 2 "arm_add_operand" "rIL")])
8742 (match_operator:SI 6 "arm_comparison_operator"
8743 [(match_operand:SI 4 "s_register_operand" "r")
8744 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8746 (set (match_operand:SI 7 "s_register_operand" "=r")
8747 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8748 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8751 "TARGET_ARM && reload_completed"
8755 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8756 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8758 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8760 [(set_attr "conds" "set")
8761 (set_attr "length" "16")])
8763 ;; If there is no dominance in the comparison, then we can still save an
8764 ;; instruction in the AND case, since we can know that the second compare
8765 ;; need only zero the value if false (if true, then the value is already
8767 (define_insn_and_split "*and_scc_scc_nodom"
8768 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8769 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8770 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8771 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8772 (match_operator:SI 6 "arm_comparison_operator"
8773 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8774 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8775 (clobber (reg:CC CC_REGNUM))]
8777 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8780 "TARGET_ARM && reload_completed"
8781 [(parallel [(set (match_dup 0)
8782 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8783 (clobber (reg:CC CC_REGNUM))])
8784 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8786 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8789 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8790 operands[4], operands[5]),
8792 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8794 [(set_attr "conds" "clob")
8795 (set_attr "length" "20")])
8798 [(set (reg:CC_NOOV CC_REGNUM)
8799 (compare:CC_NOOV (ior:SI
8800 (and:SI (match_operand:SI 0 "s_register_operand" "")
8802 (match_operator:SI 1 "comparison_operator"
8803 [(match_operand:SI 2 "s_register_operand" "")
8804 (match_operand:SI 3 "arm_add_operand" "")]))
8806 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8809 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8811 (set (reg:CC_NOOV CC_REGNUM)
8812 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8817 [(set (reg:CC_NOOV CC_REGNUM)
8818 (compare:CC_NOOV (ior:SI
8819 (match_operator:SI 1 "comparison_operator"
8820 [(match_operand:SI 2 "s_register_operand" "")
8821 (match_operand:SI 3 "arm_add_operand" "")])
8822 (and:SI (match_operand:SI 0 "s_register_operand" "")
8825 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8828 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8830 (set (reg:CC_NOOV CC_REGNUM)
8831 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8835 (define_insn "*negscc"
8836 [(set (match_operand:SI 0 "s_register_operand" "=r")
8837 (neg:SI (match_operator 3 "arm_comparison_operator"
8838 [(match_operand:SI 1 "s_register_operand" "r")
8839 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8840 (clobber (reg:CC CC_REGNUM))]
8843 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8844 return \"mov\\t%0, %1, asr #31\";
8846 if (GET_CODE (operands[3]) == NE)
8847 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8849 if (GET_CODE (operands[3]) == GT)
8850 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8852 output_asm_insn (\"cmp\\t%1, %2\", operands);
8853 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8854 return \"mvn%d3\\t%0, #0\";
8856 [(set_attr "conds" "clob")
8857 (set_attr "length" "12")]
8860 (define_insn "movcond"
8861 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8863 (match_operator 5 "arm_comparison_operator"
8864 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8865 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8866 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8867 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8868 (clobber (reg:CC CC_REGNUM))]
8871 if (GET_CODE (operands[5]) == LT
8872 && (operands[4] == const0_rtx))
8874 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8876 if (operands[2] == const0_rtx)
8877 return \"and\\t%0, %1, %3, asr #31\";
8878 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8880 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8882 if (operands[1] == const0_rtx)
8883 return \"bic\\t%0, %2, %3, asr #31\";
8884 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8886 /* The only case that falls through to here is when both ops 1 & 2
8890 if (GET_CODE (operands[5]) == GE
8891 && (operands[4] == const0_rtx))
8893 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8895 if (operands[2] == const0_rtx)
8896 return \"bic\\t%0, %1, %3, asr #31\";
8897 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8899 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8901 if (operands[1] == const0_rtx)
8902 return \"and\\t%0, %2, %3, asr #31\";
8903 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8905 /* The only case that falls through to here is when both ops 1 & 2
8908 if (GET_CODE (operands[4]) == CONST_INT
8909 && !const_ok_for_arm (INTVAL (operands[4])))
8910 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8912 output_asm_insn (\"cmp\\t%3, %4\", operands);
8913 if (which_alternative != 0)
8914 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8915 if (which_alternative != 1)
8916 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8919 [(set_attr "conds" "clob")
8920 (set_attr "length" "8,8,12")]
8923 (define_insn "*ifcompare_plus_move"
8924 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8925 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8926 [(match_operand:SI 4 "s_register_operand" "r,r")
8927 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8929 (match_operand:SI 2 "s_register_operand" "r,r")
8930 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8931 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8932 (clobber (reg:CC CC_REGNUM))]
8935 [(set_attr "conds" "clob")
8936 (set_attr "length" "8,12")]
8939 (define_insn "*if_plus_move"
8940 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8942 (match_operator 4 "arm_comparison_operator"
8943 [(match_operand 5 "cc_register" "") (const_int 0)])
8945 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8946 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8947 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8951 sub%d4\\t%0, %2, #%n3
8952 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8953 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8954 [(set_attr "conds" "use")
8955 (set_attr "length" "4,4,8,8")
8956 (set_attr "type" "*,*,*,*")]
8959 (define_insn "*ifcompare_move_plus"
8960 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8961 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8962 [(match_operand:SI 4 "s_register_operand" "r,r")
8963 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8964 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8966 (match_operand:SI 2 "s_register_operand" "r,r")
8967 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8968 (clobber (reg:CC CC_REGNUM))]
8971 [(set_attr "conds" "clob")
8972 (set_attr "length" "8,12")]
8975 (define_insn "*if_move_plus"
8976 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8978 (match_operator 4 "arm_comparison_operator"
8979 [(match_operand 5 "cc_register" "") (const_int 0)])
8980 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8982 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8983 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8987 sub%D4\\t%0, %2, #%n3
8988 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8989 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8990 [(set_attr "conds" "use")
8991 (set_attr "length" "4,4,8,8")
8992 (set_attr "type" "*,*,*,*")]
8995 (define_insn "*ifcompare_arith_arith"
8996 [(set (match_operand:SI 0 "s_register_operand" "=r")
8997 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8998 [(match_operand:SI 5 "s_register_operand" "r")
8999 (match_operand:SI 6 "arm_add_operand" "rIL")])
9000 (match_operator:SI 8 "shiftable_operator"
9001 [(match_operand:SI 1 "s_register_operand" "r")
9002 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9003 (match_operator:SI 7 "shiftable_operator"
9004 [(match_operand:SI 3 "s_register_operand" "r")
9005 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9006 (clobber (reg:CC CC_REGNUM))]
9009 [(set_attr "conds" "clob")
9010 (set_attr "length" "12")]
9013 (define_insn "*if_arith_arith"
9014 [(set (match_operand:SI 0 "s_register_operand" "=r")
9015 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9016 [(match_operand 8 "cc_register" "") (const_int 0)])
9017 (match_operator:SI 6 "shiftable_operator"
9018 [(match_operand:SI 1 "s_register_operand" "r")
9019 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9020 (match_operator:SI 7 "shiftable_operator"
9021 [(match_operand:SI 3 "s_register_operand" "r")
9022 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9024 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9025 [(set_attr "conds" "use")
9026 (set_attr "length" "8")]
9029 (define_insn "*ifcompare_arith_move"
9030 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9031 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9032 [(match_operand:SI 2 "s_register_operand" "r,r")
9033 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9034 (match_operator:SI 7 "shiftable_operator"
9035 [(match_operand:SI 4 "s_register_operand" "r,r")
9036 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9037 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9038 (clobber (reg:CC CC_REGNUM))]
9041 /* If we have an operation where (op x 0) is the identity operation and
9042 the conditional operator is LT or GE and we are comparing against zero and
9043 everything is in registers then we can do this in two instructions. */
9044 if (operands[3] == const0_rtx
9045 && GET_CODE (operands[7]) != AND
9046 && GET_CODE (operands[5]) == REG
9047 && GET_CODE (operands[1]) == REG
9048 && REGNO (operands[1]) == REGNO (operands[4])
9049 && REGNO (operands[4]) != REGNO (operands[0]))
9051 if (GET_CODE (operands[6]) == LT)
9052 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9053 else if (GET_CODE (operands[6]) == GE)
9054 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9056 if (GET_CODE (operands[3]) == CONST_INT
9057 && !const_ok_for_arm (INTVAL (operands[3])))
9058 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9060 output_asm_insn (\"cmp\\t%2, %3\", operands);
9061 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9062 if (which_alternative != 0)
9063 return \"mov%D6\\t%0, %1\";
9066 [(set_attr "conds" "clob")
9067 (set_attr "length" "8,12")]
9070 (define_insn "*if_arith_move"
9071 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9072 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9073 [(match_operand 6 "cc_register" "") (const_int 0)])
9074 (match_operator:SI 5 "shiftable_operator"
9075 [(match_operand:SI 2 "s_register_operand" "r,r")
9076 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9077 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9081 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9082 [(set_attr "conds" "use")
9083 (set_attr "length" "4,8")
9084 (set_attr "type" "*,*")]
9087 (define_insn "*ifcompare_move_arith"
9088 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9089 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9090 [(match_operand:SI 4 "s_register_operand" "r,r")
9091 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9092 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9093 (match_operator:SI 7 "shiftable_operator"
9094 [(match_operand:SI 2 "s_register_operand" "r,r")
9095 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9096 (clobber (reg:CC CC_REGNUM))]
9099 /* If we have an operation where (op x 0) is the identity operation and
9100 the conditional operator is LT or GE and we are comparing against zero and
9101 everything is in registers then we can do this in two instructions */
9102 if (operands[5] == const0_rtx
9103 && GET_CODE (operands[7]) != AND
9104 && GET_CODE (operands[3]) == REG
9105 && GET_CODE (operands[1]) == REG
9106 && REGNO (operands[1]) == REGNO (operands[2])
9107 && REGNO (operands[2]) != REGNO (operands[0]))
9109 if (GET_CODE (operands[6]) == GE)
9110 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9111 else if (GET_CODE (operands[6]) == LT)
9112 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9115 if (GET_CODE (operands[5]) == CONST_INT
9116 && !const_ok_for_arm (INTVAL (operands[5])))
9117 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9119 output_asm_insn (\"cmp\\t%4, %5\", operands);
9121 if (which_alternative != 0)
9122 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9123 return \"%I7%D6\\t%0, %2, %3\";
9125 [(set_attr "conds" "clob")
9126 (set_attr "length" "8,12")]
9129 (define_insn "*if_move_arith"
9130 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9132 (match_operator 4 "arm_comparison_operator"
9133 [(match_operand 6 "cc_register" "") (const_int 0)])
9134 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9135 (match_operator:SI 5 "shiftable_operator"
9136 [(match_operand:SI 2 "s_register_operand" "r,r")
9137 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9141 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9142 [(set_attr "conds" "use")
9143 (set_attr "length" "4,8")
9144 (set_attr "type" "*,*")]
9147 (define_insn "*ifcompare_move_not"
9148 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9150 (match_operator 5 "arm_comparison_operator"
9151 [(match_operand:SI 3 "s_register_operand" "r,r")
9152 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9153 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9155 (match_operand:SI 2 "s_register_operand" "r,r"))))
9156 (clobber (reg:CC CC_REGNUM))]
9159 [(set_attr "conds" "clob")
9160 (set_attr "length" "8,12")]
9163 (define_insn "*if_move_not"
9164 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9166 (match_operator 4 "arm_comparison_operator"
9167 [(match_operand 3 "cc_register" "") (const_int 0)])
9168 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9169 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9173 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9174 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9175 [(set_attr "conds" "use")
9176 (set_attr "length" "4,8,8")]
9179 (define_insn "*ifcompare_not_move"
9180 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9182 (match_operator 5 "arm_comparison_operator"
9183 [(match_operand:SI 3 "s_register_operand" "r,r")
9184 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9186 (match_operand:SI 2 "s_register_operand" "r,r"))
9187 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9188 (clobber (reg:CC CC_REGNUM))]
9191 [(set_attr "conds" "clob")
9192 (set_attr "length" "8,12")]
9195 (define_insn "*if_not_move"
9196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9198 (match_operator 4 "arm_comparison_operator"
9199 [(match_operand 3 "cc_register" "") (const_int 0)])
9200 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9201 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9205 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9206 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9207 [(set_attr "conds" "use")
9208 (set_attr "length" "4,8,8")]
9211 (define_insn "*ifcompare_shift_move"
9212 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9214 (match_operator 6 "arm_comparison_operator"
9215 [(match_operand:SI 4 "s_register_operand" "r,r")
9216 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9217 (match_operator:SI 7 "shift_operator"
9218 [(match_operand:SI 2 "s_register_operand" "r,r")
9219 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9220 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9221 (clobber (reg:CC CC_REGNUM))]
9224 [(set_attr "conds" "clob")
9225 (set_attr "length" "8,12")]
9228 (define_insn "*if_shift_move"
9229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9231 (match_operator 5 "arm_comparison_operator"
9232 [(match_operand 6 "cc_register" "") (const_int 0)])
9233 (match_operator:SI 4 "shift_operator"
9234 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9235 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9236 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9240 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9241 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9242 [(set_attr "conds" "use")
9243 (set_attr "shift" "2")
9244 (set_attr "length" "4,8,8")
9245 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9246 (const_string "alu_shift")
9247 (const_string "alu_shift_reg")))]
9250 (define_insn "*ifcompare_move_shift"
9251 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9253 (match_operator 6 "arm_comparison_operator"
9254 [(match_operand:SI 4 "s_register_operand" "r,r")
9255 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9256 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9257 (match_operator:SI 7 "shift_operator"
9258 [(match_operand:SI 2 "s_register_operand" "r,r")
9259 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9260 (clobber (reg:CC CC_REGNUM))]
9263 [(set_attr "conds" "clob")
9264 (set_attr "length" "8,12")]
9267 (define_insn "*if_move_shift"
9268 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9270 (match_operator 5 "arm_comparison_operator"
9271 [(match_operand 6 "cc_register" "") (const_int 0)])
9272 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9273 (match_operator:SI 4 "shift_operator"
9274 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9275 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9279 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9280 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9281 [(set_attr "conds" "use")
9282 (set_attr "shift" "2")
9283 (set_attr "length" "4,8,8")
9284 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9285 (const_string "alu_shift")
9286 (const_string "alu_shift_reg")))]
9289 (define_insn "*ifcompare_shift_shift"
9290 [(set (match_operand:SI 0 "s_register_operand" "=r")
9292 (match_operator 7 "arm_comparison_operator"
9293 [(match_operand:SI 5 "s_register_operand" "r")
9294 (match_operand:SI 6 "arm_add_operand" "rIL")])
9295 (match_operator:SI 8 "shift_operator"
9296 [(match_operand:SI 1 "s_register_operand" "r")
9297 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9298 (match_operator:SI 9 "shift_operator"
9299 [(match_operand:SI 3 "s_register_operand" "r")
9300 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9301 (clobber (reg:CC CC_REGNUM))]
9304 [(set_attr "conds" "clob")
9305 (set_attr "length" "12")]
9308 (define_insn "*if_shift_shift"
9309 [(set (match_operand:SI 0 "s_register_operand" "=r")
9311 (match_operator 5 "arm_comparison_operator"
9312 [(match_operand 8 "cc_register" "") (const_int 0)])
9313 (match_operator:SI 6 "shift_operator"
9314 [(match_operand:SI 1 "s_register_operand" "r")
9315 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9316 (match_operator:SI 7 "shift_operator"
9317 [(match_operand:SI 3 "s_register_operand" "r")
9318 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9320 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9321 [(set_attr "conds" "use")
9322 (set_attr "shift" "1")
9323 (set_attr "length" "8")
9324 (set (attr "type") (if_then_else
9325 (and (match_operand 2 "const_int_operand" "")
9326 (match_operand 4 "const_int_operand" ""))
9327 (const_string "alu_shift")
9328 (const_string "alu_shift_reg")))]
9331 (define_insn "*ifcompare_not_arith"
9332 [(set (match_operand:SI 0 "s_register_operand" "=r")
9334 (match_operator 6 "arm_comparison_operator"
9335 [(match_operand:SI 4 "s_register_operand" "r")
9336 (match_operand:SI 5 "arm_add_operand" "rIL")])
9337 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9338 (match_operator:SI 7 "shiftable_operator"
9339 [(match_operand:SI 2 "s_register_operand" "r")
9340 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9341 (clobber (reg:CC CC_REGNUM))]
9344 [(set_attr "conds" "clob")
9345 (set_attr "length" "12")]
9348 (define_insn "*if_not_arith"
9349 [(set (match_operand:SI 0 "s_register_operand" "=r")
9351 (match_operator 5 "arm_comparison_operator"
9352 [(match_operand 4 "cc_register" "") (const_int 0)])
9353 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9354 (match_operator:SI 6 "shiftable_operator"
9355 [(match_operand:SI 2 "s_register_operand" "r")
9356 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9358 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9359 [(set_attr "conds" "use")
9360 (set_attr "length" "8")]
9363 (define_insn "*ifcompare_arith_not"
9364 [(set (match_operand:SI 0 "s_register_operand" "=r")
9366 (match_operator 6 "arm_comparison_operator"
9367 [(match_operand:SI 4 "s_register_operand" "r")
9368 (match_operand:SI 5 "arm_add_operand" "rIL")])
9369 (match_operator:SI 7 "shiftable_operator"
9370 [(match_operand:SI 2 "s_register_operand" "r")
9371 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9372 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9373 (clobber (reg:CC CC_REGNUM))]
9376 [(set_attr "conds" "clob")
9377 (set_attr "length" "12")]
9380 (define_insn "*if_arith_not"
9381 [(set (match_operand:SI 0 "s_register_operand" "=r")
9383 (match_operator 5 "arm_comparison_operator"
9384 [(match_operand 4 "cc_register" "") (const_int 0)])
9385 (match_operator:SI 6 "shiftable_operator"
9386 [(match_operand:SI 2 "s_register_operand" "r")
9387 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9388 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9390 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9391 [(set_attr "conds" "use")
9392 (set_attr "length" "8")]
9395 (define_insn "*ifcompare_neg_move"
9396 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9398 (match_operator 5 "arm_comparison_operator"
9399 [(match_operand:SI 3 "s_register_operand" "r,r")
9400 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9401 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9402 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9403 (clobber (reg:CC CC_REGNUM))]
9406 [(set_attr "conds" "clob")
9407 (set_attr "length" "8,12")]
9410 (define_insn "*if_neg_move"
9411 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9413 (match_operator 4 "arm_comparison_operator"
9414 [(match_operand 3 "cc_register" "") (const_int 0)])
9415 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9416 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9420 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9421 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9422 [(set_attr "conds" "use")
9423 (set_attr "length" "4,8,8")]
9426 (define_insn "*ifcompare_move_neg"
9427 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9429 (match_operator 5 "arm_comparison_operator"
9430 [(match_operand:SI 3 "s_register_operand" "r,r")
9431 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9432 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9433 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9434 (clobber (reg:CC CC_REGNUM))]
9437 [(set_attr "conds" "clob")
9438 (set_attr "length" "8,12")]
9441 (define_insn "*if_move_neg"
9442 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9444 (match_operator 4 "arm_comparison_operator"
9445 [(match_operand 3 "cc_register" "") (const_int 0)])
9446 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9447 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9451 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9452 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9453 [(set_attr "conds" "use")
9454 (set_attr "length" "4,8,8")]
9457 (define_insn "*arith_adjacentmem"
9458 [(set (match_operand:SI 0 "s_register_operand" "=r")
9459 (match_operator:SI 1 "shiftable_operator"
9460 [(match_operand:SI 2 "memory_operand" "m")
9461 (match_operand:SI 3 "memory_operand" "m")]))
9462 (clobber (match_scratch:SI 4 "=r"))]
9463 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9469 HOST_WIDE_INT val1 = 0, val2 = 0;
9471 if (REGNO (operands[0]) > REGNO (operands[4]))
9473 ldm[1] = operands[4];
9474 ldm[2] = operands[0];
9478 ldm[1] = operands[0];
9479 ldm[2] = operands[4];
9482 base_reg = XEXP (operands[2], 0);
9484 if (!REG_P (base_reg))
9486 val1 = INTVAL (XEXP (base_reg, 1));
9487 base_reg = XEXP (base_reg, 0);
9490 if (!REG_P (XEXP (operands[3], 0)))
9491 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9493 arith[0] = operands[0];
9494 arith[3] = operands[1];
9508 if (val1 !=0 && val2 != 0)
9510 if (val1 == 4 || val2 == 4)
9511 /* Other val must be 8, since we know they are adjacent and neither
9513 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9518 ldm[0] = ops[0] = operands[4];
9520 ops[2] = GEN_INT (val1);
9521 output_add_immediate (ops);
9523 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9525 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9531 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9533 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9538 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9540 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9542 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9545 [(set_attr "length" "12")
9546 (set_attr "predicable" "yes")
9547 (set_attr "type" "load1")]
9550 ; This pattern is never tried by combine, so do it as a peephole
9553 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9554 (match_operand:SI 1 "arm_general_register_operand" ""))
9555 (set (reg:CC CC_REGNUM)
9556 (compare:CC (match_dup 1) (const_int 0)))]
9558 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9559 (set (match_dup 0) (match_dup 1))])]
9563 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9564 ; reversed, check that the memory references aren't volatile.
9567 [(set (match_operand:SI 0 "s_register_operand" "=r")
9568 (match_operand:SI 4 "memory_operand" "m"))
9569 (set (match_operand:SI 1 "s_register_operand" "=r")
9570 (match_operand:SI 5 "memory_operand" "m"))
9571 (set (match_operand:SI 2 "s_register_operand" "=r")
9572 (match_operand:SI 6 "memory_operand" "m"))
9573 (set (match_operand:SI 3 "s_register_operand" "=r")
9574 (match_operand:SI 7 "memory_operand" "m"))]
9575 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9577 return emit_ldm_seq (operands, 4);
9582 [(set (match_operand:SI 0 "s_register_operand" "=r")
9583 (match_operand:SI 3 "memory_operand" "m"))
9584 (set (match_operand:SI 1 "s_register_operand" "=r")
9585 (match_operand:SI 4 "memory_operand" "m"))
9586 (set (match_operand:SI 2 "s_register_operand" "=r")
9587 (match_operand:SI 5 "memory_operand" "m"))]
9588 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9590 return emit_ldm_seq (operands, 3);
9595 [(set (match_operand:SI 0 "s_register_operand" "=r")
9596 (match_operand:SI 2 "memory_operand" "m"))
9597 (set (match_operand:SI 1 "s_register_operand" "=r")
9598 (match_operand:SI 3 "memory_operand" "m"))]
9599 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9601 return emit_ldm_seq (operands, 2);
9606 [(set (match_operand:SI 4 "memory_operand" "=m")
9607 (match_operand:SI 0 "s_register_operand" "r"))
9608 (set (match_operand:SI 5 "memory_operand" "=m")
9609 (match_operand:SI 1 "s_register_operand" "r"))
9610 (set (match_operand:SI 6 "memory_operand" "=m")
9611 (match_operand:SI 2 "s_register_operand" "r"))
9612 (set (match_operand:SI 7 "memory_operand" "=m")
9613 (match_operand:SI 3 "s_register_operand" "r"))]
9614 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9616 return emit_stm_seq (operands, 4);
9621 [(set (match_operand:SI 3 "memory_operand" "=m")
9622 (match_operand:SI 0 "s_register_operand" "r"))
9623 (set (match_operand:SI 4 "memory_operand" "=m")
9624 (match_operand:SI 1 "s_register_operand" "r"))
9625 (set (match_operand:SI 5 "memory_operand" "=m")
9626 (match_operand:SI 2 "s_register_operand" "r"))]
9627 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9629 return emit_stm_seq (operands, 3);
9634 [(set (match_operand:SI 2 "memory_operand" "=m")
9635 (match_operand:SI 0 "s_register_operand" "r"))
9636 (set (match_operand:SI 3 "memory_operand" "=m")
9637 (match_operand:SI 1 "s_register_operand" "r"))]
9638 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9640 return emit_stm_seq (operands, 2);
9645 [(set (match_operand:SI 0 "s_register_operand" "")
9646 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9648 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9649 [(match_operand:SI 3 "s_register_operand" "")
9650 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9651 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9653 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9654 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9659 ;; This split can be used because CC_Z mode implies that the following
9660 ;; branch will be an equality, or an unsigned inequality, so the sign
9661 ;; extension is not needed.
9664 [(set (reg:CC_Z CC_REGNUM)
9666 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9668 (match_operand 1 "const_int_operand" "")))
9669 (clobber (match_scratch:SI 2 ""))]
9671 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9672 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9673 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9674 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9676 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9680 (define_expand "prologue"
9681 [(clobber (const_int 0))]
9684 arm_expand_prologue ();
9686 thumb_expand_prologue ();
9691 (define_expand "epilogue"
9692 [(clobber (const_int 0))]
9695 if (current_function_calls_eh_return)
9696 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9698 thumb_expand_epilogue ();
9699 else if (USE_RETURN_INSN (FALSE))
9701 emit_jump_insn (gen_return ());
9704 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9706 gen_rtx_RETURN (VOIDmode)),
9712 ;; Note - although unspec_volatile's USE all hard registers,
9713 ;; USEs are ignored after relaod has completed. Thus we need
9714 ;; to add an unspec of the link register to ensure that flow
9715 ;; does not think that it is unused by the sibcall branch that
9716 ;; will replace the standard function epilogue.
9717 (define_insn "sibcall_epilogue"
9718 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9719 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9722 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9723 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9724 return arm_output_epilogue (next_nonnote_insn (insn));
9726 ;; Length is absolute worst case
9727 [(set_attr "length" "44")
9728 (set_attr "type" "block")
9729 ;; We don't clobber the conditions, but the potential length of this
9730 ;; operation is sufficient to make conditionalizing the sequence
9731 ;; unlikely to be profitable.
9732 (set_attr "conds" "clob")]
9735 (define_insn "*epilogue_insns"
9736 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9740 return arm_output_epilogue (NULL);
9741 else /* TARGET_THUMB */
9742 return thumb_unexpanded_epilogue ();
9744 ; Length is absolute worst case
9745 [(set_attr "length" "44")
9746 (set_attr "type" "block")
9747 ;; We don't clobber the conditions, but the potential length of this
9748 ;; operation is sufficient to make conditionalizing the sequence
9749 ;; unlikely to be profitable.
9750 (set_attr "conds" "clob")]
9753 (define_expand "eh_epilogue"
9754 [(use (match_operand:SI 0 "register_operand" ""))
9755 (use (match_operand:SI 1 "register_operand" ""))
9756 (use (match_operand:SI 2 "register_operand" ""))]
9760 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9761 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9763 rtx ra = gen_rtx_REG (Pmode, 2);
9765 emit_move_insn (ra, operands[2]);
9768 /* This is a hack -- we may have crystalized the function type too
9770 cfun->machine->func_type = 0;
9774 ;; This split is only used during output to reduce the number of patterns
9775 ;; that need assembler instructions adding to them. We allowed the setting
9776 ;; of the conditions to be implicit during rtl generation so that
9777 ;; the conditional compare patterns would work. However this conflicts to
9778 ;; some extent with the conditional data operations, so we have to split them
9782 [(set (match_operand:SI 0 "s_register_operand" "")
9783 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9784 [(match_operand 2 "" "") (match_operand 3 "" "")])
9786 (match_operand 4 "" "")))
9787 (clobber (reg:CC CC_REGNUM))]
9788 "TARGET_ARM && reload_completed"
9789 [(set (match_dup 5) (match_dup 6))
9790 (cond_exec (match_dup 7)
9791 (set (match_dup 0) (match_dup 4)))]
9794 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9795 operands[2], operands[3]);
9796 enum rtx_code rc = GET_CODE (operands[1]);
9798 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9799 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9800 if (mode == CCFPmode || mode == CCFPEmode)
9801 rc = reverse_condition_maybe_unordered (rc);
9803 rc = reverse_condition (rc);
9805 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9810 [(set (match_operand:SI 0 "s_register_operand" "")
9811 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9812 [(match_operand 2 "" "") (match_operand 3 "" "")])
9813 (match_operand 4 "" "")
9815 (clobber (reg:CC CC_REGNUM))]
9816 "TARGET_ARM && reload_completed"
9817 [(set (match_dup 5) (match_dup 6))
9818 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9819 (set (match_dup 0) (match_dup 4)))]
9822 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9823 operands[2], operands[3]);
9825 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9826 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9831 [(set (match_operand:SI 0 "s_register_operand" "")
9832 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9833 [(match_operand 2 "" "") (match_operand 3 "" "")])
9834 (match_operand 4 "" "")
9835 (match_operand 5 "" "")))
9836 (clobber (reg:CC CC_REGNUM))]
9837 "TARGET_ARM && reload_completed"
9838 [(set (match_dup 6) (match_dup 7))
9839 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9840 (set (match_dup 0) (match_dup 4)))
9841 (cond_exec (match_dup 8)
9842 (set (match_dup 0) (match_dup 5)))]
9845 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9846 operands[2], operands[3]);
9847 enum rtx_code rc = GET_CODE (operands[1]);
9849 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9850 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9851 if (mode == CCFPmode || mode == CCFPEmode)
9852 rc = reverse_condition_maybe_unordered (rc);
9854 rc = reverse_condition (rc);
9856 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9861 [(set (match_operand:SI 0 "s_register_operand" "")
9862 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9863 [(match_operand:SI 2 "s_register_operand" "")
9864 (match_operand:SI 3 "arm_add_operand" "")])
9865 (match_operand:SI 4 "arm_rhs_operand" "")
9867 (match_operand:SI 5 "s_register_operand" ""))))
9868 (clobber (reg:CC CC_REGNUM))]
9869 "TARGET_ARM && reload_completed"
9870 [(set (match_dup 6) (match_dup 7))
9871 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9872 (set (match_dup 0) (match_dup 4)))
9873 (cond_exec (match_dup 8)
9874 (set (match_dup 0) (not:SI (match_dup 5))))]
9877 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9878 operands[2], operands[3]);
9879 enum rtx_code rc = GET_CODE (operands[1]);
9881 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9882 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9883 if (mode == CCFPmode || mode == CCFPEmode)
9884 rc = reverse_condition_maybe_unordered (rc);
9886 rc = reverse_condition (rc);
9888 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9892 (define_insn "*cond_move_not"
9893 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9894 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9895 [(match_operand 3 "cc_register" "") (const_int 0)])
9896 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9898 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9902 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9903 [(set_attr "conds" "use")
9904 (set_attr "length" "4,8")]
9907 ;; The next two patterns occur when an AND operation is followed by a
9908 ;; scc insn sequence
9910 (define_insn "*sign_extract_onebit"
9911 [(set (match_operand:SI 0 "s_register_operand" "=r")
9912 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9914 (match_operand:SI 2 "const_int_operand" "n")))
9915 (clobber (reg:CC CC_REGNUM))]
9918 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9919 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9920 return \"mvnne\\t%0, #0\";
9922 [(set_attr "conds" "clob")
9923 (set_attr "length" "8")]
9926 (define_insn "*not_signextract_onebit"
9927 [(set (match_operand:SI 0 "s_register_operand" "=r")
9929 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9931 (match_operand:SI 2 "const_int_operand" "n"))))
9932 (clobber (reg:CC CC_REGNUM))]
9935 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9936 output_asm_insn (\"tst\\t%1, %2\", operands);
9937 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9938 return \"movne\\t%0, #0\";
9940 [(set_attr "conds" "clob")
9941 (set_attr "length" "12")]
9944 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9945 ;; expressions. For simplicity, the first register is also in the unspec
9947 (define_insn "*push_multi"
9948 [(match_parallel 2 "multi_register_push"
9949 [(set (match_operand:BLK 0 "memory_operand" "=m")
9950 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9951 UNSPEC_PUSH_MULT))])]
9955 int num_saves = XVECLEN (operands[2], 0);
9957 /* For the StrongARM at least it is faster to
9958 use STR to store only a single register. */
9960 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9966 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9968 for (i = 1; i < num_saves; i++)
9970 strcat (pattern, \", %|\");
9972 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9975 strcat (pattern, \"}\");
9976 output_asm_insn (pattern, operands);
9981 [(set_attr "type" "store4")]
9984 (define_insn "stack_tie"
9985 [(set (mem:BLK (scratch))
9986 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9987 (match_operand:SI 1 "s_register_operand" "r")]
9991 [(set_attr "length" "0")]
9994 ;; Similarly for the floating point registers
9995 (define_insn "*push_fp_multi"
9996 [(match_parallel 2 "multi_register_push"
9997 [(set (match_operand:BLK 0 "memory_operand" "=m")
9998 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9999 UNSPEC_PUSH_MULT))])]
10000 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10005 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10006 output_asm_insn (pattern, operands);
10009 [(set_attr "type" "f_store")]
10012 ;; Special patterns for dealing with the constant pool
10014 (define_insn "align_4"
10015 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10018 assemble_align (32);
10023 (define_insn "align_8"
10024 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10027 assemble_align (64);
10032 (define_insn "consttable_end"
10033 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10036 making_const_table = FALSE;
10041 (define_insn "consttable_1"
10042 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10045 making_const_table = TRUE;
10046 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10047 assemble_zeros (3);
10050 [(set_attr "length" "4")]
10053 (define_insn "consttable_2"
10054 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10057 making_const_table = TRUE;
10058 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10059 assemble_zeros (2);
10062 [(set_attr "length" "4")]
10065 (define_insn "consttable_4"
10066 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10070 making_const_table = TRUE;
10071 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10076 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10077 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10081 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10086 [(set_attr "length" "4")]
10089 (define_insn "consttable_8"
10090 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10094 making_const_table = TRUE;
10095 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10100 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10101 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10105 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10110 [(set_attr "length" "8")]
10113 ;; Miscellaneous Thumb patterns
10115 (define_expand "tablejump"
10116 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10117 (use (label_ref (match_operand 1 "" "")))])]
10122 /* Hopefully, CSE will eliminate this copy. */
10123 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10124 rtx reg2 = gen_reg_rtx (SImode);
10126 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10127 operands[0] = reg2;
10132 ;; NB never uses BX.
10133 (define_insn "*thumb_tablejump"
10134 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10135 (use (label_ref (match_operand 1 "" "")))]
10138 [(set_attr "length" "2")]
10141 ;; V5 Instructions,
10143 (define_insn "clzsi2"
10144 [(set (match_operand:SI 0 "s_register_operand" "=r")
10145 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10146 "TARGET_ARM && arm_arch5"
10148 [(set_attr "predicable" "yes")])
10150 (define_expand "ffssi2"
10151 [(set (match_operand:SI 0 "s_register_operand" "")
10152 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10153 "TARGET_ARM && arm_arch5"
10158 t1 = gen_reg_rtx (SImode);
10159 t2 = gen_reg_rtx (SImode);
10160 t3 = gen_reg_rtx (SImode);
10162 emit_insn (gen_negsi2 (t1, operands[1]));
10163 emit_insn (gen_andsi3 (t2, operands[1], t1));
10164 emit_insn (gen_clzsi2 (t3, t2));
10165 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10170 (define_expand "ctzsi2"
10171 [(set (match_operand:SI 0 "s_register_operand" "")
10172 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10173 "TARGET_ARM && arm_arch5"
10178 t1 = gen_reg_rtx (SImode);
10179 t2 = gen_reg_rtx (SImode);
10180 t3 = gen_reg_rtx (SImode);
10182 emit_insn (gen_negsi2 (t1, operands[1]));
10183 emit_insn (gen_andsi3 (t2, operands[1], t1));
10184 emit_insn (gen_clzsi2 (t3, t2));
10185 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10190 ;; V5E instructions.
10192 (define_insn "prefetch"
10193 [(prefetch (match_operand:SI 0 "address_operand" "p")
10194 (match_operand:SI 1 "" "")
10195 (match_operand:SI 2 "" ""))]
10196 "TARGET_ARM && arm_arch5e"
10199 ;; General predication pattern
10202 [(match_operator 0 "arm_comparison_operator"
10203 [(match_operand 1 "cc_register" "")
10209 (define_insn "prologue_use"
10210 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10212 "%@ %0 needed for prologue"
10216 ;; Patterns for exception handling
10218 (define_expand "eh_return"
10219 [(use (match_operand 0 "general_operand" ""))]
10224 emit_insn (gen_arm_eh_return (operands[0]));
10226 emit_insn (gen_thumb_eh_return (operands[0]));
10231 ;; We can't expand this before we know where the link register is stored.
10232 (define_insn_and_split "arm_eh_return"
10233 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10235 (clobber (match_scratch:SI 1 "=&r"))]
10238 "&& reload_completed"
10242 arm_set_return_address (operands[0], operands[1]);
10247 (define_insn_and_split "thumb_eh_return"
10248 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10250 (clobber (match_scratch:SI 1 "=&l"))]
10253 "&& reload_completed"
10257 thumb_set_return_address (operands[0], operands[1]);
10265 (define_insn "load_tp_hard"
10266 [(set (match_operand:SI 0 "register_operand" "=r")
10267 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10269 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10270 [(set_attr "predicable" "yes")]
10273 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10274 (define_insn "load_tp_soft"
10275 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10276 (clobber (reg:SI LR_REGNUM))
10277 (clobber (reg:SI IP_REGNUM))
10278 (clobber (reg:CC CC_REGNUM))]
10280 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10281 [(set_attr "conds" "clob")]
10284 ;; Load the FPA co-processor patterns
10286 ;; Load the Maverick co-processor patterns
10287 (include "cirrus.md")
10288 ;; Load the Intel Wireless Multimedia Extension patterns
10289 (include "iwmmxt.md")
10290 ;; Load the VFP co-processor patterns