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")
312 (include "constraints.md")
314 ;;---------------------------------------------------------------------------
315 ;; Pipeline descriptions
317 ;; Processor type. This is created automatically from arm-cores.def.
318 (include "arm-tune.md")
320 ;; True if the generic scheduling description should be used.
322 (define_attr "generic_sched" "yes,no"
324 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
326 (const_string "yes"))))
328 (define_attr "generic_vfp" "yes,no"
330 (and (eq_attr "fpu" "vfp")
331 (eq_attr "tune" "!arm1020e,arm1022e"))
333 (const_string "no"))))
335 (include "arm-generic.md")
336 (include "arm926ejs.md")
337 (include "arm1020e.md")
338 (include "arm1026ejs.md")
339 (include "arm1136jfs.md")
342 ;;---------------------------------------------------------------------------
347 ;; Note: For DImode insns, there is normally no reason why operands should
348 ;; not be in the same register, what we don't want is for something being
349 ;; written to partially overlap something that is an input.
350 ;; Cirrus 64bit additions should not be split because we have a native
351 ;; 64bit addition instructions.
353 (define_expand "adddi3"
355 [(set (match_operand:DI 0 "s_register_operand" "")
356 (plus:DI (match_operand:DI 1 "s_register_operand" "")
357 (match_operand:DI 2 "s_register_operand" "")))
358 (clobber (reg:CC CC_REGNUM))])]
361 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
363 if (!cirrus_fp_register (operands[0], DImode))
364 operands[0] = force_reg (DImode, operands[0]);
365 if (!cirrus_fp_register (operands[1], DImode))
366 operands[1] = force_reg (DImode, operands[1]);
367 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
373 if (GET_CODE (operands[1]) != REG)
374 operands[1] = force_reg (SImode, operands[1]);
375 if (GET_CODE (operands[2]) != REG)
376 operands[2] = force_reg (SImode, operands[2]);
381 (define_insn "*thumb_adddi3"
382 [(set (match_operand:DI 0 "register_operand" "=l")
383 (plus:DI (match_operand:DI 1 "register_operand" "%0")
384 (match_operand:DI 2 "register_operand" "l")))
385 (clobber (reg:CC CC_REGNUM))
388 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
389 [(set_attr "length" "4")]
392 (define_insn_and_split "*arm_adddi3"
393 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
394 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
395 (match_operand:DI 2 "s_register_operand" "r, 0")))
396 (clobber (reg:CC CC_REGNUM))]
397 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
399 "TARGET_ARM && reload_completed"
400 [(parallel [(set (reg:CC_C CC_REGNUM)
401 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
403 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405 (plus:SI (match_dup 4) (match_dup 5))))]
408 operands[3] = gen_highpart (SImode, operands[0]);
409 operands[0] = gen_lowpart (SImode, operands[0]);
410 operands[4] = gen_highpart (SImode, operands[1]);
411 operands[1] = gen_lowpart (SImode, operands[1]);
412 operands[5] = gen_highpart (SImode, operands[2]);
413 operands[2] = gen_lowpart (SImode, operands[2]);
415 [(set_attr "conds" "clob")
416 (set_attr "length" "8")]
419 (define_insn_and_split "*adddi_sesidi_di"
420 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
421 (plus:DI (sign_extend:DI
422 (match_operand:SI 2 "s_register_operand" "r,r"))
423 (match_operand:DI 1 "s_register_operand" "r,0")))
424 (clobber (reg:CC CC_REGNUM))]
425 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
427 "TARGET_ARM && reload_completed"
428 [(parallel [(set (reg:CC_C CC_REGNUM)
429 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
431 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
432 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
433 (plus:SI (ashiftrt:SI (match_dup 2)
438 operands[3] = gen_highpart (SImode, operands[0]);
439 operands[0] = gen_lowpart (SImode, operands[0]);
440 operands[4] = gen_highpart (SImode, operands[1]);
441 operands[1] = gen_lowpart (SImode, operands[1]);
442 operands[2] = gen_lowpart (SImode, operands[2]);
444 [(set_attr "conds" "clob")
445 (set_attr "length" "8")]
448 (define_insn_and_split "*adddi_zesidi_di"
449 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
450 (plus:DI (zero_extend:DI
451 (match_operand:SI 2 "s_register_operand" "r,r"))
452 (match_operand:DI 1 "s_register_operand" "r,0")))
453 (clobber (reg:CC CC_REGNUM))]
454 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
456 "TARGET_ARM && reload_completed"
457 [(parallel [(set (reg:CC_C CC_REGNUM)
458 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
460 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
461 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
462 (plus:SI (match_dup 4) (const_int 0))))]
465 operands[3] = gen_highpart (SImode, operands[0]);
466 operands[0] = gen_lowpart (SImode, operands[0]);
467 operands[4] = gen_highpart (SImode, operands[1]);
468 operands[1] = gen_lowpart (SImode, operands[1]);
469 operands[2] = gen_lowpart (SImode, operands[2]);
471 [(set_attr "conds" "clob")
472 (set_attr "length" "8")]
475 (define_expand "addsi3"
476 [(set (match_operand:SI 0 "s_register_operand" "")
477 (plus:SI (match_operand:SI 1 "s_register_operand" "")
478 (match_operand:SI 2 "reg_or_int_operand" "")))]
481 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
483 arm_split_constant (PLUS, SImode, NULL_RTX,
484 INTVAL (operands[2]), operands[0], operands[1],
485 optimize && !no_new_pseudos);
491 ; If there is a scratch available, this will be faster than synthesizing the
494 [(match_scratch:SI 3 "r")
495 (set (match_operand:SI 0 "arm_general_register_operand" "")
496 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
497 (match_operand:SI 2 "const_int_operand" "")))]
499 !(const_ok_for_arm (INTVAL (operands[2]))
500 || const_ok_for_arm (-INTVAL (operands[2])))
501 && const_ok_for_arm (~INTVAL (operands[2]))"
502 [(set (match_dup 3) (match_dup 2))
503 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
507 (define_insn_and_split "*arm_addsi3"
508 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
509 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
510 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
517 GET_CODE (operands[2]) == CONST_INT
518 && !(const_ok_for_arm (INTVAL (operands[2]))
519 || const_ok_for_arm (-INTVAL (operands[2])))"
520 [(clobber (const_int 0))]
522 arm_split_constant (PLUS, SImode, curr_insn,
523 INTVAL (operands[2]), operands[0],
527 [(set_attr "length" "4,4,16")
528 (set_attr "predicable" "yes")]
531 ;; Register group 'k' is a single register group containing only the stack
532 ;; register. Trying to reload it will always fail catastrophically,
533 ;; so never allow those alternatives to match if reloading is needed.
535 (define_insn "*thumb_addsi3"
536 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
537 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
538 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
541 static const char * const asms[] =
543 \"add\\t%0, %0, %2\",
544 \"sub\\t%0, %0, #%n2\",
545 \"add\\t%0, %1, %2\",
546 \"add\\t%0, %0, %2\",
547 \"add\\t%0, %0, %2\",
548 \"add\\t%0, %1, %2\",
551 if ((which_alternative == 2 || which_alternative == 6)
552 && GET_CODE (operands[2]) == CONST_INT
553 && INTVAL (operands[2]) < 0)
554 return \"sub\\t%0, %1, #%n2\";
555 return asms[which_alternative];
557 [(set_attr "length" "2")]
560 ;; Reloading and elimination of the frame pointer can
561 ;; sometimes cause this optimization to be missed.
563 [(set (match_operand:SI 0 "arm_general_register_operand" "")
564 (match_operand:SI 1 "const_int_operand" ""))
566 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
568 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
569 && (INTVAL (operands[1]) & 3) == 0"
570 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
574 (define_insn "*addsi3_compare0"
575 [(set (reg:CC_NOOV CC_REGNUM)
577 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
578 (match_operand:SI 2 "arm_add_operand" "rI,L"))
580 (set (match_operand:SI 0 "s_register_operand" "=r,r")
581 (plus:SI (match_dup 1) (match_dup 2)))]
585 sub%?s\\t%0, %1, #%n2"
586 [(set_attr "conds" "set")]
589 (define_insn "*addsi3_compare0_scratch"
590 [(set (reg:CC_NOOV CC_REGNUM)
592 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
593 (match_operand:SI 1 "arm_add_operand" "rI,L"))
599 [(set_attr "conds" "set")]
602 (define_insn "*compare_negsi_si"
603 [(set (reg:CC_Z CC_REGNUM)
605 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
606 (match_operand:SI 1 "s_register_operand" "r")))]
609 [(set_attr "conds" "set")]
612 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
613 ;; addend is a constant.
614 (define_insn "*cmpsi2_addneg"
615 [(set (reg:CC CC_REGNUM)
617 (match_operand:SI 1 "s_register_operand" "r,r")
618 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
619 (set (match_operand:SI 0 "s_register_operand" "=r,r")
620 (plus:SI (match_dup 1)
621 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
622 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
625 add%?s\\t%0, %1, #%n2"
626 [(set_attr "conds" "set")]
629 ;; Convert the sequence
631 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
635 ;; bcs dest ((unsigned)rn >= 1)
636 ;; similarly for the beq variant using bcc.
637 ;; This is a common looping idiom (while (n--))
639 [(set (match_operand:SI 0 "arm_general_register_operand" "")
640 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
642 (set (match_operand 2 "cc_register" "")
643 (compare (match_dup 0) (const_int -1)))
645 (if_then_else (match_operator 3 "equality_operator"
646 [(match_dup 2) (const_int 0)])
647 (match_operand 4 "" "")
648 (match_operand 5 "" "")))]
649 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
653 (match_dup 1) (const_int 1)))
654 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
656 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
659 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
660 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
663 operands[2], const0_rtx);"
666 ;; The next four insns work because they compare the result with one of
667 ;; the operands, and we know that the use of the condition code is
668 ;; either GEU or LTU, so we can use the carry flag from the addition
669 ;; instead of doing the compare a second time.
670 (define_insn "*addsi3_compare_op1"
671 [(set (reg:CC_C CC_REGNUM)
673 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
674 (match_operand:SI 2 "arm_add_operand" "rI,L"))
676 (set (match_operand:SI 0 "s_register_operand" "=r,r")
677 (plus:SI (match_dup 1) (match_dup 2)))]
681 sub%?s\\t%0, %1, #%n2"
682 [(set_attr "conds" "set")]
685 (define_insn "*addsi3_compare_op2"
686 [(set (reg:CC_C CC_REGNUM)
688 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
689 (match_operand:SI 2 "arm_add_operand" "rI,L"))
691 (set (match_operand:SI 0 "s_register_operand" "=r,r")
692 (plus:SI (match_dup 1) (match_dup 2)))]
696 sub%?s\\t%0, %1, #%n2"
697 [(set_attr "conds" "set")]
700 (define_insn "*compare_addsi2_op0"
701 [(set (reg:CC_C CC_REGNUM)
703 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704 (match_operand:SI 1 "arm_add_operand" "rI,L"))
710 [(set_attr "conds" "set")]
713 (define_insn "*compare_addsi2_op1"
714 [(set (reg:CC_C CC_REGNUM)
716 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
717 (match_operand:SI 1 "arm_add_operand" "rI,L"))
723 [(set_attr "conds" "set")]
726 (define_insn "*addsi3_carryin"
727 [(set (match_operand:SI 0 "s_register_operand" "=r")
728 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
729 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
730 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
733 [(set_attr "conds" "use")]
736 (define_insn "*addsi3_carryin_shift"
737 [(set (match_operand:SI 0 "s_register_operand" "=r")
738 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
740 (match_operator:SI 2 "shift_operator"
741 [(match_operand:SI 3 "s_register_operand" "r")
742 (match_operand:SI 4 "reg_or_int_operand" "rM")])
743 (match_operand:SI 1 "s_register_operand" "r"))))]
745 "adc%?\\t%0, %1, %3%S2"
746 [(set_attr "conds" "use")
747 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
748 (const_string "alu_shift")
749 (const_string "alu_shift_reg")))]
752 (define_insn "*addsi3_carryin_alt1"
753 [(set (match_operand:SI 0 "s_register_operand" "=r")
754 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
755 (match_operand:SI 2 "arm_rhs_operand" "rI"))
756 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
759 [(set_attr "conds" "use")]
762 (define_insn "*addsi3_carryin_alt2"
763 [(set (match_operand:SI 0 "s_register_operand" "=r")
764 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
765 (match_operand:SI 1 "s_register_operand" "r"))
766 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
769 [(set_attr "conds" "use")]
772 (define_insn "*addsi3_carryin_alt3"
773 [(set (match_operand:SI 0 "s_register_operand" "=r")
774 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
775 (match_operand:SI 2 "arm_rhs_operand" "rI"))
776 (match_operand:SI 1 "s_register_operand" "r")))]
779 [(set_attr "conds" "use")]
782 (define_insn "incscc"
783 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
784 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
785 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
786 (match_operand:SI 1 "s_register_operand" "0,?r")))]
790 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
791 [(set_attr "conds" "use")
792 (set_attr "length" "4,8")]
795 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
797 [(set (match_operand:SI 0 "s_register_operand" "")
798 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
799 (match_operand:SI 2 "s_register_operand" ""))
801 (clobber (match_operand:SI 3 "s_register_operand" ""))]
803 [(set (match_dup 3) (match_dup 1))
804 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
806 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
809 (define_expand "addsf3"
810 [(set (match_operand:SF 0 "s_register_operand" "")
811 (plus:SF (match_operand:SF 1 "s_register_operand" "")
812 (match_operand:SF 2 "arm_float_add_operand" "")))]
813 "TARGET_ARM && TARGET_HARD_FLOAT"
816 && !cirrus_fp_register (operands[2], SFmode))
817 operands[2] = force_reg (SFmode, operands[2]);
820 (define_expand "adddf3"
821 [(set (match_operand:DF 0 "s_register_operand" "")
822 (plus:DF (match_operand:DF 1 "s_register_operand" "")
823 (match_operand:DF 2 "arm_float_add_operand" "")))]
824 "TARGET_ARM && TARGET_HARD_FLOAT"
827 && !cirrus_fp_register (operands[2], DFmode))
828 operands[2] = force_reg (DFmode, operands[2]);
831 (define_expand "subdi3"
833 [(set (match_operand:DI 0 "s_register_operand" "")
834 (minus:DI (match_operand:DI 1 "s_register_operand" "")
835 (match_operand:DI 2 "s_register_operand" "")))
836 (clobber (reg:CC CC_REGNUM))])]
839 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
841 && cirrus_fp_register (operands[0], DImode)
842 && cirrus_fp_register (operands[1], DImode))
844 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
850 if (GET_CODE (operands[1]) != REG)
851 operands[1] = force_reg (SImode, operands[1]);
852 if (GET_CODE (operands[2]) != REG)
853 operands[2] = force_reg (SImode, operands[2]);
858 (define_insn "*arm_subdi3"
859 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
860 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
861 (match_operand:DI 2 "s_register_operand" "r,0,0")))
862 (clobber (reg:CC CC_REGNUM))]
864 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
865 [(set_attr "conds" "clob")
866 (set_attr "length" "8")]
869 (define_insn "*thumb_subdi3"
870 [(set (match_operand:DI 0 "register_operand" "=l")
871 (minus:DI (match_operand:DI 1 "register_operand" "0")
872 (match_operand:DI 2 "register_operand" "l")))
873 (clobber (reg:CC CC_REGNUM))]
875 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
876 [(set_attr "length" "4")]
879 (define_insn "*subdi_di_zesidi"
880 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
881 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
883 (match_operand:SI 2 "s_register_operand" "r,r"))))
884 (clobber (reg:CC CC_REGNUM))]
886 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
887 [(set_attr "conds" "clob")
888 (set_attr "length" "8")]
891 (define_insn "*subdi_di_sesidi"
892 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
893 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
895 (match_operand:SI 2 "s_register_operand" "r,r"))))
896 (clobber (reg:CC CC_REGNUM))]
898 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
899 [(set_attr "conds" "clob")
900 (set_attr "length" "8")]
903 (define_insn "*subdi_zesidi_di"
904 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
905 (minus:DI (zero_extend:DI
906 (match_operand:SI 2 "s_register_operand" "r,r"))
907 (match_operand:DI 1 "s_register_operand" "?r,0")))
908 (clobber (reg:CC CC_REGNUM))]
910 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
911 [(set_attr "conds" "clob")
912 (set_attr "length" "8")]
915 (define_insn "*subdi_sesidi_di"
916 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
917 (minus:DI (sign_extend:DI
918 (match_operand:SI 2 "s_register_operand" "r,r"))
919 (match_operand:DI 1 "s_register_operand" "?r,0")))
920 (clobber (reg:CC CC_REGNUM))]
922 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
923 [(set_attr "conds" "clob")
924 (set_attr "length" "8")]
927 (define_insn "*subdi_zesidi_zesidi"
928 [(set (match_operand:DI 0 "s_register_operand" "=r")
929 (minus:DI (zero_extend:DI
930 (match_operand:SI 1 "s_register_operand" "r"))
932 (match_operand:SI 2 "s_register_operand" "r"))))
933 (clobber (reg:CC CC_REGNUM))]
935 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
936 [(set_attr "conds" "clob")
937 (set_attr "length" "8")]
940 (define_expand "subsi3"
941 [(set (match_operand:SI 0 "s_register_operand" "")
942 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
943 (match_operand:SI 2 "s_register_operand" "")))]
946 if (GET_CODE (operands[1]) == CONST_INT)
950 arm_split_constant (MINUS, SImode, NULL_RTX,
951 INTVAL (operands[1]), operands[0],
952 operands[2], optimize && !no_new_pseudos);
955 else /* TARGET_THUMB */
956 operands[1] = force_reg (SImode, operands[1]);
961 (define_insn "*thumb_subsi3_insn"
962 [(set (match_operand:SI 0 "register_operand" "=l")
963 (minus:SI (match_operand:SI 1 "register_operand" "l")
964 (match_operand:SI 2 "register_operand" "l")))]
967 [(set_attr "length" "2")]
970 (define_insn_and_split "*arm_subsi3_insn"
971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
972 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
973 (match_operand:SI 2 "s_register_operand" "r,r")))]
979 && GET_CODE (operands[1]) == CONST_INT
980 && !const_ok_for_arm (INTVAL (operands[1]))"
981 [(clobber (const_int 0))]
983 arm_split_constant (MINUS, SImode, curr_insn,
984 INTVAL (operands[1]), operands[0], operands[2], 0);
987 [(set_attr "length" "4,16")
988 (set_attr "predicable" "yes")]
992 [(match_scratch:SI 3 "r")
993 (set (match_operand:SI 0 "arm_general_register_operand" "")
994 (minus:SI (match_operand:SI 1 "const_int_operand" "")
995 (match_operand:SI 2 "arm_general_register_operand" "")))]
997 && !const_ok_for_arm (INTVAL (operands[1]))
998 && const_ok_for_arm (~INTVAL (operands[1]))"
999 [(set (match_dup 3) (match_dup 1))
1000 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1004 (define_insn "*subsi3_compare0"
1005 [(set (reg:CC_NOOV CC_REGNUM)
1007 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1008 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1010 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1011 (minus:SI (match_dup 1) (match_dup 2)))]
1015 rsb%?s\\t%0, %2, %1"
1016 [(set_attr "conds" "set")]
1019 (define_insn "decscc"
1020 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1021 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1022 (match_operator:SI 2 "arm_comparison_operator"
1023 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1027 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1028 [(set_attr "conds" "use")
1029 (set_attr "length" "*,8")]
1032 (define_expand "subsf3"
1033 [(set (match_operand:SF 0 "s_register_operand" "")
1034 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1035 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1036 "TARGET_ARM && TARGET_HARD_FLOAT"
1038 if (TARGET_MAVERICK)
1040 if (!cirrus_fp_register (operands[1], SFmode))
1041 operands[1] = force_reg (SFmode, operands[1]);
1042 if (!cirrus_fp_register (operands[2], SFmode))
1043 operands[2] = force_reg (SFmode, operands[2]);
1047 (define_expand "subdf3"
1048 [(set (match_operand:DF 0 "s_register_operand" "")
1049 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1050 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1051 "TARGET_ARM && TARGET_HARD_FLOAT"
1053 if (TARGET_MAVERICK)
1055 if (!cirrus_fp_register (operands[1], DFmode))
1056 operands[1] = force_reg (DFmode, operands[1]);
1057 if (!cirrus_fp_register (operands[2], DFmode))
1058 operands[2] = force_reg (DFmode, operands[2]);
1063 ;; Multiplication insns
1065 (define_expand "mulsi3"
1066 [(set (match_operand:SI 0 "s_register_operand" "")
1067 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1068 (match_operand:SI 1 "s_register_operand" "")))]
1073 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1074 (define_insn "*arm_mulsi3"
1075 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1076 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1077 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1079 "mul%?\\t%0, %2, %1"
1080 [(set_attr "insn" "mul")
1081 (set_attr "predicable" "yes")]
1084 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1085 ; 1 and 2; are the same, because reload will make operand 0 match
1086 ; operand 1 without realizing that this conflicts with operand 2. We fix
1087 ; this by adding another alternative to match this case, and then `reload'
1088 ; it ourselves. This alternative must come first.
1089 (define_insn "*thumb_mulsi3"
1090 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1091 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1092 (match_operand:SI 2 "register_operand" "l,l,l")))]
1095 if (which_alternative < 2)
1096 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1098 return \"mul\\t%0, %2\";
1100 [(set_attr "length" "4,4,2")
1101 (set_attr "insn" "mul")]
1104 (define_insn "*mulsi3_compare0"
1105 [(set (reg:CC_NOOV CC_REGNUM)
1106 (compare:CC_NOOV (mult:SI
1107 (match_operand:SI 2 "s_register_operand" "r,r")
1108 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1110 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1111 (mult:SI (match_dup 2) (match_dup 1)))]
1113 "mul%?s\\t%0, %2, %1"
1114 [(set_attr "conds" "set")
1115 (set_attr "insn" "muls")]
1118 (define_insn "*mulsi_compare0_scratch"
1119 [(set (reg:CC_NOOV CC_REGNUM)
1120 (compare:CC_NOOV (mult:SI
1121 (match_operand:SI 2 "s_register_operand" "r,r")
1122 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1124 (clobber (match_scratch:SI 0 "=&r,&r"))]
1126 "mul%?s\\t%0, %2, %1"
1127 [(set_attr "conds" "set")
1128 (set_attr "insn" "muls")]
1131 ;; Unnamed templates to match MLA instruction.
1133 (define_insn "*mulsi3addsi"
1134 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1136 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1137 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1138 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1140 "mla%?\\t%0, %2, %1, %3"
1141 [(set_attr "insn" "mla")
1142 (set_attr "predicable" "yes")]
1145 (define_insn "*mulsi3addsi_compare0"
1146 [(set (reg:CC_NOOV CC_REGNUM)
1149 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1150 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1151 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1153 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1154 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1157 "mla%?s\\t%0, %2, %1, %3"
1158 [(set_attr "conds" "set")
1159 (set_attr "insn" "mlas")]
1162 (define_insn "*mulsi3addsi_compare0_scratch"
1163 [(set (reg:CC_NOOV CC_REGNUM)
1166 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1167 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1168 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1170 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1172 "mla%?s\\t%0, %2, %1, %3"
1173 [(set_attr "conds" "set")
1174 (set_attr "insn" "mlas")]
1177 ;; Unnamed template to match long long multiply-accumulate (smlal)
1179 (define_insn "*mulsidi3adddi"
1180 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1183 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1184 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1185 (match_operand:DI 1 "s_register_operand" "0")))]
1186 "TARGET_ARM && arm_arch3m"
1187 "smlal%?\\t%Q0, %R0, %3, %2"
1188 [(set_attr "insn" "smlal")
1189 (set_attr "predicable" "yes")]
1192 (define_insn "mulsidi3"
1193 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1195 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197 "TARGET_ARM && arm_arch3m"
1198 "smull%?\\t%Q0, %R0, %1, %2"
1199 [(set_attr "insn" "smull")
1200 (set_attr "predicable" "yes")]
1203 (define_insn "umulsidi3"
1204 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1206 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1207 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1208 "TARGET_ARM && arm_arch3m"
1209 "umull%?\\t%Q0, %R0, %1, %2"
1210 [(set_attr "insn" "umull")
1211 (set_attr "predicable" "yes")]
1214 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1216 (define_insn "*umulsidi3adddi"
1217 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1220 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1221 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1222 (match_operand:DI 1 "s_register_operand" "0")))]
1223 "TARGET_ARM && arm_arch3m"
1224 "umlal%?\\t%Q0, %R0, %3, %2"
1225 [(set_attr "insn" "umlal")
1226 (set_attr "predicable" "yes")]
1229 (define_insn "smulsi3_highpart"
1230 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1234 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1235 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1237 (clobber (match_scratch:SI 3 "=&r,&r"))]
1238 "TARGET_ARM && arm_arch3m"
1239 "smull%?\\t%3, %0, %2, %1"
1240 [(set_attr "insn" "smull")
1241 (set_attr "predicable" "yes")]
1244 (define_insn "umulsi3_highpart"
1245 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1249 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1250 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1252 (clobber (match_scratch:SI 3 "=&r,&r"))]
1253 "TARGET_ARM && arm_arch3m"
1254 "umull%?\\t%3, %0, %2, %1"
1255 [(set_attr "insn" "umull")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "mulhisi3"
1260 [(set (match_operand:SI 0 "s_register_operand" "=r")
1261 (mult:SI (sign_extend:SI
1262 (match_operand:HI 1 "s_register_operand" "%r"))
1264 (match_operand:HI 2 "s_register_operand" "r"))))]
1265 "TARGET_ARM && arm_arch5e"
1266 "smulbb%?\\t%0, %1, %2"
1267 [(set_attr "insn" "smulxy")
1268 (set_attr "predicable" "yes")]
1271 (define_insn "*mulhisi3tb"
1272 [(set (match_operand:SI 0 "s_register_operand" "=r")
1273 (mult:SI (ashiftrt:SI
1274 (match_operand:SI 1 "s_register_operand" "r")
1277 (match_operand:HI 2 "s_register_operand" "r"))))]
1278 "TARGET_ARM && arm_arch5e"
1279 "smultb%?\\t%0, %1, %2"
1280 [(set_attr "insn" "smulxy")
1281 (set_attr "predicable" "yes")]
1284 (define_insn "*mulhisi3bt"
1285 [(set (match_operand:SI 0 "s_register_operand" "=r")
1286 (mult:SI (sign_extend:SI
1287 (match_operand:HI 1 "s_register_operand" "r"))
1289 (match_operand:SI 2 "s_register_operand" "r")
1291 "TARGET_ARM && arm_arch5e"
1292 "smulbt%?\\t%0, %1, %2"
1293 [(set_attr "insn" "smulxy")
1294 (set_attr "predicable" "yes")]
1297 (define_insn "*mulhisi3tt"
1298 [(set (match_operand:SI 0 "s_register_operand" "=r")
1299 (mult:SI (ashiftrt:SI
1300 (match_operand:SI 1 "s_register_operand" "r")
1303 (match_operand:SI 2 "s_register_operand" "r")
1305 "TARGET_ARM && arm_arch5e"
1306 "smultt%?\\t%0, %1, %2"
1307 [(set_attr "insn" "smulxy")
1308 (set_attr "predicable" "yes")]
1311 (define_insn "*mulhisi3addsi"
1312 [(set (match_operand:SI 0 "s_register_operand" "=r")
1313 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1314 (mult:SI (sign_extend:SI
1315 (match_operand:HI 2 "s_register_operand" "%r"))
1317 (match_operand:HI 3 "s_register_operand" "r")))))]
1318 "TARGET_ARM && arm_arch5e"
1319 "smlabb%?\\t%0, %2, %3, %1"
1320 [(set_attr "insn" "smlaxy")
1321 (set_attr "predicable" "yes")]
1324 (define_insn "*mulhidi3adddi"
1325 [(set (match_operand:DI 0 "s_register_operand" "=r")
1327 (match_operand:DI 1 "s_register_operand" "0")
1328 (mult:DI (sign_extend:DI
1329 (match_operand:HI 2 "s_register_operand" "%r"))
1331 (match_operand:HI 3 "s_register_operand" "r")))))]
1332 "TARGET_ARM && arm_arch5e"
1333 "smlalbb%?\\t%Q0, %R0, %2, %3"
1334 [(set_attr "insn" "smlalxy")
1335 (set_attr "predicable" "yes")])
1337 (define_expand "mulsf3"
1338 [(set (match_operand:SF 0 "s_register_operand" "")
1339 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1340 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1341 "TARGET_ARM && TARGET_HARD_FLOAT"
1344 && !cirrus_fp_register (operands[2], SFmode))
1345 operands[2] = force_reg (SFmode, operands[2]);
1348 (define_expand "muldf3"
1349 [(set (match_operand:DF 0 "s_register_operand" "")
1350 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1351 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1352 "TARGET_ARM && TARGET_HARD_FLOAT"
1355 && !cirrus_fp_register (operands[2], DFmode))
1356 operands[2] = force_reg (DFmode, operands[2]);
1361 (define_expand "divsf3"
1362 [(set (match_operand:SF 0 "s_register_operand" "")
1363 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1364 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1365 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1368 (define_expand "divdf3"
1369 [(set (match_operand:DF 0 "s_register_operand" "")
1370 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1371 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1372 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1377 (define_expand "modsf3"
1378 [(set (match_operand:SF 0 "s_register_operand" "")
1379 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1380 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1381 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1384 (define_expand "moddf3"
1385 [(set (match_operand:DF 0 "s_register_operand" "")
1386 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1387 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1388 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1391 ;; Boolean and,ior,xor insns
1393 ;; Split up double word logical operations
1395 ;; Split up simple DImode logical operations. Simply perform the logical
1396 ;; operation on the upper and lower halves of the registers.
1398 [(set (match_operand:DI 0 "s_register_operand" "")
1399 (match_operator:DI 6 "logical_binary_operator"
1400 [(match_operand:DI 1 "s_register_operand" "")
1401 (match_operand:DI 2 "s_register_operand" "")]))]
1402 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1403 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1404 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1407 operands[3] = gen_highpart (SImode, operands[0]);
1408 operands[0] = gen_lowpart (SImode, operands[0]);
1409 operands[4] = gen_highpart (SImode, operands[1]);
1410 operands[1] = gen_lowpart (SImode, operands[1]);
1411 operands[5] = gen_highpart (SImode, operands[2]);
1412 operands[2] = gen_lowpart (SImode, operands[2]);
1417 [(set (match_operand:DI 0 "s_register_operand" "")
1418 (match_operator:DI 6 "logical_binary_operator"
1419 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1420 (match_operand:DI 1 "s_register_operand" "")]))]
1421 "TARGET_ARM && reload_completed"
1422 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1423 (set (match_dup 3) (match_op_dup:SI 6
1424 [(ashiftrt:SI (match_dup 2) (const_int 31))
1428 operands[3] = gen_highpart (SImode, operands[0]);
1429 operands[0] = gen_lowpart (SImode, operands[0]);
1430 operands[4] = gen_highpart (SImode, operands[1]);
1431 operands[1] = gen_lowpart (SImode, operands[1]);
1432 operands[5] = gen_highpart (SImode, operands[2]);
1433 operands[2] = gen_lowpart (SImode, operands[2]);
1437 ;; The zero extend of operand 2 means we can just copy the high part of
1438 ;; operand1 into operand0.
1440 [(set (match_operand:DI 0 "s_register_operand" "")
1442 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1443 (match_operand:DI 1 "s_register_operand" "")))]
1444 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1445 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1446 (set (match_dup 3) (match_dup 4))]
1449 operands[4] = gen_highpart (SImode, operands[1]);
1450 operands[3] = gen_highpart (SImode, operands[0]);
1451 operands[0] = gen_lowpart (SImode, operands[0]);
1452 operands[1] = gen_lowpart (SImode, operands[1]);
1456 ;; The zero extend of operand 2 means we can just copy the high part of
1457 ;; operand1 into operand0.
1459 [(set (match_operand:DI 0 "s_register_operand" "")
1461 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462 (match_operand:DI 1 "s_register_operand" "")))]
1463 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1464 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1465 (set (match_dup 3) (match_dup 4))]
1468 operands[4] = gen_highpart (SImode, operands[1]);
1469 operands[3] = gen_highpart (SImode, operands[0]);
1470 operands[0] = gen_lowpart (SImode, operands[0]);
1471 operands[1] = gen_lowpart (SImode, operands[1]);
1475 (define_insn "anddi3"
1476 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1477 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1478 (match_operand:DI 2 "s_register_operand" "r,r")))]
1479 "TARGET_ARM && ! TARGET_IWMMXT"
1481 [(set_attr "length" "8")]
1484 (define_insn_and_split "*anddi_zesidi_di"
1485 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1486 (and:DI (zero_extend:DI
1487 (match_operand:SI 2 "s_register_operand" "r,r"))
1488 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1491 "TARGET_ARM && reload_completed"
1492 ; The zero extend of operand 2 clears the high word of the output
1494 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1495 (set (match_dup 3) (const_int 0))]
1498 operands[3] = gen_highpart (SImode, operands[0]);
1499 operands[0] = gen_lowpart (SImode, operands[0]);
1500 operands[1] = gen_lowpart (SImode, operands[1]);
1502 [(set_attr "length" "8")]
1505 (define_insn "*anddi_sesdi_di"
1506 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1507 (and:DI (sign_extend:DI
1508 (match_operand:SI 2 "s_register_operand" "r,r"))
1509 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1512 [(set_attr "length" "8")]
1515 (define_expand "andsi3"
1516 [(set (match_operand:SI 0 "s_register_operand" "")
1517 (and:SI (match_operand:SI 1 "s_register_operand" "")
1518 (match_operand:SI 2 "reg_or_int_operand" "")))]
1523 if (GET_CODE (operands[2]) == CONST_INT)
1525 arm_split_constant (AND, SImode, NULL_RTX,
1526 INTVAL (operands[2]), operands[0],
1527 operands[1], optimize && !no_new_pseudos);
1532 else /* TARGET_THUMB */
1534 if (GET_CODE (operands[2]) != CONST_INT)
1535 operands[2] = force_reg (SImode, operands[2]);
1540 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1542 operands[2] = force_reg (SImode,
1543 GEN_INT (~INTVAL (operands[2])));
1545 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1550 for (i = 9; i <= 31; i++)
1552 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1554 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1558 else if ((((HOST_WIDE_INT) 1) << i) - 1
1559 == ~INTVAL (operands[2]))
1561 rtx shift = GEN_INT (i);
1562 rtx reg = gen_reg_rtx (SImode);
1564 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1565 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1571 operands[2] = force_reg (SImode, operands[2]);
1577 (define_insn_and_split "*arm_andsi3_insn"
1578 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1579 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1580 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1584 bic%?\\t%0, %1, #%B2
1587 && GET_CODE (operands[2]) == CONST_INT
1588 && !(const_ok_for_arm (INTVAL (operands[2]))
1589 || const_ok_for_arm (~INTVAL (operands[2])))"
1590 [(clobber (const_int 0))]
1592 arm_split_constant (AND, SImode, curr_insn,
1593 INTVAL (operands[2]), operands[0], operands[1], 0);
1596 [(set_attr "length" "4,4,16")
1597 (set_attr "predicable" "yes")]
1600 (define_insn "*thumb_andsi3_insn"
1601 [(set (match_operand:SI 0 "register_operand" "=l")
1602 (and:SI (match_operand:SI 1 "register_operand" "%0")
1603 (match_operand:SI 2 "register_operand" "l")))]
1606 [(set_attr "length" "2")]
1609 (define_insn "*andsi3_compare0"
1610 [(set (reg:CC_NOOV CC_REGNUM)
1612 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1613 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1615 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1616 (and:SI (match_dup 1) (match_dup 2)))]
1620 bic%?s\\t%0, %1, #%B2"
1621 [(set_attr "conds" "set")]
1624 (define_insn "*andsi3_compare0_scratch"
1625 [(set (reg:CC_NOOV CC_REGNUM)
1627 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1628 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1630 (clobber (match_scratch:SI 2 "=X,r"))]
1634 bic%?s\\t%2, %0, #%B1"
1635 [(set_attr "conds" "set")]
1638 (define_insn "*zeroextractsi_compare0_scratch"
1639 [(set (reg:CC_NOOV CC_REGNUM)
1640 (compare:CC_NOOV (zero_extract:SI
1641 (match_operand:SI 0 "s_register_operand" "r")
1642 (match_operand 1 "const_int_operand" "n")
1643 (match_operand 2 "const_int_operand" "n"))
1646 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1647 && INTVAL (operands[1]) > 0
1648 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1649 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1651 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1652 << INTVAL (operands[2]));
1653 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1656 [(set_attr "conds" "set")]
1659 (define_insn_and_split "*ne_zeroextractsi"
1660 [(set (match_operand:SI 0 "s_register_operand" "=r")
1661 (ne:SI (zero_extract:SI
1662 (match_operand:SI 1 "s_register_operand" "r")
1663 (match_operand:SI 2 "const_int_operand" "n")
1664 (match_operand:SI 3 "const_int_operand" "n"))
1666 (clobber (reg:CC CC_REGNUM))]
1668 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1669 && INTVAL (operands[2]) > 0
1670 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1671 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1674 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1675 && INTVAL (operands[2]) > 0
1676 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1677 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1678 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1679 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1681 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1683 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1684 (match_dup 0) (const_int 1)))]
1686 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1687 << INTVAL (operands[3]));
1689 [(set_attr "conds" "clob")
1690 (set_attr "length" "8")]
1693 (define_insn_and_split "*ne_zeroextractsi_shifted"
1694 [(set (match_operand:SI 0 "s_register_operand" "=r")
1695 (ne:SI (zero_extract:SI
1696 (match_operand:SI 1 "s_register_operand" "r")
1697 (match_operand:SI 2 "const_int_operand" "n")
1700 (clobber (reg:CC CC_REGNUM))]
1704 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1705 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1707 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1709 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1710 (match_dup 0) (const_int 1)))]
1712 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1714 [(set_attr "conds" "clob")
1715 (set_attr "length" "8")]
1718 (define_insn_and_split "*ite_ne_zeroextractsi"
1719 [(set (match_operand:SI 0 "s_register_operand" "=r")
1720 (if_then_else:SI (ne (zero_extract:SI
1721 (match_operand:SI 1 "s_register_operand" "r")
1722 (match_operand:SI 2 "const_int_operand" "n")
1723 (match_operand:SI 3 "const_int_operand" "n"))
1725 (match_operand:SI 4 "arm_not_operand" "rIK")
1727 (clobber (reg:CC CC_REGNUM))]
1729 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1730 && INTVAL (operands[2]) > 0
1731 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1732 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1733 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1736 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1737 && INTVAL (operands[2]) > 0
1738 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1739 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1740 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1741 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1742 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1744 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1746 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1747 (match_dup 0) (match_dup 4)))]
1749 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1750 << INTVAL (operands[3]));
1752 [(set_attr "conds" "clob")
1753 (set_attr "length" "8")]
1756 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1757 [(set (match_operand:SI 0 "s_register_operand" "=r")
1758 (if_then_else:SI (ne (zero_extract:SI
1759 (match_operand:SI 1 "s_register_operand" "r")
1760 (match_operand:SI 2 "const_int_operand" "n")
1763 (match_operand:SI 3 "arm_not_operand" "rIK")
1765 (clobber (reg:CC CC_REGNUM))]
1766 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1769 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1770 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1772 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1774 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1775 (match_dup 0) (match_dup 3)))]
1777 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1779 [(set_attr "conds" "clob")
1780 (set_attr "length" "8")]
1784 [(set (match_operand:SI 0 "s_register_operand" "")
1785 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1786 (match_operand:SI 2 "const_int_operand" "")
1787 (match_operand:SI 3 "const_int_operand" "")))
1788 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1790 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1791 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1793 HOST_WIDE_INT temp = INTVAL (operands[2]);
1795 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1796 operands[3] = GEN_INT (32 - temp);
1801 [(set (match_operand:SI 0 "s_register_operand" "")
1802 (match_operator:SI 1 "shiftable_operator"
1803 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1804 (match_operand:SI 3 "const_int_operand" "")
1805 (match_operand:SI 4 "const_int_operand" ""))
1806 (match_operand:SI 5 "s_register_operand" "")]))
1807 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1809 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1812 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1815 HOST_WIDE_INT temp = INTVAL (operands[3]);
1817 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1818 operands[4] = GEN_INT (32 - temp);
1823 [(set (match_operand:SI 0 "s_register_operand" "")
1824 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1825 (match_operand:SI 2 "const_int_operand" "")
1826 (match_operand:SI 3 "const_int_operand" "")))]
1828 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1829 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1831 HOST_WIDE_INT temp = INTVAL (operands[2]);
1833 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1834 operands[3] = GEN_INT (32 - temp);
1839 [(set (match_operand:SI 0 "s_register_operand" "")
1840 (match_operator:SI 1 "shiftable_operator"
1841 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1842 (match_operand:SI 3 "const_int_operand" "")
1843 (match_operand:SI 4 "const_int_operand" ""))
1844 (match_operand:SI 5 "s_register_operand" "")]))
1845 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1847 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1850 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1853 HOST_WIDE_INT temp = INTVAL (operands[3]);
1855 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1856 operands[4] = GEN_INT (32 - temp);
1860 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1861 ;;; represented by the bitfield, then this will produce incorrect results.
1862 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1863 ;;; which have a real bit-field insert instruction, the truncation happens
1864 ;;; in the bit-field insert instruction itself. Since arm does not have a
1865 ;;; bit-field insert instruction, we would have to emit code here to truncate
1866 ;;; the value before we insert. This loses some of the advantage of having
1867 ;;; this insv pattern, so this pattern needs to be reevalutated.
1869 (define_expand "insv"
1870 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1871 (match_operand:SI 1 "general_operand" "")
1872 (match_operand:SI 2 "general_operand" ""))
1873 (match_operand:SI 3 "reg_or_int_operand" ""))]
1877 int start_bit = INTVAL (operands[2]);
1878 int width = INTVAL (operands[1]);
1879 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1880 rtx target, subtarget;
1882 target = operands[0];
1883 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1884 subreg as the final target. */
1885 if (GET_CODE (target) == SUBREG)
1887 subtarget = gen_reg_rtx (SImode);
1888 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1889 < GET_MODE_SIZE (SImode))
1890 target = SUBREG_REG (target);
1895 if (GET_CODE (operands[3]) == CONST_INT)
1897 /* Since we are inserting a known constant, we may be able to
1898 reduce the number of bits that we have to clear so that
1899 the mask becomes simple. */
1900 /* ??? This code does not check to see if the new mask is actually
1901 simpler. It may not be. */
1902 rtx op1 = gen_reg_rtx (SImode);
1903 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1904 start of this pattern. */
1905 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1906 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1908 emit_insn (gen_andsi3 (op1, operands[0],
1909 gen_int_mode (~mask2, SImode)));
1910 emit_insn (gen_iorsi3 (subtarget, op1,
1911 gen_int_mode (op3_value << start_bit, SImode)));
1913 else if (start_bit == 0
1914 && !(const_ok_for_arm (mask)
1915 || const_ok_for_arm (~mask)))
1917 /* A Trick, since we are setting the bottom bits in the word,
1918 we can shift operand[3] up, operand[0] down, OR them together
1919 and rotate the result back again. This takes 3 insns, and
1920 the third might be mergeable into another op. */
1921 /* The shift up copes with the possibility that operand[3] is
1922 wider than the bitfield. */
1923 rtx op0 = gen_reg_rtx (SImode);
1924 rtx op1 = gen_reg_rtx (SImode);
1926 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1927 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1928 emit_insn (gen_iorsi3 (op1, op1, op0));
1929 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1931 else if ((width + start_bit == 32)
1932 && !(const_ok_for_arm (mask)
1933 || const_ok_for_arm (~mask)))
1935 /* Similar trick, but slightly less efficient. */
1937 rtx op0 = gen_reg_rtx (SImode);
1938 rtx op1 = gen_reg_rtx (SImode);
1940 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1941 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1942 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1943 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1947 rtx op0 = gen_int_mode (mask, SImode);
1948 rtx op1 = gen_reg_rtx (SImode);
1949 rtx op2 = gen_reg_rtx (SImode);
1951 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1953 rtx tmp = gen_reg_rtx (SImode);
1955 emit_insn (gen_movsi (tmp, op0));
1959 /* Mask out any bits in operand[3] that are not needed. */
1960 emit_insn (gen_andsi3 (op1, operands[3], op0));
1962 if (GET_CODE (op0) == CONST_INT
1963 && (const_ok_for_arm (mask << start_bit)
1964 || const_ok_for_arm (~(mask << start_bit))))
1966 op0 = gen_int_mode (~(mask << start_bit), SImode);
1967 emit_insn (gen_andsi3 (op2, operands[0], op0));
1971 if (GET_CODE (op0) == CONST_INT)
1973 rtx tmp = gen_reg_rtx (SImode);
1975 emit_insn (gen_movsi (tmp, op0));
1980 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1982 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1986 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1988 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1991 if (subtarget != target)
1993 /* If TARGET is still a SUBREG, then it must be wider than a word,
1994 so we must be careful only to set the subword we were asked to. */
1995 if (GET_CODE (target) == SUBREG)
1996 emit_move_insn (target, subtarget);
1998 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2005 ; constants for op 2 will never be given to these patterns.
2006 (define_insn_and_split "*anddi_notdi_di"
2007 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2008 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2009 (match_operand:DI 2 "s_register_operand" "0,r")))]
2012 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2013 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2014 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2017 operands[3] = gen_highpart (SImode, operands[0]);
2018 operands[0] = gen_lowpart (SImode, operands[0]);
2019 operands[4] = gen_highpart (SImode, operands[1]);
2020 operands[1] = gen_lowpart (SImode, operands[1]);
2021 operands[5] = gen_highpart (SImode, operands[2]);
2022 operands[2] = gen_lowpart (SImode, operands[2]);
2024 [(set_attr "length" "8")
2025 (set_attr "predicable" "yes")]
2028 (define_insn_and_split "*anddi_notzesidi_di"
2029 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2030 (and:DI (not:DI (zero_extend:DI
2031 (match_operand:SI 2 "s_register_operand" "r,r")))
2032 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2035 bic%?\\t%Q0, %Q1, %2
2037 ; (not (zero_extend ...)) allows us to just copy the high word from
2038 ; operand1 to operand0.
2041 && operands[0] != operands[1]"
2042 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2043 (set (match_dup 3) (match_dup 4))]
2046 operands[3] = gen_highpart (SImode, operands[0]);
2047 operands[0] = gen_lowpart (SImode, operands[0]);
2048 operands[4] = gen_highpart (SImode, operands[1]);
2049 operands[1] = gen_lowpart (SImode, operands[1]);
2051 [(set_attr "length" "4,8")
2052 (set_attr "predicable" "yes")]
2055 (define_insn_and_split "*anddi_notsesidi_di"
2056 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2057 (and:DI (not:DI (sign_extend:DI
2058 (match_operand:SI 2 "s_register_operand" "r,r")))
2059 (match_operand:DI 1 "s_register_operand" "0,r")))]
2062 "TARGET_ARM && reload_completed"
2063 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2064 (set (match_dup 3) (and:SI (not:SI
2065 (ashiftrt:SI (match_dup 2) (const_int 31)))
2069 operands[3] = gen_highpart (SImode, operands[0]);
2070 operands[0] = gen_lowpart (SImode, operands[0]);
2071 operands[4] = gen_highpart (SImode, operands[1]);
2072 operands[1] = gen_lowpart (SImode, operands[1]);
2074 [(set_attr "length" "8")
2075 (set_attr "predicable" "yes")]
2078 (define_insn "andsi_notsi_si"
2079 [(set (match_operand:SI 0 "s_register_operand" "=r")
2080 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2081 (match_operand:SI 1 "s_register_operand" "r")))]
2083 "bic%?\\t%0, %1, %2"
2084 [(set_attr "predicable" "yes")]
2087 (define_insn "bicsi3"
2088 [(set (match_operand:SI 0 "register_operand" "=l")
2089 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2090 (match_operand:SI 2 "register_operand" "0")))]
2093 [(set_attr "length" "2")]
2096 (define_insn "andsi_not_shiftsi_si"
2097 [(set (match_operand:SI 0 "s_register_operand" "=r")
2098 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2099 [(match_operand:SI 2 "s_register_operand" "r")
2100 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2101 (match_operand:SI 1 "s_register_operand" "r")))]
2103 "bic%?\\t%0, %1, %2%S4"
2104 [(set_attr "predicable" "yes")
2105 (set_attr "shift" "2")
2106 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2107 (const_string "alu_shift")
2108 (const_string "alu_shift_reg")))]
2111 (define_insn "*andsi_notsi_si_compare0"
2112 [(set (reg:CC_NOOV CC_REGNUM)
2114 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2115 (match_operand:SI 1 "s_register_operand" "r"))
2117 (set (match_operand:SI 0 "s_register_operand" "=r")
2118 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2120 "bic%?s\\t%0, %1, %2"
2121 [(set_attr "conds" "set")]
2124 (define_insn "*andsi_notsi_si_compare0_scratch"
2125 [(set (reg:CC_NOOV CC_REGNUM)
2127 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2128 (match_operand:SI 1 "s_register_operand" "r"))
2130 (clobber (match_scratch:SI 0 "=r"))]
2132 "bic%?s\\t%0, %1, %2"
2133 [(set_attr "conds" "set")]
2136 (define_insn "iordi3"
2137 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2138 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2139 (match_operand:DI 2 "s_register_operand" "r,r")))]
2140 "TARGET_ARM && ! TARGET_IWMMXT"
2142 [(set_attr "length" "8")
2143 (set_attr "predicable" "yes")]
2146 (define_insn "*iordi_zesidi_di"
2147 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2148 (ior:DI (zero_extend:DI
2149 (match_operand:SI 2 "s_register_operand" "r,r"))
2150 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2153 orr%?\\t%Q0, %Q1, %2
2155 [(set_attr "length" "4,8")
2156 (set_attr "predicable" "yes")]
2159 (define_insn "*iordi_sesidi_di"
2160 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2161 (ior:DI (sign_extend:DI
2162 (match_operand:SI 2 "s_register_operand" "r,r"))
2163 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2166 [(set_attr "length" "8")
2167 (set_attr "predicable" "yes")]
2170 (define_expand "iorsi3"
2171 [(set (match_operand:SI 0 "s_register_operand" "")
2172 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2173 (match_operand:SI 2 "reg_or_int_operand" "")))]
2176 if (GET_CODE (operands[2]) == CONST_INT)
2180 arm_split_constant (IOR, SImode, NULL_RTX,
2181 INTVAL (operands[2]), operands[0], operands[1],
2182 optimize && !no_new_pseudos);
2185 else /* TARGET_THUMB */
2186 operands [2] = force_reg (SImode, operands [2]);
2191 (define_insn_and_split "*arm_iorsi3"
2192 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2193 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2194 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2200 && GET_CODE (operands[2]) == CONST_INT
2201 && !const_ok_for_arm (INTVAL (operands[2]))"
2202 [(clobber (const_int 0))]
2204 arm_split_constant (IOR, SImode, curr_insn,
2205 INTVAL (operands[2]), operands[0], operands[1], 0);
2208 [(set_attr "length" "4,16")
2209 (set_attr "predicable" "yes")]
2212 (define_insn "*thumb_iorsi3"
2213 [(set (match_operand:SI 0 "register_operand" "=l")
2214 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2215 (match_operand:SI 2 "register_operand" "l")))]
2218 [(set_attr "length" "2")]
2222 [(match_scratch:SI 3 "r")
2223 (set (match_operand:SI 0 "arm_general_register_operand" "")
2224 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2225 (match_operand:SI 2 "const_int_operand" "")))]
2227 && !const_ok_for_arm (INTVAL (operands[2]))
2228 && const_ok_for_arm (~INTVAL (operands[2]))"
2229 [(set (match_dup 3) (match_dup 2))
2230 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2234 (define_insn "*iorsi3_compare0"
2235 [(set (reg:CC_NOOV CC_REGNUM)
2236 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2237 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2239 (set (match_operand:SI 0 "s_register_operand" "=r")
2240 (ior:SI (match_dup 1) (match_dup 2)))]
2242 "orr%?s\\t%0, %1, %2"
2243 [(set_attr "conds" "set")]
2246 (define_insn "*iorsi3_compare0_scratch"
2247 [(set (reg:CC_NOOV CC_REGNUM)
2248 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2249 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2251 (clobber (match_scratch:SI 0 "=r"))]
2253 "orr%?s\\t%0, %1, %2"
2254 [(set_attr "conds" "set")]
2257 (define_insn "xordi3"
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2260 (match_operand:DI 2 "s_register_operand" "r,r")))]
2261 "TARGET_ARM && !TARGET_IWMMXT"
2263 [(set_attr "length" "8")
2264 (set_attr "predicable" "yes")]
2267 (define_insn "*xordi_zesidi_di"
2268 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269 (xor:DI (zero_extend:DI
2270 (match_operand:SI 2 "s_register_operand" "r,r"))
2271 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2274 eor%?\\t%Q0, %Q1, %2
2276 [(set_attr "length" "4,8")
2277 (set_attr "predicable" "yes")]
2280 (define_insn "*xordi_sesidi_di"
2281 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2282 (xor:DI (sign_extend:DI
2283 (match_operand:SI 2 "s_register_operand" "r,r"))
2284 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2287 [(set_attr "length" "8")
2288 (set_attr "predicable" "yes")]
2291 (define_expand "xorsi3"
2292 [(set (match_operand:SI 0 "s_register_operand" "")
2293 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2294 (match_operand:SI 2 "arm_rhs_operand" "")))]
2297 if (GET_CODE (operands[2]) == CONST_INT)
2298 operands[2] = force_reg (SImode, operands[2]);
2302 (define_insn "*arm_xorsi3"
2303 [(set (match_operand:SI 0 "s_register_operand" "=r")
2304 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2305 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2307 "eor%?\\t%0, %1, %2"
2308 [(set_attr "predicable" "yes")]
2311 (define_insn "*thumb_xorsi3"
2312 [(set (match_operand:SI 0 "register_operand" "=l")
2313 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2314 (match_operand:SI 2 "register_operand" "l")))]
2317 [(set_attr "length" "2")]
2320 (define_insn "*xorsi3_compare0"
2321 [(set (reg:CC_NOOV CC_REGNUM)
2322 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2323 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2325 (set (match_operand:SI 0 "s_register_operand" "=r")
2326 (xor:SI (match_dup 1) (match_dup 2)))]
2328 "eor%?s\\t%0, %1, %2"
2329 [(set_attr "conds" "set")]
2332 (define_insn "*xorsi3_compare0_scratch"
2333 [(set (reg:CC_NOOV CC_REGNUM)
2334 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2335 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2339 [(set_attr "conds" "set")]
2342 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2343 ; (NOT D) we can sometimes merge the final NOT into one of the following
2347 [(set (match_operand:SI 0 "s_register_operand" "")
2348 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2349 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2350 (match_operand:SI 3 "arm_rhs_operand" "")))
2351 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2353 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2354 (not:SI (match_dup 3))))
2355 (set (match_dup 0) (not:SI (match_dup 4)))]
2359 (define_insn "*andsi_iorsi3_notsi"
2360 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2361 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2362 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2363 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2365 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2366 [(set_attr "length" "8")
2367 (set_attr "predicable" "yes")]
2371 [(set (match_operand:SI 0 "s_register_operand" "")
2372 (match_operator:SI 1 "logical_binary_operator"
2373 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2374 (match_operand:SI 3 "const_int_operand" "")
2375 (match_operand:SI 4 "const_int_operand" ""))
2376 (match_operator:SI 9 "logical_binary_operator"
2377 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2378 (match_operand:SI 6 "const_int_operand" ""))
2379 (match_operand:SI 7 "s_register_operand" "")])]))
2380 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2382 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2383 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2386 [(ashift:SI (match_dup 2) (match_dup 4))
2390 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2393 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2397 [(set (match_operand:SI 0 "s_register_operand" "")
2398 (match_operator:SI 1 "logical_binary_operator"
2399 [(match_operator:SI 9 "logical_binary_operator"
2400 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2401 (match_operand:SI 6 "const_int_operand" ""))
2402 (match_operand:SI 7 "s_register_operand" "")])
2403 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2404 (match_operand:SI 3 "const_int_operand" "")
2405 (match_operand:SI 4 "const_int_operand" ""))]))
2406 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2408 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2409 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2412 [(ashift:SI (match_dup 2) (match_dup 4))
2416 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2419 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2423 [(set (match_operand:SI 0 "s_register_operand" "")
2424 (match_operator:SI 1 "logical_binary_operator"
2425 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2426 (match_operand:SI 3 "const_int_operand" "")
2427 (match_operand:SI 4 "const_int_operand" ""))
2428 (match_operator:SI 9 "logical_binary_operator"
2429 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2430 (match_operand:SI 6 "const_int_operand" ""))
2431 (match_operand:SI 7 "s_register_operand" "")])]))
2432 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2434 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2435 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2438 [(ashift:SI (match_dup 2) (match_dup 4))
2442 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2445 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2449 [(set (match_operand:SI 0 "s_register_operand" "")
2450 (match_operator:SI 1 "logical_binary_operator"
2451 [(match_operator:SI 9 "logical_binary_operator"
2452 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2453 (match_operand:SI 6 "const_int_operand" ""))
2454 (match_operand:SI 7 "s_register_operand" "")])
2455 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2456 (match_operand:SI 3 "const_int_operand" "")
2457 (match_operand:SI 4 "const_int_operand" ""))]))
2458 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2460 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2461 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2464 [(ashift:SI (match_dup 2) (match_dup 4))
2468 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2471 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2475 ;; Minimum and maximum insns
2477 (define_expand "smaxsi3"
2479 (set (match_operand:SI 0 "s_register_operand" "")
2480 (smax:SI (match_operand:SI 1 "s_register_operand" "")
2481 (match_operand:SI 2 "arm_rhs_operand" "")))
2482 (clobber (reg:CC CC_REGNUM))])]
2485 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2487 /* No need for a clobber of the condition code register here. */
2488 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2489 gen_rtx_SMAX (SImode, operands[1],
2495 (define_insn "*smax_0"
2496 [(set (match_operand:SI 0 "s_register_operand" "=r")
2497 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2500 "bic%?\\t%0, %1, %1, asr #31"
2501 [(set_attr "predicable" "yes")]
2504 (define_insn "*smax_m1"
2505 [(set (match_operand:SI 0 "s_register_operand" "=r")
2506 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2509 "orr%?\\t%0, %1, %1, asr #31"
2510 [(set_attr "predicable" "yes")]
2513 (define_insn "*smax_insn"
2514 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2515 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2516 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2517 (clobber (reg:CC CC_REGNUM))]
2520 cmp\\t%1, %2\;movlt\\t%0, %2
2521 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2522 [(set_attr "conds" "clob")
2523 (set_attr "length" "8,12")]
2526 (define_expand "sminsi3"
2528 (set (match_operand:SI 0 "s_register_operand" "")
2529 (smin:SI (match_operand:SI 1 "s_register_operand" "")
2530 (match_operand:SI 2 "arm_rhs_operand" "")))
2531 (clobber (reg:CC CC_REGNUM))])]
2534 if (operands[2] == const0_rtx)
2536 /* No need for a clobber of the condition code register here. */
2537 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2538 gen_rtx_SMIN (SImode, operands[1],
2544 (define_insn "*smin_0"
2545 [(set (match_operand:SI 0 "s_register_operand" "=r")
2546 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2549 "and%?\\t%0, %1, %1, asr #31"
2550 [(set_attr "predicable" "yes")]
2553 (define_insn "*smin_insn"
2554 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2555 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2556 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2557 (clobber (reg:CC CC_REGNUM))]
2560 cmp\\t%1, %2\;movge\\t%0, %2
2561 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2562 [(set_attr "conds" "clob")
2563 (set_attr "length" "8,12")]
2566 (define_insn "umaxsi3"
2567 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2568 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2569 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2570 (clobber (reg:CC CC_REGNUM))]
2573 cmp\\t%1, %2\;movcc\\t%0, %2
2574 cmp\\t%1, %2\;movcs\\t%0, %1
2575 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2576 [(set_attr "conds" "clob")
2577 (set_attr "length" "8,8,12")]
2580 (define_insn "uminsi3"
2581 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2582 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2583 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2584 (clobber (reg:CC CC_REGNUM))]
2587 cmp\\t%1, %2\;movcs\\t%0, %2
2588 cmp\\t%1, %2\;movcc\\t%0, %1
2589 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2590 [(set_attr "conds" "clob")
2591 (set_attr "length" "8,8,12")]
2594 (define_insn "*store_minmaxsi"
2595 [(set (match_operand:SI 0 "memory_operand" "=m")
2596 (match_operator:SI 3 "minmax_operator"
2597 [(match_operand:SI 1 "s_register_operand" "r")
2598 (match_operand:SI 2 "s_register_operand" "r")]))
2599 (clobber (reg:CC CC_REGNUM))]
2602 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2603 operands[1], operands[2]);
2604 output_asm_insn (\"cmp\\t%1, %2\", operands);
2605 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2606 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2609 [(set_attr "conds" "clob")
2610 (set_attr "length" "12")
2611 (set_attr "type" "store1")]
2614 ; Reject the frame pointer in operand[1], since reloading this after
2615 ; it has been eliminated can cause carnage.
2616 (define_insn "*minmax_arithsi"
2617 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2618 (match_operator:SI 4 "shiftable_operator"
2619 [(match_operator:SI 5 "minmax_operator"
2620 [(match_operand:SI 2 "s_register_operand" "r,r")
2621 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2622 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2623 (clobber (reg:CC CC_REGNUM))]
2624 "TARGET_ARM && !arm_eliminable_register (operands[1])"
2627 enum rtx_code code = GET_CODE (operands[4]);
2629 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2630 operands[2], operands[3]);
2631 output_asm_insn (\"cmp\\t%2, %3\", operands);
2632 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2633 if (which_alternative != 0 || operands[3] != const0_rtx
2634 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2635 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2638 [(set_attr "conds" "clob")
2639 (set_attr "length" "12")]
2643 ;; Shift and rotation insns
2645 (define_expand "ashldi3"
2646 [(set (match_operand:DI 0 "s_register_operand" "")
2647 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2648 (match_operand:SI 2 "reg_or_int_operand" "")))]
2651 if (GET_CODE (operands[2]) == CONST_INT)
2653 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2655 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2658 /* Ideally we shouldn't fail here if we could know that operands[1]
2659 ends up already living in an iwmmxt register. Otherwise it's
2660 cheaper to have the alternate code being generated than moving
2661 values to iwmmxt regs and back. */
2664 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2669 (define_insn "arm_ashldi3_1bit"
2670 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2671 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2673 (clobber (reg:CC CC_REGNUM))]
2675 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2676 [(set_attr "conds" "clob")
2677 (set_attr "length" "8")]
2680 (define_expand "ashlsi3"
2681 [(set (match_operand:SI 0 "s_register_operand" "")
2682 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2683 (match_operand:SI 2 "arm_rhs_operand" "")))]
2686 if (GET_CODE (operands[2]) == CONST_INT
2687 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2689 emit_insn (gen_movsi (operands[0], const0_rtx));
2695 (define_insn "*thumb_ashlsi3"
2696 [(set (match_operand:SI 0 "register_operand" "=l,l")
2697 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2698 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2701 [(set_attr "length" "2")]
2704 (define_expand "ashrdi3"
2705 [(set (match_operand:DI 0 "s_register_operand" "")
2706 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2707 (match_operand:SI 2 "reg_or_int_operand" "")))]
2710 if (GET_CODE (operands[2]) == CONST_INT)
2712 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2714 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2717 /* Ideally we shouldn't fail here if we could know that operands[1]
2718 ends up already living in an iwmmxt register. Otherwise it's
2719 cheaper to have the alternate code being generated than moving
2720 values to iwmmxt regs and back. */
2723 else if (!TARGET_REALLY_IWMMXT)
2728 (define_insn "arm_ashrdi3_1bit"
2729 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2730 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2732 (clobber (reg:CC CC_REGNUM))]
2734 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2735 [(set_attr "conds" "clob")
2736 (set_attr "length" "8")]
2739 (define_expand "ashrsi3"
2740 [(set (match_operand:SI 0 "s_register_operand" "")
2741 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2742 (match_operand:SI 2 "arm_rhs_operand" "")))]
2745 if (GET_CODE (operands[2]) == CONST_INT
2746 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2747 operands[2] = GEN_INT (31);
2751 (define_insn "*thumb_ashrsi3"
2752 [(set (match_operand:SI 0 "register_operand" "=l,l")
2753 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2754 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2757 [(set_attr "length" "2")]
2760 (define_expand "lshrdi3"
2761 [(set (match_operand:DI 0 "s_register_operand" "")
2762 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2763 (match_operand:SI 2 "reg_or_int_operand" "")))]
2766 if (GET_CODE (operands[2]) == CONST_INT)
2768 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2770 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2773 /* Ideally we shouldn't fail here if we could know that operands[1]
2774 ends up already living in an iwmmxt register. Otherwise it's
2775 cheaper to have the alternate code being generated than moving
2776 values to iwmmxt regs and back. */
2779 else if (!TARGET_REALLY_IWMMXT)
2784 (define_insn "arm_lshrdi3_1bit"
2785 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2786 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2788 (clobber (reg:CC CC_REGNUM))]
2790 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2791 [(set_attr "conds" "clob")
2792 (set_attr "length" "8")]
2795 (define_expand "lshrsi3"
2796 [(set (match_operand:SI 0 "s_register_operand" "")
2797 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2798 (match_operand:SI 2 "arm_rhs_operand" "")))]
2801 if (GET_CODE (operands[2]) == CONST_INT
2802 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2804 emit_insn (gen_movsi (operands[0], const0_rtx));
2810 (define_insn "*thumb_lshrsi3"
2811 [(set (match_operand:SI 0 "register_operand" "=l,l")
2812 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2813 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2816 [(set_attr "length" "2")]
2819 (define_expand "rotlsi3"
2820 [(set (match_operand:SI 0 "s_register_operand" "")
2821 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2822 (match_operand:SI 2 "reg_or_int_operand" "")))]
2825 if (GET_CODE (operands[2]) == CONST_INT)
2826 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2829 rtx reg = gen_reg_rtx (SImode);
2830 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2836 (define_expand "rotrsi3"
2837 [(set (match_operand:SI 0 "s_register_operand" "")
2838 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2839 (match_operand:SI 2 "arm_rhs_operand" "")))]
2844 if (GET_CODE (operands[2]) == CONST_INT
2845 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2846 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2848 else /* TARGET_THUMB */
2850 if (GET_CODE (operands [2]) == CONST_INT)
2851 operands [2] = force_reg (SImode, operands[2]);
2856 (define_insn "*thumb_rotrsi3"
2857 [(set (match_operand:SI 0 "register_operand" "=l")
2858 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2859 (match_operand:SI 2 "register_operand" "l")))]
2862 [(set_attr "length" "2")]
2865 (define_insn "*arm_shiftsi3"
2866 [(set (match_operand:SI 0 "s_register_operand" "=r")
2867 (match_operator:SI 3 "shift_operator"
2868 [(match_operand:SI 1 "s_register_operand" "r")
2869 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2872 [(set_attr "predicable" "yes")
2873 (set_attr "shift" "1")
2874 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2875 (const_string "alu_shift")
2876 (const_string "alu_shift_reg")))]
2879 (define_insn "*shiftsi3_compare0"
2880 [(set (reg:CC_NOOV CC_REGNUM)
2881 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2882 [(match_operand:SI 1 "s_register_operand" "r")
2883 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2885 (set (match_operand:SI 0 "s_register_operand" "=r")
2886 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2888 "mov%?s\\t%0, %1%S3"
2889 [(set_attr "conds" "set")
2890 (set_attr "shift" "1")
2891 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2892 (const_string "alu_shift")
2893 (const_string "alu_shift_reg")))]
2896 (define_insn "*shiftsi3_compare0_scratch"
2897 [(set (reg:CC_NOOV CC_REGNUM)
2898 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2899 [(match_operand:SI 1 "s_register_operand" "r")
2900 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2902 (clobber (match_scratch:SI 0 "=r"))]
2904 "mov%?s\\t%0, %1%S3"
2905 [(set_attr "conds" "set")
2906 (set_attr "shift" "1")]
2909 (define_insn "*notsi_shiftsi"
2910 [(set (match_operand:SI 0 "s_register_operand" "=r")
2911 (not:SI (match_operator:SI 3 "shift_operator"
2912 [(match_operand:SI 1 "s_register_operand" "r")
2913 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2916 [(set_attr "predicable" "yes")
2917 (set_attr "shift" "1")
2918 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2919 (const_string "alu_shift")
2920 (const_string "alu_shift_reg")))]
2923 (define_insn "*notsi_shiftsi_compare0"
2924 [(set (reg:CC_NOOV CC_REGNUM)
2925 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2926 [(match_operand:SI 1 "s_register_operand" "r")
2927 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2929 (set (match_operand:SI 0 "s_register_operand" "=r")
2930 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2932 "mvn%?s\\t%0, %1%S3"
2933 [(set_attr "conds" "set")
2934 (set_attr "shift" "1")
2935 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2936 (const_string "alu_shift")
2937 (const_string "alu_shift_reg")))]
2940 (define_insn "*not_shiftsi_compare0_scratch"
2941 [(set (reg:CC_NOOV CC_REGNUM)
2942 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2943 [(match_operand:SI 1 "s_register_operand" "r")
2944 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2946 (clobber (match_scratch:SI 0 "=r"))]
2948 "mvn%?s\\t%0, %1%S3"
2949 [(set_attr "conds" "set")
2950 (set_attr "shift" "1")
2951 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2952 (const_string "alu_shift")
2953 (const_string "alu_shift_reg")))]
2956 ;; We don't really have extzv, but defining this using shifts helps
2957 ;; to reduce register pressure later on.
2959 (define_expand "extzv"
2961 (ashift:SI (match_operand:SI 1 "register_operand" "")
2962 (match_operand:SI 2 "const_int_operand" "")))
2963 (set (match_operand:SI 0 "register_operand" "")
2964 (lshiftrt:SI (match_dup 4)
2965 (match_operand:SI 3 "const_int_operand" "")))]
2969 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2970 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2972 operands[3] = GEN_INT (rshift);
2976 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2980 operands[2] = GEN_INT (lshift);
2981 operands[4] = gen_reg_rtx (SImode);
2986 ;; Unary arithmetic insns
2988 (define_expand "negdi2"
2990 [(set (match_operand:DI 0 "s_register_operand" "")
2991 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2992 (clobber (reg:CC CC_REGNUM))])]
2997 if (GET_CODE (operands[1]) != REG)
2998 operands[1] = force_reg (SImode, operands[1]);
3003 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3004 ;; The second alternative is to allow the common case of a *full* overlap.
3005 (define_insn "*arm_negdi2"
3006 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
3007 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
3008 (clobber (reg:CC CC_REGNUM))]
3010 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3011 [(set_attr "conds" "clob")
3012 (set_attr "length" "8")]
3015 (define_insn "*thumb_negdi2"
3016 [(set (match_operand:DI 0 "register_operand" "=&l")
3017 (neg:DI (match_operand:DI 1 "register_operand" "l")))
3018 (clobber (reg:CC CC_REGNUM))]
3020 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3021 [(set_attr "length" "6")]
3024 (define_expand "negsi2"
3025 [(set (match_operand:SI 0 "s_register_operand" "")
3026 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3031 (define_insn "*arm_negsi2"
3032 [(set (match_operand:SI 0 "s_register_operand" "=r")
3033 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3035 "rsb%?\\t%0, %1, #0"
3036 [(set_attr "predicable" "yes")]
3039 (define_insn "*thumb_negsi2"
3040 [(set (match_operand:SI 0 "register_operand" "=l")
3041 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3044 [(set_attr "length" "2")]
3047 (define_expand "negsf2"
3048 [(set (match_operand:SF 0 "s_register_operand" "")
3049 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3050 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3054 (define_expand "negdf2"
3055 [(set (match_operand:DF 0 "s_register_operand" "")
3056 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3057 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3060 ;; abssi2 doesn't really clobber the condition codes if a different register
3061 ;; is being set. To keep things simple, assume during rtl manipulations that
3062 ;; it does, but tell the final scan operator the truth. Similarly for
3065 (define_expand "abssi2"
3067 [(set (match_operand:SI 0 "s_register_operand" "")
3068 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3069 (clobber (match_dup 2))])]
3073 operands[2] = gen_rtx_SCRATCH (SImode);
3075 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
3078 (define_insn "*arm_abssi2"
3079 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3080 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3081 (clobber (reg:CC CC_REGNUM))]
3084 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3085 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3086 [(set_attr "conds" "clob,*")
3087 (set_attr "shift" "1")
3088 ;; predicable can't be set based on the variant, so left as no
3089 (set_attr "length" "8")]
3092 (define_insn_and_split "*thumb_abssi2"
3093 [(set (match_operand:SI 0 "s_register_operand" "=l")
3094 (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
3095 (clobber (match_scratch:SI 2 "=&l"))]
3098 "TARGET_THUMB && reload_completed"
3099 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3100 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
3101 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3103 [(set_attr "length" "6")]
3106 (define_insn "*arm_neg_abssi2"
3107 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3108 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3109 (clobber (reg:CC CC_REGNUM))]
3112 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3113 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3114 [(set_attr "conds" "clob,*")
3115 (set_attr "shift" "1")
3116 ;; predicable can't be set based on the variant, so left as no
3117 (set_attr "length" "8")]
3120 (define_insn_and_split "*thumb_neg_abssi2"
3121 [(set (match_operand:SI 0 "s_register_operand" "=l")
3122 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
3123 (clobber (match_scratch:SI 2 "=&l"))]
3126 "TARGET_THUMB && reload_completed"
3127 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
3128 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
3129 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
3131 [(set_attr "length" "6")]
3134 (define_expand "abssf2"
3135 [(set (match_operand:SF 0 "s_register_operand" "")
3136 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3137 "TARGET_ARM && TARGET_HARD_FLOAT"
3140 (define_expand "absdf2"
3141 [(set (match_operand:DF 0 "s_register_operand" "")
3142 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3143 "TARGET_ARM && TARGET_HARD_FLOAT"
3146 (define_expand "sqrtsf2"
3147 [(set (match_operand:SF 0 "s_register_operand" "")
3148 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3149 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3152 (define_expand "sqrtdf2"
3153 [(set (match_operand:DF 0 "s_register_operand" "")
3154 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3155 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3158 (define_insn_and_split "one_cmpldi2"
3159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3160 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3163 "TARGET_ARM && reload_completed"
3164 [(set (match_dup 0) (not:SI (match_dup 1)))
3165 (set (match_dup 2) (not:SI (match_dup 3)))]
3168 operands[2] = gen_highpart (SImode, operands[0]);
3169 operands[0] = gen_lowpart (SImode, operands[0]);
3170 operands[3] = gen_highpart (SImode, operands[1]);
3171 operands[1] = gen_lowpart (SImode, operands[1]);
3173 [(set_attr "length" "8")
3174 (set_attr "predicable" "yes")]
3177 (define_expand "one_cmplsi2"
3178 [(set (match_operand:SI 0 "s_register_operand" "")
3179 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3184 (define_insn "*arm_one_cmplsi2"
3185 [(set (match_operand:SI 0 "s_register_operand" "=r")
3186 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3189 [(set_attr "predicable" "yes")]
3192 (define_insn "*thumb_one_cmplsi2"
3193 [(set (match_operand:SI 0 "register_operand" "=l")
3194 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3197 [(set_attr "length" "2")]
3200 (define_insn "*notsi_compare0"
3201 [(set (reg:CC_NOOV CC_REGNUM)
3202 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3204 (set (match_operand:SI 0 "s_register_operand" "=r")
3205 (not:SI (match_dup 1)))]
3208 [(set_attr "conds" "set")]
3211 (define_insn "*notsi_compare0_scratch"
3212 [(set (reg:CC_NOOV CC_REGNUM)
3213 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3215 (clobber (match_scratch:SI 0 "=r"))]
3218 [(set_attr "conds" "set")]
3221 ;; Fixed <--> Floating conversion insns
3223 (define_expand "floatsisf2"
3224 [(set (match_operand:SF 0 "s_register_operand" "")
3225 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3226 "TARGET_ARM && TARGET_HARD_FLOAT"
3228 if (TARGET_MAVERICK)
3230 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3235 (define_expand "floatsidf2"
3236 [(set (match_operand:DF 0 "s_register_operand" "")
3237 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3238 "TARGET_ARM && TARGET_HARD_FLOAT"
3240 if (TARGET_MAVERICK)
3242 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3247 (define_expand "fix_truncsfsi2"
3248 [(set (match_operand:SI 0 "s_register_operand" "")
3249 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3250 "TARGET_ARM && TARGET_HARD_FLOAT"
3252 if (TARGET_MAVERICK)
3254 if (!cirrus_fp_register (operands[0], SImode))
3255 operands[0] = force_reg (SImode, operands[0]);
3256 if (!cirrus_fp_register (operands[1], SFmode))
3257 operands[1] = force_reg (SFmode, operands[0]);
3258 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3263 (define_expand "fix_truncdfsi2"
3264 [(set (match_operand:SI 0 "s_register_operand" "")
3265 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3266 "TARGET_ARM && TARGET_HARD_FLOAT"
3268 if (TARGET_MAVERICK)
3270 if (!cirrus_fp_register (operands[1], DFmode))
3271 operands[1] = force_reg (DFmode, operands[0]);
3272 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3279 (define_expand "truncdfsf2"
3280 [(set (match_operand:SF 0 "s_register_operand" "")
3282 (match_operand:DF 1 "s_register_operand" "")))]
3283 "TARGET_ARM && TARGET_HARD_FLOAT"
3287 ;; Zero and sign extension instructions.
3289 (define_insn "zero_extendsidi2"
3290 [(set (match_operand:DI 0 "s_register_operand" "=r")
3291 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3294 if (REGNO (operands[1])
3295 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3296 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3297 return \"mov%?\\t%R0, #0\";
3299 [(set_attr "length" "8")
3300 (set_attr "predicable" "yes")]
3303 (define_insn "zero_extendqidi2"
3304 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3305 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3308 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3309 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3310 [(set_attr "length" "8")
3311 (set_attr "predicable" "yes")
3312 (set_attr "type" "*,load_byte")
3313 (set_attr "pool_range" "*,4092")
3314 (set_attr "neg_pool_range" "*,4084")]
3317 (define_insn "extendsidi2"
3318 [(set (match_operand:DI 0 "s_register_operand" "=r")
3319 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3322 if (REGNO (operands[1])
3323 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3324 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3325 return \"mov%?\\t%R0, %Q0, asr #31\";
3327 [(set_attr "length" "8")
3328 (set_attr "shift" "1")
3329 (set_attr "predicable" "yes")]
3332 (define_expand "zero_extendhisi2"
3334 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3336 (set (match_operand:SI 0 "s_register_operand" "")
3337 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3341 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3343 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3348 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3350 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3354 if (!s_register_operand (operands[1], HImode))
3355 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3359 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3360 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3364 operands[1] = gen_lowpart (SImode, operands[1]);
3365 operands[2] = gen_reg_rtx (SImode);
3369 (define_insn "*thumb_zero_extendhisi2"
3370 [(set (match_operand:SI 0 "register_operand" "=l")
3371 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3372 "TARGET_THUMB && !arm_arch6"
3374 rtx mem = XEXP (operands[1], 0);
3376 if (GET_CODE (mem) == CONST)
3377 mem = XEXP (mem, 0);
3379 if (GET_CODE (mem) == LABEL_REF)
3380 return \"ldr\\t%0, %1\";
3382 if (GET_CODE (mem) == PLUS)
3384 rtx a = XEXP (mem, 0);
3385 rtx b = XEXP (mem, 1);
3387 /* This can happen due to bugs in reload. */
3388 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3391 ops[0] = operands[0];
3394 output_asm_insn (\"mov %0, %1\", ops);
3396 XEXP (mem, 0) = operands[0];
3399 else if ( GET_CODE (a) == LABEL_REF
3400 && GET_CODE (b) == CONST_INT)
3401 return \"ldr\\t%0, %1\";
3404 return \"ldrh\\t%0, %1\";
3406 [(set_attr "length" "4")
3407 (set_attr "type" "load_byte")
3408 (set_attr "pool_range" "60")]
3411 (define_insn "*thumb_zero_extendhisi2_v6"
3412 [(set (match_operand:SI 0 "register_operand" "=l,l")
3413 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3414 "TARGET_THUMB && arm_arch6"
3418 if (which_alternative == 0)
3419 return \"uxth\\t%0, %1\";
3421 mem = XEXP (operands[1], 0);
3423 if (GET_CODE (mem) == CONST)
3424 mem = XEXP (mem, 0);
3426 if (GET_CODE (mem) == LABEL_REF)
3427 return \"ldr\\t%0, %1\";
3429 if (GET_CODE (mem) == PLUS)
3431 rtx a = XEXP (mem, 0);
3432 rtx b = XEXP (mem, 1);
3434 /* This can happen due to bugs in reload. */
3435 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3438 ops[0] = operands[0];
3441 output_asm_insn (\"mov %0, %1\", ops);
3443 XEXP (mem, 0) = operands[0];
3446 else if ( GET_CODE (a) == LABEL_REF
3447 && GET_CODE (b) == CONST_INT)
3448 return \"ldr\\t%0, %1\";
3451 return \"ldrh\\t%0, %1\";
3453 [(set_attr "length" "2,4")
3454 (set_attr "type" "alu_shift,load_byte")
3455 (set_attr "pool_range" "*,60")]
3458 (define_insn "*arm_zero_extendhisi2"
3459 [(set (match_operand:SI 0 "s_register_operand" "=r")
3460 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3461 "TARGET_ARM && arm_arch4 && !arm_arch6"
3463 [(set_attr "type" "load_byte")
3464 (set_attr "predicable" "yes")
3465 (set_attr "pool_range" "256")
3466 (set_attr "neg_pool_range" "244")]
3469 (define_insn "*arm_zero_extendhisi2_v6"
3470 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3471 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3472 "TARGET_ARM && arm_arch6"
3476 [(set_attr "type" "alu_shift,load_byte")
3477 (set_attr "predicable" "yes")
3478 (set_attr "pool_range" "*,256")
3479 (set_attr "neg_pool_range" "*,244")]
3482 (define_insn "*arm_zero_extendhisi2addsi"
3483 [(set (match_operand:SI 0 "s_register_operand" "=r")
3484 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3485 (match_operand:SI 2 "s_register_operand" "r")))]
3486 "TARGET_ARM && arm_arch6"
3487 "uxtah%?\\t%0, %2, %1"
3488 [(set_attr "type" "alu_shift")
3489 (set_attr "predicable" "yes")]
3492 (define_expand "zero_extendqisi2"
3493 [(set (match_operand:SI 0 "s_register_operand" "")
3494 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3497 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3501 emit_insn (gen_andsi3 (operands[0],
3502 gen_lowpart (SImode, operands[1]),
3505 else /* TARGET_THUMB */
3507 rtx temp = gen_reg_rtx (SImode);
3510 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3511 operands[1] = gen_lowpart (SImode, operands[1]);
3514 ops[1] = operands[1];
3515 ops[2] = GEN_INT (24);
3517 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3518 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3520 ops[0] = operands[0];
3522 ops[2] = GEN_INT (24);
3524 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3525 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3532 (define_insn "*thumb_zero_extendqisi2"
3533 [(set (match_operand:SI 0 "register_operand" "=l")
3534 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3535 "TARGET_THUMB && !arm_arch6"
3537 [(set_attr "length" "2")
3538 (set_attr "type" "load_byte")
3539 (set_attr "pool_range" "32")]
3542 (define_insn "*thumb_zero_extendqisi2_v6"
3543 [(set (match_operand:SI 0 "register_operand" "=l,l")
3544 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3545 "TARGET_THUMB && arm_arch6"
3549 [(set_attr "length" "2,2")
3550 (set_attr "type" "alu_shift,load_byte")
3551 (set_attr "pool_range" "*,32")]
3554 (define_insn "*arm_zero_extendqisi2"
3555 [(set (match_operand:SI 0 "s_register_operand" "=r")
3556 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3557 "TARGET_ARM && !arm_arch6"
3558 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3559 [(set_attr "type" "load_byte")
3560 (set_attr "predicable" "yes")
3561 (set_attr "pool_range" "4096")
3562 (set_attr "neg_pool_range" "4084")]
3565 (define_insn "*arm_zero_extendqisi2_v6"
3566 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3567 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3568 "TARGET_ARM && arm_arch6"
3571 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3572 [(set_attr "type" "alu_shift,load_byte")
3573 (set_attr "predicable" "yes")
3574 (set_attr "pool_range" "*,4096")
3575 (set_attr "neg_pool_range" "*,4084")]
3578 (define_insn "*arm_zero_extendqisi2addsi"
3579 [(set (match_operand:SI 0 "s_register_operand" "=r")
3580 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3581 (match_operand:SI 2 "s_register_operand" "r")))]
3582 "TARGET_ARM && arm_arch6"
3583 "uxtab%?\\t%0, %2, %1"
3584 [(set_attr "predicable" "yes")
3585 (set_attr "type" "alu_shift")]
3589 [(set (match_operand:SI 0 "s_register_operand" "")
3590 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3591 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3592 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3593 [(set (match_dup 2) (match_dup 1))
3594 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3599 [(set (match_operand:SI 0 "s_register_operand" "")
3600 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3601 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3602 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3603 [(set (match_dup 2) (match_dup 1))
3604 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3608 (define_insn "*compareqi_eq0"
3609 [(set (reg:CC_Z CC_REGNUM)
3610 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3614 [(set_attr "conds" "set")]
3617 (define_expand "extendhisi2"
3619 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3621 (set (match_operand:SI 0 "s_register_operand" "")
3622 (ashiftrt:SI (match_dup 2)
3627 if (GET_CODE (operands[1]) == MEM)
3631 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3636 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3637 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3642 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3644 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3648 if (!s_register_operand (operands[1], HImode))
3649 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3654 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3656 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3657 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3662 operands[1] = gen_lowpart (SImode, operands[1]);
3663 operands[2] = gen_reg_rtx (SImode);
3667 (define_insn "thumb_extendhisi2"
3668 [(set (match_operand:SI 0 "register_operand" "=l")
3669 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3670 (clobber (match_scratch:SI 2 "=&l"))]
3671 "TARGET_THUMB && !arm_arch6"
3675 rtx mem = XEXP (operands[1], 0);
3677 /* This code used to try to use 'V', and fix the address only if it was
3678 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3679 range of QImode offsets, and offsettable_address_p does a QImode
3682 if (GET_CODE (mem) == CONST)
3683 mem = XEXP (mem, 0);
3685 if (GET_CODE (mem) == LABEL_REF)
3686 return \"ldr\\t%0, %1\";
3688 if (GET_CODE (mem) == PLUS)
3690 rtx a = XEXP (mem, 0);
3691 rtx b = XEXP (mem, 1);
3693 if (GET_CODE (a) == LABEL_REF
3694 && GET_CODE (b) == CONST_INT)
3695 return \"ldr\\t%0, %1\";
3697 if (GET_CODE (b) == REG)
3698 return \"ldrsh\\t%0, %1\";
3706 ops[2] = const0_rtx;
3709 gcc_assert (GET_CODE (ops[1]) == REG);
3711 ops[0] = operands[0];
3712 ops[3] = operands[2];
3713 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3716 [(set_attr "length" "4")
3717 (set_attr "type" "load_byte")
3718 (set_attr "pool_range" "1020")]
3721 ;; We used to have an early-clobber on the scratch register here.
3722 ;; However, there's a bug somewhere in reload which means that this
3723 ;; can be partially ignored during spill allocation if the memory
3724 ;; address also needs reloading; this causes us to die later on when
3725 ;; we try to verify the operands. Fortunately, we don't really need
3726 ;; the early-clobber: we can always use operand 0 if operand 2
3727 ;; overlaps the address.
3728 (define_insn "*thumb_extendhisi2_insn_v6"
3729 [(set (match_operand:SI 0 "register_operand" "=l,l")
3730 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3731 (clobber (match_scratch:SI 2 "=X,l"))]
3732 "TARGET_THUMB && arm_arch6"
3738 if (which_alternative == 0)
3739 return \"sxth\\t%0, %1\";
3741 mem = XEXP (operands[1], 0);
3743 /* This code used to try to use 'V', and fix the address only if it was
3744 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3745 range of QImode offsets, and offsettable_address_p does a QImode
3748 if (GET_CODE (mem) == CONST)
3749 mem = XEXP (mem, 0);
3751 if (GET_CODE (mem) == LABEL_REF)
3752 return \"ldr\\t%0, %1\";
3754 if (GET_CODE (mem) == PLUS)
3756 rtx a = XEXP (mem, 0);
3757 rtx b = XEXP (mem, 1);
3759 if (GET_CODE (a) == LABEL_REF
3760 && GET_CODE (b) == CONST_INT)
3761 return \"ldr\\t%0, %1\";
3763 if (GET_CODE (b) == REG)
3764 return \"ldrsh\\t%0, %1\";
3772 ops[2] = const0_rtx;
3775 gcc_assert (GET_CODE (ops[1]) == REG);
3777 ops[0] = operands[0];
3778 if (reg_mentioned_p (operands[2], ops[1]))
3781 ops[3] = operands[2];
3782 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3785 [(set_attr "length" "2,4")
3786 (set_attr "type" "alu_shift,load_byte")
3787 (set_attr "pool_range" "*,1020")]
3790 (define_expand "extendhisi2_mem"
3791 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3793 (zero_extend:SI (match_dup 7)))
3794 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3795 (set (match_operand:SI 0 "" "")
3796 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3801 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3803 mem1 = change_address (operands[1], QImode, addr);
3804 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3805 operands[0] = gen_lowpart (SImode, operands[0]);
3807 operands[2] = gen_reg_rtx (SImode);
3808 operands[3] = gen_reg_rtx (SImode);
3809 operands[6] = gen_reg_rtx (SImode);
3812 if (BYTES_BIG_ENDIAN)
3814 operands[4] = operands[2];
3815 operands[5] = operands[3];
3819 operands[4] = operands[3];
3820 operands[5] = operands[2];
3825 (define_insn "*arm_extendhisi2"
3826 [(set (match_operand:SI 0 "s_register_operand" "=r")
3827 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3828 "TARGET_ARM && arm_arch4 && !arm_arch6"
3830 [(set_attr "type" "load_byte")
3831 (set_attr "predicable" "yes")
3832 (set_attr "pool_range" "256")
3833 (set_attr "neg_pool_range" "244")]
3836 (define_insn "*arm_extendhisi2_v6"
3837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3838 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3839 "TARGET_ARM && arm_arch6"
3843 [(set_attr "type" "alu_shift,load_byte")
3844 (set_attr "predicable" "yes")
3845 (set_attr "pool_range" "*,256")
3846 (set_attr "neg_pool_range" "*,244")]
3849 (define_insn "*arm_extendhisi2addsi"
3850 [(set (match_operand:SI 0 "s_register_operand" "=r")
3851 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3852 (match_operand:SI 2 "s_register_operand" "r")))]
3853 "TARGET_ARM && arm_arch6"
3854 "sxtah%?\\t%0, %2, %1"
3857 (define_expand "extendqihi2"
3859 (ashift:SI (match_operand:QI 1 "general_operand" "")
3861 (set (match_operand:HI 0 "s_register_operand" "")
3862 (ashiftrt:SI (match_dup 2)
3867 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3869 emit_insn (gen_rtx_SET (VOIDmode,
3871 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3874 if (!s_register_operand (operands[1], QImode))
3875 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3876 operands[0] = gen_lowpart (SImode, operands[0]);
3877 operands[1] = gen_lowpart (SImode, operands[1]);
3878 operands[2] = gen_reg_rtx (SImode);
3882 (define_insn "*extendqihi_insn"
3883 [(set (match_operand:HI 0 "s_register_operand" "=r")
3884 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3885 "TARGET_ARM && arm_arch4"
3887 [(set_attr "type" "load_byte")
3888 (set_attr "predicable" "yes")
3889 (set_attr "pool_range" "256")
3890 (set_attr "neg_pool_range" "244")]
3893 (define_expand "extendqisi2"
3895 (ashift:SI (match_operand:QI 1 "general_operand" "")
3897 (set (match_operand:SI 0 "s_register_operand" "")
3898 (ashiftrt:SI (match_dup 2)
3903 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3905 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3906 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3910 if (!s_register_operand (operands[1], QImode))
3911 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3915 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3916 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3920 operands[1] = gen_lowpart (SImode, operands[1]);
3921 operands[2] = gen_reg_rtx (SImode);
3925 (define_insn "*arm_extendqisi"
3926 [(set (match_operand:SI 0 "s_register_operand" "=r")
3927 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3928 "TARGET_ARM && arm_arch4 && !arm_arch6"
3930 [(set_attr "type" "load_byte")
3931 (set_attr "predicable" "yes")
3932 (set_attr "pool_range" "256")
3933 (set_attr "neg_pool_range" "244")]
3936 (define_insn "*arm_extendqisi_v6"
3937 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3938 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3939 "TARGET_ARM && arm_arch6"
3943 [(set_attr "type" "alu_shift,load_byte")
3944 (set_attr "predicable" "yes")
3945 (set_attr "pool_range" "*,256")
3946 (set_attr "neg_pool_range" "*,244")]
3949 (define_insn "*arm_extendqisi2addsi"
3950 [(set (match_operand:SI 0 "s_register_operand" "=r")
3951 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3952 (match_operand:SI 2 "s_register_operand" "r")))]
3953 "TARGET_ARM && arm_arch6"
3954 "sxtab%?\\t%0, %2, %1"
3955 [(set_attr "type" "alu_shift")
3956 (set_attr "predicable" "yes")]
3959 (define_insn "*thumb_extendqisi2"
3960 [(set (match_operand:SI 0 "register_operand" "=l,l")
3961 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3962 "TARGET_THUMB && !arm_arch6"
3966 rtx mem = XEXP (operands[1], 0);
3968 if (GET_CODE (mem) == CONST)
3969 mem = XEXP (mem, 0);
3971 if (GET_CODE (mem) == LABEL_REF)
3972 return \"ldr\\t%0, %1\";
3974 if (GET_CODE (mem) == PLUS
3975 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3976 return \"ldr\\t%0, %1\";
3978 if (which_alternative == 0)
3979 return \"ldrsb\\t%0, %1\";
3981 ops[0] = operands[0];
3983 if (GET_CODE (mem) == PLUS)
3985 rtx a = XEXP (mem, 0);
3986 rtx b = XEXP (mem, 1);
3991 if (GET_CODE (a) == REG)
3993 if (GET_CODE (b) == REG)
3994 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3995 else if (REGNO (a) == REGNO (ops[0]))
3997 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3998 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3999 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4002 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4006 gcc_assert (GET_CODE (b) == REG);
4007 if (REGNO (b) == REGNO (ops[0]))
4009 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4010 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4011 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4014 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4017 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4019 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4020 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
4021 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
4026 ops[2] = const0_rtx;
4028 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4032 [(set_attr "length" "2,6")
4033 (set_attr "type" "load_byte,load_byte")
4034 (set_attr "pool_range" "32,32")]
4037 (define_insn "*thumb_extendqisi2_v6"
4038 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4039 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4040 "TARGET_THUMB && arm_arch6"
4046 if (which_alternative == 0)
4047 return \"sxtb\\t%0, %1\";
4049 mem = XEXP (operands[1], 0);
4051 if (GET_CODE (mem) == CONST)
4052 mem = XEXP (mem, 0);
4054 if (GET_CODE (mem) == LABEL_REF)
4055 return \"ldr\\t%0, %1\";
4057 if (GET_CODE (mem) == PLUS
4058 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4059 return \"ldr\\t%0, %1\";
4061 if (which_alternative == 0)
4062 return \"ldrsb\\t%0, %1\";
4064 ops[0] = operands[0];
4066 if (GET_CODE (mem) == PLUS)
4068 rtx a = XEXP (mem, 0);
4069 rtx b = XEXP (mem, 1);
4074 if (GET_CODE (a) == REG)
4076 if (GET_CODE (b) == REG)
4077 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4078 else if (REGNO (a) == REGNO (ops[0]))
4080 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4081 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4084 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4088 gcc_assert (GET_CODE (b) == REG);
4089 if (REGNO (b) == REGNO (ops[0]))
4091 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4092 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4095 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4098 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4100 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4101 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4106 ops[2] = const0_rtx;
4108 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4112 [(set_attr "length" "2,2,4")
4113 (set_attr "type" "alu_shift,load_byte,load_byte")
4114 (set_attr "pool_range" "*,32,32")]
4117 (define_expand "extendsfdf2"
4118 [(set (match_operand:DF 0 "s_register_operand" "")
4119 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4120 "TARGET_ARM && TARGET_HARD_FLOAT"
4124 ;; Move insns (including loads and stores)
4126 ;; XXX Just some ideas about movti.
4127 ;; I don't think these are a good idea on the arm, there just aren't enough
4129 ;;(define_expand "loadti"
4130 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4131 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4134 ;;(define_expand "storeti"
4135 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4136 ;; (match_operand:TI 1 "s_register_operand" ""))]
4139 ;;(define_expand "movti"
4140 ;; [(set (match_operand:TI 0 "general_operand" "")
4141 ;; (match_operand:TI 1 "general_operand" ""))]
4147 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4148 ;; operands[1] = copy_to_reg (operands[1]);
4149 ;; if (GET_CODE (operands[0]) == MEM)
4150 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4151 ;; else if (GET_CODE (operands[1]) == MEM)
4152 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4156 ;; emit_insn (insn);
4160 ;; Recognize garbage generated above.
4163 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4164 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4168 ;; register mem = (which_alternative < 3);
4169 ;; register const char *template;
4171 ;; operands[mem] = XEXP (operands[mem], 0);
4172 ;; switch (which_alternative)
4174 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4175 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4176 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4177 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4178 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4179 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4181 ;; output_asm_insn (template, operands);
4185 (define_expand "movdi"
4186 [(set (match_operand:DI 0 "general_operand" "")
4187 (match_operand:DI 1 "general_operand" ""))]
4190 if (!no_new_pseudos)
4192 if (GET_CODE (operands[0]) != REG)
4193 operands[1] = force_reg (DImode, operands[1]);
4198 (define_insn "*arm_movdi"
4199 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4200 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4202 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4204 && ( register_operand (operands[0], DImode)
4205 || register_operand (operands[1], DImode))"
4207 switch (which_alternative)
4214 return output_move_double (operands);
4217 [(set_attr "length" "8,12,16,8,8")
4218 (set_attr "type" "*,*,*,load2,store2")
4219 (set_attr "pool_range" "*,*,*,1020,*")
4220 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4224 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4225 (match_operand:ANY64 1 "const_double_operand" ""))]
4228 && (arm_const_double_inline_cost (operands[1])
4229 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4232 arm_split_constant (SET, SImode, curr_insn,
4233 INTVAL (gen_lowpart (SImode, operands[1])),
4234 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4235 arm_split_constant (SET, SImode, curr_insn,
4236 INTVAL (gen_highpart_mode (SImode,
4237 GET_MODE (operands[0]),
4239 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4244 ; If optimizing for size, or if we have load delay slots, then
4245 ; we want to split the constant into two separate operations.
4246 ; In both cases this may split a trivial part into a single data op
4247 ; leaving a single complex constant to load. We can also get longer
4248 ; offsets in a LDR which means we get better chances of sharing the pool
4249 ; entries. Finally, we can normally do a better job of scheduling
4250 ; LDR instructions than we can with LDM.
4251 ; This pattern will only match if the one above did not.
4253 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4254 (match_operand:ANY64 1 "const_double_operand" ""))]
4255 "TARGET_ARM && reload_completed
4256 && arm_const_double_by_parts (operands[1])"
4257 [(set (match_dup 0) (match_dup 1))
4258 (set (match_dup 2) (match_dup 3))]
4260 operands[2] = gen_highpart (SImode, operands[0]);
4261 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4263 operands[0] = gen_lowpart (SImode, operands[0]);
4264 operands[1] = gen_lowpart (SImode, operands[1]);
4269 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4270 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4271 "TARGET_EITHER && reload_completed"
4272 [(set (match_dup 0) (match_dup 1))
4273 (set (match_dup 2) (match_dup 3))]
4275 operands[2] = gen_highpart (SImode, operands[0]);
4276 operands[3] = gen_highpart (SImode, operands[1]);
4277 operands[0] = gen_lowpart (SImode, operands[0]);
4278 operands[1] = gen_lowpart (SImode, operands[1]);
4280 /* Handle a partial overlap. */
4281 if (rtx_equal_p (operands[0], operands[3]))
4283 rtx tmp0 = operands[0];
4284 rtx tmp1 = operands[1];
4286 operands[0] = operands[2];
4287 operands[1] = operands[3];
4294 ;; We can't actually do base+index doubleword loads if the index and
4295 ;; destination overlap. Split here so that we at least have chance to
4298 [(set (match_operand:DI 0 "s_register_operand" "")
4299 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4300 (match_operand:SI 2 "s_register_operand" ""))))]
4302 && reg_overlap_mentioned_p (operands[0], operands[1])
4303 && reg_overlap_mentioned_p (operands[0], operands[2])"
4305 (plus:SI (match_dup 1)
4308 (mem:DI (match_dup 4)))]
4310 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4314 ;;; ??? This should have alternatives for constants.
4315 ;;; ??? This was originally identical to the movdf_insn pattern.
4316 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4317 ;;; thumb_reorg with a memory reference.
4318 (define_insn "*thumb_movdi_insn"
4319 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4320 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4322 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4323 && ( register_operand (operands[0], DImode)
4324 || register_operand (operands[1], DImode))"
4327 switch (which_alternative)
4331 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4332 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4333 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4335 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4337 operands[1] = GEN_INT (- INTVAL (operands[1]));
4338 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4340 return \"ldmia\\t%1, {%0, %H0}\";
4342 return \"stmia\\t%0, {%1, %H1}\";
4344 return thumb_load_double_from_address (operands);
4346 operands[2] = gen_rtx_MEM (SImode,
4347 plus_constant (XEXP (operands[0], 0), 4));
4348 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4351 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4352 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4353 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4356 [(set_attr "length" "4,4,6,2,2,6,4,4")
4357 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4358 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4361 (define_expand "movsi"
4362 [(set (match_operand:SI 0 "general_operand" "")
4363 (match_operand:SI 1 "general_operand" ""))]
4368 /* Everything except mem = const or mem = mem can be done easily. */
4369 if (GET_CODE (operands[0]) == MEM)
4370 operands[1] = force_reg (SImode, operands[1]);
4371 if (arm_general_register_operand (operands[0], SImode)
4372 && GET_CODE (operands[1]) == CONST_INT
4373 && !(const_ok_for_arm (INTVAL (operands[1]))
4374 || const_ok_for_arm (~INTVAL (operands[1]))))
4376 arm_split_constant (SET, SImode, NULL_RTX,
4377 INTVAL (operands[1]), operands[0], NULL_RTX,
4378 optimize && !no_new_pseudos);
4382 else /* TARGET_THUMB.... */
4384 if (!no_new_pseudos)
4386 if (GET_CODE (operands[0]) != REG)
4387 operands[1] = force_reg (SImode, operands[1]);
4391 /* Recognize the case where operand[1] is a reference to thread-local
4392 data and load its address to a register. */
4393 if (arm_tls_referenced_p (operands[1]))
4395 rtx tmp = operands[1];
4398 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4400 addend = XEXP (XEXP (tmp, 0), 1);
4401 tmp = XEXP (XEXP (tmp, 0), 0);
4404 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4405 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4407 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4410 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4411 tmp = force_operand (tmp, operands[0]);
4416 && (CONSTANT_P (operands[1])
4417 || symbol_mentioned_p (operands[1])
4418 || label_mentioned_p (operands[1])))
4419 operands[1] = legitimize_pic_address (operands[1], SImode,
4420 (no_new_pseudos ? operands[0] : 0));
4424 (define_insn "*arm_movsi_insn"
4425 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4426 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4427 "TARGET_ARM && ! TARGET_IWMMXT
4428 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4429 && ( register_operand (operands[0], SImode)
4430 || register_operand (operands[1], SImode))"
4436 [(set_attr "type" "*,*,load1,store1")
4437 (set_attr "predicable" "yes")
4438 (set_attr "pool_range" "*,*,4096,*")
4439 (set_attr "neg_pool_range" "*,*,4084,*")]
4443 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4444 (match_operand:SI 1 "const_int_operand" ""))]
4446 && (!(const_ok_for_arm (INTVAL (operands[1]))
4447 || const_ok_for_arm (~INTVAL (operands[1]))))"
4448 [(clobber (const_int 0))]
4450 arm_split_constant (SET, SImode, NULL_RTX,
4451 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4456 (define_insn "*thumb_movsi_insn"
4457 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4458 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4460 && ( register_operand (operands[0], SImode)
4461 || register_operand (operands[1], SImode))"
4472 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4473 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4474 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4478 [(set (match_operand:SI 0 "register_operand" "")
4479 (match_operand:SI 1 "const_int_operand" ""))]
4480 "TARGET_THUMB && satisfies_constraint_J (operands[1])"
4481 [(set (match_dup 0) (match_dup 1))
4482 (set (match_dup 0) (neg:SI (match_dup 0)))]
4483 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4487 [(set (match_operand:SI 0 "register_operand" "")
4488 (match_operand:SI 1 "const_int_operand" ""))]
4489 "TARGET_THUMB && satisfies_constraint_K (operands[1])"
4490 [(set (match_dup 0) (match_dup 1))
4491 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4494 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4495 unsigned HOST_WIDE_INT mask = 0xff;
4498 for (i = 0; i < 25; i++)
4499 if ((val & (mask << i)) == val)
4502 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4506 operands[1] = GEN_INT (val >> i);
4507 operands[2] = GEN_INT (i);
4511 ;; When generating pic, we need to load the symbol offset into a register.
4512 ;; So that the optimizer does not confuse this with a normal symbol load
4513 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4514 ;; since that is the only type of relocation we can use.
4516 ;; The rather odd constraints on the following are to force reload to leave
4517 ;; the insn alone, and to force the minipool generation pass to then move
4518 ;; the GOT symbol to memory.
4520 (define_insn "pic_load_addr_arm"
4521 [(set (match_operand:SI 0 "s_register_operand" "=r")
4522 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4523 "TARGET_ARM && flag_pic"
4525 [(set_attr "type" "load1")
4526 (set (attr "pool_range") (const_int 4096))
4527 (set (attr "neg_pool_range") (const_int 4084))]
4530 (define_insn "pic_load_addr_thumb"
4531 [(set (match_operand:SI 0 "s_register_operand" "=l")
4532 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4533 "TARGET_THUMB && flag_pic"
4535 [(set_attr "type" "load1")
4536 (set (attr "pool_range") (const_int 1024))]
4539 ;; This variant is used for AOF assembly, since it needs to mention the
4540 ;; pic register in the rtl.
4541 (define_expand "pic_load_addr_based"
4542 [(set (match_operand:SI 0 "s_register_operand" "")
4543 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4544 "TARGET_ARM && flag_pic"
4545 "operands[2] = cfun->machine->pic_reg;"
4548 (define_insn "*pic_load_addr_based_insn"
4549 [(set (match_operand:SI 0 "s_register_operand" "=r")
4550 (unspec:SI [(match_operand 1 "" "")
4551 (match_operand 2 "s_register_operand" "r")]
4553 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4555 #ifdef AOF_ASSEMBLER
4556 operands[1] = aof_pic_entry (operands[1]);
4558 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4561 [(set_attr "type" "load1")
4562 (set (attr "pool_range")
4563 (if_then_else (eq_attr "is_thumb" "yes")
4566 (set (attr "neg_pool_range")
4567 (if_then_else (eq_attr "is_thumb" "yes")
4572 (define_insn "pic_add_dot_plus_four"
4573 [(set (match_operand:SI 0 "register_operand" "=r")
4574 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4575 (const (plus:SI (pc) (const_int 4))))]
4577 (use (match_operand 2 "" ""))]
4580 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4581 INTVAL (operands[2]));
4582 return \"add\\t%0, %|pc\";
4584 [(set_attr "length" "2")]
4587 (define_insn "pic_add_dot_plus_eight"
4588 [(set (match_operand:SI 0 "register_operand" "=r")
4589 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4590 (const (plus:SI (pc) (const_int 8))))]
4592 (use (match_operand 2 "" ""))]
4595 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4596 INTVAL (operands[2]));
4597 return \"add%?\\t%0, %|pc, %1\";
4599 [(set_attr "predicable" "yes")]
4602 (define_insn "tls_load_dot_plus_eight"
4603 [(set (match_operand:SI 0 "register_operand" "+r")
4604 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4605 (const (plus:SI (pc) (const_int 8))))]
4607 (use (match_operand 2 "" ""))]
4610 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4611 INTVAL (operands[2]));
4612 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4614 [(set_attr "predicable" "yes")]
4617 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4618 ;; followed by a load. These sequences can be crunched down to
4619 ;; tls_load_dot_plus_eight by a peephole.
4622 [(parallel [(set (match_operand:SI 0 "register_operand" "")
4623 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4624 (const (plus:SI (pc) (const_int 8))))]
4626 (use (label_ref (match_operand 1 "" "")))])
4627 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4628 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4629 [(parallel [(set (match_dup 2)
4630 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4631 (const (plus:SI (pc) (const_int 8))))]
4633 (use (label_ref (match_dup 1)))])]
4637 (define_expand "builtin_setjmp_receiver"
4638 [(label_ref (match_operand 0 "" ""))]
4642 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4644 if (arm_pic_register != INVALID_REGNUM)
4645 arm_load_pic_register (1UL << 3);
4649 ;; If copying one reg to another we can set the condition codes according to
4650 ;; its value. Such a move is common after a return from subroutine and the
4651 ;; result is being tested against zero.
4653 (define_insn "*movsi_compare0"
4654 [(set (reg:CC CC_REGNUM)
4655 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4657 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4662 sub%?s\\t%0, %1, #0"
4663 [(set_attr "conds" "set")]
4666 ;; Subroutine to store a half word from a register into memory.
4667 ;; Operand 0 is the source register (HImode)
4668 ;; Operand 1 is the destination address in a register (SImode)
4670 ;; In both this routine and the next, we must be careful not to spill
4671 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4672 ;; can generate unrecognizable rtl.
4674 (define_expand "storehi"
4675 [;; store the low byte
4676 (set (match_operand 1 "" "") (match_dup 3))
4677 ;; extract the high byte
4679 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4680 ;; store the high byte
4681 (set (match_dup 4) (match_dup 5))]
4685 rtx op1 = operands[1];
4686 rtx addr = XEXP (op1, 0);
4687 enum rtx_code code = GET_CODE (addr);
4689 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4691 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4693 operands[4] = adjust_address (op1, QImode, 1);
4694 operands[1] = adjust_address (operands[1], QImode, 0);
4695 operands[3] = gen_lowpart (QImode, operands[0]);
4696 operands[0] = gen_lowpart (SImode, operands[0]);
4697 operands[2] = gen_reg_rtx (SImode);
4698 operands[5] = gen_lowpart (QImode, operands[2]);
4702 (define_expand "storehi_bigend"
4703 [(set (match_dup 4) (match_dup 3))
4705 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4706 (set (match_operand 1 "" "") (match_dup 5))]
4710 rtx op1 = operands[1];
4711 rtx addr = XEXP (op1, 0);
4712 enum rtx_code code = GET_CODE (addr);
4714 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4716 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4718 operands[4] = adjust_address (op1, QImode, 1);
4719 operands[1] = adjust_address (operands[1], QImode, 0);
4720 operands[3] = gen_lowpart (QImode, operands[0]);
4721 operands[0] = gen_lowpart (SImode, operands[0]);
4722 operands[2] = gen_reg_rtx (SImode);
4723 operands[5] = gen_lowpart (QImode, operands[2]);
4727 ;; Subroutine to store a half word integer constant into memory.
4728 (define_expand "storeinthi"
4729 [(set (match_operand 0 "" "")
4730 (match_operand 1 "" ""))
4731 (set (match_dup 3) (match_dup 2))]
4735 HOST_WIDE_INT value = INTVAL (operands[1]);
4736 rtx addr = XEXP (operands[0], 0);
4737 rtx op0 = operands[0];
4738 enum rtx_code code = GET_CODE (addr);
4740 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4742 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4744 operands[1] = gen_reg_rtx (SImode);
4745 if (BYTES_BIG_ENDIAN)
4747 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4748 if ((value & 255) == ((value >> 8) & 255))
4749 operands[2] = operands[1];
4752 operands[2] = gen_reg_rtx (SImode);
4753 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4758 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4759 if ((value & 255) == ((value >> 8) & 255))
4760 operands[2] = operands[1];
4763 operands[2] = gen_reg_rtx (SImode);
4764 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4768 operands[3] = adjust_address (op0, QImode, 1);
4769 operands[0] = adjust_address (operands[0], QImode, 0);
4770 operands[2] = gen_lowpart (QImode, operands[2]);
4771 operands[1] = gen_lowpart (QImode, operands[1]);
4775 (define_expand "storehi_single_op"
4776 [(set (match_operand:HI 0 "memory_operand" "")
4777 (match_operand:HI 1 "general_operand" ""))]
4778 "TARGET_ARM && arm_arch4"
4780 if (!s_register_operand (operands[1], HImode))
4781 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4785 (define_expand "movhi"
4786 [(set (match_operand:HI 0 "general_operand" "")
4787 (match_operand:HI 1 "general_operand" ""))]
4792 if (!no_new_pseudos)
4794 if (GET_CODE (operands[0]) == MEM)
4798 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4801 if (GET_CODE (operands[1]) == CONST_INT)
4802 emit_insn (gen_storeinthi (operands[0], operands[1]));
4805 if (GET_CODE (operands[1]) == MEM)
4806 operands[1] = force_reg (HImode, operands[1]);
4807 if (BYTES_BIG_ENDIAN)
4808 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4810 emit_insn (gen_storehi (operands[1], operands[0]));
4814 /* Sign extend a constant, and keep it in an SImode reg. */
4815 else if (GET_CODE (operands[1]) == CONST_INT)
4817 rtx reg = gen_reg_rtx (SImode);
4818 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4820 /* If the constant is already valid, leave it alone. */
4821 if (!const_ok_for_arm (val))
4823 /* If setting all the top bits will make the constant
4824 loadable in a single instruction, then set them.
4825 Otherwise, sign extend the number. */
4827 if (const_ok_for_arm (~(val | ~0xffff)))
4829 else if (val & 0x8000)
4833 emit_insn (gen_movsi (reg, GEN_INT (val)));
4834 operands[1] = gen_lowpart (HImode, reg);
4836 else if (arm_arch4 && optimize && !no_new_pseudos
4837 && GET_CODE (operands[1]) == MEM)
4839 rtx reg = gen_reg_rtx (SImode);
4841 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4842 operands[1] = gen_lowpart (HImode, reg);
4844 else if (!arm_arch4)
4846 if (GET_CODE (operands[1]) == MEM)
4849 rtx offset = const0_rtx;
4850 rtx reg = gen_reg_rtx (SImode);
4852 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4853 || (GET_CODE (base) == PLUS
4854 && (GET_CODE (offset = XEXP (base, 1))
4856 && ((INTVAL(offset) & 1) != 1)
4857 && GET_CODE (base = XEXP (base, 0)) == REG))
4858 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4862 new = widen_memory_access (operands[1], SImode,
4863 ((INTVAL (offset) & ~3)
4864 - INTVAL (offset)));
4865 emit_insn (gen_movsi (reg, new));
4866 if (((INTVAL (offset) & 2) != 0)
4867 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4869 rtx reg2 = gen_reg_rtx (SImode);
4871 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4876 emit_insn (gen_movhi_bytes (reg, operands[1]));
4878 operands[1] = gen_lowpart (HImode, reg);
4882 /* Handle loading a large integer during reload. */
4883 else if (GET_CODE (operands[1]) == CONST_INT
4884 && !const_ok_for_arm (INTVAL (operands[1]))
4885 && !const_ok_for_arm (~INTVAL (operands[1])))
4887 /* Writing a constant to memory needs a scratch, which should
4888 be handled with SECONDARY_RELOADs. */
4889 gcc_assert (GET_CODE (operands[0]) == REG);
4891 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4892 emit_insn (gen_movsi (operands[0], operands[1]));
4896 else /* TARGET_THUMB */
4898 if (!no_new_pseudos)
4900 if (GET_CODE (operands[1]) == CONST_INT)
4902 rtx reg = gen_reg_rtx (SImode);
4904 emit_insn (gen_movsi (reg, operands[1]));
4905 operands[1] = gen_lowpart (HImode, reg);
4908 /* ??? We shouldn't really get invalid addresses here, but this can
4909 happen if we are passed a SP (never OK for HImode/QImode) or
4910 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4911 HImode/QImode) relative address. */
4912 /* ??? This should perhaps be fixed elsewhere, for instance, in
4913 fixup_stack_1, by checking for other kinds of invalid addresses,
4914 e.g. a bare reference to a virtual register. This may confuse the
4915 alpha though, which must handle this case differently. */
4916 if (GET_CODE (operands[0]) == MEM
4917 && !memory_address_p (GET_MODE (operands[0]),
4918 XEXP (operands[0], 0)))
4920 = replace_equiv_address (operands[0],
4921 copy_to_reg (XEXP (operands[0], 0)));
4923 if (GET_CODE (operands[1]) == MEM
4924 && !memory_address_p (GET_MODE (operands[1]),
4925 XEXP (operands[1], 0)))
4927 = replace_equiv_address (operands[1],
4928 copy_to_reg (XEXP (operands[1], 0)));
4930 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4932 rtx reg = gen_reg_rtx (SImode);
4934 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4935 operands[1] = gen_lowpart (HImode, reg);
4938 if (GET_CODE (operands[0]) == MEM)
4939 operands[1] = force_reg (HImode, operands[1]);
4941 else if (GET_CODE (operands[1]) == CONST_INT
4942 && !satisfies_constraint_I (operands[1]))
4944 /* Handle loading a large integer during reload. */
4946 /* Writing a constant to memory needs a scratch, which should
4947 be handled with SECONDARY_RELOADs. */
4948 gcc_assert (GET_CODE (operands[0]) == REG);
4950 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4951 emit_insn (gen_movsi (operands[0], operands[1]));
4958 (define_insn "*thumb_movhi_insn"
4959 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4960 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4962 && ( register_operand (operands[0], HImode)
4963 || register_operand (operands[1], HImode))"
4965 switch (which_alternative)
4967 case 0: return \"add %0, %1, #0\";
4968 case 2: return \"strh %1, %0\";
4969 case 3: return \"mov %0, %1\";
4970 case 4: return \"mov %0, %1\";
4971 case 5: return \"mov %0, %1\";
4972 default: gcc_unreachable ();
4974 /* The stack pointer can end up being taken as an index register.
4975 Catch this case here and deal with it. */
4976 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4977 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4978 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4981 ops[0] = operands[0];
4982 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4984 output_asm_insn (\"mov %0, %1\", ops);
4986 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4989 return \"ldrh %0, %1\";
4991 [(set_attr "length" "2,4,2,2,2,2")
4992 (set_attr "type" "*,load1,store1,*,*,*")]
4996 (define_expand "movhi_bytes"
4997 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4999 (zero_extend:SI (match_dup 6)))
5000 (set (match_operand:SI 0 "" "")
5001 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
5006 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5008 mem1 = change_address (operands[1], QImode, addr);
5009 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
5010 operands[0] = gen_lowpart (SImode, operands[0]);
5012 operands[2] = gen_reg_rtx (SImode);
5013 operands[3] = gen_reg_rtx (SImode);
5016 if (BYTES_BIG_ENDIAN)
5018 operands[4] = operands[2];
5019 operands[5] = operands[3];
5023 operands[4] = operands[3];
5024 operands[5] = operands[2];
5029 (define_expand "movhi_bigend"
5031 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
5034 (ashiftrt:SI (match_dup 2) (const_int 16)))
5035 (set (match_operand:HI 0 "s_register_operand" "")
5039 operands[2] = gen_reg_rtx (SImode);
5040 operands[3] = gen_reg_rtx (SImode);
5041 operands[4] = gen_lowpart (HImode, operands[3]);
5045 ;; Pattern to recognize insn generated default case above
5046 (define_insn "*movhi_insn_arch4"
5047 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5048 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
5051 && (GET_CODE (operands[1]) != CONST_INT
5052 || const_ok_for_arm (INTVAL (operands[1]))
5053 || const_ok_for_arm (~INTVAL (operands[1])))"
5055 mov%?\\t%0, %1\\t%@ movhi
5056 mvn%?\\t%0, #%B1\\t%@ movhi
5057 str%?h\\t%1, %0\\t%@ movhi
5058 ldr%?h\\t%0, %1\\t%@ movhi"
5059 [(set_attr "type" "*,*,store1,load1")
5060 (set_attr "predicable" "yes")
5061 (set_attr "pool_range" "*,*,*,256")
5062 (set_attr "neg_pool_range" "*,*,*,244")]
5065 (define_insn "*movhi_bytes"
5066 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5067 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
5070 mov%?\\t%0, %1\\t%@ movhi
5071 mvn%?\\t%0, #%B1\\t%@ movhi"
5072 [(set_attr "predicable" "yes")]
5075 (define_expand "thumb_movhi_clobber"
5076 [(set (match_operand:HI 0 "memory_operand" "")
5077 (match_operand:HI 1 "register_operand" ""))
5078 (clobber (match_operand:DI 2 "register_operand" ""))]
5081 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5082 && REGNO (operands[1]) <= LAST_LO_REGNUM)
5084 emit_insn (gen_movhi (operands[0], operands[1]));
5087 /* XXX Fixme, need to handle other cases here as well. */
5092 ;; We use a DImode scratch because we may occasionally need an additional
5093 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5094 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5095 (define_expand "reload_outhi"
5096 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5097 (match_operand:HI 1 "s_register_operand" "r")
5098 (match_operand:DI 2 "s_register_operand" "=&l")])]
5101 arm_reload_out_hi (operands);
5103 thumb_reload_out_hi (operands);
5108 (define_expand "reload_inhi"
5109 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5110 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5111 (match_operand:DI 2 "s_register_operand" "=&r")])]
5115 arm_reload_in_hi (operands);
5117 thumb_reload_out_hi (operands);
5121 (define_expand "movqi"
5122 [(set (match_operand:QI 0 "general_operand" "")
5123 (match_operand:QI 1 "general_operand" ""))]
5126 /* Everything except mem = const or mem = mem can be done easily */
5128 if (!no_new_pseudos)
5130 if (GET_CODE (operands[1]) == CONST_INT)
5132 rtx reg = gen_reg_rtx (SImode);
5134 emit_insn (gen_movsi (reg, operands[1]));
5135 operands[1] = gen_lowpart (QImode, reg);
5140 /* ??? We shouldn't really get invalid addresses here, but this can
5141 happen if we are passed a SP (never OK for HImode/QImode) or
5142 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5143 HImode/QImode) relative address. */
5144 /* ??? This should perhaps be fixed elsewhere, for instance, in
5145 fixup_stack_1, by checking for other kinds of invalid addresses,
5146 e.g. a bare reference to a virtual register. This may confuse the
5147 alpha though, which must handle this case differently. */
5148 if (GET_CODE (operands[0]) == MEM
5149 && !memory_address_p (GET_MODE (operands[0]),
5150 XEXP (operands[0], 0)))
5152 = replace_equiv_address (operands[0],
5153 copy_to_reg (XEXP (operands[0], 0)));
5154 if (GET_CODE (operands[1]) == MEM
5155 && !memory_address_p (GET_MODE (operands[1]),
5156 XEXP (operands[1], 0)))
5158 = replace_equiv_address (operands[1],
5159 copy_to_reg (XEXP (operands[1], 0)));
5162 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5164 rtx reg = gen_reg_rtx (SImode);
5166 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5167 operands[1] = gen_lowpart (QImode, reg);
5170 if (GET_CODE (operands[0]) == MEM)
5171 operands[1] = force_reg (QImode, operands[1]);
5173 else if (TARGET_THUMB
5174 && GET_CODE (operands[1]) == CONST_INT
5175 && !satisfies_constraint_I (operands[1]))
5177 /* Handle loading a large integer during reload. */
5179 /* Writing a constant to memory needs a scratch, which should
5180 be handled with SECONDARY_RELOADs. */
5181 gcc_assert (GET_CODE (operands[0]) == REG);
5183 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5184 emit_insn (gen_movsi (operands[0], operands[1]));
5191 (define_insn "*arm_movqi_insn"
5192 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5193 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5195 && ( register_operand (operands[0], QImode)
5196 || register_operand (operands[1], QImode))"
5202 [(set_attr "type" "*,*,load1,store1")
5203 (set_attr "predicable" "yes")]
5206 (define_insn "*thumb_movqi_insn"
5207 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5208 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5210 && ( register_operand (operands[0], QImode)
5211 || register_operand (operands[1], QImode))"
5219 [(set_attr "length" "2")
5220 (set_attr "type" "*,load1,store1,*,*,*")
5221 (set_attr "pool_range" "*,32,*,*,*,*")]
5224 (define_expand "movsf"
5225 [(set (match_operand:SF 0 "general_operand" "")
5226 (match_operand:SF 1 "general_operand" ""))]
5231 if (GET_CODE (operands[0]) == MEM)
5232 operands[1] = force_reg (SFmode, operands[1]);
5234 else /* TARGET_THUMB */
5236 if (!no_new_pseudos)
5238 if (GET_CODE (operands[0]) != REG)
5239 operands[1] = force_reg (SFmode, operands[1]);
5245 ;; Transform a floating-point move of a constant into a core register into
5246 ;; an SImode operation.
5248 [(set (match_operand:SF 0 "arm_general_register_operand" "")
5249 (match_operand:SF 1 "immediate_operand" ""))]
5252 && GET_CODE (operands[1]) == CONST_DOUBLE"
5253 [(set (match_dup 2) (match_dup 3))]
5255 operands[2] = gen_lowpart (SImode, operands[0]);
5256 operands[3] = gen_lowpart (SImode, operands[1]);
5257 if (operands[2] == 0 || operands[3] == 0)
5262 (define_insn "*arm_movsf_soft_insn"
5263 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5264 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5266 && TARGET_SOFT_FLOAT
5267 && (GET_CODE (operands[0]) != MEM
5268 || register_operand (operands[1], SFmode))"
5271 ldr%?\\t%0, %1\\t%@ float
5272 str%?\\t%1, %0\\t%@ float"
5273 [(set_attr "length" "4,4,4")
5274 (set_attr "predicable" "yes")
5275 (set_attr "type" "*,load1,store1")
5276 (set_attr "pool_range" "*,4096,*")
5277 (set_attr "neg_pool_range" "*,4084,*")]
5280 ;;; ??? This should have alternatives for constants.
5281 (define_insn "*thumb_movsf_insn"
5282 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5283 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5285 && ( register_operand (operands[0], SFmode)
5286 || register_operand (operands[1], SFmode))"
5295 [(set_attr "length" "2")
5296 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5297 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5300 (define_expand "movdf"
5301 [(set (match_operand:DF 0 "general_operand" "")
5302 (match_operand:DF 1 "general_operand" ""))]
5307 if (GET_CODE (operands[0]) == MEM)
5308 operands[1] = force_reg (DFmode, operands[1]);
5310 else /* TARGET_THUMB */
5312 if (!no_new_pseudos)
5314 if (GET_CODE (operands[0]) != REG)
5315 operands[1] = force_reg (DFmode, operands[1]);
5321 ;; Reloading a df mode value stored in integer regs to memory can require a
5323 (define_expand "reload_outdf"
5324 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5325 (match_operand:DF 1 "s_register_operand" "r")
5326 (match_operand:SI 2 "s_register_operand" "=&r")]
5330 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5333 operands[2] = XEXP (operands[0], 0);
5334 else if (code == POST_INC || code == PRE_DEC)
5336 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5337 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5338 emit_insn (gen_movdi (operands[0], operands[1]));
5341 else if (code == PRE_INC)
5343 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5345 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5348 else if (code == POST_DEC)
5349 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5351 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5352 XEXP (XEXP (operands[0], 0), 1)));
5354 emit_insn (gen_rtx_SET (VOIDmode,
5355 replace_equiv_address (operands[0], operands[2]),
5358 if (code == POST_DEC)
5359 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5365 (define_insn "*movdf_soft_insn"
5366 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5367 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5368 "TARGET_ARM && TARGET_SOFT_FLOAT
5369 && ( register_operand (operands[0], DFmode)
5370 || register_operand (operands[1], DFmode))"
5372 switch (which_alternative)
5379 return output_move_double (operands);
5382 [(set_attr "length" "8,12,16,8,8")
5383 (set_attr "type" "*,*,*,load2,store2")
5384 (set_attr "pool_range" "1020")
5385 (set_attr "neg_pool_range" "1008")]
5388 ;;; ??? This should have alternatives for constants.
5389 ;;; ??? This was originally identical to the movdi_insn pattern.
5390 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5391 ;;; thumb_reorg with a memory reference.
5392 (define_insn "*thumb_movdf_insn"
5393 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5394 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5396 && ( register_operand (operands[0], DFmode)
5397 || register_operand (operands[1], DFmode))"
5399 switch (which_alternative)
5403 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5404 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5405 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5407 return \"ldmia\\t%1, {%0, %H0}\";
5409 return \"stmia\\t%0, {%1, %H1}\";
5411 return thumb_load_double_from_address (operands);
5413 operands[2] = gen_rtx_MEM (SImode,
5414 plus_constant (XEXP (operands[0], 0), 4));
5415 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5418 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5419 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5420 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5423 [(set_attr "length" "4,2,2,6,4,4")
5424 (set_attr "type" "*,load2,store2,load2,store2,*")
5425 (set_attr "pool_range" "*,*,*,1020,*,*")]
5428 (define_expand "movxf"
5429 [(set (match_operand:XF 0 "general_operand" "")
5430 (match_operand:XF 1 "general_operand" ""))]
5431 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5433 if (GET_CODE (operands[0]) == MEM)
5434 operands[1] = force_reg (XFmode, operands[1]);
5439 (define_expand "movv2si"
5440 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5441 (match_operand:V2SI 1 "general_operand" ""))]
5442 "TARGET_REALLY_IWMMXT"
5446 (define_expand "movv4hi"
5447 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5448 (match_operand:V4HI 1 "general_operand" ""))]
5449 "TARGET_REALLY_IWMMXT"
5453 (define_expand "movv8qi"
5454 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5455 (match_operand:V8QI 1 "general_operand" ""))]
5456 "TARGET_REALLY_IWMMXT"
5461 ;; load- and store-multiple insns
5462 ;; The arm can load/store any set of registers, provided that they are in
5463 ;; ascending order; but that is beyond GCC so stick with what it knows.
5465 (define_expand "load_multiple"
5466 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5467 (match_operand:SI 1 "" ""))
5468 (use (match_operand:SI 2 "" ""))])]
5471 HOST_WIDE_INT offset = 0;
5473 /* Support only fixed point registers. */
5474 if (GET_CODE (operands[2]) != CONST_INT
5475 || INTVAL (operands[2]) > 14
5476 || INTVAL (operands[2]) < 2
5477 || GET_CODE (operands[1]) != MEM
5478 || GET_CODE (operands[0]) != REG
5479 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5480 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5484 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5485 force_reg (SImode, XEXP (operands[1], 0)),
5486 TRUE, FALSE, operands[1], &offset);
5489 ;; Load multiple with write-back
5491 (define_insn "*ldmsi_postinc4"
5492 [(match_parallel 0 "load_multiple_operation"
5493 [(set (match_operand:SI 1 "s_register_operand" "=r")
5494 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5496 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5497 (mem:SI (match_dup 2)))
5498 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5499 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5500 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5501 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5502 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5503 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5504 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5505 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5506 [(set_attr "type" "load4")
5507 (set_attr "predicable" "yes")]
5510 (define_insn "*ldmsi_postinc4_thumb"
5511 [(match_parallel 0 "load_multiple_operation"
5512 [(set (match_operand:SI 1 "s_register_operand" "=l")
5513 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5515 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5516 (mem:SI (match_dup 2)))
5517 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5518 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5519 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5520 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5521 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5522 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5523 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5524 "ldmia\\t%1!, {%3, %4, %5, %6}"
5525 [(set_attr "type" "load4")]
5528 (define_insn "*ldmsi_postinc3"
5529 [(match_parallel 0 "load_multiple_operation"
5530 [(set (match_operand:SI 1 "s_register_operand" "=r")
5531 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5533 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5534 (mem:SI (match_dup 2)))
5535 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5536 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5537 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5538 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5539 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5540 "ldm%?ia\\t%1!, {%3, %4, %5}"
5541 [(set_attr "type" "load3")
5542 (set_attr "predicable" "yes")]
5545 (define_insn "*ldmsi_postinc2"
5546 [(match_parallel 0 "load_multiple_operation"
5547 [(set (match_operand:SI 1 "s_register_operand" "=r")
5548 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5550 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5551 (mem:SI (match_dup 2)))
5552 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5553 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5554 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5555 "ldm%?ia\\t%1!, {%3, %4}"
5556 [(set_attr "type" "load2")
5557 (set_attr "predicable" "yes")]
5560 ;; Ordinary load multiple
5562 (define_insn "*ldmsi4"
5563 [(match_parallel 0 "load_multiple_operation"
5564 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5565 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5566 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5567 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5568 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5569 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5570 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5571 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5572 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5573 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5574 [(set_attr "type" "load4")
5575 (set_attr "predicable" "yes")]
5578 (define_insn "*ldmsi3"
5579 [(match_parallel 0 "load_multiple_operation"
5580 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5581 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5582 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5583 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5584 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5585 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5586 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5587 "ldm%?ia\\t%1, {%2, %3, %4}"
5588 [(set_attr "type" "load3")
5589 (set_attr "predicable" "yes")]
5592 (define_insn "*ldmsi2"
5593 [(match_parallel 0 "load_multiple_operation"
5594 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5595 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5596 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5597 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5598 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5599 "ldm%?ia\\t%1, {%2, %3}"
5600 [(set_attr "type" "load2")
5601 (set_attr "predicable" "yes")]
5604 (define_expand "store_multiple"
5605 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5606 (match_operand:SI 1 "" ""))
5607 (use (match_operand:SI 2 "" ""))])]
5610 HOST_WIDE_INT offset = 0;
5612 /* Support only fixed point registers. */
5613 if (GET_CODE (operands[2]) != CONST_INT
5614 || INTVAL (operands[2]) > 14
5615 || INTVAL (operands[2]) < 2
5616 || GET_CODE (operands[1]) != REG
5617 || GET_CODE (operands[0]) != MEM
5618 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5619 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5623 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5624 force_reg (SImode, XEXP (operands[0], 0)),
5625 TRUE, FALSE, operands[0], &offset);
5628 ;; Store multiple with write-back
5630 (define_insn "*stmsi_postinc4"
5631 [(match_parallel 0 "store_multiple_operation"
5632 [(set (match_operand:SI 1 "s_register_operand" "=r")
5633 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5635 (set (mem:SI (match_dup 2))
5636 (match_operand:SI 3 "arm_hard_register_operand" ""))
5637 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5638 (match_operand:SI 4 "arm_hard_register_operand" ""))
5639 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5640 (match_operand:SI 5 "arm_hard_register_operand" ""))
5641 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5642 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5643 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5644 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5645 [(set_attr "predicable" "yes")
5646 (set_attr "type" "store4")]
5649 (define_insn "*stmsi_postinc4_thumb"
5650 [(match_parallel 0 "store_multiple_operation"
5651 [(set (match_operand:SI 1 "s_register_operand" "=l")
5652 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5654 (set (mem:SI (match_dup 2))
5655 (match_operand:SI 3 "arm_hard_register_operand" ""))
5656 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5657 (match_operand:SI 4 "arm_hard_register_operand" ""))
5658 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5659 (match_operand:SI 5 "arm_hard_register_operand" ""))
5660 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5661 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5662 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5663 "stmia\\t%1!, {%3, %4, %5, %6}"
5664 [(set_attr "type" "store4")]
5667 (define_insn "*stmsi_postinc3"
5668 [(match_parallel 0 "store_multiple_operation"
5669 [(set (match_operand:SI 1 "s_register_operand" "=r")
5670 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5672 (set (mem:SI (match_dup 2))
5673 (match_operand:SI 3 "arm_hard_register_operand" ""))
5674 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5675 (match_operand:SI 4 "arm_hard_register_operand" ""))
5676 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5677 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5678 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5679 "stm%?ia\\t%1!, {%3, %4, %5}"
5680 [(set_attr "predicable" "yes")
5681 (set_attr "type" "store3")]
5684 (define_insn "*stmsi_postinc2"
5685 [(match_parallel 0 "store_multiple_operation"
5686 [(set (match_operand:SI 1 "s_register_operand" "=r")
5687 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5689 (set (mem:SI (match_dup 2))
5690 (match_operand:SI 3 "arm_hard_register_operand" ""))
5691 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5692 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5693 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5694 "stm%?ia\\t%1!, {%3, %4}"
5695 [(set_attr "predicable" "yes")
5696 (set_attr "type" "store2")]
5699 ;; Ordinary store multiple
5701 (define_insn "*stmsi4"
5702 [(match_parallel 0 "store_multiple_operation"
5703 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5704 (match_operand:SI 2 "arm_hard_register_operand" ""))
5705 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5706 (match_operand:SI 3 "arm_hard_register_operand" ""))
5707 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5708 (match_operand:SI 4 "arm_hard_register_operand" ""))
5709 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5710 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5711 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5712 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5713 [(set_attr "predicable" "yes")
5714 (set_attr "type" "store4")]
5717 (define_insn "*stmsi3"
5718 [(match_parallel 0 "store_multiple_operation"
5719 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5720 (match_operand:SI 2 "arm_hard_register_operand" ""))
5721 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5722 (match_operand:SI 3 "arm_hard_register_operand" ""))
5723 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5724 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5725 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5726 "stm%?ia\\t%1, {%2, %3, %4}"
5727 [(set_attr "predicable" "yes")
5728 (set_attr "type" "store3")]
5731 (define_insn "*stmsi2"
5732 [(match_parallel 0 "store_multiple_operation"
5733 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5734 (match_operand:SI 2 "arm_hard_register_operand" ""))
5735 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5736 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5737 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5738 "stm%?ia\\t%1, {%2, %3}"
5739 [(set_attr "predicable" "yes")
5740 (set_attr "type" "store2")]
5743 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5744 ;; We could let this apply for blocks of less than this, but it clobbers so
5745 ;; many registers that there is then probably a better way.
5747 (define_expand "movmemqi"
5748 [(match_operand:BLK 0 "general_operand" "")
5749 (match_operand:BLK 1 "general_operand" "")
5750 (match_operand:SI 2 "const_int_operand" "")
5751 (match_operand:SI 3 "const_int_operand" "")]
5756 if (arm_gen_movmemqi (operands))
5760 else /* TARGET_THUMB */
5762 if ( INTVAL (operands[3]) != 4
5763 || INTVAL (operands[2]) > 48)
5766 thumb_expand_movmemqi (operands);
5772 ;; Thumb block-move insns
5774 (define_insn "movmem12b"
5775 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5776 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5777 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5778 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5779 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5780 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5781 (set (match_operand:SI 0 "register_operand" "=l")
5782 (plus:SI (match_dup 2) (const_int 12)))
5783 (set (match_operand:SI 1 "register_operand" "=l")
5784 (plus:SI (match_dup 3) (const_int 12)))
5785 (clobber (match_scratch:SI 4 "=&l"))
5786 (clobber (match_scratch:SI 5 "=&l"))
5787 (clobber (match_scratch:SI 6 "=&l"))]
5789 "* return thumb_output_move_mem_multiple (3, operands);"
5790 [(set_attr "length" "4")
5791 ; This isn't entirely accurate... It loads as well, but in terms of
5792 ; scheduling the following insn it is better to consider it as a store
5793 (set_attr "type" "store3")]
5796 (define_insn "movmem8b"
5797 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5798 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5799 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5800 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5801 (set (match_operand:SI 0 "register_operand" "=l")
5802 (plus:SI (match_dup 2) (const_int 8)))
5803 (set (match_operand:SI 1 "register_operand" "=l")
5804 (plus:SI (match_dup 3) (const_int 8)))
5805 (clobber (match_scratch:SI 4 "=&l"))
5806 (clobber (match_scratch:SI 5 "=&l"))]
5808 "* return thumb_output_move_mem_multiple (2, operands);"
5809 [(set_attr "length" "4")
5810 ; This isn't entirely accurate... It loads as well, but in terms of
5811 ; scheduling the following insn it is better to consider it as a store
5812 (set_attr "type" "store2")]
5817 ;; Compare & branch insns
5818 ;; The range calculations are based as follows:
5819 ;; For forward branches, the address calculation returns the address of
5820 ;; the next instruction. This is 2 beyond the branch instruction.
5821 ;; For backward branches, the address calculation returns the address of
5822 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5823 ;; instruction for the shortest sequence, and 4 before the branch instruction
5824 ;; if we have to jump around an unconditional branch.
5825 ;; To the basic branch range the PC offset must be added (this is +4).
5826 ;; So for forward branches we have
5827 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5828 ;; And for backward branches we have
5829 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5831 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5832 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5834 (define_expand "cbranchsi4"
5835 [(set (pc) (if_then_else
5836 (match_operator 0 "arm_comparison_operator"
5837 [(match_operand:SI 1 "s_register_operand" "")
5838 (match_operand:SI 2 "nonmemory_operand" "")])
5839 (label_ref (match_operand 3 "" ""))
5843 if (thumb_cmpneg_operand (operands[2], SImode))
5845 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5846 operands[3], operands[0]));
5849 if (!thumb_cmp_operand (operands[2], SImode))
5850 operands[2] = force_reg (SImode, operands[2]);
5853 (define_insn "*cbranchsi4_insn"
5854 [(set (pc) (if_then_else
5855 (match_operator 0 "arm_comparison_operator"
5856 [(match_operand:SI 1 "s_register_operand" "l,*h")
5857 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5858 (label_ref (match_operand 3 "" ""))
5862 output_asm_insn (\"cmp\\t%1, %2\", operands);
5864 switch (get_attr_length (insn))
5866 case 4: return \"b%d0\\t%l3\";
5867 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5868 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5871 [(set (attr "far_jump")
5873 (eq_attr "length" "8")
5874 (const_string "yes")
5875 (const_string "no")))
5876 (set (attr "length")
5878 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5879 (le (minus (match_dup 3) (pc)) (const_int 256)))
5882 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5883 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5888 (define_insn "cbranchsi4_scratch"
5889 [(set (pc) (if_then_else
5890 (match_operator 4 "arm_comparison_operator"
5891 [(match_operand:SI 1 "s_register_operand" "l,0")
5892 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5893 (label_ref (match_operand 3 "" ""))
5895 (clobber (match_scratch:SI 0 "=l,l"))]
5898 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5900 switch (get_attr_length (insn))
5902 case 4: return \"b%d4\\t%l3\";
5903 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5904 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5907 [(set (attr "far_jump")
5909 (eq_attr "length" "8")
5910 (const_string "yes")
5911 (const_string "no")))
5912 (set (attr "length")
5914 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5915 (le (minus (match_dup 3) (pc)) (const_int 256)))
5918 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5919 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5923 (define_insn "*movsi_cbranchsi4"
5926 (match_operator 3 "arm_comparison_operator"
5927 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5929 (label_ref (match_operand 2 "" ""))
5931 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5935 if (which_alternative == 0)
5936 output_asm_insn (\"cmp\t%0, #0\", operands);
5937 else if (which_alternative == 1)
5938 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5941 output_asm_insn (\"cmp\t%1, #0\", operands);
5942 if (which_alternative == 2)
5943 output_asm_insn (\"mov\t%0, %1\", operands);
5945 output_asm_insn (\"str\t%1, %0\", operands);
5947 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5949 case 4: return \"b%d3\\t%l2\";
5950 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5951 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5954 [(set (attr "far_jump")
5956 (ior (and (gt (symbol_ref ("which_alternative"))
5958 (eq_attr "length" "8"))
5959 (eq_attr "length" "10"))
5960 (const_string "yes")
5961 (const_string "no")))
5962 (set (attr "length")
5964 (le (symbol_ref ("which_alternative"))
5967 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5968 (le (minus (match_dup 2) (pc)) (const_int 256)))
5971 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5972 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5976 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5977 (le (minus (match_dup 2) (pc)) (const_int 256)))
5980 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5981 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5986 (define_insn "*negated_cbranchsi4"
5989 (match_operator 0 "equality_operator"
5990 [(match_operand:SI 1 "s_register_operand" "l")
5991 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5992 (label_ref (match_operand 3 "" ""))
5996 output_asm_insn (\"cmn\\t%1, %2\", operands);
5997 switch (get_attr_length (insn))
5999 case 4: return \"b%d0\\t%l3\";
6000 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6001 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6004 [(set (attr "far_jump")
6006 (eq_attr "length" "8")
6007 (const_string "yes")
6008 (const_string "no")))
6009 (set (attr "length")
6011 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6012 (le (minus (match_dup 3) (pc)) (const_int 256)))
6015 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6016 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6021 (define_insn "*tbit_cbranch"
6024 (match_operator 0 "equality_operator"
6025 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6027 (match_operand:SI 2 "const_int_operand" "i"))
6029 (label_ref (match_operand 3 "" ""))
6031 (clobber (match_scratch:SI 4 "=l"))]
6036 op[0] = operands[4];
6037 op[1] = operands[1];
6038 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6040 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6041 switch (get_attr_length (insn))
6043 case 4: return \"b%d0\\t%l3\";
6044 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6045 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6048 [(set (attr "far_jump")
6050 (eq_attr "length" "8")
6051 (const_string "yes")
6052 (const_string "no")))
6053 (set (attr "length")
6055 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6056 (le (minus (match_dup 3) (pc)) (const_int 256)))
6059 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6060 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6065 (define_insn "*tlobits_cbranch"
6068 (match_operator 0 "equality_operator"
6069 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6070 (match_operand:SI 2 "const_int_operand" "i")
6073 (label_ref (match_operand 3 "" ""))
6075 (clobber (match_scratch:SI 4 "=l"))]
6080 op[0] = operands[4];
6081 op[1] = operands[1];
6082 op[2] = GEN_INT (32 - INTVAL (operands[2]));
6084 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6085 switch (get_attr_length (insn))
6087 case 4: return \"b%d0\\t%l3\";
6088 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6089 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6092 [(set (attr "far_jump")
6094 (eq_attr "length" "8")
6095 (const_string "yes")
6096 (const_string "no")))
6097 (set (attr "length")
6099 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6100 (le (minus (match_dup 3) (pc)) (const_int 256)))
6103 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6104 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6109 (define_insn "*tstsi3_cbranch"
6112 (match_operator 3 "equality_operator"
6113 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6114 (match_operand:SI 1 "s_register_operand" "l"))
6116 (label_ref (match_operand 2 "" ""))
6121 output_asm_insn (\"tst\\t%0, %1\", operands);
6122 switch (get_attr_length (insn))
6124 case 4: return \"b%d3\\t%l2\";
6125 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6126 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6129 [(set (attr "far_jump")
6131 (eq_attr "length" "8")
6132 (const_string "yes")
6133 (const_string "no")))
6134 (set (attr "length")
6136 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6137 (le (minus (match_dup 2) (pc)) (const_int 256)))
6140 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6141 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6146 (define_insn "*andsi3_cbranch"
6149 (match_operator 5 "equality_operator"
6150 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6151 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6153 (label_ref (match_operand 4 "" ""))
6155 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6156 (and:SI (match_dup 2) (match_dup 3)))
6157 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6161 if (which_alternative == 0)
6162 output_asm_insn (\"and\\t%0, %3\", operands);
6163 else if (which_alternative == 1)
6165 output_asm_insn (\"and\\t%1, %3\", operands);
6166 output_asm_insn (\"mov\\t%0, %1\", operands);
6170 output_asm_insn (\"and\\t%1, %3\", operands);
6171 output_asm_insn (\"str\\t%1, %0\", operands);
6174 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6176 case 4: return \"b%d5\\t%l4\";
6177 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6178 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6181 [(set (attr "far_jump")
6183 (ior (and (eq (symbol_ref ("which_alternative"))
6185 (eq_attr "length" "8"))
6186 (eq_attr "length" "10"))
6187 (const_string "yes")
6188 (const_string "no")))
6189 (set (attr "length")
6191 (eq (symbol_ref ("which_alternative"))
6194 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6195 (le (minus (match_dup 4) (pc)) (const_int 256)))
6198 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6199 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6203 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6204 (le (minus (match_dup 4) (pc)) (const_int 256)))
6207 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6208 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6213 (define_insn "*orrsi3_cbranch_scratch"
6216 (match_operator 4 "equality_operator"
6217 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6218 (match_operand:SI 2 "s_register_operand" "l"))
6220 (label_ref (match_operand 3 "" ""))
6222 (clobber (match_scratch:SI 0 "=l"))]
6226 output_asm_insn (\"orr\\t%0, %2\", operands);
6227 switch (get_attr_length (insn))
6229 case 4: return \"b%d4\\t%l3\";
6230 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6231 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6234 [(set (attr "far_jump")
6236 (eq_attr "length" "8")
6237 (const_string "yes")
6238 (const_string "no")))
6239 (set (attr "length")
6241 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6242 (le (minus (match_dup 3) (pc)) (const_int 256)))
6245 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6246 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6251 (define_insn "*orrsi3_cbranch"
6254 (match_operator 5 "equality_operator"
6255 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6256 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6258 (label_ref (match_operand 4 "" ""))
6260 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6261 (ior:SI (match_dup 2) (match_dup 3)))
6262 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6266 if (which_alternative == 0)
6267 output_asm_insn (\"orr\\t%0, %3\", operands);
6268 else if (which_alternative == 1)
6270 output_asm_insn (\"orr\\t%1, %3\", operands);
6271 output_asm_insn (\"mov\\t%0, %1\", operands);
6275 output_asm_insn (\"orr\\t%1, %3\", operands);
6276 output_asm_insn (\"str\\t%1, %0\", operands);
6279 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6281 case 4: return \"b%d5\\t%l4\";
6282 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6283 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6286 [(set (attr "far_jump")
6288 (ior (and (eq (symbol_ref ("which_alternative"))
6290 (eq_attr "length" "8"))
6291 (eq_attr "length" "10"))
6292 (const_string "yes")
6293 (const_string "no")))
6294 (set (attr "length")
6296 (eq (symbol_ref ("which_alternative"))
6299 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6300 (le (minus (match_dup 4) (pc)) (const_int 256)))
6303 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6304 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6308 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6309 (le (minus (match_dup 4) (pc)) (const_int 256)))
6312 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6313 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6318 (define_insn "*xorsi3_cbranch_scratch"
6321 (match_operator 4 "equality_operator"
6322 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6323 (match_operand:SI 2 "s_register_operand" "l"))
6325 (label_ref (match_operand 3 "" ""))
6327 (clobber (match_scratch:SI 0 "=l"))]
6331 output_asm_insn (\"eor\\t%0, %2\", operands);
6332 switch (get_attr_length (insn))
6334 case 4: return \"b%d4\\t%l3\";
6335 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6336 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6339 [(set (attr "far_jump")
6341 (eq_attr "length" "8")
6342 (const_string "yes")
6343 (const_string "no")))
6344 (set (attr "length")
6346 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6347 (le (minus (match_dup 3) (pc)) (const_int 256)))
6350 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6351 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6356 (define_insn "*xorsi3_cbranch"
6359 (match_operator 5 "equality_operator"
6360 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6361 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6363 (label_ref (match_operand 4 "" ""))
6365 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6366 (xor:SI (match_dup 2) (match_dup 3)))
6367 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6371 if (which_alternative == 0)
6372 output_asm_insn (\"eor\\t%0, %3\", operands);
6373 else if (which_alternative == 1)
6375 output_asm_insn (\"eor\\t%1, %3\", operands);
6376 output_asm_insn (\"mov\\t%0, %1\", operands);
6380 output_asm_insn (\"eor\\t%1, %3\", operands);
6381 output_asm_insn (\"str\\t%1, %0\", operands);
6384 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6386 case 4: return \"b%d5\\t%l4\";
6387 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6388 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6391 [(set (attr "far_jump")
6393 (ior (and (eq (symbol_ref ("which_alternative"))
6395 (eq_attr "length" "8"))
6396 (eq_attr "length" "10"))
6397 (const_string "yes")
6398 (const_string "no")))
6399 (set (attr "length")
6401 (eq (symbol_ref ("which_alternative"))
6404 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6405 (le (minus (match_dup 4) (pc)) (const_int 256)))
6408 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6409 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6413 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6414 (le (minus (match_dup 4) (pc)) (const_int 256)))
6417 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6418 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6423 (define_insn "*bicsi3_cbranch_scratch"
6426 (match_operator 4 "equality_operator"
6427 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6428 (match_operand:SI 1 "s_register_operand" "0"))
6430 (label_ref (match_operand 3 "" ""))
6432 (clobber (match_scratch:SI 0 "=l"))]
6436 output_asm_insn (\"bic\\t%0, %2\", operands);
6437 switch (get_attr_length (insn))
6439 case 4: return \"b%d4\\t%l3\";
6440 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6441 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6444 [(set (attr "far_jump")
6446 (eq_attr "length" "8")
6447 (const_string "yes")
6448 (const_string "no")))
6449 (set (attr "length")
6451 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6452 (le (minus (match_dup 3) (pc)) (const_int 256)))
6455 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6456 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6461 (define_insn "*bicsi3_cbranch"
6464 (match_operator 5 "equality_operator"
6465 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6466 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6468 (label_ref (match_operand 4 "" ""))
6470 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6471 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6472 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6476 if (which_alternative == 0)
6477 output_asm_insn (\"bic\\t%0, %3\", operands);
6478 else if (which_alternative <= 2)
6480 output_asm_insn (\"bic\\t%1, %3\", operands);
6481 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6482 conditions again, since we're only testing for equality. */
6483 output_asm_insn (\"mov\\t%0, %1\", operands);
6487 output_asm_insn (\"bic\\t%1, %3\", operands);
6488 output_asm_insn (\"str\\t%1, %0\", operands);
6491 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6493 case 4: return \"b%d5\\t%l4\";
6494 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6495 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6498 [(set (attr "far_jump")
6500 (ior (and (eq (symbol_ref ("which_alternative"))
6502 (eq_attr "length" "8"))
6503 (eq_attr "length" "10"))
6504 (const_string "yes")
6505 (const_string "no")))
6506 (set (attr "length")
6508 (eq (symbol_ref ("which_alternative"))
6511 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6512 (le (minus (match_dup 4) (pc)) (const_int 256)))
6515 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6516 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6520 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6521 (le (minus (match_dup 4) (pc)) (const_int 256)))
6524 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6525 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6530 (define_insn "*cbranchne_decr1"
6532 (if_then_else (match_operator 3 "equality_operator"
6533 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6535 (label_ref (match_operand 4 "" ""))
6537 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6538 (plus:SI (match_dup 2) (const_int -1)))
6539 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6544 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6546 VOIDmode, operands[2], const1_rtx);
6547 cond[1] = operands[4];
6549 if (which_alternative == 0)
6550 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6551 else if (which_alternative == 1)
6553 /* We must provide an alternative for a hi reg because reload
6554 cannot handle output reloads on a jump instruction, but we
6555 can't subtract into that. Fortunately a mov from lo to hi
6556 does not clobber the condition codes. */
6557 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6558 output_asm_insn (\"mov\\t%0, %1\", operands);
6562 /* Similarly, but the target is memory. */
6563 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6564 output_asm_insn (\"str\\t%1, %0\", operands);
6567 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6570 output_asm_insn (\"b%d0\\t%l1\", cond);
6573 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6574 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6576 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6577 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6581 [(set (attr "far_jump")
6583 (ior (and (eq (symbol_ref ("which_alternative"))
6585 (eq_attr "length" "8"))
6586 (eq_attr "length" "10"))
6587 (const_string "yes")
6588 (const_string "no")))
6589 (set_attr_alternative "length"
6593 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6594 (le (minus (match_dup 4) (pc)) (const_int 256)))
6597 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6598 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6603 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6604 (le (minus (match_dup 4) (pc)) (const_int 256)))
6607 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6608 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6613 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6614 (le (minus (match_dup 4) (pc)) (const_int 256)))
6617 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6618 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6623 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6624 (le (minus (match_dup 4) (pc)) (const_int 256)))
6627 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6628 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6633 (define_insn "*addsi3_cbranch"
6636 (match_operator 4 "comparison_operator"
6638 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6639 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6641 (label_ref (match_operand 5 "" ""))
6644 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6645 (plus:SI (match_dup 2) (match_dup 3)))
6646 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6648 && (GET_CODE (operands[4]) == EQ
6649 || GET_CODE (operands[4]) == NE
6650 || GET_CODE (operands[4]) == GE
6651 || GET_CODE (operands[4]) == LT)"
6657 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6658 cond[1] = operands[2];
6659 cond[2] = operands[3];
6661 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6662 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6664 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6666 if (which_alternative >= 3
6667 && which_alternative < 4)
6668 output_asm_insn (\"mov\\t%0, %1\", operands);
6669 else if (which_alternative >= 4)
6670 output_asm_insn (\"str\\t%1, %0\", operands);
6672 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6675 return \"b%d4\\t%l5\";
6677 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6679 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6683 [(set (attr "far_jump")
6685 (ior (and (lt (symbol_ref ("which_alternative"))
6687 (eq_attr "length" "8"))
6688 (eq_attr "length" "10"))
6689 (const_string "yes")
6690 (const_string "no")))
6691 (set (attr "length")
6693 (lt (symbol_ref ("which_alternative"))
6696 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6697 (le (minus (match_dup 5) (pc)) (const_int 256)))
6700 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6701 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6705 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6706 (le (minus (match_dup 5) (pc)) (const_int 256)))
6709 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6710 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6715 (define_insn "*addsi3_cbranch_scratch"
6718 (match_operator 3 "comparison_operator"
6720 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6721 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6723 (label_ref (match_operand 4 "" ""))
6725 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6727 && (GET_CODE (operands[3]) == EQ
6728 || GET_CODE (operands[3]) == NE
6729 || GET_CODE (operands[3]) == GE
6730 || GET_CODE (operands[3]) == LT)"
6733 switch (which_alternative)
6736 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6739 output_asm_insn (\"cmn\t%1, %2\", operands);
6742 if (INTVAL (operands[2]) < 0)
6743 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6745 output_asm_insn (\"add\t%0, %1, %2\", operands);
6748 if (INTVAL (operands[2]) < 0)
6749 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6751 output_asm_insn (\"add\t%0, %0, %2\", operands);
6755 switch (get_attr_length (insn))
6758 return \"b%d3\\t%l4\";
6760 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6762 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6766 [(set (attr "far_jump")
6768 (eq_attr "length" "8")
6769 (const_string "yes")
6770 (const_string "no")))
6771 (set (attr "length")
6773 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6774 (le (minus (match_dup 4) (pc)) (const_int 256)))
6777 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6778 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6783 (define_insn "*subsi3_cbranch"
6786 (match_operator 4 "comparison_operator"
6788 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6789 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6791 (label_ref (match_operand 5 "" ""))
6793 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6794 (minus:SI (match_dup 2) (match_dup 3)))
6795 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6797 && (GET_CODE (operands[4]) == EQ
6798 || GET_CODE (operands[4]) == NE
6799 || GET_CODE (operands[4]) == GE
6800 || GET_CODE (operands[4]) == LT)"
6803 if (which_alternative == 0)
6804 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6805 else if (which_alternative == 1)
6807 /* We must provide an alternative for a hi reg because reload
6808 cannot handle output reloads on a jump instruction, but we
6809 can't subtract into that. Fortunately a mov from lo to hi
6810 does not clobber the condition codes. */
6811 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6812 output_asm_insn (\"mov\\t%0, %1\", operands);
6816 /* Similarly, but the target is memory. */
6817 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6818 output_asm_insn (\"str\\t%1, %0\", operands);
6821 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6824 return \"b%d4\\t%l5\";
6826 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6828 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6832 [(set (attr "far_jump")
6834 (ior (and (eq (symbol_ref ("which_alternative"))
6836 (eq_attr "length" "8"))
6837 (eq_attr "length" "10"))
6838 (const_string "yes")
6839 (const_string "no")))
6840 (set (attr "length")
6842 (eq (symbol_ref ("which_alternative"))
6845 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6846 (le (minus (match_dup 5) (pc)) (const_int 256)))
6849 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6850 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6854 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6855 (le (minus (match_dup 5) (pc)) (const_int 256)))
6858 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6859 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6864 (define_insn "*subsi3_cbranch_scratch"
6867 (match_operator 0 "arm_comparison_operator"
6868 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6869 (match_operand:SI 2 "nonmemory_operand" "l"))
6871 (label_ref (match_operand 3 "" ""))
6874 && (GET_CODE (operands[0]) == EQ
6875 || GET_CODE (operands[0]) == NE
6876 || GET_CODE (operands[0]) == GE
6877 || GET_CODE (operands[0]) == LT)"
6879 output_asm_insn (\"cmp\\t%1, %2\", operands);
6880 switch (get_attr_length (insn))
6882 case 4: return \"b%d0\\t%l3\";
6883 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6884 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6887 [(set (attr "far_jump")
6889 (eq_attr "length" "8")
6890 (const_string "yes")
6891 (const_string "no")))
6892 (set (attr "length")
6894 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6895 (le (minus (match_dup 3) (pc)) (const_int 256)))
6898 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6899 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6904 ;; Comparison and test insns
6906 (define_expand "cmpsi"
6907 [(match_operand:SI 0 "s_register_operand" "")
6908 (match_operand:SI 1 "arm_add_operand" "")]
6911 arm_compare_op0 = operands[0];
6912 arm_compare_op1 = operands[1];
6917 (define_expand "cmpsf"
6918 [(match_operand:SF 0 "s_register_operand" "")
6919 (match_operand:SF 1 "arm_float_compare_operand" "")]
6920 "TARGET_ARM && TARGET_HARD_FLOAT"
6922 arm_compare_op0 = operands[0];
6923 arm_compare_op1 = operands[1];
6928 (define_expand "cmpdf"
6929 [(match_operand:DF 0 "s_register_operand" "")
6930 (match_operand:DF 1 "arm_float_compare_operand" "")]
6931 "TARGET_ARM && TARGET_HARD_FLOAT"
6933 arm_compare_op0 = operands[0];
6934 arm_compare_op1 = operands[1];
6939 (define_insn "*arm_cmpsi_insn"
6940 [(set (reg:CC CC_REGNUM)
6941 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6942 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6947 [(set_attr "conds" "set")]
6950 (define_insn "*cmpsi_shiftsi"
6951 [(set (reg:CC CC_REGNUM)
6952 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6953 (match_operator:SI 3 "shift_operator"
6954 [(match_operand:SI 1 "s_register_operand" "r")
6955 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6958 [(set_attr "conds" "set")
6959 (set_attr "shift" "1")
6960 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6961 (const_string "alu_shift")
6962 (const_string "alu_shift_reg")))]
6965 (define_insn "*cmpsi_shiftsi_swp"
6966 [(set (reg:CC_SWP CC_REGNUM)
6967 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6968 [(match_operand:SI 1 "s_register_operand" "r")
6969 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6970 (match_operand:SI 0 "s_register_operand" "r")))]
6973 [(set_attr "conds" "set")
6974 (set_attr "shift" "1")
6975 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6976 (const_string "alu_shift")
6977 (const_string "alu_shift_reg")))]
6980 (define_insn "*cmpsi_negshiftsi_si"
6981 [(set (reg:CC_Z CC_REGNUM)
6983 (neg:SI (match_operator:SI 1 "shift_operator"
6984 [(match_operand:SI 2 "s_register_operand" "r")
6985 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6986 (match_operand:SI 0 "s_register_operand" "r")))]
6989 [(set_attr "conds" "set")
6990 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6991 (const_string "alu_shift")
6992 (const_string "alu_shift_reg")))]
6995 ;; Cirrus SF compare instruction
6996 (define_insn "*cirrus_cmpsf"
6997 [(set (reg:CCFP CC_REGNUM)
6998 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6999 (match_operand:SF 1 "cirrus_fp_register" "v")))]
7000 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7001 "cfcmps%?\\tr15, %V0, %V1"
7002 [(set_attr "type" "mav_farith")
7003 (set_attr "cirrus" "compare")]
7006 ;; Cirrus DF compare instruction
7007 (define_insn "*cirrus_cmpdf"
7008 [(set (reg:CCFP CC_REGNUM)
7009 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7010 (match_operand:DF 1 "cirrus_fp_register" "v")))]
7011 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7012 "cfcmpd%?\\tr15, %V0, %V1"
7013 [(set_attr "type" "mav_farith")
7014 (set_attr "cirrus" "compare")]
7017 ;; Cirrus DI compare instruction
7018 (define_expand "cmpdi"
7019 [(match_operand:DI 0 "cirrus_fp_register" "")
7020 (match_operand:DI 1 "cirrus_fp_register" "")]
7021 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7023 arm_compare_op0 = operands[0];
7024 arm_compare_op1 = operands[1];
7028 (define_insn "*cirrus_cmpdi"
7029 [(set (reg:CC CC_REGNUM)
7030 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7031 (match_operand:DI 1 "cirrus_fp_register" "v")))]
7032 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7033 "cfcmp64%?\\tr15, %V0, %V1"
7034 [(set_attr "type" "mav_farith")
7035 (set_attr "cirrus" "compare")]
7038 ; This insn allows redundant compares to be removed by cse, nothing should
7039 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7040 ; is deleted later on. The match_dup will match the mode here, so that
7041 ; mode changes of the condition codes aren't lost by this even though we don't
7042 ; specify what they are.
7044 (define_insn "*deleted_compare"
7045 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7047 "\\t%@ deleted compare"
7048 [(set_attr "conds" "set")
7049 (set_attr "length" "0")]
7053 ;; Conditional branch insns
7055 (define_expand "beq"
7057 (if_then_else (eq (match_dup 1) (const_int 0))
7058 (label_ref (match_operand 0 "" ""))
7061 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7064 (define_expand "bne"
7066 (if_then_else (ne (match_dup 1) (const_int 0))
7067 (label_ref (match_operand 0 "" ""))
7070 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7073 (define_expand "bgt"
7075 (if_then_else (gt (match_dup 1) (const_int 0))
7076 (label_ref (match_operand 0 "" ""))
7079 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7082 (define_expand "ble"
7084 (if_then_else (le (match_dup 1) (const_int 0))
7085 (label_ref (match_operand 0 "" ""))
7088 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7091 (define_expand "bge"
7093 (if_then_else (ge (match_dup 1) (const_int 0))
7094 (label_ref (match_operand 0 "" ""))
7097 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7100 (define_expand "blt"
7102 (if_then_else (lt (match_dup 1) (const_int 0))
7103 (label_ref (match_operand 0 "" ""))
7106 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7109 (define_expand "bgtu"
7111 (if_then_else (gtu (match_dup 1) (const_int 0))
7112 (label_ref (match_operand 0 "" ""))
7115 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7118 (define_expand "bleu"
7120 (if_then_else (leu (match_dup 1) (const_int 0))
7121 (label_ref (match_operand 0 "" ""))
7124 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7127 (define_expand "bgeu"
7129 (if_then_else (geu (match_dup 1) (const_int 0))
7130 (label_ref (match_operand 0 "" ""))
7133 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7136 (define_expand "bltu"
7138 (if_then_else (ltu (match_dup 1) (const_int 0))
7139 (label_ref (match_operand 0 "" ""))
7142 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7145 (define_expand "bunordered"
7147 (if_then_else (unordered (match_dup 1) (const_int 0))
7148 (label_ref (match_operand 0 "" ""))
7150 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7151 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7155 (define_expand "bordered"
7157 (if_then_else (ordered (match_dup 1) (const_int 0))
7158 (label_ref (match_operand 0 "" ""))
7160 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7161 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7165 (define_expand "bungt"
7167 (if_then_else (ungt (match_dup 1) (const_int 0))
7168 (label_ref (match_operand 0 "" ""))
7170 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7171 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7174 (define_expand "bunlt"
7176 (if_then_else (unlt (match_dup 1) (const_int 0))
7177 (label_ref (match_operand 0 "" ""))
7179 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7180 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7183 (define_expand "bunge"
7185 (if_then_else (unge (match_dup 1) (const_int 0))
7186 (label_ref (match_operand 0 "" ""))
7188 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7189 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7192 (define_expand "bunle"
7194 (if_then_else (unle (match_dup 1) (const_int 0))
7195 (label_ref (match_operand 0 "" ""))
7197 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7198 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7201 ;; The following two patterns need two branch instructions, since there is
7202 ;; no single instruction that will handle all cases.
7203 (define_expand "buneq"
7205 (if_then_else (uneq (match_dup 1) (const_int 0))
7206 (label_ref (match_operand 0 "" ""))
7208 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7209 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7212 (define_expand "bltgt"
7214 (if_then_else (ltgt (match_dup 1) (const_int 0))
7215 (label_ref (match_operand 0 "" ""))
7217 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7218 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7222 ;; Patterns to match conditional branch insns.
7225 ; Special pattern to match UNEQ.
7226 (define_insn "*arm_buneq"
7228 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7229 (label_ref (match_operand 0 "" ""))
7231 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7233 gcc_assert (!arm_ccfsm_state);
7235 return \"bvs\\t%l0\;beq\\t%l0\";
7237 [(set_attr "conds" "jump_clob")
7238 (set_attr "length" "8")]
7241 ; Special pattern to match LTGT.
7242 (define_insn "*arm_bltgt"
7244 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7245 (label_ref (match_operand 0 "" ""))
7247 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249 gcc_assert (!arm_ccfsm_state);
7251 return \"bmi\\t%l0\;bgt\\t%l0\";
7253 [(set_attr "conds" "jump_clob")
7254 (set_attr "length" "8")]
7257 (define_insn "*arm_cond_branch"
7259 (if_then_else (match_operator 1 "arm_comparison_operator"
7260 [(match_operand 2 "cc_register" "") (const_int 0)])
7261 (label_ref (match_operand 0 "" ""))
7265 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7267 arm_ccfsm_state += 2;
7270 return \"b%d1\\t%l0\";
7272 [(set_attr "conds" "use")
7273 (set_attr "type" "branch")]
7276 ; Special pattern to match reversed UNEQ.
7277 (define_insn "*arm_buneq_reversed"
7279 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7281 (label_ref (match_operand 0 "" ""))))]
7282 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7284 gcc_assert (!arm_ccfsm_state);
7286 return \"bmi\\t%l0\;bgt\\t%l0\";
7288 [(set_attr "conds" "jump_clob")
7289 (set_attr "length" "8")]
7292 ; Special pattern to match reversed LTGT.
7293 (define_insn "*arm_bltgt_reversed"
7295 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7297 (label_ref (match_operand 0 "" ""))))]
7298 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7300 gcc_assert (!arm_ccfsm_state);
7302 return \"bvs\\t%l0\;beq\\t%l0\";
7304 [(set_attr "conds" "jump_clob")
7305 (set_attr "length" "8")]
7308 (define_insn "*arm_cond_branch_reversed"
7310 (if_then_else (match_operator 1 "arm_comparison_operator"
7311 [(match_operand 2 "cc_register" "") (const_int 0)])
7313 (label_ref (match_operand 0 "" ""))))]
7316 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7318 arm_ccfsm_state += 2;
7321 return \"b%D1\\t%l0\";
7323 [(set_attr "conds" "use")
7324 (set_attr "type" "branch")]
7331 (define_expand "seq"
7332 [(set (match_operand:SI 0 "s_register_operand" "")
7333 (eq:SI (match_dup 1) (const_int 0)))]
7335 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7338 (define_expand "sne"
7339 [(set (match_operand:SI 0 "s_register_operand" "")
7340 (ne:SI (match_dup 1) (const_int 0)))]
7342 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7345 (define_expand "sgt"
7346 [(set (match_operand:SI 0 "s_register_operand" "")
7347 (gt:SI (match_dup 1) (const_int 0)))]
7349 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7352 (define_expand "sle"
7353 [(set (match_operand:SI 0 "s_register_operand" "")
7354 (le:SI (match_dup 1) (const_int 0)))]
7356 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7359 (define_expand "sge"
7360 [(set (match_operand:SI 0 "s_register_operand" "")
7361 (ge:SI (match_dup 1) (const_int 0)))]
7363 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7366 (define_expand "slt"
7367 [(set (match_operand:SI 0 "s_register_operand" "")
7368 (lt:SI (match_dup 1) (const_int 0)))]
7370 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7373 (define_expand "sgtu"
7374 [(set (match_operand:SI 0 "s_register_operand" "")
7375 (gtu:SI (match_dup 1) (const_int 0)))]
7377 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7380 (define_expand "sleu"
7381 [(set (match_operand:SI 0 "s_register_operand" "")
7382 (leu:SI (match_dup 1) (const_int 0)))]
7384 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7387 (define_expand "sgeu"
7388 [(set (match_operand:SI 0 "s_register_operand" "")
7389 (geu:SI (match_dup 1) (const_int 0)))]
7391 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7394 (define_expand "sltu"
7395 [(set (match_operand:SI 0 "s_register_operand" "")
7396 (ltu:SI (match_dup 1) (const_int 0)))]
7398 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7401 (define_expand "sunordered"
7402 [(set (match_operand:SI 0 "s_register_operand" "")
7403 (unordered:SI (match_dup 1) (const_int 0)))]
7404 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7405 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7409 (define_expand "sordered"
7410 [(set (match_operand:SI 0 "s_register_operand" "")
7411 (ordered:SI (match_dup 1) (const_int 0)))]
7412 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7413 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7417 (define_expand "sungt"
7418 [(set (match_operand:SI 0 "s_register_operand" "")
7419 (ungt:SI (match_dup 1) (const_int 0)))]
7420 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7421 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7425 (define_expand "sunge"
7426 [(set (match_operand:SI 0 "s_register_operand" "")
7427 (unge:SI (match_dup 1) (const_int 0)))]
7428 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7429 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7433 (define_expand "sunlt"
7434 [(set (match_operand:SI 0 "s_register_operand" "")
7435 (unlt:SI (match_dup 1) (const_int 0)))]
7436 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7437 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7441 (define_expand "sunle"
7442 [(set (match_operand:SI 0 "s_register_operand" "")
7443 (unle:SI (match_dup 1) (const_int 0)))]
7444 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7445 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7449 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7450 ;;; simple ARM instructions.
7452 ; (define_expand "suneq"
7453 ; [(set (match_operand:SI 0 "s_register_operand" "")
7454 ; (uneq:SI (match_dup 1) (const_int 0)))]
7455 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7456 ; "gcc_unreachable ();"
7459 ; (define_expand "sltgt"
7460 ; [(set (match_operand:SI 0 "s_register_operand" "")
7461 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7462 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7463 ; "gcc_unreachable ();"
7466 (define_insn "*mov_scc"
7467 [(set (match_operand:SI 0 "s_register_operand" "=r")
7468 (match_operator:SI 1 "arm_comparison_operator"
7469 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7471 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7472 [(set_attr "conds" "use")
7473 (set_attr "length" "8")]
7476 (define_insn "*mov_negscc"
7477 [(set (match_operand:SI 0 "s_register_operand" "=r")
7478 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7479 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7481 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7482 [(set_attr "conds" "use")
7483 (set_attr "length" "8")]
7486 (define_insn "*mov_notscc"
7487 [(set (match_operand:SI 0 "s_register_operand" "=r")
7488 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7489 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7491 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7492 [(set_attr "conds" "use")
7493 (set_attr "length" "8")]
7496 (define_expand "cstoresi4"
7497 [(set (match_operand:SI 0 "s_register_operand" "")
7498 (match_operator:SI 1 "arm_comparison_operator"
7499 [(match_operand:SI 2 "s_register_operand" "")
7500 (match_operand:SI 3 "reg_or_int_operand" "")]))]
7503 rtx op3, scratch, scratch2;
7505 if (operands[3] == const0_rtx)
7507 switch (GET_CODE (operands[1]))
7510 emit_insn (gen_cstoresi_eq0_thumb (operands[0], operands[2]));
7514 emit_insn (gen_cstoresi_ne0_thumb (operands[0], operands[2]));
7518 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7519 NULL_RTX, 0, OPTAB_WIDEN);
7520 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7521 NULL_RTX, 0, OPTAB_WIDEN);
7522 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7523 operands[0], 1, OPTAB_WIDEN);
7527 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7529 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7530 NULL_RTX, 1, OPTAB_WIDEN);
7534 scratch = expand_binop (SImode, ashr_optab, operands[2],
7535 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7536 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7537 NULL_RTX, 0, OPTAB_WIDEN);
7538 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7542 /* LT is handled by generic code. No need for unsigned with 0. */
7549 switch (GET_CODE (operands[1]))
7552 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7553 NULL_RTX, 0, OPTAB_WIDEN);
7554 emit_insn (gen_cstoresi_eq0_thumb (operands[0], scratch));
7558 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7559 NULL_RTX, 0, OPTAB_WIDEN);
7560 emit_insn (gen_cstoresi_ne0_thumb (operands[0], scratch));
7564 op3 = force_reg (SImode, operands[3]);
7566 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7567 NULL_RTX, 1, OPTAB_WIDEN);
7568 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7569 NULL_RTX, 0, OPTAB_WIDEN);
7570 emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
7576 if (!thumb_cmp_operand (op3, SImode))
7577 op3 = force_reg (SImode, op3);
7578 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7579 NULL_RTX, 0, OPTAB_WIDEN);
7580 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7581 NULL_RTX, 1, OPTAB_WIDEN);
7582 emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch2,
7587 op3 = force_reg (SImode, operands[3]);
7588 scratch = force_reg (SImode, const0_rtx);
7589 emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
7595 if (!thumb_cmp_operand (op3, SImode))
7596 op3 = force_reg (SImode, op3);
7597 scratch = force_reg (SImode, const0_rtx);
7598 emit_insn (gen_thumb_addsi3_addgeu (operands[0], scratch, scratch,
7604 if (!thumb_cmp_operand (op3, SImode))
7605 op3 = force_reg (SImode, op3);
7606 scratch = gen_reg_rtx (SImode);
7607 emit_insn (gen_cstoresi_nltu_thumb (scratch, operands[2], op3));
7608 emit_insn (gen_negsi2 (operands[0], scratch));
7612 op3 = force_reg (SImode, operands[3]);
7613 scratch = gen_reg_rtx (SImode);
7614 emit_insn (gen_cstoresi_nltu_thumb (scratch, op3, operands[2]));
7615 emit_insn (gen_negsi2 (operands[0], scratch));
7618 /* No good sequences for GT, LT. */
7625 (define_expand "cstoresi_eq0_thumb"
7627 [(set (match_operand:SI 0 "s_register_operand" "")
7628 (eq:SI (match_operand:SI 1 "s_register_operand" "")
7630 (clobber (match_dup:SI 2))])]
7632 "operands[2] = gen_reg_rtx (SImode);"
7635 (define_expand "cstoresi_ne0_thumb"
7637 [(set (match_operand:SI 0 "s_register_operand" "")
7638 (ne:SI (match_operand:SI 1 "s_register_operand" "")
7640 (clobber (match_dup:SI 2))])]
7642 "operands[2] = gen_reg_rtx (SImode);"
7645 (define_insn "*cstoresi_eq0_thumb_insn"
7646 [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7647 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7649 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7652 neg\\t%0, %1\;adc\\t%0, %0, %1
7653 neg\\t%2, %1\;adc\\t%0, %1, %2"
7654 [(set_attr "length" "4")]
7657 (define_insn "*cstoresi_ne0_thumb_insn"
7658 [(set (match_operand:SI 0 "s_register_operand" "=l")
7659 (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7661 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7663 "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7664 [(set_attr "length" "4")]
7667 (define_insn "cstoresi_nltu_thumb"
7668 [(set (match_operand:SI 0 "s_register_operand" "=l,l")
7669 (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
7670 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r"))))]
7672 "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
7673 [(set_attr "length" "4")]
7676 ;; Used as part of the expansion of thumb les sequence.
7677 (define_insn "thumb_addsi3_addgeu"
7678 [(set (match_operand:SI 0 "s_register_operand" "=l")
7679 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7680 (match_operand:SI 2 "s_register_operand" "l"))
7681 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
7682 (match_operand:SI 4 "thumb_cmp_operand" "lI"))))]
7684 "cmp\\t%3, %4\;adc\\t%0, %1, %2"
7685 [(set_attr "length" "4")]
7689 ;; Conditional move insns
7691 (define_expand "movsicc"
7692 [(set (match_operand:SI 0 "s_register_operand" "")
7693 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7694 (match_operand:SI 2 "arm_not_operand" "")
7695 (match_operand:SI 3 "arm_not_operand" "")))]
7699 enum rtx_code code = GET_CODE (operands[1]);
7702 if (code == UNEQ || code == LTGT)
7705 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7706 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7710 (define_expand "movsfcc"
7711 [(set (match_operand:SF 0 "s_register_operand" "")
7712 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7713 (match_operand:SF 2 "s_register_operand" "")
7714 (match_operand:SF 3 "nonmemory_operand" "")))]
7718 enum rtx_code code = GET_CODE (operands[1]);
7721 if (code == UNEQ || code == LTGT)
7724 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7725 Otherwise, ensure it is a valid FP add operand */
7726 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7727 || (!arm_float_add_operand (operands[3], SFmode)))
7728 operands[3] = force_reg (SFmode, operands[3]);
7730 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7731 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7735 (define_expand "movdfcc"
7736 [(set (match_operand:DF 0 "s_register_operand" "")
7737 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7738 (match_operand:DF 2 "s_register_operand" "")
7739 (match_operand:DF 3 "arm_float_add_operand" "")))]
7740 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7743 enum rtx_code code = GET_CODE (operands[1]);
7746 if (code == UNEQ || code == LTGT)
7749 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7750 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7754 (define_insn "*movsicc_insn"
7755 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7757 (match_operator 3 "arm_comparison_operator"
7758 [(match_operand 4 "cc_register" "") (const_int 0)])
7759 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7760 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7767 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7768 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7769 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7770 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7771 [(set_attr "length" "4,4,4,4,8,8,8,8")
7772 (set_attr "conds" "use")]
7775 (define_insn "*movsfcc_soft_insn"
7776 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7777 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7778 [(match_operand 4 "cc_register" "") (const_int 0)])
7779 (match_operand:SF 1 "s_register_operand" "0,r")
7780 (match_operand:SF 2 "s_register_operand" "r,0")))]
7781 "TARGET_ARM && TARGET_SOFT_FLOAT"
7785 [(set_attr "conds" "use")]
7789 ;; Jump and linkage insns
7791 (define_expand "jump"
7793 (label_ref (match_operand 0 "" "")))]
7798 (define_insn "*arm_jump"
7800 (label_ref (match_operand 0 "" "")))]
7804 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7806 arm_ccfsm_state += 2;
7809 return \"b%?\\t%l0\";
7812 [(set_attr "predicable" "yes")]
7815 (define_insn "*thumb_jump"
7817 (label_ref (match_operand 0 "" "")))]
7820 if (get_attr_length (insn) == 2)
7822 return \"bl\\t%l0\\t%@ far jump\";
7824 [(set (attr "far_jump")
7826 (eq_attr "length" "4")
7827 (const_string "yes")
7828 (const_string "no")))
7829 (set (attr "length")
7831 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7832 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7837 (define_expand "call"
7838 [(parallel [(call (match_operand 0 "memory_operand" "")
7839 (match_operand 1 "general_operand" ""))
7840 (use (match_operand 2 "" ""))
7841 (clobber (reg:SI LR_REGNUM))])]
7847 /* In an untyped call, we can get NULL for operand 2. */
7848 if (operands[2] == NULL_RTX)
7849 operands[2] = const0_rtx;
7851 /* This is to decide if we should generate indirect calls by loading the
7852 32 bit address of the callee into a register before performing the
7853 branch and link. operand[2] encodes the long_call/short_call
7854 attribute of the function being called. This attribute is set whenever
7855 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7856 is used, and the short_call attribute can also be set if function is
7857 declared as static or if it has already been defined in the current
7858 compilation unit. See arm.c and arm.h for info about this. The third
7859 parameter to arm_is_longcall_p is used to tell it which pattern
7861 callee = XEXP (operands[0], 0);
7863 if ((GET_CODE (callee) == SYMBOL_REF
7864 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7865 || (GET_CODE (callee) != SYMBOL_REF
7866 && GET_CODE (callee) != REG))
7867 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7871 (define_insn "*call_reg_armv5"
7872 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7873 (match_operand 1 "" ""))
7874 (use (match_operand 2 "" ""))
7875 (clobber (reg:SI LR_REGNUM))]
7876 "TARGET_ARM && arm_arch5"
7878 [(set_attr "type" "call")]
7881 (define_insn "*call_reg_arm"
7882 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7883 (match_operand 1 "" ""))
7884 (use (match_operand 2 "" ""))
7885 (clobber (reg:SI LR_REGNUM))]
7886 "TARGET_ARM && !arm_arch5"
7888 return output_call (operands);
7890 ;; length is worst case, normally it is only two
7891 [(set_attr "length" "12")
7892 (set_attr "type" "call")]
7895 (define_insn "*call_mem"
7896 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7897 (match_operand 1 "" ""))
7898 (use (match_operand 2 "" ""))
7899 (clobber (reg:SI LR_REGNUM))]
7902 return output_call_mem (operands);
7904 [(set_attr "length" "12")
7905 (set_attr "type" "call")]
7908 (define_insn "*call_reg_thumb_v5"
7909 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7910 (match_operand 1 "" ""))
7911 (use (match_operand 2 "" ""))
7912 (clobber (reg:SI LR_REGNUM))]
7913 "TARGET_THUMB && arm_arch5"
7915 [(set_attr "length" "2")
7916 (set_attr "type" "call")]
7919 (define_insn "*call_reg_thumb"
7920 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7921 (match_operand 1 "" ""))
7922 (use (match_operand 2 "" ""))
7923 (clobber (reg:SI LR_REGNUM))]
7924 "TARGET_THUMB && !arm_arch5"
7927 if (!TARGET_CALLER_INTERWORKING)
7928 return thumb_call_via_reg (operands[0]);
7929 else if (operands[1] == const0_rtx)
7930 return \"bl\\t%__interwork_call_via_%0\";
7931 else if (frame_pointer_needed)
7932 return \"bl\\t%__interwork_r7_call_via_%0\";
7934 return \"bl\\t%__interwork_r11_call_via_%0\";
7936 [(set_attr "type" "call")]
7939 (define_expand "call_value"
7940 [(parallel [(set (match_operand 0 "" "")
7941 (call (match_operand 1 "memory_operand" "")
7942 (match_operand 2 "general_operand" "")))
7943 (use (match_operand 3 "" ""))
7944 (clobber (reg:SI LR_REGNUM))])]
7948 rtx callee = XEXP (operands[1], 0);
7950 /* In an untyped call, we can get NULL for operand 2. */
7951 if (operands[3] == 0)
7952 operands[3] = const0_rtx;
7954 /* See the comment in define_expand \"call\". */
7955 if ((GET_CODE (callee) == SYMBOL_REF
7956 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7957 || (GET_CODE (callee) != SYMBOL_REF
7958 && GET_CODE (callee) != REG))
7959 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7963 (define_insn "*call_value_reg_armv5"
7964 [(set (match_operand 0 "" "")
7965 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7966 (match_operand 2 "" "")))
7967 (use (match_operand 3 "" ""))
7968 (clobber (reg:SI LR_REGNUM))]
7969 "TARGET_ARM && arm_arch5"
7971 [(set_attr "type" "call")]
7974 (define_insn "*call_value_reg_arm"
7975 [(set (match_operand 0 "" "")
7976 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7977 (match_operand 2 "" "")))
7978 (use (match_operand 3 "" ""))
7979 (clobber (reg:SI LR_REGNUM))]
7980 "TARGET_ARM && !arm_arch5"
7982 return output_call (&operands[1]);
7984 [(set_attr "length" "12")
7985 (set_attr "type" "call")]
7988 (define_insn "*call_value_mem"
7989 [(set (match_operand 0 "" "")
7990 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7991 (match_operand 2 "" "")))
7992 (use (match_operand 3 "" ""))
7993 (clobber (reg:SI LR_REGNUM))]
7994 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7996 return output_call_mem (&operands[1]);
7998 [(set_attr "length" "12")
7999 (set_attr "type" "call")]
8002 (define_insn "*call_value_reg_thumb_v5"
8003 [(set (match_operand 0 "" "")
8004 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8005 (match_operand 2 "" "")))
8006 (use (match_operand 3 "" ""))
8007 (clobber (reg:SI LR_REGNUM))]
8008 "TARGET_THUMB && arm_arch5"
8010 [(set_attr "length" "2")
8011 (set_attr "type" "call")]
8014 (define_insn "*call_value_reg_thumb"
8015 [(set (match_operand 0 "" "")
8016 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8017 (match_operand 2 "" "")))
8018 (use (match_operand 3 "" ""))
8019 (clobber (reg:SI LR_REGNUM))]
8020 "TARGET_THUMB && !arm_arch5"
8023 if (!TARGET_CALLER_INTERWORKING)
8024 return thumb_call_via_reg (operands[1]);
8025 else if (operands[2] == const0_rtx)
8026 return \"bl\\t%__interwork_call_via_%1\";
8027 else if (frame_pointer_needed)
8028 return \"bl\\t%__interwork_r7_call_via_%1\";
8030 return \"bl\\t%__interwork_r11_call_via_%1\";
8032 [(set_attr "type" "call")]
8035 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8036 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8038 (define_insn "*call_symbol"
8039 [(call (mem:SI (match_operand:SI 0 "" ""))
8040 (match_operand 1 "" ""))
8041 (use (match_operand 2 "" ""))
8042 (clobber (reg:SI LR_REGNUM))]
8044 && (GET_CODE (operands[0]) == SYMBOL_REF)
8045 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8048 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8050 [(set_attr "type" "call")]
8053 (define_insn "*call_value_symbol"
8054 [(set (match_operand 0 "" "")
8055 (call (mem:SI (match_operand:SI 1 "" ""))
8056 (match_operand:SI 2 "" "")))
8057 (use (match_operand 3 "" ""))
8058 (clobber (reg:SI LR_REGNUM))]
8060 && (GET_CODE (operands[1]) == SYMBOL_REF)
8061 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8064 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8066 [(set_attr "type" "call")]
8069 (define_insn "*call_insn"
8070 [(call (mem:SI (match_operand:SI 0 "" ""))
8071 (match_operand:SI 1 "" ""))
8072 (use (match_operand 2 "" ""))
8073 (clobber (reg:SI LR_REGNUM))]
8075 && GET_CODE (operands[0]) == SYMBOL_REF
8076 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
8078 [(set_attr "length" "4")
8079 (set_attr "type" "call")]
8082 (define_insn "*call_value_insn"
8083 [(set (match_operand 0 "" "")
8084 (call (mem:SI (match_operand 1 "" ""))
8085 (match_operand 2 "" "")))
8086 (use (match_operand 3 "" ""))
8087 (clobber (reg:SI LR_REGNUM))]
8089 && GET_CODE (operands[1]) == SYMBOL_REF
8090 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
8092 [(set_attr "length" "4")
8093 (set_attr "type" "call")]
8096 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8097 (define_expand "sibcall"
8098 [(parallel [(call (match_operand 0 "memory_operand" "")
8099 (match_operand 1 "general_operand" ""))
8101 (use (match_operand 2 "" ""))])]
8105 if (operands[2] == NULL_RTX)
8106 operands[2] = const0_rtx;
8110 (define_expand "sibcall_value"
8111 [(parallel [(set (match_operand 0 "" "")
8112 (call (match_operand 1 "memory_operand" "")
8113 (match_operand 2 "general_operand" "")))
8115 (use (match_operand 3 "" ""))])]
8119 if (operands[3] == NULL_RTX)
8120 operands[3] = const0_rtx;
8124 (define_insn "*sibcall_insn"
8125 [(call (mem:SI (match_operand:SI 0 "" "X"))
8126 (match_operand 1 "" ""))
8128 (use (match_operand 2 "" ""))]
8129 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
8131 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8133 [(set_attr "type" "call")]
8136 (define_insn "*sibcall_value_insn"
8137 [(set (match_operand 0 "" "")
8138 (call (mem:SI (match_operand:SI 1 "" "X"))
8139 (match_operand 2 "" "")))
8141 (use (match_operand 3 "" ""))]
8142 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
8144 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8146 [(set_attr "type" "call")]
8149 ;; Often the return insn will be the same as loading from memory, so set attr
8150 (define_insn "return"
8152 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8155 if (arm_ccfsm_state == 2)
8157 arm_ccfsm_state += 2;
8160 return output_return_instruction (const_true_rtx, TRUE, FALSE);
8162 [(set_attr "type" "load1")
8163 (set_attr "length" "12")
8164 (set_attr "predicable" "yes")]
8167 (define_insn "*cond_return"
8169 (if_then_else (match_operator 0 "arm_comparison_operator"
8170 [(match_operand 1 "cc_register" "") (const_int 0)])
8173 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8176 if (arm_ccfsm_state == 2)
8178 arm_ccfsm_state += 2;
8181 return output_return_instruction (operands[0], TRUE, FALSE);
8183 [(set_attr "conds" "use")
8184 (set_attr "length" "12")
8185 (set_attr "type" "load1")]
8188 (define_insn "*cond_return_inverted"
8190 (if_then_else (match_operator 0 "arm_comparison_operator"
8191 [(match_operand 1 "cc_register" "") (const_int 0)])
8194 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8197 if (arm_ccfsm_state == 2)
8199 arm_ccfsm_state += 2;
8202 return output_return_instruction (operands[0], TRUE, TRUE);
8204 [(set_attr "conds" "use")
8205 (set_attr "length" "12")
8206 (set_attr "type" "load1")]
8209 ;; Generate a sequence of instructions to determine if the processor is
8210 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8213 (define_expand "return_addr_mask"
8215 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8217 (set (match_operand:SI 0 "s_register_operand" "")
8218 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8220 (const_int 67108860)))] ; 0x03fffffc
8223 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8226 (define_insn "*check_arch2"
8227 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8228 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8231 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8232 [(set_attr "length" "8")
8233 (set_attr "conds" "set")]
8236 ;; Call subroutine returning any type.
8238 (define_expand "untyped_call"
8239 [(parallel [(call (match_operand 0 "" "")
8241 (match_operand 1 "" "")
8242 (match_operand 2 "" "")])]
8247 rtx par = gen_rtx_PARALLEL (VOIDmode,
8248 rtvec_alloc (XVECLEN (operands[2], 0)));
8249 rtx addr = gen_reg_rtx (Pmode);
8253 emit_move_insn (addr, XEXP (operands[1], 0));
8254 mem = change_address (operands[1], BLKmode, addr);
8256 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8258 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8260 /* Default code only uses r0 as a return value, but we could
8261 be using anything up to 4 registers. */
8262 if (REGNO (src) == R0_REGNUM)
8263 src = gen_rtx_REG (TImode, R0_REGNUM);
8265 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8267 size += GET_MODE_SIZE (GET_MODE (src));
8270 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8275 for (i = 0; i < XVECLEN (par, 0); i++)
8277 HOST_WIDE_INT offset = 0;
8278 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8281 emit_move_insn (addr, plus_constant (addr, size));
8283 mem = change_address (mem, GET_MODE (reg), NULL);
8284 if (REGNO (reg) == R0_REGNUM)
8286 /* On thumb we have to use a write-back instruction. */
8287 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8288 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8289 size = TARGET_ARM ? 16 : 0;
8293 emit_move_insn (mem, reg);
8294 size = GET_MODE_SIZE (GET_MODE (reg));
8298 /* The optimizer does not know that the call sets the function value
8299 registers we stored in the result block. We avoid problems by
8300 claiming that all hard registers are used and clobbered at this
8302 emit_insn (gen_blockage ());
8308 (define_expand "untyped_return"
8309 [(match_operand:BLK 0 "memory_operand" "")
8310 (match_operand 1 "" "")]
8315 rtx addr = gen_reg_rtx (Pmode);
8319 emit_move_insn (addr, XEXP (operands[0], 0));
8320 mem = change_address (operands[0], BLKmode, addr);
8322 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8324 HOST_WIDE_INT offset = 0;
8325 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8328 emit_move_insn (addr, plus_constant (addr, size));
8330 mem = change_address (mem, GET_MODE (reg), NULL);
8331 if (REGNO (reg) == R0_REGNUM)
8333 /* On thumb we have to use a write-back instruction. */
8334 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8335 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8336 size = TARGET_ARM ? 16 : 0;
8340 emit_move_insn (reg, mem);
8341 size = GET_MODE_SIZE (GET_MODE (reg));
8345 /* Emit USE insns before the return. */
8346 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8347 emit_insn (gen_rtx_USE (VOIDmode,
8348 SET_DEST (XVECEXP (operands[1], 0, i))));
8350 /* Construct the return. */
8351 expand_naked_return ();
8357 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8358 ;; all of memory. This blocks insns from being moved across this point.
8360 (define_insn "blockage"
8361 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8364 [(set_attr "length" "0")
8365 (set_attr "type" "block")]
8368 (define_expand "casesi"
8369 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8370 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8371 (match_operand:SI 2 "const_int_operand" "") ; total range
8372 (match_operand:SI 3 "" "") ; table label
8373 (match_operand:SI 4 "" "")] ; Out of range label
8378 if (operands[1] != const0_rtx)
8380 reg = gen_reg_rtx (SImode);
8382 emit_insn (gen_addsi3 (reg, operands[0],
8383 GEN_INT (-INTVAL (operands[1]))));
8387 if (!const_ok_for_arm (INTVAL (operands[2])))
8388 operands[2] = force_reg (SImode, operands[2]);
8390 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8396 ;; The USE in this pattern is needed to tell flow analysis that this is
8397 ;; a CASESI insn. It has no other purpose.
8398 (define_insn "casesi_internal"
8399 [(parallel [(set (pc)
8401 (leu (match_operand:SI 0 "s_register_operand" "r")
8402 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8403 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8404 (label_ref (match_operand 2 "" ""))))
8405 (label_ref (match_operand 3 "" ""))))
8406 (clobber (reg:CC CC_REGNUM))
8407 (use (label_ref (match_dup 2)))])]
8411 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8412 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8414 [(set_attr "conds" "clob")
8415 (set_attr "length" "12")]
8418 (define_expand "indirect_jump"
8420 (match_operand:SI 0 "s_register_operand" ""))]
8425 ;; NB Never uses BX.
8426 (define_insn "*arm_indirect_jump"
8428 (match_operand:SI 0 "s_register_operand" "r"))]
8430 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8431 [(set_attr "predicable" "yes")]
8434 (define_insn "*load_indirect_jump"
8436 (match_operand:SI 0 "memory_operand" "m"))]
8438 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8439 [(set_attr "type" "load1")
8440 (set_attr "pool_range" "4096")
8441 (set_attr "neg_pool_range" "4084")
8442 (set_attr "predicable" "yes")]
8445 ;; NB Never uses BX.
8446 (define_insn "*thumb_indirect_jump"
8448 (match_operand:SI 0 "register_operand" "l*r"))]
8451 [(set_attr "conds" "clob")
8452 (set_attr "length" "2")]
8463 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8464 return \"mov\\tr8, r8\";
8466 [(set (attr "length")
8467 (if_then_else (eq_attr "is_thumb" "yes")
8473 ;; Patterns to allow combination of arithmetic, cond code and shifts
8475 (define_insn "*arith_shiftsi"
8476 [(set (match_operand:SI 0 "s_register_operand" "=r")
8477 (match_operator:SI 1 "shiftable_operator"
8478 [(match_operator:SI 3 "shift_operator"
8479 [(match_operand:SI 4 "s_register_operand" "r")
8480 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8481 (match_operand:SI 2 "s_register_operand" "r")]))]
8483 "%i1%?\\t%0, %2, %4%S3"
8484 [(set_attr "predicable" "yes")
8485 (set_attr "shift" "4")
8486 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8487 (const_string "alu_shift")
8488 (const_string "alu_shift_reg")))]
8492 [(set (match_operand:SI 0 "s_register_operand" "")
8493 (match_operator:SI 1 "shiftable_operator"
8494 [(match_operator:SI 2 "shiftable_operator"
8495 [(match_operator:SI 3 "shift_operator"
8496 [(match_operand:SI 4 "s_register_operand" "")
8497 (match_operand:SI 5 "reg_or_int_operand" "")])
8498 (match_operand:SI 6 "s_register_operand" "")])
8499 (match_operand:SI 7 "arm_rhs_operand" "")]))
8500 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8503 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8506 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8509 (define_insn "*arith_shiftsi_compare0"
8510 [(set (reg:CC_NOOV CC_REGNUM)
8511 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8512 [(match_operator:SI 3 "shift_operator"
8513 [(match_operand:SI 4 "s_register_operand" "r")
8514 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8515 (match_operand:SI 2 "s_register_operand" "r")])
8517 (set (match_operand:SI 0 "s_register_operand" "=r")
8518 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8521 "%i1%?s\\t%0, %2, %4%S3"
8522 [(set_attr "conds" "set")
8523 (set_attr "shift" "4")
8524 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8525 (const_string "alu_shift")
8526 (const_string "alu_shift_reg")))]
8529 (define_insn "*arith_shiftsi_compare0_scratch"
8530 [(set (reg:CC_NOOV CC_REGNUM)
8531 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8532 [(match_operator:SI 3 "shift_operator"
8533 [(match_operand:SI 4 "s_register_operand" "r")
8534 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8535 (match_operand:SI 2 "s_register_operand" "r")])
8537 (clobber (match_scratch:SI 0 "=r"))]
8539 "%i1%?s\\t%0, %2, %4%S3"
8540 [(set_attr "conds" "set")
8541 (set_attr "shift" "4")
8542 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8543 (const_string "alu_shift")
8544 (const_string "alu_shift_reg")))]
8547 (define_insn "*sub_shiftsi"
8548 [(set (match_operand:SI 0 "s_register_operand" "=r")
8549 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8550 (match_operator:SI 2 "shift_operator"
8551 [(match_operand:SI 3 "s_register_operand" "r")
8552 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8554 "sub%?\\t%0, %1, %3%S2"
8555 [(set_attr "predicable" "yes")
8556 (set_attr "shift" "3")
8557 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8558 (const_string "alu_shift")
8559 (const_string "alu_shift_reg")))]
8562 (define_insn "*sub_shiftsi_compare0"
8563 [(set (reg:CC_NOOV CC_REGNUM)
8565 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8566 (match_operator:SI 2 "shift_operator"
8567 [(match_operand:SI 3 "s_register_operand" "r")
8568 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8570 (set (match_operand:SI 0 "s_register_operand" "=r")
8571 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8574 "sub%?s\\t%0, %1, %3%S2"
8575 [(set_attr "conds" "set")
8576 (set_attr "shift" "3")
8577 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8578 (const_string "alu_shift")
8579 (const_string "alu_shift_reg")))]
8582 (define_insn "*sub_shiftsi_compare0_scratch"
8583 [(set (reg:CC_NOOV CC_REGNUM)
8585 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8586 (match_operator:SI 2 "shift_operator"
8587 [(match_operand:SI 3 "s_register_operand" "r")
8588 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8590 (clobber (match_scratch:SI 0 "=r"))]
8592 "sub%?s\\t%0, %1, %3%S2"
8593 [(set_attr "conds" "set")
8594 (set_attr "shift" "3")
8595 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8596 (const_string "alu_shift")
8597 (const_string "alu_shift_reg")))]
8602 (define_insn "*and_scc"
8603 [(set (match_operand:SI 0 "s_register_operand" "=r")
8604 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8605 [(match_operand 3 "cc_register" "") (const_int 0)])
8606 (match_operand:SI 2 "s_register_operand" "r")))]
8608 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8609 [(set_attr "conds" "use")
8610 (set_attr "length" "8")]
8613 (define_insn "*ior_scc"
8614 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8615 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8616 [(match_operand 3 "cc_register" "") (const_int 0)])
8617 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8621 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8622 [(set_attr "conds" "use")
8623 (set_attr "length" "4,8")]
8626 (define_insn "*compare_scc"
8627 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8628 (match_operator:SI 1 "arm_comparison_operator"
8629 [(match_operand:SI 2 "s_register_operand" "r,r")
8630 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8631 (clobber (reg:CC CC_REGNUM))]
8634 if (operands[3] == const0_rtx)
8636 if (GET_CODE (operands[1]) == LT)
8637 return \"mov\\t%0, %2, lsr #31\";
8639 if (GET_CODE (operands[1]) == GE)
8640 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8642 if (GET_CODE (operands[1]) == EQ)
8643 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8646 if (GET_CODE (operands[1]) == NE)
8648 if (which_alternative == 1)
8649 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8650 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8652 if (which_alternative == 1)
8653 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8655 output_asm_insn (\"cmp\\t%2, %3\", operands);
8656 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8658 [(set_attr "conds" "clob")
8659 (set_attr "length" "12")]
8662 (define_insn "*cond_move"
8663 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8664 (if_then_else:SI (match_operator 3 "equality_operator"
8665 [(match_operator 4 "arm_comparison_operator"
8666 [(match_operand 5 "cc_register" "") (const_int 0)])
8668 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8669 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8672 if (GET_CODE (operands[3]) == NE)
8674 if (which_alternative != 1)
8675 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8676 if (which_alternative != 0)
8677 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8680 if (which_alternative != 0)
8681 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8682 if (which_alternative != 1)
8683 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8686 [(set_attr "conds" "use")
8687 (set_attr "length" "4,4,8")]
8690 (define_insn "*cond_arith"
8691 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8692 (match_operator:SI 5 "shiftable_operator"
8693 [(match_operator:SI 4 "arm_comparison_operator"
8694 [(match_operand:SI 2 "s_register_operand" "r,r")
8695 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8696 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8697 (clobber (reg:CC CC_REGNUM))]
8700 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8701 return \"%i5\\t%0, %1, %2, lsr #31\";
8703 output_asm_insn (\"cmp\\t%2, %3\", operands);
8704 if (GET_CODE (operands[5]) == AND)
8705 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8706 else if (GET_CODE (operands[5]) == MINUS)
8707 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8708 else if (which_alternative != 0)
8709 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8710 return \"%i5%d4\\t%0, %1, #1\";
8712 [(set_attr "conds" "clob")
8713 (set_attr "length" "12")]
8716 (define_insn "*cond_sub"
8717 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8718 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8719 (match_operator:SI 4 "arm_comparison_operator"
8720 [(match_operand:SI 2 "s_register_operand" "r,r")
8721 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8722 (clobber (reg:CC CC_REGNUM))]
8725 output_asm_insn (\"cmp\\t%2, %3\", operands);
8726 if (which_alternative != 0)
8727 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8728 return \"sub%d4\\t%0, %1, #1\";
8730 [(set_attr "conds" "clob")
8731 (set_attr "length" "8,12")]
8734 (define_insn "*cmp_ite0"
8735 [(set (match_operand 6 "dominant_cc_register" "")
8738 (match_operator 4 "arm_comparison_operator"
8739 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8740 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8741 (match_operator:SI 5 "arm_comparison_operator"
8742 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8743 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8749 static const char * const opcodes[4][2] =
8751 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8752 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8753 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8754 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8755 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8756 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8757 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8758 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8761 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8763 return opcodes[which_alternative][swap];
8765 [(set_attr "conds" "set")
8766 (set_attr "length" "8")]
8769 (define_insn "*cmp_ite1"
8770 [(set (match_operand 6 "dominant_cc_register" "")
8773 (match_operator 4 "arm_comparison_operator"
8774 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8775 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8776 (match_operator:SI 5 "arm_comparison_operator"
8777 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8778 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8784 static const char * const opcodes[4][2] =
8786 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8787 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8788 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8789 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8790 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8791 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8792 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8793 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8796 comparison_dominates_p (GET_CODE (operands[5]),
8797 reverse_condition (GET_CODE (operands[4])));
8799 return opcodes[which_alternative][swap];
8801 [(set_attr "conds" "set")
8802 (set_attr "length" "8")]
8805 (define_insn "*cmp_and"
8806 [(set (match_operand 6 "dominant_cc_register" "")
8809 (match_operator 4 "arm_comparison_operator"
8810 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8811 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8812 (match_operator:SI 5 "arm_comparison_operator"
8813 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8814 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8819 static const char *const opcodes[4][2] =
8821 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8822 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8823 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8824 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8825 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8826 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8827 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8828 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8831 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8833 return opcodes[which_alternative][swap];
8835 [(set_attr "conds" "set")
8836 (set_attr "predicable" "no")
8837 (set_attr "length" "8")]
8840 (define_insn "*cmp_ior"
8841 [(set (match_operand 6 "dominant_cc_register" "")
8844 (match_operator 4 "arm_comparison_operator"
8845 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8846 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8847 (match_operator:SI 5 "arm_comparison_operator"
8848 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8849 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8854 static const char *const opcodes[4][2] =
8856 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8857 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8858 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8859 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8860 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8861 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8862 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8863 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8866 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8868 return opcodes[which_alternative][swap];
8871 [(set_attr "conds" "set")
8872 (set_attr "length" "8")]
8875 (define_insn_and_split "*ior_scc_scc"
8876 [(set (match_operand:SI 0 "s_register_operand" "=r")
8877 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8878 [(match_operand:SI 1 "s_register_operand" "r")
8879 (match_operand:SI 2 "arm_add_operand" "rIL")])
8880 (match_operator:SI 6 "arm_comparison_operator"
8881 [(match_operand:SI 4 "s_register_operand" "r")
8882 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8883 (clobber (reg:CC CC_REGNUM))]
8885 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8888 "TARGET_ARM && reload_completed"
8892 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8893 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8895 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8897 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8900 [(set_attr "conds" "clob")
8901 (set_attr "length" "16")])
8903 ; If the above pattern is followed by a CMP insn, then the compare is
8904 ; redundant, since we can rework the conditional instruction that follows.
8905 (define_insn_and_split "*ior_scc_scc_cmp"
8906 [(set (match_operand 0 "dominant_cc_register" "")
8907 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8908 [(match_operand:SI 1 "s_register_operand" "r")
8909 (match_operand:SI 2 "arm_add_operand" "rIL")])
8910 (match_operator:SI 6 "arm_comparison_operator"
8911 [(match_operand:SI 4 "s_register_operand" "r")
8912 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8914 (set (match_operand:SI 7 "s_register_operand" "=r")
8915 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8916 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8919 "TARGET_ARM && reload_completed"
8923 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8924 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8926 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8928 [(set_attr "conds" "set")
8929 (set_attr "length" "16")])
8931 (define_insn_and_split "*and_scc_scc"
8932 [(set (match_operand:SI 0 "s_register_operand" "=r")
8933 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8934 [(match_operand:SI 1 "s_register_operand" "r")
8935 (match_operand:SI 2 "arm_add_operand" "rIL")])
8936 (match_operator:SI 6 "arm_comparison_operator"
8937 [(match_operand:SI 4 "s_register_operand" "r")
8938 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8939 (clobber (reg:CC CC_REGNUM))]
8941 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8944 "TARGET_ARM && reload_completed
8945 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8950 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8951 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8953 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8955 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8958 [(set_attr "conds" "clob")
8959 (set_attr "length" "16")])
8961 ; If the above pattern is followed by a CMP insn, then the compare is
8962 ; redundant, since we can rework the conditional instruction that follows.
8963 (define_insn_and_split "*and_scc_scc_cmp"
8964 [(set (match_operand 0 "dominant_cc_register" "")
8965 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8966 [(match_operand:SI 1 "s_register_operand" "r")
8967 (match_operand:SI 2 "arm_add_operand" "rIL")])
8968 (match_operator:SI 6 "arm_comparison_operator"
8969 [(match_operand:SI 4 "s_register_operand" "r")
8970 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8972 (set (match_operand:SI 7 "s_register_operand" "=r")
8973 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8974 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8977 "TARGET_ARM && reload_completed"
8981 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8982 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8984 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8986 [(set_attr "conds" "set")
8987 (set_attr "length" "16")])
8989 ;; If there is no dominance in the comparison, then we can still save an
8990 ;; instruction in the AND case, since we can know that the second compare
8991 ;; need only zero the value if false (if true, then the value is already
8993 (define_insn_and_split "*and_scc_scc_nodom"
8994 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8995 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8996 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8997 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8998 (match_operator:SI 6 "arm_comparison_operator"
8999 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9000 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9001 (clobber (reg:CC CC_REGNUM))]
9003 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9006 "TARGET_ARM && reload_completed"
9007 [(parallel [(set (match_dup 0)
9008 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9009 (clobber (reg:CC CC_REGNUM))])
9010 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9012 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9015 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9016 operands[4], operands[5]),
9018 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9020 [(set_attr "conds" "clob")
9021 (set_attr "length" "20")])
9024 [(set (reg:CC_NOOV CC_REGNUM)
9025 (compare:CC_NOOV (ior:SI
9026 (and:SI (match_operand:SI 0 "s_register_operand" "")
9028 (match_operator:SI 1 "comparison_operator"
9029 [(match_operand:SI 2 "s_register_operand" "")
9030 (match_operand:SI 3 "arm_add_operand" "")]))
9032 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9035 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9037 (set (reg:CC_NOOV CC_REGNUM)
9038 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9043 [(set (reg:CC_NOOV CC_REGNUM)
9044 (compare:CC_NOOV (ior:SI
9045 (match_operator:SI 1 "comparison_operator"
9046 [(match_operand:SI 2 "s_register_operand" "")
9047 (match_operand:SI 3 "arm_add_operand" "")])
9048 (and:SI (match_operand:SI 0 "s_register_operand" "")
9051 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9054 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9056 (set (reg:CC_NOOV CC_REGNUM)
9057 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9061 (define_insn "*negscc"
9062 [(set (match_operand:SI 0 "s_register_operand" "=r")
9063 (neg:SI (match_operator 3 "arm_comparison_operator"
9064 [(match_operand:SI 1 "s_register_operand" "r")
9065 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9066 (clobber (reg:CC CC_REGNUM))]
9069 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
9070 return \"mov\\t%0, %1, asr #31\";
9072 if (GET_CODE (operands[3]) == NE)
9073 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9075 if (GET_CODE (operands[3]) == GT)
9076 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
9078 output_asm_insn (\"cmp\\t%1, %2\", operands);
9079 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9080 return \"mvn%d3\\t%0, #0\";
9082 [(set_attr "conds" "clob")
9083 (set_attr "length" "12")]
9086 (define_insn "movcond"
9087 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9089 (match_operator 5 "arm_comparison_operator"
9090 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9091 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9092 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9093 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9094 (clobber (reg:CC CC_REGNUM))]
9097 if (GET_CODE (operands[5]) == LT
9098 && (operands[4] == const0_rtx))
9100 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9102 if (operands[2] == const0_rtx)
9103 return \"and\\t%0, %1, %3, asr #31\";
9104 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9106 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9108 if (operands[1] == const0_rtx)
9109 return \"bic\\t%0, %2, %3, asr #31\";
9110 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9112 /* The only case that falls through to here is when both ops 1 & 2
9116 if (GET_CODE (operands[5]) == GE
9117 && (operands[4] == const0_rtx))
9119 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9121 if (operands[2] == const0_rtx)
9122 return \"bic\\t%0, %1, %3, asr #31\";
9123 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9125 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9127 if (operands[1] == const0_rtx)
9128 return \"and\\t%0, %2, %3, asr #31\";
9129 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9131 /* The only case that falls through to here is when both ops 1 & 2
9134 if (GET_CODE (operands[4]) == CONST_INT
9135 && !const_ok_for_arm (INTVAL (operands[4])))
9136 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9138 output_asm_insn (\"cmp\\t%3, %4\", operands);
9139 if (which_alternative != 0)
9140 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9141 if (which_alternative != 1)
9142 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9145 [(set_attr "conds" "clob")
9146 (set_attr "length" "8,8,12")]
9149 (define_insn "*ifcompare_plus_move"
9150 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9151 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9152 [(match_operand:SI 4 "s_register_operand" "r,r")
9153 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9155 (match_operand:SI 2 "s_register_operand" "r,r")
9156 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9157 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9158 (clobber (reg:CC CC_REGNUM))]
9161 [(set_attr "conds" "clob")
9162 (set_attr "length" "8,12")]
9165 (define_insn "*if_plus_move"
9166 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9168 (match_operator 4 "arm_comparison_operator"
9169 [(match_operand 5 "cc_register" "") (const_int 0)])
9171 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9172 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9173 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9177 sub%d4\\t%0, %2, #%n3
9178 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9179 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9180 [(set_attr "conds" "use")
9181 (set_attr "length" "4,4,8,8")
9182 (set_attr "type" "*,*,*,*")]
9185 (define_insn "*ifcompare_move_plus"
9186 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9187 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9188 [(match_operand:SI 4 "s_register_operand" "r,r")
9189 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9190 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9192 (match_operand:SI 2 "s_register_operand" "r,r")
9193 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9194 (clobber (reg:CC CC_REGNUM))]
9197 [(set_attr "conds" "clob")
9198 (set_attr "length" "8,12")]
9201 (define_insn "*if_move_plus"
9202 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9204 (match_operator 4 "arm_comparison_operator"
9205 [(match_operand 5 "cc_register" "") (const_int 0)])
9206 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9208 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9209 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9213 sub%D4\\t%0, %2, #%n3
9214 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9215 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9216 [(set_attr "conds" "use")
9217 (set_attr "length" "4,4,8,8")
9218 (set_attr "type" "*,*,*,*")]
9221 (define_insn "*ifcompare_arith_arith"
9222 [(set (match_operand:SI 0 "s_register_operand" "=r")
9223 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9224 [(match_operand:SI 5 "s_register_operand" "r")
9225 (match_operand:SI 6 "arm_add_operand" "rIL")])
9226 (match_operator:SI 8 "shiftable_operator"
9227 [(match_operand:SI 1 "s_register_operand" "r")
9228 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9229 (match_operator:SI 7 "shiftable_operator"
9230 [(match_operand:SI 3 "s_register_operand" "r")
9231 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9232 (clobber (reg:CC CC_REGNUM))]
9235 [(set_attr "conds" "clob")
9236 (set_attr "length" "12")]
9239 (define_insn "*if_arith_arith"
9240 [(set (match_operand:SI 0 "s_register_operand" "=r")
9241 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9242 [(match_operand 8 "cc_register" "") (const_int 0)])
9243 (match_operator:SI 6 "shiftable_operator"
9244 [(match_operand:SI 1 "s_register_operand" "r")
9245 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9246 (match_operator:SI 7 "shiftable_operator"
9247 [(match_operand:SI 3 "s_register_operand" "r")
9248 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9250 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9251 [(set_attr "conds" "use")
9252 (set_attr "length" "8")]
9255 (define_insn "*ifcompare_arith_move"
9256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9257 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9258 [(match_operand:SI 2 "s_register_operand" "r,r")
9259 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9260 (match_operator:SI 7 "shiftable_operator"
9261 [(match_operand:SI 4 "s_register_operand" "r,r")
9262 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9263 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9264 (clobber (reg:CC CC_REGNUM))]
9267 /* If we have an operation where (op x 0) is the identity operation and
9268 the conditional operator is LT or GE and we are comparing against zero and
9269 everything is in registers then we can do this in two instructions. */
9270 if (operands[3] == const0_rtx
9271 && GET_CODE (operands[7]) != AND
9272 && GET_CODE (operands[5]) == REG
9273 && GET_CODE (operands[1]) == REG
9274 && REGNO (operands[1]) == REGNO (operands[4])
9275 && REGNO (operands[4]) != REGNO (operands[0]))
9277 if (GET_CODE (operands[6]) == LT)
9278 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9279 else if (GET_CODE (operands[6]) == GE)
9280 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9282 if (GET_CODE (operands[3]) == CONST_INT
9283 && !const_ok_for_arm (INTVAL (operands[3])))
9284 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9286 output_asm_insn (\"cmp\\t%2, %3\", operands);
9287 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9288 if (which_alternative != 0)
9289 return \"mov%D6\\t%0, %1\";
9292 [(set_attr "conds" "clob")
9293 (set_attr "length" "8,12")]
9296 (define_insn "*if_arith_move"
9297 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9298 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9299 [(match_operand 6 "cc_register" "") (const_int 0)])
9300 (match_operator:SI 5 "shiftable_operator"
9301 [(match_operand:SI 2 "s_register_operand" "r,r")
9302 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9303 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9307 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9308 [(set_attr "conds" "use")
9309 (set_attr "length" "4,8")
9310 (set_attr "type" "*,*")]
9313 (define_insn "*ifcompare_move_arith"
9314 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9315 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9316 [(match_operand:SI 4 "s_register_operand" "r,r")
9317 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9318 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9319 (match_operator:SI 7 "shiftable_operator"
9320 [(match_operand:SI 2 "s_register_operand" "r,r")
9321 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9322 (clobber (reg:CC CC_REGNUM))]
9325 /* If we have an operation where (op x 0) is the identity operation and
9326 the conditional operator is LT or GE and we are comparing against zero and
9327 everything is in registers then we can do this in two instructions */
9328 if (operands[5] == const0_rtx
9329 && GET_CODE (operands[7]) != AND
9330 && GET_CODE (operands[3]) == REG
9331 && GET_CODE (operands[1]) == REG
9332 && REGNO (operands[1]) == REGNO (operands[2])
9333 && REGNO (operands[2]) != REGNO (operands[0]))
9335 if (GET_CODE (operands[6]) == GE)
9336 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9337 else if (GET_CODE (operands[6]) == LT)
9338 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9341 if (GET_CODE (operands[5]) == CONST_INT
9342 && !const_ok_for_arm (INTVAL (operands[5])))
9343 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9345 output_asm_insn (\"cmp\\t%4, %5\", operands);
9347 if (which_alternative != 0)
9348 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9349 return \"%I7%D6\\t%0, %2, %3\";
9351 [(set_attr "conds" "clob")
9352 (set_attr "length" "8,12")]
9355 (define_insn "*if_move_arith"
9356 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9358 (match_operator 4 "arm_comparison_operator"
9359 [(match_operand 6 "cc_register" "") (const_int 0)])
9360 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9361 (match_operator:SI 5 "shiftable_operator"
9362 [(match_operand:SI 2 "s_register_operand" "r,r")
9363 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9367 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9368 [(set_attr "conds" "use")
9369 (set_attr "length" "4,8")
9370 (set_attr "type" "*,*")]
9373 (define_insn "*ifcompare_move_not"
9374 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9376 (match_operator 5 "arm_comparison_operator"
9377 [(match_operand:SI 3 "s_register_operand" "r,r")
9378 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9379 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9381 (match_operand:SI 2 "s_register_operand" "r,r"))))
9382 (clobber (reg:CC CC_REGNUM))]
9385 [(set_attr "conds" "clob")
9386 (set_attr "length" "8,12")]
9389 (define_insn "*if_move_not"
9390 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9392 (match_operator 4 "arm_comparison_operator"
9393 [(match_operand 3 "cc_register" "") (const_int 0)])
9394 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9395 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9399 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9400 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9401 [(set_attr "conds" "use")
9402 (set_attr "length" "4,8,8")]
9405 (define_insn "*ifcompare_not_move"
9406 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9408 (match_operator 5 "arm_comparison_operator"
9409 [(match_operand:SI 3 "s_register_operand" "r,r")
9410 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9412 (match_operand:SI 2 "s_register_operand" "r,r"))
9413 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9414 (clobber (reg:CC CC_REGNUM))]
9417 [(set_attr "conds" "clob")
9418 (set_attr "length" "8,12")]
9421 (define_insn "*if_not_move"
9422 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9424 (match_operator 4 "arm_comparison_operator"
9425 [(match_operand 3 "cc_register" "") (const_int 0)])
9426 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9427 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9431 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9432 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9433 [(set_attr "conds" "use")
9434 (set_attr "length" "4,8,8")]
9437 (define_insn "*ifcompare_shift_move"
9438 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9440 (match_operator 6 "arm_comparison_operator"
9441 [(match_operand:SI 4 "s_register_operand" "r,r")
9442 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9443 (match_operator:SI 7 "shift_operator"
9444 [(match_operand:SI 2 "s_register_operand" "r,r")
9445 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9446 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9447 (clobber (reg:CC CC_REGNUM))]
9450 [(set_attr "conds" "clob")
9451 (set_attr "length" "8,12")]
9454 (define_insn "*if_shift_move"
9455 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9457 (match_operator 5 "arm_comparison_operator"
9458 [(match_operand 6 "cc_register" "") (const_int 0)])
9459 (match_operator:SI 4 "shift_operator"
9460 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9461 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9462 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9466 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9467 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9468 [(set_attr "conds" "use")
9469 (set_attr "shift" "2")
9470 (set_attr "length" "4,8,8")
9471 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9472 (const_string "alu_shift")
9473 (const_string "alu_shift_reg")))]
9476 (define_insn "*ifcompare_move_shift"
9477 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9479 (match_operator 6 "arm_comparison_operator"
9480 [(match_operand:SI 4 "s_register_operand" "r,r")
9481 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9482 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9483 (match_operator:SI 7 "shift_operator"
9484 [(match_operand:SI 2 "s_register_operand" "r,r")
9485 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9486 (clobber (reg:CC CC_REGNUM))]
9489 [(set_attr "conds" "clob")
9490 (set_attr "length" "8,12")]
9493 (define_insn "*if_move_shift"
9494 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9496 (match_operator 5 "arm_comparison_operator"
9497 [(match_operand 6 "cc_register" "") (const_int 0)])
9498 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9499 (match_operator:SI 4 "shift_operator"
9500 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9501 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9505 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9506 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9507 [(set_attr "conds" "use")
9508 (set_attr "shift" "2")
9509 (set_attr "length" "4,8,8")
9510 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9511 (const_string "alu_shift")
9512 (const_string "alu_shift_reg")))]
9515 (define_insn "*ifcompare_shift_shift"
9516 [(set (match_operand:SI 0 "s_register_operand" "=r")
9518 (match_operator 7 "arm_comparison_operator"
9519 [(match_operand:SI 5 "s_register_operand" "r")
9520 (match_operand:SI 6 "arm_add_operand" "rIL")])
9521 (match_operator:SI 8 "shift_operator"
9522 [(match_operand:SI 1 "s_register_operand" "r")
9523 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9524 (match_operator:SI 9 "shift_operator"
9525 [(match_operand:SI 3 "s_register_operand" "r")
9526 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9527 (clobber (reg:CC CC_REGNUM))]
9530 [(set_attr "conds" "clob")
9531 (set_attr "length" "12")]
9534 (define_insn "*if_shift_shift"
9535 [(set (match_operand:SI 0 "s_register_operand" "=r")
9537 (match_operator 5 "arm_comparison_operator"
9538 [(match_operand 8 "cc_register" "") (const_int 0)])
9539 (match_operator:SI 6 "shift_operator"
9540 [(match_operand:SI 1 "s_register_operand" "r")
9541 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9542 (match_operator:SI 7 "shift_operator"
9543 [(match_operand:SI 3 "s_register_operand" "r")
9544 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9546 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9547 [(set_attr "conds" "use")
9548 (set_attr "shift" "1")
9549 (set_attr "length" "8")
9550 (set (attr "type") (if_then_else
9551 (and (match_operand 2 "const_int_operand" "")
9552 (match_operand 4 "const_int_operand" ""))
9553 (const_string "alu_shift")
9554 (const_string "alu_shift_reg")))]
9557 (define_insn "*ifcompare_not_arith"
9558 [(set (match_operand:SI 0 "s_register_operand" "=r")
9560 (match_operator 6 "arm_comparison_operator"
9561 [(match_operand:SI 4 "s_register_operand" "r")
9562 (match_operand:SI 5 "arm_add_operand" "rIL")])
9563 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9564 (match_operator:SI 7 "shiftable_operator"
9565 [(match_operand:SI 2 "s_register_operand" "r")
9566 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9567 (clobber (reg:CC CC_REGNUM))]
9570 [(set_attr "conds" "clob")
9571 (set_attr "length" "12")]
9574 (define_insn "*if_not_arith"
9575 [(set (match_operand:SI 0 "s_register_operand" "=r")
9577 (match_operator 5 "arm_comparison_operator"
9578 [(match_operand 4 "cc_register" "") (const_int 0)])
9579 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9580 (match_operator:SI 6 "shiftable_operator"
9581 [(match_operand:SI 2 "s_register_operand" "r")
9582 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9584 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9585 [(set_attr "conds" "use")
9586 (set_attr "length" "8")]
9589 (define_insn "*ifcompare_arith_not"
9590 [(set (match_operand:SI 0 "s_register_operand" "=r")
9592 (match_operator 6 "arm_comparison_operator"
9593 [(match_operand:SI 4 "s_register_operand" "r")
9594 (match_operand:SI 5 "arm_add_operand" "rIL")])
9595 (match_operator:SI 7 "shiftable_operator"
9596 [(match_operand:SI 2 "s_register_operand" "r")
9597 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9598 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9599 (clobber (reg:CC CC_REGNUM))]
9602 [(set_attr "conds" "clob")
9603 (set_attr "length" "12")]
9606 (define_insn "*if_arith_not"
9607 [(set (match_operand:SI 0 "s_register_operand" "=r")
9609 (match_operator 5 "arm_comparison_operator"
9610 [(match_operand 4 "cc_register" "") (const_int 0)])
9611 (match_operator:SI 6 "shiftable_operator"
9612 [(match_operand:SI 2 "s_register_operand" "r")
9613 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9614 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9616 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9617 [(set_attr "conds" "use")
9618 (set_attr "length" "8")]
9621 (define_insn "*ifcompare_neg_move"
9622 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9624 (match_operator 5 "arm_comparison_operator"
9625 [(match_operand:SI 3 "s_register_operand" "r,r")
9626 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9627 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9628 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9629 (clobber (reg:CC CC_REGNUM))]
9632 [(set_attr "conds" "clob")
9633 (set_attr "length" "8,12")]
9636 (define_insn "*if_neg_move"
9637 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9639 (match_operator 4 "arm_comparison_operator"
9640 [(match_operand 3 "cc_register" "") (const_int 0)])
9641 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9642 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9646 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9647 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9648 [(set_attr "conds" "use")
9649 (set_attr "length" "4,8,8")]
9652 (define_insn "*ifcompare_move_neg"
9653 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9655 (match_operator 5 "arm_comparison_operator"
9656 [(match_operand:SI 3 "s_register_operand" "r,r")
9657 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9658 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9659 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9660 (clobber (reg:CC CC_REGNUM))]
9663 [(set_attr "conds" "clob")
9664 (set_attr "length" "8,12")]
9667 (define_insn "*if_move_neg"
9668 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9670 (match_operator 4 "arm_comparison_operator"
9671 [(match_operand 3 "cc_register" "") (const_int 0)])
9672 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9673 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9677 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9678 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9679 [(set_attr "conds" "use")
9680 (set_attr "length" "4,8,8")]
9683 (define_insn "*arith_adjacentmem"
9684 [(set (match_operand:SI 0 "s_register_operand" "=r")
9685 (match_operator:SI 1 "shiftable_operator"
9686 [(match_operand:SI 2 "memory_operand" "m")
9687 (match_operand:SI 3 "memory_operand" "m")]))
9688 (clobber (match_scratch:SI 4 "=r"))]
9689 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9695 HOST_WIDE_INT val1 = 0, val2 = 0;
9697 if (REGNO (operands[0]) > REGNO (operands[4]))
9699 ldm[1] = operands[4];
9700 ldm[2] = operands[0];
9704 ldm[1] = operands[0];
9705 ldm[2] = operands[4];
9708 base_reg = XEXP (operands[2], 0);
9710 if (!REG_P (base_reg))
9712 val1 = INTVAL (XEXP (base_reg, 1));
9713 base_reg = XEXP (base_reg, 0);
9716 if (!REG_P (XEXP (operands[3], 0)))
9717 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9719 arith[0] = operands[0];
9720 arith[3] = operands[1];
9734 if (val1 !=0 && val2 != 0)
9738 if (val1 == 4 || val2 == 4)
9739 /* Other val must be 8, since we know they are adjacent and neither
9741 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9742 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9744 ldm[0] = ops[0] = operands[4];
9746 ops[2] = GEN_INT (val1);
9747 output_add_immediate (ops);
9749 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9751 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9755 /* Offset is out of range for a single add, so use two ldr. */
9758 ops[2] = GEN_INT (val1);
9759 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9761 ops[2] = GEN_INT (val2);
9762 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9768 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9770 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9775 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9777 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9779 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9782 [(set_attr "length" "12")
9783 (set_attr "predicable" "yes")
9784 (set_attr "type" "load1")]
9787 ; This pattern is never tried by combine, so do it as a peephole
9790 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9791 (match_operand:SI 1 "arm_general_register_operand" ""))
9792 (set (reg:CC CC_REGNUM)
9793 (compare:CC (match_dup 1) (const_int 0)))]
9795 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9796 (set (match_dup 0) (match_dup 1))])]
9800 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9801 ; reversed, check that the memory references aren't volatile.
9804 [(set (match_operand:SI 0 "s_register_operand" "=r")
9805 (match_operand:SI 4 "memory_operand" "m"))
9806 (set (match_operand:SI 1 "s_register_operand" "=r")
9807 (match_operand:SI 5 "memory_operand" "m"))
9808 (set (match_operand:SI 2 "s_register_operand" "=r")
9809 (match_operand:SI 6 "memory_operand" "m"))
9810 (set (match_operand:SI 3 "s_register_operand" "=r")
9811 (match_operand:SI 7 "memory_operand" "m"))]
9812 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9814 return emit_ldm_seq (operands, 4);
9819 [(set (match_operand:SI 0 "s_register_operand" "=r")
9820 (match_operand:SI 3 "memory_operand" "m"))
9821 (set (match_operand:SI 1 "s_register_operand" "=r")
9822 (match_operand:SI 4 "memory_operand" "m"))
9823 (set (match_operand:SI 2 "s_register_operand" "=r")
9824 (match_operand:SI 5 "memory_operand" "m"))]
9825 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9827 return emit_ldm_seq (operands, 3);
9832 [(set (match_operand:SI 0 "s_register_operand" "=r")
9833 (match_operand:SI 2 "memory_operand" "m"))
9834 (set (match_operand:SI 1 "s_register_operand" "=r")
9835 (match_operand:SI 3 "memory_operand" "m"))]
9836 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9838 return emit_ldm_seq (operands, 2);
9843 [(set (match_operand:SI 4 "memory_operand" "=m")
9844 (match_operand:SI 0 "s_register_operand" "r"))
9845 (set (match_operand:SI 5 "memory_operand" "=m")
9846 (match_operand:SI 1 "s_register_operand" "r"))
9847 (set (match_operand:SI 6 "memory_operand" "=m")
9848 (match_operand:SI 2 "s_register_operand" "r"))
9849 (set (match_operand:SI 7 "memory_operand" "=m")
9850 (match_operand:SI 3 "s_register_operand" "r"))]
9851 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9853 return emit_stm_seq (operands, 4);
9858 [(set (match_operand:SI 3 "memory_operand" "=m")
9859 (match_operand:SI 0 "s_register_operand" "r"))
9860 (set (match_operand:SI 4 "memory_operand" "=m")
9861 (match_operand:SI 1 "s_register_operand" "r"))
9862 (set (match_operand:SI 5 "memory_operand" "=m")
9863 (match_operand:SI 2 "s_register_operand" "r"))]
9864 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9866 return emit_stm_seq (operands, 3);
9871 [(set (match_operand:SI 2 "memory_operand" "=m")
9872 (match_operand:SI 0 "s_register_operand" "r"))
9873 (set (match_operand:SI 3 "memory_operand" "=m")
9874 (match_operand:SI 1 "s_register_operand" "r"))]
9875 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9877 return emit_stm_seq (operands, 2);
9882 [(set (match_operand:SI 0 "s_register_operand" "")
9883 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9885 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9886 [(match_operand:SI 3 "s_register_operand" "")
9887 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9888 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9890 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9891 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9896 ;; This split can be used because CC_Z mode implies that the following
9897 ;; branch will be an equality, or an unsigned inequality, so the sign
9898 ;; extension is not needed.
9901 [(set (reg:CC_Z CC_REGNUM)
9903 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9905 (match_operand 1 "const_int_operand" "")))
9906 (clobber (match_scratch:SI 2 ""))]
9908 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9909 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9910 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9911 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9913 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9917 (define_expand "prologue"
9918 [(clobber (const_int 0))]
9921 arm_expand_prologue ();
9923 thumb_expand_prologue ();
9928 (define_expand "epilogue"
9929 [(clobber (const_int 0))]
9932 if (current_function_calls_eh_return)
9933 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9935 thumb_expand_epilogue ();
9936 else if (USE_RETURN_INSN (FALSE))
9938 emit_jump_insn (gen_return ());
9941 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9943 gen_rtx_RETURN (VOIDmode)),
9949 ;; Note - although unspec_volatile's USE all hard registers,
9950 ;; USEs are ignored after relaod has completed. Thus we need
9951 ;; to add an unspec of the link register to ensure that flow
9952 ;; does not think that it is unused by the sibcall branch that
9953 ;; will replace the standard function epilogue.
9954 (define_insn "sibcall_epilogue"
9955 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9956 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9959 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9960 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9961 return arm_output_epilogue (next_nonnote_insn (insn));
9963 ;; Length is absolute worst case
9964 [(set_attr "length" "44")
9965 (set_attr "type" "block")
9966 ;; We don't clobber the conditions, but the potential length of this
9967 ;; operation is sufficient to make conditionalizing the sequence
9968 ;; unlikely to be profitable.
9969 (set_attr "conds" "clob")]
9972 (define_insn "*epilogue_insns"
9973 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9977 return arm_output_epilogue (NULL);
9978 else /* TARGET_THUMB */
9979 return thumb_unexpanded_epilogue ();
9981 ; Length is absolute worst case
9982 [(set_attr "length" "44")
9983 (set_attr "type" "block")
9984 ;; We don't clobber the conditions, but the potential length of this
9985 ;; operation is sufficient to make conditionalizing the sequence
9986 ;; unlikely to be profitable.
9987 (set_attr "conds" "clob")]
9990 (define_expand "eh_epilogue"
9991 [(use (match_operand:SI 0 "register_operand" ""))
9992 (use (match_operand:SI 1 "register_operand" ""))
9993 (use (match_operand:SI 2 "register_operand" ""))]
9997 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9998 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10000 rtx ra = gen_rtx_REG (Pmode, 2);
10002 emit_move_insn (ra, operands[2]);
10005 /* This is a hack -- we may have crystalized the function type too
10007 cfun->machine->func_type = 0;
10011 ;; This split is only used during output to reduce the number of patterns
10012 ;; that need assembler instructions adding to them. We allowed the setting
10013 ;; of the conditions to be implicit during rtl generation so that
10014 ;; the conditional compare patterns would work. However this conflicts to
10015 ;; some extent with the conditional data operations, so we have to split them
10019 [(set (match_operand:SI 0 "s_register_operand" "")
10020 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10021 [(match_operand 2 "" "") (match_operand 3 "" "")])
10023 (match_operand 4 "" "")))
10024 (clobber (reg:CC CC_REGNUM))]
10025 "TARGET_ARM && reload_completed"
10026 [(set (match_dup 5) (match_dup 6))
10027 (cond_exec (match_dup 7)
10028 (set (match_dup 0) (match_dup 4)))]
10031 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10032 operands[2], operands[3]);
10033 enum rtx_code rc = GET_CODE (operands[1]);
10035 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10036 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10037 if (mode == CCFPmode || mode == CCFPEmode)
10038 rc = reverse_condition_maybe_unordered (rc);
10040 rc = reverse_condition (rc);
10042 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10047 [(set (match_operand:SI 0 "s_register_operand" "")
10048 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10049 [(match_operand 2 "" "") (match_operand 3 "" "")])
10050 (match_operand 4 "" "")
10052 (clobber (reg:CC CC_REGNUM))]
10053 "TARGET_ARM && reload_completed"
10054 [(set (match_dup 5) (match_dup 6))
10055 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10056 (set (match_dup 0) (match_dup 4)))]
10059 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10060 operands[2], operands[3]);
10062 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10063 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10068 [(set (match_operand:SI 0 "s_register_operand" "")
10069 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10070 [(match_operand 2 "" "") (match_operand 3 "" "")])
10071 (match_operand 4 "" "")
10072 (match_operand 5 "" "")))
10073 (clobber (reg:CC CC_REGNUM))]
10074 "TARGET_ARM && reload_completed"
10075 [(set (match_dup 6) (match_dup 7))
10076 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10077 (set (match_dup 0) (match_dup 4)))
10078 (cond_exec (match_dup 8)
10079 (set (match_dup 0) (match_dup 5)))]
10082 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10083 operands[2], operands[3]);
10084 enum rtx_code rc = GET_CODE (operands[1]);
10086 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10087 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10088 if (mode == CCFPmode || mode == CCFPEmode)
10089 rc = reverse_condition_maybe_unordered (rc);
10091 rc = reverse_condition (rc);
10093 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10098 [(set (match_operand:SI 0 "s_register_operand" "")
10099 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10100 [(match_operand:SI 2 "s_register_operand" "")
10101 (match_operand:SI 3 "arm_add_operand" "")])
10102 (match_operand:SI 4 "arm_rhs_operand" "")
10104 (match_operand:SI 5 "s_register_operand" ""))))
10105 (clobber (reg:CC CC_REGNUM))]
10106 "TARGET_ARM && reload_completed"
10107 [(set (match_dup 6) (match_dup 7))
10108 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10109 (set (match_dup 0) (match_dup 4)))
10110 (cond_exec (match_dup 8)
10111 (set (match_dup 0) (not:SI (match_dup 5))))]
10114 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10115 operands[2], operands[3]);
10116 enum rtx_code rc = GET_CODE (operands[1]);
10118 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10119 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10120 if (mode == CCFPmode || mode == CCFPEmode)
10121 rc = reverse_condition_maybe_unordered (rc);
10123 rc = reverse_condition (rc);
10125 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10129 (define_insn "*cond_move_not"
10130 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10131 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10132 [(match_operand 3 "cc_register" "") (const_int 0)])
10133 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10135 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10139 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10140 [(set_attr "conds" "use")
10141 (set_attr "length" "4,8")]
10144 ;; The next two patterns occur when an AND operation is followed by a
10145 ;; scc insn sequence
10147 (define_insn "*sign_extract_onebit"
10148 [(set (match_operand:SI 0 "s_register_operand" "=r")
10149 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10151 (match_operand:SI 2 "const_int_operand" "n")))
10152 (clobber (reg:CC CC_REGNUM))]
10155 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10156 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10157 return \"mvnne\\t%0, #0\";
10159 [(set_attr "conds" "clob")
10160 (set_attr "length" "8")]
10163 (define_insn "*not_signextract_onebit"
10164 [(set (match_operand:SI 0 "s_register_operand" "=r")
10166 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10168 (match_operand:SI 2 "const_int_operand" "n"))))
10169 (clobber (reg:CC CC_REGNUM))]
10172 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10173 output_asm_insn (\"tst\\t%1, %2\", operands);
10174 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10175 return \"movne\\t%0, #0\";
10177 [(set_attr "conds" "clob")
10178 (set_attr "length" "12")]
10181 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10182 ;; expressions. For simplicity, the first register is also in the unspec
10184 (define_insn "*push_multi"
10185 [(match_parallel 2 "multi_register_push"
10186 [(set (match_operand:BLK 0 "memory_operand" "=m")
10187 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10188 UNSPEC_PUSH_MULT))])]
10192 int num_saves = XVECLEN (operands[2], 0);
10194 /* For the StrongARM at least it is faster to
10195 use STR to store only a single register. */
10196 if (num_saves == 1)
10197 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10203 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10205 for (i = 1; i < num_saves; i++)
10207 strcat (pattern, \", %|\");
10209 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10212 strcat (pattern, \"}\");
10213 output_asm_insn (pattern, operands);
10218 [(set_attr "type" "store4")]
10221 (define_insn "stack_tie"
10222 [(set (mem:BLK (scratch))
10223 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10224 (match_operand:SI 1 "s_register_operand" "r")]
10228 [(set_attr "length" "0")]
10231 ;; Similarly for the floating point registers
10232 (define_insn "*push_fp_multi"
10233 [(match_parallel 2 "multi_register_push"
10234 [(set (match_operand:BLK 0 "memory_operand" "=m")
10235 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10236 UNSPEC_PUSH_MULT))])]
10237 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10242 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10243 output_asm_insn (pattern, operands);
10246 [(set_attr "type" "f_store")]
10249 ;; Special patterns for dealing with the constant pool
10251 (define_insn "align_4"
10252 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10255 assemble_align (32);
10260 (define_insn "align_8"
10261 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10264 assemble_align (64);
10269 (define_insn "consttable_end"
10270 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10273 making_const_table = FALSE;
10278 (define_insn "consttable_1"
10279 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10282 making_const_table = TRUE;
10283 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10284 assemble_zeros (3);
10287 [(set_attr "length" "4")]
10290 (define_insn "consttable_2"
10291 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10294 making_const_table = TRUE;
10295 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10296 assemble_zeros (2);
10299 [(set_attr "length" "4")]
10302 (define_insn "consttable_4"
10303 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10307 making_const_table = TRUE;
10308 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10313 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10314 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10318 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10323 [(set_attr "length" "4")]
10326 (define_insn "consttable_8"
10327 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10331 making_const_table = TRUE;
10332 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10337 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10338 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10342 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10347 [(set_attr "length" "8")]
10350 ;; Miscellaneous Thumb patterns
10352 (define_expand "tablejump"
10353 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10354 (use (label_ref (match_operand 1 "" "")))])]
10359 /* Hopefully, CSE will eliminate this copy. */
10360 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10361 rtx reg2 = gen_reg_rtx (SImode);
10363 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10364 operands[0] = reg2;
10369 ;; NB never uses BX.
10370 (define_insn "*thumb_tablejump"
10371 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10372 (use (label_ref (match_operand 1 "" "")))]
10375 [(set_attr "length" "2")]
10378 ;; V5 Instructions,
10380 (define_insn "clzsi2"
10381 [(set (match_operand:SI 0 "s_register_operand" "=r")
10382 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10383 "TARGET_ARM && arm_arch5"
10385 [(set_attr "predicable" "yes")])
10387 (define_expand "ffssi2"
10388 [(set (match_operand:SI 0 "s_register_operand" "")
10389 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10390 "TARGET_ARM && arm_arch5"
10395 t1 = gen_reg_rtx (SImode);
10396 t2 = gen_reg_rtx (SImode);
10397 t3 = gen_reg_rtx (SImode);
10399 emit_insn (gen_negsi2 (t1, operands[1]));
10400 emit_insn (gen_andsi3 (t2, operands[1], t1));
10401 emit_insn (gen_clzsi2 (t3, t2));
10402 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10407 (define_expand "ctzsi2"
10408 [(set (match_operand:SI 0 "s_register_operand" "")
10409 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10410 "TARGET_ARM && arm_arch5"
10415 t1 = gen_reg_rtx (SImode);
10416 t2 = gen_reg_rtx (SImode);
10417 t3 = gen_reg_rtx (SImode);
10419 emit_insn (gen_negsi2 (t1, operands[1]));
10420 emit_insn (gen_andsi3 (t2, operands[1], t1));
10421 emit_insn (gen_clzsi2 (t3, t2));
10422 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10427 ;; V5E instructions.
10429 (define_insn "prefetch"
10430 [(prefetch (match_operand:SI 0 "address_operand" "p")
10431 (match_operand:SI 1 "" "")
10432 (match_operand:SI 2 "" ""))]
10433 "TARGET_ARM && arm_arch5e"
10436 ;; General predication pattern
10439 [(match_operator 0 "arm_comparison_operator"
10440 [(match_operand 1 "cc_register" "")
10446 (define_insn "prologue_use"
10447 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10449 "%@ %0 needed for prologue"
10453 ;; Patterns for exception handling
10455 (define_expand "eh_return"
10456 [(use (match_operand 0 "general_operand" ""))]
10461 emit_insn (gen_arm_eh_return (operands[0]));
10463 emit_insn (gen_thumb_eh_return (operands[0]));
10468 ;; We can't expand this before we know where the link register is stored.
10469 (define_insn_and_split "arm_eh_return"
10470 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10472 (clobber (match_scratch:SI 1 "=&r"))]
10475 "&& reload_completed"
10479 arm_set_return_address (operands[0], operands[1]);
10484 (define_insn_and_split "thumb_eh_return"
10485 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10487 (clobber (match_scratch:SI 1 "=&l"))]
10490 "&& reload_completed"
10494 thumb_set_return_address (operands[0], operands[1]);
10502 (define_insn "load_tp_hard"
10503 [(set (match_operand:SI 0 "register_operand" "=r")
10504 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10506 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10507 [(set_attr "predicable" "yes")]
10510 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10511 (define_insn "load_tp_soft"
10512 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10513 (clobber (reg:SI LR_REGNUM))
10514 (clobber (reg:SI IP_REGNUM))
10515 (clobber (reg:CC CC_REGNUM))]
10517 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10518 [(set_attr "conds" "clob")]
10521 ;; Load the FPA co-processor patterns
10523 ;; Load the Maverick co-processor patterns
10524 (include "cirrus.md")
10525 ;; Load the Intel Wireless Multimedia Extension patterns
10526 (include "iwmmxt.md")
10527 ;; Load the VFP co-processor patterns