1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
44 ;; 3rd operand to select_dominance_cc_mode
53 ;; Note: sin and cos are no-longer used.
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
96 ;; UNSPEC_VOLATILE Usage:
99 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
101 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102 ; instruction epilogue sequence that isn't expanded
103 ; into normal RTL. Used for both normal and sibcall
105 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
106 ; for inlined constants.
107 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
109 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
111 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
113 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
115 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
117 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
118 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
119 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
120 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
121 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
128 ;;---------------------------------------------------------------------------
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code. This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted. Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit. If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns. (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151 (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed. If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168 [(set_attr "conds" "clob")
169 (set_attr "length" "4")
170 (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern. This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
177 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178 (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu any alu instruction that doesn't hit memory or fp
187 ; regs or have a shifted source operand
188 ; alu_shift any data instruction that doesn't hit memory or fp
189 ; regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ; regs, but has a source operand shifted by a register value
192 ; mult a multiply instruction
193 ; block blockage insn, this blocks all functional units
194 ; float a floating point arithmetic operation (subject to expansion)
195 ; fdivd DFmode floating point division
196 ; fdivs SFmode floating point division
197 ; fmul Floating point multiply
198 ; ffmul Fast floating point multiply
199 ; farith Floating point arithmetic (4 cycle)
200 ; ffarith Fast floating point arithmetic (2 cycle)
201 ; float_em a floating point arithmetic operation that is normally emulated
202 ; even on a machine with an fpa.
203 ; f_load a floating point load from memory
204 ; f_store a floating point store to memory
205 ; f_mem_r a transfer of a floating point register to a real reg via mem
206 ; r_mem_f the reverse of f_mem_r
207 ; f_2_r fast transfer float to arm (no memory needed)
208 ; r_2_f fast transfer arm to float
210 ; call a subroutine call
211 ; load_byte load byte(s) from memory to arm registers
212 ; load1 load 1 word from memory to arm registers
213 ; load2 load 2 words from memory to arm registers
214 ; load3 load 3 words from memory to arm registers
215 ; load4 load 4 words from memory to arm registers
216 ; store store 1 word to memory from arm registers
217 ; store2 store 2 words
218 ; store3 store 3 words
219 ; store4 store 4 (or more) words
220 ; Additions for Cirrus Maverick co-processor:
221 ; mav_farith Floating point arithmetic (4 cycle)
222 ; mav_dmult Double multiplies (7 cycle)
225 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
227 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228 (const_string "mult")
229 (const_string "alu")))
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options()
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions. It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
239 ; USE means that the condition codes are used by the insn in the process of
240 ; outputting code, this means (at present) that we can't use the insn in
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ; well defined manner.
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ; they are altered at all
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ; instruction (UNEQ and LTGT). These cannot be predicated.
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ; output of this insn
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256 (if_then_else (eq_attr "type" "call")
257 (const_string "clob")
258 (const_string "nocond")))
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by
262 ; gen...). We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
266 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
267 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor. Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275 (if_then_else (eq_attr "type"
276 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
278 (const_string "no")))
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283 (if_then_else (eq_attr "type"
284 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285 (const_string "single")
286 (const_string "multi")))
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label. Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
292 (include "predicates.md")
294 ;;---------------------------------------------------------------------------
295 ;; Pipeline descriptions
297 ;; Processor type. This is created automatically from arm-cores.def.
298 (include "arm-tune.md")
300 ;; True if the generic scheduling description should be used.
302 (define_attr "generic_sched" "yes,no"
304 (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs")
306 (const_string "yes"))))
308 (include "arm-generic.md")
309 (include "arm926ejs.md")
310 (include "arm1026ejs.md")
311 (include "arm1136jfs.md")
314 ;;---------------------------------------------------------------------------
319 ;; Note: For DImode insns, there is normally no reason why operands should
320 ;; not be in the same register, what we don't want is for something being
321 ;; written to partially overlap something that is an input.
322 ;; Cirrus 64bit additions should not be split because we have a native
323 ;; 64bit addition instructions.
325 (define_expand "adddi3"
327 [(set (match_operand:DI 0 "s_register_operand" "")
328 (plus:DI (match_operand:DI 1 "s_register_operand" "")
329 (match_operand:DI 2 "s_register_operand" "")))
330 (clobber (reg:CC CC_REGNUM))])]
333 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
335 if (!cirrus_fp_register (operands[0], DImode))
336 operands[0] = force_reg (DImode, operands[0]);
337 if (!cirrus_fp_register (operands[1], DImode))
338 operands[1] = force_reg (DImode, operands[1]);
339 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
345 if (GET_CODE (operands[1]) != REG)
346 operands[1] = force_reg (SImode, operands[1]);
347 if (GET_CODE (operands[2]) != REG)
348 operands[2] = force_reg (SImode, operands[2]);
353 (define_insn "*thumb_adddi3"
354 [(set (match_operand:DI 0 "register_operand" "=l")
355 (plus:DI (match_operand:DI 1 "register_operand" "%0")
356 (match_operand:DI 2 "register_operand" "l")))
357 (clobber (reg:CC CC_REGNUM))
360 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
361 [(set_attr "length" "4")]
364 (define_insn_and_split "*arm_adddi3"
365 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
366 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
367 (match_operand:DI 2 "s_register_operand" "r, 0")))
368 (clobber (reg:CC CC_REGNUM))]
369 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
371 "TARGET_ARM && reload_completed"
372 [(parallel [(set (reg:CC_C CC_REGNUM)
373 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
375 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
376 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
377 (plus:SI (match_dup 4) (match_dup 5))))]
380 operands[3] = gen_highpart (SImode, operands[0]);
381 operands[0] = gen_lowpart (SImode, operands[0]);
382 operands[4] = gen_highpart (SImode, operands[1]);
383 operands[1] = gen_lowpart (SImode, operands[1]);
384 operands[5] = gen_highpart (SImode, operands[2]);
385 operands[2] = gen_lowpart (SImode, operands[2]);
387 [(set_attr "conds" "clob")
388 (set_attr "length" "8")]
391 (define_insn_and_split "*adddi_sesidi_di"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (sign_extend:DI
394 (match_operand:SI 2 "s_register_operand" "r,r"))
395 (match_operand:DI 1 "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 (ashiftrt:SI (match_dup 2)
410 operands[3] = gen_highpart (SImode, operands[0]);
411 operands[0] = gen_lowpart (SImode, operands[0]);
412 operands[4] = gen_highpart (SImode, operands[1]);
413 operands[1] = gen_lowpart (SImode, operands[1]);
414 operands[2] = gen_lowpart (SImode, operands[2]);
416 [(set_attr "conds" "clob")
417 (set_attr "length" "8")]
420 (define_insn_and_split "*adddi_zesidi_di"
421 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
422 (plus:DI (zero_extend:DI
423 (match_operand:SI 2 "s_register_operand" "r,r"))
424 (match_operand:DI 1 "s_register_operand" "r,0")))
425 (clobber (reg:CC CC_REGNUM))]
426 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
428 "TARGET_ARM && reload_completed"
429 [(parallel [(set (reg:CC_C CC_REGNUM)
430 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
432 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
433 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
434 (plus:SI (match_dup 4) (const_int 0))))]
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
447 (define_expand "addsi3"
448 [(set (match_operand:SI 0 "s_register_operand" "")
449 (plus:SI (match_operand:SI 1 "s_register_operand" "")
450 (match_operand:SI 2 "reg_or_int_operand" "")))]
453 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
455 arm_split_constant (PLUS, SImode, NULL_RTX,
456 INTVAL (operands[2]), operands[0], operands[1],
457 optimize && !no_new_pseudos);
463 ; If there is a scratch available, this will be faster than synthesizing the
466 [(match_scratch:SI 3 "r")
467 (set (match_operand:SI 0 "arm_general_register_operand" "")
468 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
469 (match_operand:SI 2 "const_int_operand" "")))]
471 !(const_ok_for_arm (INTVAL (operands[2]))
472 || const_ok_for_arm (-INTVAL (operands[2])))
473 && const_ok_for_arm (~INTVAL (operands[2]))"
474 [(set (match_dup 3) (match_dup 2))
475 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
479 (define_insn_and_split "*arm_addsi3"
480 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
481 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
482 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
489 GET_CODE (operands[2]) == CONST_INT
490 && !(const_ok_for_arm (INTVAL (operands[2]))
491 || const_ok_for_arm (-INTVAL (operands[2])))"
492 [(clobber (const_int 0))]
494 arm_split_constant (PLUS, SImode, curr_insn,
495 INTVAL (operands[2]), operands[0],
499 [(set_attr "length" "4,4,16")
500 (set_attr "predicable" "yes")]
503 ;; Register group 'k' is a single register group containing only the stack
504 ;; register. Trying to reload it will always fail catastrophically,
505 ;; so never allow those alternatives to match if reloading is needed.
507 (define_insn "*thumb_addsi3"
508 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
509 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
510 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
513 static const char * const asms[] =
515 \"add\\t%0, %0, %2\",
516 \"sub\\t%0, %0, #%n2\",
517 \"add\\t%0, %1, %2\",
518 \"add\\t%0, %0, %2\",
519 \"add\\t%0, %0, %2\",
520 \"add\\t%0, %1, %2\",
523 if ((which_alternative == 2 || which_alternative == 6)
524 && GET_CODE (operands[2]) == CONST_INT
525 && INTVAL (operands[2]) < 0)
526 return \"sub\\t%0, %1, #%n2\";
527 return asms[which_alternative];
529 [(set_attr "length" "2")]
532 ;; Reloading and elimination of the frame pointer can
533 ;; sometimes cause this optimization to be missed.
535 [(set (match_operand:SI 0 "arm_general_register_operand" "")
536 (match_operand:SI 1 "const_int_operand" ""))
538 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
540 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
541 && (INTVAL (operands[1]) & 3) == 0"
542 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
546 (define_insn "*addsi3_compare0"
547 [(set (reg:CC_NOOV CC_REGNUM)
549 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
550 (match_operand:SI 2 "arm_add_operand" "rI,L"))
552 (set (match_operand:SI 0 "s_register_operand" "=r,r")
553 (plus:SI (match_dup 1) (match_dup 2)))]
557 sub%?s\\t%0, %1, #%n2"
558 [(set_attr "conds" "set")]
561 (define_insn "*addsi3_compare0_scratch"
562 [(set (reg:CC_NOOV CC_REGNUM)
564 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
565 (match_operand:SI 1 "arm_add_operand" "rI,L"))
571 [(set_attr "conds" "set")]
574 ;; These patterns are the same ones as the two regular addsi3_compare0
575 ;; patterns, except we write them slightly different - the combiner
576 ;; tends to generate them this way.
577 (define_insn "*addsi3_compare0_for_combiner"
578 [(set (reg:CC CC_REGNUM)
580 (match_operand:SI 1 "s_register_operand" "r,r")
581 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
582 (set (match_operand:SI 0 "s_register_operand" "=r,r")
583 (plus:SI (match_dup 1) (match_dup 2)))]
587 sub%?s\\t%0, %1, #%n2"
588 [(set_attr "conds" "set")]
591 (define_insn "*addsi3_compare0_scratch_for_combiner"
592 [(set (reg:CC CC_REGNUM)
594 (match_operand:SI 0 "s_register_operand" "r,r")
595 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
600 [(set_attr "conds" "set")]
603 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
604 ;; addend is a constant.
605 (define_insn "*cmpsi2_addneg"
606 [(set (reg:CC CC_REGNUM)
608 (match_operand:SI 1 "s_register_operand" "r,r")
609 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
610 (set (match_operand:SI 0 "s_register_operand" "=r,r")
611 (plus:SI (match_dup 1)
612 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
613 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
616 add%?s\\t%0, %1, #%n2"
617 [(set_attr "conds" "set")]
620 ;; Convert the sequence
622 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
626 ;; bcs dest ((unsigned)rn >= 1)
627 ;; similarly for the beq variant using bcc.
628 ;; This is a common looping idiom (while (n--))
630 [(set (match_operand:SI 0 "arm_general_register_operand" "")
631 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
633 (set (match_operand 2 "cc_register" "")
634 (compare (match_dup 0) (const_int -1)))
636 (if_then_else (match_operator 3 "equality_operator"
637 [(match_dup 2) (const_int 0)])
638 (match_operand 4 "" "")
639 (match_operand 5 "" "")))]
640 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
644 (match_dup 1) (const_int 1)))
645 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
647 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
650 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
651 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
654 operands[2], const0_rtx);"
657 ;; The next four insns work because they compare the result with one of
658 ;; the operands, and we know that the use of the condition code is
659 ;; either GEU or LTU, so we can use the carry flag from the addition
660 ;; instead of doing the compare a second time.
661 (define_insn "*addsi3_compare_op1"
662 [(set (reg:CC_C CC_REGNUM)
664 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
665 (match_operand:SI 2 "arm_add_operand" "rI,L"))
667 (set (match_operand:SI 0 "s_register_operand" "=r,r")
668 (plus:SI (match_dup 1) (match_dup 2)))]
672 sub%?s\\t%0, %1, #%n2"
673 [(set_attr "conds" "set")]
676 (define_insn "*addsi3_compare_op2"
677 [(set (reg:CC_C CC_REGNUM)
679 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680 (match_operand:SI 2 "arm_add_operand" "rI,L"))
682 (set (match_operand:SI 0 "s_register_operand" "=r,r")
683 (plus:SI (match_dup 1) (match_dup 2)))]
687 sub%?s\\t%0, %1, #%n2"
688 [(set_attr "conds" "set")]
691 (define_insn "*compare_addsi2_op0"
692 [(set (reg:CC_C CC_REGNUM)
694 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
695 (match_operand:SI 1 "arm_add_operand" "rI,L"))
701 [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op1"
705 [(set (reg:CC_C CC_REGNUM)
707 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708 (match_operand:SI 1 "arm_add_operand" "rI,L"))
714 [(set_attr "conds" "set")]
717 (define_insn "*addsi3_carryin"
718 [(set (match_operand:SI 0 "s_register_operand" "=r")
719 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
720 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
721 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
724 [(set_attr "conds" "use")]
727 (define_insn "*addsi3_carryin_shift"
728 [(set (match_operand:SI 0 "s_register_operand" "=r")
729 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
731 (match_operator:SI 2 "shift_operator"
732 [(match_operand:SI 3 "s_register_operand" "r")
733 (match_operand:SI 4 "reg_or_int_operand" "rM")])
734 (match_operand:SI 1 "s_register_operand" "r"))))]
736 "adc%?\\t%0, %1, %3%S2"
737 [(set_attr "conds" "use")
738 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
739 (const_string "alu_shift")
740 (const_string "alu_shift_reg")))]
743 (define_insn "*addsi3_carryin_alt1"
744 [(set (match_operand:SI 0 "s_register_operand" "=r")
745 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
746 (match_operand:SI 2 "arm_rhs_operand" "rI"))
747 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
750 [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt2"
754 [(set (match_operand:SI 0 "s_register_operand" "=r")
755 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756 (match_operand:SI 1 "s_register_operand" "r"))
757 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
760 [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt3"
764 [(set (match_operand:SI 0 "s_register_operand" "=r")
765 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766 (match_operand:SI 2 "arm_rhs_operand" "rI"))
767 (match_operand:SI 1 "s_register_operand" "r")))]
770 [(set_attr "conds" "use")]
773 (define_insn "incscc"
774 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
775 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
776 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
777 (match_operand:SI 1 "s_register_operand" "0,?r")))]
781 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
782 [(set_attr "conds" "use")
783 (set_attr "length" "4,8")]
786 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
788 [(set (match_operand:SI 0 "s_register_operand" "")
789 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
790 (match_operand:SI 2 "s_register_operand" ""))
792 (clobber (match_operand:SI 3 "s_register_operand" ""))]
794 [(set (match_dup 3) (match_dup 1))
795 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
797 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
800 (define_expand "addsf3"
801 [(set (match_operand:SF 0 "s_register_operand" "")
802 (plus:SF (match_operand:SF 1 "s_register_operand" "")
803 (match_operand:SF 2 "arm_float_add_operand" "")))]
804 "TARGET_ARM && TARGET_HARD_FLOAT"
807 && !cirrus_fp_register (operands[2], SFmode))
808 operands[2] = force_reg (SFmode, operands[2]);
811 (define_expand "adddf3"
812 [(set (match_operand:DF 0 "s_register_operand" "")
813 (plus:DF (match_operand:DF 1 "s_register_operand" "")
814 (match_operand:DF 2 "arm_float_add_operand" "")))]
815 "TARGET_ARM && TARGET_HARD_FLOAT"
818 && !cirrus_fp_register (operands[2], DFmode))
819 operands[2] = force_reg (DFmode, operands[2]);
822 (define_expand "subdi3"
824 [(set (match_operand:DI 0 "s_register_operand" "")
825 (minus:DI (match_operand:DI 1 "s_register_operand" "")
826 (match_operand:DI 2 "s_register_operand" "")))
827 (clobber (reg:CC CC_REGNUM))])]
830 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
832 && cirrus_fp_register (operands[0], DImode)
833 && cirrus_fp_register (operands[1], DImode))
835 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
841 if (GET_CODE (operands[1]) != REG)
842 operands[1] = force_reg (SImode, operands[1]);
843 if (GET_CODE (operands[2]) != REG)
844 operands[2] = force_reg (SImode, operands[2]);
849 (define_insn "*arm_subdi3"
850 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
851 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
852 (match_operand:DI 2 "s_register_operand" "r,0,0")))
853 (clobber (reg:CC CC_REGNUM))]
855 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
856 [(set_attr "conds" "clob")
857 (set_attr "length" "8")]
860 (define_insn "*thumb_subdi3"
861 [(set (match_operand:DI 0 "register_operand" "=l")
862 (minus:DI (match_operand:DI 1 "register_operand" "0")
863 (match_operand:DI 2 "register_operand" "l")))
864 (clobber (reg:CC CC_REGNUM))]
866 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
867 [(set_attr "length" "4")]
870 (define_insn "*subdi_di_zesidi"
871 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
872 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
874 (match_operand:SI 2 "s_register_operand" "r,r"))))
875 (clobber (reg:CC CC_REGNUM))]
877 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
878 [(set_attr "conds" "clob")
879 (set_attr "length" "8")]
882 (define_insn "*subdi_di_sesidi"
883 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
884 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
886 (match_operand:SI 2 "s_register_operand" "r,r"))))
887 (clobber (reg:CC CC_REGNUM))]
889 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
890 [(set_attr "conds" "clob")
891 (set_attr "length" "8")]
894 (define_insn "*subdi_zesidi_di"
895 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
896 (minus:DI (zero_extend:DI
897 (match_operand:SI 2 "s_register_operand" "r,r"))
898 (match_operand:DI 1 "s_register_operand" "?r,0")))
899 (clobber (reg:CC CC_REGNUM))]
901 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
902 [(set_attr "conds" "clob")
903 (set_attr "length" "8")]
906 (define_insn "*subdi_sesidi_di"
907 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
908 (minus:DI (sign_extend:DI
909 (match_operand:SI 2 "s_register_operand" "r,r"))
910 (match_operand:DI 1 "s_register_operand" "?r,0")))
911 (clobber (reg:CC CC_REGNUM))]
913 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
914 [(set_attr "conds" "clob")
915 (set_attr "length" "8")]
918 (define_insn "*subdi_zesidi_zesidi"
919 [(set (match_operand:DI 0 "s_register_operand" "=r")
920 (minus:DI (zero_extend:DI
921 (match_operand:SI 1 "s_register_operand" "r"))
923 (match_operand:SI 2 "s_register_operand" "r"))))
924 (clobber (reg:CC CC_REGNUM))]
926 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
927 [(set_attr "conds" "clob")
928 (set_attr "length" "8")]
931 (define_expand "subsi3"
932 [(set (match_operand:SI 0 "s_register_operand" "")
933 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
934 (match_operand:SI 2 "s_register_operand" "")))]
937 if (GET_CODE (operands[1]) == CONST_INT)
941 arm_split_constant (MINUS, SImode, NULL_RTX,
942 INTVAL (operands[1]), operands[0],
943 operands[2], optimize && !no_new_pseudos);
946 else /* TARGET_THUMB */
947 operands[1] = force_reg (SImode, operands[1]);
952 (define_insn "*thumb_subsi3_insn"
953 [(set (match_operand:SI 0 "register_operand" "=l")
954 (minus:SI (match_operand:SI 1 "register_operand" "l")
955 (match_operand:SI 2 "register_operand" "l")))]
958 [(set_attr "length" "2")]
961 (define_insn_and_split "*arm_subsi3_insn"
962 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
963 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
964 (match_operand:SI 2 "s_register_operand" "r,r")))]
970 && GET_CODE (operands[1]) == CONST_INT
971 && !const_ok_for_arm (INTVAL (operands[1]))"
972 [(clobber (const_int 0))]
974 arm_split_constant (MINUS, SImode, curr_insn,
975 INTVAL (operands[1]), operands[0], operands[2], 0);
978 [(set_attr "length" "4,16")
979 (set_attr "predicable" "yes")]
983 [(match_scratch:SI 3 "r")
984 (set (match_operand:SI 0 "arm_general_register_operand" "")
985 (minus:SI (match_operand:SI 1 "const_int_operand" "")
986 (match_operand:SI 2 "arm_general_register_operand" "")))]
988 && !const_ok_for_arm (INTVAL (operands[1]))
989 && const_ok_for_arm (~INTVAL (operands[1]))"
990 [(set (match_dup 3) (match_dup 1))
991 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
995 (define_insn "*subsi3_compare0"
996 [(set (reg:CC_NOOV CC_REGNUM)
998 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
999 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1001 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1002 (minus:SI (match_dup 1) (match_dup 2)))]
1006 rsb%?s\\t%0, %2, %1"
1007 [(set_attr "conds" "set")]
1010 (define_insn "decscc"
1011 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1012 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1013 (match_operator:SI 2 "arm_comparison_operator"
1014 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1018 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1019 [(set_attr "conds" "use")
1020 (set_attr "length" "*,8")]
1023 (define_expand "subsf3"
1024 [(set (match_operand:SF 0 "s_register_operand" "")
1025 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1026 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1027 "TARGET_ARM && TARGET_HARD_FLOAT"
1029 if (TARGET_MAVERICK)
1031 if (!cirrus_fp_register (operands[1], SFmode))
1032 operands[1] = force_reg (SFmode, operands[1]);
1033 if (!cirrus_fp_register (operands[2], SFmode))
1034 operands[2] = force_reg (SFmode, operands[2]);
1038 (define_expand "subdf3"
1039 [(set (match_operand:DF 0 "s_register_operand" "")
1040 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1041 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1042 "TARGET_ARM && TARGET_HARD_FLOAT"
1044 if (TARGET_MAVERICK)
1046 if (!cirrus_fp_register (operands[1], DFmode))
1047 operands[1] = force_reg (DFmode, operands[1]);
1048 if (!cirrus_fp_register (operands[2], DFmode))
1049 operands[2] = force_reg (DFmode, operands[2]);
1054 ;; Multiplication insns
1056 (define_expand "mulsi3"
1057 [(set (match_operand:SI 0 "s_register_operand" "")
1058 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1059 (match_operand:SI 1 "s_register_operand" "")))]
1064 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1065 (define_insn "*arm_mulsi3"
1066 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1067 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1068 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1070 "mul%?\\t%0, %2, %1"
1071 [(set_attr "insn" "mul")
1072 (set_attr "predicable" "yes")]
1075 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1076 ; 1 and 2; are the same, because reload will make operand 0 match
1077 ; operand 1 without realizing that this conflicts with operand 2. We fix
1078 ; this by adding another alternative to match this case, and then `reload'
1079 ; it ourselves. This alternative must come first.
1080 (define_insn "*thumb_mulsi3"
1081 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1082 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1083 (match_operand:SI 2 "register_operand" "l,l,l")))]
1086 if (which_alternative < 2)
1087 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1089 return \"mul\\t%0, %0, %2\";
1091 [(set_attr "length" "4,4,2")
1092 (set_attr "insn" "mul")]
1095 (define_insn "*mulsi3_compare0"
1096 [(set (reg:CC_NOOV CC_REGNUM)
1097 (compare:CC_NOOV (mult:SI
1098 (match_operand:SI 2 "s_register_operand" "r,r")
1099 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1101 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1102 (mult:SI (match_dup 2) (match_dup 1)))]
1104 "mul%?s\\t%0, %2, %1"
1105 [(set_attr "conds" "set")
1106 (set_attr "insn" "muls")]
1109 (define_insn "*mulsi_compare0_scratch"
1110 [(set (reg:CC_NOOV CC_REGNUM)
1111 (compare:CC_NOOV (mult:SI
1112 (match_operand:SI 2 "s_register_operand" "r,r")
1113 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1115 (clobber (match_scratch:SI 0 "=&r,&r"))]
1117 "mul%?s\\t%0, %2, %1"
1118 [(set_attr "conds" "set")
1119 (set_attr "insn" "muls")]
1122 ;; Unnamed templates to match MLA instruction.
1124 (define_insn "*mulsi3addsi"
1125 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1127 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1128 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1129 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1131 "mla%?\\t%0, %2, %1, %3"
1132 [(set_attr "insn" "mla")
1133 (set_attr "predicable" "yes")]
1136 (define_insn "*mulsi3addsi_compare0"
1137 [(set (reg:CC_NOOV CC_REGNUM)
1140 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1141 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1142 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1144 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1145 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1148 "mla%?s\\t%0, %2, %1, %3"
1149 [(set_attr "conds" "set")
1150 (set_attr "insn" "mlas")]
1153 (define_insn "*mulsi3addsi_compare0_scratch"
1154 [(set (reg:CC_NOOV CC_REGNUM)
1157 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1158 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1159 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1161 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1163 "mla%?s\\t%0, %2, %1, %3"
1164 [(set_attr "conds" "set")
1165 (set_attr "insn" "mlas")]
1168 ;; Unnamed template to match long long multiply-accumulate (smlal)
1170 (define_insn "*mulsidi3adddi"
1171 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1174 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1175 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1176 (match_operand:DI 1 "s_register_operand" "0")))]
1177 "TARGET_ARM && arm_arch3m"
1178 "smlal%?\\t%Q0, %R0, %3, %2"
1179 [(set_attr "insn" "smlal")
1180 (set_attr "predicable" "yes")]
1183 (define_insn "mulsidi3"
1184 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1186 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1187 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1188 "TARGET_ARM && arm_arch3m"
1189 "smull%?\\t%Q0, %R0, %1, %2"
1190 [(set_attr "insn" "smull")
1191 (set_attr "predicable" "yes")]
1194 (define_insn "umulsidi3"
1195 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1197 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1198 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1199 "TARGET_ARM && arm_arch3m"
1200 "umull%?\\t%Q0, %R0, %1, %2"
1201 [(set_attr "insn" "umull")
1202 (set_attr "predicable" "yes")]
1205 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1207 (define_insn "*umulsidi3adddi"
1208 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1211 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1212 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1213 (match_operand:DI 1 "s_register_operand" "0")))]
1214 "TARGET_ARM && arm_arch3m"
1215 "umlal%?\\t%Q0, %R0, %3, %2"
1216 [(set_attr "insn" "umlal")
1217 (set_attr "predicable" "yes")]
1220 (define_insn "smulsi3_highpart"
1221 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1225 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1226 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1228 (clobber (match_scratch:SI 3 "=&r,&r"))]
1229 "TARGET_ARM && arm_arch3m"
1230 "smull%?\\t%3, %0, %2, %1"
1231 [(set_attr "insn" "smull")
1232 (set_attr "predicable" "yes")]
1235 (define_insn "umulsi3_highpart"
1236 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1240 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1241 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1243 (clobber (match_scratch:SI 3 "=&r,&r"))]
1244 "TARGET_ARM && arm_arch3m"
1245 "umull%?\\t%3, %0, %2, %1"
1246 [(set_attr "insn" "umull")
1247 (set_attr "predicable" "yes")]
1250 (define_insn "mulhisi3"
1251 [(set (match_operand:SI 0 "s_register_operand" "=r")
1252 (mult:SI (sign_extend:SI
1253 (match_operand:HI 1 "s_register_operand" "%r"))
1255 (match_operand:HI 2 "s_register_operand" "r"))))]
1256 "TARGET_ARM && arm_arch5e"
1257 "smulbb%?\\t%0, %1, %2"
1258 [(set_attr "insn" "smulxy")
1259 (set_attr "predicable" "yes")]
1262 (define_insn "*mulhisi3tb"
1263 [(set (match_operand:SI 0 "s_register_operand" "=r")
1264 (mult:SI (ashiftrt:SI
1265 (match_operand:SI 1 "s_register_operand" "r")
1268 (match_operand:HI 2 "s_register_operand" "r"))))]
1269 "TARGET_ARM && arm_arch5e"
1270 "smultb%?\\t%0, %1, %2"
1271 [(set_attr "insn" "smulxy")
1272 (set_attr "predicable" "yes")]
1275 (define_insn "*mulhisi3bt"
1276 [(set (match_operand:SI 0 "s_register_operand" "=r")
1277 (mult:SI (sign_extend:SI
1278 (match_operand:HI 1 "s_register_operand" "r"))
1280 (match_operand:SI 2 "s_register_operand" "r")
1282 "TARGET_ARM && arm_arch5e"
1283 "smulbt%?\\t%0, %1, %2"
1284 [(set_attr "insn" "smulxy")
1285 (set_attr "predicable" "yes")]
1288 (define_insn "*mulhisi3tt"
1289 [(set (match_operand:SI 0 "s_register_operand" "=r")
1290 (mult:SI (ashiftrt:SI
1291 (match_operand:SI 1 "s_register_operand" "r")
1294 (match_operand:SI 2 "s_register_operand" "r")
1296 "TARGET_ARM && arm_arch5e"
1297 "smultt%?\\t%0, %1, %2"
1298 [(set_attr "insn" "smulxy")
1299 (set_attr "predicable" "yes")]
1302 (define_insn "*mulhisi3addsi"
1303 [(set (match_operand:SI 0 "s_register_operand" "=r")
1304 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1305 (mult:SI (sign_extend:SI
1306 (match_operand:HI 2 "s_register_operand" "%r"))
1308 (match_operand:HI 3 "s_register_operand" "r")))))]
1309 "TARGET_ARM && arm_arch5e"
1310 "smlabb%?\\t%0, %2, %3, %1"
1311 [(set_attr "insn" "smlaxy")
1312 (set_attr "predicable" "yes")]
1315 (define_insn "*mulhidi3adddi"
1316 [(set (match_operand:DI 0 "s_register_operand" "=r")
1318 (match_operand:DI 1 "s_register_operand" "0")
1319 (mult:DI (sign_extend:DI
1320 (match_operand:HI 2 "s_register_operand" "%r"))
1322 (match_operand:HI 3 "s_register_operand" "r")))))]
1323 "TARGET_ARM && arm_arch5e"
1324 "smlalbb%?\\t%Q0, %R0, %2, %3"
1325 [(set_attr "insn" "smlalxy")
1326 (set_attr "predicable" "yes")])
1328 (define_expand "mulsf3"
1329 [(set (match_operand:SF 0 "s_register_operand" "")
1330 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1331 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1332 "TARGET_ARM && TARGET_HARD_FLOAT"
1335 && !cirrus_fp_register (operands[2], SFmode))
1336 operands[2] = force_reg (SFmode, operands[2]);
1339 (define_expand "muldf3"
1340 [(set (match_operand:DF 0 "s_register_operand" "")
1341 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1342 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1343 "TARGET_ARM && TARGET_HARD_FLOAT"
1346 && !cirrus_fp_register (operands[2], DFmode))
1347 operands[2] = force_reg (DFmode, operands[2]);
1352 (define_expand "divsf3"
1353 [(set (match_operand:SF 0 "s_register_operand" "")
1354 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1355 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1356 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1359 (define_expand "divdf3"
1360 [(set (match_operand:DF 0 "s_register_operand" "")
1361 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1362 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1363 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1368 (define_expand "modsf3"
1369 [(set (match_operand:SF 0 "s_register_operand" "")
1370 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1371 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1372 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1375 (define_expand "moddf3"
1376 [(set (match_operand:DF 0 "s_register_operand" "")
1377 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1378 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1379 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1382 ;; Boolean and,ior,xor insns
1384 ;; Split up double word logical operations
1386 ;; Split up simple DImode logical operations. Simply perform the logical
1387 ;; operation on the upper and lower halves of the registers.
1389 [(set (match_operand:DI 0 "s_register_operand" "")
1390 (match_operator:DI 6 "logical_binary_operator"
1391 [(match_operand:DI 1 "s_register_operand" "")
1392 (match_operand:DI 2 "s_register_operand" "")]))]
1393 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1394 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1395 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1398 operands[3] = gen_highpart (SImode, operands[0]);
1399 operands[0] = gen_lowpart (SImode, operands[0]);
1400 operands[4] = gen_highpart (SImode, operands[1]);
1401 operands[1] = gen_lowpart (SImode, operands[1]);
1402 operands[5] = gen_highpart (SImode, operands[2]);
1403 operands[2] = gen_lowpart (SImode, operands[2]);
1408 [(set (match_operand:DI 0 "s_register_operand" "")
1409 (match_operator:DI 6 "logical_binary_operator"
1410 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1411 (match_operand:DI 1 "s_register_operand" "")]))]
1412 "TARGET_ARM && reload_completed"
1413 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1414 (set (match_dup 3) (match_op_dup:SI 6
1415 [(ashiftrt:SI (match_dup 2) (const_int 31))
1419 operands[3] = gen_highpart (SImode, operands[0]);
1420 operands[0] = gen_lowpart (SImode, operands[0]);
1421 operands[4] = gen_highpart (SImode, operands[1]);
1422 operands[1] = gen_lowpart (SImode, operands[1]);
1423 operands[5] = gen_highpart (SImode, operands[2]);
1424 operands[2] = gen_lowpart (SImode, operands[2]);
1428 ;; The zero extend of operand 2 means we can just copy the high part of
1429 ;; operand1 into operand0.
1431 [(set (match_operand:DI 0 "s_register_operand" "")
1433 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1434 (match_operand:DI 1 "s_register_operand" "")))]
1435 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1436 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1437 (set (match_dup 3) (match_dup 4))]
1440 operands[4] = gen_highpart (SImode, operands[1]);
1441 operands[3] = gen_highpart (SImode, operands[0]);
1442 operands[0] = gen_lowpart (SImode, operands[0]);
1443 operands[1] = gen_lowpart (SImode, operands[1]);
1447 ;; The zero extend of operand 2 means we can just copy the high part of
1448 ;; operand1 into operand0.
1450 [(set (match_operand:DI 0 "s_register_operand" "")
1452 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1453 (match_operand:DI 1 "s_register_operand" "")))]
1454 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1455 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1456 (set (match_dup 3) (match_dup 4))]
1459 operands[4] = gen_highpart (SImode, operands[1]);
1460 operands[3] = gen_highpart (SImode, operands[0]);
1461 operands[0] = gen_lowpart (SImode, operands[0]);
1462 operands[1] = gen_lowpart (SImode, operands[1]);
1466 (define_insn "anddi3"
1467 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1468 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1469 (match_operand:DI 2 "s_register_operand" "r,r")))]
1470 "TARGET_ARM && ! TARGET_IWMMXT"
1472 [(set_attr "length" "8")]
1475 (define_insn_and_split "*anddi_zesidi_di"
1476 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1477 (and:DI (zero_extend:DI
1478 (match_operand:SI 2 "s_register_operand" "r,r"))
1479 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1482 "TARGET_ARM && reload_completed"
1483 ; The zero extend of operand 2 clears the high word of the output
1485 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1486 (set (match_dup 3) (const_int 0))]
1489 operands[3] = gen_highpart (SImode, operands[0]);
1490 operands[0] = gen_lowpart (SImode, operands[0]);
1491 operands[1] = gen_lowpart (SImode, operands[1]);
1493 [(set_attr "length" "8")]
1496 (define_insn "*anddi_sesdi_di"
1497 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1498 (and:DI (sign_extend:DI
1499 (match_operand:SI 2 "s_register_operand" "r,r"))
1500 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1503 [(set_attr "length" "8")]
1506 (define_expand "andsi3"
1507 [(set (match_operand:SI 0 "s_register_operand" "")
1508 (and:SI (match_operand:SI 1 "s_register_operand" "")
1509 (match_operand:SI 2 "reg_or_int_operand" "")))]
1514 if (GET_CODE (operands[2]) == CONST_INT)
1516 arm_split_constant (AND, SImode, NULL_RTX,
1517 INTVAL (operands[2]), operands[0],
1518 operands[1], optimize && !no_new_pseudos);
1523 else /* TARGET_THUMB */
1525 if (GET_CODE (operands[2]) != CONST_INT)
1526 operands[2] = force_reg (SImode, operands[2]);
1531 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1533 operands[2] = force_reg (SImode,
1534 GEN_INT (~INTVAL (operands[2])));
1536 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1541 for (i = 9; i <= 31; i++)
1543 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1545 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1549 else if ((((HOST_WIDE_INT) 1) << i) - 1
1550 == ~INTVAL (operands[2]))
1552 rtx shift = GEN_INT (i);
1553 rtx reg = gen_reg_rtx (SImode);
1555 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1556 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1562 operands[2] = force_reg (SImode, operands[2]);
1568 (define_insn_and_split "*arm_andsi3_insn"
1569 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1570 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1571 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1575 bic%?\\t%0, %1, #%B2
1578 && GET_CODE (operands[2]) == CONST_INT
1579 && !(const_ok_for_arm (INTVAL (operands[2]))
1580 || const_ok_for_arm (~INTVAL (operands[2])))"
1581 [(clobber (const_int 0))]
1583 arm_split_constant (AND, SImode, curr_insn,
1584 INTVAL (operands[2]), operands[0], operands[1], 0);
1587 [(set_attr "length" "4,4,16")
1588 (set_attr "predicable" "yes")]
1591 (define_insn "*thumb_andsi3_insn"
1592 [(set (match_operand:SI 0 "register_operand" "=l")
1593 (and:SI (match_operand:SI 1 "register_operand" "%0")
1594 (match_operand:SI 2 "register_operand" "l")))]
1597 [(set_attr "length" "2")]
1600 (define_insn "*andsi3_compare0"
1601 [(set (reg:CC_NOOV CC_REGNUM)
1603 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1604 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1606 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1607 (and:SI (match_dup 1) (match_dup 2)))]
1611 bic%?s\\t%0, %1, #%B2"
1612 [(set_attr "conds" "set")]
1615 (define_insn "*andsi3_compare0_scratch"
1616 [(set (reg:CC_NOOV CC_REGNUM)
1618 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1619 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1621 (clobber (match_scratch:SI 2 "=X,r"))]
1625 bic%?s\\t%2, %0, #%B1"
1626 [(set_attr "conds" "set")]
1629 (define_insn "*zeroextractsi_compare0_scratch"
1630 [(set (reg:CC_NOOV CC_REGNUM)
1631 (compare:CC_NOOV (zero_extract:SI
1632 (match_operand:SI 0 "s_register_operand" "r")
1633 (match_operand 1 "const_int_operand" "n")
1634 (match_operand 2 "const_int_operand" "n"))
1637 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1638 && INTVAL (operands[1]) > 0
1639 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1640 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1642 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1643 << INTVAL (operands[2]));
1644 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1647 [(set_attr "conds" "set")]
1650 (define_insn_and_split "*ne_zeroextractsi"
1651 [(set (match_operand:SI 0 "s_register_operand" "=r")
1652 (ne:SI (zero_extract:SI
1653 (match_operand:SI 1 "s_register_operand" "r")
1654 (match_operand:SI 2 "const_int_operand" "n")
1655 (match_operand:SI 3 "const_int_operand" "n"))
1657 (clobber (reg:CC CC_REGNUM))]
1659 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1660 && INTVAL (operands[2]) > 0
1661 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1662 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1665 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1666 && INTVAL (operands[2]) > 0
1667 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1668 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1669 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1670 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1672 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1674 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1675 (match_dup 0) (const_int 1)))]
1677 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1678 << INTVAL (operands[3]));
1680 [(set_attr "conds" "clob")
1681 (set_attr "length" "8")]
1684 (define_insn_and_split "*ne_zeroextractsi_shifted"
1685 [(set (match_operand:SI 0 "s_register_operand" "=r")
1686 (ne:SI (zero_extract:SI
1687 (match_operand:SI 1 "s_register_operand" "r")
1688 (match_operand:SI 2 "const_int_operand" "n")
1691 (clobber (reg:CC CC_REGNUM))]
1695 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1696 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1698 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1700 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1701 (match_dup 0) (const_int 1)))]
1703 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1705 [(set_attr "conds" "clob")
1706 (set_attr "length" "8")]
1709 (define_insn_and_split "*ite_ne_zeroextractsi"
1710 [(set (match_operand:SI 0 "s_register_operand" "=r")
1711 (if_then_else:SI (ne (zero_extract:SI
1712 (match_operand:SI 1 "s_register_operand" "r")
1713 (match_operand:SI 2 "const_int_operand" "n")
1714 (match_operand:SI 3 "const_int_operand" "n"))
1716 (match_operand:SI 4 "arm_not_operand" "rIK")
1718 (clobber (reg:CC CC_REGNUM))]
1720 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721 && INTVAL (operands[2]) > 0
1722 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1727 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1728 && INTVAL (operands[2]) > 0
1729 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1730 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1731 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1732 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1733 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1735 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1737 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1738 (match_dup 0) (match_dup 4)))]
1740 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1741 << INTVAL (operands[3]));
1743 [(set_attr "conds" "clob")
1744 (set_attr "length" "8")]
1747 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1748 [(set (match_operand:SI 0 "s_register_operand" "=r")
1749 (if_then_else:SI (ne (zero_extract:SI
1750 (match_operand:SI 1 "s_register_operand" "r")
1751 (match_operand:SI 2 "const_int_operand" "n")
1754 (match_operand:SI 3 "arm_not_operand" "rIK")
1756 (clobber (reg:CC CC_REGNUM))]
1757 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1759 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1760 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1761 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1763 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1765 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1766 (match_dup 0) (match_dup 3)))]
1768 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1770 [(set_attr "conds" "clob")
1771 (set_attr "length" "8")]
1775 [(set (match_operand:SI 0 "s_register_operand" "")
1776 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1777 (match_operand:SI 2 "const_int_operand" "")
1778 (match_operand:SI 3 "const_int_operand" "")))
1779 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1781 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1782 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1784 HOST_WIDE_INT temp = INTVAL (operands[2]);
1786 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1787 operands[3] = GEN_INT (32 - temp);
1792 [(set (match_operand:SI 0 "s_register_operand" "")
1793 (match_operator:SI 1 "shiftable_operator"
1794 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1795 (match_operand:SI 3 "const_int_operand" "")
1796 (match_operand:SI 4 "const_int_operand" ""))
1797 (match_operand:SI 5 "s_register_operand" "")]))
1798 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1800 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1803 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1806 HOST_WIDE_INT temp = INTVAL (operands[3]);
1808 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1809 operands[4] = GEN_INT (32 - temp);
1814 [(set (match_operand:SI 0 "s_register_operand" "")
1815 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1816 (match_operand:SI 2 "const_int_operand" "")
1817 (match_operand:SI 3 "const_int_operand" "")))]
1819 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1820 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1822 HOST_WIDE_INT temp = INTVAL (operands[2]);
1824 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1825 operands[3] = GEN_INT (32 - temp);
1830 [(set (match_operand:SI 0 "s_register_operand" "")
1831 (match_operator:SI 1 "shiftable_operator"
1832 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1833 (match_operand:SI 3 "const_int_operand" "")
1834 (match_operand:SI 4 "const_int_operand" ""))
1835 (match_operand:SI 5 "s_register_operand" "")]))
1836 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1838 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1841 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1844 HOST_WIDE_INT temp = INTVAL (operands[3]);
1846 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1847 operands[4] = GEN_INT (32 - temp);
1851 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1852 ;;; represented by the bitfield, then this will produce incorrect results.
1853 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1854 ;;; which have a real bit-field insert instruction, the truncation happens
1855 ;;; in the bit-field insert instruction itself. Since arm does not have a
1856 ;;; bit-field insert instruction, we would have to emit code here to truncate
1857 ;;; the value before we insert. This loses some of the advantage of having
1858 ;;; this insv pattern, so this pattern needs to be reevalutated.
1860 (define_expand "insv"
1861 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1862 (match_operand:SI 1 "general_operand" "")
1863 (match_operand:SI 2 "general_operand" ""))
1864 (match_operand:SI 3 "reg_or_int_operand" ""))]
1868 int start_bit = INTVAL (operands[2]);
1869 int width = INTVAL (operands[1]);
1870 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1871 rtx target, subtarget;
1873 target = operands[0];
1874 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1875 subreg as the final target. */
1876 if (GET_CODE (target) == SUBREG)
1878 subtarget = gen_reg_rtx (SImode);
1879 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1880 < GET_MODE_SIZE (SImode))
1881 target = SUBREG_REG (target);
1886 if (GET_CODE (operands[3]) == CONST_INT)
1888 /* Since we are inserting a known constant, we may be able to
1889 reduce the number of bits that we have to clear so that
1890 the mask becomes simple. */
1891 /* ??? This code does not check to see if the new mask is actually
1892 simpler. It may not be. */
1893 rtx op1 = gen_reg_rtx (SImode);
1894 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1895 start of this pattern. */
1896 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1897 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1899 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1900 emit_insn (gen_iorsi3 (subtarget, op1,
1901 gen_int_mode (op3_value << start_bit, SImode)));
1903 else if (start_bit == 0
1904 && !(const_ok_for_arm (mask)
1905 || const_ok_for_arm (~mask)))
1907 /* A Trick, since we are setting the bottom bits in the word,
1908 we can shift operand[3] up, operand[0] down, OR them together
1909 and rotate the result back again. This takes 3 insns, and
1910 the third might be mergeable into another op. */
1911 /* The shift up copes with the possibility that operand[3] is
1912 wider than the bitfield. */
1913 rtx op0 = gen_reg_rtx (SImode);
1914 rtx op1 = gen_reg_rtx (SImode);
1916 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1917 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1918 emit_insn (gen_iorsi3 (op1, op1, op0));
1919 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1921 else if ((width + start_bit == 32)
1922 && !(const_ok_for_arm (mask)
1923 || const_ok_for_arm (~mask)))
1925 /* Similar trick, but slightly less efficient. */
1927 rtx op0 = gen_reg_rtx (SImode);
1928 rtx op1 = gen_reg_rtx (SImode);
1930 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1931 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1932 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1933 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1937 rtx op0 = GEN_INT (mask);
1938 rtx op1 = gen_reg_rtx (SImode);
1939 rtx op2 = gen_reg_rtx (SImode);
1941 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1943 rtx tmp = gen_reg_rtx (SImode);
1945 emit_insn (gen_movsi (tmp, op0));
1949 /* Mask out any bits in operand[3] that are not needed. */
1950 emit_insn (gen_andsi3 (op1, operands[3], op0));
1952 if (GET_CODE (op0) == CONST_INT
1953 && (const_ok_for_arm (mask << start_bit)
1954 || const_ok_for_arm (~(mask << start_bit))))
1956 op0 = GEN_INT (~(mask << start_bit));
1957 emit_insn (gen_andsi3 (op2, operands[0], op0));
1961 if (GET_CODE (op0) == CONST_INT)
1963 rtx tmp = gen_reg_rtx (SImode);
1965 emit_insn (gen_movsi (tmp, op0));
1970 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1972 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1976 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1978 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1981 if (subtarget != target)
1983 /* If TARGET is still a SUBREG, then it must be wider than a word,
1984 so we must be careful only to set the subword we were asked to. */
1985 if (GET_CODE (target) == SUBREG)
1986 emit_move_insn (target, subtarget);
1988 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1995 ; constants for op 2 will never be given to these patterns.
1996 (define_insn_and_split "*anddi_notdi_di"
1997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1998 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1999 (match_operand:DI 2 "s_register_operand" "0,r")))]
2002 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2003 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2004 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2007 operands[3] = gen_highpart (SImode, operands[0]);
2008 operands[0] = gen_lowpart (SImode, operands[0]);
2009 operands[4] = gen_highpart (SImode, operands[1]);
2010 operands[1] = gen_lowpart (SImode, operands[1]);
2011 operands[5] = gen_highpart (SImode, operands[2]);
2012 operands[2] = gen_lowpart (SImode, operands[2]);
2014 [(set_attr "length" "8")
2015 (set_attr "predicable" "yes")]
2018 (define_insn_and_split "*anddi_notzesidi_di"
2019 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2020 (and:DI (not:DI (zero_extend:DI
2021 (match_operand:SI 2 "s_register_operand" "r,r")))
2022 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2025 bic%?\\t%Q0, %Q1, %2
2027 ; (not (zero_extend ...)) allows us to just copy the high word from
2028 ; operand1 to operand0.
2031 && operands[0] != operands[1]"
2032 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2033 (set (match_dup 3) (match_dup 4))]
2036 operands[3] = gen_highpart (SImode, operands[0]);
2037 operands[0] = gen_lowpart (SImode, operands[0]);
2038 operands[4] = gen_highpart (SImode, operands[1]);
2039 operands[1] = gen_lowpart (SImode, operands[1]);
2041 [(set_attr "length" "4,8")
2042 (set_attr "predicable" "yes")]
2045 (define_insn_and_split "*anddi_notsesidi_di"
2046 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2047 (and:DI (not:DI (sign_extend:DI
2048 (match_operand:SI 2 "s_register_operand" "r,r")))
2049 (match_operand:DI 1 "s_register_operand" "0,r")))]
2052 "TARGET_ARM && reload_completed"
2053 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2054 (set (match_dup 3) (and:SI (not:SI
2055 (ashiftrt:SI (match_dup 2) (const_int 31)))
2059 operands[3] = gen_highpart (SImode, operands[0]);
2060 operands[0] = gen_lowpart (SImode, operands[0]);
2061 operands[4] = gen_highpart (SImode, operands[1]);
2062 operands[1] = gen_lowpart (SImode, operands[1]);
2064 [(set_attr "length" "8")
2065 (set_attr "predicable" "yes")]
2068 (define_insn "andsi_notsi_si"
2069 [(set (match_operand:SI 0 "s_register_operand" "=r")
2070 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2071 (match_operand:SI 1 "s_register_operand" "r")))]
2073 "bic%?\\t%0, %1, %2"
2074 [(set_attr "predicable" "yes")]
2077 (define_insn "bicsi3"
2078 [(set (match_operand:SI 0 "register_operand" "=l")
2079 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2080 (match_operand:SI 2 "register_operand" "0")))]
2083 [(set_attr "length" "2")]
2086 (define_insn "andsi_not_shiftsi_si"
2087 [(set (match_operand:SI 0 "s_register_operand" "=r")
2088 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2089 [(match_operand:SI 2 "s_register_operand" "r")
2090 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2091 (match_operand:SI 1 "s_register_operand" "r")))]
2093 "bic%?\\t%0, %1, %2%S4"
2094 [(set_attr "predicable" "yes")
2095 (set_attr "shift" "2")
2096 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2097 (const_string "alu_shift")
2098 (const_string "alu_shift_reg")))]
2101 (define_insn "*andsi_notsi_si_compare0"
2102 [(set (reg:CC_NOOV CC_REGNUM)
2104 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2105 (match_operand:SI 1 "s_register_operand" "r"))
2107 (set (match_operand:SI 0 "s_register_operand" "=r")
2108 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2110 "bic%?s\\t%0, %1, %2"
2111 [(set_attr "conds" "set")]
2114 (define_insn "*andsi_notsi_si_compare0_scratch"
2115 [(set (reg:CC_NOOV CC_REGNUM)
2117 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2118 (match_operand:SI 1 "s_register_operand" "r"))
2120 (clobber (match_scratch:SI 0 "=r"))]
2122 "bic%?s\\t%0, %1, %2"
2123 [(set_attr "conds" "set")]
2126 (define_insn "iordi3"
2127 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2128 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2129 (match_operand:DI 2 "s_register_operand" "r,r")))]
2130 "TARGET_ARM && ! TARGET_IWMMXT"
2132 [(set_attr "length" "8")
2133 (set_attr "predicable" "yes")]
2136 (define_insn "*iordi_zesidi_di"
2137 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2138 (ior:DI (zero_extend:DI
2139 (match_operand:SI 2 "s_register_operand" "r,r"))
2140 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2143 orr%?\\t%Q0, %Q1, %2
2145 [(set_attr "length" "4,8")
2146 (set_attr "predicable" "yes")]
2149 (define_insn "*iordi_sesidi_di"
2150 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2151 (ior:DI (sign_extend:DI
2152 (match_operand:SI 2 "s_register_operand" "r,r"))
2153 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2156 [(set_attr "length" "8")
2157 (set_attr "predicable" "yes")]
2160 (define_expand "iorsi3"
2161 [(set (match_operand:SI 0 "s_register_operand" "")
2162 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2163 (match_operand:SI 2 "reg_or_int_operand" "")))]
2166 if (GET_CODE (operands[2]) == CONST_INT)
2170 arm_split_constant (IOR, SImode, NULL_RTX,
2171 INTVAL (operands[2]), operands[0], operands[1],
2172 optimize && !no_new_pseudos);
2175 else /* TARGET_THUMB */
2176 operands [2] = force_reg (SImode, operands [2]);
2181 (define_insn_and_split "*arm_iorsi3"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2183 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190 && GET_CODE (operands[2]) == CONST_INT
2191 && !const_ok_for_arm (INTVAL (operands[2]))"
2192 [(clobber (const_int 0))]
2194 arm_split_constant (IOR, SImode, curr_insn,
2195 INTVAL (operands[2]), operands[0], operands[1], 0);
2198 [(set_attr "length" "4,16")
2199 (set_attr "predicable" "yes")]
2202 (define_insn "*thumb_iorsi3"
2203 [(set (match_operand:SI 0 "register_operand" "=l")
2204 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205 (match_operand:SI 2 "register_operand" "l")))]
2208 [(set_attr "length" "2")]
2212 [(match_scratch:SI 3 "r")
2213 (set (match_operand:SI 0 "arm_general_register_operand" "")
2214 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2215 (match_operand:SI 2 "const_int_operand" "")))]
2217 && !const_ok_for_arm (INTVAL (operands[2]))
2218 && const_ok_for_arm (~INTVAL (operands[2]))"
2219 [(set (match_dup 3) (match_dup 2))
2220 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2224 (define_insn "*iorsi3_compare0"
2225 [(set (reg:CC_NOOV CC_REGNUM)
2226 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2229 (set (match_operand:SI 0 "s_register_operand" "=r")
2230 (ior:SI (match_dup 1) (match_dup 2)))]
2232 "orr%?s\\t%0, %1, %2"
2233 [(set_attr "conds" "set")]
2236 (define_insn "*iorsi3_compare0_scratch"
2237 [(set (reg:CC_NOOV CC_REGNUM)
2238 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2241 (clobber (match_scratch:SI 0 "=r"))]
2243 "orr%?s\\t%0, %1, %2"
2244 [(set_attr "conds" "set")]
2247 (define_insn "xordi3"
2248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2249 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2250 (match_operand:DI 2 "s_register_operand" "r,r")))]
2251 "TARGET_ARM && !TARGET_IWMMXT"
2253 [(set_attr "length" "8")
2254 (set_attr "predicable" "yes")]
2257 (define_insn "*xordi_zesidi_di"
2258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259 (xor:DI (zero_extend:DI
2260 (match_operand:SI 2 "s_register_operand" "r,r"))
2261 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2264 eor%?\\t%Q0, %Q1, %2
2266 [(set_attr "length" "4,8")
2267 (set_attr "predicable" "yes")]
2270 (define_insn "*xordi_sesidi_di"
2271 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272 (xor:DI (sign_extend:DI
2273 (match_operand:SI 2 "s_register_operand" "r,r"))
2274 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2277 [(set_attr "length" "8")
2278 (set_attr "predicable" "yes")]
2281 (define_expand "xorsi3"
2282 [(set (match_operand:SI 0 "s_register_operand" "")
2283 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284 (match_operand:SI 2 "arm_rhs_operand" "")))]
2287 if (GET_CODE (operands[2]) == CONST_INT)
2288 operands[2] = force_reg (SImode, operands[2]);
2292 (define_insn "*arm_xorsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "=r")
2294 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2297 "eor%?\\t%0, %1, %2"
2298 [(set_attr "predicable" "yes")]
2301 (define_insn "*thumb_xorsi3"
2302 [(set (match_operand:SI 0 "register_operand" "=l")
2303 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304 (match_operand:SI 2 "register_operand" "l")))]
2307 [(set_attr "length" "2")]
2310 (define_insn "*xorsi3_compare0"
2311 [(set (reg:CC_NOOV CC_REGNUM)
2312 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2315 (set (match_operand:SI 0 "s_register_operand" "=r")
2316 (xor:SI (match_dup 1) (match_dup 2)))]
2318 "eor%?s\\t%0, %1, %2"
2319 [(set_attr "conds" "set")]
2322 (define_insn "*xorsi3_compare0_scratch"
2323 [(set (reg:CC_NOOV CC_REGNUM)
2324 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2329 [(set_attr "conds" "set")]
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2337 [(set (match_operand:SI 0 "s_register_operand" "")
2338 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340 (match_operand:SI 3 "arm_rhs_operand" "")))
2341 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2343 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344 (not:SI (match_dup 3))))
2345 (set (match_dup 0) (not:SI (match_dup 4)))]
2349 (define_insn "*andsi_iorsi3_notsi"
2350 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2355 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356 [(set_attr "length" "8")
2357 (set_attr "predicable" "yes")]
2361 [(set (match_operand:SI 0 "s_register_operand" "")
2362 (match_operator:SI 1 "logical_binary_operator"
2363 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364 (match_operand:SI 3 "const_int_operand" "")
2365 (match_operand:SI 4 "const_int_operand" ""))
2366 (match_operator:SI 9 "logical_binary_operator"
2367 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368 (match_operand:SI 6 "const_int_operand" ""))
2369 (match_operand:SI 7 "s_register_operand" "")])]))
2370 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2372 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2376 [(ashift:SI (match_dup 2) (match_dup 4))
2380 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2383 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2387 [(set (match_operand:SI 0 "s_register_operand" "")
2388 (match_operator:SI 1 "logical_binary_operator"
2389 [(match_operator:SI 9 "logical_binary_operator"
2390 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391 (match_operand:SI 6 "const_int_operand" ""))
2392 (match_operand:SI 7 "s_register_operand" "")])
2393 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394 (match_operand:SI 3 "const_int_operand" "")
2395 (match_operand:SI 4 "const_int_operand" ""))]))
2396 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2398 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2402 [(ashift:SI (match_dup 2) (match_dup 4))
2406 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2409 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2413 [(set (match_operand:SI 0 "s_register_operand" "")
2414 (match_operator:SI 1 "logical_binary_operator"
2415 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416 (match_operand:SI 3 "const_int_operand" "")
2417 (match_operand:SI 4 "const_int_operand" ""))
2418 (match_operator:SI 9 "logical_binary_operator"
2419 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420 (match_operand:SI 6 "const_int_operand" ""))
2421 (match_operand:SI 7 "s_register_operand" "")])]))
2422 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2424 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2428 [(ashift:SI (match_dup 2) (match_dup 4))
2432 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2435 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2439 [(set (match_operand:SI 0 "s_register_operand" "")
2440 (match_operator:SI 1 "logical_binary_operator"
2441 [(match_operator:SI 9 "logical_binary_operator"
2442 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443 (match_operand:SI 6 "const_int_operand" ""))
2444 (match_operand:SI 7 "s_register_operand" "")])
2445 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446 (match_operand:SI 3 "const_int_operand" "")
2447 (match_operand:SI 4 "const_int_operand" ""))]))
2448 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2450 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2454 [(ashift:SI (match_dup 2) (match_dup 4))
2458 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2461 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2465 ;; Minimum and maximum insns
2467 (define_insn "smaxsi3"
2468 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2469 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2470 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2471 (clobber (reg:CC CC_REGNUM))]
2474 cmp\\t%1, %2\;movlt\\t%0, %2
2475 cmp\\t%1, %2\;movge\\t%0, %1
2476 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2477 [(set_attr "conds" "clob")
2478 (set_attr "length" "8,8,12")]
2481 (define_insn "sminsi3"
2482 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2485 (clobber (reg:CC CC_REGNUM))]
2488 cmp\\t%1, %2\;movge\\t%0, %2
2489 cmp\\t%1, %2\;movlt\\t%0, %1
2490 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2491 [(set_attr "conds" "clob")
2492 (set_attr "length" "8,8,12")]
2495 (define_insn "umaxsi3"
2496 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2499 (clobber (reg:CC CC_REGNUM))]
2502 cmp\\t%1, %2\;movcc\\t%0, %2
2503 cmp\\t%1, %2\;movcs\\t%0, %1
2504 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2505 [(set_attr "conds" "clob")
2506 (set_attr "length" "8,8,12")]
2509 (define_insn "uminsi3"
2510 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2513 (clobber (reg:CC CC_REGNUM))]
2516 cmp\\t%1, %2\;movcs\\t%0, %2
2517 cmp\\t%1, %2\;movcc\\t%0, %1
2518 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2519 [(set_attr "conds" "clob")
2520 (set_attr "length" "8,8,12")]
2523 (define_insn "*store_minmaxsi"
2524 [(set (match_operand:SI 0 "memory_operand" "=m")
2525 (match_operator:SI 3 "minmax_operator"
2526 [(match_operand:SI 1 "s_register_operand" "r")
2527 (match_operand:SI 2 "s_register_operand" "r")]))
2528 (clobber (reg:CC CC_REGNUM))]
2531 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532 operands[1], operands[2]);
2533 output_asm_insn (\"cmp\\t%1, %2\", operands);
2534 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2538 [(set_attr "conds" "clob")
2539 (set_attr "length" "12")
2540 (set_attr "type" "store1")]
2543 ; Reject the frame pointer in operand[1], since reloading this after
2544 ; it has been eliminated can cause carnage.
2545 (define_insn "*minmax_arithsi"
2546 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547 (match_operator:SI 4 "shiftable_operator"
2548 [(match_operator:SI 5 "minmax_operator"
2549 [(match_operand:SI 2 "s_register_operand" "r,r")
2550 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2552 (clobber (reg:CC CC_REGNUM))]
2554 && (GET_CODE (operands[1]) != REG
2555 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2556 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2559 enum rtx_code code = GET_CODE (operands[4]);
2561 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2562 operands[2], operands[3]);
2563 output_asm_insn (\"cmp\\t%2, %3\", operands);
2564 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2565 if (which_alternative != 0 || operands[3] != const0_rtx
2566 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2567 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2570 [(set_attr "conds" "clob")
2571 (set_attr "length" "12")]
2575 ;; Shift and rotation insns
2577 (define_expand "ashldi3"
2578 [(set (match_operand:DI 0 "s_register_operand" "")
2579 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2580 (match_operand:SI 2 "reg_or_int_operand" "")))]
2583 if (GET_CODE (operands[2]) == CONST_INT)
2585 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2587 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2590 /* Ideally we shouldn't fail here if we could know that operands[1]
2591 ends up already living in an iwmmxt register. Otherwise it's
2592 cheaper to have the alternate code being generated than moving
2593 values to iwmmxt regs and back. */
2596 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2601 (define_insn "arm_ashldi3_1bit"
2602 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2603 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2605 (clobber (reg:CC CC_REGNUM))]
2607 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2608 [(set_attr "conds" "clob")
2609 (set_attr "length" "8")]
2612 (define_expand "ashlsi3"
2613 [(set (match_operand:SI 0 "s_register_operand" "")
2614 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2615 (match_operand:SI 2 "arm_rhs_operand" "")))]
2618 if (GET_CODE (operands[2]) == CONST_INT
2619 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2621 emit_insn (gen_movsi (operands[0], const0_rtx));
2627 (define_insn "*thumb_ashlsi3"
2628 [(set (match_operand:SI 0 "register_operand" "=l,l")
2629 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2630 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2633 [(set_attr "length" "2")]
2636 (define_expand "ashrdi3"
2637 [(set (match_operand:DI 0 "s_register_operand" "")
2638 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2639 (match_operand:SI 2 "reg_or_int_operand" "")))]
2642 if (GET_CODE (operands[2]) == CONST_INT)
2644 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2646 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2649 /* Ideally we shouldn't fail here if we could know that operands[1]
2650 ends up already living in an iwmmxt register. Otherwise it's
2651 cheaper to have the alternate code being generated than moving
2652 values to iwmmxt regs and back. */
2655 else if (!TARGET_REALLY_IWMMXT)
2660 (define_insn "arm_ashrdi3_1bit"
2661 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2662 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2664 (clobber (reg:CC CC_REGNUM))]
2666 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2667 [(set_attr "conds" "clob")
2668 (set_attr "length" "8")]
2671 (define_expand "ashrsi3"
2672 [(set (match_operand:SI 0 "s_register_operand" "")
2673 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2674 (match_operand:SI 2 "arm_rhs_operand" "")))]
2677 if (GET_CODE (operands[2]) == CONST_INT
2678 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679 operands[2] = GEN_INT (31);
2683 (define_insn "*thumb_ashrsi3"
2684 [(set (match_operand:SI 0 "register_operand" "=l,l")
2685 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2686 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2689 [(set_attr "length" "2")]
2692 (define_expand "lshrdi3"
2693 [(set (match_operand:DI 0 "s_register_operand" "")
2694 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2695 (match_operand:SI 2 "reg_or_int_operand" "")))]
2698 if (GET_CODE (operands[2]) == CONST_INT)
2700 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2702 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2705 /* Ideally we shouldn't fail here if we could know that operands[1]
2706 ends up already living in an iwmmxt register. Otherwise it's
2707 cheaper to have the alternate code being generated than moving
2708 values to iwmmxt regs and back. */
2711 else if (!TARGET_REALLY_IWMMXT)
2716 (define_insn "arm_lshrdi3_1bit"
2717 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2718 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2720 (clobber (reg:CC CC_REGNUM))]
2722 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2723 [(set_attr "conds" "clob")
2724 (set_attr "length" "8")]
2727 (define_expand "lshrsi3"
2728 [(set (match_operand:SI 0 "s_register_operand" "")
2729 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2730 (match_operand:SI 2 "arm_rhs_operand" "")))]
2733 if (GET_CODE (operands[2]) == CONST_INT
2734 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2736 emit_insn (gen_movsi (operands[0], const0_rtx));
2742 (define_insn "*thumb_lshrsi3"
2743 [(set (match_operand:SI 0 "register_operand" "=l,l")
2744 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2745 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2748 [(set_attr "length" "2")]
2751 (define_expand "rotlsi3"
2752 [(set (match_operand:SI 0 "s_register_operand" "")
2753 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2754 (match_operand:SI 2 "reg_or_int_operand" "")))]
2757 if (GET_CODE (operands[2]) == CONST_INT)
2758 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2761 rtx reg = gen_reg_rtx (SImode);
2762 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2768 (define_expand "rotrsi3"
2769 [(set (match_operand:SI 0 "s_register_operand" "")
2770 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2771 (match_operand:SI 2 "arm_rhs_operand" "")))]
2776 if (GET_CODE (operands[2]) == CONST_INT
2777 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2778 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2780 else /* TARGET_THUMB */
2782 if (GET_CODE (operands [2]) == CONST_INT)
2783 operands [2] = force_reg (SImode, operands[2]);
2788 (define_insn "*thumb_rotrsi3"
2789 [(set (match_operand:SI 0 "register_operand" "=l")
2790 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2791 (match_operand:SI 2 "register_operand" "l")))]
2794 [(set_attr "length" "2")]
2797 (define_insn "*arm_shiftsi3"
2798 [(set (match_operand:SI 0 "s_register_operand" "=r")
2799 (match_operator:SI 3 "shift_operator"
2800 [(match_operand:SI 1 "s_register_operand" "r")
2801 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2804 [(set_attr "predicable" "yes")
2805 (set_attr "shift" "1")
2806 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2807 (const_string "alu_shift")
2808 (const_string "alu_shift_reg")))]
2811 (define_insn "*shiftsi3_compare0"
2812 [(set (reg:CC_NOOV CC_REGNUM)
2813 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2814 [(match_operand:SI 1 "s_register_operand" "r")
2815 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2817 (set (match_operand:SI 0 "s_register_operand" "=r")
2818 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2820 "mov%?s\\t%0, %1%S3"
2821 [(set_attr "conds" "set")
2822 (set_attr "shift" "1")
2823 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2824 (const_string "alu_shift")
2825 (const_string "alu_shift_reg")))]
2828 (define_insn "*shiftsi3_compare0_scratch"
2829 [(set (reg:CC_NOOV CC_REGNUM)
2830 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2831 [(match_operand:SI 1 "s_register_operand" "r")
2832 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2834 (clobber (match_scratch:SI 0 "=r"))]
2836 "mov%?s\\t%0, %1%S3"
2837 [(set_attr "conds" "set")
2838 (set_attr "shift" "1")]
2841 (define_insn "*notsi_shiftsi"
2842 [(set (match_operand:SI 0 "s_register_operand" "=r")
2843 (not:SI (match_operator:SI 3 "shift_operator"
2844 [(match_operand:SI 1 "s_register_operand" "r")
2845 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2848 [(set_attr "predicable" "yes")
2849 (set_attr "shift" "1")
2850 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2851 (const_string "alu_shift")
2852 (const_string "alu_shift_reg")))]
2855 (define_insn "*notsi_shiftsi_compare0"
2856 [(set (reg:CC_NOOV CC_REGNUM)
2857 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2858 [(match_operand:SI 1 "s_register_operand" "r")
2859 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2861 (set (match_operand:SI 0 "s_register_operand" "=r")
2862 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2864 "mvn%?s\\t%0, %1%S3"
2865 [(set_attr "conds" "set")
2866 (set_attr "shift" "1")
2867 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868 (const_string "alu_shift")
2869 (const_string "alu_shift_reg")))]
2872 (define_insn "*not_shiftsi_compare0_scratch"
2873 [(set (reg:CC_NOOV CC_REGNUM)
2874 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2875 [(match_operand:SI 1 "s_register_operand" "r")
2876 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2878 (clobber (match_scratch:SI 0 "=r"))]
2880 "mvn%?s\\t%0, %1%S3"
2881 [(set_attr "conds" "set")
2882 (set_attr "shift" "1")
2883 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2884 (const_string "alu_shift")
2885 (const_string "alu_shift_reg")))]
2888 ;; We don't really have extzv, but defining this using shifts helps
2889 ;; to reduce register pressure later on.
2891 (define_expand "extzv"
2893 (ashift:SI (match_operand:SI 1 "register_operand" "")
2894 (match_operand:SI 2 "const_int_operand" "")))
2895 (set (match_operand:SI 0 "register_operand" "")
2896 (lshiftrt:SI (match_dup 4)
2897 (match_operand:SI 3 "const_int_operand" "")))]
2901 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2902 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2904 operands[3] = GEN_INT (rshift);
2908 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2912 operands[2] = GEN_INT (lshift);
2913 operands[4] = gen_reg_rtx (SImode);
2918 ;; Unary arithmetic insns
2920 (define_expand "negdi2"
2922 [(set (match_operand:DI 0 "s_register_operand" "")
2923 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2924 (clobber (reg:CC CC_REGNUM))])]
2929 if (GET_CODE (operands[1]) != REG)
2930 operands[1] = force_reg (SImode, operands[1]);
2935 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2936 ;; The second alternative is to allow the common case of a *full* overlap.
2937 (define_insn "*arm_negdi2"
2938 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2939 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2940 (clobber (reg:CC CC_REGNUM))]
2942 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2943 [(set_attr "conds" "clob")
2944 (set_attr "length" "8")]
2947 (define_insn "*thumb_negdi2"
2948 [(set (match_operand:DI 0 "register_operand" "=&l")
2949 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2950 (clobber (reg:CC CC_REGNUM))]
2952 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2953 [(set_attr "length" "6")]
2956 (define_expand "negsi2"
2957 [(set (match_operand:SI 0 "s_register_operand" "")
2958 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2963 (define_insn "*arm_negsi2"
2964 [(set (match_operand:SI 0 "s_register_operand" "=r")
2965 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2967 "rsb%?\\t%0, %1, #0"
2968 [(set_attr "predicable" "yes")]
2971 (define_insn "*thumb_negsi2"
2972 [(set (match_operand:SI 0 "register_operand" "=l")
2973 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2976 [(set_attr "length" "2")]
2979 (define_expand "negsf2"
2980 [(set (match_operand:SF 0 "s_register_operand" "")
2981 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2982 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2986 (define_expand "negdf2"
2987 [(set (match_operand:DF 0 "s_register_operand" "")
2988 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2989 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2992 ;; abssi2 doesn't really clobber the condition codes if a different register
2993 ;; is being set. To keep things simple, assume during rtl manipulations that
2994 ;; it does, but tell the final scan operator the truth. Similarly for
2997 (define_expand "abssi2"
2999 [(set (match_operand:SI 0 "s_register_operand" "")
3000 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3001 (clobber (reg:CC CC_REGNUM))])]
3005 (define_insn "*arm_abssi2"
3006 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3007 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3008 (clobber (reg:CC CC_REGNUM))]
3011 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3012 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3013 [(set_attr "conds" "clob,*")
3014 (set_attr "shift" "1")
3015 ;; predicable can't be set based on the variant, so left as no
3016 (set_attr "length" "8")]
3019 (define_insn "*neg_abssi2"
3020 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3021 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3022 (clobber (reg:CC CC_REGNUM))]
3025 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3026 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3027 [(set_attr "conds" "clob,*")
3028 (set_attr "shift" "1")
3029 ;; predicable can't be set based on the variant, so left as no
3030 (set_attr "length" "8")]
3033 (define_expand "abssf2"
3034 [(set (match_operand:SF 0 "s_register_operand" "")
3035 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3036 "TARGET_ARM && TARGET_HARD_FLOAT"
3039 (define_expand "absdf2"
3040 [(set (match_operand:DF 0 "s_register_operand" "")
3041 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3042 "TARGET_ARM && TARGET_HARD_FLOAT"
3045 (define_expand "sqrtsf2"
3046 [(set (match_operand:SF 0 "s_register_operand" "")
3047 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3051 (define_expand "sqrtdf2"
3052 [(set (match_operand:DF 0 "s_register_operand" "")
3053 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057 (define_insn_and_split "one_cmpldi2"
3058 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3059 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3062 "TARGET_ARM && reload_completed"
3063 [(set (match_dup 0) (not:SI (match_dup 1)))
3064 (set (match_dup 2) (not:SI (match_dup 3)))]
3067 operands[2] = gen_highpart (SImode, operands[0]);
3068 operands[0] = gen_lowpart (SImode, operands[0]);
3069 operands[3] = gen_highpart (SImode, operands[1]);
3070 operands[1] = gen_lowpart (SImode, operands[1]);
3072 [(set_attr "length" "8")
3073 (set_attr "predicable" "yes")]
3076 (define_expand "one_cmplsi2"
3077 [(set (match_operand:SI 0 "s_register_operand" "")
3078 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3083 (define_insn "*arm_one_cmplsi2"
3084 [(set (match_operand:SI 0 "s_register_operand" "=r")
3085 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3088 [(set_attr "predicable" "yes")]
3091 (define_insn "*thumb_one_cmplsi2"
3092 [(set (match_operand:SI 0 "register_operand" "=l")
3093 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3096 [(set_attr "length" "2")]
3099 (define_insn "*notsi_compare0"
3100 [(set (reg:CC_NOOV CC_REGNUM)
3101 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3103 (set (match_operand:SI 0 "s_register_operand" "=r")
3104 (not:SI (match_dup 1)))]
3107 [(set_attr "conds" "set")]
3110 (define_insn "*notsi_compare0_scratch"
3111 [(set (reg:CC_NOOV CC_REGNUM)
3112 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3114 (clobber (match_scratch:SI 0 "=r"))]
3117 [(set_attr "conds" "set")]
3120 ;; Fixed <--> Floating conversion insns
3122 (define_expand "floatsisf2"
3123 [(set (match_operand:SF 0 "s_register_operand" "")
3124 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3125 "TARGET_ARM && TARGET_HARD_FLOAT"
3127 if (TARGET_MAVERICK)
3129 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3134 (define_expand "floatsidf2"
3135 [(set (match_operand:DF 0 "s_register_operand" "")
3136 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3137 "TARGET_ARM && TARGET_HARD_FLOAT"
3139 if (TARGET_MAVERICK)
3141 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3146 (define_expand "fix_truncsfsi2"
3147 [(set (match_operand:SI 0 "s_register_operand" "")
3148 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3149 "TARGET_ARM && TARGET_HARD_FLOAT"
3151 if (TARGET_MAVERICK)
3153 if (!cirrus_fp_register (operands[0], SImode))
3154 operands[0] = force_reg (SImode, operands[0]);
3155 if (!cirrus_fp_register (operands[1], SFmode))
3156 operands[1] = force_reg (SFmode, operands[0]);
3157 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3162 (define_expand "fix_truncdfsi2"
3163 [(set (match_operand:SI 0 "s_register_operand" "")
3164 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3165 "TARGET_ARM && TARGET_HARD_FLOAT"
3167 if (TARGET_MAVERICK)
3169 if (!cirrus_fp_register (operands[1], DFmode))
3170 operands[1] = force_reg (DFmode, operands[0]);
3171 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178 (define_expand "truncdfsf2"
3179 [(set (match_operand:SF 0 "s_register_operand" "")
3181 (match_operand:DF 1 "s_register_operand" "")))]
3182 "TARGET_ARM && TARGET_HARD_FLOAT"
3186 ;; Zero and sign extension instructions.
3188 (define_insn "zero_extendsidi2"
3189 [(set (match_operand:DI 0 "s_register_operand" "=r")
3190 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3193 if (REGNO (operands[1])
3194 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196 return \"mov%?\\t%R0, #0\";
3198 [(set_attr "length" "8")
3199 (set_attr "predicable" "yes")]
3202 (define_insn "zero_extendqidi2"
3203 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3204 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3207 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3209 [(set_attr "length" "8")
3210 (set_attr "predicable" "yes")
3211 (set_attr "type" "*,load_byte")
3212 (set_attr "pool_range" "*,4092")
3213 (set_attr "neg_pool_range" "*,4084")]
3216 (define_insn "extendsidi2"
3217 [(set (match_operand:DI 0 "s_register_operand" "=r")
3218 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3221 if (REGNO (operands[1])
3222 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224 return \"mov%?\\t%R0, %Q0, asr #31\";
3226 [(set_attr "length" "8")
3227 (set_attr "shift" "1")
3228 (set_attr "predicable" "yes")]
3231 (define_expand "zero_extendhisi2"
3233 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3235 (set (match_operand:SI 0 "s_register_operand" "")
3236 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3240 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3242 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3243 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3247 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3249 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3253 if (!s_register_operand (operands[1], HImode))
3254 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3258 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3259 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3263 operands[1] = gen_lowpart (SImode, operands[1]);
3264 operands[2] = gen_reg_rtx (SImode);
3268 (define_insn "*thumb_zero_extendhisi2"
3269 [(set (match_operand:SI 0 "register_operand" "=l")
3270 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3271 "TARGET_THUMB && !arm_arch6"
3273 rtx mem = XEXP (operands[1], 0);
3275 if (GET_CODE (mem) == CONST)
3276 mem = XEXP (mem, 0);
3278 if (GET_CODE (mem) == LABEL_REF)
3279 return \"ldr\\t%0, %1\";
3281 if (GET_CODE (mem) == PLUS)
3283 rtx a = XEXP (mem, 0);
3284 rtx b = XEXP (mem, 1);
3286 /* This can happen due to bugs in reload. */
3287 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3290 ops[0] = operands[0];
3293 output_asm_insn (\"mov %0, %1\", ops);
3295 XEXP (mem, 0) = operands[0];
3298 else if ( GET_CODE (a) == LABEL_REF
3299 && GET_CODE (b) == CONST_INT)
3300 return \"ldr\\t%0, %1\";
3303 return \"ldrh\\t%0, %1\";
3305 [(set_attr "length" "4")
3306 (set_attr "type" "load_byte")
3307 (set_attr "pool_range" "60")]
3310 (define_insn "*thumb_zero_extendhisi2_v6"
3311 [(set (match_operand:SI 0 "register_operand" "=l,l")
3312 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3313 "TARGET_THUMB && arm_arch6"
3317 if (which_alternative == 0)
3318 return \"uxth\\t%0, %1\";
3320 mem = XEXP (operands[1], 0);
3322 if (GET_CODE (mem) == CONST)
3323 mem = XEXP (mem, 0);
3325 if (GET_CODE (mem) == LABEL_REF)
3326 return \"ldr\\t%0, %1\";
3328 if (GET_CODE (mem) == PLUS)
3330 rtx a = XEXP (mem, 0);
3331 rtx b = XEXP (mem, 1);
3333 /* This can happen due to bugs in reload. */
3334 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3337 ops[0] = operands[0];
3340 output_asm_insn (\"mov %0, %1\", ops);
3342 XEXP (mem, 0) = operands[0];
3345 else if ( GET_CODE (a) == LABEL_REF
3346 && GET_CODE (b) == CONST_INT)
3347 return \"ldr\\t%0, %1\";
3350 return \"ldrh\\t%0, %1\";
3352 [(set_attr "length" "2,4")
3353 (set_attr "type" "alu_shift,load_byte")
3354 (set_attr "pool_range" "*,60")]
3357 (define_insn "*arm_zero_extendhisi2"
3358 [(set (match_operand:SI 0 "s_register_operand" "=r")
3359 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3360 "TARGET_ARM && arm_arch4 && !arm_arch6"
3362 [(set_attr "type" "load_byte")
3363 (set_attr "predicable" "yes")
3364 (set_attr "pool_range" "256")
3365 (set_attr "neg_pool_range" "244")]
3368 (define_insn "*arm_zero_extendhisi2_v6"
3369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3370 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3371 "TARGET_ARM && arm_arch6"
3375 [(set_attr "type" "alu_shift,load_byte")
3376 (set_attr "predicable" "yes")
3377 (set_attr "pool_range" "*,256")
3378 (set_attr "neg_pool_range" "*,244")]
3381 (define_insn "*arm_zero_extendhisi2addsi"
3382 [(set (match_operand:SI 0 "s_register_operand" "=r")
3383 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3384 (match_operand:SI 2 "s_register_operand" "r")))]
3385 "TARGET_ARM && arm_arch6"
3386 "uxtah%?\\t%0, %2, %1"
3387 [(set_attr "type" "alu_shift")
3388 (set_attr "predicable" "yes")]
3392 [(set (match_operand:SI 0 "s_register_operand" "")
3393 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3394 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3395 "TARGET_ARM && (!arm_arch4)"
3396 [(set (match_dup 2) (match_dup 1))
3397 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3399 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3405 [(set (match_operand:SI 0 "s_register_operand" "")
3406 (match_operator:SI 3 "shiftable_operator"
3407 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3408 (match_operand:SI 4 "s_register_operand" "")]))
3409 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3410 "TARGET_ARM && (!arm_arch4)"
3411 [(set (match_dup 2) (match_dup 1))
3414 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3416 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3421 (define_expand "zero_extendqisi2"
3422 [(set (match_operand:SI 0 "s_register_operand" "")
3423 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3426 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3430 emit_insn (gen_andsi3 (operands[0],
3431 gen_lowpart (SImode, operands[1]),
3434 else /* TARGET_THUMB */
3436 rtx temp = gen_reg_rtx (SImode);
3439 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3440 operands[1] = gen_lowpart (SImode, operands[1]);
3443 ops[1] = operands[1];
3444 ops[2] = GEN_INT (24);
3446 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3447 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3449 ops[0] = operands[0];
3451 ops[2] = GEN_INT (24);
3453 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3461 (define_insn "*thumb_zero_extendqisi2"
3462 [(set (match_operand:SI 0 "register_operand" "=l")
3463 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3464 "TARGET_THUMB && !arm_arch6"
3466 [(set_attr "length" "2")
3467 (set_attr "type" "load_byte")
3468 (set_attr "pool_range" "32")]
3471 (define_insn "*thumb_zero_extendqisi2_v6"
3472 [(set (match_operand:SI 0 "register_operand" "=l,l")
3473 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3474 "TARGET_THUMB && arm_arch6"
3478 [(set_attr "length" "2,2")
3479 (set_attr "type" "alu_shift,load_byte")
3480 (set_attr "pool_range" "*,32")]
3483 (define_insn "*arm_zero_extendqisi2"
3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3486 "TARGET_ARM && !arm_arch6"
3487 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3488 [(set_attr "type" "load_byte")
3489 (set_attr "predicable" "yes")
3490 (set_attr "pool_range" "4096")
3491 (set_attr "neg_pool_range" "4084")]
3494 (define_insn "*arm_zero_extendqisi2_v6"
3495 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3496 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3497 "TARGET_ARM && arm_arch6"
3500 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3501 [(set_attr "type" "alu_shift,load_byte")
3502 (set_attr "predicable" "yes")
3503 (set_attr "pool_range" "*,4096")
3504 (set_attr "neg_pool_range" "*,4084")]
3507 (define_insn "*arm_zero_extendqisi2addsi"
3508 [(set (match_operand:SI 0 "s_register_operand" "=r")
3509 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3510 (match_operand:SI 2 "s_register_operand" "r")))]
3511 "TARGET_ARM && arm_arch6"
3512 "uxtab%?\\t%0, %2, %1"
3513 [(set_attr "predicable" "yes")
3514 (set_attr "type" "alu_shift")]
3518 [(set (match_operand:SI 0 "s_register_operand" "")
3519 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3520 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3521 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3522 [(set (match_dup 2) (match_dup 1))
3523 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3527 (define_insn "*compareqi_eq0"
3528 [(set (reg:CC_Z CC_REGNUM)
3529 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3533 [(set_attr "conds" "set")]
3536 (define_expand "extendhisi2"
3538 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3540 (set (match_operand:SI 0 "s_register_operand" "")
3541 (ashiftrt:SI (match_dup 2)
3546 if (GET_CODE (operands[1]) == MEM)
3550 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3555 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3556 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3561 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3563 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3567 if (!s_register_operand (operands[1], HImode))
3568 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3573 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3575 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3576 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3581 operands[1] = gen_lowpart (SImode, operands[1]);
3582 operands[2] = gen_reg_rtx (SImode);
3586 (define_insn "thumb_extendhisi2"
3587 [(set (match_operand:SI 0 "register_operand" "=l")
3588 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3589 (clobber (match_scratch:SI 2 "=&l"))]
3590 "TARGET_THUMB && !arm_arch6"
3594 rtx mem = XEXP (operands[1], 0);
3596 /* This code used to try to use 'V', and fix the address only if it was
3597 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3598 range of QImode offsets, and offsettable_address_p does a QImode
3601 if (GET_CODE (mem) == CONST)
3602 mem = XEXP (mem, 0);
3604 if (GET_CODE (mem) == LABEL_REF)
3605 return \"ldr\\t%0, %1\";
3607 if (GET_CODE (mem) == PLUS)
3609 rtx a = XEXP (mem, 0);
3610 rtx b = XEXP (mem, 1);
3612 if (GET_CODE (a) == LABEL_REF
3613 && GET_CODE (b) == CONST_INT)
3614 return \"ldr\\t%0, %1\";
3616 if (GET_CODE (b) == REG)
3617 return \"ldrsh\\t%0, %1\";
3625 ops[2] = const0_rtx;
3628 if (GET_CODE (ops[1]) != REG)
3634 ops[0] = operands[0];
3635 ops[3] = operands[2];
3636 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3639 [(set_attr "length" "4")
3640 (set_attr "type" "load_byte")
3641 (set_attr "pool_range" "1020")]
3644 ;; We used to have an early-clobber on the scratch register here.
3645 ;; However, there's a bug somewhere in reload which means that this
3646 ;; can be partially ignored during spill allocation if the memory
3647 ;; address also needs reloading; this causes an abort later on when
3648 ;; we try to verify the operands. Fortunately, we don't really need
3649 ;; the early-clobber: we can always use operand 0 if operand 2
3650 ;; overlaps the address.
3651 (define_insn "*thumb_extendhisi2_insn_v6"
3652 [(set (match_operand:SI 0 "register_operand" "=l,l")
3653 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3654 (clobber (match_scratch:SI 2 "=X,l"))]
3655 "TARGET_THUMB && arm_arch6"
3661 if (which_alternative == 0)
3662 return \"sxth\\t%0, %1\";
3664 mem = XEXP (operands[1], 0);
3666 /* This code used to try to use 'V', and fix the address only if it was
3667 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3668 range of QImode offsets, and offsettable_address_p does a QImode
3671 if (GET_CODE (mem) == CONST)
3672 mem = XEXP (mem, 0);
3674 if (GET_CODE (mem) == LABEL_REF)
3675 return \"ldr\\t%0, %1\";
3677 if (GET_CODE (mem) == PLUS)
3679 rtx a = XEXP (mem, 0);
3680 rtx b = XEXP (mem, 1);
3682 if (GET_CODE (a) == LABEL_REF
3683 && GET_CODE (b) == CONST_INT)
3684 return \"ldr\\t%0, %1\";
3686 if (GET_CODE (b) == REG)
3687 return \"ldrsh\\t%0, %1\";
3695 ops[2] = const0_rtx;
3698 if (GET_CODE (ops[1]) != REG)
3704 ops[0] = operands[0];
3705 if (reg_mentioned_p (operands[2], ops[1]))
3708 ops[3] = operands[2];
3709 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3712 [(set_attr "length" "2,4")
3713 (set_attr "type" "alu_shift,load_byte")
3714 (set_attr "pool_range" "*,1020")]
3717 (define_expand "extendhisi2_mem"
3718 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3720 (zero_extend:SI (match_dup 7)))
3721 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3722 (set (match_operand:SI 0 "" "")
3723 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3728 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3730 mem1 = gen_rtx_MEM (QImode, addr);
3731 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3732 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3733 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3734 operands[0] = gen_lowpart (SImode, operands[0]);
3736 operands[2] = gen_reg_rtx (SImode);
3737 operands[3] = gen_reg_rtx (SImode);
3738 operands[6] = gen_reg_rtx (SImode);
3741 if (BYTES_BIG_ENDIAN)
3743 operands[4] = operands[2];
3744 operands[5] = operands[3];
3748 operands[4] = operands[3];
3749 operands[5] = operands[2];
3754 (define_insn "*arm_extendhisi2"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3757 "TARGET_ARM && arm_arch4 && !arm_arch6"
3759 [(set_attr "type" "load_byte")
3760 (set_attr "predicable" "yes")
3761 (set_attr "pool_range" "256")
3762 (set_attr "neg_pool_range" "244")]
3765 (define_insn "*arm_extendhisi2_v6"
3766 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3767 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3768 "TARGET_ARM && arm_arch6"
3772 [(set_attr "type" "alu_shift,load_byte")
3773 (set_attr "predicable" "yes")
3774 (set_attr "pool_range" "*,256")
3775 (set_attr "neg_pool_range" "*,244")]
3778 (define_insn "*arm_extendhisi2addsi"
3779 [(set (match_operand:SI 0 "s_register_operand" "=r")
3780 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3781 (match_operand:SI 2 "s_register_operand" "r")))]
3782 "TARGET_ARM && arm_arch6"
3783 "sxtah%?\\t%0, %2, %1"
3787 [(set (match_operand:SI 0 "s_register_operand" "")
3788 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3789 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3790 "TARGET_ARM && (!arm_arch4)"
3791 [(set (match_dup 2) (match_dup 1))
3792 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3794 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3800 [(set (match_operand:SI 0 "s_register_operand" "")
3801 (match_operator:SI 3 "shiftable_operator"
3802 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3803 (match_operand:SI 4 "s_register_operand" "")]))
3804 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3805 "TARGET_ARM && (!arm_arch4)"
3806 [(set (match_dup 2) (match_dup 1))
3809 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3810 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3815 (define_expand "extendqihi2"
3817 (ashift:SI (match_operand:QI 1 "general_operand" "")
3819 (set (match_operand:HI 0 "s_register_operand" "")
3820 (ashiftrt:SI (match_dup 2)
3825 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3827 emit_insn (gen_rtx_SET (VOIDmode,
3829 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3832 if (!s_register_operand (operands[1], QImode))
3833 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3834 operands[0] = gen_lowpart (SImode, operands[0]);
3835 operands[1] = gen_lowpart (SImode, operands[1]);
3836 operands[2] = gen_reg_rtx (SImode);
3840 (define_insn "*extendqihi_insn"
3841 [(set (match_operand:HI 0 "s_register_operand" "=r")
3842 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3843 "TARGET_ARM && arm_arch4"
3845 [(set_attr "type" "load_byte")
3846 (set_attr "predicable" "yes")
3847 (set_attr "pool_range" "256")
3848 (set_attr "neg_pool_range" "244")]
3851 (define_expand "extendqisi2"
3853 (ashift:SI (match_operand:QI 1 "general_operand" "")
3855 (set (match_operand:SI 0 "s_register_operand" "")
3856 (ashiftrt:SI (match_dup 2)
3861 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3863 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3868 if (!s_register_operand (operands[1], QImode))
3869 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3873 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3874 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3878 operands[1] = gen_lowpart (SImode, operands[1]);
3879 operands[2] = gen_reg_rtx (SImode);
3883 (define_insn "*arm_extendqisi"
3884 [(set (match_operand:SI 0 "s_register_operand" "=r")
3885 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3886 "TARGET_ARM && arm_arch4 && !arm_arch6"
3888 [(set_attr "type" "load_byte")
3889 (set_attr "predicable" "yes")
3890 (set_attr "pool_range" "256")
3891 (set_attr "neg_pool_range" "244")]
3894 (define_insn "*arm_extendqisi_v6"
3895 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3896 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3897 "TARGET_ARM && arm_arch6"
3901 [(set_attr "type" "alu_shift,load_byte")
3902 (set_attr "predicable" "yes")
3903 (set_attr "pool_range" "*,256")
3904 (set_attr "neg_pool_range" "*,244")]
3907 (define_insn "*arm_extendqisi2addsi"
3908 [(set (match_operand:SI 0 "s_register_operand" "=r")
3909 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3910 (match_operand:SI 2 "s_register_operand" "r")))]
3911 "TARGET_ARM && arm_arch6"
3912 "sxtab%?\\t%0, %2, %1"
3913 [(set_attr "type" "alu_shift")
3914 (set_attr "predicable" "yes")]
3917 (define_insn "*thumb_extendqisi2"
3918 [(set (match_operand:SI 0 "register_operand" "=l,l")
3919 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3920 "TARGET_THUMB && !arm_arch6"
3924 rtx mem = XEXP (operands[1], 0);
3926 if (GET_CODE (mem) == CONST)
3927 mem = XEXP (mem, 0);
3929 if (GET_CODE (mem) == LABEL_REF)
3930 return \"ldr\\t%0, %1\";
3932 if (GET_CODE (mem) == PLUS
3933 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934 return \"ldr\\t%0, %1\";
3936 if (which_alternative == 0)
3937 return \"ldrsb\\t%0, %1\";
3939 ops[0] = operands[0];
3941 if (GET_CODE (mem) == PLUS)
3943 rtx a = XEXP (mem, 0);
3944 rtx b = XEXP (mem, 1);
3949 if (GET_CODE (a) == REG)
3951 if (GET_CODE (b) == REG)
3952 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953 else if (REGNO (a) == REGNO (ops[0]))
3955 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3956 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3957 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3960 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3962 else if (GET_CODE (b) != REG)
3966 if (REGNO (b) == REGNO (ops[0]))
3968 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3969 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3973 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3976 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3978 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3979 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3980 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3985 ops[2] = const0_rtx;
3987 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991 [(set_attr "length" "2,6")
3992 (set_attr "type" "load_byte,load_byte")
3993 (set_attr "pool_range" "32,32")]
3996 (define_insn "*thumb_extendqisi2_v6"
3997 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3998 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3999 "TARGET_THUMB && arm_arch6"
4005 if (which_alternative == 0)
4006 return \"sxtb\\t%0, %1\";
4008 mem = XEXP (operands[1], 0);
4010 if (GET_CODE (mem) == CONST)
4011 mem = XEXP (mem, 0);
4013 if (GET_CODE (mem) == LABEL_REF)
4014 return \"ldr\\t%0, %1\";
4016 if (GET_CODE (mem) == PLUS
4017 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018 return \"ldr\\t%0, %1\";
4020 if (which_alternative == 0)
4021 return \"ldrsb\\t%0, %1\";
4023 ops[0] = operands[0];
4025 if (GET_CODE (mem) == PLUS)
4027 rtx a = XEXP (mem, 0);
4028 rtx b = XEXP (mem, 1);
4033 if (GET_CODE (a) == REG)
4035 if (GET_CODE (b) == REG)
4036 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037 else if (REGNO (a) == REGNO (ops[0]))
4039 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4043 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4045 else if (GET_CODE (b) != REG)
4049 if (REGNO (b) == REGNO (ops[0]))
4051 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4055 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4058 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4060 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4066 ops[2] = const0_rtx;
4068 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4072 [(set_attr "length" "2,2,4")
4073 (set_attr "type" "alu_shift,load_byte,load_byte")
4074 (set_attr "pool_range" "*,32,32")]
4077 (define_expand "extendsfdf2"
4078 [(set (match_operand:DF 0 "s_register_operand" "")
4079 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4080 "TARGET_ARM && TARGET_HARD_FLOAT"
4084 ;; Move insns (including loads and stores)
4086 ;; XXX Just some ideas about movti.
4087 ;; I don't think these are a good idea on the arm, there just aren't enough
4089 ;;(define_expand "loadti"
4090 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4091 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4094 ;;(define_expand "storeti"
4095 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4096 ;; (match_operand:TI 1 "s_register_operand" ""))]
4099 ;;(define_expand "movti"
4100 ;; [(set (match_operand:TI 0 "general_operand" "")
4101 ;; (match_operand:TI 1 "general_operand" ""))]
4107 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4108 ;; operands[1] = copy_to_reg (operands[1]);
4109 ;; if (GET_CODE (operands[0]) == MEM)
4110 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4111 ;; else if (GET_CODE (operands[1]) == MEM)
4112 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4116 ;; emit_insn (insn);
4120 ;; Recognize garbage generated above.
4123 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4128 ;; register mem = (which_alternative < 3);
4129 ;; register const char *template;
4131 ;; operands[mem] = XEXP (operands[mem], 0);
4132 ;; switch (which_alternative)
4134 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4135 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4136 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4137 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4138 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4139 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4141 ;; output_asm_insn (template, operands);
4145 (define_expand "movdi"
4146 [(set (match_operand:DI 0 "general_operand" "")
4147 (match_operand:DI 1 "general_operand" ""))]
4152 if (!no_new_pseudos)
4154 if (GET_CODE (operands[0]) != REG)
4155 operands[1] = force_reg (DImode, operands[1]);
4161 (define_insn "*arm_movdi"
4162 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4163 (match_operand:DI 1 "di_operand" "rIKDa,Db,Dc,mi,r"))]
4165 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4168 return (output_move_double (operands));
4170 [(set_attr "length" "8,12,16,8,8")
4171 (set_attr "type" "*,*,*,load2,store2")
4172 (set_attr "pool_range" "*,*,*,1020,*")
4173 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4176 ;; We can't actually do base+index doubleword loads if the index and
4177 ;; destination overlap. Split here so that we at least have chance to
4180 [(set (match_operand:DI 0 "s_register_operand" "")
4181 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4182 (match_operand:SI 2 "s_register_operand" ""))))]
4184 && reg_overlap_mentioned_p (operands[0], operands[1])
4185 && reg_overlap_mentioned_p (operands[0], operands[2])"
4187 (plus:SI (match_dup 1)
4190 (mem:DI (match_dup 4)))]
4192 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4196 ;;; ??? This should have alternatives for constants.
4197 ;;; ??? This was originally identical to the movdf_insn pattern.
4198 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4199 ;;; thumb_reorg with a memory reference.
4200 (define_insn "*thumb_movdi_insn"
4201 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4202 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4204 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4205 && ( register_operand (operands[0], DImode)
4206 || register_operand (operands[1], DImode))"
4209 switch (which_alternative)
4213 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4215 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4217 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4219 operands[1] = GEN_INT (- INTVAL (operands[1]));
4220 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4222 return \"ldmia\\t%1, {%0, %H0}\";
4224 return \"stmia\\t%0, {%1, %H1}\";
4226 return thumb_load_double_from_address (operands);
4228 operands[2] = gen_rtx_MEM (SImode,
4229 plus_constant (XEXP (operands[0], 0), 4));
4230 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4233 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4234 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4235 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4238 [(set_attr "length" "4,4,6,2,2,6,4,4")
4239 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4240 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4243 (define_expand "movsi"
4244 [(set (match_operand:SI 0 "general_operand" "")
4245 (match_operand:SI 1 "general_operand" ""))]
4250 /* Everything except mem = const or mem = mem can be done easily. */
4251 if (GET_CODE (operands[0]) == MEM)
4252 operands[1] = force_reg (SImode, operands[1]);
4253 if (arm_general_register_operand (operands[0], SImode)
4254 && GET_CODE (operands[1]) == CONST_INT
4255 && !(const_ok_for_arm (INTVAL (operands[1]))
4256 || const_ok_for_arm (~INTVAL (operands[1]))))
4258 arm_split_constant (SET, SImode, NULL_RTX,
4259 INTVAL (operands[1]), operands[0], NULL_RTX,
4260 optimize && !no_new_pseudos);
4264 else /* TARGET_THUMB.... */
4266 if (!no_new_pseudos)
4268 if (GET_CODE (operands[0]) != REG)
4269 operands[1] = force_reg (SImode, operands[1]);
4274 && (CONSTANT_P (operands[1])
4275 || symbol_mentioned_p (operands[1])
4276 || label_mentioned_p (operands[1])))
4277 operands[1] = legitimize_pic_address (operands[1], SImode,
4278 (no_new_pseudos ? operands[0] : 0));
4282 (define_insn "*arm_movsi_insn"
4283 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4284 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4285 "TARGET_ARM && ! TARGET_IWMMXT
4286 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4287 && ( register_operand (operands[0], SImode)
4288 || register_operand (operands[1], SImode))"
4294 [(set_attr "type" "*,*,load1,store1")
4295 (set_attr "predicable" "yes")
4296 (set_attr "pool_range" "*,*,4096,*")
4297 (set_attr "neg_pool_range" "*,*,4084,*")]
4301 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4302 (match_operand:SI 1 "const_int_operand" ""))]
4304 && (!(const_ok_for_arm (INTVAL (operands[1]))
4305 || const_ok_for_arm (~INTVAL (operands[1]))))"
4306 [(clobber (const_int 0))]
4308 arm_split_constant (SET, SImode, NULL_RTX,
4309 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4314 (define_insn "*thumb_movsi_insn"
4315 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4316 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4318 && ( register_operand (operands[0], SImode)
4319 || register_operand (operands[1], SImode))"
4330 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4331 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4332 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4336 [(set (match_operand:SI 0 "register_operand" "")
4337 (match_operand:SI 1 "const_int_operand" ""))]
4338 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4339 [(set (match_dup 0) (match_dup 1))
4340 (set (match_dup 0) (neg:SI (match_dup 0)))]
4341 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4345 [(set (match_operand:SI 0 "register_operand" "")
4346 (match_operand:SI 1 "const_int_operand" ""))]
4347 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4348 [(set (match_dup 0) (match_dup 1))
4349 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4352 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4353 unsigned HOST_WIDE_INT mask = 0xff;
4356 for (i = 0; i < 25; i++)
4357 if ((val & (mask << i)) == val)
4360 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4364 operands[1] = GEN_INT (val >> i);
4365 operands[2] = GEN_INT (i);
4369 ;; When generating pic, we need to load the symbol offset into a register.
4370 ;; So that the optimizer does not confuse this with a normal symbol load
4371 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4372 ;; since that is the only type of relocation we can use.
4374 ;; The rather odd constraints on the following are to force reload to leave
4375 ;; the insn alone, and to force the minipool generation pass to then move
4376 ;; the GOT symbol to memory.
4378 (define_insn "pic_load_addr_arm"
4379 [(set (match_operand:SI 0 "s_register_operand" "=r")
4380 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4381 "TARGET_ARM && flag_pic"
4383 [(set_attr "type" "load1")
4384 (set (attr "pool_range") (const_int 4096))
4385 (set (attr "neg_pool_range") (const_int 4084))]
4388 (define_insn "pic_load_addr_thumb"
4389 [(set (match_operand:SI 0 "s_register_operand" "=l")
4390 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4391 "TARGET_THUMB && flag_pic"
4393 [(set_attr "type" "load1")
4394 (set (attr "pool_range") (const_int 1024))]
4397 ;; This variant is used for AOF assembly, since it needs to mention the
4398 ;; pic register in the rtl.
4399 (define_expand "pic_load_addr_based"
4400 [(set (match_operand:SI 0 "s_register_operand" "")
4401 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4402 "TARGET_ARM && flag_pic"
4403 "operands[2] = pic_offset_table_rtx;"
4406 (define_insn "*pic_load_addr_based_insn"
4407 [(set (match_operand:SI 0 "s_register_operand" "=r")
4408 (unspec:SI [(match_operand 1 "" "")
4409 (match_operand 2 "s_register_operand" "r")]
4411 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4413 #ifdef AOF_ASSEMBLER
4414 operands[1] = aof_pic_entry (operands[1]);
4416 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4419 [(set_attr "type" "load1")
4420 (set (attr "pool_range")
4421 (if_then_else (eq_attr "is_thumb" "yes")
4424 (set (attr "neg_pool_range")
4425 (if_then_else (eq_attr "is_thumb" "yes")
4430 (define_insn "pic_add_dot_plus_four"
4431 [(set (match_operand:SI 0 "register_operand" "+r")
4432 (unspec:SI [(plus:SI (match_dup 0)
4433 (const (plus:SI (pc) (const_int 4))))]
4435 (use (label_ref (match_operand 1 "" "")))]
4436 "TARGET_THUMB && flag_pic"
4438 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4439 CODE_LABEL_NUMBER (operands[1]));
4440 return \"add\\t%0, %|pc\";
4442 [(set_attr "length" "2")]
4445 (define_insn "pic_add_dot_plus_eight"
4446 [(set (match_operand:SI 0 "register_operand" "+r")
4447 (unspec:SI [(plus:SI (match_dup 0)
4448 (const (plus:SI (pc) (const_int 8))))]
4450 (use (label_ref (match_operand 1 "" "")))]
4451 "TARGET_ARM && flag_pic"
4453 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4454 CODE_LABEL_NUMBER (operands[1]));
4455 return \"add%?\\t%0, %|pc, %0\";
4457 [(set_attr "predicable" "yes")]
4460 (define_expand "builtin_setjmp_receiver"
4461 [(label_ref (match_operand 0 "" ""))]
4465 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4467 arm_load_pic_register (3);
4471 ;; If copying one reg to another we can set the condition codes according to
4472 ;; its value. Such a move is common after a return from subroutine and the
4473 ;; result is being tested against zero.
4475 (define_insn "*movsi_compare0"
4476 [(set (reg:CC CC_REGNUM)
4477 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4479 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4484 sub%?s\\t%0, %1, #0"
4485 [(set_attr "conds" "set")]
4488 ;; Subroutine to store a half word from a register into memory.
4489 ;; Operand 0 is the source register (HImode)
4490 ;; Operand 1 is the destination address in a register (SImode)
4492 ;; In both this routine and the next, we must be careful not to spill
4493 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4494 ;; can generate unrecognizable rtl.
4496 (define_expand "storehi"
4497 [;; store the low byte
4498 (set (match_operand 1 "" "") (match_dup 3))
4499 ;; extract the high byte
4501 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4502 ;; store the high byte
4503 (set (match_dup 4) (match_dup 5))]
4507 rtx op1 = operands[1];
4508 rtx addr = XEXP (op1, 0);
4509 enum rtx_code code = GET_CODE (addr);
4511 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4513 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4515 operands[4] = adjust_address (op1, QImode, 1);
4516 operands[1] = adjust_address (operands[1], QImode, 0);
4517 operands[3] = gen_lowpart (QImode, operands[0]);
4518 operands[0] = gen_lowpart (SImode, operands[0]);
4519 operands[2] = gen_reg_rtx (SImode);
4520 operands[5] = gen_lowpart (QImode, operands[2]);
4524 (define_expand "storehi_bigend"
4525 [(set (match_dup 4) (match_dup 3))
4527 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4528 (set (match_operand 1 "" "") (match_dup 5))]
4532 rtx op1 = operands[1];
4533 rtx addr = XEXP (op1, 0);
4534 enum rtx_code code = GET_CODE (addr);
4536 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4538 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4540 operands[4] = adjust_address (op1, QImode, 1);
4541 operands[1] = adjust_address (operands[1], QImode, 0);
4542 operands[3] = gen_lowpart (QImode, operands[0]);
4543 operands[0] = gen_lowpart (SImode, operands[0]);
4544 operands[2] = gen_reg_rtx (SImode);
4545 operands[5] = gen_lowpart (QImode, operands[2]);
4549 ;; Subroutine to store a half word integer constant into memory.
4550 (define_expand "storeinthi"
4551 [(set (match_operand 0 "" "")
4552 (match_operand 1 "" ""))
4553 (set (match_dup 3) (match_dup 2))]
4557 HOST_WIDE_INT value = INTVAL (operands[1]);
4558 rtx addr = XEXP (operands[0], 0);
4559 rtx op0 = operands[0];
4560 enum rtx_code code = GET_CODE (addr);
4562 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4564 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4566 operands[1] = gen_reg_rtx (SImode);
4567 if (BYTES_BIG_ENDIAN)
4569 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4570 if ((value & 255) == ((value >> 8) & 255))
4571 operands[2] = operands[1];
4574 operands[2] = gen_reg_rtx (SImode);
4575 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4580 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4581 if ((value & 255) == ((value >> 8) & 255))
4582 operands[2] = operands[1];
4585 operands[2] = gen_reg_rtx (SImode);
4586 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4590 operands[3] = adjust_address (op0, QImode, 1);
4591 operands[0] = adjust_address (operands[0], QImode, 0);
4592 operands[2] = gen_lowpart (QImode, operands[2]);
4593 operands[1] = gen_lowpart (QImode, operands[1]);
4597 (define_expand "storehi_single_op"
4598 [(set (match_operand:HI 0 "memory_operand" "")
4599 (match_operand:HI 1 "general_operand" ""))]
4600 "TARGET_ARM && arm_arch4"
4602 if (!s_register_operand (operands[1], HImode))
4603 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4607 (define_expand "movhi"
4608 [(set (match_operand:HI 0 "general_operand" "")
4609 (match_operand:HI 1 "general_operand" ""))]
4614 if (!no_new_pseudos)
4616 if (GET_CODE (operands[0]) == MEM)
4620 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4623 if (GET_CODE (operands[1]) == CONST_INT)
4624 emit_insn (gen_storeinthi (operands[0], operands[1]));
4627 if (GET_CODE (operands[1]) == MEM)
4628 operands[1] = force_reg (HImode, operands[1]);
4629 if (BYTES_BIG_ENDIAN)
4630 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4632 emit_insn (gen_storehi (operands[1], operands[0]));
4636 /* Sign extend a constant, and keep it in an SImode reg. */
4637 else if (GET_CODE (operands[1]) == CONST_INT)
4639 rtx reg = gen_reg_rtx (SImode);
4640 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4642 /* If the constant is already valid, leave it alone. */
4643 if (!const_ok_for_arm (val))
4645 /* If setting all the top bits will make the constant
4646 loadable in a single instruction, then set them.
4647 Otherwise, sign extend the number. */
4649 if (const_ok_for_arm (~(val | ~0xffff)))
4651 else if (val & 0x8000)
4655 emit_insn (gen_movsi (reg, GEN_INT (val)));
4656 operands[1] = gen_lowpart (HImode, reg);
4658 else if (arm_arch4 && optimize && !no_new_pseudos
4659 && GET_CODE (operands[1]) == MEM)
4661 rtx reg = gen_reg_rtx (SImode);
4663 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4664 operands[1] = gen_lowpart (HImode, reg);
4666 else if (!arm_arch4)
4668 if (GET_CODE (operands[1]) == MEM)
4671 rtx offset = const0_rtx;
4672 rtx reg = gen_reg_rtx (SImode);
4674 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4675 || (GET_CODE (base) == PLUS
4676 && (GET_CODE (offset = XEXP (base, 1))
4678 && ((INTVAL(offset) & 1) != 1)
4679 && GET_CODE (base = XEXP (base, 0)) == REG))
4680 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4682 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4685 new = gen_rtx_MEM (SImode,
4686 plus_constant (base, new_offset));
4687 MEM_COPY_ATTRIBUTES (new, operands[1]);
4688 emit_insn (gen_movsi (reg, new));
4689 if (((INTVAL (offset) & 2) != 0)
4690 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4692 rtx reg2 = gen_reg_rtx (SImode);
4694 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4699 emit_insn (gen_movhi_bytes (reg, operands[1]));
4701 operands[1] = gen_lowpart (HImode, reg);
4705 /* Handle loading a large integer during reload. */
4706 else if (GET_CODE (operands[1]) == CONST_INT
4707 && !const_ok_for_arm (INTVAL (operands[1]))
4708 && !const_ok_for_arm (~INTVAL (operands[1])))
4710 /* Writing a constant to memory needs a scratch, which should
4711 be handled with SECONDARY_RELOADs. */
4712 if (GET_CODE (operands[0]) != REG)
4715 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4716 emit_insn (gen_movsi (operands[0], operands[1]));
4720 else /* TARGET_THUMB */
4722 if (!no_new_pseudos)
4724 if (GET_CODE (operands[0]) != REG)
4725 operands[1] = force_reg (HImode, operands[1]);
4727 /* ??? We shouldn't really get invalid addresses here, but this can
4728 happen if we are passed a SP (never OK for HImode/QImode) or
4729 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4730 HImode/QImode) relative address. */
4731 /* ??? This should perhaps be fixed elsewhere, for instance, in
4732 fixup_stack_1, by checking for other kinds of invalid addresses,
4733 e.g. a bare reference to a virtual register. This may confuse the
4734 alpha though, which must handle this case differently. */
4735 if (GET_CODE (operands[0]) == MEM
4736 && !memory_address_p (GET_MODE (operands[0]),
4737 XEXP (operands[0], 0)))
4739 = replace_equiv_address (operands[0],
4740 copy_to_reg (XEXP (operands[0], 0)));
4742 if (GET_CODE (operands[1]) == MEM
4743 && !memory_address_p (GET_MODE (operands[1]),
4744 XEXP (operands[1], 0)))
4746 = replace_equiv_address (operands[1],
4747 copy_to_reg (XEXP (operands[1], 0)));
4749 /* Handle loading a large integer during reload. */
4750 else if (GET_CODE (operands[1]) == CONST_INT
4751 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4753 /* Writing a constant to memory needs a scratch, which should
4754 be handled with SECONDARY_RELOADs. */
4755 if (GET_CODE (operands[0]) != REG)
4758 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4759 emit_insn (gen_movsi (operands[0], operands[1]));
4766 (define_insn "*thumb_movhi_insn"
4767 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4768 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4770 && ( register_operand (operands[0], HImode)
4771 || register_operand (operands[1], HImode))"
4773 switch (which_alternative)
4775 case 0: return \"add %0, %1, #0\";
4776 case 2: return \"strh %1, %0\";
4777 case 3: return \"mov %0, %1\";
4778 case 4: return \"mov %0, %1\";
4779 case 5: return \"mov %0, %1\";
4782 /* The stack pointer can end up being taken as an index register.
4783 Catch this case here and deal with it. */
4784 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4785 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4786 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4789 ops[0] = operands[0];
4790 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4792 output_asm_insn (\"mov %0, %1\", ops);
4794 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4797 return \"ldrh %0, %1\";
4799 [(set_attr "length" "2,4,2,2,2,2")
4800 (set_attr "type" "*,load1,store1,*,*,*")]
4804 (define_expand "movhi_bytes"
4805 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4807 (zero_extend:SI (match_dup 6)))
4808 (set (match_operand:SI 0 "" "")
4809 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4814 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4816 mem1 = gen_rtx_MEM (QImode, addr);
4817 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4818 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4819 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4820 operands[0] = gen_lowpart (SImode, operands[0]);
4822 operands[2] = gen_reg_rtx (SImode);
4823 operands[3] = gen_reg_rtx (SImode);
4826 if (BYTES_BIG_ENDIAN)
4828 operands[4] = operands[2];
4829 operands[5] = operands[3];
4833 operands[4] = operands[3];
4834 operands[5] = operands[2];
4839 (define_expand "movhi_bigend"
4841 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4844 (ashiftrt:SI (match_dup 2) (const_int 16)))
4845 (set (match_operand:HI 0 "s_register_operand" "")
4849 operands[2] = gen_reg_rtx (SImode);
4850 operands[3] = gen_reg_rtx (SImode);
4851 operands[4] = gen_lowpart (HImode, operands[3]);
4855 ;; Pattern to recognize insn generated default case above
4856 (define_insn "*movhi_insn_arch4"
4857 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4858 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4861 && (GET_CODE (operands[1]) != CONST_INT
4862 || const_ok_for_arm (INTVAL (operands[1]))
4863 || const_ok_for_arm (~INTVAL (operands[1])))"
4865 mov%?\\t%0, %1\\t%@ movhi
4866 mvn%?\\t%0, #%B1\\t%@ movhi
4867 str%?h\\t%1, %0\\t%@ movhi
4868 ldr%?h\\t%0, %1\\t%@ movhi"
4869 [(set_attr "type" "*,*,store1,load1")
4870 (set_attr "predicable" "yes")
4871 (set_attr "pool_range" "*,*,*,256")
4872 (set_attr "neg_pool_range" "*,*,*,244")]
4875 (define_insn "*movhi_bytes"
4876 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4877 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4880 mov%?\\t%0, %1\\t%@ movhi
4881 mvn%?\\t%0, #%B1\\t%@ movhi"
4882 [(set_attr "predicable" "yes")]
4885 (define_insn "thumb_movhi_clobber"
4886 [(set (match_operand:HI 0 "memory_operand" "=m")
4887 (match_operand:HI 1 "register_operand" "l"))
4888 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4894 ;; We use a DImode scratch because we may occasionally need an additional
4895 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4896 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4897 (define_expand "reload_outhi"
4898 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4899 (match_operand:HI 1 "s_register_operand" "r")
4900 (match_operand:DI 2 "s_register_operand" "=&l")])]
4903 arm_reload_out_hi (operands);
4905 thumb_reload_out_hi (operands);
4910 (define_expand "reload_inhi"
4911 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4912 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4913 (match_operand:DI 2 "s_register_operand" "=&r")])]
4917 arm_reload_in_hi (operands);
4919 thumb_reload_out_hi (operands);
4923 (define_expand "movqi"
4924 [(set (match_operand:QI 0 "general_operand" "")
4925 (match_operand:QI 1 "general_operand" ""))]
4930 /* Everything except mem = const or mem = mem can be done easily */
4932 if (!no_new_pseudos)
4934 if (GET_CODE (operands[1]) == CONST_INT)
4936 rtx reg = gen_reg_rtx (SImode);
4938 emit_insn (gen_movsi (reg, operands[1]));
4939 operands[1] = gen_lowpart (QImode, reg);
4941 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4943 rtx reg = gen_reg_rtx (SImode);
4945 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4946 operands[1] = gen_lowpart (QImode, reg);
4948 if (GET_CODE (operands[0]) == MEM)
4949 operands[1] = force_reg (QImode, operands[1]);
4952 else /* TARGET_THUMB */
4954 if (!no_new_pseudos)
4956 if (GET_CODE (operands[0]) != REG)
4957 operands[1] = force_reg (QImode, operands[1]);
4959 /* ??? We shouldn't really get invalid addresses here, but this can
4960 happen if we are passed a SP (never OK for HImode/QImode) or
4961 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4962 HImode/QImode) relative address. */
4963 /* ??? This should perhaps be fixed elsewhere, for instance, in
4964 fixup_stack_1, by checking for other kinds of invalid addresses,
4965 e.g. a bare reference to a virtual register. This may confuse the
4966 alpha though, which must handle this case differently. */
4967 if (GET_CODE (operands[0]) == MEM
4968 && !memory_address_p (GET_MODE (operands[0]),
4969 XEXP (operands[0], 0)))
4971 = replace_equiv_address (operands[0],
4972 copy_to_reg (XEXP (operands[0], 0)));
4973 if (GET_CODE (operands[1]) == MEM
4974 && !memory_address_p (GET_MODE (operands[1]),
4975 XEXP (operands[1], 0)))
4977 = replace_equiv_address (operands[1],
4978 copy_to_reg (XEXP (operands[1], 0)));
4980 /* Handle loading a large integer during reload. */
4981 else if (GET_CODE (operands[1]) == CONST_INT
4982 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4984 /* Writing a constant to memory needs a scratch, which should
4985 be handled with SECONDARY_RELOADs. */
4986 if (GET_CODE (operands[0]) != REG)
4989 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4990 emit_insn (gen_movsi (operands[0], operands[1]));
4998 (define_insn "*arm_movqi_insn"
4999 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5000 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5002 && ( register_operand (operands[0], QImode)
5003 || register_operand (operands[1], QImode))"
5009 [(set_attr "type" "*,*,load1,store1")
5010 (set_attr "predicable" "yes")]
5013 (define_insn "*thumb_movqi_insn"
5014 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5015 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5017 && ( register_operand (operands[0], QImode)
5018 || register_operand (operands[1], QImode))"
5026 [(set_attr "length" "2")
5027 (set_attr "type" "*,load1,store1,*,*,*")
5028 (set_attr "pool_range" "*,32,*,*,*,*")]
5031 (define_expand "movsf"
5032 [(set (match_operand:SF 0 "general_operand" "")
5033 (match_operand:SF 1 "general_operand" ""))]
5038 if (GET_CODE (operands[0]) == MEM)
5039 operands[1] = force_reg (SFmode, operands[1]);
5041 else /* TARGET_THUMB */
5043 if (!no_new_pseudos)
5045 if (GET_CODE (operands[0]) != REG)
5046 operands[1] = force_reg (SFmode, operands[1]);
5053 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5054 (match_operand:SF 1 "immediate_operand" ""))]
5056 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5058 && GET_CODE (operands[1]) == CONST_DOUBLE"
5059 [(set (match_dup 2) (match_dup 3))]
5061 operands[2] = gen_lowpart (SImode, operands[0]);
5062 operands[3] = gen_lowpart (SImode, operands[1]);
5063 if (operands[2] == 0 || operands[3] == 0)
5068 (define_insn "*arm_movsf_soft_insn"
5069 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5070 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5072 && TARGET_SOFT_FLOAT
5073 && (GET_CODE (operands[0]) != MEM
5074 || register_operand (operands[1], SFmode))"
5077 ldr%?\\t%0, %1\\t%@ float
5078 str%?\\t%1, %0\\t%@ float"
5079 [(set_attr "length" "4,4,4")
5080 (set_attr "predicable" "yes")
5081 (set_attr "type" "*,load1,store1")
5082 (set_attr "pool_range" "*,4096,*")
5083 (set_attr "neg_pool_range" "*,4084,*")]
5086 ;;; ??? This should have alternatives for constants.
5087 (define_insn "*thumb_movsf_insn"
5088 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5089 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5091 && ( register_operand (operands[0], SFmode)
5092 || register_operand (operands[1], SFmode))"
5101 [(set_attr "length" "2")
5102 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5103 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5106 (define_expand "movdf"
5107 [(set (match_operand:DF 0 "general_operand" "")
5108 (match_operand:DF 1 "general_operand" ""))]
5113 if (GET_CODE (operands[0]) == MEM)
5114 operands[1] = force_reg (DFmode, operands[1]);
5116 else /* TARGET_THUMB */
5118 if (!no_new_pseudos)
5120 if (GET_CODE (operands[0]) != REG)
5121 operands[1] = force_reg (DFmode, operands[1]);
5127 ;; Reloading a df mode value stored in integer regs to memory can require a
5129 (define_expand "reload_outdf"
5130 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5131 (match_operand:DF 1 "s_register_operand" "r")
5132 (match_operand:SI 2 "s_register_operand" "=&r")]
5136 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5139 operands[2] = XEXP (operands[0], 0);
5140 else if (code == POST_INC || code == PRE_DEC)
5142 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5143 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5144 emit_insn (gen_movdi (operands[0], operands[1]));
5147 else if (code == PRE_INC)
5149 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5151 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5154 else if (code == POST_DEC)
5155 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5157 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5158 XEXP (XEXP (operands[0], 0), 1)));
5160 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5163 if (code == POST_DEC)
5164 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5170 (define_insn "*movdf_soft_insn"
5171 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5172 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5173 "TARGET_ARM && TARGET_SOFT_FLOAT
5175 "* return output_move_double (operands);"
5176 [(set_attr "length" "8,12,16,8,8")
5177 (set_attr "type" "*,*,*,load2,store2")
5178 (set_attr "pool_range" "1020")
5179 (set_attr "neg_pool_range" "1008")]
5182 ;;; ??? This should have alternatives for constants.
5183 ;;; ??? This was originally identical to the movdi_insn pattern.
5184 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5185 ;;; thumb_reorg with a memory reference.
5186 (define_insn "*thumb_movdf_insn"
5187 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5188 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5190 && ( register_operand (operands[0], DFmode)
5191 || register_operand (operands[1], DFmode))"
5193 switch (which_alternative)
5197 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5198 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5199 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5201 return \"ldmia\\t%1, {%0, %H0}\";
5203 return \"stmia\\t%0, {%1, %H1}\";
5205 return thumb_load_double_from_address (operands);
5207 operands[2] = gen_rtx_MEM (SImode,
5208 plus_constant (XEXP (operands[0], 0), 4));
5209 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5212 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5213 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5214 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5217 [(set_attr "length" "4,2,2,6,4,4")
5218 (set_attr "type" "*,load2,store2,load2,store2,*")
5219 (set_attr "pool_range" "*,*,*,1020,*,*")]
5222 (define_expand "movxf"
5223 [(set (match_operand:XF 0 "general_operand" "")
5224 (match_operand:XF 1 "general_operand" ""))]
5225 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5227 if (GET_CODE (operands[0]) == MEM)
5228 operands[1] = force_reg (XFmode, operands[1]);
5233 (define_expand "movv2si"
5234 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5235 (match_operand:V2SI 1 "general_operand" ""))]
5236 "TARGET_REALLY_IWMMXT"
5240 (define_expand "movv4hi"
5241 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5242 (match_operand:V4HI 1 "general_operand" ""))]
5243 "TARGET_REALLY_IWMMXT"
5247 (define_expand "movv8qi"
5248 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5249 (match_operand:V8QI 1 "general_operand" ""))]
5250 "TARGET_REALLY_IWMMXT"
5255 ;; load- and store-multiple insns
5256 ;; The arm can load/store any set of registers, provided that they are in
5257 ;; ascending order; but that is beyond GCC so stick with what it knows.
5259 (define_expand "load_multiple"
5260 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5261 (match_operand:SI 1 "" ""))
5262 (use (match_operand:SI 2 "" ""))])]
5265 HOST_WIDE_INT offset = 0;
5267 /* Support only fixed point registers. */
5268 if (GET_CODE (operands[2]) != CONST_INT
5269 || INTVAL (operands[2]) > 14
5270 || INTVAL (operands[2]) < 2
5271 || GET_CODE (operands[1]) != MEM
5272 || GET_CODE (operands[0]) != REG
5273 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5274 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5278 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5279 force_reg (SImode, XEXP (operands[1], 0)),
5280 TRUE, FALSE, operands[1], &offset);
5283 ;; Load multiple with write-back
5285 (define_insn "*ldmsi_postinc4"
5286 [(match_parallel 0 "load_multiple_operation"
5287 [(set (match_operand:SI 1 "s_register_operand" "=r")
5288 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5290 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5291 (mem:SI (match_dup 2)))
5292 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5293 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5294 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5295 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5296 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5297 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5298 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5299 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5300 [(set_attr "type" "load4")
5301 (set_attr "predicable" "yes")]
5304 (define_insn "*ldmsi_postinc4_thumb"
5305 [(match_parallel 0 "load_multiple_operation"
5306 [(set (match_operand:SI 1 "s_register_operand" "=l")
5307 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5309 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5310 (mem:SI (match_dup 2)))
5311 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5312 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5313 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5314 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5315 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5316 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5317 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5318 "ldmia\\t%1!, {%3, %4, %5, %6}"
5319 [(set_attr "type" "load4")]
5322 (define_insn "*ldmsi_postinc3"
5323 [(match_parallel 0 "load_multiple_operation"
5324 [(set (match_operand:SI 1 "s_register_operand" "=r")
5325 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5327 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328 (mem:SI (match_dup 2)))
5329 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5330 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5331 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5332 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5333 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5334 "ldm%?ia\\t%1!, {%3, %4, %5}"
5335 [(set_attr "type" "load3")
5336 (set_attr "predicable" "yes")]
5339 (define_insn "*ldmsi_postinc2"
5340 [(match_parallel 0 "load_multiple_operation"
5341 [(set (match_operand:SI 1 "s_register_operand" "=r")
5342 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5344 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5345 (mem:SI (match_dup 2)))
5346 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5347 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5348 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5349 "ldm%?ia\\t%1!, {%3, %4}"
5350 [(set_attr "type" "load2")
5351 (set_attr "predicable" "yes")]
5354 ;; Ordinary load multiple
5356 (define_insn "*ldmsi4"
5357 [(match_parallel 0 "load_multiple_operation"
5358 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5359 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5360 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5361 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5362 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5363 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5364 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5365 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5366 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5367 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5368 [(set_attr "type" "load4")
5369 (set_attr "predicable" "yes")]
5372 (define_insn "*ldmsi3"
5373 [(match_parallel 0 "load_multiple_operation"
5374 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5375 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5376 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5377 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5378 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5379 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5380 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5381 "ldm%?ia\\t%1, {%2, %3, %4}"
5382 [(set_attr "type" "load3")
5383 (set_attr "predicable" "yes")]
5386 (define_insn "*ldmsi2"
5387 [(match_parallel 0 "load_multiple_operation"
5388 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5389 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5390 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5391 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5392 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5393 "ldm%?ia\\t%1, {%2, %3}"
5394 [(set_attr "type" "load2")
5395 (set_attr "predicable" "yes")]
5398 (define_expand "store_multiple"
5399 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5400 (match_operand:SI 1 "" ""))
5401 (use (match_operand:SI 2 "" ""))])]
5404 HOST_WIDE_INT offset = 0;
5406 /* Support only fixed point registers. */
5407 if (GET_CODE (operands[2]) != CONST_INT
5408 || INTVAL (operands[2]) > 14
5409 || INTVAL (operands[2]) < 2
5410 || GET_CODE (operands[1]) != REG
5411 || GET_CODE (operands[0]) != MEM
5412 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5413 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5417 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5418 force_reg (SImode, XEXP (operands[0], 0)),
5419 TRUE, FALSE, operands[0], &offset);
5422 ;; Store multiple with write-back
5424 (define_insn "*stmsi_postinc4"
5425 [(match_parallel 0 "store_multiple_operation"
5426 [(set (match_operand:SI 1 "s_register_operand" "=r")
5427 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5429 (set (mem:SI (match_dup 2))
5430 (match_operand:SI 3 "arm_hard_register_operand" ""))
5431 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5432 (match_operand:SI 4 "arm_hard_register_operand" ""))
5433 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5434 (match_operand:SI 5 "arm_hard_register_operand" ""))
5435 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5436 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5437 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5438 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5439 [(set_attr "predicable" "yes")
5440 (set_attr "type" "store4")]
5443 (define_insn "*stmsi_postinc4_thumb"
5444 [(match_parallel 0 "store_multiple_operation"
5445 [(set (match_operand:SI 1 "s_register_operand" "=l")
5446 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5448 (set (mem:SI (match_dup 2))
5449 (match_operand:SI 3 "arm_hard_register_operand" ""))
5450 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5451 (match_operand:SI 4 "arm_hard_register_operand" ""))
5452 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5453 (match_operand:SI 5 "arm_hard_register_operand" ""))
5454 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5455 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5456 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5457 "stmia\\t%1!, {%3, %4, %5, %6}"
5458 [(set_attr "type" "store4")]
5461 (define_insn "*stmsi_postinc3"
5462 [(match_parallel 0 "store_multiple_operation"
5463 [(set (match_operand:SI 1 "s_register_operand" "=r")
5464 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5466 (set (mem:SI (match_dup 2))
5467 (match_operand:SI 3 "arm_hard_register_operand" ""))
5468 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5469 (match_operand:SI 4 "arm_hard_register_operand" ""))
5470 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5471 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5472 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5473 "stm%?ia\\t%1!, {%3, %4, %5}"
5474 [(set_attr "predicable" "yes")
5475 (set_attr "type" "store3")]
5478 (define_insn "*stmsi_postinc2"
5479 [(match_parallel 0 "store_multiple_operation"
5480 [(set (match_operand:SI 1 "s_register_operand" "=r")
5481 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5483 (set (mem:SI (match_dup 2))
5484 (match_operand:SI 3 "arm_hard_register_operand" ""))
5485 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5486 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5487 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5488 "stm%?ia\\t%1!, {%3, %4}"
5489 [(set_attr "predicable" "yes")
5490 (set_attr "type" "store2")]
5493 ;; Ordinary store multiple
5495 (define_insn "*stmsi4"
5496 [(match_parallel 0 "store_multiple_operation"
5497 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5498 (match_operand:SI 2 "arm_hard_register_operand" ""))
5499 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5500 (match_operand:SI 3 "arm_hard_register_operand" ""))
5501 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5502 (match_operand:SI 4 "arm_hard_register_operand" ""))
5503 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5504 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5505 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5506 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5507 [(set_attr "predicable" "yes")
5508 (set_attr "type" "store4")]
5511 (define_insn "*stmsi3"
5512 [(match_parallel 0 "store_multiple_operation"
5513 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5514 (match_operand:SI 2 "arm_hard_register_operand" ""))
5515 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5516 (match_operand:SI 3 "arm_hard_register_operand" ""))
5517 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5518 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5519 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5520 "stm%?ia\\t%1, {%2, %3, %4}"
5521 [(set_attr "predicable" "yes")
5522 (set_attr "type" "store3")]
5525 (define_insn "*stmsi2"
5526 [(match_parallel 0 "store_multiple_operation"
5527 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5528 (match_operand:SI 2 "arm_hard_register_operand" ""))
5529 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5530 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5531 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5532 "stm%?ia\\t%1, {%2, %3}"
5533 [(set_attr "predicable" "yes")
5534 (set_attr "type" "store2")]
5537 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5538 ;; We could let this apply for blocks of less than this, but it clobbers so
5539 ;; many registers that there is then probably a better way.
5541 (define_expand "movmemqi"
5542 [(match_operand:BLK 0 "general_operand" "")
5543 (match_operand:BLK 1 "general_operand" "")
5544 (match_operand:SI 2 "const_int_operand" "")
5545 (match_operand:SI 3 "const_int_operand" "")]
5550 if (arm_gen_movmemqi (operands))
5554 else /* TARGET_THUMB */
5556 if ( INTVAL (operands[3]) != 4
5557 || INTVAL (operands[2]) > 48)
5560 thumb_expand_movmemqi (operands);
5566 ;; Thumb block-move insns
5568 (define_insn "movmem12b"
5569 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5570 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5571 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5572 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5573 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5574 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5575 (set (match_operand:SI 0 "register_operand" "=l")
5576 (plus:SI (match_dup 2) (const_int 12)))
5577 (set (match_operand:SI 1 "register_operand" "=l")
5578 (plus:SI (match_dup 3) (const_int 12)))
5579 (clobber (match_scratch:SI 4 "=&l"))
5580 (clobber (match_scratch:SI 5 "=&l"))
5581 (clobber (match_scratch:SI 6 "=&l"))]
5583 "* return thumb_output_move_mem_multiple (3, operands);"
5584 [(set_attr "length" "4")
5585 ; This isn't entirely accurate... It loads as well, but in terms of
5586 ; scheduling the following insn it is better to consider it as a store
5587 (set_attr "type" "store3")]
5590 (define_insn "movmem8b"
5591 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5592 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5593 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5594 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5595 (set (match_operand:SI 0 "register_operand" "=l")
5596 (plus:SI (match_dup 2) (const_int 8)))
5597 (set (match_operand:SI 1 "register_operand" "=l")
5598 (plus:SI (match_dup 3) (const_int 8)))
5599 (clobber (match_scratch:SI 4 "=&l"))
5600 (clobber (match_scratch:SI 5 "=&l"))]
5602 "* return thumb_output_move_mem_multiple (2, operands);"
5603 [(set_attr "length" "4")
5604 ; This isn't entirely accurate... It loads as well, but in terms of
5605 ; scheduling the following insn it is better to consider it as a store
5606 (set_attr "type" "store2")]
5611 ;; Compare & branch insns
5612 ;; The range calculations are based as follows:
5613 ;; For forward branches, the address calculation returns the address of
5614 ;; the next instruction. This is 2 beyond the branch instruction.
5615 ;; For backward branches, the address calculation returns the address of
5616 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5617 ;; instruction for the shortest sequence, and 4 before the branch instruction
5618 ;; if we have to jump around an unconditional branch.
5619 ;; To the basic branch range the PC offset must be added (this is +4).
5620 ;; So for forward branches we have
5621 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5622 ;; And for backward branches we have
5623 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5625 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5626 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5628 (define_expand "cbranchsi4"
5629 [(set (pc) (if_then_else
5630 (match_operator 0 "arm_comparison_operator"
5631 [(match_operand:SI 1 "s_register_operand" "")
5632 (match_operand:SI 2 "nonmemory_operand" "")])
5633 (label_ref (match_operand 3 "" ""))
5637 if (thumb_cmpneg_operand (operands[2], SImode))
5639 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5640 operands[3], operands[0]));
5643 if (!thumb_cmp_operand (operands[2], SImode))
5644 operands[2] = force_reg (SImode, operands[2]);
5647 (define_insn "*cbranchsi4_insn"
5648 [(set (pc) (if_then_else
5649 (match_operator 0 "arm_comparison_operator"
5650 [(match_operand:SI 1 "s_register_operand" "l,*h")
5651 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5652 (label_ref (match_operand 3 "" ""))
5656 output_asm_insn (\"cmp\\t%1, %2\", operands);
5658 switch (get_attr_length (insn))
5660 case 4: return \"b%d0\\t%l3\";
5661 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5662 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5665 [(set (attr "far_jump")
5667 (eq_attr "length" "8")
5668 (const_string "yes")
5669 (const_string "no")))
5670 (set (attr "length")
5672 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5673 (le (minus (match_dup 3) (pc)) (const_int 256)))
5676 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5677 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5682 (define_insn "cbranchsi4_scratch"
5683 [(set (pc) (if_then_else
5684 (match_operator 4 "arm_comparison_operator"
5685 [(match_operand:SI 1 "s_register_operand" "l,0")
5686 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5687 (label_ref (match_operand 3 "" ""))
5689 (clobber (match_scratch:SI 0 "=l,l"))]
5692 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5694 switch (get_attr_length (insn))
5696 case 4: return \"b%d4\\t%l3\";
5697 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5698 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5701 [(set (attr "far_jump")
5703 (eq_attr "length" "8")
5704 (const_string "yes")
5705 (const_string "no")))
5706 (set (attr "length")
5708 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5709 (le (minus (match_dup 3) (pc)) (const_int 256)))
5712 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5713 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5717 (define_insn "*movsi_cbranchsi4"
5720 (match_operator 3 "arm_comparison_operator"
5721 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5723 (label_ref (match_operand 2 "" ""))
5725 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5729 if (which_alternative == 0)
5730 output_asm_insn (\"cmp\t%0, #0\", operands);
5731 else if (which_alternative == 1)
5732 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5735 output_asm_insn (\"cmp\t%1, #0\", operands);
5736 if (which_alternative == 2)
5737 output_asm_insn (\"mov\t%0, %1\", operands);
5739 output_asm_insn (\"str\t%1, %0\", operands);
5741 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5743 case 4: return \"b%d3\\t%l2\";
5744 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5745 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5748 [(set (attr "far_jump")
5750 (ior (and (gt (symbol_ref ("which_alternative"))
5752 (eq_attr "length" "8"))
5753 (eq_attr "length" "10"))
5754 (const_string "yes")
5755 (const_string "no")))
5756 (set (attr "length")
5758 (le (symbol_ref ("which_alternative"))
5761 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5762 (le (minus (match_dup 2) (pc)) (const_int 256)))
5765 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5766 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5770 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5771 (le (minus (match_dup 2) (pc)) (const_int 256)))
5774 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5775 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5780 (define_insn "*negated_cbranchsi4"
5783 (match_operator 0 "arm_comparison_operator"
5784 [(match_operand:SI 1 "s_register_operand" "l")
5785 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5786 (label_ref (match_operand 3 "" ""))
5790 output_asm_insn (\"cmn\\t%1, %2\", operands);
5791 switch (get_attr_length (insn))
5793 case 4: return \"b%d0\\t%l3\";
5794 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5795 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5798 [(set (attr "far_jump")
5800 (eq_attr "length" "8")
5801 (const_string "yes")
5802 (const_string "no")))
5803 (set (attr "length")
5805 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5806 (le (minus (match_dup 3) (pc)) (const_int 256)))
5809 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5810 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5815 (define_insn "*tbit_cbranch"
5818 (match_operator 0 "equality_operator"
5819 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5821 (match_operand:SI 2 "const_int_operand" "i"))
5823 (label_ref (match_operand 3 "" ""))
5825 (clobber (match_scratch:SI 4 "=l"))]
5830 op[0] = operands[4];
5831 op[1] = operands[1];
5832 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5834 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5835 switch (get_attr_length (insn))
5837 case 4: return \"b%d0\\t%l3\";
5838 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5839 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5842 [(set (attr "far_jump")
5844 (eq_attr "length" "8")
5845 (const_string "yes")
5846 (const_string "no")))
5847 (set (attr "length")
5849 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5850 (le (minus (match_dup 3) (pc)) (const_int 256)))
5853 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5854 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5859 (define_insn "*tstsi3_cbranch"
5862 (match_operator 3 "equality_operator"
5863 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5864 (match_operand:SI 1 "s_register_operand" "l"))
5866 (label_ref (match_operand 2 "" ""))
5871 output_asm_insn (\"tst\\t%0, %1\", operands);
5872 switch (get_attr_length (insn))
5874 case 4: return \"b%d3\\t%l2\";
5875 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5876 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5879 [(set (attr "far_jump")
5881 (eq_attr "length" "8")
5882 (const_string "yes")
5883 (const_string "no")))
5884 (set (attr "length")
5886 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5887 (le (minus (match_dup 2) (pc)) (const_int 256)))
5890 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5891 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5896 (define_insn "*andsi3_cbranch"
5899 (match_operator 5 "equality_operator"
5900 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5901 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5903 (label_ref (match_operand 4 "" ""))
5905 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5906 (and:SI (match_dup 2) (match_dup 3)))
5907 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5911 if (which_alternative == 0)
5912 output_asm_insn (\"and\\t%0, %3\", operands);
5913 else if (which_alternative == 1)
5915 output_asm_insn (\"and\\t%1, %3\", operands);
5916 output_asm_insn (\"mov\\t%0, %1\", operands);
5920 output_asm_insn (\"and\\t%1, %3\", operands);
5921 output_asm_insn (\"str\\t%1, %0\", operands);
5924 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5926 case 4: return \"b%d5\\t%l4\";
5927 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5928 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5931 [(set (attr "far_jump")
5933 (ior (and (eq (symbol_ref ("which_alternative"))
5935 (eq_attr "length" "8"))
5936 (eq_attr "length" "10"))
5937 (const_string "yes")
5938 (const_string "no")))
5939 (set (attr "length")
5941 (eq (symbol_ref ("which_alternative"))
5944 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5945 (le (minus (match_dup 4) (pc)) (const_int 256)))
5948 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5949 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5953 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5954 (le (minus (match_dup 4) (pc)) (const_int 256)))
5957 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5958 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5963 (define_insn "*orrsi3_cbranch_scratch"
5966 (match_operator 4 "equality_operator"
5967 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5968 (match_operand:SI 2 "s_register_operand" "l"))
5970 (label_ref (match_operand 3 "" ""))
5972 (clobber (match_scratch:SI 0 "=l"))]
5976 output_asm_insn (\"orr\\t%0, %2\", operands);
5977 switch (get_attr_length (insn))
5979 case 4: return \"b%d4\\t%l3\";
5980 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5981 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5984 [(set (attr "far_jump")
5986 (eq_attr "length" "8")
5987 (const_string "yes")
5988 (const_string "no")))
5989 (set (attr "length")
5991 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5992 (le (minus (match_dup 3) (pc)) (const_int 256)))
5995 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5996 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6001 (define_insn "*orrsi3_cbranch"
6004 (match_operator 5 "equality_operator"
6005 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6006 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6008 (label_ref (match_operand 4 "" ""))
6010 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6011 (ior:SI (match_dup 2) (match_dup 3)))
6012 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6016 if (which_alternative == 0)
6017 output_asm_insn (\"orr\\t%0, %3\", operands);
6018 else if (which_alternative == 1)
6020 output_asm_insn (\"orr\\t%1, %3\", operands);
6021 output_asm_insn (\"mov\\t%0, %1\", operands);
6025 output_asm_insn (\"orr\\t%1, %3\", operands);
6026 output_asm_insn (\"str\\t%1, %0\", operands);
6029 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6031 case 4: return \"b%d5\\t%l4\";
6032 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6033 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6036 [(set (attr "far_jump")
6038 (ior (and (eq (symbol_ref ("which_alternative"))
6040 (eq_attr "length" "8"))
6041 (eq_attr "length" "10"))
6042 (const_string "yes")
6043 (const_string "no")))
6044 (set (attr "length")
6046 (eq (symbol_ref ("which_alternative"))
6049 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6050 (le (minus (match_dup 4) (pc)) (const_int 256)))
6053 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6054 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6058 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6059 (le (minus (match_dup 4) (pc)) (const_int 256)))
6062 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6063 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6068 (define_insn "*xorsi3_cbranch_scratch"
6071 (match_operator 4 "equality_operator"
6072 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6073 (match_operand:SI 2 "s_register_operand" "l"))
6075 (label_ref (match_operand 3 "" ""))
6077 (clobber (match_scratch:SI 0 "=l"))]
6081 output_asm_insn (\"eor\\t%0, %2\", operands);
6082 switch (get_attr_length (insn))
6084 case 4: return \"b%d4\\t%l3\";
6085 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6086 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6089 [(set (attr "far_jump")
6091 (eq_attr "length" "8")
6092 (const_string "yes")
6093 (const_string "no")))
6094 (set (attr "length")
6096 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6097 (le (minus (match_dup 3) (pc)) (const_int 256)))
6100 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6101 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6106 (define_insn "*xorsi3_cbranch"
6109 (match_operator 5 "equality_operator"
6110 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6111 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6113 (label_ref (match_operand 4 "" ""))
6115 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6116 (xor:SI (match_dup 2) (match_dup 3)))
6117 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6121 if (which_alternative == 0)
6122 output_asm_insn (\"eor\\t%0, %3\", operands);
6123 else if (which_alternative == 1)
6125 output_asm_insn (\"eor\\t%1, %3\", operands);
6126 output_asm_insn (\"mov\\t%0, %1\", operands);
6130 output_asm_insn (\"eor\\t%1, %3\", operands);
6131 output_asm_insn (\"str\\t%1, %0\", operands);
6134 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6136 case 4: return \"b%d5\\t%l4\";
6137 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6138 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6141 [(set (attr "far_jump")
6143 (ior (and (eq (symbol_ref ("which_alternative"))
6145 (eq_attr "length" "8"))
6146 (eq_attr "length" "10"))
6147 (const_string "yes")
6148 (const_string "no")))
6149 (set (attr "length")
6151 (eq (symbol_ref ("which_alternative"))
6154 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6155 (le (minus (match_dup 4) (pc)) (const_int 256)))
6158 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6159 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6163 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6164 (le (minus (match_dup 4) (pc)) (const_int 256)))
6167 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6168 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6173 (define_insn "*bicsi3_cbranch_scratch"
6176 (match_operator 4 "equality_operator"
6177 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6178 (match_operand:SI 1 "s_register_operand" "0"))
6180 (label_ref (match_operand 3 "" ""))
6182 (clobber (match_scratch:SI 0 "=l"))]
6186 output_asm_insn (\"bic\\t%0, %2\", operands);
6187 switch (get_attr_length (insn))
6189 case 4: return \"b%d4\\t%l3\";
6190 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6191 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6194 [(set (attr "far_jump")
6196 (eq_attr "length" "8")
6197 (const_string "yes")
6198 (const_string "no")))
6199 (set (attr "length")
6201 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6202 (le (minus (match_dup 3) (pc)) (const_int 256)))
6205 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6206 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6211 (define_insn "*bicsi3_cbranch"
6214 (match_operator 5 "equality_operator"
6215 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6216 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6218 (label_ref (match_operand 4 "" ""))
6220 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6221 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6222 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6226 if (which_alternative == 0)
6227 output_asm_insn (\"bic\\t%0, %3\", operands);
6228 else if (which_alternative <= 2)
6230 output_asm_insn (\"bic\\t%1, %3\", operands);
6231 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6232 conditions again, since we're only testing for equality. */
6233 output_asm_insn (\"mov\\t%0, %1\", operands);
6237 output_asm_insn (\"bic\\t%1, %3\", operands);
6238 output_asm_insn (\"str\\t%1, %0\", operands);
6241 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6243 case 4: return \"b%d5\\t%l4\";
6244 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6245 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6248 [(set (attr "far_jump")
6250 (ior (and (eq (symbol_ref ("which_alternative"))
6252 (eq_attr "length" "8"))
6253 (eq_attr "length" "10"))
6254 (const_string "yes")
6255 (const_string "no")))
6256 (set (attr "length")
6258 (eq (symbol_ref ("which_alternative"))
6261 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6262 (le (minus (match_dup 4) (pc)) (const_int 256)))
6265 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6266 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6270 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6271 (le (minus (match_dup 4) (pc)) (const_int 256)))
6274 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6275 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6280 (define_insn "*cbranchne_decr1"
6282 (if_then_else (match_operator 3 "equality_operator"
6283 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6285 (label_ref (match_operand 4 "" ""))
6287 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6288 (plus:SI (match_dup 2) (const_int -1)))
6289 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6294 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6296 VOIDmode, operands[2], const1_rtx);
6297 cond[1] = operands[4];
6299 if (which_alternative == 0)
6300 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6301 else if (which_alternative == 1)
6303 /* We must provide an alternative for a hi reg because reload
6304 cannot handle output reloads on a jump instruction, but we
6305 can't subtract into that. Fortunately a mov from lo to hi
6306 does not clobber the condition codes. */
6307 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6308 output_asm_insn (\"mov\\t%0, %1\", operands);
6312 /* Similarly, but the target is memory. */
6313 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6314 output_asm_insn (\"str\\t%1, %0\", operands);
6317 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6320 output_asm_insn (\"b%d0\\t%l1\", cond);
6323 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6324 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6326 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6327 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6331 [(set (attr "far_jump")
6333 (ior (and (eq (symbol_ref ("which_alternative"))
6335 (eq_attr "length" "8"))
6336 (eq_attr "length" "10"))
6337 (const_string "yes")
6338 (const_string "no")))
6339 (set_attr_alternative "length"
6343 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6344 (le (minus (match_dup 4) (pc)) (const_int 256)))
6347 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6348 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6353 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6354 (le (minus (match_dup 4) (pc)) (const_int 256)))
6357 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6358 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6363 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6364 (le (minus (match_dup 4) (pc)) (const_int 256)))
6367 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6368 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6373 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6374 (le (minus (match_dup 4) (pc)) (const_int 256)))
6377 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6378 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6383 (define_insn "*addsi3_cbranch"
6386 (match_operator 4 "comparison_operator"
6388 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6389 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6391 (label_ref (match_operand 5 "" ""))
6394 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6395 (plus:SI (match_dup 2) (match_dup 3)))
6396 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6398 && (GET_CODE (operands[4]) == EQ
6399 || GET_CODE (operands[4]) == NE
6400 || GET_CODE (operands[4]) == GE
6401 || GET_CODE (operands[4]) == LT)"
6407 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6408 cond[1] = operands[2];
6409 cond[2] = operands[3];
6411 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6412 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6414 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6416 if (which_alternative >= 3
6417 && which_alternative < 4)
6418 output_asm_insn (\"mov\\t%0, %1\", operands);
6419 else if (which_alternative >= 4)
6420 output_asm_insn (\"str\\t%1, %0\", operands);
6422 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6425 return \"b%d4\\t%l5\";
6427 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6429 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6433 [(set (attr "far_jump")
6435 (ior (and (lt (symbol_ref ("which_alternative"))
6437 (eq_attr "length" "8"))
6438 (eq_attr "length" "10"))
6439 (const_string "yes")
6440 (const_string "no")))
6441 (set (attr "length")
6443 (lt (symbol_ref ("which_alternative"))
6446 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6447 (le (minus (match_dup 5) (pc)) (const_int 256)))
6450 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6451 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6455 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6456 (le (minus (match_dup 5) (pc)) (const_int 256)))
6459 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6460 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6465 (define_insn "*addsi3_cbranch_scratch"
6468 (match_operator 3 "comparison_operator"
6470 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6471 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6473 (label_ref (match_operand 4 "" ""))
6475 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6477 && (GET_CODE (operands[3]) == EQ
6478 || GET_CODE (operands[3]) == NE
6479 || GET_CODE (operands[3]) == GE
6480 || GET_CODE (operands[3]) == LT)"
6483 switch (which_alternative)
6486 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6489 output_asm_insn (\"cmn\t%1, %2\", operands);
6492 if (INTVAL (operands[2]) < 0)
6493 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6495 output_asm_insn (\"add\t%0, %1, %2\", operands);
6498 if (INTVAL (operands[2]) < 0)
6499 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6501 output_asm_insn (\"add\t%0, %0, %2\", operands);
6505 switch (get_attr_length (insn))
6508 return \"b%d3\\t%l4\";
6510 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6512 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6516 [(set (attr "far_jump")
6518 (eq_attr "length" "8")
6519 (const_string "yes")
6520 (const_string "no")))
6521 (set (attr "length")
6523 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6524 (le (minus (match_dup 4) (pc)) (const_int 256)))
6527 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6528 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6533 (define_insn "*subsi3_cbranch"
6536 (match_operator 4 "comparison_operator"
6538 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6539 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6541 (label_ref (match_operand 5 "" ""))
6543 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6544 (minus:SI (match_dup 2) (match_dup 3)))
6545 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6547 && (GET_CODE (operands[4]) == EQ
6548 || GET_CODE (operands[4]) == NE
6549 || GET_CODE (operands[4]) == GE
6550 || GET_CODE (operands[4]) == LT)"
6553 if (which_alternative == 0)
6554 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6555 else if (which_alternative == 1)
6557 /* We must provide an alternative for a hi reg because reload
6558 cannot handle output reloads on a jump instruction, but we
6559 can't subtract into that. Fortunately a mov from lo to hi
6560 does not clobber the condition codes. */
6561 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6562 output_asm_insn (\"mov\\t%0, %1\", operands);
6566 /* Similarly, but the target is memory. */
6567 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6568 output_asm_insn (\"str\\t%1, %0\", operands);
6571 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6574 return \"b%d4\\t%l5\";
6576 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6578 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6582 [(set (attr "far_jump")
6584 (ior (and (eq (symbol_ref ("which_alternative"))
6586 (eq_attr "length" "8"))
6587 (eq_attr "length" "10"))
6588 (const_string "yes")
6589 (const_string "no")))
6590 (set (attr "length")
6592 (eq (symbol_ref ("which_alternative"))
6595 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6596 (le (minus (match_dup 5) (pc)) (const_int 256)))
6599 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6600 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6604 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6605 (le (minus (match_dup 5) (pc)) (const_int 256)))
6608 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6609 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6614 (define_insn "*subsi3_cbranch_scratch"
6617 (match_operator 0 "arm_comparison_operator"
6618 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6619 (match_operand:SI 2 "nonmemory_operand" "l"))
6621 (label_ref (match_operand 3 "" ""))
6624 && (GET_CODE (operands[0]) == EQ
6625 || GET_CODE (operands[0]) == NE
6626 || GET_CODE (operands[0]) == GE
6627 || GET_CODE (operands[0]) == LT)"
6629 output_asm_insn (\"cmp\\t%1, %2\", operands);
6630 switch (get_attr_length (insn))
6632 case 4: return \"b%d0\\t%l3\";
6633 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6634 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6637 [(set (attr "far_jump")
6639 (eq_attr "length" "8")
6640 (const_string "yes")
6641 (const_string "no")))
6642 (set (attr "length")
6644 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6645 (le (minus (match_dup 3) (pc)) (const_int 256)))
6648 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6649 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6654 ;; Comparison and test insns
6656 (define_expand "cmpsi"
6657 [(match_operand:SI 0 "s_register_operand" "")
6658 (match_operand:SI 1 "arm_add_operand" "")]
6661 arm_compare_op0 = operands[0];
6662 arm_compare_op1 = operands[1];
6667 (define_expand "cmpsf"
6668 [(match_operand:SF 0 "s_register_operand" "")
6669 (match_operand:SF 1 "arm_float_compare_operand" "")]
6670 "TARGET_ARM && TARGET_HARD_FLOAT"
6672 arm_compare_op0 = operands[0];
6673 arm_compare_op1 = operands[1];
6678 (define_expand "cmpdf"
6679 [(match_operand:DF 0 "s_register_operand" "")
6680 (match_operand:DF 1 "arm_float_compare_operand" "")]
6681 "TARGET_ARM && TARGET_HARD_FLOAT"
6683 arm_compare_op0 = operands[0];
6684 arm_compare_op1 = operands[1];
6689 (define_insn "*arm_cmpsi_insn"
6690 [(set (reg:CC CC_REGNUM)
6691 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6692 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6697 [(set_attr "conds" "set")]
6700 (define_insn "*cmpsi_shiftsi"
6701 [(set (reg:CC CC_REGNUM)
6702 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6703 (match_operator:SI 3 "shift_operator"
6704 [(match_operand:SI 1 "s_register_operand" "r")
6705 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6708 [(set_attr "conds" "set")
6709 (set_attr "shift" "1")
6710 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6711 (const_string "alu_shift")
6712 (const_string "alu_shift_reg")))]
6715 (define_insn "*cmpsi_shiftsi_swp"
6716 [(set (reg:CC_SWP CC_REGNUM)
6717 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6718 [(match_operand:SI 1 "s_register_operand" "r")
6719 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6720 (match_operand:SI 0 "s_register_operand" "r")))]
6723 [(set_attr "conds" "set")
6724 (set_attr "shift" "1")
6725 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6726 (const_string "alu_shift")
6727 (const_string "alu_shift_reg")))]
6730 (define_insn "*cmpsi_neg_shiftsi"
6731 [(set (reg:CC CC_REGNUM)
6732 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6733 (neg:SI (match_operator:SI 3 "shift_operator"
6734 [(match_operand:SI 1 "s_register_operand" "r")
6735 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6738 [(set_attr "conds" "set")
6739 (set_attr "shift" "1")
6740 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6741 (const_string "alu_shift")
6742 (const_string "alu_shift_reg")))]
6745 ;; Cirrus SF compare instruction
6746 (define_insn "*cirrus_cmpsf"
6747 [(set (reg:CCFP CC_REGNUM)
6748 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6749 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6750 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6751 "cfcmps%?\\tr15, %V0, %V1"
6752 [(set_attr "type" "mav_farith")
6753 (set_attr "cirrus" "compare")]
6756 ;; Cirrus DF compare instruction
6757 (define_insn "*cirrus_cmpdf"
6758 [(set (reg:CCFP CC_REGNUM)
6759 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6760 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6761 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6762 "cfcmpd%?\\tr15, %V0, %V1"
6763 [(set_attr "type" "mav_farith")
6764 (set_attr "cirrus" "compare")]
6767 ;; Cirrus DI compare instruction
6768 (define_expand "cmpdi"
6769 [(match_operand:DI 0 "cirrus_fp_register" "")
6770 (match_operand:DI 1 "cirrus_fp_register" "")]
6771 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6773 arm_compare_op0 = operands[0];
6774 arm_compare_op1 = operands[1];
6778 (define_insn "*cirrus_cmpdi"
6779 [(set (reg:CC CC_REGNUM)
6780 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6781 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6782 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6783 "cfcmp64%?\\tr15, %V0, %V1"
6784 [(set_attr "type" "mav_farith")
6785 (set_attr "cirrus" "compare")]
6788 ; This insn allows redundant compares to be removed by cse, nothing should
6789 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6790 ; is deleted later on. The match_dup will match the mode here, so that
6791 ; mode changes of the condition codes aren't lost by this even though we don't
6792 ; specify what they are.
6794 (define_insn "*deleted_compare"
6795 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6797 "\\t%@ deleted compare"
6798 [(set_attr "conds" "set")
6799 (set_attr "length" "0")]
6803 ;; Conditional branch insns
6805 (define_expand "beq"
6807 (if_then_else (eq (match_dup 1) (const_int 0))
6808 (label_ref (match_operand 0 "" ""))
6811 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6814 (define_expand "bne"
6816 (if_then_else (ne (match_dup 1) (const_int 0))
6817 (label_ref (match_operand 0 "" ""))
6820 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6823 (define_expand "bgt"
6825 (if_then_else (gt (match_dup 1) (const_int 0))
6826 (label_ref (match_operand 0 "" ""))
6829 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6832 (define_expand "ble"
6834 (if_then_else (le (match_dup 1) (const_int 0))
6835 (label_ref (match_operand 0 "" ""))
6838 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6841 (define_expand "bge"
6843 (if_then_else (ge (match_dup 1) (const_int 0))
6844 (label_ref (match_operand 0 "" ""))
6847 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6850 (define_expand "blt"
6852 (if_then_else (lt (match_dup 1) (const_int 0))
6853 (label_ref (match_operand 0 "" ""))
6856 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6859 (define_expand "bgtu"
6861 (if_then_else (gtu (match_dup 1) (const_int 0))
6862 (label_ref (match_operand 0 "" ""))
6865 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6868 (define_expand "bleu"
6870 (if_then_else (leu (match_dup 1) (const_int 0))
6871 (label_ref (match_operand 0 "" ""))
6874 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6877 (define_expand "bgeu"
6879 (if_then_else (geu (match_dup 1) (const_int 0))
6880 (label_ref (match_operand 0 "" ""))
6883 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6886 (define_expand "bltu"
6888 (if_then_else (ltu (match_dup 1) (const_int 0))
6889 (label_ref (match_operand 0 "" ""))
6892 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6895 (define_expand "bunordered"
6897 (if_then_else (unordered (match_dup 1) (const_int 0))
6898 (label_ref (match_operand 0 "" ""))
6900 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6901 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6905 (define_expand "bordered"
6907 (if_then_else (ordered (match_dup 1) (const_int 0))
6908 (label_ref (match_operand 0 "" ""))
6910 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6911 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6915 (define_expand "bungt"
6917 (if_then_else (ungt (match_dup 1) (const_int 0))
6918 (label_ref (match_operand 0 "" ""))
6920 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6921 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6924 (define_expand "bunlt"
6926 (if_then_else (unlt (match_dup 1) (const_int 0))
6927 (label_ref (match_operand 0 "" ""))
6929 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6930 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6933 (define_expand "bunge"
6935 (if_then_else (unge (match_dup 1) (const_int 0))
6936 (label_ref (match_operand 0 "" ""))
6938 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6939 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6942 (define_expand "bunle"
6944 (if_then_else (unle (match_dup 1) (const_int 0))
6945 (label_ref (match_operand 0 "" ""))
6947 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6948 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6951 ;; The following two patterns need two branch instructions, since there is
6952 ;; no single instruction that will handle all cases.
6953 (define_expand "buneq"
6955 (if_then_else (uneq (match_dup 1) (const_int 0))
6956 (label_ref (match_operand 0 "" ""))
6958 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6959 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6962 (define_expand "bltgt"
6964 (if_then_else (ltgt (match_dup 1) (const_int 0))
6965 (label_ref (match_operand 0 "" ""))
6967 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6968 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6972 ;; Patterns to match conditional branch insns.
6975 ; Special pattern to match UNEQ.
6976 (define_insn "*arm_buneq"
6978 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6979 (label_ref (match_operand 0 "" ""))
6981 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6983 if (arm_ccfsm_state != 0)
6986 return \"bvs\\t%l0\;beq\\t%l0\";
6988 [(set_attr "conds" "jump_clob")
6989 (set_attr "length" "8")]
6992 ; Special pattern to match LTGT.
6993 (define_insn "*arm_bltgt"
6995 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6996 (label_ref (match_operand 0 "" ""))
6998 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7000 if (arm_ccfsm_state != 0)
7003 return \"bmi\\t%l0\;bgt\\t%l0\";
7005 [(set_attr "conds" "jump_clob")
7006 (set_attr "length" "8")]
7009 (define_insn "*arm_cond_branch"
7011 (if_then_else (match_operator 1 "arm_comparison_operator"
7012 [(match_operand 2 "cc_register" "") (const_int 0)])
7013 (label_ref (match_operand 0 "" ""))
7017 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7019 arm_ccfsm_state += 2;
7022 return \"b%d1\\t%l0\";
7024 [(set_attr "conds" "use")
7025 (set_attr "type" "branch")]
7028 ; Special pattern to match reversed UNEQ.
7029 (define_insn "*arm_buneq_reversed"
7031 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7033 (label_ref (match_operand 0 "" ""))))]
7034 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7036 if (arm_ccfsm_state != 0)
7039 return \"bmi\\t%l0\;bgt\\t%l0\";
7041 [(set_attr "conds" "jump_clob")
7042 (set_attr "length" "8")]
7045 ; Special pattern to match reversed LTGT.
7046 (define_insn "*arm_bltgt_reversed"
7048 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7050 (label_ref (match_operand 0 "" ""))))]
7051 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7053 if (arm_ccfsm_state != 0)
7056 return \"bvs\\t%l0\;beq\\t%l0\";
7058 [(set_attr "conds" "jump_clob")
7059 (set_attr "length" "8")]
7062 (define_insn "*arm_cond_branch_reversed"
7064 (if_then_else (match_operator 1 "arm_comparison_operator"
7065 [(match_operand 2 "cc_register" "") (const_int 0)])
7067 (label_ref (match_operand 0 "" ""))))]
7070 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7072 arm_ccfsm_state += 2;
7075 return \"b%D1\\t%l0\";
7077 [(set_attr "conds" "use")
7078 (set_attr "type" "branch")]
7085 (define_expand "seq"
7086 [(set (match_operand:SI 0 "s_register_operand" "")
7087 (eq:SI (match_dup 1) (const_int 0)))]
7089 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7092 (define_expand "sne"
7093 [(set (match_operand:SI 0 "s_register_operand" "")
7094 (ne:SI (match_dup 1) (const_int 0)))]
7096 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7099 (define_expand "sgt"
7100 [(set (match_operand:SI 0 "s_register_operand" "")
7101 (gt:SI (match_dup 1) (const_int 0)))]
7103 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7106 (define_expand "sle"
7107 [(set (match_operand:SI 0 "s_register_operand" "")
7108 (le:SI (match_dup 1) (const_int 0)))]
7110 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7113 (define_expand "sge"
7114 [(set (match_operand:SI 0 "s_register_operand" "")
7115 (ge:SI (match_dup 1) (const_int 0)))]
7117 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7120 (define_expand "slt"
7121 [(set (match_operand:SI 0 "s_register_operand" "")
7122 (lt:SI (match_dup 1) (const_int 0)))]
7124 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7127 (define_expand "sgtu"
7128 [(set (match_operand:SI 0 "s_register_operand" "")
7129 (gtu:SI (match_dup 1) (const_int 0)))]
7131 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7134 (define_expand "sleu"
7135 [(set (match_operand:SI 0 "s_register_operand" "")
7136 (leu:SI (match_dup 1) (const_int 0)))]
7138 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7141 (define_expand "sgeu"
7142 [(set (match_operand:SI 0 "s_register_operand" "")
7143 (geu:SI (match_dup 1) (const_int 0)))]
7145 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7148 (define_expand "sltu"
7149 [(set (match_operand:SI 0 "s_register_operand" "")
7150 (ltu:SI (match_dup 1) (const_int 0)))]
7152 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7155 (define_expand "sunordered"
7156 [(set (match_operand:SI 0 "s_register_operand" "")
7157 (unordered:SI (match_dup 1) (const_int 0)))]
7158 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7159 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7163 (define_expand "sordered"
7164 [(set (match_operand:SI 0 "s_register_operand" "")
7165 (ordered:SI (match_dup 1) (const_int 0)))]
7166 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7167 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7171 (define_expand "sungt"
7172 [(set (match_operand:SI 0 "s_register_operand" "")
7173 (ungt:SI (match_dup 1) (const_int 0)))]
7174 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7175 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7179 (define_expand "sunge"
7180 [(set (match_operand:SI 0 "s_register_operand" "")
7181 (unge:SI (match_dup 1) (const_int 0)))]
7182 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7183 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7187 (define_expand "sunlt"
7188 [(set (match_operand:SI 0 "s_register_operand" "")
7189 (unlt:SI (match_dup 1) (const_int 0)))]
7190 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7191 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7195 (define_expand "sunle"
7196 [(set (match_operand:SI 0 "s_register_operand" "")
7197 (unle:SI (match_dup 1) (const_int 0)))]
7198 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7199 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7203 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7204 ;;; simple ARM instructions.
7206 ; (define_expand "suneq"
7207 ; [(set (match_operand:SI 0 "s_register_operand" "")
7208 ; (uneq:SI (match_dup 1) (const_int 0)))]
7209 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7213 ; (define_expand "sltgt"
7214 ; [(set (match_operand:SI 0 "s_register_operand" "")
7215 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7216 ; "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7220 (define_insn "*mov_scc"
7221 [(set (match_operand:SI 0 "s_register_operand" "=r")
7222 (match_operator:SI 1 "arm_comparison_operator"
7223 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7225 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7226 [(set_attr "conds" "use")
7227 (set_attr "length" "8")]
7230 (define_insn "*mov_negscc"
7231 [(set (match_operand:SI 0 "s_register_operand" "=r")
7232 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7233 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7235 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7236 [(set_attr "conds" "use")
7237 (set_attr "length" "8")]
7240 (define_insn "*mov_notscc"
7241 [(set (match_operand:SI 0 "s_register_operand" "=r")
7242 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7243 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7245 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7246 [(set_attr "conds" "use")
7247 (set_attr "length" "8")]
7251 ;; Conditional move insns
7253 (define_expand "movsicc"
7254 [(set (match_operand:SI 0 "s_register_operand" "")
7255 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7256 (match_operand:SI 2 "arm_not_operand" "")
7257 (match_operand:SI 3 "arm_not_operand" "")))]
7261 enum rtx_code code = GET_CODE (operands[1]);
7264 if (code == UNEQ || code == LTGT)
7267 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7268 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7272 (define_expand "movsfcc"
7273 [(set (match_operand:SF 0 "s_register_operand" "")
7274 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7275 (match_operand:SF 2 "s_register_operand" "")
7276 (match_operand:SF 3 "nonmemory_operand" "")))]
7280 enum rtx_code code = GET_CODE (operands[1]);
7283 if (code == UNEQ || code == LTGT)
7286 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7287 Otherwise, ensure it is a valid FP add operand */
7288 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7289 || (!arm_float_add_operand (operands[3], SFmode)))
7290 operands[3] = force_reg (SFmode, operands[3]);
7292 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7293 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7297 (define_expand "movdfcc"
7298 [(set (match_operand:DF 0 "s_register_operand" "")
7299 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7300 (match_operand:DF 2 "s_register_operand" "")
7301 (match_operand:DF 3 "arm_float_add_operand" "")))]
7302 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7305 enum rtx_code code = GET_CODE (operands[1]);
7308 if (code == UNEQ || code == LTGT)
7311 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7312 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7316 (define_insn "*movsicc_insn"
7317 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7319 (match_operator 3 "arm_comparison_operator"
7320 [(match_operand 4 "cc_register" "") (const_int 0)])
7321 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7322 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7329 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7330 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7331 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7332 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7333 [(set_attr "length" "4,4,4,4,8,8,8,8")
7334 (set_attr "conds" "use")]
7337 (define_insn "*movsfcc_soft_insn"
7338 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7339 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7340 [(match_operand 4 "cc_register" "") (const_int 0)])
7341 (match_operand:SF 1 "s_register_operand" "0,r")
7342 (match_operand:SF 2 "s_register_operand" "r,0")))]
7343 "TARGET_ARM && TARGET_SOFT_FLOAT"
7347 [(set_attr "conds" "use")]
7351 ;; Jump and linkage insns
7353 (define_expand "jump"
7355 (label_ref (match_operand 0 "" "")))]
7360 (define_insn "*arm_jump"
7362 (label_ref (match_operand 0 "" "")))]
7366 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7368 arm_ccfsm_state += 2;
7371 return \"b%?\\t%l0\";
7374 [(set_attr "predicable" "yes")]
7377 (define_insn "*thumb_jump"
7379 (label_ref (match_operand 0 "" "")))]
7382 if (get_attr_length (insn) == 2)
7384 return \"bl\\t%l0\\t%@ far jump\";
7386 [(set (attr "far_jump")
7388 (eq_attr "length" "4")
7389 (const_string "yes")
7390 (const_string "no")))
7391 (set (attr "length")
7393 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7394 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7399 (define_expand "call"
7400 [(parallel [(call (match_operand 0 "memory_operand" "")
7401 (match_operand 1 "general_operand" ""))
7402 (use (match_operand 2 "" ""))
7403 (clobber (reg:SI LR_REGNUM))])]
7409 /* In an untyped call, we can get NULL for operand 2. */
7410 if (operands[2] == NULL_RTX)
7411 operands[2] = const0_rtx;
7413 /* This is to decide if we should generate indirect calls by loading the
7414 32 bit address of the callee into a register before performing the
7415 branch and link. operand[2] encodes the long_call/short_call
7416 attribute of the function being called. This attribute is set whenever
7417 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7418 is used, and the short_call attribute can also be set if function is
7419 declared as static or if it has already been defined in the current
7420 compilation unit. See arm.c and arm.h for info about this. The third
7421 parameter to arm_is_longcall_p is used to tell it which pattern
7423 callee = XEXP (operands[0], 0);
7425 if (GET_CODE (callee) != REG
7426 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7427 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7431 (define_insn "*call_reg_armv5"
7432 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7433 (match_operand 1 "" ""))
7434 (use (match_operand 2 "" ""))
7435 (clobber (reg:SI LR_REGNUM))]
7436 "TARGET_ARM && arm_arch5"
7438 [(set_attr "type" "call")]
7441 (define_insn "*call_reg_arm"
7442 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7443 (match_operand 1 "" ""))
7444 (use (match_operand 2 "" ""))
7445 (clobber (reg:SI LR_REGNUM))]
7446 "TARGET_ARM && !arm_arch5"
7448 return output_call (operands);
7450 ;; length is worst case, normally it is only two
7451 [(set_attr "length" "12")
7452 (set_attr "type" "call")]
7455 (define_insn "*call_mem"
7456 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7457 (match_operand 1 "" ""))
7458 (use (match_operand 2 "" ""))
7459 (clobber (reg:SI LR_REGNUM))]
7462 return output_call_mem (operands);
7464 [(set_attr "length" "12")
7465 (set_attr "type" "call")]
7468 (define_insn "*call_reg_thumb_v5"
7469 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7470 (match_operand 1 "" ""))
7471 (use (match_operand 2 "" ""))
7472 (clobber (reg:SI LR_REGNUM))]
7473 "TARGET_THUMB && arm_arch5"
7475 [(set_attr "length" "2")
7476 (set_attr "type" "call")]
7479 (define_insn "*call_reg_thumb"
7480 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7481 (match_operand 1 "" ""))
7482 (use (match_operand 2 "" ""))
7483 (clobber (reg:SI LR_REGNUM))]
7484 "TARGET_THUMB && !arm_arch5"
7487 if (!TARGET_CALLER_INTERWORKING)
7488 return thumb_call_via_reg (operands[0]);
7489 else if (operands[1] == const0_rtx)
7490 return \"bl\\t%__interwork_call_via_%0\";
7491 else if (frame_pointer_needed)
7492 return \"bl\\t%__interwork_r7_call_via_%0\";
7494 return \"bl\\t%__interwork_r11_call_via_%0\";
7496 [(set_attr "type" "call")]
7499 (define_expand "call_value"
7500 [(parallel [(set (match_operand 0 "" "")
7501 (call (match_operand 1 "memory_operand" "")
7502 (match_operand 2 "general_operand" "")))
7503 (use (match_operand 3 "" ""))
7504 (clobber (reg:SI LR_REGNUM))])]
7508 rtx callee = XEXP (operands[1], 0);
7510 /* In an untyped call, we can get NULL for operand 2. */
7511 if (operands[3] == 0)
7512 operands[3] = const0_rtx;
7514 /* See the comment in define_expand \"call\". */
7515 if (GET_CODE (callee) != REG
7516 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7517 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7521 (define_insn "*call_value_reg_armv5"
7522 [(set (match_operand 0 "" "")
7523 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7524 (match_operand 2 "" "")))
7525 (use (match_operand 3 "" ""))
7526 (clobber (reg:SI LR_REGNUM))]
7527 "TARGET_ARM && arm_arch5"
7529 [(set_attr "type" "call")]
7532 (define_insn "*call_value_reg_arm"
7533 [(set (match_operand 0 "" "")
7534 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7535 (match_operand 2 "" "")))
7536 (use (match_operand 3 "" ""))
7537 (clobber (reg:SI LR_REGNUM))]
7538 "TARGET_ARM && !arm_arch5"
7540 return output_call (&operands[1]);
7542 [(set_attr "length" "12")
7543 (set_attr "type" "call")]
7546 (define_insn "*call_value_mem"
7547 [(set (match_operand 0 "" "")
7548 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7549 (match_operand 2 "" "")))
7550 (use (match_operand 3 "" ""))
7551 (clobber (reg:SI LR_REGNUM))]
7552 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7554 return output_call_mem (&operands[1]);
7556 [(set_attr "length" "12")
7557 (set_attr "type" "call")]
7560 (define_insn "*call_value_reg_thumb_v5"
7561 [(set (match_operand 0 "" "")
7562 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7563 (match_operand 2 "" "")))
7564 (use (match_operand 3 "" ""))
7565 (clobber (reg:SI LR_REGNUM))]
7566 "TARGET_THUMB && arm_arch5"
7568 [(set_attr "length" "2")
7569 (set_attr "type" "call")]
7572 (define_insn "*call_value_reg_thumb"
7573 [(set (match_operand 0 "" "")
7574 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7575 (match_operand 2 "" "")))
7576 (use (match_operand 3 "" ""))
7577 (clobber (reg:SI LR_REGNUM))]
7578 "TARGET_THUMB && !arm_arch5"
7581 if (!TARGET_CALLER_INTERWORKING)
7582 return thumb_call_via_reg (operands[1]);
7583 else if (operands[2] == const0_rtx)
7584 return \"bl\\t%__interwork_call_via_%1\";
7585 else if (frame_pointer_needed)
7586 return \"bl\\t%__interwork_r7_call_via_%1\";
7588 return \"bl\\t%__interwork_r11_call_via_%1\";
7590 [(set_attr "type" "call")]
7593 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7594 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7596 (define_insn "*call_symbol"
7597 [(call (mem:SI (match_operand:SI 0 "" ""))
7598 (match_operand 1 "" ""))
7599 (use (match_operand 2 "" ""))
7600 (clobber (reg:SI LR_REGNUM))]
7602 && (GET_CODE (operands[0]) == SYMBOL_REF)
7603 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7606 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7608 [(set_attr "type" "call")]
7611 (define_insn "*call_value_symbol"
7612 [(set (match_operand 0 "" "")
7613 (call (mem:SI (match_operand:SI 1 "" ""))
7614 (match_operand:SI 2 "" "")))
7615 (use (match_operand 3 "" ""))
7616 (clobber (reg:SI LR_REGNUM))]
7618 && (GET_CODE (operands[1]) == SYMBOL_REF)
7619 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7622 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7624 [(set_attr "type" "call")]
7627 (define_insn "*call_insn"
7628 [(call (mem:SI (match_operand:SI 0 "" ""))
7629 (match_operand:SI 1 "" ""))
7630 (use (match_operand 2 "" ""))
7631 (clobber (reg:SI LR_REGNUM))]
7633 && GET_CODE (operands[0]) == SYMBOL_REF
7634 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7636 [(set_attr "length" "4")
7637 (set_attr "type" "call")]
7640 (define_insn "*call_value_insn"
7641 [(set (match_operand 0 "" "")
7642 (call (mem:SI (match_operand 1 "" ""))
7643 (match_operand 2 "" "")))
7644 (use (match_operand 3 "" ""))
7645 (clobber (reg:SI LR_REGNUM))]
7647 && GET_CODE (operands[1]) == SYMBOL_REF
7648 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7650 [(set_attr "length" "4")
7651 (set_attr "type" "call")]
7654 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7655 (define_expand "sibcall"
7656 [(parallel [(call (match_operand 0 "memory_operand" "")
7657 (match_operand 1 "general_operand" ""))
7659 (use (match_operand 2 "" ""))])]
7663 if (operands[2] == NULL_RTX)
7664 operands[2] = const0_rtx;
7668 (define_expand "sibcall_value"
7669 [(parallel [(set (match_operand 0 "" "")
7670 (call (match_operand 1 "memory_operand" "")
7671 (match_operand 2 "general_operand" "")))
7673 (use (match_operand 3 "" ""))])]
7677 if (operands[3] == NULL_RTX)
7678 operands[3] = const0_rtx;
7682 (define_insn "*sibcall_insn"
7683 [(call (mem:SI (match_operand:SI 0 "" "X"))
7684 (match_operand 1 "" ""))
7686 (use (match_operand 2 "" ""))]
7687 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7689 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7691 [(set_attr "type" "call")]
7694 (define_insn "*sibcall_value_insn"
7695 [(set (match_operand 0 "" "")
7696 (call (mem:SI (match_operand:SI 1 "" "X"))
7697 (match_operand 2 "" "")))
7699 (use (match_operand 3 "" ""))]
7700 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7702 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7704 [(set_attr "type" "call")]
7707 ;; Often the return insn will be the same as loading from memory, so set attr
7708 (define_insn "return"
7710 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7713 if (arm_ccfsm_state == 2)
7715 arm_ccfsm_state += 2;
7718 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7720 [(set_attr "type" "load1")
7721 (set_attr "length" "12")
7722 (set_attr "predicable" "yes")]
7725 (define_insn "*cond_return"
7727 (if_then_else (match_operator 0 "arm_comparison_operator"
7728 [(match_operand 1 "cc_register" "") (const_int 0)])
7731 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7734 if (arm_ccfsm_state == 2)
7736 arm_ccfsm_state += 2;
7739 return output_return_instruction (operands[0], TRUE, FALSE);
7741 [(set_attr "conds" "use")
7742 (set_attr "length" "12")
7743 (set_attr "type" "load1")]
7746 (define_insn "*cond_return_inverted"
7748 (if_then_else (match_operator 0 "arm_comparison_operator"
7749 [(match_operand 1 "cc_register" "") (const_int 0)])
7752 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7755 if (arm_ccfsm_state == 2)
7757 arm_ccfsm_state += 2;
7760 return output_return_instruction (operands[0], TRUE, TRUE);
7762 [(set_attr "conds" "use")
7763 (set_attr "length" "12")
7764 (set_attr "type" "load1")]
7767 ;; Generate a sequence of instructions to determine if the processor is
7768 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7771 (define_expand "return_addr_mask"
7773 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7775 (set (match_operand:SI 0 "s_register_operand" "")
7776 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7778 (const_int 67108860)))] ; 0x03fffffc
7781 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7784 (define_insn "*check_arch2"
7785 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7786 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7789 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7790 [(set_attr "length" "8")
7791 (set_attr "conds" "set")]
7794 ;; Call subroutine returning any type.
7796 (define_expand "untyped_call"
7797 [(parallel [(call (match_operand 0 "" "")
7799 (match_operand 1 "" "")
7800 (match_operand 2 "" "")])]
7805 rtx par = gen_rtx_PARALLEL (VOIDmode,
7806 rtvec_alloc (XVECLEN (operands[2], 0)));
7807 rtx addr = gen_reg_rtx (Pmode);
7811 emit_move_insn (addr, XEXP (operands[1], 0));
7812 mem = change_address (operands[1], BLKmode, addr);
7814 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7816 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7818 /* Default code only uses r0 as a return value, but we could
7819 be using anything up to 4 registers. */
7820 if (REGNO (src) == R0_REGNUM)
7821 src = gen_rtx_REG (TImode, R0_REGNUM);
7823 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7825 size += GET_MODE_SIZE (GET_MODE (src));
7828 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7833 for (i = 0; i < XVECLEN (par, 0); i++)
7835 HOST_WIDE_INT offset = 0;
7836 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7839 emit_move_insn (addr, plus_constant (addr, size));
7841 mem = change_address (mem, GET_MODE (reg), NULL);
7842 if (REGNO (reg) == R0_REGNUM)
7844 /* On thumb we have to use a write-back instruction. */
7845 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7846 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7847 size = TARGET_ARM ? 16 : 0;
7851 emit_move_insn (mem, reg);
7852 size = GET_MODE_SIZE (GET_MODE (reg));
7856 /* The optimizer does not know that the call sets the function value
7857 registers we stored in the result block. We avoid problems by
7858 claiming that all hard registers are used and clobbered at this
7860 emit_insn (gen_blockage ());
7866 (define_expand "untyped_return"
7867 [(match_operand:BLK 0 "memory_operand" "")
7868 (match_operand 1 "" "")]
7873 rtx addr = gen_reg_rtx (Pmode);
7877 emit_move_insn (addr, XEXP (operands[0], 0));
7878 mem = change_address (operands[0], BLKmode, addr);
7880 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7882 HOST_WIDE_INT offset = 0;
7883 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7886 emit_move_insn (addr, plus_constant (addr, size));
7888 mem = change_address (mem, GET_MODE (reg), NULL);
7889 if (REGNO (reg) == R0_REGNUM)
7891 /* On thumb we have to use a write-back instruction. */
7892 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7893 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7894 size = TARGET_ARM ? 16 : 0;
7898 emit_move_insn (reg, mem);
7899 size = GET_MODE_SIZE (GET_MODE (reg));
7903 /* Emit USE insns before the return. */
7904 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7905 emit_insn (gen_rtx_USE (VOIDmode,
7906 SET_DEST (XVECEXP (operands[1], 0, i))));
7908 /* Construct the return. */
7909 expand_naked_return ();
7915 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7916 ;; all of memory. This blocks insns from being moved across this point.
7918 (define_insn "blockage"
7919 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7922 [(set_attr "length" "0")
7923 (set_attr "type" "block")]
7926 (define_expand "casesi"
7927 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7928 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7929 (match_operand:SI 2 "const_int_operand" "") ; total range
7930 (match_operand:SI 3 "" "") ; table label
7931 (match_operand:SI 4 "" "")] ; Out of range label
7936 if (operands[1] != const0_rtx)
7938 reg = gen_reg_rtx (SImode);
7940 emit_insn (gen_addsi3 (reg, operands[0],
7941 GEN_INT (-INTVAL (operands[1]))));
7945 if (!const_ok_for_arm (INTVAL (operands[2])))
7946 operands[2] = force_reg (SImode, operands[2]);
7948 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7954 ;; The USE in this pattern is needed to tell flow analysis that this is
7955 ;; a CASESI insn. It has no other purpose.
7956 (define_insn "casesi_internal"
7957 [(parallel [(set (pc)
7959 (leu (match_operand:SI 0 "s_register_operand" "r")
7960 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7961 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7962 (label_ref (match_operand 2 "" ""))))
7963 (label_ref (match_operand 3 "" ""))))
7964 (clobber (reg:CC CC_REGNUM))
7965 (use (label_ref (match_dup 2)))])]
7969 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7970 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7972 [(set_attr "conds" "clob")
7973 (set_attr "length" "12")]
7976 (define_expand "indirect_jump"
7978 (match_operand:SI 0 "s_register_operand" ""))]
7983 ;; NB Never uses BX.
7984 (define_insn "*arm_indirect_jump"
7986 (match_operand:SI 0 "s_register_operand" "r"))]
7988 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7989 [(set_attr "predicable" "yes")]
7992 (define_insn "*load_indirect_jump"
7994 (match_operand:SI 0 "memory_operand" "m"))]
7996 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7997 [(set_attr "type" "load1")
7998 (set_attr "pool_range" "4096")
7999 (set_attr "neg_pool_range" "4084")
8000 (set_attr "predicable" "yes")]
8003 ;; NB Never uses BX.
8004 (define_insn "*thumb_indirect_jump"
8006 (match_operand:SI 0 "register_operand" "l*r"))]
8009 [(set_attr "conds" "clob")
8010 (set_attr "length" "2")]
8021 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8022 return \"mov\\tr8, r8\";
8024 [(set (attr "length")
8025 (if_then_else (eq_attr "is_thumb" "yes")
8031 ;; Patterns to allow combination of arithmetic, cond code and shifts
8033 (define_insn "*arith_shiftsi"
8034 [(set (match_operand:SI 0 "s_register_operand" "=r")
8035 (match_operator:SI 1 "shiftable_operator"
8036 [(match_operator:SI 3 "shift_operator"
8037 [(match_operand:SI 4 "s_register_operand" "r")
8038 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8039 (match_operand:SI 2 "s_register_operand" "r")]))]
8041 "%i1%?\\t%0, %2, %4%S3"
8042 [(set_attr "predicable" "yes")
8043 (set_attr "shift" "4")
8044 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8045 (const_string "alu_shift")
8046 (const_string "alu_shift_reg")))]
8050 [(set (match_operand:SI 0 "s_register_operand" "")
8051 (match_operator:SI 1 "shiftable_operator"
8052 [(match_operator:SI 2 "shiftable_operator"
8053 [(match_operator:SI 3 "shift_operator"
8054 [(match_operand:SI 4 "s_register_operand" "")
8055 (match_operand:SI 5 "reg_or_int_operand" "")])
8056 (match_operand:SI 6 "s_register_operand" "")])
8057 (match_operand:SI 7 "arm_rhs_operand" "")]))
8058 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8061 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8064 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8067 (define_insn "*arith_shiftsi_compare0"
8068 [(set (reg:CC_NOOV CC_REGNUM)
8069 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8070 [(match_operator:SI 3 "shift_operator"
8071 [(match_operand:SI 4 "s_register_operand" "r")
8072 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8073 (match_operand:SI 2 "s_register_operand" "r")])
8075 (set (match_operand:SI 0 "s_register_operand" "=r")
8076 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8079 "%i1%?s\\t%0, %2, %4%S3"
8080 [(set_attr "conds" "set")
8081 (set_attr "shift" "4")
8082 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8083 (const_string "alu_shift")
8084 (const_string "alu_shift_reg")))]
8087 (define_insn "*arith_shiftsi_compare0_scratch"
8088 [(set (reg:CC_NOOV CC_REGNUM)
8089 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8090 [(match_operator:SI 3 "shift_operator"
8091 [(match_operand:SI 4 "s_register_operand" "r")
8092 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8093 (match_operand:SI 2 "s_register_operand" "r")])
8095 (clobber (match_scratch:SI 0 "=r"))]
8097 "%i1%?s\\t%0, %2, %4%S3"
8098 [(set_attr "conds" "set")
8099 (set_attr "shift" "4")
8100 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8101 (const_string "alu_shift")
8102 (const_string "alu_shift_reg")))]
8105 (define_insn "*sub_shiftsi"
8106 [(set (match_operand:SI 0 "s_register_operand" "=r")
8107 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8108 (match_operator:SI 2 "shift_operator"
8109 [(match_operand:SI 3 "s_register_operand" "r")
8110 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8112 "sub%?\\t%0, %1, %3%S2"
8113 [(set_attr "predicable" "yes")
8114 (set_attr "shift" "3")
8115 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8116 (const_string "alu_shift")
8117 (const_string "alu_shift_reg")))]
8120 (define_insn "*sub_shiftsi_compare0"
8121 [(set (reg:CC_NOOV CC_REGNUM)
8123 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8124 (match_operator:SI 2 "shift_operator"
8125 [(match_operand:SI 3 "s_register_operand" "r")
8126 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8128 (set (match_operand:SI 0 "s_register_operand" "=r")
8129 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8132 "sub%?s\\t%0, %1, %3%S2"
8133 [(set_attr "conds" "set")
8134 (set_attr "shift" "3")
8135 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8136 (const_string "alu_shift")
8137 (const_string "alu_shift_reg")))]
8140 (define_insn "*sub_shiftsi_compare0_scratch"
8141 [(set (reg:CC_NOOV CC_REGNUM)
8143 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8144 (match_operator:SI 2 "shift_operator"
8145 [(match_operand:SI 3 "s_register_operand" "r")
8146 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8148 (clobber (match_scratch:SI 0 "=r"))]
8150 "sub%?s\\t%0, %1, %3%S2"
8151 [(set_attr "conds" "set")
8152 (set_attr "shift" "3")
8153 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8154 (const_string "alu_shift")
8155 (const_string "alu_shift_reg")))]
8160 (define_insn "*and_scc"
8161 [(set (match_operand:SI 0 "s_register_operand" "=r")
8162 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8163 [(match_operand 3 "cc_register" "") (const_int 0)])
8164 (match_operand:SI 2 "s_register_operand" "r")))]
8166 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8167 [(set_attr "conds" "use")
8168 (set_attr "length" "8")]
8171 (define_insn "*ior_scc"
8172 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8173 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8174 [(match_operand 3 "cc_register" "") (const_int 0)])
8175 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8179 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8180 [(set_attr "conds" "use")
8181 (set_attr "length" "4,8")]
8184 (define_insn "*compare_scc"
8185 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8186 (match_operator:SI 1 "arm_comparison_operator"
8187 [(match_operand:SI 2 "s_register_operand" "r,r")
8188 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8189 (clobber (reg:CC CC_REGNUM))]
8192 if (operands[3] == const0_rtx)
8194 if (GET_CODE (operands[1]) == LT)
8195 return \"mov\\t%0, %2, lsr #31\";
8197 if (GET_CODE (operands[1]) == GE)
8198 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8200 if (GET_CODE (operands[1]) == EQ)
8201 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8204 if (GET_CODE (operands[1]) == NE)
8206 if (which_alternative == 1)
8207 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8208 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8210 if (which_alternative == 1)
8211 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8213 output_asm_insn (\"cmp\\t%2, %3\", operands);
8214 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8216 [(set_attr "conds" "clob")
8217 (set_attr "length" "12")]
8220 (define_insn "*cond_move"
8221 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8222 (if_then_else:SI (match_operator 3 "equality_operator"
8223 [(match_operator 4 "arm_comparison_operator"
8224 [(match_operand 5 "cc_register" "") (const_int 0)])
8226 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8227 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8230 if (GET_CODE (operands[3]) == NE)
8232 if (which_alternative != 1)
8233 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8234 if (which_alternative != 0)
8235 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8238 if (which_alternative != 0)
8239 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8240 if (which_alternative != 1)
8241 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8244 [(set_attr "conds" "use")
8245 (set_attr "length" "4,4,8")]
8248 (define_insn "*cond_arith"
8249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8250 (match_operator:SI 5 "shiftable_operator"
8251 [(match_operator:SI 4 "arm_comparison_operator"
8252 [(match_operand:SI 2 "s_register_operand" "r,r")
8253 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8254 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8255 (clobber (reg:CC CC_REGNUM))]
8258 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8259 return \"%i5\\t%0, %1, %2, lsr #31\";
8261 output_asm_insn (\"cmp\\t%2, %3\", operands);
8262 if (GET_CODE (operands[5]) == AND)
8263 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8264 else if (GET_CODE (operands[5]) == MINUS)
8265 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8266 else if (which_alternative != 0)
8267 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8268 return \"%i5%d4\\t%0, %1, #1\";
8270 [(set_attr "conds" "clob")
8271 (set_attr "length" "12")]
8274 (define_insn "*cond_sub"
8275 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8276 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8277 (match_operator:SI 4 "arm_comparison_operator"
8278 [(match_operand:SI 2 "s_register_operand" "r,r")
8279 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8280 (clobber (reg:CC CC_REGNUM))]
8283 output_asm_insn (\"cmp\\t%2, %3\", operands);
8284 if (which_alternative != 0)
8285 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8286 return \"sub%d4\\t%0, %1, #1\";
8288 [(set_attr "conds" "clob")
8289 (set_attr "length" "8,12")]
8292 (define_insn "*cmp_ite0"
8293 [(set (match_operand 6 "dominant_cc_register" "")
8296 (match_operator 4 "arm_comparison_operator"
8297 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8298 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8299 (match_operator:SI 5 "arm_comparison_operator"
8300 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8301 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8307 static const char * const opcodes[4][2] =
8309 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8310 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8311 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8312 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8313 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8314 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8315 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8316 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8319 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8321 return opcodes[which_alternative][swap];
8323 [(set_attr "conds" "set")
8324 (set_attr "length" "8")]
8327 (define_insn "*cmp_ite1"
8328 [(set (match_operand 6 "dominant_cc_register" "")
8331 (match_operator 4 "arm_comparison_operator"
8332 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8333 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8334 (match_operator:SI 5 "arm_comparison_operator"
8335 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8336 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8342 static const char * const opcodes[4][2] =
8344 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8345 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8346 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8347 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8348 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8349 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8350 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8351 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8354 comparison_dominates_p (GET_CODE (operands[5]),
8355 reverse_condition (GET_CODE (operands[4])));
8357 return opcodes[which_alternative][swap];
8359 [(set_attr "conds" "set")
8360 (set_attr "length" "8")]
8363 (define_insn "*cmp_and"
8364 [(set (match_operand 6 "dominant_cc_register" "")
8367 (match_operator 4 "arm_comparison_operator"
8368 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8369 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8370 (match_operator:SI 5 "arm_comparison_operator"
8371 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8372 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8377 static const char *const opcodes[4][2] =
8379 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8380 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8381 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8382 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8383 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8384 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8385 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8386 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8389 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8391 return opcodes[which_alternative][swap];
8393 [(set_attr "conds" "set")
8394 (set_attr "predicable" "no")
8395 (set_attr "length" "8")]
8398 (define_insn "*cmp_ior"
8399 [(set (match_operand 6 "dominant_cc_register" "")
8402 (match_operator 4 "arm_comparison_operator"
8403 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8404 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8405 (match_operator:SI 5 "arm_comparison_operator"
8406 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8407 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8412 static const char *const opcodes[4][2] =
8414 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8415 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8416 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8417 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8418 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8419 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8420 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8421 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8424 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8426 return opcodes[which_alternative][swap];
8429 [(set_attr "conds" "set")
8430 (set_attr "length" "8")]
8433 (define_insn_and_split "*ior_scc_scc"
8434 [(set (match_operand:SI 0 "s_register_operand" "=r")
8435 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8436 [(match_operand:SI 1 "s_register_operand" "r")
8437 (match_operand:SI 2 "arm_add_operand" "rIL")])
8438 (match_operator:SI 6 "arm_comparison_operator"
8439 [(match_operand:SI 4 "s_register_operand" "r")
8440 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8441 (clobber (reg:CC CC_REGNUM))]
8443 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8446 "TARGET_ARM && reload_completed"
8450 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8451 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8453 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8455 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8458 [(set_attr "conds" "clob")
8459 (set_attr "length" "16")])
8461 ; If the above pattern is followed by a CMP insn, then the compare is
8462 ; redundant, since we can rework the conditional instruction that follows.
8463 (define_insn_and_split "*ior_scc_scc_cmp"
8464 [(set (match_operand 0 "dominant_cc_register" "")
8465 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8466 [(match_operand:SI 1 "s_register_operand" "r")
8467 (match_operand:SI 2 "arm_add_operand" "rIL")])
8468 (match_operator:SI 6 "arm_comparison_operator"
8469 [(match_operand:SI 4 "s_register_operand" "r")
8470 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8472 (set (match_operand:SI 7 "s_register_operand" "=r")
8473 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8474 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8477 "TARGET_ARM && reload_completed"
8481 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8482 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8484 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8486 [(set_attr "conds" "set")
8487 (set_attr "length" "16")])
8489 (define_insn_and_split "*and_scc_scc"
8490 [(set (match_operand:SI 0 "s_register_operand" "=r")
8491 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8492 [(match_operand:SI 1 "s_register_operand" "r")
8493 (match_operand:SI 2 "arm_add_operand" "rIL")])
8494 (match_operator:SI 6 "arm_comparison_operator"
8495 [(match_operand:SI 4 "s_register_operand" "r")
8496 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8497 (clobber (reg:CC CC_REGNUM))]
8499 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8502 "TARGET_ARM && reload_completed
8503 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8508 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8509 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8511 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8513 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8516 [(set_attr "conds" "clob")
8517 (set_attr "length" "16")])
8519 ; If the above pattern is followed by a CMP insn, then the compare is
8520 ; redundant, since we can rework the conditional instruction that follows.
8521 (define_insn_and_split "*and_scc_scc_cmp"
8522 [(set (match_operand 0 "dominant_cc_register" "")
8523 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8524 [(match_operand:SI 1 "s_register_operand" "r")
8525 (match_operand:SI 2 "arm_add_operand" "rIL")])
8526 (match_operator:SI 6 "arm_comparison_operator"
8527 [(match_operand:SI 4 "s_register_operand" "r")
8528 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8530 (set (match_operand:SI 7 "s_register_operand" "=r")
8531 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8532 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8535 "TARGET_ARM && reload_completed"
8539 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8540 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8542 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8544 [(set_attr "conds" "set")
8545 (set_attr "length" "16")])
8547 ;; If there is no dominance in the comparison, then we can still save an
8548 ;; instruction in the AND case, since we can know that the second compare
8549 ;; need only zero the value if false (if true, then the value is already
8551 (define_insn_and_split "*and_scc_scc_nodom"
8552 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8553 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8554 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8555 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8556 (match_operator:SI 6 "arm_comparison_operator"
8557 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8558 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8559 (clobber (reg:CC CC_REGNUM))]
8561 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8564 "TARGET_ARM && reload_completed"
8565 [(parallel [(set (match_dup 0)
8566 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8567 (clobber (reg:CC CC_REGNUM))])
8568 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8570 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8573 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8574 operands[4], operands[5]),
8576 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8578 [(set_attr "conds" "clob")
8579 (set_attr "length" "20")])
8582 [(set (reg:CC_NOOV CC_REGNUM)
8583 (compare:CC_NOOV (ior:SI
8584 (and:SI (match_operand:SI 0 "s_register_operand" "")
8586 (match_operator:SI 1 "comparison_operator"
8587 [(match_operand:SI 2 "s_register_operand" "")
8588 (match_operand:SI 3 "arm_add_operand" "")]))
8590 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8593 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8595 (set (reg:CC_NOOV CC_REGNUM)
8596 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8601 [(set (reg:CC_NOOV CC_REGNUM)
8602 (compare:CC_NOOV (ior:SI
8603 (match_operator:SI 1 "comparison_operator"
8604 [(match_operand:SI 2 "s_register_operand" "")
8605 (match_operand:SI 3 "arm_add_operand" "")])
8606 (and:SI (match_operand:SI 0 "s_register_operand" "")
8609 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8612 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8614 (set (reg:CC_NOOV CC_REGNUM)
8615 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8619 (define_insn "*negscc"
8620 [(set (match_operand:SI 0 "s_register_operand" "=r")
8621 (neg:SI (match_operator 3 "arm_comparison_operator"
8622 [(match_operand:SI 1 "s_register_operand" "r")
8623 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8624 (clobber (reg:CC CC_REGNUM))]
8627 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8628 return \"mov\\t%0, %1, asr #31\";
8630 if (GET_CODE (operands[3]) == NE)
8631 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8633 if (GET_CODE (operands[3]) == GT)
8634 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8636 output_asm_insn (\"cmp\\t%1, %2\", operands);
8637 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8638 return \"mvn%d3\\t%0, #0\";
8640 [(set_attr "conds" "clob")
8641 (set_attr "length" "12")]
8644 (define_insn "movcond"
8645 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8647 (match_operator 5 "arm_comparison_operator"
8648 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8649 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8650 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8651 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8652 (clobber (reg:CC CC_REGNUM))]
8655 if (GET_CODE (operands[5]) == LT
8656 && (operands[4] == const0_rtx))
8658 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8660 if (operands[2] == const0_rtx)
8661 return \"and\\t%0, %1, %3, asr #31\";
8662 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8664 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8666 if (operands[1] == const0_rtx)
8667 return \"bic\\t%0, %2, %3, asr #31\";
8668 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8670 /* The only case that falls through to here is when both ops 1 & 2
8674 if (GET_CODE (operands[5]) == GE
8675 && (operands[4] == const0_rtx))
8677 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8679 if (operands[2] == const0_rtx)
8680 return \"bic\\t%0, %1, %3, asr #31\";
8681 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8683 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8685 if (operands[1] == const0_rtx)
8686 return \"and\\t%0, %2, %3, asr #31\";
8687 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8689 /* The only case that falls through to here is when both ops 1 & 2
8692 if (GET_CODE (operands[4]) == CONST_INT
8693 && !const_ok_for_arm (INTVAL (operands[4])))
8694 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8696 output_asm_insn (\"cmp\\t%3, %4\", operands);
8697 if (which_alternative != 0)
8698 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8699 if (which_alternative != 1)
8700 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8703 [(set_attr "conds" "clob")
8704 (set_attr "length" "8,8,12")]
8707 (define_insn "*ifcompare_plus_move"
8708 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8709 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8710 [(match_operand:SI 4 "s_register_operand" "r,r")
8711 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8713 (match_operand:SI 2 "s_register_operand" "r,r")
8714 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8715 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8716 (clobber (reg:CC CC_REGNUM))]
8719 [(set_attr "conds" "clob")
8720 (set_attr "length" "8,12")]
8723 (define_insn "*if_plus_move"
8724 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8726 (match_operator 4 "arm_comparison_operator"
8727 [(match_operand 5 "cc_register" "") (const_int 0)])
8729 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8730 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8731 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8735 sub%d4\\t%0, %2, #%n3
8736 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8737 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8738 [(set_attr "conds" "use")
8739 (set_attr "length" "4,4,8,8")
8740 (set_attr "type" "*,*,*,*")]
8743 (define_insn "*ifcompare_move_plus"
8744 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8745 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8746 [(match_operand:SI 4 "s_register_operand" "r,r")
8747 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8748 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8750 (match_operand:SI 2 "s_register_operand" "r,r")
8751 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8752 (clobber (reg:CC CC_REGNUM))]
8755 [(set_attr "conds" "clob")
8756 (set_attr "length" "8,12")]
8759 (define_insn "*if_move_plus"
8760 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8762 (match_operator 4 "arm_comparison_operator"
8763 [(match_operand 5 "cc_register" "") (const_int 0)])
8764 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8766 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8767 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8771 sub%D4\\t%0, %2, #%n3
8772 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8773 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8774 [(set_attr "conds" "use")
8775 (set_attr "length" "4,4,8,8")
8776 (set_attr "type" "*,*,*,*")]
8779 (define_insn "*ifcompare_arith_arith"
8780 [(set (match_operand:SI 0 "s_register_operand" "=r")
8781 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8782 [(match_operand:SI 5 "s_register_operand" "r")
8783 (match_operand:SI 6 "arm_add_operand" "rIL")])
8784 (match_operator:SI 8 "shiftable_operator"
8785 [(match_operand:SI 1 "s_register_operand" "r")
8786 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8787 (match_operator:SI 7 "shiftable_operator"
8788 [(match_operand:SI 3 "s_register_operand" "r")
8789 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8790 (clobber (reg:CC CC_REGNUM))]
8793 [(set_attr "conds" "clob")
8794 (set_attr "length" "12")]
8797 (define_insn "*if_arith_arith"
8798 [(set (match_operand:SI 0 "s_register_operand" "=r")
8799 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8800 [(match_operand 8 "cc_register" "") (const_int 0)])
8801 (match_operator:SI 6 "shiftable_operator"
8802 [(match_operand:SI 1 "s_register_operand" "r")
8803 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8804 (match_operator:SI 7 "shiftable_operator"
8805 [(match_operand:SI 3 "s_register_operand" "r")
8806 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8808 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8809 [(set_attr "conds" "use")
8810 (set_attr "length" "8")]
8813 (define_insn "*ifcompare_arith_move"
8814 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8815 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8816 [(match_operand:SI 2 "s_register_operand" "r,r")
8817 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8818 (match_operator:SI 7 "shiftable_operator"
8819 [(match_operand:SI 4 "s_register_operand" "r,r")
8820 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8821 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8822 (clobber (reg:CC CC_REGNUM))]
8825 /* If we have an operation where (op x 0) is the identity operation and
8826 the conditional operator is LT or GE and we are comparing against zero and
8827 everything is in registers then we can do this in two instructions. */
8828 if (operands[3] == const0_rtx
8829 && GET_CODE (operands[7]) != AND
8830 && GET_CODE (operands[5]) == REG
8831 && GET_CODE (operands[1]) == REG
8832 && REGNO (operands[1]) == REGNO (operands[4])
8833 && REGNO (operands[4]) != REGNO (operands[0]))
8835 if (GET_CODE (operands[6]) == LT)
8836 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8837 else if (GET_CODE (operands[6]) == GE)
8838 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8840 if (GET_CODE (operands[3]) == CONST_INT
8841 && !const_ok_for_arm (INTVAL (operands[3])))
8842 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8844 output_asm_insn (\"cmp\\t%2, %3\", operands);
8845 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8846 if (which_alternative != 0)
8847 return \"mov%D6\\t%0, %1\";
8850 [(set_attr "conds" "clob")
8851 (set_attr "length" "8,12")]
8854 (define_insn "*if_arith_move"
8855 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8857 [(match_operand 6 "cc_register" "") (const_int 0)])
8858 (match_operator:SI 5 "shiftable_operator"
8859 [(match_operand:SI 2 "s_register_operand" "r,r")
8860 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8861 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8865 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8866 [(set_attr "conds" "use")
8867 (set_attr "length" "4,8")
8868 (set_attr "type" "*,*")]
8871 (define_insn "*ifcompare_move_arith"
8872 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8873 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8874 [(match_operand:SI 4 "s_register_operand" "r,r")
8875 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8876 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8877 (match_operator:SI 7 "shiftable_operator"
8878 [(match_operand:SI 2 "s_register_operand" "r,r")
8879 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8880 (clobber (reg:CC CC_REGNUM))]
8883 /* If we have an operation where (op x 0) is the identity operation and
8884 the conditional operator is LT or GE and we are comparing against zero and
8885 everything is in registers then we can do this in two instructions */
8886 if (operands[5] == const0_rtx
8887 && GET_CODE (operands[7]) != AND
8888 && GET_CODE (operands[3]) == REG
8889 && GET_CODE (operands[1]) == REG
8890 && REGNO (operands[1]) == REGNO (operands[2])
8891 && REGNO (operands[2]) != REGNO (operands[0]))
8893 if (GET_CODE (operands[6]) == GE)
8894 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8895 else if (GET_CODE (operands[6]) == LT)
8896 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8899 if (GET_CODE (operands[5]) == CONST_INT
8900 && !const_ok_for_arm (INTVAL (operands[5])))
8901 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8903 output_asm_insn (\"cmp\\t%4, %5\", operands);
8905 if (which_alternative != 0)
8906 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8907 return \"%I7%D6\\t%0, %2, %3\";
8909 [(set_attr "conds" "clob")
8910 (set_attr "length" "8,12")]
8913 (define_insn "*if_move_arith"
8914 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8916 (match_operator 4 "arm_comparison_operator"
8917 [(match_operand 6 "cc_register" "") (const_int 0)])
8918 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8919 (match_operator:SI 5 "shiftable_operator"
8920 [(match_operand:SI 2 "s_register_operand" "r,r")
8921 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8925 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8926 [(set_attr "conds" "use")
8927 (set_attr "length" "4,8")
8928 (set_attr "type" "*,*")]
8931 (define_insn "*ifcompare_move_not"
8932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8934 (match_operator 5 "arm_comparison_operator"
8935 [(match_operand:SI 3 "s_register_operand" "r,r")
8936 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8937 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8939 (match_operand:SI 2 "s_register_operand" "r,r"))))
8940 (clobber (reg:CC CC_REGNUM))]
8943 [(set_attr "conds" "clob")
8944 (set_attr "length" "8,12")]
8947 (define_insn "*if_move_not"
8948 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8950 (match_operator 4 "arm_comparison_operator"
8951 [(match_operand 3 "cc_register" "") (const_int 0)])
8952 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8953 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8957 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8958 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8959 [(set_attr "conds" "use")
8960 (set_attr "length" "4,8,8")]
8963 (define_insn "*ifcompare_not_move"
8964 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8966 (match_operator 5 "arm_comparison_operator"
8967 [(match_operand:SI 3 "s_register_operand" "r,r")
8968 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8970 (match_operand:SI 2 "s_register_operand" "r,r"))
8971 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8972 (clobber (reg:CC CC_REGNUM))]
8975 [(set_attr "conds" "clob")
8976 (set_attr "length" "8,12")]
8979 (define_insn "*if_not_move"
8980 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8982 (match_operator 4 "arm_comparison_operator"
8983 [(match_operand 3 "cc_register" "") (const_int 0)])
8984 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8985 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8989 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8990 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8991 [(set_attr "conds" "use")
8992 (set_attr "length" "4,8,8")]
8995 (define_insn "*ifcompare_shift_move"
8996 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8998 (match_operator 6 "arm_comparison_operator"
8999 [(match_operand:SI 4 "s_register_operand" "r,r")
9000 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9001 (match_operator:SI 7 "shift_operator"
9002 [(match_operand:SI 2 "s_register_operand" "r,r")
9003 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9004 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9005 (clobber (reg:CC CC_REGNUM))]
9008 [(set_attr "conds" "clob")
9009 (set_attr "length" "8,12")]
9012 (define_insn "*if_shift_move"
9013 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9015 (match_operator 5 "arm_comparison_operator"
9016 [(match_operand 6 "cc_register" "") (const_int 0)])
9017 (match_operator:SI 4 "shift_operator"
9018 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9019 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9020 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9024 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9025 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9026 [(set_attr "conds" "use")
9027 (set_attr "shift" "2")
9028 (set_attr "length" "4,8,8")
9029 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9030 (const_string "alu_shift")
9031 (const_string "alu_shift_reg")))]
9034 (define_insn "*ifcompare_move_shift"
9035 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9037 (match_operator 6 "arm_comparison_operator"
9038 [(match_operand:SI 4 "s_register_operand" "r,r")
9039 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9040 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9041 (match_operator:SI 7 "shift_operator"
9042 [(match_operand:SI 2 "s_register_operand" "r,r")
9043 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9044 (clobber (reg:CC CC_REGNUM))]
9047 [(set_attr "conds" "clob")
9048 (set_attr "length" "8,12")]
9051 (define_insn "*if_move_shift"
9052 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9054 (match_operator 5 "arm_comparison_operator"
9055 [(match_operand 6 "cc_register" "") (const_int 0)])
9056 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9057 (match_operator:SI 4 "shift_operator"
9058 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9059 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9063 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9064 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9065 [(set_attr "conds" "use")
9066 (set_attr "shift" "2")
9067 (set_attr "length" "4,8,8")
9068 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9069 (const_string "alu_shift")
9070 (const_string "alu_shift_reg")))]
9073 (define_insn "*ifcompare_shift_shift"
9074 [(set (match_operand:SI 0 "s_register_operand" "=r")
9076 (match_operator 7 "arm_comparison_operator"
9077 [(match_operand:SI 5 "s_register_operand" "r")
9078 (match_operand:SI 6 "arm_add_operand" "rIL")])
9079 (match_operator:SI 8 "shift_operator"
9080 [(match_operand:SI 1 "s_register_operand" "r")
9081 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9082 (match_operator:SI 9 "shift_operator"
9083 [(match_operand:SI 3 "s_register_operand" "r")
9084 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9085 (clobber (reg:CC CC_REGNUM))]
9088 [(set_attr "conds" "clob")
9089 (set_attr "length" "12")]
9092 (define_insn "*if_shift_shift"
9093 [(set (match_operand:SI 0 "s_register_operand" "=r")
9095 (match_operator 5 "arm_comparison_operator"
9096 [(match_operand 8 "cc_register" "") (const_int 0)])
9097 (match_operator:SI 6 "shift_operator"
9098 [(match_operand:SI 1 "s_register_operand" "r")
9099 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9100 (match_operator:SI 7 "shift_operator"
9101 [(match_operand:SI 3 "s_register_operand" "r")
9102 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9104 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9105 [(set_attr "conds" "use")
9106 (set_attr "shift" "1")
9107 (set_attr "length" "8")
9108 (set (attr "type") (if_then_else
9109 (and (match_operand 2 "const_int_operand" "")
9110 (match_operand 4 "const_int_operand" ""))
9111 (const_string "alu_shift")
9112 (const_string "alu_shift_reg")))]
9115 (define_insn "*ifcompare_not_arith"
9116 [(set (match_operand:SI 0 "s_register_operand" "=r")
9118 (match_operator 6 "arm_comparison_operator"
9119 [(match_operand:SI 4 "s_register_operand" "r")
9120 (match_operand:SI 5 "arm_add_operand" "rIL")])
9121 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9122 (match_operator:SI 7 "shiftable_operator"
9123 [(match_operand:SI 2 "s_register_operand" "r")
9124 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9125 (clobber (reg:CC CC_REGNUM))]
9128 [(set_attr "conds" "clob")
9129 (set_attr "length" "12")]
9132 (define_insn "*if_not_arith"
9133 [(set (match_operand:SI 0 "s_register_operand" "=r")
9135 (match_operator 5 "arm_comparison_operator"
9136 [(match_operand 4 "cc_register" "") (const_int 0)])
9137 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9138 (match_operator:SI 6 "shiftable_operator"
9139 [(match_operand:SI 2 "s_register_operand" "r")
9140 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9142 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9143 [(set_attr "conds" "use")
9144 (set_attr "length" "8")]
9147 (define_insn "*ifcompare_arith_not"
9148 [(set (match_operand:SI 0 "s_register_operand" "=r")
9150 (match_operator 6 "arm_comparison_operator"
9151 [(match_operand:SI 4 "s_register_operand" "r")
9152 (match_operand:SI 5 "arm_add_operand" "rIL")])
9153 (match_operator:SI 7 "shiftable_operator"
9154 [(match_operand:SI 2 "s_register_operand" "r")
9155 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9156 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9157 (clobber (reg:CC CC_REGNUM))]
9160 [(set_attr "conds" "clob")
9161 (set_attr "length" "12")]
9164 (define_insn "*if_arith_not"
9165 [(set (match_operand:SI 0 "s_register_operand" "=r")
9167 (match_operator 5 "arm_comparison_operator"
9168 [(match_operand 4 "cc_register" "") (const_int 0)])
9169 (match_operator:SI 6 "shiftable_operator"
9170 [(match_operand:SI 2 "s_register_operand" "r")
9171 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9172 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9174 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9175 [(set_attr "conds" "use")
9176 (set_attr "length" "8")]
9179 (define_insn "*ifcompare_neg_move"
9180 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9182 (match_operator 5 "arm_comparison_operator"
9183 [(match_operand:SI 3 "s_register_operand" "r,r")
9184 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9185 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9186 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9187 (clobber (reg:CC CC_REGNUM))]
9190 [(set_attr "conds" "clob")
9191 (set_attr "length" "8,12")]
9194 (define_insn "*if_neg_move"
9195 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9197 (match_operator 4 "arm_comparison_operator"
9198 [(match_operand 3 "cc_register" "") (const_int 0)])
9199 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9200 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9204 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9205 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9206 [(set_attr "conds" "use")
9207 (set_attr "length" "4,8,8")]
9210 (define_insn "*ifcompare_move_neg"
9211 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9213 (match_operator 5 "arm_comparison_operator"
9214 [(match_operand:SI 3 "s_register_operand" "r,r")
9215 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9216 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9217 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9218 (clobber (reg:CC CC_REGNUM))]
9221 [(set_attr "conds" "clob")
9222 (set_attr "length" "8,12")]
9225 (define_insn "*if_move_neg"
9226 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9228 (match_operator 4 "arm_comparison_operator"
9229 [(match_operand 3 "cc_register" "") (const_int 0)])
9230 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9231 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9235 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9236 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9237 [(set_attr "conds" "use")
9238 (set_attr "length" "4,8,8")]
9241 (define_insn "*arith_adjacentmem"
9242 [(set (match_operand:SI 0 "s_register_operand" "=r")
9243 (match_operator:SI 1 "shiftable_operator"
9244 [(match_operand:SI 2 "memory_operand" "m")
9245 (match_operand:SI 3 "memory_operand" "m")]))
9246 (clobber (match_scratch:SI 4 "=r"))]
9247 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9252 int val1 = 0, val2 = 0;
9254 if (REGNO (operands[0]) > REGNO (operands[4]))
9256 ldm[1] = operands[4];
9257 ldm[2] = operands[0];
9261 ldm[1] = operands[0];
9262 ldm[2] = operands[4];
9264 if (GET_CODE (XEXP (operands[2], 0)) != REG)
9265 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9266 if (GET_CODE (XEXP (operands[3], 0)) != REG)
9267 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9268 arith[0] = operands[0];
9269 arith[3] = operands[1];
9283 ldm[0] = ops[0] = operands[4];
9284 ops[1] = XEXP (XEXP (operands[2], 0), 0);
9285 ops[2] = XEXP (XEXP (operands[2], 0), 1);
9286 output_add_immediate (ops);
9288 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9290 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9294 ldm[0] = XEXP (operands[3], 0);
9296 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9298 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9302 ldm[0] = XEXP (operands[2], 0);
9304 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9306 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9308 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9311 [(set_attr "length" "12")
9312 (set_attr "predicable" "yes")
9313 (set_attr "type" "load1")]
9316 ;; the arm can support extended pre-inc instructions
9318 ;; In all these cases, we use operands 0 and 1 for the register being
9319 ;; incremented because those are the operands that local-alloc will
9320 ;; tie and these are the pair most likely to be tieable (and the ones
9321 ;; that will benefit the most).
9323 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9324 ;; elimination will cause too many headaches.
9326 (define_insn "*strqi_preinc"
9327 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9328 (match_operand:SI 2 "index_operand" "rJ")))
9329 (match_operand:QI 3 "s_register_operand" "r"))
9330 (set (match_operand:SI 0 "s_register_operand" "=r")
9331 (plus:SI (match_dup 1) (match_dup 2)))]
9333 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9334 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9335 && (GET_CODE (operands[2]) != REG
9336 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9337 "str%?b\\t%3, [%0, %2]!"
9338 [(set_attr "type" "store1")
9339 (set_attr "predicable" "yes")]
9342 (define_insn "*strqi_predec"
9343 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9344 (match_operand:SI 2 "s_register_operand" "r")))
9345 (match_operand:QI 3 "s_register_operand" "r"))
9346 (set (match_operand:SI 0 "s_register_operand" "=r")
9347 (minus:SI (match_dup 1) (match_dup 2)))]
9349 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9350 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9351 && (GET_CODE (operands[2]) != REG
9352 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9353 "str%?b\\t%3, [%0, -%2]!"
9354 [(set_attr "type" "store1")
9355 (set_attr "predicable" "yes")]
9358 (define_insn "*loadqi_preinc"
9359 [(set (match_operand:QI 3 "s_register_operand" "=r")
9360 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9361 (match_operand:SI 2 "index_operand" "rJ"))))
9362 (set (match_operand:SI 0 "s_register_operand" "=r")
9363 (plus:SI (match_dup 1) (match_dup 2)))]
9365 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9366 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9367 && (GET_CODE (operands[2]) != REG
9368 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9369 "ldr%?b\\t%3, [%0, %2]!"
9370 [(set_attr "type" "load_byte")
9371 (set_attr "predicable" "yes")]
9374 (define_insn "*loadqi_predec"
9375 [(set (match_operand:QI 3 "s_register_operand" "=r")
9376 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9377 (match_operand:SI 2 "s_register_operand" "r"))))
9378 (set (match_operand:SI 0 "s_register_operand" "=r")
9379 (minus:SI (match_dup 1) (match_dup 2)))]
9381 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9382 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9383 && (GET_CODE (operands[2]) != REG
9384 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9385 "ldr%?b\\t%3, [%0, -%2]!"
9386 [(set_attr "type" "load_byte")
9387 (set_attr "predicable" "yes")]
9390 (define_insn "*loadqisi_preinc"
9391 [(set (match_operand:SI 3 "s_register_operand" "=r")
9393 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9394 (match_operand:SI 2 "index_operand" "rJ")))))
9395 (set (match_operand:SI 0 "s_register_operand" "=r")
9396 (plus:SI (match_dup 1) (match_dup 2)))]
9398 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9399 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9400 && (GET_CODE (operands[2]) != REG
9401 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9402 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9403 [(set_attr "type" "load_byte")
9404 (set_attr "predicable" "yes")]
9407 (define_insn "*loadqisi_predec"
9408 [(set (match_operand:SI 3 "s_register_operand" "=r")
9410 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9411 (match_operand:SI 2 "s_register_operand" "r")))))
9412 (set (match_operand:SI 0 "s_register_operand" "=r")
9413 (minus:SI (match_dup 1) (match_dup 2)))]
9415 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9416 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9417 && (GET_CODE (operands[2]) != REG
9418 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9419 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9420 [(set_attr "type" "load_byte")
9421 (set_attr "predicable" "yes")]
9424 (define_insn "*strsi_preinc"
9425 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9426 (match_operand:SI 2 "index_operand" "rJ")))
9427 (match_operand:SI 3 "s_register_operand" "r"))
9428 (set (match_operand:SI 0 "s_register_operand" "=r")
9429 (plus:SI (match_dup 1) (match_dup 2)))]
9431 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9432 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9433 && (GET_CODE (operands[2]) != REG
9434 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9435 "str%?\\t%3, [%0, %2]!"
9436 [(set_attr "type" "store1")
9437 (set_attr "predicable" "yes")]
9440 (define_insn "*strsi_predec"
9441 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9442 (match_operand:SI 2 "s_register_operand" "r")))
9443 (match_operand:SI 3 "s_register_operand" "r"))
9444 (set (match_operand:SI 0 "s_register_operand" "=r")
9445 (minus:SI (match_dup 1) (match_dup 2)))]
9447 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9448 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9449 && (GET_CODE (operands[2]) != REG
9450 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9451 "str%?\\t%3, [%0, -%2]!"
9452 [(set_attr "type" "store1")
9453 (set_attr "predicable" "yes")]
9456 (define_insn "*loadsi_preinc"
9457 [(set (match_operand:SI 3 "s_register_operand" "=r")
9458 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9459 (match_operand:SI 2 "index_operand" "rJ"))))
9460 (set (match_operand:SI 0 "s_register_operand" "=r")
9461 (plus:SI (match_dup 1) (match_dup 2)))]
9463 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9464 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9465 && (GET_CODE (operands[2]) != REG
9466 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9467 "ldr%?\\t%3, [%0, %2]!"
9468 [(set_attr "type" "load1")
9469 (set_attr "predicable" "yes")]
9472 (define_insn "*loadsi_predec"
9473 [(set (match_operand:SI 3 "s_register_operand" "=r")
9474 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9475 (match_operand:SI 2 "s_register_operand" "r"))))
9476 (set (match_operand:SI 0 "s_register_operand" "=r")
9477 (minus:SI (match_dup 1) (match_dup 2)))]
9479 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9480 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9481 && (GET_CODE (operands[2]) != REG
9482 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9483 "ldr%?\\t%3, [%0, -%2]!"
9484 [(set_attr "type" "load1")
9485 (set_attr "predicable" "yes")]
9488 (define_insn "*strqi_shiftpreinc"
9489 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9490 [(match_operand:SI 3 "s_register_operand" "r")
9491 (match_operand:SI 4 "const_shift_operand" "n")])
9492 (match_operand:SI 1 "s_register_operand" "0")))
9493 (match_operand:QI 5 "s_register_operand" "r"))
9494 (set (match_operand:SI 0 "s_register_operand" "=r")
9495 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9498 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9499 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9500 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9501 "str%?b\\t%5, [%0, %3%S2]!"
9502 [(set_attr "type" "store1")
9503 (set_attr "predicable" "yes")]
9506 (define_insn "*strqi_shiftpredec"
9507 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9508 (match_operator:SI 2 "shift_operator"
9509 [(match_operand:SI 3 "s_register_operand" "r")
9510 (match_operand:SI 4 "const_shift_operand" "n")])))
9511 (match_operand:QI 5 "s_register_operand" "r"))
9512 (set (match_operand:SI 0 "s_register_operand" "=r")
9513 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9516 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9517 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9518 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9519 "str%?b\\t%5, [%0, -%3%S2]!"
9520 [(set_attr "type" "store1")
9521 (set_attr "predicable" "yes")]
9524 (define_insn "*loadqi_shiftpreinc"
9525 [(set (match_operand:QI 5 "s_register_operand" "=r")
9526 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9527 [(match_operand:SI 3 "s_register_operand" "r")
9528 (match_operand:SI 4 "const_shift_operand" "n")])
9529 (match_operand:SI 1 "s_register_operand" "0"))))
9530 (set (match_operand:SI 0 "s_register_operand" "=r")
9531 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9534 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9535 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9536 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9537 "ldr%?b\\t%5, [%0, %3%S2]!"
9538 [(set_attr "type" "load_byte")
9539 (set_attr "predicable" "yes")]
9542 (define_insn "*loadqi_shiftpredec"
9543 [(set (match_operand:QI 5 "s_register_operand" "=r")
9544 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9545 (match_operator:SI 2 "shift_operator"
9546 [(match_operand:SI 3 "s_register_operand" "r")
9547 (match_operand:SI 4 "const_shift_operand" "n")]))))
9548 (set (match_operand:SI 0 "s_register_operand" "=r")
9549 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9552 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9553 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9554 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9555 "ldr%?b\\t%5, [%0, -%3%S2]!"
9556 [(set_attr "type" "load_byte")
9557 (set_attr "predicable" "yes")]
9560 (define_insn "*strsi_shiftpreinc"
9561 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9562 [(match_operand:SI 3 "s_register_operand" "r")
9563 (match_operand:SI 4 "const_shift_operand" "n")])
9564 (match_operand:SI 1 "s_register_operand" "0")))
9565 (match_operand:SI 5 "s_register_operand" "r"))
9566 (set (match_operand:SI 0 "s_register_operand" "=r")
9567 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9570 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9571 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9572 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9573 "str%?\\t%5, [%0, %3%S2]!"
9574 [(set_attr "type" "store1")
9575 (set_attr "predicable" "yes")]
9578 (define_insn "*strsi_shiftpredec"
9579 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9580 (match_operator:SI 2 "shift_operator"
9581 [(match_operand:SI 3 "s_register_operand" "r")
9582 (match_operand:SI 4 "const_shift_operand" "n")])))
9583 (match_operand:SI 5 "s_register_operand" "r"))
9584 (set (match_operand:SI 0 "s_register_operand" "=r")
9585 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9588 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9589 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9590 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9591 "str%?\\t%5, [%0, -%3%S2]!"
9592 [(set_attr "type" "store1")
9593 (set_attr "predicable" "yes")]
9596 (define_insn "*loadsi_shiftpreinc"
9597 [(set (match_operand:SI 5 "s_register_operand" "=r")
9598 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9599 [(match_operand:SI 3 "s_register_operand" "r")
9600 (match_operand:SI 4 "const_shift_operand" "n")])
9601 (match_operand:SI 1 "s_register_operand" "0"))))
9602 (set (match_operand:SI 0 "s_register_operand" "=r")
9603 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9606 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9607 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9608 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9609 "ldr%?\\t%5, [%0, %3%S2]!"
9610 [(set_attr "type" "load1")
9611 (set_attr "predicable" "yes")]
9614 (define_insn "*loadsi_shiftpredec"
9615 [(set (match_operand:SI 5 "s_register_operand" "=r")
9616 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9617 (match_operator:SI 2 "shift_operator"
9618 [(match_operand:SI 3 "s_register_operand" "r")
9619 (match_operand:SI 4 "const_shift_operand" "n")]))))
9620 (set (match_operand:SI 0 "s_register_operand" "=r")
9621 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9624 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9625 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9626 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9627 "ldr%?\\t%5, [%0, -%3%S2]!"
9628 [(set_attr "type" "load1")
9629 (set_attr "predicable" "yes")])
9631 ; It can also support extended post-inc expressions, but combine doesn't
9633 ; It doesn't seem worth adding peepholes for anything but the most common
9634 ; cases since, unlike combine, the increment must immediately follow the load
9635 ; for this pattern to match.
9636 ; We must watch to see that the source/destination register isn't also the
9637 ; same as the base address register, and that if the index is a register,
9638 ; that it is not the same as the base address register. In such cases the
9639 ; instruction that we would generate would have UNPREDICTABLE behavior so
9643 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9644 (match_operand:QI 2 "s_register_operand" "r"))
9646 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9648 && (REGNO (operands[2]) != REGNO (operands[0]))
9649 && (GET_CODE (operands[1]) != REG
9650 || (REGNO (operands[1]) != REGNO (operands[0])))"
9651 "str%?b\\t%2, [%0], %1"
9655 [(set (match_operand:QI 0 "s_register_operand" "=r")
9656 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9658 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9660 && REGNO (operands[0]) != REGNO(operands[1])
9661 && (GET_CODE (operands[2]) != REG
9662 || REGNO(operands[0]) != REGNO (operands[2]))"
9663 "ldr%?b\\t%0, [%1], %2"
9667 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9668 (match_operand:SI 2 "s_register_operand" "r"))
9670 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9672 && (REGNO (operands[2]) != REGNO (operands[0]))
9673 && (GET_CODE (operands[1]) != REG
9674 || (REGNO (operands[1]) != REGNO (operands[0])))"
9675 "str%?\\t%2, [%0], %1"
9679 [(set (match_operand:SI 0 "s_register_operand" "=r")
9680 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9682 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9684 && REGNO (operands[0]) != REGNO(operands[1])
9685 && (GET_CODE (operands[2]) != REG
9686 || REGNO(operands[0]) != REGNO (operands[2]))"
9687 "ldr%?\\t%0, [%1], %2"
9691 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9692 (match_operand:SI 1 "index_operand" "rJ")))
9693 (match_operand:QI 2 "s_register_operand" "r"))
9694 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9696 && (REGNO (operands[2]) != REGNO (operands[0]))
9697 && (GET_CODE (operands[1]) != REG
9698 || (REGNO (operands[1]) != REGNO (operands[0])))"
9699 "str%?b\\t%2, [%0, %1]!"
9703 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9704 [(match_operand:SI 0 "s_register_operand" "r")
9705 (match_operand:SI 1 "const_int_operand" "n")])
9706 (match_operand:SI 2 "s_register_operand" "+r")))
9707 (match_operand:QI 3 "s_register_operand" "r"))
9708 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9711 && (REGNO (operands[3]) != REGNO (operands[2]))
9712 && (REGNO (operands[0]) != REGNO (operands[2]))"
9713 "str%?b\\t%3, [%2, %0%S4]!"
9716 ; This pattern is never tried by combine, so do it as a peephole
9719 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9720 (match_operand:SI 1 "arm_general_register_operand" ""))
9721 (set (reg:CC CC_REGNUM)
9722 (compare:CC (match_dup 1) (const_int 0)))]
9724 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9725 (set (match_dup 0) (match_dup 1))])]
9729 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9730 ; reversed, check that the memory references aren't volatile.
9733 [(set (match_operand:SI 0 "s_register_operand" "=r")
9734 (match_operand:SI 4 "memory_operand" "m"))
9735 (set (match_operand:SI 1 "s_register_operand" "=r")
9736 (match_operand:SI 5 "memory_operand" "m"))
9737 (set (match_operand:SI 2 "s_register_operand" "=r")
9738 (match_operand:SI 6 "memory_operand" "m"))
9739 (set (match_operand:SI 3 "s_register_operand" "=r")
9740 (match_operand:SI 7 "memory_operand" "m"))]
9741 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9743 return emit_ldm_seq (operands, 4);
9748 [(set (match_operand:SI 0 "s_register_operand" "=r")
9749 (match_operand:SI 3 "memory_operand" "m"))
9750 (set (match_operand:SI 1 "s_register_operand" "=r")
9751 (match_operand:SI 4 "memory_operand" "m"))
9752 (set (match_operand:SI 2 "s_register_operand" "=r")
9753 (match_operand:SI 5 "memory_operand" "m"))]
9754 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9756 return emit_ldm_seq (operands, 3);
9761 [(set (match_operand:SI 0 "s_register_operand" "=r")
9762 (match_operand:SI 2 "memory_operand" "m"))
9763 (set (match_operand:SI 1 "s_register_operand" "=r")
9764 (match_operand:SI 3 "memory_operand" "m"))]
9765 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9767 return emit_ldm_seq (operands, 2);
9772 [(set (match_operand:SI 4 "memory_operand" "=m")
9773 (match_operand:SI 0 "s_register_operand" "r"))
9774 (set (match_operand:SI 5 "memory_operand" "=m")
9775 (match_operand:SI 1 "s_register_operand" "r"))
9776 (set (match_operand:SI 6 "memory_operand" "=m")
9777 (match_operand:SI 2 "s_register_operand" "r"))
9778 (set (match_operand:SI 7 "memory_operand" "=m")
9779 (match_operand:SI 3 "s_register_operand" "r"))]
9780 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9782 return emit_stm_seq (operands, 4);
9787 [(set (match_operand:SI 3 "memory_operand" "=m")
9788 (match_operand:SI 0 "s_register_operand" "r"))
9789 (set (match_operand:SI 4 "memory_operand" "=m")
9790 (match_operand:SI 1 "s_register_operand" "r"))
9791 (set (match_operand:SI 5 "memory_operand" "=m")
9792 (match_operand:SI 2 "s_register_operand" "r"))]
9793 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9795 return emit_stm_seq (operands, 3);
9800 [(set (match_operand:SI 2 "memory_operand" "=m")
9801 (match_operand:SI 0 "s_register_operand" "r"))
9802 (set (match_operand:SI 3 "memory_operand" "=m")
9803 (match_operand:SI 1 "s_register_operand" "r"))]
9804 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9806 return emit_stm_seq (operands, 2);
9811 [(set (match_operand:SI 0 "s_register_operand" "")
9812 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9814 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9815 [(match_operand:SI 3 "s_register_operand" "")
9816 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9817 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9819 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9820 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9825 ;; This split can be used because CC_Z mode implies that the following
9826 ;; branch will be an equality, or an unsigned inequality, so the sign
9827 ;; extension is not needed.
9830 [(set (reg:CC_Z CC_REGNUM)
9832 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9834 (match_operand 1 "const_int_operand" "")))
9835 (clobber (match_scratch:SI 2 ""))]
9837 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9838 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9839 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9840 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9842 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9846 (define_expand "prologue"
9847 [(clobber (const_int 0))]
9850 arm_expand_prologue ();
9852 thumb_expand_prologue ();
9857 (define_expand "epilogue"
9858 [(clobber (const_int 0))]
9861 if (current_function_calls_eh_return)
9862 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9864 thumb_expand_epilogue ();
9865 else if (USE_RETURN_INSN (FALSE))
9867 emit_jump_insn (gen_return ());
9870 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9872 gen_rtx_RETURN (VOIDmode)),
9878 ;; Note - although unspec_volatile's USE all hard registers,
9879 ;; USEs are ignored after relaod has completed. Thus we need
9880 ;; to add an unspec of the link register to ensure that flow
9881 ;; does not think that it is unused by the sibcall branch that
9882 ;; will replace the standard function epilogue.
9883 (define_insn "sibcall_epilogue"
9884 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9885 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9888 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9889 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9890 return arm_output_epilogue (next_nonnote_insn (insn));
9892 ;; Length is absolute worst case
9893 [(set_attr "length" "44")
9894 (set_attr "type" "block")
9895 ;; We don't clobber the conditions, but the potential length of this
9896 ;; operation is sufficient to make conditionalizing the sequence
9897 ;; unlikely to be profitable.
9898 (set_attr "conds" "clob")]
9901 (define_insn "*epilogue_insns"
9902 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9906 return arm_output_epilogue (NULL);
9907 else /* TARGET_THUMB */
9908 return thumb_unexpanded_epilogue ();
9910 ; Length is absolute worst case
9911 [(set_attr "length" "44")
9912 (set_attr "type" "block")
9913 ;; We don't clobber the conditions, but the potential length of this
9914 ;; operation is sufficient to make conditionalizing the sequence
9915 ;; unlikely to be profitable.
9916 (set_attr "conds" "clob")]
9919 (define_expand "eh_epilogue"
9920 [(use (match_operand:SI 0 "register_operand" ""))
9921 (use (match_operand:SI 1 "register_operand" ""))
9922 (use (match_operand:SI 2 "register_operand" ""))]
9926 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9927 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9929 rtx ra = gen_rtx_REG (Pmode, 2);
9931 emit_move_insn (ra, operands[2]);
9934 /* This is a hack -- we may have crystalized the function type too
9936 cfun->machine->func_type = 0;
9940 ;; This split is only used during output to reduce the number of patterns
9941 ;; that need assembler instructions adding to them. We allowed the setting
9942 ;; of the conditions to be implicit during rtl generation so that
9943 ;; the conditional compare patterns would work. However this conflicts to
9944 ;; some extent with the conditional data operations, so we have to split them
9948 [(set (match_operand:SI 0 "s_register_operand" "")
9949 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9950 [(match_operand 2 "" "") (match_operand 3 "" "")])
9952 (match_operand 4 "" "")))
9953 (clobber (reg:CC CC_REGNUM))]
9954 "TARGET_ARM && reload_completed"
9955 [(set (match_dup 5) (match_dup 6))
9956 (cond_exec (match_dup 7)
9957 (set (match_dup 0) (match_dup 4)))]
9960 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9961 operands[2], operands[3]);
9962 enum rtx_code rc = GET_CODE (operands[1]);
9964 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9965 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9966 if (mode == CCFPmode || mode == CCFPEmode)
9967 rc = reverse_condition_maybe_unordered (rc);
9969 rc = reverse_condition (rc);
9971 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9976 [(set (match_operand:SI 0 "s_register_operand" "")
9977 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9978 [(match_operand 2 "" "") (match_operand 3 "" "")])
9979 (match_operand 4 "" "")
9981 (clobber (reg:CC CC_REGNUM))]
9982 "TARGET_ARM && reload_completed"
9983 [(set (match_dup 5) (match_dup 6))
9984 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9985 (set (match_dup 0) (match_dup 4)))]
9988 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9989 operands[2], operands[3]);
9991 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9992 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9997 [(set (match_operand:SI 0 "s_register_operand" "")
9998 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9999 [(match_operand 2 "" "") (match_operand 3 "" "")])
10000 (match_operand 4 "" "")
10001 (match_operand 5 "" "")))
10002 (clobber (reg:CC CC_REGNUM))]
10003 "TARGET_ARM && reload_completed"
10004 [(set (match_dup 6) (match_dup 7))
10005 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10006 (set (match_dup 0) (match_dup 4)))
10007 (cond_exec (match_dup 8)
10008 (set (match_dup 0) (match_dup 5)))]
10011 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10012 operands[2], operands[3]);
10013 enum rtx_code rc = GET_CODE (operands[1]);
10015 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10016 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10017 if (mode == CCFPmode || mode == CCFPEmode)
10018 rc = reverse_condition_maybe_unordered (rc);
10020 rc = reverse_condition (rc);
10022 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10027 [(set (match_operand:SI 0 "s_register_operand" "")
10028 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10029 [(match_operand:SI 2 "s_register_operand" "")
10030 (match_operand:SI 3 "arm_add_operand" "")])
10031 (match_operand:SI 4 "arm_rhs_operand" "")
10033 (match_operand:SI 5 "s_register_operand" ""))))
10034 (clobber (reg:CC CC_REGNUM))]
10035 "TARGET_ARM && reload_completed"
10036 [(set (match_dup 6) (match_dup 7))
10037 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10038 (set (match_dup 0) (match_dup 4)))
10039 (cond_exec (match_dup 8)
10040 (set (match_dup 0) (not:SI (match_dup 5))))]
10043 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10044 operands[2], operands[3]);
10045 enum rtx_code rc = GET_CODE (operands[1]);
10047 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10048 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10049 if (mode == CCFPmode || mode == CCFPEmode)
10050 rc = reverse_condition_maybe_unordered (rc);
10052 rc = reverse_condition (rc);
10054 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10058 (define_insn "*cond_move_not"
10059 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10060 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10061 [(match_operand 3 "cc_register" "") (const_int 0)])
10062 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10064 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10068 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10069 [(set_attr "conds" "use")
10070 (set_attr "length" "4,8")]
10073 ;; The next two patterns occur when an AND operation is followed by a
10074 ;; scc insn sequence
10076 (define_insn "*sign_extract_onebit"
10077 [(set (match_operand:SI 0 "s_register_operand" "=r")
10078 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10080 (match_operand:SI 2 "const_int_operand" "n")))
10081 (clobber (reg:CC CC_REGNUM))]
10084 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10085 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10086 return \"mvnne\\t%0, #0\";
10088 [(set_attr "conds" "clob")
10089 (set_attr "length" "8")]
10092 (define_insn "*not_signextract_onebit"
10093 [(set (match_operand:SI 0 "s_register_operand" "=r")
10095 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10097 (match_operand:SI 2 "const_int_operand" "n"))))
10098 (clobber (reg:CC CC_REGNUM))]
10101 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10102 output_asm_insn (\"tst\\t%1, %2\", operands);
10103 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10104 return \"movne\\t%0, #0\";
10106 [(set_attr "conds" "clob")
10107 (set_attr "length" "12")]
10110 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10111 ;; expressions. For simplicity, the first register is also in the unspec
10113 (define_insn "*push_multi"
10114 [(match_parallel 2 "multi_register_push"
10115 [(set (match_operand:BLK 0 "memory_operand" "=m")
10116 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10117 UNSPEC_PUSH_MULT))])]
10121 int num_saves = XVECLEN (operands[2], 0);
10123 /* For the StrongARM at least it is faster to
10124 use STR to store only a single register. */
10125 if (num_saves == 1)
10126 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10132 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10134 for (i = 1; i < num_saves; i++)
10136 strcat (pattern, \", %|\");
10138 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10141 strcat (pattern, \"}\");
10142 output_asm_insn (pattern, operands);
10147 [(set_attr "type" "store4")]
10150 (define_insn "stack_tie"
10151 [(set (mem:BLK (scratch))
10152 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10153 (match_operand:SI 1 "s_register_operand" "r")]
10157 [(set_attr "length" "0")]
10160 ;; Similarly for the floating point registers
10161 (define_insn "*push_fp_multi"
10162 [(match_parallel 2 "multi_register_push"
10163 [(set (match_operand:BLK 0 "memory_operand" "=m")
10164 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10165 UNSPEC_PUSH_MULT))])]
10166 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10171 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10172 output_asm_insn (pattern, operands);
10175 [(set_attr "type" "f_store")]
10178 ;; Special patterns for dealing with the constant pool
10180 (define_insn "align_4"
10181 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10184 assemble_align (32);
10189 (define_insn "align_8"
10190 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10193 assemble_align (64);
10198 (define_insn "consttable_end"
10199 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10202 making_const_table = FALSE;
10207 (define_insn "consttable_1"
10208 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10211 making_const_table = TRUE;
10212 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10213 assemble_zeros (3);
10216 [(set_attr "length" "4")]
10219 (define_insn "consttable_2"
10220 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10223 making_const_table = TRUE;
10224 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10225 assemble_zeros (2);
10228 [(set_attr "length" "4")]
10231 (define_insn "consttable_4"
10232 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10236 making_const_table = TRUE;
10237 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10242 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10243 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10247 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10252 [(set_attr "length" "4")]
10255 (define_insn "consttable_8"
10256 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10260 making_const_table = TRUE;
10261 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10266 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10267 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10271 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10276 [(set_attr "length" "8")]
10279 ;; Miscellaneous Thumb patterns
10281 (define_expand "tablejump"
10282 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10283 (use (label_ref (match_operand 1 "" "")))])]
10288 /* Hopefully, CSE will eliminate this copy. */
10289 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10290 rtx reg2 = gen_reg_rtx (SImode);
10292 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10293 operands[0] = reg2;
10298 ;; NB never uses BX.
10299 (define_insn "*thumb_tablejump"
10300 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10301 (use (label_ref (match_operand 1 "" "")))]
10304 [(set_attr "length" "2")]
10307 ;; V5 Instructions,
10309 (define_insn "clzsi2"
10310 [(set (match_operand:SI 0 "s_register_operand" "=r")
10311 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10312 "TARGET_ARM && arm_arch5"
10314 [(set_attr "predicable" "yes")])
10316 (define_expand "ffssi2"
10317 [(set (match_operand:SI 0 "s_register_operand" "")
10318 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10319 "TARGET_ARM && arm_arch5"
10324 t1 = gen_reg_rtx (SImode);
10325 t2 = gen_reg_rtx (SImode);
10326 t3 = gen_reg_rtx (SImode);
10328 emit_insn (gen_negsi2 (t1, operands[1]));
10329 emit_insn (gen_andsi3 (t2, operands[1], t1));
10330 emit_insn (gen_clzsi2 (t3, t2));
10331 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10336 (define_expand "ctzsi2"
10337 [(set (match_operand:SI 0 "s_register_operand" "")
10338 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10339 "TARGET_ARM && arm_arch5"
10344 t1 = gen_reg_rtx (SImode);
10345 t2 = gen_reg_rtx (SImode);
10346 t3 = gen_reg_rtx (SImode);
10348 emit_insn (gen_negsi2 (t1, operands[1]));
10349 emit_insn (gen_andsi3 (t2, operands[1], t1));
10350 emit_insn (gen_clzsi2 (t3, t2));
10351 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10356 ;; V5E instructions.
10358 (define_insn "prefetch"
10359 [(prefetch (match_operand:SI 0 "address_operand" "p")
10360 (match_operand:SI 1 "" "")
10361 (match_operand:SI 2 "" ""))]
10362 "TARGET_ARM && arm_arch5e"
10365 ;; General predication pattern
10368 [(match_operator 0 "arm_comparison_operator"
10369 [(match_operand 1 "cc_register" "")
10375 (define_insn "prologue_use"
10376 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10378 "%@ %0 needed for prologue"
10382 ;; Patterns for exception handling
10384 (define_expand "eh_return"
10385 [(use (match_operand 0 "general_operand" ""))]
10390 emit_insn (gen_arm_eh_return (operands[0]));
10392 emit_insn (gen_thumb_eh_return (operands[0]));
10397 ;; We can't expand this before we know where the link register is stored.
10398 (define_insn_and_split "arm_eh_return"
10399 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10401 (clobber (match_scratch:SI 1 "=&r"))]
10404 "&& reload_completed"
10408 arm_set_return_address (operands[0], operands[1]);
10413 (define_insn_and_split "thumb_eh_return"
10414 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10416 (clobber (match_scratch:SI 1 "=&l"))]
10419 "&& reload_completed"
10423 thumb_set_return_address (operands[0], operands[1]);
10428 ;; Load the FPA co-processor patterns
10430 ;; Load the Maverick co-processor patterns
10431 (include "cirrus.md")
10432 ;; Load the Intel Wireless Multimedia Extension patterns
10433 (include "iwmmxt.md")
10434 ;; Load the VFP co-processor patterns