1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
44 ;; 3rd operand to select_dominance_cc_mode
53 ;; Note: sin and cos are no-longer used.
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
97 ;; UNSPEC_VOLATILE Usage:
100 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
102 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
103 ; instruction epilogue sequence that isn't expanded
104 ; into normal RTL. Used for both normal and sibcall
106 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
107 ; for inlined constants.
108 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
110 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
112 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
114 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
116 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
118 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
119 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
120 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
121 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
122 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
123 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
124 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
129 ;;---------------------------------------------------------------------------
132 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
133 ; generating ARM code. This is used to control the length of some insn
134 ; patterns that share the same RTL in both ARM and Thumb code.
135 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
137 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
138 ; scheduling decisions for the load unit and the multiplier.
139 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
141 ; IS_XSCALE is set to 'yes' when compiling for XScale.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
144 ;; Operand number of an input operand that is shifted. Zero if the
145 ;; given instruction does not shift one of its input operands.
146 (define_attr "shift" "" (const_int 0))
148 ; Floating Point Unit. If we only have floating point emulation, then there
149 ; is no point in scheduling the floating point insns. (Well, for best
150 ; performance we should try and group them together).
151 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
152 (const (symbol_ref "arm_fpu_attr")))
154 ; LENGTH of an instruction (in bytes)
155 (define_attr "length" "" (const_int 4))
157 ; POOL_RANGE is how far away from a constant pool entry that this insn
158 ; can be placed. If the distance is zero, then this insn will never
159 ; reference the pool.
160 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
161 ; before its address.
162 (define_attr "pool_range" "" (const_int 0))
163 (define_attr "neg_pool_range" "" (const_int 0))
165 ; An assembler sequence may clobber the condition codes without us knowing.
166 ; If such an insn references the pool, then we have no way of knowing how,
167 ; so use the most conservative value for pool_range.
168 (define_asm_attributes
169 [(set_attr "conds" "clob")
170 (set_attr "length" "4")
171 (set_attr "pool_range" "250")])
173 ;; The instruction used to implement a particular pattern. This
174 ;; information is used by pipeline descriptions to provide accurate
175 ;; scheduling information.
178 "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"
179 (const_string "other"))
181 ; TYPE attribute is used to detect floating point instructions which, if
182 ; running on a co-processor can run in parallel with other, basic instructions
183 ; If write-buffer scheduling is enabled then it can also be used in the
184 ; scheduling of writes.
186 ; Classification of each insn
187 ; alu any alu instruction that doesn't hit memory or fp
188 ; regs or have a shifted source operand
189 ; alu_shift any data instruction that doesn't hit memory or fp
190 ; regs, but has a source operand shifted by a constant
191 ; alu_shift_reg any data instruction that doesn't hit memory or fp
192 ; regs, but has a source operand shifted by a register value
193 ; mult a multiply instruction
194 ; block blockage insn, this blocks all functional units
195 ; float a floating point arithmetic operation (subject to expansion)
196 ; fdivd DFmode floating point division
197 ; fdivs SFmode floating point division
198 ; fmul Floating point multiply
199 ; ffmul Fast floating point multiply
200 ; farith Floating point arithmetic (4 cycle)
201 ; ffarith Fast floating point arithmetic (2 cycle)
202 ; float_em a floating point arithmetic operation that is normally emulated
203 ; even on a machine with an fpa.
204 ; f_load a floating point load from memory
205 ; f_store a floating point store to memory
206 ; f_load[sd] single/double load from memory
207 ; f_store[sd] single/double store to memory
208 ; f_flag a transfer of co-processor flags to the CPSR
209 ; f_mem_r a transfer of a floating point register to a real reg via mem
210 ; r_mem_f the reverse of f_mem_r
211 ; f_2_r fast transfer float to arm (no memory needed)
212 ; r_2_f fast transfer arm to float
213 ; f_cvt convert floating<->integral
215 ; call a subroutine call
216 ; load_byte load byte(s) from memory to arm registers
217 ; load1 load 1 word from memory to arm registers
218 ; load2 load 2 words from memory to arm registers
219 ; load3 load 3 words from memory to arm registers
220 ; load4 load 4 words from memory to arm registers
221 ; store store 1 word to memory from arm registers
222 ; store2 store 2 words
223 ; store3 store 3 words
224 ; store4 store 4 (or more) words
225 ; Additions for Cirrus Maverick co-processor:
226 ; mav_farith Floating point arithmetic (4 cycle)
227 ; mav_dmult Double multiplies (7 cycle)
230 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
232 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
233 (const_string "mult")
234 (const_string "alu")))
236 ; Load scheduling, set from the arm_ld_sched variable
237 ; initialized by arm_override_options()
238 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
240 ; condition codes: this one is used by final_prescan_insn to speed up
241 ; conditionalizing instructions. It saves having to scan the rtl to see if
242 ; it uses or alters the condition codes.
244 ; USE means that the condition codes are used by the insn in the process of
245 ; outputting code, this means (at present) that we can't use the insn in
248 ; SET means that the purpose of the insn is to set the condition codes in a
249 ; well defined manner.
251 ; CLOB means that the condition codes are altered in an undefined manner, if
252 ; they are altered at all
254 ; JUMP_CLOB is used when the condition cannot be represented by a single
255 ; instruction (UNEQ and LTGT). These cannot be predicated.
257 ; NOCOND means that the condition codes are neither altered nor affect the
258 ; output of this insn
260 (define_attr "conds" "use,set,clob,jump_clob,nocond"
261 (if_then_else (eq_attr "type" "call")
262 (const_string "clob")
263 (const_string "nocond")))
265 ; Predicable means that the insn can be conditionally executed based on
266 ; an automatically added predicate (additional patterns are generated by
267 ; gen...). We default to 'no' because no Thumb patterns match this rule
268 ; and not all ARM patterns do.
269 (define_attr "predicable" "no,yes" (const_string "no"))
271 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
272 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
273 ; suffer blockages enough to warrant modelling this (and it can adversely
274 ; affect the schedule).
275 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
277 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
278 ; to stall the processor. Used with model_wbuf above.
279 (define_attr "write_conflict" "no,yes"
280 (if_then_else (eq_attr "type"
281 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
283 (const_string "no")))
285 ; Classify the insns into those that take one cycle and those that take more
286 ; than one on the main cpu execution unit.
287 (define_attr "core_cycles" "single,multi"
288 (if_then_else (eq_attr "type"
289 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
290 (const_string "single")
291 (const_string "multi")))
293 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
294 ;; distant label. Only applicable to Thumb code.
295 (define_attr "far_jump" "yes,no" (const_string "no"))
298 ;;---------------------------------------------------------------------------
301 ; A list of modes that are exactly 64 bits in size. We use this to expand
302 ; some splits that are the same for all modes when operating on ARM
304 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
306 ;;---------------------------------------------------------------------------
309 (include "predicates.md")
311 ;;---------------------------------------------------------------------------
312 ;; Pipeline descriptions
314 ;; Processor type. This is created automatically from arm-cores.def.
315 (include "arm-tune.md")
317 ;; True if the generic scheduling description should be used.
319 (define_attr "generic_sched" "yes,no"
321 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
323 (const_string "yes"))))
325 (define_attr "generic_vfp" "yes,no"
327 (and (eq_attr "fpu" "vfp")
328 (eq_attr "tune" "!arm1020e,arm1022e"))
330 (const_string "no"))))
332 (include "arm-generic.md")
333 (include "arm926ejs.md")
334 (include "arm1020e.md")
335 (include "arm1026ejs.md")
336 (include "arm1136jfs.md")
339 ;;---------------------------------------------------------------------------
344 ;; Note: For DImode insns, there is normally no reason why operands should
345 ;; not be in the same register, what we don't want is for something being
346 ;; written to partially overlap something that is an input.
347 ;; Cirrus 64bit additions should not be split because we have a native
348 ;; 64bit addition instructions.
350 (define_expand "adddi3"
352 [(set (match_operand:DI 0 "s_register_operand" "")
353 (plus:DI (match_operand:DI 1 "s_register_operand" "")
354 (match_operand:DI 2 "s_register_operand" "")))
355 (clobber (reg:CC CC_REGNUM))])]
358 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
360 if (!cirrus_fp_register (operands[0], DImode))
361 operands[0] = force_reg (DImode, operands[0]);
362 if (!cirrus_fp_register (operands[1], DImode))
363 operands[1] = force_reg (DImode, operands[1]);
364 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
370 if (GET_CODE (operands[1]) != REG)
371 operands[1] = force_reg (SImode, operands[1]);
372 if (GET_CODE (operands[2]) != REG)
373 operands[2] = force_reg (SImode, operands[2]);
378 (define_insn "*thumb_adddi3"
379 [(set (match_operand:DI 0 "register_operand" "=l")
380 (plus:DI (match_operand:DI 1 "register_operand" "%0")
381 (match_operand:DI 2 "register_operand" "l")))
382 (clobber (reg:CC CC_REGNUM))
385 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
386 [(set_attr "length" "4")]
389 (define_insn_and_split "*arm_adddi3"
390 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
391 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
392 (match_operand:DI 2 "s_register_operand" "r, 0")))
393 (clobber (reg:CC CC_REGNUM))]
394 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
396 "TARGET_ARM && reload_completed"
397 [(parallel [(set (reg:CC_C CC_REGNUM)
398 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
400 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
401 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
402 (plus:SI (match_dup 4) (match_dup 5))))]
405 operands[3] = gen_highpart (SImode, operands[0]);
406 operands[0] = gen_lowpart (SImode, operands[0]);
407 operands[4] = gen_highpart (SImode, operands[1]);
408 operands[1] = gen_lowpart (SImode, operands[1]);
409 operands[5] = gen_highpart (SImode, operands[2]);
410 operands[2] = gen_lowpart (SImode, operands[2]);
412 [(set_attr "conds" "clob")
413 (set_attr "length" "8")]
416 (define_insn_and_split "*adddi_sesidi_di"
417 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418 (plus:DI (sign_extend:DI
419 (match_operand:SI 2 "s_register_operand" "r,r"))
420 (match_operand:DI 1 "s_register_operand" "r,0")))
421 (clobber (reg:CC CC_REGNUM))]
422 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
424 "TARGET_ARM && reload_completed"
425 [(parallel [(set (reg:CC_C CC_REGNUM)
426 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
428 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430 (plus:SI (ashiftrt:SI (match_dup 2)
435 operands[3] = gen_highpart (SImode, operands[0]);
436 operands[0] = gen_lowpart (SImode, operands[0]);
437 operands[4] = gen_highpart (SImode, operands[1]);
438 operands[1] = gen_lowpart (SImode, operands[1]);
439 operands[2] = gen_lowpart (SImode, operands[2]);
441 [(set_attr "conds" "clob")
442 (set_attr "length" "8")]
445 (define_insn_and_split "*adddi_zesidi_di"
446 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
447 (plus:DI (zero_extend:DI
448 (match_operand:SI 2 "s_register_operand" "r,r"))
449 (match_operand:DI 1 "s_register_operand" "r,0")))
450 (clobber (reg:CC CC_REGNUM))]
451 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
453 "TARGET_ARM && reload_completed"
454 [(parallel [(set (reg:CC_C CC_REGNUM)
455 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
457 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
458 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
459 (plus:SI (match_dup 4) (const_int 0))))]
462 operands[3] = gen_highpart (SImode, operands[0]);
463 operands[0] = gen_lowpart (SImode, operands[0]);
464 operands[4] = gen_highpart (SImode, operands[1]);
465 operands[1] = gen_lowpart (SImode, operands[1]);
466 operands[2] = gen_lowpart (SImode, operands[2]);
468 [(set_attr "conds" "clob")
469 (set_attr "length" "8")]
472 (define_expand "addsi3"
473 [(set (match_operand:SI 0 "s_register_operand" "")
474 (plus:SI (match_operand:SI 1 "s_register_operand" "")
475 (match_operand:SI 2 "reg_or_int_operand" "")))]
478 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
480 arm_split_constant (PLUS, SImode, NULL_RTX,
481 INTVAL (operands[2]), operands[0], operands[1],
482 optimize && !no_new_pseudos);
488 ; If there is a scratch available, this will be faster than synthesizing the
491 [(match_scratch:SI 3 "r")
492 (set (match_operand:SI 0 "arm_general_register_operand" "")
493 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
494 (match_operand:SI 2 "const_int_operand" "")))]
496 !(const_ok_for_arm (INTVAL (operands[2]))
497 || const_ok_for_arm (-INTVAL (operands[2])))
498 && const_ok_for_arm (~INTVAL (operands[2]))"
499 [(set (match_dup 3) (match_dup 2))
500 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
504 (define_insn_and_split "*arm_addsi3"
505 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
506 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
507 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
514 GET_CODE (operands[2]) == CONST_INT
515 && !(const_ok_for_arm (INTVAL (operands[2]))
516 || const_ok_for_arm (-INTVAL (operands[2])))"
517 [(clobber (const_int 0))]
519 arm_split_constant (PLUS, SImode, curr_insn,
520 INTVAL (operands[2]), operands[0],
524 [(set_attr "length" "4,4,16")
525 (set_attr "predicable" "yes")]
528 ;; Register group 'k' is a single register group containing only the stack
529 ;; register. Trying to reload it will always fail catastrophically,
530 ;; so never allow those alternatives to match if reloading is needed.
532 (define_insn "*thumb_addsi3"
533 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
534 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
535 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538 static const char * const asms[] =
540 \"add\\t%0, %0, %2\",
541 \"sub\\t%0, %0, #%n2\",
542 \"add\\t%0, %1, %2\",
543 \"add\\t%0, %0, %2\",
544 \"add\\t%0, %0, %2\",
545 \"add\\t%0, %1, %2\",
548 if ((which_alternative == 2 || which_alternative == 6)
549 && GET_CODE (operands[2]) == CONST_INT
550 && INTVAL (operands[2]) < 0)
551 return \"sub\\t%0, %1, #%n2\";
552 return asms[which_alternative];
554 [(set_attr "length" "2")]
557 ;; Reloading and elimination of the frame pointer can
558 ;; sometimes cause this optimization to be missed.
560 [(set (match_operand:SI 0 "arm_general_register_operand" "")
561 (match_operand:SI 1 "const_int_operand" ""))
563 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
565 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
566 && (INTVAL (operands[1]) & 3) == 0"
567 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
571 (define_insn "*addsi3_compare0"
572 [(set (reg:CC_NOOV CC_REGNUM)
574 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
575 (match_operand:SI 2 "arm_add_operand" "rI,L"))
577 (set (match_operand:SI 0 "s_register_operand" "=r,r")
578 (plus:SI (match_dup 1) (match_dup 2)))]
582 sub%?s\\t%0, %1, #%n2"
583 [(set_attr "conds" "set")]
586 (define_insn "*addsi3_compare0_scratch"
587 [(set (reg:CC_NOOV CC_REGNUM)
589 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
590 (match_operand:SI 1 "arm_add_operand" "rI,L"))
596 [(set_attr "conds" "set")]
599 (define_insn "*compare_negsi_si"
600 [(set (reg:CC_Z CC_REGNUM)
602 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
603 (match_operand:SI 1 "s_register_operand" "r")))]
606 [(set_attr "conds" "set")]
609 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
610 ;; addend is a constant.
611 (define_insn "*cmpsi2_addneg"
612 [(set (reg:CC CC_REGNUM)
614 (match_operand:SI 1 "s_register_operand" "r,r")
615 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
616 (set (match_operand:SI 0 "s_register_operand" "=r,r")
617 (plus:SI (match_dup 1)
618 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
619 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622 add%?s\\t%0, %1, #%n2"
623 [(set_attr "conds" "set")]
626 ;; Convert the sequence
628 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
632 ;; bcs dest ((unsigned)rn >= 1)
633 ;; similarly for the beq variant using bcc.
634 ;; This is a common looping idiom (while (n--))
636 [(set (match_operand:SI 0 "arm_general_register_operand" "")
637 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
639 (set (match_operand 2 "cc_register" "")
640 (compare (match_dup 0) (const_int -1)))
642 (if_then_else (match_operator 3 "equality_operator"
643 [(match_dup 2) (const_int 0)])
644 (match_operand 4 "" "")
645 (match_operand 5 "" "")))]
646 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
650 (match_dup 1) (const_int 1)))
651 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
653 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
657 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660 operands[2], const0_rtx);"
663 ;; The next four insns work because they compare the result with one of
664 ;; the operands, and we know that the use of the condition code is
665 ;; either GEU or LTU, so we can use the carry flag from the addition
666 ;; instead of doing the compare a second time.
667 (define_insn "*addsi3_compare_op1"
668 [(set (reg:CC_C CC_REGNUM)
670 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
671 (match_operand:SI 2 "arm_add_operand" "rI,L"))
673 (set (match_operand:SI 0 "s_register_operand" "=r,r")
674 (plus:SI (match_dup 1) (match_dup 2)))]
678 sub%?s\\t%0, %1, #%n2"
679 [(set_attr "conds" "set")]
682 (define_insn "*addsi3_compare_op2"
683 [(set (reg:CC_C CC_REGNUM)
685 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
686 (match_operand:SI 2 "arm_add_operand" "rI,L"))
688 (set (match_operand:SI 0 "s_register_operand" "=r,r")
689 (plus:SI (match_dup 1) (match_dup 2)))]
693 sub%?s\\t%0, %1, #%n2"
694 [(set_attr "conds" "set")]
697 (define_insn "*compare_addsi2_op0"
698 [(set (reg:CC_C CC_REGNUM)
700 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
701 (match_operand:SI 1 "arm_add_operand" "rI,L"))
707 [(set_attr "conds" "set")]
710 (define_insn "*compare_addsi2_op1"
711 [(set (reg:CC_C CC_REGNUM)
713 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
714 (match_operand:SI 1 "arm_add_operand" "rI,L"))
720 [(set_attr "conds" "set")]
723 (define_insn "*addsi3_carryin"
724 [(set (match_operand:SI 0 "s_register_operand" "=r")
725 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
727 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730 [(set_attr "conds" "use")]
733 (define_insn "*addsi3_carryin_shift"
734 [(set (match_operand:SI 0 "s_register_operand" "=r")
735 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
737 (match_operator:SI 2 "shift_operator"
738 [(match_operand:SI 3 "s_register_operand" "r")
739 (match_operand:SI 4 "reg_or_int_operand" "rM")])
740 (match_operand:SI 1 "s_register_operand" "r"))))]
742 "adc%?\\t%0, %1, %3%S2"
743 [(set_attr "conds" "use")
744 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
745 (const_string "alu_shift")
746 (const_string "alu_shift_reg")))]
749 (define_insn "*addsi3_carryin_alt1"
750 [(set (match_operand:SI 0 "s_register_operand" "=r")
751 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
752 (match_operand:SI 2 "arm_rhs_operand" "rI"))
753 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756 [(set_attr "conds" "use")]
759 (define_insn "*addsi3_carryin_alt2"
760 [(set (match_operand:SI 0 "s_register_operand" "=r")
761 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
762 (match_operand:SI 1 "s_register_operand" "r"))
763 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766 [(set_attr "conds" "use")]
769 (define_insn "*addsi3_carryin_alt3"
770 [(set (match_operand:SI 0 "s_register_operand" "=r")
771 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
772 (match_operand:SI 2 "arm_rhs_operand" "rI"))
773 (match_operand:SI 1 "s_register_operand" "r")))]
776 [(set_attr "conds" "use")]
779 (define_insn "incscc"
780 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
781 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
782 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
783 (match_operand:SI 1 "s_register_operand" "0,?r")))]
787 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
788 [(set_attr "conds" "use")
789 (set_attr "length" "4,8")]
792 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
794 [(set (match_operand:SI 0 "s_register_operand" "")
795 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
796 (match_operand:SI 2 "s_register_operand" ""))
798 (clobber (match_operand:SI 3 "s_register_operand" ""))]
800 [(set (match_dup 3) (match_dup 1))
801 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
803 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806 (define_expand "addsf3"
807 [(set (match_operand:SF 0 "s_register_operand" "")
808 (plus:SF (match_operand:SF 1 "s_register_operand" "")
809 (match_operand:SF 2 "arm_float_add_operand" "")))]
810 "TARGET_ARM && TARGET_HARD_FLOAT"
813 && !cirrus_fp_register (operands[2], SFmode))
814 operands[2] = force_reg (SFmode, operands[2]);
817 (define_expand "adddf3"
818 [(set (match_operand:DF 0 "s_register_operand" "")
819 (plus:DF (match_operand:DF 1 "s_register_operand" "")
820 (match_operand:DF 2 "arm_float_add_operand" "")))]
821 "TARGET_ARM && TARGET_HARD_FLOAT"
824 && !cirrus_fp_register (operands[2], DFmode))
825 operands[2] = force_reg (DFmode, operands[2]);
828 (define_expand "subdi3"
830 [(set (match_operand:DI 0 "s_register_operand" "")
831 (minus:DI (match_operand:DI 1 "s_register_operand" "")
832 (match_operand:DI 2 "s_register_operand" "")))
833 (clobber (reg:CC CC_REGNUM))])]
836 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
838 && cirrus_fp_register (operands[0], DImode)
839 && cirrus_fp_register (operands[1], DImode))
841 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
847 if (GET_CODE (operands[1]) != REG)
848 operands[1] = force_reg (SImode, operands[1]);
849 if (GET_CODE (operands[2]) != REG)
850 operands[2] = force_reg (SImode, operands[2]);
855 (define_insn "*arm_subdi3"
856 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
857 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
858 (match_operand:DI 2 "s_register_operand" "r,0,0")))
859 (clobber (reg:CC CC_REGNUM))]
861 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
862 [(set_attr "conds" "clob")
863 (set_attr "length" "8")]
866 (define_insn "*thumb_subdi3"
867 [(set (match_operand:DI 0 "register_operand" "=l")
868 (minus:DI (match_operand:DI 1 "register_operand" "0")
869 (match_operand:DI 2 "register_operand" "l")))
870 (clobber (reg:CC CC_REGNUM))]
872 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
873 [(set_attr "length" "4")]
876 (define_insn "*subdi_di_zesidi"
877 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
878 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
880 (match_operand:SI 2 "s_register_operand" "r,r"))))
881 (clobber (reg:CC CC_REGNUM))]
883 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
884 [(set_attr "conds" "clob")
885 (set_attr "length" "8")]
888 (define_insn "*subdi_di_sesidi"
889 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
890 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
892 (match_operand:SI 2 "s_register_operand" "r,r"))))
893 (clobber (reg:CC CC_REGNUM))]
895 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
896 [(set_attr "conds" "clob")
897 (set_attr "length" "8")]
900 (define_insn "*subdi_zesidi_di"
901 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
902 (minus:DI (zero_extend:DI
903 (match_operand:SI 2 "s_register_operand" "r,r"))
904 (match_operand:DI 1 "s_register_operand" "?r,0")))
905 (clobber (reg:CC CC_REGNUM))]
907 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
908 [(set_attr "conds" "clob")
909 (set_attr "length" "8")]
912 (define_insn "*subdi_sesidi_di"
913 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
914 (minus:DI (sign_extend:DI
915 (match_operand:SI 2 "s_register_operand" "r,r"))
916 (match_operand:DI 1 "s_register_operand" "?r,0")))
917 (clobber (reg:CC CC_REGNUM))]
919 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
920 [(set_attr "conds" "clob")
921 (set_attr "length" "8")]
924 (define_insn "*subdi_zesidi_zesidi"
925 [(set (match_operand:DI 0 "s_register_operand" "=r")
926 (minus:DI (zero_extend:DI
927 (match_operand:SI 1 "s_register_operand" "r"))
929 (match_operand:SI 2 "s_register_operand" "r"))))
930 (clobber (reg:CC CC_REGNUM))]
932 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
933 [(set_attr "conds" "clob")
934 (set_attr "length" "8")]
937 (define_expand "subsi3"
938 [(set (match_operand:SI 0 "s_register_operand" "")
939 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
940 (match_operand:SI 2 "s_register_operand" "")))]
943 if (GET_CODE (operands[1]) == CONST_INT)
947 arm_split_constant (MINUS, SImode, NULL_RTX,
948 INTVAL (operands[1]), operands[0],
949 operands[2], optimize && !no_new_pseudos);
952 else /* TARGET_THUMB */
953 operands[1] = force_reg (SImode, operands[1]);
958 (define_insn "*thumb_subsi3_insn"
959 [(set (match_operand:SI 0 "register_operand" "=l")
960 (minus:SI (match_operand:SI 1 "register_operand" "l")
961 (match_operand:SI 2 "register_operand" "l")))]
964 [(set_attr "length" "2")]
967 (define_insn_and_split "*arm_subsi3_insn"
968 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
969 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
970 (match_operand:SI 2 "s_register_operand" "r,r")))]
976 && GET_CODE (operands[1]) == CONST_INT
977 && !const_ok_for_arm (INTVAL (operands[1]))"
978 [(clobber (const_int 0))]
980 arm_split_constant (MINUS, SImode, curr_insn,
981 INTVAL (operands[1]), operands[0], operands[2], 0);
984 [(set_attr "length" "4,16")
985 (set_attr "predicable" "yes")]
989 [(match_scratch:SI 3 "r")
990 (set (match_operand:SI 0 "arm_general_register_operand" "")
991 (minus:SI (match_operand:SI 1 "const_int_operand" "")
992 (match_operand:SI 2 "arm_general_register_operand" "")))]
994 && !const_ok_for_arm (INTVAL (operands[1]))
995 && const_ok_for_arm (~INTVAL (operands[1]))"
996 [(set (match_dup 3) (match_dup 1))
997 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1001 (define_insn "*subsi3_compare0"
1002 [(set (reg:CC_NOOV CC_REGNUM)
1004 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1005 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1007 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1008 (minus:SI (match_dup 1) (match_dup 2)))]
1012 rsb%?s\\t%0, %2, %1"
1013 [(set_attr "conds" "set")]
1016 (define_insn "decscc"
1017 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1018 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1019 (match_operator:SI 2 "arm_comparison_operator"
1020 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1024 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1025 [(set_attr "conds" "use")
1026 (set_attr "length" "*,8")]
1029 (define_expand "subsf3"
1030 [(set (match_operand:SF 0 "s_register_operand" "")
1031 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1032 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1033 "TARGET_ARM && TARGET_HARD_FLOAT"
1035 if (TARGET_MAVERICK)
1037 if (!cirrus_fp_register (operands[1], SFmode))
1038 operands[1] = force_reg (SFmode, operands[1]);
1039 if (!cirrus_fp_register (operands[2], SFmode))
1040 operands[2] = force_reg (SFmode, operands[2]);
1044 (define_expand "subdf3"
1045 [(set (match_operand:DF 0 "s_register_operand" "")
1046 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1047 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1048 "TARGET_ARM && TARGET_HARD_FLOAT"
1050 if (TARGET_MAVERICK)
1052 if (!cirrus_fp_register (operands[1], DFmode))
1053 operands[1] = force_reg (DFmode, operands[1]);
1054 if (!cirrus_fp_register (operands[2], DFmode))
1055 operands[2] = force_reg (DFmode, operands[2]);
1060 ;; Multiplication insns
1062 (define_expand "mulsi3"
1063 [(set (match_operand:SI 0 "s_register_operand" "")
1064 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1065 (match_operand:SI 1 "s_register_operand" "")))]
1070 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1071 (define_insn "*arm_mulsi3"
1072 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1073 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1074 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1076 "mul%?\\t%0, %2, %1"
1077 [(set_attr "insn" "mul")
1078 (set_attr "predicable" "yes")]
1081 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1082 ; 1 and 2; are the same, because reload will make operand 0 match
1083 ; operand 1 without realizing that this conflicts with operand 2. We fix
1084 ; this by adding another alternative to match this case, and then `reload'
1085 ; it ourselves. This alternative must come first.
1086 (define_insn "*thumb_mulsi3"
1087 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1088 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1089 (match_operand:SI 2 "register_operand" "l,l,l")))]
1092 if (which_alternative < 2)
1093 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1095 return \"mul\\t%0, %2\";
1097 [(set_attr "length" "4,4,2")
1098 (set_attr "insn" "mul")]
1101 (define_insn "*mulsi3_compare0"
1102 [(set (reg:CC_NOOV CC_REGNUM)
1103 (compare:CC_NOOV (mult:SI
1104 (match_operand:SI 2 "s_register_operand" "r,r")
1105 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1107 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1108 (mult:SI (match_dup 2) (match_dup 1)))]
1110 "mul%?s\\t%0, %2, %1"
1111 [(set_attr "conds" "set")
1112 (set_attr "insn" "muls")]
1115 (define_insn "*mulsi_compare0_scratch"
1116 [(set (reg:CC_NOOV CC_REGNUM)
1117 (compare:CC_NOOV (mult:SI
1118 (match_operand:SI 2 "s_register_operand" "r,r")
1119 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1121 (clobber (match_scratch:SI 0 "=&r,&r"))]
1123 "mul%?s\\t%0, %2, %1"
1124 [(set_attr "conds" "set")
1125 (set_attr "insn" "muls")]
1128 ;; Unnamed templates to match MLA instruction.
1130 (define_insn "*mulsi3addsi"
1131 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1133 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1134 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1135 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1137 "mla%?\\t%0, %2, %1, %3"
1138 [(set_attr "insn" "mla")
1139 (set_attr "predicable" "yes")]
1142 (define_insn "*mulsi3addsi_compare0"
1143 [(set (reg:CC_NOOV CC_REGNUM)
1146 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1147 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1148 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1150 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1151 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154 "mla%?s\\t%0, %2, %1, %3"
1155 [(set_attr "conds" "set")
1156 (set_attr "insn" "mlas")]
1159 (define_insn "*mulsi3addsi_compare0_scratch"
1160 [(set (reg:CC_NOOV CC_REGNUM)
1163 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1164 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1165 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1167 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1169 "mla%?s\\t%0, %2, %1, %3"
1170 [(set_attr "conds" "set")
1171 (set_attr "insn" "mlas")]
1174 ;; Unnamed template to match long long multiply-accumulate (smlal)
1176 (define_insn "*mulsidi3adddi"
1177 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1181 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1182 (match_operand:DI 1 "s_register_operand" "0")))]
1183 "TARGET_ARM && arm_arch3m"
1184 "smlal%?\\t%Q0, %R0, %3, %2"
1185 [(set_attr "insn" "smlal")
1186 (set_attr "predicable" "yes")]
1189 (define_insn "mulsidi3"
1190 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1192 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1193 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1194 "TARGET_ARM && arm_arch3m"
1195 "smull%?\\t%Q0, %R0, %1, %2"
1196 [(set_attr "insn" "smull")
1197 (set_attr "predicable" "yes")]
1200 (define_insn "umulsidi3"
1201 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1203 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1204 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1205 "TARGET_ARM && arm_arch3m"
1206 "umull%?\\t%Q0, %R0, %1, %2"
1207 [(set_attr "insn" "umull")
1208 (set_attr "predicable" "yes")]
1211 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1213 (define_insn "*umulsidi3adddi"
1214 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1218 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1219 (match_operand:DI 1 "s_register_operand" "0")))]
1220 "TARGET_ARM && arm_arch3m"
1221 "umlal%?\\t%Q0, %R0, %3, %2"
1222 [(set_attr "insn" "umlal")
1223 (set_attr "predicable" "yes")]
1226 (define_insn "smulsi3_highpart"
1227 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1231 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1232 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1234 (clobber (match_scratch:SI 3 "=&r,&r"))]
1235 "TARGET_ARM && arm_arch3m"
1236 "smull%?\\t%3, %0, %2, %1"
1237 [(set_attr "insn" "smull")
1238 (set_attr "predicable" "yes")]
1241 (define_insn "umulsi3_highpart"
1242 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1246 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1247 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1249 (clobber (match_scratch:SI 3 "=&r,&r"))]
1250 "TARGET_ARM && arm_arch3m"
1251 "umull%?\\t%3, %0, %2, %1"
1252 [(set_attr "insn" "umull")
1253 (set_attr "predicable" "yes")]
1256 (define_insn "mulhisi3"
1257 [(set (match_operand:SI 0 "s_register_operand" "=r")
1258 (mult:SI (sign_extend:SI
1259 (match_operand:HI 1 "s_register_operand" "%r"))
1261 (match_operand:HI 2 "s_register_operand" "r"))))]
1262 "TARGET_ARM && arm_arch5e"
1263 "smulbb%?\\t%0, %1, %2"
1264 [(set_attr "insn" "smulxy")
1265 (set_attr "predicable" "yes")]
1268 (define_insn "*mulhisi3tb"
1269 [(set (match_operand:SI 0 "s_register_operand" "=r")
1270 (mult:SI (ashiftrt:SI
1271 (match_operand:SI 1 "s_register_operand" "r")
1274 (match_operand:HI 2 "s_register_operand" "r"))))]
1275 "TARGET_ARM && arm_arch5e"
1276 "smultb%?\\t%0, %1, %2"
1277 [(set_attr "insn" "smulxy")
1278 (set_attr "predicable" "yes")]
1281 (define_insn "*mulhisi3bt"
1282 [(set (match_operand:SI 0 "s_register_operand" "=r")
1283 (mult:SI (sign_extend:SI
1284 (match_operand:HI 1 "s_register_operand" "r"))
1286 (match_operand:SI 2 "s_register_operand" "r")
1288 "TARGET_ARM && arm_arch5e"
1289 "smulbt%?\\t%0, %1, %2"
1290 [(set_attr "insn" "smulxy")
1291 (set_attr "predicable" "yes")]
1294 (define_insn "*mulhisi3tt"
1295 [(set (match_operand:SI 0 "s_register_operand" "=r")
1296 (mult:SI (ashiftrt:SI
1297 (match_operand:SI 1 "s_register_operand" "r")
1300 (match_operand:SI 2 "s_register_operand" "r")
1302 "TARGET_ARM && arm_arch5e"
1303 "smultt%?\\t%0, %1, %2"
1304 [(set_attr "insn" "smulxy")
1305 (set_attr "predicable" "yes")]
1308 (define_insn "*mulhisi3addsi"
1309 [(set (match_operand:SI 0 "s_register_operand" "=r")
1310 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1311 (mult:SI (sign_extend:SI
1312 (match_operand:HI 2 "s_register_operand" "%r"))
1314 (match_operand:HI 3 "s_register_operand" "r")))))]
1315 "TARGET_ARM && arm_arch5e"
1316 "smlabb%?\\t%0, %2, %3, %1"
1317 [(set_attr "insn" "smlaxy")
1318 (set_attr "predicable" "yes")]
1321 (define_insn "*mulhidi3adddi"
1322 [(set (match_operand:DI 0 "s_register_operand" "=r")
1324 (match_operand:DI 1 "s_register_operand" "0")
1325 (mult:DI (sign_extend:DI
1326 (match_operand:HI 2 "s_register_operand" "%r"))
1328 (match_operand:HI 3 "s_register_operand" "r")))))]
1329 "TARGET_ARM && arm_arch5e"
1330 "smlalbb%?\\t%Q0, %R0, %2, %3"
1331 [(set_attr "insn" "smlalxy")
1332 (set_attr "predicable" "yes")])
1334 (define_expand "mulsf3"
1335 [(set (match_operand:SF 0 "s_register_operand" "")
1336 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1337 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1338 "TARGET_ARM && TARGET_HARD_FLOAT"
1341 && !cirrus_fp_register (operands[2], SFmode))
1342 operands[2] = force_reg (SFmode, operands[2]);
1345 (define_expand "muldf3"
1346 [(set (match_operand:DF 0 "s_register_operand" "")
1347 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1348 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1349 "TARGET_ARM && TARGET_HARD_FLOAT"
1352 && !cirrus_fp_register (operands[2], DFmode))
1353 operands[2] = force_reg (DFmode, operands[2]);
1358 (define_expand "divsf3"
1359 [(set (match_operand:SF 0 "s_register_operand" "")
1360 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1361 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1362 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365 (define_expand "divdf3"
1366 [(set (match_operand:DF 0 "s_register_operand" "")
1367 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1368 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1369 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1374 (define_expand "modsf3"
1375 [(set (match_operand:SF 0 "s_register_operand" "")
1376 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1377 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1378 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381 (define_expand "moddf3"
1382 [(set (match_operand:DF 0 "s_register_operand" "")
1383 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1384 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1385 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388 ;; Boolean and,ior,xor insns
1390 ;; Split up double word logical operations
1392 ;; Split up simple DImode logical operations. Simply perform the logical
1393 ;; operation on the upper and lower halves of the registers.
1395 [(set (match_operand:DI 0 "s_register_operand" "")
1396 (match_operator:DI 6 "logical_binary_operator"
1397 [(match_operand:DI 1 "s_register_operand" "")
1398 (match_operand:DI 2 "s_register_operand" "")]))]
1399 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1400 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1401 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404 operands[3] = gen_highpart (SImode, operands[0]);
1405 operands[0] = gen_lowpart (SImode, operands[0]);
1406 operands[4] = gen_highpart (SImode, operands[1]);
1407 operands[1] = gen_lowpart (SImode, operands[1]);
1408 operands[5] = gen_highpart (SImode, operands[2]);
1409 operands[2] = gen_lowpart (SImode, operands[2]);
1414 [(set (match_operand:DI 0 "s_register_operand" "")
1415 (match_operator:DI 6 "logical_binary_operator"
1416 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1417 (match_operand:DI 1 "s_register_operand" "")]))]
1418 "TARGET_ARM && reload_completed"
1419 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1420 (set (match_dup 3) (match_op_dup:SI 6
1421 [(ashiftrt:SI (match_dup 2) (const_int 31))
1425 operands[3] = gen_highpart (SImode, operands[0]);
1426 operands[0] = gen_lowpart (SImode, operands[0]);
1427 operands[4] = gen_highpart (SImode, operands[1]);
1428 operands[1] = gen_lowpart (SImode, operands[1]);
1429 operands[5] = gen_highpart (SImode, operands[2]);
1430 operands[2] = gen_lowpart (SImode, operands[2]);
1434 ;; The zero extend of operand 2 means we can just copy the high part of
1435 ;; operand1 into operand0.
1437 [(set (match_operand:DI 0 "s_register_operand" "")
1439 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1440 (match_operand:DI 1 "s_register_operand" "")))]
1441 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1442 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1443 (set (match_dup 3) (match_dup 4))]
1446 operands[4] = gen_highpart (SImode, operands[1]);
1447 operands[3] = gen_highpart (SImode, operands[0]);
1448 operands[0] = gen_lowpart (SImode, operands[0]);
1449 operands[1] = gen_lowpart (SImode, operands[1]);
1453 ;; The zero extend of operand 2 means we can just copy the high part of
1454 ;; operand1 into operand0.
1456 [(set (match_operand:DI 0 "s_register_operand" "")
1458 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1459 (match_operand:DI 1 "s_register_operand" "")))]
1460 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1461 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1462 (set (match_dup 3) (match_dup 4))]
1465 operands[4] = gen_highpart (SImode, operands[1]);
1466 operands[3] = gen_highpart (SImode, operands[0]);
1467 operands[0] = gen_lowpart (SImode, operands[0]);
1468 operands[1] = gen_lowpart (SImode, operands[1]);
1472 (define_insn "anddi3"
1473 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1475 (match_operand:DI 2 "s_register_operand" "r,r")))]
1476 "TARGET_ARM && ! TARGET_IWMMXT"
1478 [(set_attr "length" "8")]
1481 (define_insn_and_split "*anddi_zesidi_di"
1482 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1483 (and:DI (zero_extend:DI
1484 (match_operand:SI 2 "s_register_operand" "r,r"))
1485 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488 "TARGET_ARM && reload_completed"
1489 ; The zero extend of operand 2 clears the high word of the output
1491 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1492 (set (match_dup 3) (const_int 0))]
1495 operands[3] = gen_highpart (SImode, operands[0]);
1496 operands[0] = gen_lowpart (SImode, operands[0]);
1497 operands[1] = gen_lowpart (SImode, operands[1]);
1499 [(set_attr "length" "8")]
1502 (define_insn "*anddi_sesdi_di"
1503 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1504 (and:DI (sign_extend:DI
1505 (match_operand:SI 2 "s_register_operand" "r,r"))
1506 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1509 [(set_attr "length" "8")]
1512 (define_expand "andsi3"
1513 [(set (match_operand:SI 0 "s_register_operand" "")
1514 (and:SI (match_operand:SI 1 "s_register_operand" "")
1515 (match_operand:SI 2 "reg_or_int_operand" "")))]
1520 if (GET_CODE (operands[2]) == CONST_INT)
1522 arm_split_constant (AND, SImode, NULL_RTX,
1523 INTVAL (operands[2]), operands[0],
1524 operands[1], optimize && !no_new_pseudos);
1529 else /* TARGET_THUMB */
1531 if (GET_CODE (operands[2]) != CONST_INT)
1532 operands[2] = force_reg (SImode, operands[2]);
1537 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1539 operands[2] = force_reg (SImode,
1540 GEN_INT (~INTVAL (operands[2])));
1542 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1547 for (i = 9; i <= 31; i++)
1549 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1551 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1555 else if ((((HOST_WIDE_INT) 1) << i) - 1
1556 == ~INTVAL (operands[2]))
1558 rtx shift = GEN_INT (i);
1559 rtx reg = gen_reg_rtx (SImode);
1561 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1562 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1568 operands[2] = force_reg (SImode, operands[2]);
1574 (define_insn_and_split "*arm_andsi3_insn"
1575 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1576 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1577 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1581 bic%?\\t%0, %1, #%B2
1584 && GET_CODE (operands[2]) == CONST_INT
1585 && !(const_ok_for_arm (INTVAL (operands[2]))
1586 || const_ok_for_arm (~INTVAL (operands[2])))"
1587 [(clobber (const_int 0))]
1589 arm_split_constant (AND, SImode, curr_insn,
1590 INTVAL (operands[2]), operands[0], operands[1], 0);
1593 [(set_attr "length" "4,4,16")
1594 (set_attr "predicable" "yes")]
1597 (define_insn "*thumb_andsi3_insn"
1598 [(set (match_operand:SI 0 "register_operand" "=l")
1599 (and:SI (match_operand:SI 1 "register_operand" "%0")
1600 (match_operand:SI 2 "register_operand" "l")))]
1603 [(set_attr "length" "2")]
1606 (define_insn "*andsi3_compare0"
1607 [(set (reg:CC_NOOV CC_REGNUM)
1609 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1610 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1612 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1613 (and:SI (match_dup 1) (match_dup 2)))]
1617 bic%?s\\t%0, %1, #%B2"
1618 [(set_attr "conds" "set")]
1621 (define_insn "*andsi3_compare0_scratch"
1622 [(set (reg:CC_NOOV CC_REGNUM)
1624 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1625 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1627 (clobber (match_scratch:SI 2 "=X,r"))]
1631 bic%?s\\t%2, %0, #%B1"
1632 [(set_attr "conds" "set")]
1635 (define_insn "*zeroextractsi_compare0_scratch"
1636 [(set (reg:CC_NOOV CC_REGNUM)
1637 (compare:CC_NOOV (zero_extract:SI
1638 (match_operand:SI 0 "s_register_operand" "r")
1639 (match_operand 1 "const_int_operand" "n")
1640 (match_operand 2 "const_int_operand" "n"))
1643 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1644 && INTVAL (operands[1]) > 0
1645 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1646 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1648 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1649 << INTVAL (operands[2]));
1650 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653 [(set_attr "conds" "set")]
1656 (define_insn_and_split "*ne_zeroextractsi"
1657 [(set (match_operand:SI 0 "s_register_operand" "=r")
1658 (ne:SI (zero_extract:SI
1659 (match_operand:SI 1 "s_register_operand" "r")
1660 (match_operand:SI 2 "const_int_operand" "n")
1661 (match_operand:SI 3 "const_int_operand" "n"))
1663 (clobber (reg:CC CC_REGNUM))]
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)"
1671 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1672 && INTVAL (operands[2]) > 0
1673 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1674 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1675 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1676 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1678 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1680 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1681 (match_dup 0) (const_int 1)))]
1683 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1684 << INTVAL (operands[3]));
1686 [(set_attr "conds" "clob")
1687 (set_attr "length" "8")]
1690 (define_insn_and_split "*ne_zeroextractsi_shifted"
1691 [(set (match_operand:SI 0 "s_register_operand" "=r")
1692 (ne:SI (zero_extract:SI
1693 (match_operand:SI 1 "s_register_operand" "r")
1694 (match_operand:SI 2 "const_int_operand" "n")
1697 (clobber (reg:CC CC_REGNUM))]
1701 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1702 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1704 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1706 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1707 (match_dup 0) (const_int 1)))]
1709 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1711 [(set_attr "conds" "clob")
1712 (set_attr "length" "8")]
1715 (define_insn_and_split "*ite_ne_zeroextractsi"
1716 [(set (match_operand:SI 0 "s_register_operand" "=r")
1717 (if_then_else:SI (ne (zero_extract:SI
1718 (match_operand:SI 1 "s_register_operand" "r")
1719 (match_operand:SI 2 "const_int_operand" "n")
1720 (match_operand:SI 3 "const_int_operand" "n"))
1722 (match_operand:SI 4 "arm_not_operand" "rIK")
1724 (clobber (reg:CC CC_REGNUM))]
1726 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1727 && INTVAL (operands[2]) > 0
1728 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1729 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1730 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1734 && INTVAL (operands[2]) > 0
1735 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1736 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1737 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1738 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1739 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1741 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1743 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1744 (match_dup 0) (match_dup 4)))]
1746 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1747 << INTVAL (operands[3]));
1749 [(set_attr "conds" "clob")
1750 (set_attr "length" "8")]
1753 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1754 [(set (match_operand:SI 0 "s_register_operand" "=r")
1755 (if_then_else:SI (ne (zero_extract:SI
1756 (match_operand:SI 1 "s_register_operand" "r")
1757 (match_operand:SI 2 "const_int_operand" "n")
1760 (match_operand:SI 3 "arm_not_operand" "rIK")
1762 (clobber (reg:CC CC_REGNUM))]
1763 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1765 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1767 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1769 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1771 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1772 (match_dup 0) (match_dup 3)))]
1774 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1776 [(set_attr "conds" "clob")
1777 (set_attr "length" "8")]
1781 [(set (match_operand:SI 0 "s_register_operand" "")
1782 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1783 (match_operand:SI 2 "const_int_operand" "")
1784 (match_operand:SI 3 "const_int_operand" "")))
1785 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1787 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1788 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1790 HOST_WIDE_INT temp = INTVAL (operands[2]);
1792 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1793 operands[3] = GEN_INT (32 - temp);
1798 [(set (match_operand:SI 0 "s_register_operand" "")
1799 (match_operator:SI 1 "shiftable_operator"
1800 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1801 (match_operand:SI 3 "const_int_operand" "")
1802 (match_operand:SI 4 "const_int_operand" ""))
1803 (match_operand:SI 5 "s_register_operand" "")]))
1804 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1806 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812 HOST_WIDE_INT temp = INTVAL (operands[3]);
1814 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1815 operands[4] = GEN_INT (32 - temp);
1820 [(set (match_operand:SI 0 "s_register_operand" "")
1821 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1822 (match_operand:SI 2 "const_int_operand" "")
1823 (match_operand:SI 3 "const_int_operand" "")))]
1825 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1826 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1828 HOST_WIDE_INT temp = INTVAL (operands[2]);
1830 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1831 operands[3] = GEN_INT (32 - temp);
1836 [(set (match_operand:SI 0 "s_register_operand" "")
1837 (match_operator:SI 1 "shiftable_operator"
1838 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1839 (match_operand:SI 3 "const_int_operand" "")
1840 (match_operand:SI 4 "const_int_operand" ""))
1841 (match_operand:SI 5 "s_register_operand" "")]))
1842 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1844 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850 HOST_WIDE_INT temp = INTVAL (operands[3]);
1852 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1853 operands[4] = GEN_INT (32 - temp);
1857 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1858 ;;; represented by the bitfield, then this will produce incorrect results.
1859 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1860 ;;; which have a real bit-field insert instruction, the truncation happens
1861 ;;; in the bit-field insert instruction itself. Since arm does not have a
1862 ;;; bit-field insert instruction, we would have to emit code here to truncate
1863 ;;; the value before we insert. This loses some of the advantage of having
1864 ;;; this insv pattern, so this pattern needs to be reevalutated.
1866 (define_expand "insv"
1867 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1868 (match_operand:SI 1 "general_operand" "")
1869 (match_operand:SI 2 "general_operand" ""))
1870 (match_operand:SI 3 "reg_or_int_operand" ""))]
1874 int start_bit = INTVAL (operands[2]);
1875 int width = INTVAL (operands[1]);
1876 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1877 rtx target, subtarget;
1879 target = operands[0];
1880 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1881 subreg as the final target. */
1882 if (GET_CODE (target) == SUBREG)
1884 subtarget = gen_reg_rtx (SImode);
1885 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1886 < GET_MODE_SIZE (SImode))
1887 target = SUBREG_REG (target);
1892 if (GET_CODE (operands[3]) == CONST_INT)
1894 /* Since we are inserting a known constant, we may be able to
1895 reduce the number of bits that we have to clear so that
1896 the mask becomes simple. */
1897 /* ??? This code does not check to see if the new mask is actually
1898 simpler. It may not be. */
1899 rtx op1 = gen_reg_rtx (SImode);
1900 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1901 start of this pattern. */
1902 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1903 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1905 emit_insn (gen_andsi3 (op1, operands[0],
1906 gen_int_mode (~mask2, SImode)));
1907 emit_insn (gen_iorsi3 (subtarget, op1,
1908 gen_int_mode (op3_value << start_bit, SImode)));
1910 else if (start_bit == 0
1911 && !(const_ok_for_arm (mask)
1912 || const_ok_for_arm (~mask)))
1914 /* A Trick, since we are setting the bottom bits in the word,
1915 we can shift operand[3] up, operand[0] down, OR them together
1916 and rotate the result back again. This takes 3 insns, and
1917 the third might be mergeable into another op. */
1918 /* The shift up copes with the possibility that operand[3] is
1919 wider than the bitfield. */
1920 rtx op0 = gen_reg_rtx (SImode);
1921 rtx op1 = gen_reg_rtx (SImode);
1923 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1924 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1925 emit_insn (gen_iorsi3 (op1, op1, op0));
1926 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1928 else if ((width + start_bit == 32)
1929 && !(const_ok_for_arm (mask)
1930 || const_ok_for_arm (~mask)))
1932 /* Similar trick, but slightly less efficient. */
1934 rtx op0 = gen_reg_rtx (SImode);
1935 rtx op1 = gen_reg_rtx (SImode);
1937 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1938 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1939 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1940 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1944 rtx op0 = gen_int_mode (mask, SImode);
1945 rtx op1 = gen_reg_rtx (SImode);
1946 rtx op2 = gen_reg_rtx (SImode);
1948 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1950 rtx tmp = gen_reg_rtx (SImode);
1952 emit_insn (gen_movsi (tmp, op0));
1956 /* Mask out any bits in operand[3] that are not needed. */
1957 emit_insn (gen_andsi3 (op1, operands[3], op0));
1959 if (GET_CODE (op0) == CONST_INT
1960 && (const_ok_for_arm (mask << start_bit)
1961 || const_ok_for_arm (~(mask << start_bit))))
1963 op0 = gen_int_mode (~(mask << start_bit), SImode);
1964 emit_insn (gen_andsi3 (op2, operands[0], op0));
1968 if (GET_CODE (op0) == CONST_INT)
1970 rtx tmp = gen_reg_rtx (SImode);
1972 emit_insn (gen_movsi (tmp, op0));
1977 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1979 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1983 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1985 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988 if (subtarget != target)
1990 /* If TARGET is still a SUBREG, then it must be wider than a word,
1991 so we must be careful only to set the subword we were asked to. */
1992 if (GET_CODE (target) == SUBREG)
1993 emit_move_insn (target, subtarget);
1995 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2002 ; constants for op 2 will never be given to these patterns.
2003 (define_insn_and_split "*anddi_notdi_di"
2004 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2005 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2006 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2010 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2011 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014 operands[3] = gen_highpart (SImode, operands[0]);
2015 operands[0] = gen_lowpart (SImode, operands[0]);
2016 operands[4] = gen_highpart (SImode, operands[1]);
2017 operands[1] = gen_lowpart (SImode, operands[1]);
2018 operands[5] = gen_highpart (SImode, operands[2]);
2019 operands[2] = gen_lowpart (SImode, operands[2]);
2021 [(set_attr "length" "8")
2022 (set_attr "predicable" "yes")]
2025 (define_insn_and_split "*anddi_notzesidi_di"
2026 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2027 (and:DI (not:DI (zero_extend:DI
2028 (match_operand:SI 2 "s_register_operand" "r,r")))
2029 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032 bic%?\\t%Q0, %Q1, %2
2034 ; (not (zero_extend ...)) allows us to just copy the high word from
2035 ; operand1 to operand0.
2038 && operands[0] != operands[1]"
2039 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2040 (set (match_dup 3) (match_dup 4))]
2043 operands[3] = gen_highpart (SImode, operands[0]);
2044 operands[0] = gen_lowpart (SImode, operands[0]);
2045 operands[4] = gen_highpart (SImode, operands[1]);
2046 operands[1] = gen_lowpart (SImode, operands[1]);
2048 [(set_attr "length" "4,8")
2049 (set_attr "predicable" "yes")]
2052 (define_insn_and_split "*anddi_notsesidi_di"
2053 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2054 (and:DI (not:DI (sign_extend:DI
2055 (match_operand:SI 2 "s_register_operand" "r,r")))
2056 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059 "TARGET_ARM && reload_completed"
2060 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2061 (set (match_dup 3) (and:SI (not:SI
2062 (ashiftrt:SI (match_dup 2) (const_int 31)))
2066 operands[3] = gen_highpart (SImode, operands[0]);
2067 operands[0] = gen_lowpart (SImode, operands[0]);
2068 operands[4] = gen_highpart (SImode, operands[1]);
2069 operands[1] = gen_lowpart (SImode, operands[1]);
2071 [(set_attr "length" "8")
2072 (set_attr "predicable" "yes")]
2075 (define_insn "andsi_notsi_si"
2076 [(set (match_operand:SI 0 "s_register_operand" "=r")
2077 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2078 (match_operand:SI 1 "s_register_operand" "r")))]
2080 "bic%?\\t%0, %1, %2"
2081 [(set_attr "predicable" "yes")]
2084 (define_insn "bicsi3"
2085 [(set (match_operand:SI 0 "register_operand" "=l")
2086 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2087 (match_operand:SI 2 "register_operand" "0")))]
2090 [(set_attr "length" "2")]
2093 (define_insn "andsi_not_shiftsi_si"
2094 [(set (match_operand:SI 0 "s_register_operand" "=r")
2095 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2096 [(match_operand:SI 2 "s_register_operand" "r")
2097 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2098 (match_operand:SI 1 "s_register_operand" "r")))]
2100 "bic%?\\t%0, %1, %2%S4"
2101 [(set_attr "predicable" "yes")
2102 (set_attr "shift" "2")
2103 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2104 (const_string "alu_shift")
2105 (const_string "alu_shift_reg")))]
2108 (define_insn "*andsi_notsi_si_compare0"
2109 [(set (reg:CC_NOOV CC_REGNUM)
2111 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2112 (match_operand:SI 1 "s_register_operand" "r"))
2114 (set (match_operand:SI 0 "s_register_operand" "=r")
2115 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2117 "bic%?s\\t%0, %1, %2"
2118 [(set_attr "conds" "set")]
2121 (define_insn "*andsi_notsi_si_compare0_scratch"
2122 [(set (reg:CC_NOOV CC_REGNUM)
2124 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2125 (match_operand:SI 1 "s_register_operand" "r"))
2127 (clobber (match_scratch:SI 0 "=r"))]
2129 "bic%?s\\t%0, %1, %2"
2130 [(set_attr "conds" "set")]
2133 (define_insn "iordi3"
2134 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2135 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2136 (match_operand:DI 2 "s_register_operand" "r,r")))]
2137 "TARGET_ARM && ! TARGET_IWMMXT"
2139 [(set_attr "length" "8")
2140 (set_attr "predicable" "yes")]
2143 (define_insn "*iordi_zesidi_di"
2144 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2145 (ior:DI (zero_extend:DI
2146 (match_operand:SI 2 "s_register_operand" "r,r"))
2147 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150 orr%?\\t%Q0, %Q1, %2
2152 [(set_attr "length" "4,8")
2153 (set_attr "predicable" "yes")]
2156 (define_insn "*iordi_sesidi_di"
2157 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2158 (ior:DI (sign_extend:DI
2159 (match_operand:SI 2 "s_register_operand" "r,r"))
2160 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163 [(set_attr "length" "8")
2164 (set_attr "predicable" "yes")]
2167 (define_expand "iorsi3"
2168 [(set (match_operand:SI 0 "s_register_operand" "")
2169 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2170 (match_operand:SI 2 "reg_or_int_operand" "")))]
2173 if (GET_CODE (operands[2]) == CONST_INT)
2177 arm_split_constant (IOR, SImode, NULL_RTX,
2178 INTVAL (operands[2]), operands[0], operands[1],
2179 optimize && !no_new_pseudos);
2182 else /* TARGET_THUMB */
2183 operands [2] = force_reg (SImode, operands [2]);
2188 (define_insn_and_split "*arm_iorsi3"
2189 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2190 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2191 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2197 && GET_CODE (operands[2]) == CONST_INT
2198 && !const_ok_for_arm (INTVAL (operands[2]))"
2199 [(clobber (const_int 0))]
2201 arm_split_constant (IOR, SImode, curr_insn,
2202 INTVAL (operands[2]), operands[0], operands[1], 0);
2205 [(set_attr "length" "4,16")
2206 (set_attr "predicable" "yes")]
2209 (define_insn "*thumb_iorsi3"
2210 [(set (match_operand:SI 0 "register_operand" "=l")
2211 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2212 (match_operand:SI 2 "register_operand" "l")))]
2215 [(set_attr "length" "2")]
2219 [(match_scratch:SI 3 "r")
2220 (set (match_operand:SI 0 "arm_general_register_operand" "")
2221 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2222 (match_operand:SI 2 "const_int_operand" "")))]
2224 && !const_ok_for_arm (INTVAL (operands[2]))
2225 && const_ok_for_arm (~INTVAL (operands[2]))"
2226 [(set (match_dup 3) (match_dup 2))
2227 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2231 (define_insn "*iorsi3_compare0"
2232 [(set (reg:CC_NOOV CC_REGNUM)
2233 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2234 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2236 (set (match_operand:SI 0 "s_register_operand" "=r")
2237 (ior:SI (match_dup 1) (match_dup 2)))]
2239 "orr%?s\\t%0, %1, %2"
2240 [(set_attr "conds" "set")]
2243 (define_insn "*iorsi3_compare0_scratch"
2244 [(set (reg:CC_NOOV CC_REGNUM)
2245 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2246 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2248 (clobber (match_scratch:SI 0 "=r"))]
2250 "orr%?s\\t%0, %1, %2"
2251 [(set_attr "conds" "set")]
2254 (define_insn "xordi3"
2255 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2257 (match_operand:DI 2 "s_register_operand" "r,r")))]
2258 "TARGET_ARM && !TARGET_IWMMXT"
2260 [(set_attr "length" "8")
2261 (set_attr "predicable" "yes")]
2264 (define_insn "*xordi_zesidi_di"
2265 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2266 (xor:DI (zero_extend:DI
2267 (match_operand:SI 2 "s_register_operand" "r,r"))
2268 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271 eor%?\\t%Q0, %Q1, %2
2273 [(set_attr "length" "4,8")
2274 (set_attr "predicable" "yes")]
2277 (define_insn "*xordi_sesidi_di"
2278 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2279 (xor:DI (sign_extend:DI
2280 (match_operand:SI 2 "s_register_operand" "r,r"))
2281 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284 [(set_attr "length" "8")
2285 (set_attr "predicable" "yes")]
2288 (define_expand "xorsi3"
2289 [(set (match_operand:SI 0 "s_register_operand" "")
2290 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2291 (match_operand:SI 2 "arm_rhs_operand" "")))]
2294 if (GET_CODE (operands[2]) == CONST_INT)
2295 operands[2] = force_reg (SImode, operands[2]);
2299 (define_insn "*arm_xorsi3"
2300 [(set (match_operand:SI 0 "s_register_operand" "=r")
2301 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2302 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2304 "eor%?\\t%0, %1, %2"
2305 [(set_attr "predicable" "yes")]
2308 (define_insn "*thumb_xorsi3"
2309 [(set (match_operand:SI 0 "register_operand" "=l")
2310 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2311 (match_operand:SI 2 "register_operand" "l")))]
2314 [(set_attr "length" "2")]
2317 (define_insn "*xorsi3_compare0"
2318 [(set (reg:CC_NOOV CC_REGNUM)
2319 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2320 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2322 (set (match_operand:SI 0 "s_register_operand" "=r")
2323 (xor:SI (match_dup 1) (match_dup 2)))]
2325 "eor%?s\\t%0, %1, %2"
2326 [(set_attr "conds" "set")]
2329 (define_insn "*xorsi3_compare0_scratch"
2330 [(set (reg:CC_NOOV CC_REGNUM)
2331 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2332 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2336 [(set_attr "conds" "set")]
2339 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2340 ; (NOT D) we can sometimes merge the final NOT into one of the following
2344 [(set (match_operand:SI 0 "s_register_operand" "")
2345 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2346 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2347 (match_operand:SI 3 "arm_rhs_operand" "")))
2348 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2350 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2351 (not:SI (match_dup 3))))
2352 (set (match_dup 0) (not:SI (match_dup 4)))]
2356 (define_insn "*andsi_iorsi3_notsi"
2357 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2358 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2359 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2360 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2362 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2363 [(set_attr "length" "8")
2364 (set_attr "predicable" "yes")]
2368 [(set (match_operand:SI 0 "s_register_operand" "")
2369 (match_operator:SI 1 "logical_binary_operator"
2370 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2371 (match_operand:SI 3 "const_int_operand" "")
2372 (match_operand:SI 4 "const_int_operand" ""))
2373 (match_operator:SI 9 "logical_binary_operator"
2374 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2375 (match_operand:SI 6 "const_int_operand" ""))
2376 (match_operand:SI 7 "s_register_operand" "")])]))
2377 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2379 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2380 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383 [(ashift:SI (match_dup 2) (match_dup 4))
2387 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2394 [(set (match_operand:SI 0 "s_register_operand" "")
2395 (match_operator:SI 1 "logical_binary_operator"
2396 [(match_operator:SI 9 "logical_binary_operator"
2397 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2398 (match_operand:SI 6 "const_int_operand" ""))
2399 (match_operand:SI 7 "s_register_operand" "")])
2400 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2401 (match_operand:SI 3 "const_int_operand" "")
2402 (match_operand:SI 4 "const_int_operand" ""))]))
2403 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2405 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2406 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409 [(ashift:SI (match_dup 2) (match_dup 4))
2413 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2420 [(set (match_operand:SI 0 "s_register_operand" "")
2421 (match_operator:SI 1 "logical_binary_operator"
2422 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2423 (match_operand:SI 3 "const_int_operand" "")
2424 (match_operand:SI 4 "const_int_operand" ""))
2425 (match_operator:SI 9 "logical_binary_operator"
2426 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2427 (match_operand:SI 6 "const_int_operand" ""))
2428 (match_operand:SI 7 "s_register_operand" "")])]))
2429 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2431 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2432 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435 [(ashift:SI (match_dup 2) (match_dup 4))
2439 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2446 [(set (match_operand:SI 0 "s_register_operand" "")
2447 (match_operator:SI 1 "logical_binary_operator"
2448 [(match_operator:SI 9 "logical_binary_operator"
2449 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2450 (match_operand:SI 6 "const_int_operand" ""))
2451 (match_operand:SI 7 "s_register_operand" "")])
2452 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2453 (match_operand:SI 3 "const_int_operand" "")
2454 (match_operand:SI 4 "const_int_operand" ""))]))
2455 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2457 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2458 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461 [(ashift:SI (match_dup 2) (match_dup 4))
2465 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2472 ;; Minimum and maximum insns
2474 (define_insn "smaxsi3"
2475 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2476 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2477 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2478 (clobber (reg:CC CC_REGNUM))]
2481 cmp\\t%1, %2\;movlt\\t%0, %2
2482 cmp\\t%1, %2\;movge\\t%0, %1
2483 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2484 [(set_attr "conds" "clob")
2485 (set_attr "length" "8,8,12")]
2488 (define_insn "sminsi3"
2489 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2490 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2491 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2492 (clobber (reg:CC CC_REGNUM))]
2495 cmp\\t%1, %2\;movge\\t%0, %2
2496 cmp\\t%1, %2\;movlt\\t%0, %1
2497 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2498 [(set_attr "conds" "clob")
2499 (set_attr "length" "8,8,12")]
2502 (define_insn "umaxsi3"
2503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2504 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2505 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2506 (clobber (reg:CC CC_REGNUM))]
2509 cmp\\t%1, %2\;movcc\\t%0, %2
2510 cmp\\t%1, %2\;movcs\\t%0, %1
2511 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2512 [(set_attr "conds" "clob")
2513 (set_attr "length" "8,8,12")]
2516 (define_insn "uminsi3"
2517 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2518 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2519 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2520 (clobber (reg:CC CC_REGNUM))]
2523 cmp\\t%1, %2\;movcs\\t%0, %2
2524 cmp\\t%1, %2\;movcc\\t%0, %1
2525 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2526 [(set_attr "conds" "clob")
2527 (set_attr "length" "8,8,12")]
2530 (define_insn "*store_minmaxsi"
2531 [(set (match_operand:SI 0 "memory_operand" "=m")
2532 (match_operator:SI 3 "minmax_operator"
2533 [(match_operand:SI 1 "s_register_operand" "r")
2534 (match_operand:SI 2 "s_register_operand" "r")]))
2535 (clobber (reg:CC CC_REGNUM))]
2538 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2539 operands[1], operands[2]);
2540 output_asm_insn (\"cmp\\t%1, %2\", operands);
2541 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2542 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545 [(set_attr "conds" "clob")
2546 (set_attr "length" "12")
2547 (set_attr "type" "store1")]
2550 ; Reject the frame pointer in operand[1], since reloading this after
2551 ; it has been eliminated can cause carnage.
2552 (define_insn "*minmax_arithsi"
2553 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2554 (match_operator:SI 4 "shiftable_operator"
2555 [(match_operator:SI 5 "minmax_operator"
2556 [(match_operand:SI 2 "s_register_operand" "r,r")
2557 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2558 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2559 (clobber (reg:CC CC_REGNUM))]
2560 "TARGET_ARM && !arm_eliminable_register (operands[1])"
2563 enum rtx_code code = GET_CODE (operands[4]);
2565 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2566 operands[2], operands[3]);
2567 output_asm_insn (\"cmp\\t%2, %3\", operands);
2568 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2569 if (which_alternative != 0 || operands[3] != const0_rtx
2570 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2571 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574 [(set_attr "conds" "clob")
2575 (set_attr "length" "12")]
2579 ;; Shift and rotation insns
2581 (define_expand "ashldi3"
2582 [(set (match_operand:DI 0 "s_register_operand" "")
2583 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2584 (match_operand:SI 2 "reg_or_int_operand" "")))]
2587 if (GET_CODE (operands[2]) == CONST_INT)
2589 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2591 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594 /* Ideally we shouldn't fail here if we could know that operands[1]
2595 ends up already living in an iwmmxt register. Otherwise it's
2596 cheaper to have the alternate code being generated than moving
2597 values to iwmmxt regs and back. */
2600 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2605 (define_insn "arm_ashldi3_1bit"
2606 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2607 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2609 (clobber (reg:CC CC_REGNUM))]
2611 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2612 [(set_attr "conds" "clob")
2613 (set_attr "length" "8")]
2616 (define_expand "ashlsi3"
2617 [(set (match_operand:SI 0 "s_register_operand" "")
2618 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2619 (match_operand:SI 2 "arm_rhs_operand" "")))]
2622 if (GET_CODE (operands[2]) == CONST_INT
2623 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2625 emit_insn (gen_movsi (operands[0], const0_rtx));
2631 (define_insn "*thumb_ashlsi3"
2632 [(set (match_operand:SI 0 "register_operand" "=l,l")
2633 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2634 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637 [(set_attr "length" "2")]
2640 (define_expand "ashrdi3"
2641 [(set (match_operand:DI 0 "s_register_operand" "")
2642 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2643 (match_operand:SI 2 "reg_or_int_operand" "")))]
2646 if (GET_CODE (operands[2]) == CONST_INT)
2648 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2650 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653 /* Ideally we shouldn't fail here if we could know that operands[1]
2654 ends up already living in an iwmmxt register. Otherwise it's
2655 cheaper to have the alternate code being generated than moving
2656 values to iwmmxt regs and back. */
2659 else if (!TARGET_REALLY_IWMMXT)
2664 (define_insn "arm_ashrdi3_1bit"
2665 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2666 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2668 (clobber (reg:CC CC_REGNUM))]
2670 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2671 [(set_attr "conds" "clob")
2672 (set_attr "length" "8")]
2675 (define_expand "ashrsi3"
2676 [(set (match_operand:SI 0 "s_register_operand" "")
2677 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2678 (match_operand:SI 2 "arm_rhs_operand" "")))]
2681 if (GET_CODE (operands[2]) == CONST_INT
2682 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2683 operands[2] = GEN_INT (31);
2687 (define_insn "*thumb_ashrsi3"
2688 [(set (match_operand:SI 0 "register_operand" "=l,l")
2689 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2690 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693 [(set_attr "length" "2")]
2696 (define_expand "lshrdi3"
2697 [(set (match_operand:DI 0 "s_register_operand" "")
2698 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2699 (match_operand:SI 2 "reg_or_int_operand" "")))]
2702 if (GET_CODE (operands[2]) == CONST_INT)
2704 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2706 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709 /* Ideally we shouldn't fail here if we could know that operands[1]
2710 ends up already living in an iwmmxt register. Otherwise it's
2711 cheaper to have the alternate code being generated than moving
2712 values to iwmmxt regs and back. */
2715 else if (!TARGET_REALLY_IWMMXT)
2720 (define_insn "arm_lshrdi3_1bit"
2721 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2722 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2724 (clobber (reg:CC CC_REGNUM))]
2726 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2727 [(set_attr "conds" "clob")
2728 (set_attr "length" "8")]
2731 (define_expand "lshrsi3"
2732 [(set (match_operand:SI 0 "s_register_operand" "")
2733 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2734 (match_operand:SI 2 "arm_rhs_operand" "")))]
2737 if (GET_CODE (operands[2]) == CONST_INT
2738 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2740 emit_insn (gen_movsi (operands[0], const0_rtx));
2746 (define_insn "*thumb_lshrsi3"
2747 [(set (match_operand:SI 0 "register_operand" "=l,l")
2748 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2749 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752 [(set_attr "length" "2")]
2755 (define_expand "rotlsi3"
2756 [(set (match_operand:SI 0 "s_register_operand" "")
2757 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2758 (match_operand:SI 2 "reg_or_int_operand" "")))]
2761 if (GET_CODE (operands[2]) == CONST_INT)
2762 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765 rtx reg = gen_reg_rtx (SImode);
2766 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2772 (define_expand "rotrsi3"
2773 [(set (match_operand:SI 0 "s_register_operand" "")
2774 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2775 (match_operand:SI 2 "arm_rhs_operand" "")))]
2780 if (GET_CODE (operands[2]) == CONST_INT
2781 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2782 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2784 else /* TARGET_THUMB */
2786 if (GET_CODE (operands [2]) == CONST_INT)
2787 operands [2] = force_reg (SImode, operands[2]);
2792 (define_insn "*thumb_rotrsi3"
2793 [(set (match_operand:SI 0 "register_operand" "=l")
2794 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2795 (match_operand:SI 2 "register_operand" "l")))]
2798 [(set_attr "length" "2")]
2801 (define_insn "*arm_shiftsi3"
2802 [(set (match_operand:SI 0 "s_register_operand" "=r")
2803 (match_operator:SI 3 "shift_operator"
2804 [(match_operand:SI 1 "s_register_operand" "r")
2805 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2808 [(set_attr "predicable" "yes")
2809 (set_attr "shift" "1")
2810 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2811 (const_string "alu_shift")
2812 (const_string "alu_shift_reg")))]
2815 (define_insn "*shiftsi3_compare0"
2816 [(set (reg:CC_NOOV CC_REGNUM)
2817 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2818 [(match_operand:SI 1 "s_register_operand" "r")
2819 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2821 (set (match_operand:SI 0 "s_register_operand" "=r")
2822 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2824 "mov%?s\\t%0, %1%S3"
2825 [(set_attr "conds" "set")
2826 (set_attr "shift" "1")
2827 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2828 (const_string "alu_shift")
2829 (const_string "alu_shift_reg")))]
2832 (define_insn "*shiftsi3_compare0_scratch"
2833 [(set (reg:CC_NOOV CC_REGNUM)
2834 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2835 [(match_operand:SI 1 "s_register_operand" "r")
2836 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2838 (clobber (match_scratch:SI 0 "=r"))]
2840 "mov%?s\\t%0, %1%S3"
2841 [(set_attr "conds" "set")
2842 (set_attr "shift" "1")]
2845 (define_insn "*notsi_shiftsi"
2846 [(set (match_operand:SI 0 "s_register_operand" "=r")
2847 (not:SI (match_operator:SI 3 "shift_operator"
2848 [(match_operand:SI 1 "s_register_operand" "r")
2849 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2852 [(set_attr "predicable" "yes")
2853 (set_attr "shift" "1")
2854 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2855 (const_string "alu_shift")
2856 (const_string "alu_shift_reg")))]
2859 (define_insn "*notsi_shiftsi_compare0"
2860 [(set (reg:CC_NOOV CC_REGNUM)
2861 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2862 [(match_operand:SI 1 "s_register_operand" "r")
2863 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2865 (set (match_operand:SI 0 "s_register_operand" "=r")
2866 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2868 "mvn%?s\\t%0, %1%S3"
2869 [(set_attr "conds" "set")
2870 (set_attr "shift" "1")
2871 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2872 (const_string "alu_shift")
2873 (const_string "alu_shift_reg")))]
2876 (define_insn "*not_shiftsi_compare0_scratch"
2877 [(set (reg:CC_NOOV CC_REGNUM)
2878 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2879 [(match_operand:SI 1 "s_register_operand" "r")
2880 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2882 (clobber (match_scratch:SI 0 "=r"))]
2884 "mvn%?s\\t%0, %1%S3"
2885 [(set_attr "conds" "set")
2886 (set_attr "shift" "1")
2887 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2888 (const_string "alu_shift")
2889 (const_string "alu_shift_reg")))]
2892 ;; We don't really have extzv, but defining this using shifts helps
2893 ;; to reduce register pressure later on.
2895 (define_expand "extzv"
2897 (ashift:SI (match_operand:SI 1 "register_operand" "")
2898 (match_operand:SI 2 "const_int_operand" "")))
2899 (set (match_operand:SI 0 "register_operand" "")
2900 (lshiftrt:SI (match_dup 4)
2901 (match_operand:SI 3 "const_int_operand" "")))]
2905 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2906 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2908 operands[3] = GEN_INT (rshift);
2912 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2916 operands[2] = GEN_INT (lshift);
2917 operands[4] = gen_reg_rtx (SImode);
2922 ;; Unary arithmetic insns
2924 (define_expand "negdi2"
2926 [(set (match_operand:DI 0 "s_register_operand" "")
2927 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2928 (clobber (reg:CC CC_REGNUM))])]
2933 if (GET_CODE (operands[1]) != REG)
2934 operands[1] = force_reg (SImode, operands[1]);
2939 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2940 ;; The second alternative is to allow the common case of a *full* overlap.
2941 (define_insn "*arm_negdi2"
2942 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2943 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2944 (clobber (reg:CC CC_REGNUM))]
2946 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2947 [(set_attr "conds" "clob")
2948 (set_attr "length" "8")]
2951 (define_insn "*thumb_negdi2"
2952 [(set (match_operand:DI 0 "register_operand" "=&l")
2953 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2954 (clobber (reg:CC CC_REGNUM))]
2956 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2957 [(set_attr "length" "6")]
2960 (define_expand "negsi2"
2961 [(set (match_operand:SI 0 "s_register_operand" "")
2962 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2967 (define_insn "*arm_negsi2"
2968 [(set (match_operand:SI 0 "s_register_operand" "=r")
2969 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2971 "rsb%?\\t%0, %1, #0"
2972 [(set_attr "predicable" "yes")]
2975 (define_insn "*thumb_negsi2"
2976 [(set (match_operand:SI 0 "register_operand" "=l")
2977 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980 [(set_attr "length" "2")]
2983 (define_expand "negsf2"
2984 [(set (match_operand:SF 0 "s_register_operand" "")
2985 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2986 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2990 (define_expand "negdf2"
2991 [(set (match_operand:DF 0 "s_register_operand" "")
2992 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2993 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2996 ;; abssi2 doesn't really clobber the condition codes if a different register
2997 ;; is being set. To keep things simple, assume during rtl manipulations that
2998 ;; it does, but tell the final scan operator the truth. Similarly for
3001 (define_expand "abssi2"
3003 [(set (match_operand:SI 0 "s_register_operand" "")
3004 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3005 (clobber (reg:CC CC_REGNUM))])]
3009 (define_insn "*arm_abssi2"
3010 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3011 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3012 (clobber (reg:CC CC_REGNUM))]
3015 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3016 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3017 [(set_attr "conds" "clob,*")
3018 (set_attr "shift" "1")
3019 ;; predicable can't be set based on the variant, so left as no
3020 (set_attr "length" "8")]
3023 (define_insn "*neg_abssi2"
3024 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3025 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3026 (clobber (reg:CC CC_REGNUM))]
3029 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3030 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3031 [(set_attr "conds" "clob,*")
3032 (set_attr "shift" "1")
3033 ;; predicable can't be set based on the variant, so left as no
3034 (set_attr "length" "8")]
3037 (define_expand "abssf2"
3038 [(set (match_operand:SF 0 "s_register_operand" "")
3039 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3040 "TARGET_ARM && TARGET_HARD_FLOAT"
3043 (define_expand "absdf2"
3044 [(set (match_operand:DF 0 "s_register_operand" "")
3045 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3046 "TARGET_ARM && TARGET_HARD_FLOAT"
3049 (define_expand "sqrtsf2"
3050 [(set (match_operand:SF 0 "s_register_operand" "")
3051 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3052 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055 (define_expand "sqrtdf2"
3056 [(set (match_operand:DF 0 "s_register_operand" "")
3057 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3058 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3061 (define_insn_and_split "one_cmpldi2"
3062 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3063 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3066 "TARGET_ARM && reload_completed"
3067 [(set (match_dup 0) (not:SI (match_dup 1)))
3068 (set (match_dup 2) (not:SI (match_dup 3)))]
3071 operands[2] = gen_highpart (SImode, operands[0]);
3072 operands[0] = gen_lowpart (SImode, operands[0]);
3073 operands[3] = gen_highpart (SImode, operands[1]);
3074 operands[1] = gen_lowpart (SImode, operands[1]);
3076 [(set_attr "length" "8")
3077 (set_attr "predicable" "yes")]
3080 (define_expand "one_cmplsi2"
3081 [(set (match_operand:SI 0 "s_register_operand" "")
3082 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3087 (define_insn "*arm_one_cmplsi2"
3088 [(set (match_operand:SI 0 "s_register_operand" "=r")
3089 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3092 [(set_attr "predicable" "yes")]
3095 (define_insn "*thumb_one_cmplsi2"
3096 [(set (match_operand:SI 0 "register_operand" "=l")
3097 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3100 [(set_attr "length" "2")]
3103 (define_insn "*notsi_compare0"
3104 [(set (reg:CC_NOOV CC_REGNUM)
3105 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3107 (set (match_operand:SI 0 "s_register_operand" "=r")
3108 (not:SI (match_dup 1)))]
3111 [(set_attr "conds" "set")]
3114 (define_insn "*notsi_compare0_scratch"
3115 [(set (reg:CC_NOOV CC_REGNUM)
3116 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3118 (clobber (match_scratch:SI 0 "=r"))]
3121 [(set_attr "conds" "set")]
3124 ;; Fixed <--> Floating conversion insns
3126 (define_expand "floatsisf2"
3127 [(set (match_operand:SF 0 "s_register_operand" "")
3128 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3129 "TARGET_ARM && TARGET_HARD_FLOAT"
3131 if (TARGET_MAVERICK)
3133 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3138 (define_expand "floatsidf2"
3139 [(set (match_operand:DF 0 "s_register_operand" "")
3140 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3141 "TARGET_ARM && TARGET_HARD_FLOAT"
3143 if (TARGET_MAVERICK)
3145 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3150 (define_expand "fix_truncsfsi2"
3151 [(set (match_operand:SI 0 "s_register_operand" "")
3152 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3153 "TARGET_ARM && TARGET_HARD_FLOAT"
3155 if (TARGET_MAVERICK)
3157 if (!cirrus_fp_register (operands[0], SImode))
3158 operands[0] = force_reg (SImode, operands[0]);
3159 if (!cirrus_fp_register (operands[1], SFmode))
3160 operands[1] = force_reg (SFmode, operands[0]);
3161 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3166 (define_expand "fix_truncdfsi2"
3167 [(set (match_operand:SI 0 "s_register_operand" "")
3168 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3169 "TARGET_ARM && TARGET_HARD_FLOAT"
3171 if (TARGET_MAVERICK)
3173 if (!cirrus_fp_register (operands[1], DFmode))
3174 operands[1] = force_reg (DFmode, operands[0]);
3175 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3182 (define_expand "truncdfsf2"
3183 [(set (match_operand:SF 0 "s_register_operand" "")
3185 (match_operand:DF 1 "s_register_operand" "")))]
3186 "TARGET_ARM && TARGET_HARD_FLOAT"
3190 ;; Zero and sign extension instructions.
3192 (define_insn "zero_extendsidi2"
3193 [(set (match_operand:DI 0 "s_register_operand" "=r")
3194 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3197 if (REGNO (operands[1])
3198 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3199 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3200 return \"mov%?\\t%R0, #0\";
3202 [(set_attr "length" "8")
3203 (set_attr "predicable" "yes")]
3206 (define_insn "zero_extendqidi2"
3207 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3208 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3211 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3212 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3213 [(set_attr "length" "8")
3214 (set_attr "predicable" "yes")
3215 (set_attr "type" "*,load_byte")
3216 (set_attr "pool_range" "*,4092")
3217 (set_attr "neg_pool_range" "*,4084")]
3220 (define_insn "extendsidi2"
3221 [(set (match_operand:DI 0 "s_register_operand" "=r")
3222 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3225 if (REGNO (operands[1])
3226 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3227 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3228 return \"mov%?\\t%R0, %Q0, asr #31\";
3230 [(set_attr "length" "8")
3231 (set_attr "shift" "1")
3232 (set_attr "predicable" "yes")]
3235 (define_expand "zero_extendhisi2"
3237 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3239 (set (match_operand:SI 0 "s_register_operand" "")
3240 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3244 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3246 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3247 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3251 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3253 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3257 if (!s_register_operand (operands[1], HImode))
3258 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3262 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3263 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3267 operands[1] = gen_lowpart (SImode, operands[1]);
3268 operands[2] = gen_reg_rtx (SImode);
3272 (define_insn "*thumb_zero_extendhisi2"
3273 [(set (match_operand:SI 0 "register_operand" "=l")
3274 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3275 "TARGET_THUMB && !arm_arch6"
3277 rtx mem = XEXP (operands[1], 0);
3279 if (GET_CODE (mem) == CONST)
3280 mem = XEXP (mem, 0);
3282 if (GET_CODE (mem) == LABEL_REF)
3283 return \"ldr\\t%0, %1\";
3285 if (GET_CODE (mem) == PLUS)
3287 rtx a = XEXP (mem, 0);
3288 rtx b = XEXP (mem, 1);
3290 /* This can happen due to bugs in reload. */
3291 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294 ops[0] = operands[0];
3297 output_asm_insn (\"mov %0, %1\", ops);
3299 XEXP (mem, 0) = operands[0];
3302 else if ( GET_CODE (a) == LABEL_REF
3303 && GET_CODE (b) == CONST_INT)
3304 return \"ldr\\t%0, %1\";
3307 return \"ldrh\\t%0, %1\";
3309 [(set_attr "length" "4")
3310 (set_attr "type" "load_byte")
3311 (set_attr "pool_range" "60")]
3314 (define_insn "*thumb_zero_extendhisi2_v6"
3315 [(set (match_operand:SI 0 "register_operand" "=l,l")
3316 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3317 "TARGET_THUMB && arm_arch6"
3321 if (which_alternative == 0)
3322 return \"uxth\\t%0, %1\";
3324 mem = XEXP (operands[1], 0);
3326 if (GET_CODE (mem) == CONST)
3327 mem = XEXP (mem, 0);
3329 if (GET_CODE (mem) == LABEL_REF)
3330 return \"ldr\\t%0, %1\";
3332 if (GET_CODE (mem) == PLUS)
3334 rtx a = XEXP (mem, 0);
3335 rtx b = XEXP (mem, 1);
3337 /* This can happen due to bugs in reload. */
3338 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341 ops[0] = operands[0];
3344 output_asm_insn (\"mov %0, %1\", ops);
3346 XEXP (mem, 0) = operands[0];
3349 else if ( GET_CODE (a) == LABEL_REF
3350 && GET_CODE (b) == CONST_INT)
3351 return \"ldr\\t%0, %1\";
3354 return \"ldrh\\t%0, %1\";
3356 [(set_attr "length" "2,4")
3357 (set_attr "type" "alu_shift,load_byte")
3358 (set_attr "pool_range" "*,60")]
3361 (define_insn "*arm_zero_extendhisi2"
3362 [(set (match_operand:SI 0 "s_register_operand" "=r")
3363 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3364 "TARGET_ARM && arm_arch4 && !arm_arch6"
3366 [(set_attr "type" "load_byte")
3367 (set_attr "predicable" "yes")
3368 (set_attr "pool_range" "256")
3369 (set_attr "neg_pool_range" "244")]
3372 (define_insn "*arm_zero_extendhisi2_v6"
3373 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3374 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3375 "TARGET_ARM && arm_arch6"
3379 [(set_attr "type" "alu_shift,load_byte")
3380 (set_attr "predicable" "yes")
3381 (set_attr "pool_range" "*,256")
3382 (set_attr "neg_pool_range" "*,244")]
3385 (define_insn "*arm_zero_extendhisi2addsi"
3386 [(set (match_operand:SI 0 "s_register_operand" "=r")
3387 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3388 (match_operand:SI 2 "s_register_operand" "r")))]
3389 "TARGET_ARM && arm_arch6"
3390 "uxtah%?\\t%0, %2, %1"
3391 [(set_attr "type" "alu_shift")
3392 (set_attr "predicable" "yes")]
3395 (define_expand "zero_extendqisi2"
3396 [(set (match_operand:SI 0 "s_register_operand" "")
3397 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3404 emit_insn (gen_andsi3 (operands[0],
3405 gen_lowpart (SImode, operands[1]),
3408 else /* TARGET_THUMB */
3410 rtx temp = gen_reg_rtx (SImode);
3413 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3414 operands[1] = gen_lowpart (SImode, operands[1]);
3417 ops[1] = operands[1];
3418 ops[2] = GEN_INT (24);
3420 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3421 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3423 ops[0] = operands[0];
3425 ops[2] = GEN_INT (24);
3427 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3428 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3435 (define_insn "*thumb_zero_extendqisi2"
3436 [(set (match_operand:SI 0 "register_operand" "=l")
3437 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3438 "TARGET_THUMB && !arm_arch6"
3440 [(set_attr "length" "2")
3441 (set_attr "type" "load_byte")
3442 (set_attr "pool_range" "32")]
3445 (define_insn "*thumb_zero_extendqisi2_v6"
3446 [(set (match_operand:SI 0 "register_operand" "=l,l")
3447 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3448 "TARGET_THUMB && arm_arch6"
3452 [(set_attr "length" "2,2")
3453 (set_attr "type" "alu_shift,load_byte")
3454 (set_attr "pool_range" "*,32")]
3457 (define_insn "*arm_zero_extendqisi2"
3458 [(set (match_operand:SI 0 "s_register_operand" "=r")
3459 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3460 "TARGET_ARM && !arm_arch6"
3461 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3462 [(set_attr "type" "load_byte")
3463 (set_attr "predicable" "yes")
3464 (set_attr "pool_range" "4096")
3465 (set_attr "neg_pool_range" "4084")]
3468 (define_insn "*arm_zero_extendqisi2_v6"
3469 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3470 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3471 "TARGET_ARM && arm_arch6"
3474 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3475 [(set_attr "type" "alu_shift,load_byte")
3476 (set_attr "predicable" "yes")
3477 (set_attr "pool_range" "*,4096")
3478 (set_attr "neg_pool_range" "*,4084")]
3481 (define_insn "*arm_zero_extendqisi2addsi"
3482 [(set (match_operand:SI 0 "s_register_operand" "=r")
3483 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3484 (match_operand:SI 2 "s_register_operand" "r")))]
3485 "TARGET_ARM && arm_arch6"
3486 "uxtab%?\\t%0, %2, %1"
3487 [(set_attr "predicable" "yes")
3488 (set_attr "type" "alu_shift")]
3492 [(set (match_operand:SI 0 "s_register_operand" "")
3493 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3494 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3495 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3496 [(set (match_dup 2) (match_dup 1))
3497 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3501 (define_insn "*compareqi_eq0"
3502 [(set (reg:CC_Z CC_REGNUM)
3503 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3507 [(set_attr "conds" "set")]
3510 (define_expand "extendhisi2"
3512 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3514 (set (match_operand:SI 0 "s_register_operand" "")
3515 (ashiftrt:SI (match_dup 2)
3520 if (GET_CODE (operands[1]) == MEM)
3524 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3529 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3530 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3535 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3537 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3541 if (!s_register_operand (operands[1], HImode))
3542 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3547 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3549 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3550 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3555 operands[1] = gen_lowpart (SImode, operands[1]);
3556 operands[2] = gen_reg_rtx (SImode);
3560 (define_insn "thumb_extendhisi2"
3561 [(set (match_operand:SI 0 "register_operand" "=l")
3562 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3563 (clobber (match_scratch:SI 2 "=&l"))]
3564 "TARGET_THUMB && !arm_arch6"
3568 rtx mem = XEXP (operands[1], 0);
3570 /* This code used to try to use 'V', and fix the address only if it was
3571 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3572 range of QImode offsets, and offsettable_address_p does a QImode
3575 if (GET_CODE (mem) == CONST)
3576 mem = XEXP (mem, 0);
3578 if (GET_CODE (mem) == LABEL_REF)
3579 return \"ldr\\t%0, %1\";
3581 if (GET_CODE (mem) == PLUS)
3583 rtx a = XEXP (mem, 0);
3584 rtx b = XEXP (mem, 1);
3586 if (GET_CODE (a) == LABEL_REF
3587 && GET_CODE (b) == CONST_INT)
3588 return \"ldr\\t%0, %1\";
3590 if (GET_CODE (b) == REG)
3591 return \"ldrsh\\t%0, %1\";
3599 ops[2] = const0_rtx;
3602 gcc_assert (GET_CODE (ops[1]) == REG);
3604 ops[0] = operands[0];
3605 ops[3] = operands[2];
3606 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3609 [(set_attr "length" "4")
3610 (set_attr "type" "load_byte")
3611 (set_attr "pool_range" "1020")]
3614 ;; We used to have an early-clobber on the scratch register here.
3615 ;; However, there's a bug somewhere in reload which means that this
3616 ;; can be partially ignored during spill allocation if the memory
3617 ;; address also needs reloading; this causes us to die later on when
3618 ;; we try to verify the operands. Fortunately, we don't really need
3619 ;; the early-clobber: we can always use operand 0 if operand 2
3620 ;; overlaps the address.
3621 (define_insn "*thumb_extendhisi2_insn_v6"
3622 [(set (match_operand:SI 0 "register_operand" "=l,l")
3623 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3624 (clobber (match_scratch:SI 2 "=X,l"))]
3625 "TARGET_THUMB && arm_arch6"
3631 if (which_alternative == 0)
3632 return \"sxth\\t%0, %1\";
3634 mem = XEXP (operands[1], 0);
3636 /* This code used to try to use 'V', and fix the address only if it was
3637 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3638 range of QImode offsets, and offsettable_address_p does a QImode
3641 if (GET_CODE (mem) == CONST)
3642 mem = XEXP (mem, 0);
3644 if (GET_CODE (mem) == LABEL_REF)
3645 return \"ldr\\t%0, %1\";
3647 if (GET_CODE (mem) == PLUS)
3649 rtx a = XEXP (mem, 0);
3650 rtx b = XEXP (mem, 1);
3652 if (GET_CODE (a) == LABEL_REF
3653 && GET_CODE (b) == CONST_INT)
3654 return \"ldr\\t%0, %1\";
3656 if (GET_CODE (b) == REG)
3657 return \"ldrsh\\t%0, %1\";
3665 ops[2] = const0_rtx;
3668 gcc_assert (GET_CODE (ops[1]) == REG);
3670 ops[0] = operands[0];
3671 if (reg_mentioned_p (operands[2], ops[1]))
3674 ops[3] = operands[2];
3675 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3678 [(set_attr "length" "2,4")
3679 (set_attr "type" "alu_shift,load_byte")
3680 (set_attr "pool_range" "*,1020")]
3683 (define_expand "extendhisi2_mem"
3684 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3686 (zero_extend:SI (match_dup 7)))
3687 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3688 (set (match_operand:SI 0 "" "")
3689 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3694 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3696 mem1 = change_address (operands[1], QImode, addr);
3697 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3698 operands[0] = gen_lowpart (SImode, operands[0]);
3700 operands[2] = gen_reg_rtx (SImode);
3701 operands[3] = gen_reg_rtx (SImode);
3702 operands[6] = gen_reg_rtx (SImode);
3705 if (BYTES_BIG_ENDIAN)
3707 operands[4] = operands[2];
3708 operands[5] = operands[3];
3712 operands[4] = operands[3];
3713 operands[5] = operands[2];
3718 (define_insn "*arm_extendhisi2"
3719 [(set (match_operand:SI 0 "s_register_operand" "=r")
3720 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3721 "TARGET_ARM && arm_arch4 && !arm_arch6"
3723 [(set_attr "type" "load_byte")
3724 (set_attr "predicable" "yes")
3725 (set_attr "pool_range" "256")
3726 (set_attr "neg_pool_range" "244")]
3729 (define_insn "*arm_extendhisi2_v6"
3730 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3731 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3732 "TARGET_ARM && arm_arch6"
3736 [(set_attr "type" "alu_shift,load_byte")
3737 (set_attr "predicable" "yes")
3738 (set_attr "pool_range" "*,256")
3739 (set_attr "neg_pool_range" "*,244")]
3742 (define_insn "*arm_extendhisi2addsi"
3743 [(set (match_operand:SI 0 "s_register_operand" "=r")
3744 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3745 (match_operand:SI 2 "s_register_operand" "r")))]
3746 "TARGET_ARM && arm_arch6"
3747 "sxtah%?\\t%0, %2, %1"
3750 (define_expand "extendqihi2"
3752 (ashift:SI (match_operand:QI 1 "general_operand" "")
3754 (set (match_operand:HI 0 "s_register_operand" "")
3755 (ashiftrt:SI (match_dup 2)
3760 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3762 emit_insn (gen_rtx_SET (VOIDmode,
3764 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3767 if (!s_register_operand (operands[1], QImode))
3768 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3769 operands[0] = gen_lowpart (SImode, operands[0]);
3770 operands[1] = gen_lowpart (SImode, operands[1]);
3771 operands[2] = gen_reg_rtx (SImode);
3775 (define_insn "*extendqihi_insn"
3776 [(set (match_operand:HI 0 "s_register_operand" "=r")
3777 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3778 "TARGET_ARM && arm_arch4"
3780 [(set_attr "type" "load_byte")
3781 (set_attr "predicable" "yes")
3782 (set_attr "pool_range" "256")
3783 (set_attr "neg_pool_range" "244")]
3786 (define_expand "extendqisi2"
3788 (ashift:SI (match_operand:QI 1 "general_operand" "")
3790 (set (match_operand:SI 0 "s_register_operand" "")
3791 (ashiftrt:SI (match_dup 2)
3796 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3798 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3799 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3803 if (!s_register_operand (operands[1], QImode))
3804 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3808 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3809 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3813 operands[1] = gen_lowpart (SImode, operands[1]);
3814 operands[2] = gen_reg_rtx (SImode);
3818 (define_insn "*arm_extendqisi"
3819 [(set (match_operand:SI 0 "s_register_operand" "=r")
3820 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3821 "TARGET_ARM && arm_arch4 && !arm_arch6"
3823 [(set_attr "type" "load_byte")
3824 (set_attr "predicable" "yes")
3825 (set_attr "pool_range" "256")
3826 (set_attr "neg_pool_range" "244")]
3829 (define_insn "*arm_extendqisi_v6"
3830 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3831 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3832 "TARGET_ARM && arm_arch6"
3836 [(set_attr "type" "alu_shift,load_byte")
3837 (set_attr "predicable" "yes")
3838 (set_attr "pool_range" "*,256")
3839 (set_attr "neg_pool_range" "*,244")]
3842 (define_insn "*arm_extendqisi2addsi"
3843 [(set (match_operand:SI 0 "s_register_operand" "=r")
3844 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3845 (match_operand:SI 2 "s_register_operand" "r")))]
3846 "TARGET_ARM && arm_arch6"
3847 "sxtab%?\\t%0, %2, %1"
3848 [(set_attr "type" "alu_shift")
3849 (set_attr "predicable" "yes")]
3852 (define_insn "*thumb_extendqisi2"
3853 [(set (match_operand:SI 0 "register_operand" "=l,l")
3854 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3855 "TARGET_THUMB && !arm_arch6"
3859 rtx mem = XEXP (operands[1], 0);
3861 if (GET_CODE (mem) == CONST)
3862 mem = XEXP (mem, 0);
3864 if (GET_CODE (mem) == LABEL_REF)
3865 return \"ldr\\t%0, %1\";
3867 if (GET_CODE (mem) == PLUS
3868 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3869 return \"ldr\\t%0, %1\";
3871 if (which_alternative == 0)
3872 return \"ldrsb\\t%0, %1\";
3874 ops[0] = operands[0];
3876 if (GET_CODE (mem) == PLUS)
3878 rtx a = XEXP (mem, 0);
3879 rtx b = XEXP (mem, 1);
3884 if (GET_CODE (a) == REG)
3886 if (GET_CODE (b) == REG)
3887 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3888 else if (REGNO (a) == REGNO (ops[0]))
3890 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3891 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3892 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3899 gcc_assert (GET_CODE (b) == REG);
3900 if (REGNO (b) == REGNO (ops[0]))
3902 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3903 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3904 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3907 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3910 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3912 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3913 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3914 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3919 ops[2] = const0_rtx;
3921 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3925 [(set_attr "length" "2,6")
3926 (set_attr "type" "load_byte,load_byte")
3927 (set_attr "pool_range" "32,32")]
3930 (define_insn "*thumb_extendqisi2_v6"
3931 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3932 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3933 "TARGET_THUMB && arm_arch6"
3939 if (which_alternative == 0)
3940 return \"sxtb\\t%0, %1\";
3942 mem = XEXP (operands[1], 0);
3944 if (GET_CODE (mem) == CONST)
3945 mem = XEXP (mem, 0);
3947 if (GET_CODE (mem) == LABEL_REF)
3948 return \"ldr\\t%0, %1\";
3950 if (GET_CODE (mem) == PLUS
3951 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3952 return \"ldr\\t%0, %1\";
3954 if (which_alternative == 0)
3955 return \"ldrsb\\t%0, %1\";
3957 ops[0] = operands[0];
3959 if (GET_CODE (mem) == PLUS)
3961 rtx a = XEXP (mem, 0);
3962 rtx b = XEXP (mem, 1);
3967 if (GET_CODE (a) == REG)
3969 if (GET_CODE (b) == REG)
3970 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3971 else if (REGNO (a) == REGNO (ops[0]))
3973 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3974 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3977 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981 gcc_assert (GET_CODE (b) == REG);
3982 if (REGNO (b) == REGNO (ops[0]))
3984 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3985 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3988 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3993 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3994 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3999 ops[2] = const0_rtx;
4001 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4005 [(set_attr "length" "2,2,4")
4006 (set_attr "type" "alu_shift,load_byte,load_byte")
4007 (set_attr "pool_range" "*,32,32")]
4010 (define_expand "extendsfdf2"
4011 [(set (match_operand:DF 0 "s_register_operand" "")
4012 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4013 "TARGET_ARM && TARGET_HARD_FLOAT"
4017 ;; Move insns (including loads and stores)
4019 ;; XXX Just some ideas about movti.
4020 ;; I don't think these are a good idea on the arm, there just aren't enough
4022 ;;(define_expand "loadti"
4023 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4024 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4027 ;;(define_expand "storeti"
4028 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4029 ;; (match_operand:TI 1 "s_register_operand" ""))]
4032 ;;(define_expand "movti"
4033 ;; [(set (match_operand:TI 0 "general_operand" "")
4034 ;; (match_operand:TI 1 "general_operand" ""))]
4040 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4041 ;; operands[1] = copy_to_reg (operands[1]);
4042 ;; if (GET_CODE (operands[0]) == MEM)
4043 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4044 ;; else if (GET_CODE (operands[1]) == MEM)
4045 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4049 ;; emit_insn (insn);
4053 ;; Recognize garbage generated above.
4056 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4057 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4061 ;; register mem = (which_alternative < 3);
4062 ;; register const char *template;
4064 ;; operands[mem] = XEXP (operands[mem], 0);
4065 ;; switch (which_alternative)
4067 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4068 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4069 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4070 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4071 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4072 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4074 ;; output_asm_insn (template, operands);
4078 (define_expand "movdi"
4079 [(set (match_operand:DI 0 "general_operand" "")
4080 (match_operand:DI 1 "general_operand" ""))]
4085 if (!no_new_pseudos)
4087 if (GET_CODE (operands[0]) != REG)
4088 operands[1] = force_reg (DImode, operands[1]);
4094 (define_insn "*arm_movdi"
4095 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4096 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4098 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4101 switch (which_alternative)
4108 return output_move_double (operands);
4111 [(set_attr "length" "8,12,16,8,8")
4112 (set_attr "type" "*,*,*,load2,store2")
4113 (set_attr "pool_range" "*,*,*,1020,*")
4114 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4118 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4119 (match_operand:ANY64 1 "const_double_operand" ""))]
4122 && (arm_const_double_inline_cost (operands[1])
4123 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4126 arm_split_constant (SET, SImode, curr_insn,
4127 INTVAL (gen_lowpart (SImode, operands[1])),
4128 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4129 arm_split_constant (SET, SImode, curr_insn,
4130 INTVAL (gen_highpart_mode (SImode,
4131 GET_MODE (operands[0]),
4133 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4138 ; If optimizing for size, or if we have load delay slots, then
4139 ; we want to split the constant into two separate operations.
4140 ; In both cases this may split a trivial part into a single data op
4141 ; leaving a single complex constant to load. We can also get longer
4142 ; offsets in a LDR which means we get better chances of sharing the pool
4143 ; entries. Finally, we can normally do a better job of scheduling
4144 ; LDR instructions than we can with LDM.
4145 ; This pattern will only match if the one above did not.
4147 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4148 (match_operand:ANY64 1 "const_double_operand" ""))]
4149 "TARGET_ARM && reload_completed
4150 && arm_const_double_by_parts (operands[1])"
4151 [(set (match_dup 0) (match_dup 1))
4152 (set (match_dup 2) (match_dup 3))]
4154 operands[2] = gen_highpart (SImode, operands[0]);
4155 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4157 operands[0] = gen_lowpart (SImode, operands[0]);
4158 operands[1] = gen_lowpart (SImode, operands[1]);
4163 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4164 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4165 "TARGET_EITHER && reload_completed"
4166 [(set (match_dup 0) (match_dup 1))
4167 (set (match_dup 2) (match_dup 3))]
4169 operands[2] = gen_highpart (SImode, operands[0]);
4170 operands[3] = gen_highpart (SImode, operands[1]);
4171 operands[0] = gen_lowpart (SImode, operands[0]);
4172 operands[1] = gen_lowpart (SImode, operands[1]);
4174 /* Handle a partial overlap. */
4175 if (rtx_equal_p (operands[0], operands[3]))
4177 rtx tmp0 = operands[0];
4178 rtx tmp1 = operands[1];
4180 operands[0] = operands[2];
4181 operands[1] = operands[3];
4188 ;; We can't actually do base+index doubleword loads if the index and
4189 ;; destination overlap. Split here so that we at least have chance to
4192 [(set (match_operand:DI 0 "s_register_operand" "")
4193 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4194 (match_operand:SI 2 "s_register_operand" ""))))]
4196 && reg_overlap_mentioned_p (operands[0], operands[1])
4197 && reg_overlap_mentioned_p (operands[0], operands[2])"
4199 (plus:SI (match_dup 1)
4202 (mem:DI (match_dup 4)))]
4204 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4208 ;;; ??? This should have alternatives for constants.
4209 ;;; ??? This was originally identical to the movdf_insn pattern.
4210 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4211 ;;; thumb_reorg with a memory reference.
4212 (define_insn "*thumb_movdi_insn"
4213 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4214 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4216 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4217 && ( register_operand (operands[0], DImode)
4218 || register_operand (operands[1], DImode))"
4221 switch (which_alternative)
4225 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4226 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4227 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4229 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4231 operands[1] = GEN_INT (- INTVAL (operands[1]));
4232 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4234 return \"ldmia\\t%1, {%0, %H0}\";
4236 return \"stmia\\t%0, {%1, %H1}\";
4238 return thumb_load_double_from_address (operands);
4240 operands[2] = gen_rtx_MEM (SImode,
4241 plus_constant (XEXP (operands[0], 0), 4));
4242 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4245 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4246 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4247 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4250 [(set_attr "length" "4,4,6,2,2,6,4,4")
4251 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4252 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4255 (define_expand "movsi"
4256 [(set (match_operand:SI 0 "general_operand" "")
4257 (match_operand:SI 1 "general_operand" ""))]
4262 /* Everything except mem = const or mem = mem can be done easily. */
4263 if (GET_CODE (operands[0]) == MEM)
4264 operands[1] = force_reg (SImode, operands[1]);
4265 if (arm_general_register_operand (operands[0], SImode)
4266 && GET_CODE (operands[1]) == CONST_INT
4267 && !(const_ok_for_arm (INTVAL (operands[1]))
4268 || const_ok_for_arm (~INTVAL (operands[1]))))
4270 arm_split_constant (SET, SImode, NULL_RTX,
4271 INTVAL (operands[1]), operands[0], NULL_RTX,
4272 optimize && !no_new_pseudos);
4276 else /* TARGET_THUMB.... */
4278 if (!no_new_pseudos)
4280 if (GET_CODE (operands[0]) != REG)
4281 operands[1] = force_reg (SImode, operands[1]);
4285 /* Recognize the case where operand[1] is a reference to thread-local
4286 data and load its address to a register. */
4287 if (arm_tls_referenced_p (operands[1]))
4289 rtx tmp = operands[1];
4292 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4294 addend = XEXP (XEXP (tmp, 0), 1);
4295 tmp = XEXP (XEXP (tmp, 0), 0);
4298 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4299 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4301 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4304 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4305 tmp = force_operand (tmp, operands[0]);
4310 && (CONSTANT_P (operands[1])
4311 || symbol_mentioned_p (operands[1])
4312 || label_mentioned_p (operands[1])))
4313 operands[1] = legitimize_pic_address (operands[1], SImode,
4314 (no_new_pseudos ? operands[0] : 0));
4318 (define_insn "*arm_movsi_insn"
4319 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4320 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4321 "TARGET_ARM && ! TARGET_IWMMXT
4322 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4323 && ( register_operand (operands[0], SImode)
4324 || register_operand (operands[1], SImode))"
4330 [(set_attr "type" "*,*,load1,store1")
4331 (set_attr "predicable" "yes")
4332 (set_attr "pool_range" "*,*,4096,*")
4333 (set_attr "neg_pool_range" "*,*,4084,*")]
4337 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4338 (match_operand:SI 1 "const_int_operand" ""))]
4340 && (!(const_ok_for_arm (INTVAL (operands[1]))
4341 || const_ok_for_arm (~INTVAL (operands[1]))))"
4342 [(clobber (const_int 0))]
4344 arm_split_constant (SET, SImode, NULL_RTX,
4345 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4350 (define_insn "*thumb_movsi_insn"
4351 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4352 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4354 && ( register_operand (operands[0], SImode)
4355 || register_operand (operands[1], SImode))"
4366 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4367 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4368 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4372 [(set (match_operand:SI 0 "register_operand" "")
4373 (match_operand:SI 1 "const_int_operand" ""))]
4374 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4375 [(set (match_dup 0) (match_dup 1))
4376 (set (match_dup 0) (neg:SI (match_dup 0)))]
4377 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4381 [(set (match_operand:SI 0 "register_operand" "")
4382 (match_operand:SI 1 "const_int_operand" ""))]
4383 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4384 [(set (match_dup 0) (match_dup 1))
4385 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4388 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4389 unsigned HOST_WIDE_INT mask = 0xff;
4392 for (i = 0; i < 25; i++)
4393 if ((val & (mask << i)) == val)
4396 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4400 operands[1] = GEN_INT (val >> i);
4401 operands[2] = GEN_INT (i);
4405 ;; When generating pic, we need to load the symbol offset into a register.
4406 ;; So that the optimizer does not confuse this with a normal symbol load
4407 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4408 ;; since that is the only type of relocation we can use.
4410 ;; The rather odd constraints on the following are to force reload to leave
4411 ;; the insn alone, and to force the minipool generation pass to then move
4412 ;; the GOT symbol to memory.
4414 (define_insn "pic_load_addr_arm"
4415 [(set (match_operand:SI 0 "s_register_operand" "=r")
4416 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4417 "TARGET_ARM && flag_pic"
4419 [(set_attr "type" "load1")
4420 (set (attr "pool_range") (const_int 4096))
4421 (set (attr "neg_pool_range") (const_int 4084))]
4424 (define_insn "pic_load_addr_thumb"
4425 [(set (match_operand:SI 0 "s_register_operand" "=l")
4426 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4427 "TARGET_THUMB && flag_pic"
4429 [(set_attr "type" "load1")
4430 (set (attr "pool_range") (const_int 1024))]
4433 ;; This variant is used for AOF assembly, since it needs to mention the
4434 ;; pic register in the rtl.
4435 (define_expand "pic_load_addr_based"
4436 [(set (match_operand:SI 0 "s_register_operand" "")
4437 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4438 "TARGET_ARM && flag_pic"
4439 "operands[2] = pic_offset_table_rtx;"
4442 (define_insn "*pic_load_addr_based_insn"
4443 [(set (match_operand:SI 0 "s_register_operand" "=r")
4444 (unspec:SI [(match_operand 1 "" "")
4445 (match_operand 2 "s_register_operand" "r")]
4447 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4449 #ifdef AOF_ASSEMBLER
4450 operands[1] = aof_pic_entry (operands[1]);
4452 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4455 [(set_attr "type" "load1")
4456 (set (attr "pool_range")
4457 (if_then_else (eq_attr "is_thumb" "yes")
4460 (set (attr "neg_pool_range")
4461 (if_then_else (eq_attr "is_thumb" "yes")
4466 (define_insn "pic_add_dot_plus_four"
4467 [(set (match_operand:SI 0 "register_operand" "+r")
4468 (unspec:SI [(plus:SI (match_dup 0)
4469 (const (plus:SI (pc) (const_int 4))))]
4471 (use (label_ref (match_operand 1 "" "")))]
4474 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4475 CODE_LABEL_NUMBER (operands[1]));
4476 return \"add\\t%0, %|pc\";
4478 [(set_attr "length" "2")]
4481 (define_insn "pic_add_dot_plus_eight"
4482 [(set (match_operand:SI 0 "register_operand" "+r")
4483 (unspec:SI [(plus:SI (match_dup 0)
4484 (const (plus:SI (pc) (const_int 8))))]
4486 (use (label_ref (match_operand 1 "" "")))]
4489 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4490 CODE_LABEL_NUMBER (operands[1]));
4491 return \"add%?\\t%0, %|pc, %0\";
4493 [(set_attr "predicable" "yes")]
4496 (define_insn "tls_load_dot_plus_eight"
4497 [(set (match_operand:SI 0 "register_operand" "+r")
4498 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4499 (const (plus:SI (pc) (const_int 8))))]
4501 (use (label_ref (match_operand 2 "" "")))]
4504 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4505 CODE_LABEL_NUMBER (operands[2]));
4506 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4508 [(set_attr "predicable" "yes")]
4511 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4512 ;; followed by a load. These sequences can be crunched down to
4513 ;; tls_load_dot_plus_eight by a peephole.
4516 [(parallel [(set (match_operand:SI 0 "register_operand" "")
4517 (unspec:SI [(plus:SI (match_dup 0)
4518 (const (plus:SI (pc) (const_int 8))))]
4520 (use (label_ref (match_operand 1 "" "")))])
4521 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4522 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4523 [(parallel [(set (match_operand:SI 2 "register_operand" "+r")
4524 (mem:SI (unspec:SI [(plus:SI (match_dup 0)
4525 (const (plus:SI (pc) (const_int 8))))]
4527 (use (label_ref (match_operand 1 "" "")))])]
4531 (define_expand "builtin_setjmp_receiver"
4532 [(label_ref (match_operand 0 "" ""))]
4536 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4538 arm_load_pic_register (3);
4542 ;; If copying one reg to another we can set the condition codes according to
4543 ;; its value. Such a move is common after a return from subroutine and the
4544 ;; result is being tested against zero.
4546 (define_insn "*movsi_compare0"
4547 [(set (reg:CC CC_REGNUM)
4548 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4550 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4555 sub%?s\\t%0, %1, #0"
4556 [(set_attr "conds" "set")]
4559 ;; Subroutine to store a half word from a register into memory.
4560 ;; Operand 0 is the source register (HImode)
4561 ;; Operand 1 is the destination address in a register (SImode)
4563 ;; In both this routine and the next, we must be careful not to spill
4564 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4565 ;; can generate unrecognizable rtl.
4567 (define_expand "storehi"
4568 [;; store the low byte
4569 (set (match_operand 1 "" "") (match_dup 3))
4570 ;; extract the high byte
4572 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4573 ;; store the high byte
4574 (set (match_dup 4) (match_dup 5))]
4578 rtx op1 = operands[1];
4579 rtx addr = XEXP (op1, 0);
4580 enum rtx_code code = GET_CODE (addr);
4582 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4584 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4586 operands[4] = adjust_address (op1, QImode, 1);
4587 operands[1] = adjust_address (operands[1], QImode, 0);
4588 operands[3] = gen_lowpart (QImode, operands[0]);
4589 operands[0] = gen_lowpart (SImode, operands[0]);
4590 operands[2] = gen_reg_rtx (SImode);
4591 operands[5] = gen_lowpart (QImode, operands[2]);
4595 (define_expand "storehi_bigend"
4596 [(set (match_dup 4) (match_dup 3))
4598 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4599 (set (match_operand 1 "" "") (match_dup 5))]
4603 rtx op1 = operands[1];
4604 rtx addr = XEXP (op1, 0);
4605 enum rtx_code code = GET_CODE (addr);
4607 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4609 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4611 operands[4] = adjust_address (op1, QImode, 1);
4612 operands[1] = adjust_address (operands[1], QImode, 0);
4613 operands[3] = gen_lowpart (QImode, operands[0]);
4614 operands[0] = gen_lowpart (SImode, operands[0]);
4615 operands[2] = gen_reg_rtx (SImode);
4616 operands[5] = gen_lowpart (QImode, operands[2]);
4620 ;; Subroutine to store a half word integer constant into memory.
4621 (define_expand "storeinthi"
4622 [(set (match_operand 0 "" "")
4623 (match_operand 1 "" ""))
4624 (set (match_dup 3) (match_dup 2))]
4628 HOST_WIDE_INT value = INTVAL (operands[1]);
4629 rtx addr = XEXP (operands[0], 0);
4630 rtx op0 = operands[0];
4631 enum rtx_code code = GET_CODE (addr);
4633 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4635 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4637 operands[1] = gen_reg_rtx (SImode);
4638 if (BYTES_BIG_ENDIAN)
4640 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4641 if ((value & 255) == ((value >> 8) & 255))
4642 operands[2] = operands[1];
4645 operands[2] = gen_reg_rtx (SImode);
4646 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4651 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4652 if ((value & 255) == ((value >> 8) & 255))
4653 operands[2] = operands[1];
4656 operands[2] = gen_reg_rtx (SImode);
4657 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4661 operands[3] = adjust_address (op0, QImode, 1);
4662 operands[0] = adjust_address (operands[0], QImode, 0);
4663 operands[2] = gen_lowpart (QImode, operands[2]);
4664 operands[1] = gen_lowpart (QImode, operands[1]);
4668 (define_expand "storehi_single_op"
4669 [(set (match_operand:HI 0 "memory_operand" "")
4670 (match_operand:HI 1 "general_operand" ""))]
4671 "TARGET_ARM && arm_arch4"
4673 if (!s_register_operand (operands[1], HImode))
4674 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4678 (define_expand "movhi"
4679 [(set (match_operand:HI 0 "general_operand" "")
4680 (match_operand:HI 1 "general_operand" ""))]
4685 if (!no_new_pseudos)
4687 if (GET_CODE (operands[0]) == MEM)
4691 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4694 if (GET_CODE (operands[1]) == CONST_INT)
4695 emit_insn (gen_storeinthi (operands[0], operands[1]));
4698 if (GET_CODE (operands[1]) == MEM)
4699 operands[1] = force_reg (HImode, operands[1]);
4700 if (BYTES_BIG_ENDIAN)
4701 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4703 emit_insn (gen_storehi (operands[1], operands[0]));
4707 /* Sign extend a constant, and keep it in an SImode reg. */
4708 else if (GET_CODE (operands[1]) == CONST_INT)
4710 rtx reg = gen_reg_rtx (SImode);
4711 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4713 /* If the constant is already valid, leave it alone. */
4714 if (!const_ok_for_arm (val))
4716 /* If setting all the top bits will make the constant
4717 loadable in a single instruction, then set them.
4718 Otherwise, sign extend the number. */
4720 if (const_ok_for_arm (~(val | ~0xffff)))
4722 else if (val & 0x8000)
4726 emit_insn (gen_movsi (reg, GEN_INT (val)));
4727 operands[1] = gen_lowpart (HImode, reg);
4729 else if (arm_arch4 && optimize && !no_new_pseudos
4730 && GET_CODE (operands[1]) == MEM)
4732 rtx reg = gen_reg_rtx (SImode);
4734 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4735 operands[1] = gen_lowpart (HImode, reg);
4737 else if (!arm_arch4)
4739 if (GET_CODE (operands[1]) == MEM)
4742 rtx offset = const0_rtx;
4743 rtx reg = gen_reg_rtx (SImode);
4745 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4746 || (GET_CODE (base) == PLUS
4747 && (GET_CODE (offset = XEXP (base, 1))
4749 && ((INTVAL(offset) & 1) != 1)
4750 && GET_CODE (base = XEXP (base, 0)) == REG))
4751 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4755 new = widen_memory_access (operands[1], SImode,
4756 ((INTVAL (offset) & ~3)
4757 - INTVAL (offset)));
4758 emit_insn (gen_movsi (reg, new));
4759 if (((INTVAL (offset) & 2) != 0)
4760 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4762 rtx reg2 = gen_reg_rtx (SImode);
4764 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4769 emit_insn (gen_movhi_bytes (reg, operands[1]));
4771 operands[1] = gen_lowpart (HImode, reg);
4775 /* Handle loading a large integer during reload. */
4776 else if (GET_CODE (operands[1]) == CONST_INT
4777 && !const_ok_for_arm (INTVAL (operands[1]))
4778 && !const_ok_for_arm (~INTVAL (operands[1])))
4780 /* Writing a constant to memory needs a scratch, which should
4781 be handled with SECONDARY_RELOADs. */
4782 gcc_assert (GET_CODE (operands[0]) == REG);
4784 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4785 emit_insn (gen_movsi (operands[0], operands[1]));
4789 else /* TARGET_THUMB */
4791 if (!no_new_pseudos)
4793 if (GET_CODE (operands[1]) == CONST_INT)
4795 rtx reg = gen_reg_rtx (SImode);
4797 emit_insn (gen_movsi (reg, operands[1]));
4798 operands[1] = gen_lowpart (HImode, reg);
4801 /* ??? We shouldn't really get invalid addresses here, but this can
4802 happen if we are passed a SP (never OK for HImode/QImode) or
4803 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4804 HImode/QImode) relative address. */
4805 /* ??? This should perhaps be fixed elsewhere, for instance, in
4806 fixup_stack_1, by checking for other kinds of invalid addresses,
4807 e.g. a bare reference to a virtual register. This may confuse the
4808 alpha though, which must handle this case differently. */
4809 if (GET_CODE (operands[0]) == MEM
4810 && !memory_address_p (GET_MODE (operands[0]),
4811 XEXP (operands[0], 0)))
4813 = replace_equiv_address (operands[0],
4814 copy_to_reg (XEXP (operands[0], 0)));
4816 if (GET_CODE (operands[1]) == MEM
4817 && !memory_address_p (GET_MODE (operands[1]),
4818 XEXP (operands[1], 0)))
4820 = replace_equiv_address (operands[1],
4821 copy_to_reg (XEXP (operands[1], 0)));
4823 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4825 rtx reg = gen_reg_rtx (SImode);
4827 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4828 operands[1] = gen_lowpart (HImode, reg);
4831 if (GET_CODE (operands[0]) == MEM)
4832 operands[1] = force_reg (HImode, operands[1]);
4834 else if (GET_CODE (operands[1]) == CONST_INT
4835 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4837 /* Handle loading a large integer during reload. */
4839 /* Writing a constant to memory needs a scratch, which should
4840 be handled with SECONDARY_RELOADs. */
4841 gcc_assert (GET_CODE (operands[0]) == REG);
4843 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4844 emit_insn (gen_movsi (operands[0], operands[1]));
4851 (define_insn "*thumb_movhi_insn"
4852 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4853 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4855 && ( register_operand (operands[0], HImode)
4856 || register_operand (operands[1], HImode))"
4858 switch (which_alternative)
4860 case 0: return \"add %0, %1, #0\";
4861 case 2: return \"strh %1, %0\";
4862 case 3: return \"mov %0, %1\";
4863 case 4: return \"mov %0, %1\";
4864 case 5: return \"mov %0, %1\";
4865 default: gcc_unreachable ();
4867 /* The stack pointer can end up being taken as an index register.
4868 Catch this case here and deal with it. */
4869 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4870 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4871 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4874 ops[0] = operands[0];
4875 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4877 output_asm_insn (\"mov %0, %1\", ops);
4879 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4882 return \"ldrh %0, %1\";
4884 [(set_attr "length" "2,4,2,2,2,2")
4885 (set_attr "type" "*,load1,store1,*,*,*")]
4889 (define_expand "movhi_bytes"
4890 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4892 (zero_extend:SI (match_dup 6)))
4893 (set (match_operand:SI 0 "" "")
4894 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4899 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4901 mem1 = change_address (operands[1], QImode, addr);
4902 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4903 operands[0] = gen_lowpart (SImode, operands[0]);
4905 operands[2] = gen_reg_rtx (SImode);
4906 operands[3] = gen_reg_rtx (SImode);
4909 if (BYTES_BIG_ENDIAN)
4911 operands[4] = operands[2];
4912 operands[5] = operands[3];
4916 operands[4] = operands[3];
4917 operands[5] = operands[2];
4922 (define_expand "movhi_bigend"
4924 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4927 (ashiftrt:SI (match_dup 2) (const_int 16)))
4928 (set (match_operand:HI 0 "s_register_operand" "")
4932 operands[2] = gen_reg_rtx (SImode);
4933 operands[3] = gen_reg_rtx (SImode);
4934 operands[4] = gen_lowpart (HImode, operands[3]);
4938 ;; Pattern to recognize insn generated default case above
4939 (define_insn "*movhi_insn_arch4"
4940 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4941 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4944 && (GET_CODE (operands[1]) != CONST_INT
4945 || const_ok_for_arm (INTVAL (operands[1]))
4946 || const_ok_for_arm (~INTVAL (operands[1])))"
4948 mov%?\\t%0, %1\\t%@ movhi
4949 mvn%?\\t%0, #%B1\\t%@ movhi
4950 str%?h\\t%1, %0\\t%@ movhi
4951 ldr%?h\\t%0, %1\\t%@ movhi"
4952 [(set_attr "type" "*,*,store1,load1")
4953 (set_attr "predicable" "yes")
4954 (set_attr "pool_range" "*,*,*,256")
4955 (set_attr "neg_pool_range" "*,*,*,244")]
4958 (define_insn "*movhi_bytes"
4959 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4960 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4963 mov%?\\t%0, %1\\t%@ movhi
4964 mvn%?\\t%0, #%B1\\t%@ movhi"
4965 [(set_attr "predicable" "yes")]
4968 (define_expand "thumb_movhi_clobber"
4969 [(set (match_operand:HI 0 "memory_operand" "")
4970 (match_operand:HI 1 "register_operand" ""))
4971 (clobber (match_operand:DI 2 "register_operand" ""))]
4974 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4975 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4977 emit_insn (gen_movhi (operands[0], operands[1]));
4980 /* XXX Fixme, need to handle other cases here as well. */
4985 ;; We use a DImode scratch because we may occasionally need an additional
4986 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4987 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4988 (define_expand "reload_outhi"
4989 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4990 (match_operand:HI 1 "s_register_operand" "r")
4991 (match_operand:DI 2 "s_register_operand" "=&l")])]
4994 arm_reload_out_hi (operands);
4996 thumb_reload_out_hi (operands);
5001 (define_expand "reload_inhi"
5002 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5003 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5004 (match_operand:DI 2 "s_register_operand" "=&r")])]
5008 arm_reload_in_hi (operands);
5010 thumb_reload_out_hi (operands);
5014 (define_expand "movqi"
5015 [(set (match_operand:QI 0 "general_operand" "")
5016 (match_operand:QI 1 "general_operand" ""))]
5019 /* Everything except mem = const or mem = mem can be done easily */
5021 if (!no_new_pseudos)
5023 if (GET_CODE (operands[1]) == CONST_INT)
5025 rtx reg = gen_reg_rtx (SImode);
5027 emit_insn (gen_movsi (reg, operands[1]));
5028 operands[1] = gen_lowpart (QImode, reg);
5033 /* ??? We shouldn't really get invalid addresses here, but this can
5034 happen if we are passed a SP (never OK for HImode/QImode) or
5035 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5036 HImode/QImode) relative address. */
5037 /* ??? This should perhaps be fixed elsewhere, for instance, in
5038 fixup_stack_1, by checking for other kinds of invalid addresses,
5039 e.g. a bare reference to a virtual register. This may confuse the
5040 alpha though, which must handle this case differently. */
5041 if (GET_CODE (operands[0]) == MEM
5042 && !memory_address_p (GET_MODE (operands[0]),
5043 XEXP (operands[0], 0)))
5045 = replace_equiv_address (operands[0],
5046 copy_to_reg (XEXP (operands[0], 0)));
5047 if (GET_CODE (operands[1]) == MEM
5048 && !memory_address_p (GET_MODE (operands[1]),
5049 XEXP (operands[1], 0)))
5051 = replace_equiv_address (operands[1],
5052 copy_to_reg (XEXP (operands[1], 0)));
5055 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5057 rtx reg = gen_reg_rtx (SImode);
5059 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5060 operands[1] = gen_lowpart (QImode, reg);
5063 if (GET_CODE (operands[0]) == MEM)
5064 operands[1] = force_reg (QImode, operands[1]);
5066 else if (TARGET_THUMB
5067 && GET_CODE (operands[1]) == CONST_INT
5068 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5070 /* Handle loading a large integer during reload. */
5072 /* Writing a constant to memory needs a scratch, which should
5073 be handled with SECONDARY_RELOADs. */
5074 gcc_assert (GET_CODE (operands[0]) == REG);
5076 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5077 emit_insn (gen_movsi (operands[0], operands[1]));
5084 (define_insn "*arm_movqi_insn"
5085 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5086 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5088 && ( register_operand (operands[0], QImode)
5089 || register_operand (operands[1], QImode))"
5095 [(set_attr "type" "*,*,load1,store1")
5096 (set_attr "predicable" "yes")]
5099 (define_insn "*thumb_movqi_insn"
5100 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5101 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5103 && ( register_operand (operands[0], QImode)
5104 || register_operand (operands[1], QImode))"
5112 [(set_attr "length" "2")
5113 (set_attr "type" "*,load1,store1,*,*,*")
5114 (set_attr "pool_range" "*,32,*,*,*,*")]
5117 (define_expand "movsf"
5118 [(set (match_operand:SF 0 "general_operand" "")
5119 (match_operand:SF 1 "general_operand" ""))]
5124 if (GET_CODE (operands[0]) == MEM)
5125 operands[1] = force_reg (SFmode, operands[1]);
5127 else /* TARGET_THUMB */
5129 if (!no_new_pseudos)
5131 if (GET_CODE (operands[0]) != REG)
5132 operands[1] = force_reg (SFmode, operands[1]);
5139 [(set (match_operand:SF 0 "nonimmediate_operand" "")
5140 (match_operand:SF 1 "immediate_operand" ""))]
5142 && !(TARGET_HARD_FLOAT && TARGET_FPA)
5144 && GET_CODE (operands[1]) == CONST_DOUBLE"
5145 [(set (match_dup 2) (match_dup 3))]
5147 operands[2] = gen_lowpart (SImode, operands[0]);
5148 operands[3] = gen_lowpart (SImode, operands[1]);
5149 if (operands[2] == 0 || operands[3] == 0)
5154 (define_insn "*arm_movsf_soft_insn"
5155 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5156 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5158 && TARGET_SOFT_FLOAT
5159 && (GET_CODE (operands[0]) != MEM
5160 || register_operand (operands[1], SFmode))"
5163 ldr%?\\t%0, %1\\t%@ float
5164 str%?\\t%1, %0\\t%@ float"
5165 [(set_attr "length" "4,4,4")
5166 (set_attr "predicable" "yes")
5167 (set_attr "type" "*,load1,store1")
5168 (set_attr "pool_range" "*,4096,*")
5169 (set_attr "neg_pool_range" "*,4084,*")]
5172 ;;; ??? This should have alternatives for constants.
5173 (define_insn "*thumb_movsf_insn"
5174 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5175 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5177 && ( register_operand (operands[0], SFmode)
5178 || register_operand (operands[1], SFmode))"
5187 [(set_attr "length" "2")
5188 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5189 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5192 (define_expand "movdf"
5193 [(set (match_operand:DF 0 "general_operand" "")
5194 (match_operand:DF 1 "general_operand" ""))]
5199 if (GET_CODE (operands[0]) == MEM)
5200 operands[1] = force_reg (DFmode, operands[1]);
5202 else /* TARGET_THUMB */
5204 if (!no_new_pseudos)
5206 if (GET_CODE (operands[0]) != REG)
5207 operands[1] = force_reg (DFmode, operands[1]);
5213 ;; Reloading a df mode value stored in integer regs to memory can require a
5215 (define_expand "reload_outdf"
5216 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5217 (match_operand:DF 1 "s_register_operand" "r")
5218 (match_operand:SI 2 "s_register_operand" "=&r")]
5222 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5225 operands[2] = XEXP (operands[0], 0);
5226 else if (code == POST_INC || code == PRE_DEC)
5228 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5229 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5230 emit_insn (gen_movdi (operands[0], operands[1]));
5233 else if (code == PRE_INC)
5235 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5237 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5240 else if (code == POST_DEC)
5241 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5243 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5244 XEXP (XEXP (operands[0], 0), 1)));
5246 emit_insn (gen_rtx_SET (VOIDmode,
5247 replace_equiv_address (operands[0], operands[2]),
5250 if (code == POST_DEC)
5251 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5257 (define_insn "*movdf_soft_insn"
5258 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5259 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5260 "TARGET_ARM && TARGET_SOFT_FLOAT
5263 switch (which_alternative)
5270 return output_move_double (operands);
5273 [(set_attr "length" "8,12,16,8,8")
5274 (set_attr "type" "*,*,*,load2,store2")
5275 (set_attr "pool_range" "1020")
5276 (set_attr "neg_pool_range" "1008")]
5279 ;;; ??? This should have alternatives for constants.
5280 ;;; ??? This was originally identical to the movdi_insn pattern.
5281 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5282 ;;; thumb_reorg with a memory reference.
5283 (define_insn "*thumb_movdf_insn"
5284 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5285 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5287 && ( register_operand (operands[0], DFmode)
5288 || register_operand (operands[1], DFmode))"
5290 switch (which_alternative)
5294 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5295 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5296 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5298 return \"ldmia\\t%1, {%0, %H0}\";
5300 return \"stmia\\t%0, {%1, %H1}\";
5302 return thumb_load_double_from_address (operands);
5304 operands[2] = gen_rtx_MEM (SImode,
5305 plus_constant (XEXP (operands[0], 0), 4));
5306 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5309 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5310 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5311 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5314 [(set_attr "length" "4,2,2,6,4,4")
5315 (set_attr "type" "*,load2,store2,load2,store2,*")
5316 (set_attr "pool_range" "*,*,*,1020,*,*")]
5319 (define_expand "movxf"
5320 [(set (match_operand:XF 0 "general_operand" "")
5321 (match_operand:XF 1 "general_operand" ""))]
5322 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5324 if (GET_CODE (operands[0]) == MEM)
5325 operands[1] = force_reg (XFmode, operands[1]);
5330 (define_expand "movv2si"
5331 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5332 (match_operand:V2SI 1 "general_operand" ""))]
5333 "TARGET_REALLY_IWMMXT"
5337 (define_expand "movv4hi"
5338 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5339 (match_operand:V4HI 1 "general_operand" ""))]
5340 "TARGET_REALLY_IWMMXT"
5344 (define_expand "movv8qi"
5345 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5346 (match_operand:V8QI 1 "general_operand" ""))]
5347 "TARGET_REALLY_IWMMXT"
5352 ;; load- and store-multiple insns
5353 ;; The arm can load/store any set of registers, provided that they are in
5354 ;; ascending order; but that is beyond GCC so stick with what it knows.
5356 (define_expand "load_multiple"
5357 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5358 (match_operand:SI 1 "" ""))
5359 (use (match_operand:SI 2 "" ""))])]
5362 HOST_WIDE_INT offset = 0;
5364 /* Support only fixed point registers. */
5365 if (GET_CODE (operands[2]) != CONST_INT
5366 || INTVAL (operands[2]) > 14
5367 || INTVAL (operands[2]) < 2
5368 || GET_CODE (operands[1]) != MEM
5369 || GET_CODE (operands[0]) != REG
5370 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5371 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5375 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5376 force_reg (SImode, XEXP (operands[1], 0)),
5377 TRUE, FALSE, operands[1], &offset);
5380 ;; Load multiple with write-back
5382 (define_insn "*ldmsi_postinc4"
5383 [(match_parallel 0 "load_multiple_operation"
5384 [(set (match_operand:SI 1 "s_register_operand" "=r")
5385 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5387 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388 (mem:SI (match_dup 2)))
5389 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5390 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5391 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5392 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5393 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5394 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5395 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5396 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5397 [(set_attr "type" "load4")
5398 (set_attr "predicable" "yes")]
5401 (define_insn "*ldmsi_postinc4_thumb"
5402 [(match_parallel 0 "load_multiple_operation"
5403 [(set (match_operand:SI 1 "s_register_operand" "=l")
5404 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5406 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5407 (mem:SI (match_dup 2)))
5408 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5409 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5410 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5411 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5412 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5413 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5414 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5415 "ldmia\\t%1!, {%3, %4, %5, %6}"
5416 [(set_attr "type" "load4")]
5419 (define_insn "*ldmsi_postinc3"
5420 [(match_parallel 0 "load_multiple_operation"
5421 [(set (match_operand:SI 1 "s_register_operand" "=r")
5422 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5424 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5425 (mem:SI (match_dup 2)))
5426 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5427 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5428 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5429 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5430 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5431 "ldm%?ia\\t%1!, {%3, %4, %5}"
5432 [(set_attr "type" "load3")
5433 (set_attr "predicable" "yes")]
5436 (define_insn "*ldmsi_postinc2"
5437 [(match_parallel 0 "load_multiple_operation"
5438 [(set (match_operand:SI 1 "s_register_operand" "=r")
5439 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5441 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5442 (mem:SI (match_dup 2)))
5443 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5444 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5445 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5446 "ldm%?ia\\t%1!, {%3, %4}"
5447 [(set_attr "type" "load2")
5448 (set_attr "predicable" "yes")]
5451 ;; Ordinary load multiple
5453 (define_insn "*ldmsi4"
5454 [(match_parallel 0 "load_multiple_operation"
5455 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5456 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5457 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5458 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5459 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5460 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5461 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5462 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5463 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5464 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5465 [(set_attr "type" "load4")
5466 (set_attr "predicable" "yes")]
5469 (define_insn "*ldmsi3"
5470 [(match_parallel 0 "load_multiple_operation"
5471 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5472 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5473 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5474 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5475 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5476 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5477 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5478 "ldm%?ia\\t%1, {%2, %3, %4}"
5479 [(set_attr "type" "load3")
5480 (set_attr "predicable" "yes")]
5483 (define_insn "*ldmsi2"
5484 [(match_parallel 0 "load_multiple_operation"
5485 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5486 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5487 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5488 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5489 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5490 "ldm%?ia\\t%1, {%2, %3}"
5491 [(set_attr "type" "load2")
5492 (set_attr "predicable" "yes")]
5495 (define_expand "store_multiple"
5496 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5497 (match_operand:SI 1 "" ""))
5498 (use (match_operand:SI 2 "" ""))])]
5501 HOST_WIDE_INT offset = 0;
5503 /* Support only fixed point registers. */
5504 if (GET_CODE (operands[2]) != CONST_INT
5505 || INTVAL (operands[2]) > 14
5506 || INTVAL (operands[2]) < 2
5507 || GET_CODE (operands[1]) != REG
5508 || GET_CODE (operands[0]) != MEM
5509 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5510 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5514 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5515 force_reg (SImode, XEXP (operands[0], 0)),
5516 TRUE, FALSE, operands[0], &offset);
5519 ;; Store multiple with write-back
5521 (define_insn "*stmsi_postinc4"
5522 [(match_parallel 0 "store_multiple_operation"
5523 [(set (match_operand:SI 1 "s_register_operand" "=r")
5524 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5526 (set (mem:SI (match_dup 2))
5527 (match_operand:SI 3 "arm_hard_register_operand" ""))
5528 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5529 (match_operand:SI 4 "arm_hard_register_operand" ""))
5530 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5531 (match_operand:SI 5 "arm_hard_register_operand" ""))
5532 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5533 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5534 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5535 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5536 [(set_attr "predicable" "yes")
5537 (set_attr "type" "store4")]
5540 (define_insn "*stmsi_postinc4_thumb"
5541 [(match_parallel 0 "store_multiple_operation"
5542 [(set (match_operand:SI 1 "s_register_operand" "=l")
5543 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5545 (set (mem:SI (match_dup 2))
5546 (match_operand:SI 3 "arm_hard_register_operand" ""))
5547 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5548 (match_operand:SI 4 "arm_hard_register_operand" ""))
5549 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5550 (match_operand:SI 5 "arm_hard_register_operand" ""))
5551 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5552 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5553 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5554 "stmia\\t%1!, {%3, %4, %5, %6}"
5555 [(set_attr "type" "store4")]
5558 (define_insn "*stmsi_postinc3"
5559 [(match_parallel 0 "store_multiple_operation"
5560 [(set (match_operand:SI 1 "s_register_operand" "=r")
5561 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5563 (set (mem:SI (match_dup 2))
5564 (match_operand:SI 3 "arm_hard_register_operand" ""))
5565 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5566 (match_operand:SI 4 "arm_hard_register_operand" ""))
5567 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5568 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5569 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5570 "stm%?ia\\t%1!, {%3, %4, %5}"
5571 [(set_attr "predicable" "yes")
5572 (set_attr "type" "store3")]
5575 (define_insn "*stmsi_postinc2"
5576 [(match_parallel 0 "store_multiple_operation"
5577 [(set (match_operand:SI 1 "s_register_operand" "=r")
5578 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5580 (set (mem:SI (match_dup 2))
5581 (match_operand:SI 3 "arm_hard_register_operand" ""))
5582 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5583 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5584 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5585 "stm%?ia\\t%1!, {%3, %4}"
5586 [(set_attr "predicable" "yes")
5587 (set_attr "type" "store2")]
5590 ;; Ordinary store multiple
5592 (define_insn "*stmsi4"
5593 [(match_parallel 0 "store_multiple_operation"
5594 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5595 (match_operand:SI 2 "arm_hard_register_operand" ""))
5596 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5597 (match_operand:SI 3 "arm_hard_register_operand" ""))
5598 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5599 (match_operand:SI 4 "arm_hard_register_operand" ""))
5600 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5601 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5602 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5603 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5604 [(set_attr "predicable" "yes")
5605 (set_attr "type" "store4")]
5608 (define_insn "*stmsi3"
5609 [(match_parallel 0 "store_multiple_operation"
5610 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5611 (match_operand:SI 2 "arm_hard_register_operand" ""))
5612 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5613 (match_operand:SI 3 "arm_hard_register_operand" ""))
5614 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5615 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5616 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5617 "stm%?ia\\t%1, {%2, %3, %4}"
5618 [(set_attr "predicable" "yes")
5619 (set_attr "type" "store3")]
5622 (define_insn "*stmsi2"
5623 [(match_parallel 0 "store_multiple_operation"
5624 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5625 (match_operand:SI 2 "arm_hard_register_operand" ""))
5626 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5627 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5628 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5629 "stm%?ia\\t%1, {%2, %3}"
5630 [(set_attr "predicable" "yes")
5631 (set_attr "type" "store2")]
5634 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5635 ;; We could let this apply for blocks of less than this, but it clobbers so
5636 ;; many registers that there is then probably a better way.
5638 (define_expand "movmemqi"
5639 [(match_operand:BLK 0 "general_operand" "")
5640 (match_operand:BLK 1 "general_operand" "")
5641 (match_operand:SI 2 "const_int_operand" "")
5642 (match_operand:SI 3 "const_int_operand" "")]
5647 if (arm_gen_movmemqi (operands))
5651 else /* TARGET_THUMB */
5653 if ( INTVAL (operands[3]) != 4
5654 || INTVAL (operands[2]) > 48)
5657 thumb_expand_movmemqi (operands);
5663 ;; Thumb block-move insns
5665 (define_insn "movmem12b"
5666 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5667 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5668 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5669 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5670 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5671 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5672 (set (match_operand:SI 0 "register_operand" "=l")
5673 (plus:SI (match_dup 2) (const_int 12)))
5674 (set (match_operand:SI 1 "register_operand" "=l")
5675 (plus:SI (match_dup 3) (const_int 12)))
5676 (clobber (match_scratch:SI 4 "=&l"))
5677 (clobber (match_scratch:SI 5 "=&l"))
5678 (clobber (match_scratch:SI 6 "=&l"))]
5680 "* return thumb_output_move_mem_multiple (3, operands);"
5681 [(set_attr "length" "4")
5682 ; This isn't entirely accurate... It loads as well, but in terms of
5683 ; scheduling the following insn it is better to consider it as a store
5684 (set_attr "type" "store3")]
5687 (define_insn "movmem8b"
5688 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5689 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5690 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5691 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5692 (set (match_operand:SI 0 "register_operand" "=l")
5693 (plus:SI (match_dup 2) (const_int 8)))
5694 (set (match_operand:SI 1 "register_operand" "=l")
5695 (plus:SI (match_dup 3) (const_int 8)))
5696 (clobber (match_scratch:SI 4 "=&l"))
5697 (clobber (match_scratch:SI 5 "=&l"))]
5699 "* return thumb_output_move_mem_multiple (2, operands);"
5700 [(set_attr "length" "4")
5701 ; This isn't entirely accurate... It loads as well, but in terms of
5702 ; scheduling the following insn it is better to consider it as a store
5703 (set_attr "type" "store2")]
5708 ;; Compare & branch insns
5709 ;; The range calculations are based as follows:
5710 ;; For forward branches, the address calculation returns the address of
5711 ;; the next instruction. This is 2 beyond the branch instruction.
5712 ;; For backward branches, the address calculation returns the address of
5713 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5714 ;; instruction for the shortest sequence, and 4 before the branch instruction
5715 ;; if we have to jump around an unconditional branch.
5716 ;; To the basic branch range the PC offset must be added (this is +4).
5717 ;; So for forward branches we have
5718 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5719 ;; And for backward branches we have
5720 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5722 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5723 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5725 (define_expand "cbranchsi4"
5726 [(set (pc) (if_then_else
5727 (match_operator 0 "arm_comparison_operator"
5728 [(match_operand:SI 1 "s_register_operand" "")
5729 (match_operand:SI 2 "nonmemory_operand" "")])
5730 (label_ref (match_operand 3 "" ""))
5734 if (thumb_cmpneg_operand (operands[2], SImode))
5736 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5737 operands[3], operands[0]));
5740 if (!thumb_cmp_operand (operands[2], SImode))
5741 operands[2] = force_reg (SImode, operands[2]);
5744 (define_insn "*cbranchsi4_insn"
5745 [(set (pc) (if_then_else
5746 (match_operator 0 "arm_comparison_operator"
5747 [(match_operand:SI 1 "s_register_operand" "l,*h")
5748 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5749 (label_ref (match_operand 3 "" ""))
5753 output_asm_insn (\"cmp\\t%1, %2\", operands);
5755 switch (get_attr_length (insn))
5757 case 4: return \"b%d0\\t%l3\";
5758 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5759 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5762 [(set (attr "far_jump")
5764 (eq_attr "length" "8")
5765 (const_string "yes")
5766 (const_string "no")))
5767 (set (attr "length")
5769 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5770 (le (minus (match_dup 3) (pc)) (const_int 256)))
5773 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5774 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5779 (define_insn "cbranchsi4_scratch"
5780 [(set (pc) (if_then_else
5781 (match_operator 4 "arm_comparison_operator"
5782 [(match_operand:SI 1 "s_register_operand" "l,0")
5783 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5784 (label_ref (match_operand 3 "" ""))
5786 (clobber (match_scratch:SI 0 "=l,l"))]
5789 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5791 switch (get_attr_length (insn))
5793 case 4: return \"b%d4\\t%l3\";
5794 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5795 default: return \"b%D4\\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)))
5814 (define_insn "*movsi_cbranchsi4"
5817 (match_operator 3 "arm_comparison_operator"
5818 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5820 (label_ref (match_operand 2 "" ""))
5822 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5826 if (which_alternative == 0)
5827 output_asm_insn (\"cmp\t%0, #0\", operands);
5828 else if (which_alternative == 1)
5829 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5832 output_asm_insn (\"cmp\t%1, #0\", operands);
5833 if (which_alternative == 2)
5834 output_asm_insn (\"mov\t%0, %1\", operands);
5836 output_asm_insn (\"str\t%1, %0\", operands);
5838 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5840 case 4: return \"b%d3\\t%l2\";
5841 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5842 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5845 [(set (attr "far_jump")
5847 (ior (and (gt (symbol_ref ("which_alternative"))
5849 (eq_attr "length" "8"))
5850 (eq_attr "length" "10"))
5851 (const_string "yes")
5852 (const_string "no")))
5853 (set (attr "length")
5855 (le (symbol_ref ("which_alternative"))
5858 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5859 (le (minus (match_dup 2) (pc)) (const_int 256)))
5862 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5863 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5867 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5868 (le (minus (match_dup 2) (pc)) (const_int 256)))
5871 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5872 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5877 (define_insn "*negated_cbranchsi4"
5880 (match_operator 0 "equality_operator"
5881 [(match_operand:SI 1 "s_register_operand" "l")
5882 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5883 (label_ref (match_operand 3 "" ""))
5887 output_asm_insn (\"cmn\\t%1, %2\", operands);
5888 switch (get_attr_length (insn))
5890 case 4: return \"b%d0\\t%l3\";
5891 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5892 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5895 [(set (attr "far_jump")
5897 (eq_attr "length" "8")
5898 (const_string "yes")
5899 (const_string "no")))
5900 (set (attr "length")
5902 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5903 (le (minus (match_dup 3) (pc)) (const_int 256)))
5906 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5907 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5912 (define_insn "*tbit_cbranch"
5915 (match_operator 0 "equality_operator"
5916 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5918 (match_operand:SI 2 "const_int_operand" "i"))
5920 (label_ref (match_operand 3 "" ""))
5922 (clobber (match_scratch:SI 4 "=l"))]
5927 op[0] = operands[4];
5928 op[1] = operands[1];
5929 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5931 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5932 switch (get_attr_length (insn))
5934 case 4: return \"b%d0\\t%l3\";
5935 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5936 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5939 [(set (attr "far_jump")
5941 (eq_attr "length" "8")
5942 (const_string "yes")
5943 (const_string "no")))
5944 (set (attr "length")
5946 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5947 (le (minus (match_dup 3) (pc)) (const_int 256)))
5950 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5951 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5956 (define_insn "*tstsi3_cbranch"
5959 (match_operator 3 "equality_operator"
5960 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5961 (match_operand:SI 1 "s_register_operand" "l"))
5963 (label_ref (match_operand 2 "" ""))
5968 output_asm_insn (\"tst\\t%0, %1\", operands);
5969 switch (get_attr_length (insn))
5971 case 4: return \"b%d3\\t%l2\";
5972 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5973 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5976 [(set (attr "far_jump")
5978 (eq_attr "length" "8")
5979 (const_string "yes")
5980 (const_string "no")))
5981 (set (attr "length")
5983 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5984 (le (minus (match_dup 2) (pc)) (const_int 256)))
5987 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5988 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5993 (define_insn "*andsi3_cbranch"
5996 (match_operator 5 "equality_operator"
5997 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5998 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6000 (label_ref (match_operand 4 "" ""))
6002 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6003 (and:SI (match_dup 2) (match_dup 3)))
6004 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6008 if (which_alternative == 0)
6009 output_asm_insn (\"and\\t%0, %3\", operands);
6010 else if (which_alternative == 1)
6012 output_asm_insn (\"and\\t%1, %3\", operands);
6013 output_asm_insn (\"mov\\t%0, %1\", operands);
6017 output_asm_insn (\"and\\t%1, %3\", operands);
6018 output_asm_insn (\"str\\t%1, %0\", operands);
6021 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6023 case 4: return \"b%d5\\t%l4\";
6024 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6025 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6028 [(set (attr "far_jump")
6030 (ior (and (eq (symbol_ref ("which_alternative"))
6032 (eq_attr "length" "8"))
6033 (eq_attr "length" "10"))
6034 (const_string "yes")
6035 (const_string "no")))
6036 (set (attr "length")
6038 (eq (symbol_ref ("which_alternative"))
6041 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6042 (le (minus (match_dup 4) (pc)) (const_int 256)))
6045 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6046 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6050 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6051 (le (minus (match_dup 4) (pc)) (const_int 256)))
6054 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6055 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6060 (define_insn "*orrsi3_cbranch_scratch"
6063 (match_operator 4 "equality_operator"
6064 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6065 (match_operand:SI 2 "s_register_operand" "l"))
6067 (label_ref (match_operand 3 "" ""))
6069 (clobber (match_scratch:SI 0 "=l"))]
6073 output_asm_insn (\"orr\\t%0, %2\", operands);
6074 switch (get_attr_length (insn))
6076 case 4: return \"b%d4\\t%l3\";
6077 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6078 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6081 [(set (attr "far_jump")
6083 (eq_attr "length" "8")
6084 (const_string "yes")
6085 (const_string "no")))
6086 (set (attr "length")
6088 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6089 (le (minus (match_dup 3) (pc)) (const_int 256)))
6092 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6093 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6098 (define_insn "*orrsi3_cbranch"
6101 (match_operator 5 "equality_operator"
6102 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6103 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6105 (label_ref (match_operand 4 "" ""))
6107 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6108 (ior:SI (match_dup 2) (match_dup 3)))
6109 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6113 if (which_alternative == 0)
6114 output_asm_insn (\"orr\\t%0, %3\", operands);
6115 else if (which_alternative == 1)
6117 output_asm_insn (\"orr\\t%1, %3\", operands);
6118 output_asm_insn (\"mov\\t%0, %1\", operands);
6122 output_asm_insn (\"orr\\t%1, %3\", operands);
6123 output_asm_insn (\"str\\t%1, %0\", operands);
6126 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6128 case 4: return \"b%d5\\t%l4\";
6129 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6130 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6133 [(set (attr "far_jump")
6135 (ior (and (eq (symbol_ref ("which_alternative"))
6137 (eq_attr "length" "8"))
6138 (eq_attr "length" "10"))
6139 (const_string "yes")
6140 (const_string "no")))
6141 (set (attr "length")
6143 (eq (symbol_ref ("which_alternative"))
6146 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6147 (le (minus (match_dup 4) (pc)) (const_int 256)))
6150 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6151 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6155 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6156 (le (minus (match_dup 4) (pc)) (const_int 256)))
6159 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6160 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6165 (define_insn "*xorsi3_cbranch_scratch"
6168 (match_operator 4 "equality_operator"
6169 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6170 (match_operand:SI 2 "s_register_operand" "l"))
6172 (label_ref (match_operand 3 "" ""))
6174 (clobber (match_scratch:SI 0 "=l"))]
6178 output_asm_insn (\"eor\\t%0, %2\", operands);
6179 switch (get_attr_length (insn))
6181 case 4: return \"b%d4\\t%l3\";
6182 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6183 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6186 [(set (attr "far_jump")
6188 (eq_attr "length" "8")
6189 (const_string "yes")
6190 (const_string "no")))
6191 (set (attr "length")
6193 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6194 (le (minus (match_dup 3) (pc)) (const_int 256)))
6197 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6198 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6203 (define_insn "*xorsi3_cbranch"
6206 (match_operator 5 "equality_operator"
6207 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6208 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6210 (label_ref (match_operand 4 "" ""))
6212 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6213 (xor:SI (match_dup 2) (match_dup 3)))
6214 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6218 if (which_alternative == 0)
6219 output_asm_insn (\"eor\\t%0, %3\", operands);
6220 else if (which_alternative == 1)
6222 output_asm_insn (\"eor\\t%1, %3\", operands);
6223 output_asm_insn (\"mov\\t%0, %1\", operands);
6227 output_asm_insn (\"eor\\t%1, %3\", operands);
6228 output_asm_insn (\"str\\t%1, %0\", operands);
6231 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6233 case 4: return \"b%d5\\t%l4\";
6234 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6235 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6238 [(set (attr "far_jump")
6240 (ior (and (eq (symbol_ref ("which_alternative"))
6242 (eq_attr "length" "8"))
6243 (eq_attr "length" "10"))
6244 (const_string "yes")
6245 (const_string "no")))
6246 (set (attr "length")
6248 (eq (symbol_ref ("which_alternative"))
6251 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6252 (le (minus (match_dup 4) (pc)) (const_int 256)))
6255 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6256 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6260 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6261 (le (minus (match_dup 4) (pc)) (const_int 256)))
6264 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6265 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6270 (define_insn "*bicsi3_cbranch_scratch"
6273 (match_operator 4 "equality_operator"
6274 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6275 (match_operand:SI 1 "s_register_operand" "0"))
6277 (label_ref (match_operand 3 "" ""))
6279 (clobber (match_scratch:SI 0 "=l"))]
6283 output_asm_insn (\"bic\\t%0, %2\", operands);
6284 switch (get_attr_length (insn))
6286 case 4: return \"b%d4\\t%l3\";
6287 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6288 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6291 [(set (attr "far_jump")
6293 (eq_attr "length" "8")
6294 (const_string "yes")
6295 (const_string "no")))
6296 (set (attr "length")
6298 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6299 (le (minus (match_dup 3) (pc)) (const_int 256)))
6302 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6303 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6308 (define_insn "*bicsi3_cbranch"
6311 (match_operator 5 "equality_operator"
6312 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6313 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6315 (label_ref (match_operand 4 "" ""))
6317 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6318 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6319 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6323 if (which_alternative == 0)
6324 output_asm_insn (\"bic\\t%0, %3\", operands);
6325 else if (which_alternative <= 2)
6327 output_asm_insn (\"bic\\t%1, %3\", operands);
6328 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6329 conditions again, since we're only testing for equality. */
6330 output_asm_insn (\"mov\\t%0, %1\", operands);
6334 output_asm_insn (\"bic\\t%1, %3\", operands);
6335 output_asm_insn (\"str\\t%1, %0\", operands);
6338 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6340 case 4: return \"b%d5\\t%l4\";
6341 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6342 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6345 [(set (attr "far_jump")
6347 (ior (and (eq (symbol_ref ("which_alternative"))
6349 (eq_attr "length" "8"))
6350 (eq_attr "length" "10"))
6351 (const_string "yes")
6352 (const_string "no")))
6353 (set (attr "length")
6355 (eq (symbol_ref ("which_alternative"))
6358 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6359 (le (minus (match_dup 4) (pc)) (const_int 256)))
6362 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6363 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6367 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6368 (le (minus (match_dup 4) (pc)) (const_int 256)))
6371 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6372 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6377 (define_insn "*cbranchne_decr1"
6379 (if_then_else (match_operator 3 "equality_operator"
6380 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6382 (label_ref (match_operand 4 "" ""))
6384 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6385 (plus:SI (match_dup 2) (const_int -1)))
6386 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6391 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6393 VOIDmode, operands[2], const1_rtx);
6394 cond[1] = operands[4];
6396 if (which_alternative == 0)
6397 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6398 else if (which_alternative == 1)
6400 /* We must provide an alternative for a hi reg because reload
6401 cannot handle output reloads on a jump instruction, but we
6402 can't subtract into that. Fortunately a mov from lo to hi
6403 does not clobber the condition codes. */
6404 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6405 output_asm_insn (\"mov\\t%0, %1\", operands);
6409 /* Similarly, but the target is memory. */
6410 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6411 output_asm_insn (\"str\\t%1, %0\", operands);
6414 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6417 output_asm_insn (\"b%d0\\t%l1\", cond);
6420 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6421 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6423 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6424 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6428 [(set (attr "far_jump")
6430 (ior (and (eq (symbol_ref ("which_alternative"))
6432 (eq_attr "length" "8"))
6433 (eq_attr "length" "10"))
6434 (const_string "yes")
6435 (const_string "no")))
6436 (set_attr_alternative "length"
6440 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6441 (le (minus (match_dup 4) (pc)) (const_int 256)))
6444 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6445 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6450 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6451 (le (minus (match_dup 4) (pc)) (const_int 256)))
6454 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6455 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6460 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6461 (le (minus (match_dup 4) (pc)) (const_int 256)))
6464 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6465 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6470 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6471 (le (minus (match_dup 4) (pc)) (const_int 256)))
6474 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6475 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6480 (define_insn "*addsi3_cbranch"
6483 (match_operator 4 "comparison_operator"
6485 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6486 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6488 (label_ref (match_operand 5 "" ""))
6491 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6492 (plus:SI (match_dup 2) (match_dup 3)))
6493 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6495 && (GET_CODE (operands[4]) == EQ
6496 || GET_CODE (operands[4]) == NE
6497 || GET_CODE (operands[4]) == GE
6498 || GET_CODE (operands[4]) == LT)"
6504 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6505 cond[1] = operands[2];
6506 cond[2] = operands[3];
6508 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6509 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6511 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6513 if (which_alternative >= 3
6514 && which_alternative < 4)
6515 output_asm_insn (\"mov\\t%0, %1\", operands);
6516 else if (which_alternative >= 4)
6517 output_asm_insn (\"str\\t%1, %0\", operands);
6519 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6522 return \"b%d4\\t%l5\";
6524 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6526 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6530 [(set (attr "far_jump")
6532 (ior (and (lt (symbol_ref ("which_alternative"))
6534 (eq_attr "length" "8"))
6535 (eq_attr "length" "10"))
6536 (const_string "yes")
6537 (const_string "no")))
6538 (set (attr "length")
6540 (lt (symbol_ref ("which_alternative"))
6543 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6544 (le (minus (match_dup 5) (pc)) (const_int 256)))
6547 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6548 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6552 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6553 (le (minus (match_dup 5) (pc)) (const_int 256)))
6556 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6557 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6562 (define_insn "*addsi3_cbranch_scratch"
6565 (match_operator 3 "comparison_operator"
6567 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6568 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6570 (label_ref (match_operand 4 "" ""))
6572 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6574 && (GET_CODE (operands[3]) == EQ
6575 || GET_CODE (operands[3]) == NE
6576 || GET_CODE (operands[3]) == GE
6577 || GET_CODE (operands[3]) == LT)"
6580 switch (which_alternative)
6583 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6586 output_asm_insn (\"cmn\t%1, %2\", operands);
6589 if (INTVAL (operands[2]) < 0)
6590 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6592 output_asm_insn (\"add\t%0, %1, %2\", operands);
6595 if (INTVAL (operands[2]) < 0)
6596 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6598 output_asm_insn (\"add\t%0, %0, %2\", operands);
6602 switch (get_attr_length (insn))
6605 return \"b%d3\\t%l4\";
6607 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6609 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6613 [(set (attr "far_jump")
6615 (eq_attr "length" "8")
6616 (const_string "yes")
6617 (const_string "no")))
6618 (set (attr "length")
6620 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6621 (le (minus (match_dup 4) (pc)) (const_int 256)))
6624 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6625 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6630 (define_insn "*subsi3_cbranch"
6633 (match_operator 4 "comparison_operator"
6635 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6636 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6638 (label_ref (match_operand 5 "" ""))
6640 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6641 (minus:SI (match_dup 2) (match_dup 3)))
6642 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6644 && (GET_CODE (operands[4]) == EQ
6645 || GET_CODE (operands[4]) == NE
6646 || GET_CODE (operands[4]) == GE
6647 || GET_CODE (operands[4]) == LT)"
6650 if (which_alternative == 0)
6651 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6652 else if (which_alternative == 1)
6654 /* We must provide an alternative for a hi reg because reload
6655 cannot handle output reloads on a jump instruction, but we
6656 can't subtract into that. Fortunately a mov from lo to hi
6657 does not clobber the condition codes. */
6658 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6659 output_asm_insn (\"mov\\t%0, %1\", operands);
6663 /* Similarly, but the target is memory. */
6664 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6665 output_asm_insn (\"str\\t%1, %0\", operands);
6668 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6671 return \"b%d4\\t%l5\";
6673 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6675 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6679 [(set (attr "far_jump")
6681 (ior (and (eq (symbol_ref ("which_alternative"))
6683 (eq_attr "length" "8"))
6684 (eq_attr "length" "10"))
6685 (const_string "yes")
6686 (const_string "no")))
6687 (set (attr "length")
6689 (eq (symbol_ref ("which_alternative"))
6692 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6693 (le (minus (match_dup 5) (pc)) (const_int 256)))
6696 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6697 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6701 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6702 (le (minus (match_dup 5) (pc)) (const_int 256)))
6705 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6706 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6711 (define_insn "*subsi3_cbranch_scratch"
6714 (match_operator 0 "arm_comparison_operator"
6715 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6716 (match_operand:SI 2 "nonmemory_operand" "l"))
6718 (label_ref (match_operand 3 "" ""))
6721 && (GET_CODE (operands[0]) == EQ
6722 || GET_CODE (operands[0]) == NE
6723 || GET_CODE (operands[0]) == GE
6724 || GET_CODE (operands[0]) == LT)"
6726 output_asm_insn (\"cmp\\t%1, %2\", operands);
6727 switch (get_attr_length (insn))
6729 case 4: return \"b%d0\\t%l3\";
6730 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6731 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6734 [(set (attr "far_jump")
6736 (eq_attr "length" "8")
6737 (const_string "yes")
6738 (const_string "no")))
6739 (set (attr "length")
6741 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6742 (le (minus (match_dup 3) (pc)) (const_int 256)))
6745 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6746 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6751 ;; Comparison and test insns
6753 (define_expand "cmpsi"
6754 [(match_operand:SI 0 "s_register_operand" "")
6755 (match_operand:SI 1 "arm_add_operand" "")]
6758 arm_compare_op0 = operands[0];
6759 arm_compare_op1 = operands[1];
6764 (define_expand "cmpsf"
6765 [(match_operand:SF 0 "s_register_operand" "")
6766 (match_operand:SF 1 "arm_float_compare_operand" "")]
6767 "TARGET_ARM && TARGET_HARD_FLOAT"
6769 arm_compare_op0 = operands[0];
6770 arm_compare_op1 = operands[1];
6775 (define_expand "cmpdf"
6776 [(match_operand:DF 0 "s_register_operand" "")
6777 (match_operand:DF 1 "arm_float_compare_operand" "")]
6778 "TARGET_ARM && TARGET_HARD_FLOAT"
6780 arm_compare_op0 = operands[0];
6781 arm_compare_op1 = operands[1];
6786 (define_insn "*arm_cmpsi_insn"
6787 [(set (reg:CC CC_REGNUM)
6788 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6789 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6794 [(set_attr "conds" "set")]
6797 (define_insn "*cmpsi_shiftsi"
6798 [(set (reg:CC CC_REGNUM)
6799 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6800 (match_operator:SI 3 "shift_operator"
6801 [(match_operand:SI 1 "s_register_operand" "r")
6802 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6805 [(set_attr "conds" "set")
6806 (set_attr "shift" "1")
6807 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6808 (const_string "alu_shift")
6809 (const_string "alu_shift_reg")))]
6812 (define_insn "*cmpsi_shiftsi_swp"
6813 [(set (reg:CC_SWP CC_REGNUM)
6814 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6815 [(match_operand:SI 1 "s_register_operand" "r")
6816 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6817 (match_operand:SI 0 "s_register_operand" "r")))]
6820 [(set_attr "conds" "set")
6821 (set_attr "shift" "1")
6822 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6823 (const_string "alu_shift")
6824 (const_string "alu_shift_reg")))]
6827 (define_insn "*cmpsi_negshiftsi_si"
6828 [(set (reg:CC_Z CC_REGNUM)
6830 (neg:SI (match_operator:SI 1 "shift_operator"
6831 [(match_operand:SI 2 "s_register_operand" "r")
6832 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6833 (match_operand:SI 0 "s_register_operand" "r")))]
6836 [(set_attr "conds" "set")
6837 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6838 (const_string "alu_shift")
6839 (const_string "alu_shift_reg")))]
6842 ;; Cirrus SF compare instruction
6843 (define_insn "*cirrus_cmpsf"
6844 [(set (reg:CCFP CC_REGNUM)
6845 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6846 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6847 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6848 "cfcmps%?\\tr15, %V0, %V1"
6849 [(set_attr "type" "mav_farith")
6850 (set_attr "cirrus" "compare")]
6853 ;; Cirrus DF compare instruction
6854 (define_insn "*cirrus_cmpdf"
6855 [(set (reg:CCFP CC_REGNUM)
6856 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6857 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6858 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6859 "cfcmpd%?\\tr15, %V0, %V1"
6860 [(set_attr "type" "mav_farith")
6861 (set_attr "cirrus" "compare")]
6864 ;; Cirrus DI compare instruction
6865 (define_expand "cmpdi"
6866 [(match_operand:DI 0 "cirrus_fp_register" "")
6867 (match_operand:DI 1 "cirrus_fp_register" "")]
6868 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6870 arm_compare_op0 = operands[0];
6871 arm_compare_op1 = operands[1];
6875 (define_insn "*cirrus_cmpdi"
6876 [(set (reg:CC CC_REGNUM)
6877 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6878 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6879 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6880 "cfcmp64%?\\tr15, %V0, %V1"
6881 [(set_attr "type" "mav_farith")
6882 (set_attr "cirrus" "compare")]
6885 ; This insn allows redundant compares to be removed by cse, nothing should
6886 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6887 ; is deleted later on. The match_dup will match the mode here, so that
6888 ; mode changes of the condition codes aren't lost by this even though we don't
6889 ; specify what they are.
6891 (define_insn "*deleted_compare"
6892 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6894 "\\t%@ deleted compare"
6895 [(set_attr "conds" "set")
6896 (set_attr "length" "0")]
6900 ;; Conditional branch insns
6902 (define_expand "beq"
6904 (if_then_else (eq (match_dup 1) (const_int 0))
6905 (label_ref (match_operand 0 "" ""))
6908 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6911 (define_expand "bne"
6913 (if_then_else (ne (match_dup 1) (const_int 0))
6914 (label_ref (match_operand 0 "" ""))
6917 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6920 (define_expand "bgt"
6922 (if_then_else (gt (match_dup 1) (const_int 0))
6923 (label_ref (match_operand 0 "" ""))
6926 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6929 (define_expand "ble"
6931 (if_then_else (le (match_dup 1) (const_int 0))
6932 (label_ref (match_operand 0 "" ""))
6935 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6938 (define_expand "bge"
6940 (if_then_else (ge (match_dup 1) (const_int 0))
6941 (label_ref (match_operand 0 "" ""))
6944 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6947 (define_expand "blt"
6949 (if_then_else (lt (match_dup 1) (const_int 0))
6950 (label_ref (match_operand 0 "" ""))
6953 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6956 (define_expand "bgtu"
6958 (if_then_else (gtu (match_dup 1) (const_int 0))
6959 (label_ref (match_operand 0 "" ""))
6962 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6965 (define_expand "bleu"
6967 (if_then_else (leu (match_dup 1) (const_int 0))
6968 (label_ref (match_operand 0 "" ""))
6971 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6974 (define_expand "bgeu"
6976 (if_then_else (geu (match_dup 1) (const_int 0))
6977 (label_ref (match_operand 0 "" ""))
6980 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6983 (define_expand "bltu"
6985 (if_then_else (ltu (match_dup 1) (const_int 0))
6986 (label_ref (match_operand 0 "" ""))
6989 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6992 (define_expand "bunordered"
6994 (if_then_else (unordered (match_dup 1) (const_int 0))
6995 (label_ref (match_operand 0 "" ""))
6997 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
6998 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7002 (define_expand "bordered"
7004 (if_then_else (ordered (match_dup 1) (const_int 0))
7005 (label_ref (match_operand 0 "" ""))
7007 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7008 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7012 (define_expand "bungt"
7014 (if_then_else (ungt (match_dup 1) (const_int 0))
7015 (label_ref (match_operand 0 "" ""))
7017 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7018 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7021 (define_expand "bunlt"
7023 (if_then_else (unlt (match_dup 1) (const_int 0))
7024 (label_ref (match_operand 0 "" ""))
7026 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7027 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7030 (define_expand "bunge"
7032 (if_then_else (unge (match_dup 1) (const_int 0))
7033 (label_ref (match_operand 0 "" ""))
7035 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7036 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7039 (define_expand "bunle"
7041 (if_then_else (unle (match_dup 1) (const_int 0))
7042 (label_ref (match_operand 0 "" ""))
7044 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7045 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7048 ;; The following two patterns need two branch instructions, since there is
7049 ;; no single instruction that will handle all cases.
7050 (define_expand "buneq"
7052 (if_then_else (uneq (match_dup 1) (const_int 0))
7053 (label_ref (match_operand 0 "" ""))
7055 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7056 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7059 (define_expand "bltgt"
7061 (if_then_else (ltgt (match_dup 1) (const_int 0))
7062 (label_ref (match_operand 0 "" ""))
7064 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7065 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7069 ;; Patterns to match conditional branch insns.
7072 ; Special pattern to match UNEQ.
7073 (define_insn "*arm_buneq"
7075 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7076 (label_ref (match_operand 0 "" ""))
7078 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7080 gcc_assert (!arm_ccfsm_state);
7082 return \"bvs\\t%l0\;beq\\t%l0\";
7084 [(set_attr "conds" "jump_clob")
7085 (set_attr "length" "8")]
7088 ; Special pattern to match LTGT.
7089 (define_insn "*arm_bltgt"
7091 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7092 (label_ref (match_operand 0 "" ""))
7094 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7096 gcc_assert (!arm_ccfsm_state);
7098 return \"bmi\\t%l0\;bgt\\t%l0\";
7100 [(set_attr "conds" "jump_clob")
7101 (set_attr "length" "8")]
7104 (define_insn "*arm_cond_branch"
7106 (if_then_else (match_operator 1 "arm_comparison_operator"
7107 [(match_operand 2 "cc_register" "") (const_int 0)])
7108 (label_ref (match_operand 0 "" ""))
7112 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7114 arm_ccfsm_state += 2;
7117 return \"b%d1\\t%l0\";
7119 [(set_attr "conds" "use")
7120 (set_attr "type" "branch")]
7123 ; Special pattern to match reversed UNEQ.
7124 (define_insn "*arm_buneq_reversed"
7126 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7128 (label_ref (match_operand 0 "" ""))))]
7129 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7131 gcc_assert (!arm_ccfsm_state);
7133 return \"bmi\\t%l0\;bgt\\t%l0\";
7135 [(set_attr "conds" "jump_clob")
7136 (set_attr "length" "8")]
7139 ; Special pattern to match reversed LTGT.
7140 (define_insn "*arm_bltgt_reversed"
7142 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7144 (label_ref (match_operand 0 "" ""))))]
7145 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7147 gcc_assert (!arm_ccfsm_state);
7149 return \"bvs\\t%l0\;beq\\t%l0\";
7151 [(set_attr "conds" "jump_clob")
7152 (set_attr "length" "8")]
7155 (define_insn "*arm_cond_branch_reversed"
7157 (if_then_else (match_operator 1 "arm_comparison_operator"
7158 [(match_operand 2 "cc_register" "") (const_int 0)])
7160 (label_ref (match_operand 0 "" ""))))]
7163 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7165 arm_ccfsm_state += 2;
7168 return \"b%D1\\t%l0\";
7170 [(set_attr "conds" "use")
7171 (set_attr "type" "branch")]
7178 (define_expand "seq"
7179 [(set (match_operand:SI 0 "s_register_operand" "")
7180 (eq:SI (match_dup 1) (const_int 0)))]
7182 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7185 (define_expand "sne"
7186 [(set (match_operand:SI 0 "s_register_operand" "")
7187 (ne:SI (match_dup 1) (const_int 0)))]
7189 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7192 (define_expand "sgt"
7193 [(set (match_operand:SI 0 "s_register_operand" "")
7194 (gt:SI (match_dup 1) (const_int 0)))]
7196 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7199 (define_expand "sle"
7200 [(set (match_operand:SI 0 "s_register_operand" "")
7201 (le:SI (match_dup 1) (const_int 0)))]
7203 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7206 (define_expand "sge"
7207 [(set (match_operand:SI 0 "s_register_operand" "")
7208 (ge:SI (match_dup 1) (const_int 0)))]
7210 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7213 (define_expand "slt"
7214 [(set (match_operand:SI 0 "s_register_operand" "")
7215 (lt:SI (match_dup 1) (const_int 0)))]
7217 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7220 (define_expand "sgtu"
7221 [(set (match_operand:SI 0 "s_register_operand" "")
7222 (gtu:SI (match_dup 1) (const_int 0)))]
7224 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7227 (define_expand "sleu"
7228 [(set (match_operand:SI 0 "s_register_operand" "")
7229 (leu:SI (match_dup 1) (const_int 0)))]
7231 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7234 (define_expand "sgeu"
7235 [(set (match_operand:SI 0 "s_register_operand" "")
7236 (geu:SI (match_dup 1) (const_int 0)))]
7238 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7241 (define_expand "sltu"
7242 [(set (match_operand:SI 0 "s_register_operand" "")
7243 (ltu:SI (match_dup 1) (const_int 0)))]
7245 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7248 (define_expand "sunordered"
7249 [(set (match_operand:SI 0 "s_register_operand" "")
7250 (unordered:SI (match_dup 1) (const_int 0)))]
7251 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7252 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7256 (define_expand "sordered"
7257 [(set (match_operand:SI 0 "s_register_operand" "")
7258 (ordered:SI (match_dup 1) (const_int 0)))]
7259 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7260 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7264 (define_expand "sungt"
7265 [(set (match_operand:SI 0 "s_register_operand" "")
7266 (ungt:SI (match_dup 1) (const_int 0)))]
7267 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7268 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7272 (define_expand "sunge"
7273 [(set (match_operand:SI 0 "s_register_operand" "")
7274 (unge:SI (match_dup 1) (const_int 0)))]
7275 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7276 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7280 (define_expand "sunlt"
7281 [(set (match_operand:SI 0 "s_register_operand" "")
7282 (unlt:SI (match_dup 1) (const_int 0)))]
7283 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7284 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7288 (define_expand "sunle"
7289 [(set (match_operand:SI 0 "s_register_operand" "")
7290 (unle:SI (match_dup 1) (const_int 0)))]
7291 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7292 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7296 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7297 ;;; simple ARM instructions.
7299 ; (define_expand "suneq"
7300 ; [(set (match_operand:SI 0 "s_register_operand" "")
7301 ; (uneq:SI (match_dup 1) (const_int 0)))]
7302 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7303 ; "gcc_unreachable ();"
7306 ; (define_expand "sltgt"
7307 ; [(set (match_operand:SI 0 "s_register_operand" "")
7308 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7309 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7310 ; "gcc_unreachable ();"
7313 (define_insn "*mov_scc"
7314 [(set (match_operand:SI 0 "s_register_operand" "=r")
7315 (match_operator:SI 1 "arm_comparison_operator"
7316 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7318 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7319 [(set_attr "conds" "use")
7320 (set_attr "length" "8")]
7323 (define_insn "*mov_negscc"
7324 [(set (match_operand:SI 0 "s_register_operand" "=r")
7325 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7326 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7328 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7329 [(set_attr "conds" "use")
7330 (set_attr "length" "8")]
7333 (define_insn "*mov_notscc"
7334 [(set (match_operand:SI 0 "s_register_operand" "=r")
7335 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7336 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7338 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7339 [(set_attr "conds" "use")
7340 (set_attr "length" "8")]
7344 ;; Conditional move insns
7346 (define_expand "movsicc"
7347 [(set (match_operand:SI 0 "s_register_operand" "")
7348 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7349 (match_operand:SI 2 "arm_not_operand" "")
7350 (match_operand:SI 3 "arm_not_operand" "")))]
7354 enum rtx_code code = GET_CODE (operands[1]);
7357 if (code == UNEQ || code == LTGT)
7360 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7361 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7365 (define_expand "movsfcc"
7366 [(set (match_operand:SF 0 "s_register_operand" "")
7367 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7368 (match_operand:SF 2 "s_register_operand" "")
7369 (match_operand:SF 3 "nonmemory_operand" "")))]
7373 enum rtx_code code = GET_CODE (operands[1]);
7376 if (code == UNEQ || code == LTGT)
7379 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7380 Otherwise, ensure it is a valid FP add operand */
7381 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7382 || (!arm_float_add_operand (operands[3], SFmode)))
7383 operands[3] = force_reg (SFmode, operands[3]);
7385 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7386 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7390 (define_expand "movdfcc"
7391 [(set (match_operand:DF 0 "s_register_operand" "")
7392 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7393 (match_operand:DF 2 "s_register_operand" "")
7394 (match_operand:DF 3 "arm_float_add_operand" "")))]
7395 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7398 enum rtx_code code = GET_CODE (operands[1]);
7401 if (code == UNEQ || code == LTGT)
7404 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7405 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7409 (define_insn "*movsicc_insn"
7410 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7412 (match_operator 3 "arm_comparison_operator"
7413 [(match_operand 4 "cc_register" "") (const_int 0)])
7414 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7415 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7422 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7423 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7424 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7425 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7426 [(set_attr "length" "4,4,4,4,8,8,8,8")
7427 (set_attr "conds" "use")]
7430 (define_insn "*movsfcc_soft_insn"
7431 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7432 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7433 [(match_operand 4 "cc_register" "") (const_int 0)])
7434 (match_operand:SF 1 "s_register_operand" "0,r")
7435 (match_operand:SF 2 "s_register_operand" "r,0")))]
7436 "TARGET_ARM && TARGET_SOFT_FLOAT"
7440 [(set_attr "conds" "use")]
7444 ;; Jump and linkage insns
7446 (define_expand "jump"
7448 (label_ref (match_operand 0 "" "")))]
7453 (define_insn "*arm_jump"
7455 (label_ref (match_operand 0 "" "")))]
7459 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7461 arm_ccfsm_state += 2;
7464 return \"b%?\\t%l0\";
7467 [(set_attr "predicable" "yes")]
7470 (define_insn "*thumb_jump"
7472 (label_ref (match_operand 0 "" "")))]
7475 if (get_attr_length (insn) == 2)
7477 return \"bl\\t%l0\\t%@ far jump\";
7479 [(set (attr "far_jump")
7481 (eq_attr "length" "4")
7482 (const_string "yes")
7483 (const_string "no")))
7484 (set (attr "length")
7486 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7487 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7492 (define_expand "call"
7493 [(parallel [(call (match_operand 0 "memory_operand" "")
7494 (match_operand 1 "general_operand" ""))
7495 (use (match_operand 2 "" ""))
7496 (clobber (reg:SI LR_REGNUM))])]
7502 /* In an untyped call, we can get NULL for operand 2. */
7503 if (operands[2] == NULL_RTX)
7504 operands[2] = const0_rtx;
7506 /* This is to decide if we should generate indirect calls by loading the
7507 32 bit address of the callee into a register before performing the
7508 branch and link. operand[2] encodes the long_call/short_call
7509 attribute of the function being called. This attribute is set whenever
7510 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7511 is used, and the short_call attribute can also be set if function is
7512 declared as static or if it has already been defined in the current
7513 compilation unit. See arm.c and arm.h for info about this. The third
7514 parameter to arm_is_longcall_p is used to tell it which pattern
7516 callee = XEXP (operands[0], 0);
7518 if ((GET_CODE (callee) == SYMBOL_REF
7519 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7520 || (GET_CODE (callee) != SYMBOL_REF
7521 && GET_CODE (callee) != REG))
7522 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7526 (define_insn "*call_reg_armv5"
7527 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7528 (match_operand 1 "" ""))
7529 (use (match_operand 2 "" ""))
7530 (clobber (reg:SI LR_REGNUM))]
7531 "TARGET_ARM && arm_arch5"
7533 [(set_attr "type" "call")]
7536 (define_insn "*call_reg_arm"
7537 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7538 (match_operand 1 "" ""))
7539 (use (match_operand 2 "" ""))
7540 (clobber (reg:SI LR_REGNUM))]
7541 "TARGET_ARM && !arm_arch5"
7543 return output_call (operands);
7545 ;; length is worst case, normally it is only two
7546 [(set_attr "length" "12")
7547 (set_attr "type" "call")]
7550 (define_insn "*call_mem"
7551 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7552 (match_operand 1 "" ""))
7553 (use (match_operand 2 "" ""))
7554 (clobber (reg:SI LR_REGNUM))]
7557 return output_call_mem (operands);
7559 [(set_attr "length" "12")
7560 (set_attr "type" "call")]
7563 (define_insn "*call_reg_thumb_v5"
7564 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7565 (match_operand 1 "" ""))
7566 (use (match_operand 2 "" ""))
7567 (clobber (reg:SI LR_REGNUM))]
7568 "TARGET_THUMB && arm_arch5"
7570 [(set_attr "length" "2")
7571 (set_attr "type" "call")]
7574 (define_insn "*call_reg_thumb"
7575 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7576 (match_operand 1 "" ""))
7577 (use (match_operand 2 "" ""))
7578 (clobber (reg:SI LR_REGNUM))]
7579 "TARGET_THUMB && !arm_arch5"
7582 if (!TARGET_CALLER_INTERWORKING)
7583 return thumb_call_via_reg (operands[0]);
7584 else if (operands[1] == const0_rtx)
7585 return \"bl\\t%__interwork_call_via_%0\";
7586 else if (frame_pointer_needed)
7587 return \"bl\\t%__interwork_r7_call_via_%0\";
7589 return \"bl\\t%__interwork_r11_call_via_%0\";
7591 [(set_attr "type" "call")]
7594 (define_expand "call_value"
7595 [(parallel [(set (match_operand 0 "" "")
7596 (call (match_operand 1 "memory_operand" "")
7597 (match_operand 2 "general_operand" "")))
7598 (use (match_operand 3 "" ""))
7599 (clobber (reg:SI LR_REGNUM))])]
7603 rtx callee = XEXP (operands[1], 0);
7605 /* In an untyped call, we can get NULL for operand 2. */
7606 if (operands[3] == 0)
7607 operands[3] = const0_rtx;
7609 /* See the comment in define_expand \"call\". */
7610 if ((GET_CODE (callee) == SYMBOL_REF
7611 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7612 || (GET_CODE (callee) != SYMBOL_REF
7613 && GET_CODE (callee) != REG))
7614 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7618 (define_insn "*call_value_reg_armv5"
7619 [(set (match_operand 0 "" "")
7620 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7621 (match_operand 2 "" "")))
7622 (use (match_operand 3 "" ""))
7623 (clobber (reg:SI LR_REGNUM))]
7624 "TARGET_ARM && arm_arch5"
7626 [(set_attr "type" "call")]
7629 (define_insn "*call_value_reg_arm"
7630 [(set (match_operand 0 "" "")
7631 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7632 (match_operand 2 "" "")))
7633 (use (match_operand 3 "" ""))
7634 (clobber (reg:SI LR_REGNUM))]
7635 "TARGET_ARM && !arm_arch5"
7637 return output_call (&operands[1]);
7639 [(set_attr "length" "12")
7640 (set_attr "type" "call")]
7643 (define_insn "*call_value_mem"
7644 [(set (match_operand 0 "" "")
7645 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7646 (match_operand 2 "" "")))
7647 (use (match_operand 3 "" ""))
7648 (clobber (reg:SI LR_REGNUM))]
7649 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7651 return output_call_mem (&operands[1]);
7653 [(set_attr "length" "12")
7654 (set_attr "type" "call")]
7657 (define_insn "*call_value_reg_thumb_v5"
7658 [(set (match_operand 0 "" "")
7659 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7660 (match_operand 2 "" "")))
7661 (use (match_operand 3 "" ""))
7662 (clobber (reg:SI LR_REGNUM))]
7663 "TARGET_THUMB && arm_arch5"
7665 [(set_attr "length" "2")
7666 (set_attr "type" "call")]
7669 (define_insn "*call_value_reg_thumb"
7670 [(set (match_operand 0 "" "")
7671 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7672 (match_operand 2 "" "")))
7673 (use (match_operand 3 "" ""))
7674 (clobber (reg:SI LR_REGNUM))]
7675 "TARGET_THUMB && !arm_arch5"
7678 if (!TARGET_CALLER_INTERWORKING)
7679 return thumb_call_via_reg (operands[1]);
7680 else if (operands[2] == const0_rtx)
7681 return \"bl\\t%__interwork_call_via_%1\";
7682 else if (frame_pointer_needed)
7683 return \"bl\\t%__interwork_r7_call_via_%1\";
7685 return \"bl\\t%__interwork_r11_call_via_%1\";
7687 [(set_attr "type" "call")]
7690 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7691 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7693 (define_insn "*call_symbol"
7694 [(call (mem:SI (match_operand:SI 0 "" ""))
7695 (match_operand 1 "" ""))
7696 (use (match_operand 2 "" ""))
7697 (clobber (reg:SI LR_REGNUM))]
7699 && (GET_CODE (operands[0]) == SYMBOL_REF)
7700 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7703 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7705 [(set_attr "type" "call")]
7708 (define_insn "*call_value_symbol"
7709 [(set (match_operand 0 "" "")
7710 (call (mem:SI (match_operand:SI 1 "" ""))
7711 (match_operand:SI 2 "" "")))
7712 (use (match_operand 3 "" ""))
7713 (clobber (reg:SI LR_REGNUM))]
7715 && (GET_CODE (operands[1]) == SYMBOL_REF)
7716 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7719 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7721 [(set_attr "type" "call")]
7724 (define_insn "*call_insn"
7725 [(call (mem:SI (match_operand:SI 0 "" ""))
7726 (match_operand:SI 1 "" ""))
7727 (use (match_operand 2 "" ""))
7728 (clobber (reg:SI LR_REGNUM))]
7730 && GET_CODE (operands[0]) == SYMBOL_REF
7731 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7733 [(set_attr "length" "4")
7734 (set_attr "type" "call")]
7737 (define_insn "*call_value_insn"
7738 [(set (match_operand 0 "" "")
7739 (call (mem:SI (match_operand 1 "" ""))
7740 (match_operand 2 "" "")))
7741 (use (match_operand 3 "" ""))
7742 (clobber (reg:SI LR_REGNUM))]
7744 && GET_CODE (operands[1]) == SYMBOL_REF
7745 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7747 [(set_attr "length" "4")
7748 (set_attr "type" "call")]
7751 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7752 (define_expand "sibcall"
7753 [(parallel [(call (match_operand 0 "memory_operand" "")
7754 (match_operand 1 "general_operand" ""))
7756 (use (match_operand 2 "" ""))])]
7760 if (operands[2] == NULL_RTX)
7761 operands[2] = const0_rtx;
7765 (define_expand "sibcall_value"
7766 [(parallel [(set (match_operand 0 "" "")
7767 (call (match_operand 1 "memory_operand" "")
7768 (match_operand 2 "general_operand" "")))
7770 (use (match_operand 3 "" ""))])]
7774 if (operands[3] == NULL_RTX)
7775 operands[3] = const0_rtx;
7779 (define_insn "*sibcall_insn"
7780 [(call (mem:SI (match_operand:SI 0 "" "X"))
7781 (match_operand 1 "" ""))
7783 (use (match_operand 2 "" ""))]
7784 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7786 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7788 [(set_attr "type" "call")]
7791 (define_insn "*sibcall_value_insn"
7792 [(set (match_operand 0 "" "")
7793 (call (mem:SI (match_operand:SI 1 "" "X"))
7794 (match_operand 2 "" "")))
7796 (use (match_operand 3 "" ""))]
7797 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7799 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7801 [(set_attr "type" "call")]
7804 ;; Often the return insn will be the same as loading from memory, so set attr
7805 (define_insn "return"
7807 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7810 if (arm_ccfsm_state == 2)
7812 arm_ccfsm_state += 2;
7815 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7817 [(set_attr "type" "load1")
7818 (set_attr "length" "12")
7819 (set_attr "predicable" "yes")]
7822 (define_insn "*cond_return"
7824 (if_then_else (match_operator 0 "arm_comparison_operator"
7825 [(match_operand 1 "cc_register" "") (const_int 0)])
7828 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7831 if (arm_ccfsm_state == 2)
7833 arm_ccfsm_state += 2;
7836 return output_return_instruction (operands[0], TRUE, FALSE);
7838 [(set_attr "conds" "use")
7839 (set_attr "length" "12")
7840 (set_attr "type" "load1")]
7843 (define_insn "*cond_return_inverted"
7845 (if_then_else (match_operator 0 "arm_comparison_operator"
7846 [(match_operand 1 "cc_register" "") (const_int 0)])
7849 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7852 if (arm_ccfsm_state == 2)
7854 arm_ccfsm_state += 2;
7857 return output_return_instruction (operands[0], TRUE, TRUE);
7859 [(set_attr "conds" "use")
7860 (set_attr "length" "12")
7861 (set_attr "type" "load1")]
7864 ;; Generate a sequence of instructions to determine if the processor is
7865 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7868 (define_expand "return_addr_mask"
7870 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7872 (set (match_operand:SI 0 "s_register_operand" "")
7873 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7875 (const_int 67108860)))] ; 0x03fffffc
7878 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7881 (define_insn "*check_arch2"
7882 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7883 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7886 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7887 [(set_attr "length" "8")
7888 (set_attr "conds" "set")]
7891 ;; Call subroutine returning any type.
7893 (define_expand "untyped_call"
7894 [(parallel [(call (match_operand 0 "" "")
7896 (match_operand 1 "" "")
7897 (match_operand 2 "" "")])]
7902 rtx par = gen_rtx_PARALLEL (VOIDmode,
7903 rtvec_alloc (XVECLEN (operands[2], 0)));
7904 rtx addr = gen_reg_rtx (Pmode);
7908 emit_move_insn (addr, XEXP (operands[1], 0));
7909 mem = change_address (operands[1], BLKmode, addr);
7911 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7913 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7915 /* Default code only uses r0 as a return value, but we could
7916 be using anything up to 4 registers. */
7917 if (REGNO (src) == R0_REGNUM)
7918 src = gen_rtx_REG (TImode, R0_REGNUM);
7920 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7922 size += GET_MODE_SIZE (GET_MODE (src));
7925 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7930 for (i = 0; i < XVECLEN (par, 0); i++)
7932 HOST_WIDE_INT offset = 0;
7933 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7936 emit_move_insn (addr, plus_constant (addr, size));
7938 mem = change_address (mem, GET_MODE (reg), NULL);
7939 if (REGNO (reg) == R0_REGNUM)
7941 /* On thumb we have to use a write-back instruction. */
7942 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7943 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7944 size = TARGET_ARM ? 16 : 0;
7948 emit_move_insn (mem, reg);
7949 size = GET_MODE_SIZE (GET_MODE (reg));
7953 /* The optimizer does not know that the call sets the function value
7954 registers we stored in the result block. We avoid problems by
7955 claiming that all hard registers are used and clobbered at this
7957 emit_insn (gen_blockage ());
7963 (define_expand "untyped_return"
7964 [(match_operand:BLK 0 "memory_operand" "")
7965 (match_operand 1 "" "")]
7970 rtx addr = gen_reg_rtx (Pmode);
7974 emit_move_insn (addr, XEXP (operands[0], 0));
7975 mem = change_address (operands[0], BLKmode, addr);
7977 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7979 HOST_WIDE_INT offset = 0;
7980 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7983 emit_move_insn (addr, plus_constant (addr, size));
7985 mem = change_address (mem, GET_MODE (reg), NULL);
7986 if (REGNO (reg) == R0_REGNUM)
7988 /* On thumb we have to use a write-back instruction. */
7989 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7990 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7991 size = TARGET_ARM ? 16 : 0;
7995 emit_move_insn (reg, mem);
7996 size = GET_MODE_SIZE (GET_MODE (reg));
8000 /* Emit USE insns before the return. */
8001 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8002 emit_insn (gen_rtx_USE (VOIDmode,
8003 SET_DEST (XVECEXP (operands[1], 0, i))));
8005 /* Construct the return. */
8006 expand_naked_return ();
8012 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8013 ;; all of memory. This blocks insns from being moved across this point.
8015 (define_insn "blockage"
8016 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8019 [(set_attr "length" "0")
8020 (set_attr "type" "block")]
8023 (define_expand "casesi"
8024 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8025 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8026 (match_operand:SI 2 "const_int_operand" "") ; total range
8027 (match_operand:SI 3 "" "") ; table label
8028 (match_operand:SI 4 "" "")] ; Out of range label
8033 if (operands[1] != const0_rtx)
8035 reg = gen_reg_rtx (SImode);
8037 emit_insn (gen_addsi3 (reg, operands[0],
8038 GEN_INT (-INTVAL (operands[1]))));
8042 if (!const_ok_for_arm (INTVAL (operands[2])))
8043 operands[2] = force_reg (SImode, operands[2]);
8045 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8051 ;; The USE in this pattern is needed to tell flow analysis that this is
8052 ;; a CASESI insn. It has no other purpose.
8053 (define_insn "casesi_internal"
8054 [(parallel [(set (pc)
8056 (leu (match_operand:SI 0 "s_register_operand" "r")
8057 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8058 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8059 (label_ref (match_operand 2 "" ""))))
8060 (label_ref (match_operand 3 "" ""))))
8061 (clobber (reg:CC CC_REGNUM))
8062 (use (label_ref (match_dup 2)))])]
8066 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8067 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8069 [(set_attr "conds" "clob")
8070 (set_attr "length" "12")]
8073 (define_expand "indirect_jump"
8075 (match_operand:SI 0 "s_register_operand" ""))]
8080 ;; NB Never uses BX.
8081 (define_insn "*arm_indirect_jump"
8083 (match_operand:SI 0 "s_register_operand" "r"))]
8085 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8086 [(set_attr "predicable" "yes")]
8089 (define_insn "*load_indirect_jump"
8091 (match_operand:SI 0 "memory_operand" "m"))]
8093 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8094 [(set_attr "type" "load1")
8095 (set_attr "pool_range" "4096")
8096 (set_attr "neg_pool_range" "4084")
8097 (set_attr "predicable" "yes")]
8100 ;; NB Never uses BX.
8101 (define_insn "*thumb_indirect_jump"
8103 (match_operand:SI 0 "register_operand" "l*r"))]
8106 [(set_attr "conds" "clob")
8107 (set_attr "length" "2")]
8118 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8119 return \"mov\\tr8, r8\";
8121 [(set (attr "length")
8122 (if_then_else (eq_attr "is_thumb" "yes")
8128 ;; Patterns to allow combination of arithmetic, cond code and shifts
8130 (define_insn "*arith_shiftsi"
8131 [(set (match_operand:SI 0 "s_register_operand" "=r")
8132 (match_operator:SI 1 "shiftable_operator"
8133 [(match_operator:SI 3 "shift_operator"
8134 [(match_operand:SI 4 "s_register_operand" "r")
8135 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8136 (match_operand:SI 2 "s_register_operand" "r")]))]
8138 "%i1%?\\t%0, %2, %4%S3"
8139 [(set_attr "predicable" "yes")
8140 (set_attr "shift" "4")
8141 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8142 (const_string "alu_shift")
8143 (const_string "alu_shift_reg")))]
8147 [(set (match_operand:SI 0 "s_register_operand" "")
8148 (match_operator:SI 1 "shiftable_operator"
8149 [(match_operator:SI 2 "shiftable_operator"
8150 [(match_operator:SI 3 "shift_operator"
8151 [(match_operand:SI 4 "s_register_operand" "")
8152 (match_operand:SI 5 "reg_or_int_operand" "")])
8153 (match_operand:SI 6 "s_register_operand" "")])
8154 (match_operand:SI 7 "arm_rhs_operand" "")]))
8155 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8158 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8161 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8164 (define_insn "*arith_shiftsi_compare0"
8165 [(set (reg:CC_NOOV CC_REGNUM)
8166 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8167 [(match_operator:SI 3 "shift_operator"
8168 [(match_operand:SI 4 "s_register_operand" "r")
8169 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8170 (match_operand:SI 2 "s_register_operand" "r")])
8172 (set (match_operand:SI 0 "s_register_operand" "=r")
8173 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8176 "%i1%?s\\t%0, %2, %4%S3"
8177 [(set_attr "conds" "set")
8178 (set_attr "shift" "4")
8179 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8180 (const_string "alu_shift")
8181 (const_string "alu_shift_reg")))]
8184 (define_insn "*arith_shiftsi_compare0_scratch"
8185 [(set (reg:CC_NOOV CC_REGNUM)
8186 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8187 [(match_operator:SI 3 "shift_operator"
8188 [(match_operand:SI 4 "s_register_operand" "r")
8189 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8190 (match_operand:SI 2 "s_register_operand" "r")])
8192 (clobber (match_scratch:SI 0 "=r"))]
8194 "%i1%?s\\t%0, %2, %4%S3"
8195 [(set_attr "conds" "set")
8196 (set_attr "shift" "4")
8197 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8198 (const_string "alu_shift")
8199 (const_string "alu_shift_reg")))]
8202 (define_insn "*sub_shiftsi"
8203 [(set (match_operand:SI 0 "s_register_operand" "=r")
8204 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8205 (match_operator:SI 2 "shift_operator"
8206 [(match_operand:SI 3 "s_register_operand" "r")
8207 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8209 "sub%?\\t%0, %1, %3%S2"
8210 [(set_attr "predicable" "yes")
8211 (set_attr "shift" "3")
8212 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8213 (const_string "alu_shift")
8214 (const_string "alu_shift_reg")))]
8217 (define_insn "*sub_shiftsi_compare0"
8218 [(set (reg:CC_NOOV CC_REGNUM)
8220 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8221 (match_operator:SI 2 "shift_operator"
8222 [(match_operand:SI 3 "s_register_operand" "r")
8223 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8225 (set (match_operand:SI 0 "s_register_operand" "=r")
8226 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8229 "sub%?s\\t%0, %1, %3%S2"
8230 [(set_attr "conds" "set")
8231 (set_attr "shift" "3")
8232 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8233 (const_string "alu_shift")
8234 (const_string "alu_shift_reg")))]
8237 (define_insn "*sub_shiftsi_compare0_scratch"
8238 [(set (reg:CC_NOOV CC_REGNUM)
8240 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8241 (match_operator:SI 2 "shift_operator"
8242 [(match_operand:SI 3 "s_register_operand" "r")
8243 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8245 (clobber (match_scratch:SI 0 "=r"))]
8247 "sub%?s\\t%0, %1, %3%S2"
8248 [(set_attr "conds" "set")
8249 (set_attr "shift" "3")
8250 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8251 (const_string "alu_shift")
8252 (const_string "alu_shift_reg")))]
8257 (define_insn "*and_scc"
8258 [(set (match_operand:SI 0 "s_register_operand" "=r")
8259 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8260 [(match_operand 3 "cc_register" "") (const_int 0)])
8261 (match_operand:SI 2 "s_register_operand" "r")))]
8263 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8264 [(set_attr "conds" "use")
8265 (set_attr "length" "8")]
8268 (define_insn "*ior_scc"
8269 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8270 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8271 [(match_operand 3 "cc_register" "") (const_int 0)])
8272 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8276 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8277 [(set_attr "conds" "use")
8278 (set_attr "length" "4,8")]
8281 (define_insn "*compare_scc"
8282 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8283 (match_operator:SI 1 "arm_comparison_operator"
8284 [(match_operand:SI 2 "s_register_operand" "r,r")
8285 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8286 (clobber (reg:CC CC_REGNUM))]
8289 if (operands[3] == const0_rtx)
8291 if (GET_CODE (operands[1]) == LT)
8292 return \"mov\\t%0, %2, lsr #31\";
8294 if (GET_CODE (operands[1]) == GE)
8295 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8297 if (GET_CODE (operands[1]) == EQ)
8298 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8301 if (GET_CODE (operands[1]) == NE)
8303 if (which_alternative == 1)
8304 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8305 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8307 if (which_alternative == 1)
8308 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8310 output_asm_insn (\"cmp\\t%2, %3\", operands);
8311 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8313 [(set_attr "conds" "clob")
8314 (set_attr "length" "12")]
8317 (define_insn "*cond_move"
8318 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8319 (if_then_else:SI (match_operator 3 "equality_operator"
8320 [(match_operator 4 "arm_comparison_operator"
8321 [(match_operand 5 "cc_register" "") (const_int 0)])
8323 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8324 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8327 if (GET_CODE (operands[3]) == NE)
8329 if (which_alternative != 1)
8330 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8331 if (which_alternative != 0)
8332 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8335 if (which_alternative != 0)
8336 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8337 if (which_alternative != 1)
8338 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8341 [(set_attr "conds" "use")
8342 (set_attr "length" "4,4,8")]
8345 (define_insn "*cond_arith"
8346 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8347 (match_operator:SI 5 "shiftable_operator"
8348 [(match_operator:SI 4 "arm_comparison_operator"
8349 [(match_operand:SI 2 "s_register_operand" "r,r")
8350 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8351 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8352 (clobber (reg:CC CC_REGNUM))]
8355 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8356 return \"%i5\\t%0, %1, %2, lsr #31\";
8358 output_asm_insn (\"cmp\\t%2, %3\", operands);
8359 if (GET_CODE (operands[5]) == AND)
8360 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8361 else if (GET_CODE (operands[5]) == MINUS)
8362 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8363 else if (which_alternative != 0)
8364 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8365 return \"%i5%d4\\t%0, %1, #1\";
8367 [(set_attr "conds" "clob")
8368 (set_attr "length" "12")]
8371 (define_insn "*cond_sub"
8372 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8373 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8374 (match_operator:SI 4 "arm_comparison_operator"
8375 [(match_operand:SI 2 "s_register_operand" "r,r")
8376 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8377 (clobber (reg:CC CC_REGNUM))]
8380 output_asm_insn (\"cmp\\t%2, %3\", operands);
8381 if (which_alternative != 0)
8382 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8383 return \"sub%d4\\t%0, %1, #1\";
8385 [(set_attr "conds" "clob")
8386 (set_attr "length" "8,12")]
8389 (define_insn "*cmp_ite0"
8390 [(set (match_operand 6 "dominant_cc_register" "")
8393 (match_operator 4 "arm_comparison_operator"
8394 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8395 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8396 (match_operator:SI 5 "arm_comparison_operator"
8397 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8398 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8404 static const char * const opcodes[4][2] =
8406 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8407 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8408 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8409 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8410 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8411 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8412 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8413 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8416 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8418 return opcodes[which_alternative][swap];
8420 [(set_attr "conds" "set")
8421 (set_attr "length" "8")]
8424 (define_insn "*cmp_ite1"
8425 [(set (match_operand 6 "dominant_cc_register" "")
8428 (match_operator 4 "arm_comparison_operator"
8429 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8430 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8431 (match_operator:SI 5 "arm_comparison_operator"
8432 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8433 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8439 static const char * const opcodes[4][2] =
8441 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8442 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8443 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8444 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8445 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8446 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8447 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8448 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8451 comparison_dominates_p (GET_CODE (operands[5]),
8452 reverse_condition (GET_CODE (operands[4])));
8454 return opcodes[which_alternative][swap];
8456 [(set_attr "conds" "set")
8457 (set_attr "length" "8")]
8460 (define_insn "*cmp_and"
8461 [(set (match_operand 6 "dominant_cc_register" "")
8464 (match_operator 4 "arm_comparison_operator"
8465 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8466 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8467 (match_operator:SI 5 "arm_comparison_operator"
8468 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8469 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8474 static const char *const opcodes[4][2] =
8476 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8477 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8478 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8479 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8480 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8481 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8482 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8483 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8486 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8488 return opcodes[which_alternative][swap];
8490 [(set_attr "conds" "set")
8491 (set_attr "predicable" "no")
8492 (set_attr "length" "8")]
8495 (define_insn "*cmp_ior"
8496 [(set (match_operand 6 "dominant_cc_register" "")
8499 (match_operator 4 "arm_comparison_operator"
8500 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8501 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8502 (match_operator:SI 5 "arm_comparison_operator"
8503 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8504 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8509 static const char *const opcodes[4][2] =
8511 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8512 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8513 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8514 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8515 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8516 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8517 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8518 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8521 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8523 return opcodes[which_alternative][swap];
8526 [(set_attr "conds" "set")
8527 (set_attr "length" "8")]
8530 (define_insn_and_split "*ior_scc_scc"
8531 [(set (match_operand:SI 0 "s_register_operand" "=r")
8532 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8533 [(match_operand:SI 1 "s_register_operand" "r")
8534 (match_operand:SI 2 "arm_add_operand" "rIL")])
8535 (match_operator:SI 6 "arm_comparison_operator"
8536 [(match_operand:SI 4 "s_register_operand" "r")
8537 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8538 (clobber (reg:CC CC_REGNUM))]
8540 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8543 "TARGET_ARM && reload_completed"
8547 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8548 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8550 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8552 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8555 [(set_attr "conds" "clob")
8556 (set_attr "length" "16")])
8558 ; If the above pattern is followed by a CMP insn, then the compare is
8559 ; redundant, since we can rework the conditional instruction that follows.
8560 (define_insn_and_split "*ior_scc_scc_cmp"
8561 [(set (match_operand 0 "dominant_cc_register" "")
8562 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8563 [(match_operand:SI 1 "s_register_operand" "r")
8564 (match_operand:SI 2 "arm_add_operand" "rIL")])
8565 (match_operator:SI 6 "arm_comparison_operator"
8566 [(match_operand:SI 4 "s_register_operand" "r")
8567 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8569 (set (match_operand:SI 7 "s_register_operand" "=r")
8570 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8571 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8574 "TARGET_ARM && reload_completed"
8578 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8579 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8581 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8583 [(set_attr "conds" "set")
8584 (set_attr "length" "16")])
8586 (define_insn_and_split "*and_scc_scc"
8587 [(set (match_operand:SI 0 "s_register_operand" "=r")
8588 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8589 [(match_operand:SI 1 "s_register_operand" "r")
8590 (match_operand:SI 2 "arm_add_operand" "rIL")])
8591 (match_operator:SI 6 "arm_comparison_operator"
8592 [(match_operand:SI 4 "s_register_operand" "r")
8593 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8594 (clobber (reg:CC CC_REGNUM))]
8596 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8599 "TARGET_ARM && reload_completed
8600 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8605 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8606 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8608 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8610 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8613 [(set_attr "conds" "clob")
8614 (set_attr "length" "16")])
8616 ; If the above pattern is followed by a CMP insn, then the compare is
8617 ; redundant, since we can rework the conditional instruction that follows.
8618 (define_insn_and_split "*and_scc_scc_cmp"
8619 [(set (match_operand 0 "dominant_cc_register" "")
8620 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8621 [(match_operand:SI 1 "s_register_operand" "r")
8622 (match_operand:SI 2 "arm_add_operand" "rIL")])
8623 (match_operator:SI 6 "arm_comparison_operator"
8624 [(match_operand:SI 4 "s_register_operand" "r")
8625 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8627 (set (match_operand:SI 7 "s_register_operand" "=r")
8628 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8629 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8632 "TARGET_ARM && reload_completed"
8636 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8637 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8639 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8641 [(set_attr "conds" "set")
8642 (set_attr "length" "16")])
8644 ;; If there is no dominance in the comparison, then we can still save an
8645 ;; instruction in the AND case, since we can know that the second compare
8646 ;; need only zero the value if false (if true, then the value is already
8648 (define_insn_and_split "*and_scc_scc_nodom"
8649 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8650 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8651 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8652 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8653 (match_operator:SI 6 "arm_comparison_operator"
8654 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8655 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8656 (clobber (reg:CC CC_REGNUM))]
8658 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8661 "TARGET_ARM && reload_completed"
8662 [(parallel [(set (match_dup 0)
8663 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8664 (clobber (reg:CC CC_REGNUM))])
8665 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8667 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8670 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8671 operands[4], operands[5]),
8673 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8675 [(set_attr "conds" "clob")
8676 (set_attr "length" "20")])
8679 [(set (reg:CC_NOOV CC_REGNUM)
8680 (compare:CC_NOOV (ior:SI
8681 (and:SI (match_operand:SI 0 "s_register_operand" "")
8683 (match_operator:SI 1 "comparison_operator"
8684 [(match_operand:SI 2 "s_register_operand" "")
8685 (match_operand:SI 3 "arm_add_operand" "")]))
8687 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8690 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8692 (set (reg:CC_NOOV CC_REGNUM)
8693 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8698 [(set (reg:CC_NOOV CC_REGNUM)
8699 (compare:CC_NOOV (ior:SI
8700 (match_operator:SI 1 "comparison_operator"
8701 [(match_operand:SI 2 "s_register_operand" "")
8702 (match_operand:SI 3 "arm_add_operand" "")])
8703 (and:SI (match_operand:SI 0 "s_register_operand" "")
8706 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8709 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8711 (set (reg:CC_NOOV CC_REGNUM)
8712 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8716 (define_insn "*negscc"
8717 [(set (match_operand:SI 0 "s_register_operand" "=r")
8718 (neg:SI (match_operator 3 "arm_comparison_operator"
8719 [(match_operand:SI 1 "s_register_operand" "r")
8720 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8721 (clobber (reg:CC CC_REGNUM))]
8724 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8725 return \"mov\\t%0, %1, asr #31\";
8727 if (GET_CODE (operands[3]) == NE)
8728 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8730 if (GET_CODE (operands[3]) == GT)
8731 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8733 output_asm_insn (\"cmp\\t%1, %2\", operands);
8734 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8735 return \"mvn%d3\\t%0, #0\";
8737 [(set_attr "conds" "clob")
8738 (set_attr "length" "12")]
8741 (define_insn "movcond"
8742 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8744 (match_operator 5 "arm_comparison_operator"
8745 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8746 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8747 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8748 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8749 (clobber (reg:CC CC_REGNUM))]
8752 if (GET_CODE (operands[5]) == LT
8753 && (operands[4] == const0_rtx))
8755 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8757 if (operands[2] == const0_rtx)
8758 return \"and\\t%0, %1, %3, asr #31\";
8759 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8761 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8763 if (operands[1] == const0_rtx)
8764 return \"bic\\t%0, %2, %3, asr #31\";
8765 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8767 /* The only case that falls through to here is when both ops 1 & 2
8771 if (GET_CODE (operands[5]) == GE
8772 && (operands[4] == const0_rtx))
8774 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8776 if (operands[2] == const0_rtx)
8777 return \"bic\\t%0, %1, %3, asr #31\";
8778 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8780 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8782 if (operands[1] == const0_rtx)
8783 return \"and\\t%0, %2, %3, asr #31\";
8784 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8786 /* The only case that falls through to here is when both ops 1 & 2
8789 if (GET_CODE (operands[4]) == CONST_INT
8790 && !const_ok_for_arm (INTVAL (operands[4])))
8791 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8793 output_asm_insn (\"cmp\\t%3, %4\", operands);
8794 if (which_alternative != 0)
8795 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8796 if (which_alternative != 1)
8797 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8800 [(set_attr "conds" "clob")
8801 (set_attr "length" "8,8,12")]
8804 (define_insn "*ifcompare_plus_move"
8805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8806 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8807 [(match_operand:SI 4 "s_register_operand" "r,r")
8808 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8810 (match_operand:SI 2 "s_register_operand" "r,r")
8811 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8812 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8813 (clobber (reg:CC CC_REGNUM))]
8816 [(set_attr "conds" "clob")
8817 (set_attr "length" "8,12")]
8820 (define_insn "*if_plus_move"
8821 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8823 (match_operator 4 "arm_comparison_operator"
8824 [(match_operand 5 "cc_register" "") (const_int 0)])
8826 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8827 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8828 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8832 sub%d4\\t%0, %2, #%n3
8833 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8834 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8835 [(set_attr "conds" "use")
8836 (set_attr "length" "4,4,8,8")
8837 (set_attr "type" "*,*,*,*")]
8840 (define_insn "*ifcompare_move_plus"
8841 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8842 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8843 [(match_operand:SI 4 "s_register_operand" "r,r")
8844 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8845 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8847 (match_operand:SI 2 "s_register_operand" "r,r")
8848 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8849 (clobber (reg:CC CC_REGNUM))]
8852 [(set_attr "conds" "clob")
8853 (set_attr "length" "8,12")]
8856 (define_insn "*if_move_plus"
8857 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8859 (match_operator 4 "arm_comparison_operator"
8860 [(match_operand 5 "cc_register" "") (const_int 0)])
8861 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8863 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8864 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8868 sub%D4\\t%0, %2, #%n3
8869 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8870 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8871 [(set_attr "conds" "use")
8872 (set_attr "length" "4,4,8,8")
8873 (set_attr "type" "*,*,*,*")]
8876 (define_insn "*ifcompare_arith_arith"
8877 [(set (match_operand:SI 0 "s_register_operand" "=r")
8878 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8879 [(match_operand:SI 5 "s_register_operand" "r")
8880 (match_operand:SI 6 "arm_add_operand" "rIL")])
8881 (match_operator:SI 8 "shiftable_operator"
8882 [(match_operand:SI 1 "s_register_operand" "r")
8883 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8884 (match_operator:SI 7 "shiftable_operator"
8885 [(match_operand:SI 3 "s_register_operand" "r")
8886 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8887 (clobber (reg:CC CC_REGNUM))]
8890 [(set_attr "conds" "clob")
8891 (set_attr "length" "12")]
8894 (define_insn "*if_arith_arith"
8895 [(set (match_operand:SI 0 "s_register_operand" "=r")
8896 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8897 [(match_operand 8 "cc_register" "") (const_int 0)])
8898 (match_operator:SI 6 "shiftable_operator"
8899 [(match_operand:SI 1 "s_register_operand" "r")
8900 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8901 (match_operator:SI 7 "shiftable_operator"
8902 [(match_operand:SI 3 "s_register_operand" "r")
8903 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8905 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8906 [(set_attr "conds" "use")
8907 (set_attr "length" "8")]
8910 (define_insn "*ifcompare_arith_move"
8911 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8912 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8913 [(match_operand:SI 2 "s_register_operand" "r,r")
8914 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8915 (match_operator:SI 7 "shiftable_operator"
8916 [(match_operand:SI 4 "s_register_operand" "r,r")
8917 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8918 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8919 (clobber (reg:CC CC_REGNUM))]
8922 /* If we have an operation where (op x 0) is the identity operation and
8923 the conditional operator is LT or GE and we are comparing against zero and
8924 everything is in registers then we can do this in two instructions. */
8925 if (operands[3] == const0_rtx
8926 && GET_CODE (operands[7]) != AND
8927 && GET_CODE (operands[5]) == REG
8928 && GET_CODE (operands[1]) == REG
8929 && REGNO (operands[1]) == REGNO (operands[4])
8930 && REGNO (operands[4]) != REGNO (operands[0]))
8932 if (GET_CODE (operands[6]) == LT)
8933 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8934 else if (GET_CODE (operands[6]) == GE)
8935 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8937 if (GET_CODE (operands[3]) == CONST_INT
8938 && !const_ok_for_arm (INTVAL (operands[3])))
8939 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8941 output_asm_insn (\"cmp\\t%2, %3\", operands);
8942 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8943 if (which_alternative != 0)
8944 return \"mov%D6\\t%0, %1\";
8947 [(set_attr "conds" "clob")
8948 (set_attr "length" "8,12")]
8951 (define_insn "*if_arith_move"
8952 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8953 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8954 [(match_operand 6 "cc_register" "") (const_int 0)])
8955 (match_operator:SI 5 "shiftable_operator"
8956 [(match_operand:SI 2 "s_register_operand" "r,r")
8957 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8958 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8962 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8963 [(set_attr "conds" "use")
8964 (set_attr "length" "4,8")
8965 (set_attr "type" "*,*")]
8968 (define_insn "*ifcompare_move_arith"
8969 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8970 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8971 [(match_operand:SI 4 "s_register_operand" "r,r")
8972 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8973 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8974 (match_operator:SI 7 "shiftable_operator"
8975 [(match_operand:SI 2 "s_register_operand" "r,r")
8976 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8977 (clobber (reg:CC CC_REGNUM))]
8980 /* If we have an operation where (op x 0) is the identity operation and
8981 the conditional operator is LT or GE and we are comparing against zero and
8982 everything is in registers then we can do this in two instructions */
8983 if (operands[5] == const0_rtx
8984 && GET_CODE (operands[7]) != AND
8985 && GET_CODE (operands[3]) == REG
8986 && GET_CODE (operands[1]) == REG
8987 && REGNO (operands[1]) == REGNO (operands[2])
8988 && REGNO (operands[2]) != REGNO (operands[0]))
8990 if (GET_CODE (operands[6]) == GE)
8991 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8992 else if (GET_CODE (operands[6]) == LT)
8993 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8996 if (GET_CODE (operands[5]) == CONST_INT
8997 && !const_ok_for_arm (INTVAL (operands[5])))
8998 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9000 output_asm_insn (\"cmp\\t%4, %5\", operands);
9002 if (which_alternative != 0)
9003 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9004 return \"%I7%D6\\t%0, %2, %3\";
9006 [(set_attr "conds" "clob")
9007 (set_attr "length" "8,12")]
9010 (define_insn "*if_move_arith"
9011 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9013 (match_operator 4 "arm_comparison_operator"
9014 [(match_operand 6 "cc_register" "") (const_int 0)])
9015 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9016 (match_operator:SI 5 "shiftable_operator"
9017 [(match_operand:SI 2 "s_register_operand" "r,r")
9018 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9022 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9023 [(set_attr "conds" "use")
9024 (set_attr "length" "4,8")
9025 (set_attr "type" "*,*")]
9028 (define_insn "*ifcompare_move_not"
9029 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9031 (match_operator 5 "arm_comparison_operator"
9032 [(match_operand:SI 3 "s_register_operand" "r,r")
9033 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9034 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9036 (match_operand:SI 2 "s_register_operand" "r,r"))))
9037 (clobber (reg:CC CC_REGNUM))]
9040 [(set_attr "conds" "clob")
9041 (set_attr "length" "8,12")]
9044 (define_insn "*if_move_not"
9045 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9047 (match_operator 4 "arm_comparison_operator"
9048 [(match_operand 3 "cc_register" "") (const_int 0)])
9049 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9050 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9054 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9055 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9056 [(set_attr "conds" "use")
9057 (set_attr "length" "4,8,8")]
9060 (define_insn "*ifcompare_not_move"
9061 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9063 (match_operator 5 "arm_comparison_operator"
9064 [(match_operand:SI 3 "s_register_operand" "r,r")
9065 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9067 (match_operand:SI 2 "s_register_operand" "r,r"))
9068 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9069 (clobber (reg:CC CC_REGNUM))]
9072 [(set_attr "conds" "clob")
9073 (set_attr "length" "8,12")]
9076 (define_insn "*if_not_move"
9077 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9079 (match_operator 4 "arm_comparison_operator"
9080 [(match_operand 3 "cc_register" "") (const_int 0)])
9081 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9082 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9086 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9087 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9088 [(set_attr "conds" "use")
9089 (set_attr "length" "4,8,8")]
9092 (define_insn "*ifcompare_shift_move"
9093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9095 (match_operator 6 "arm_comparison_operator"
9096 [(match_operand:SI 4 "s_register_operand" "r,r")
9097 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9098 (match_operator:SI 7 "shift_operator"
9099 [(match_operand:SI 2 "s_register_operand" "r,r")
9100 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9101 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9102 (clobber (reg:CC CC_REGNUM))]
9105 [(set_attr "conds" "clob")
9106 (set_attr "length" "8,12")]
9109 (define_insn "*if_shift_move"
9110 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9112 (match_operator 5 "arm_comparison_operator"
9113 [(match_operand 6 "cc_register" "") (const_int 0)])
9114 (match_operator:SI 4 "shift_operator"
9115 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9116 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9117 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9121 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9122 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9123 [(set_attr "conds" "use")
9124 (set_attr "shift" "2")
9125 (set_attr "length" "4,8,8")
9126 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9127 (const_string "alu_shift")
9128 (const_string "alu_shift_reg")))]
9131 (define_insn "*ifcompare_move_shift"
9132 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9134 (match_operator 6 "arm_comparison_operator"
9135 [(match_operand:SI 4 "s_register_operand" "r,r")
9136 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9137 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9138 (match_operator:SI 7 "shift_operator"
9139 [(match_operand:SI 2 "s_register_operand" "r,r")
9140 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9141 (clobber (reg:CC CC_REGNUM))]
9144 [(set_attr "conds" "clob")
9145 (set_attr "length" "8,12")]
9148 (define_insn "*if_move_shift"
9149 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9151 (match_operator 5 "arm_comparison_operator"
9152 [(match_operand 6 "cc_register" "") (const_int 0)])
9153 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9154 (match_operator:SI 4 "shift_operator"
9155 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9156 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9160 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9161 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9162 [(set_attr "conds" "use")
9163 (set_attr "shift" "2")
9164 (set_attr "length" "4,8,8")
9165 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9166 (const_string "alu_shift")
9167 (const_string "alu_shift_reg")))]
9170 (define_insn "*ifcompare_shift_shift"
9171 [(set (match_operand:SI 0 "s_register_operand" "=r")
9173 (match_operator 7 "arm_comparison_operator"
9174 [(match_operand:SI 5 "s_register_operand" "r")
9175 (match_operand:SI 6 "arm_add_operand" "rIL")])
9176 (match_operator:SI 8 "shift_operator"
9177 [(match_operand:SI 1 "s_register_operand" "r")
9178 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9179 (match_operator:SI 9 "shift_operator"
9180 [(match_operand:SI 3 "s_register_operand" "r")
9181 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9182 (clobber (reg:CC CC_REGNUM))]
9185 [(set_attr "conds" "clob")
9186 (set_attr "length" "12")]
9189 (define_insn "*if_shift_shift"
9190 [(set (match_operand:SI 0 "s_register_operand" "=r")
9192 (match_operator 5 "arm_comparison_operator"
9193 [(match_operand 8 "cc_register" "") (const_int 0)])
9194 (match_operator:SI 6 "shift_operator"
9195 [(match_operand:SI 1 "s_register_operand" "r")
9196 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9197 (match_operator:SI 7 "shift_operator"
9198 [(match_operand:SI 3 "s_register_operand" "r")
9199 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9201 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9202 [(set_attr "conds" "use")
9203 (set_attr "shift" "1")
9204 (set_attr "length" "8")
9205 (set (attr "type") (if_then_else
9206 (and (match_operand 2 "const_int_operand" "")
9207 (match_operand 4 "const_int_operand" ""))
9208 (const_string "alu_shift")
9209 (const_string "alu_shift_reg")))]
9212 (define_insn "*ifcompare_not_arith"
9213 [(set (match_operand:SI 0 "s_register_operand" "=r")
9215 (match_operator 6 "arm_comparison_operator"
9216 [(match_operand:SI 4 "s_register_operand" "r")
9217 (match_operand:SI 5 "arm_add_operand" "rIL")])
9218 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9219 (match_operator:SI 7 "shiftable_operator"
9220 [(match_operand:SI 2 "s_register_operand" "r")
9221 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9222 (clobber (reg:CC CC_REGNUM))]
9225 [(set_attr "conds" "clob")
9226 (set_attr "length" "12")]
9229 (define_insn "*if_not_arith"
9230 [(set (match_operand:SI 0 "s_register_operand" "=r")
9232 (match_operator 5 "arm_comparison_operator"
9233 [(match_operand 4 "cc_register" "") (const_int 0)])
9234 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9235 (match_operator:SI 6 "shiftable_operator"
9236 [(match_operand:SI 2 "s_register_operand" "r")
9237 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9239 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9240 [(set_attr "conds" "use")
9241 (set_attr "length" "8")]
9244 (define_insn "*ifcompare_arith_not"
9245 [(set (match_operand:SI 0 "s_register_operand" "=r")
9247 (match_operator 6 "arm_comparison_operator"
9248 [(match_operand:SI 4 "s_register_operand" "r")
9249 (match_operand:SI 5 "arm_add_operand" "rIL")])
9250 (match_operator:SI 7 "shiftable_operator"
9251 [(match_operand:SI 2 "s_register_operand" "r")
9252 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9253 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9254 (clobber (reg:CC CC_REGNUM))]
9257 [(set_attr "conds" "clob")
9258 (set_attr "length" "12")]
9261 (define_insn "*if_arith_not"
9262 [(set (match_operand:SI 0 "s_register_operand" "=r")
9264 (match_operator 5 "arm_comparison_operator"
9265 [(match_operand 4 "cc_register" "") (const_int 0)])
9266 (match_operator:SI 6 "shiftable_operator"
9267 [(match_operand:SI 2 "s_register_operand" "r")
9268 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9269 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9271 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9272 [(set_attr "conds" "use")
9273 (set_attr "length" "8")]
9276 (define_insn "*ifcompare_neg_move"
9277 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9279 (match_operator 5 "arm_comparison_operator"
9280 [(match_operand:SI 3 "s_register_operand" "r,r")
9281 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9282 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9283 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9284 (clobber (reg:CC CC_REGNUM))]
9287 [(set_attr "conds" "clob")
9288 (set_attr "length" "8,12")]
9291 (define_insn "*if_neg_move"
9292 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9294 (match_operator 4 "arm_comparison_operator"
9295 [(match_operand 3 "cc_register" "") (const_int 0)])
9296 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9297 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9301 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9302 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9303 [(set_attr "conds" "use")
9304 (set_attr "length" "4,8,8")]
9307 (define_insn "*ifcompare_move_neg"
9308 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9310 (match_operator 5 "arm_comparison_operator"
9311 [(match_operand:SI 3 "s_register_operand" "r,r")
9312 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9313 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9314 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9315 (clobber (reg:CC CC_REGNUM))]
9318 [(set_attr "conds" "clob")
9319 (set_attr "length" "8,12")]
9322 (define_insn "*if_move_neg"
9323 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9325 (match_operator 4 "arm_comparison_operator"
9326 [(match_operand 3 "cc_register" "") (const_int 0)])
9327 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9328 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9332 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9333 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9334 [(set_attr "conds" "use")
9335 (set_attr "length" "4,8,8")]
9338 (define_insn "*arith_adjacentmem"
9339 [(set (match_operand:SI 0 "s_register_operand" "=r")
9340 (match_operator:SI 1 "shiftable_operator"
9341 [(match_operand:SI 2 "memory_operand" "m")
9342 (match_operand:SI 3 "memory_operand" "m")]))
9343 (clobber (match_scratch:SI 4 "=r"))]
9344 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9350 HOST_WIDE_INT val1 = 0, val2 = 0;
9352 if (REGNO (operands[0]) > REGNO (operands[4]))
9354 ldm[1] = operands[4];
9355 ldm[2] = operands[0];
9359 ldm[1] = operands[0];
9360 ldm[2] = operands[4];
9363 base_reg = XEXP (operands[2], 0);
9365 if (!REG_P (base_reg))
9367 val1 = INTVAL (XEXP (base_reg, 1));
9368 base_reg = XEXP (base_reg, 0);
9371 if (!REG_P (XEXP (operands[3], 0)))
9372 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9374 arith[0] = operands[0];
9375 arith[3] = operands[1];
9389 if (val1 !=0 && val2 != 0)
9391 if (val1 == 4 || val2 == 4)
9392 /* Other val must be 8, since we know they are adjacent and neither
9394 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9399 ldm[0] = ops[0] = operands[4];
9401 ops[2] = GEN_INT (val1);
9402 output_add_immediate (ops);
9404 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9406 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9412 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9414 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9419 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9421 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9423 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9426 [(set_attr "length" "12")
9427 (set_attr "predicable" "yes")
9428 (set_attr "type" "load1")]
9431 ; This pattern is never tried by combine, so do it as a peephole
9434 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9435 (match_operand:SI 1 "arm_general_register_operand" ""))
9436 (set (reg:CC CC_REGNUM)
9437 (compare:CC (match_dup 1) (const_int 0)))]
9439 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9440 (set (match_dup 0) (match_dup 1))])]
9444 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9445 ; reversed, check that the memory references aren't volatile.
9448 [(set (match_operand:SI 0 "s_register_operand" "=r")
9449 (match_operand:SI 4 "memory_operand" "m"))
9450 (set (match_operand:SI 1 "s_register_operand" "=r")
9451 (match_operand:SI 5 "memory_operand" "m"))
9452 (set (match_operand:SI 2 "s_register_operand" "=r")
9453 (match_operand:SI 6 "memory_operand" "m"))
9454 (set (match_operand:SI 3 "s_register_operand" "=r")
9455 (match_operand:SI 7 "memory_operand" "m"))]
9456 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9458 return emit_ldm_seq (operands, 4);
9463 [(set (match_operand:SI 0 "s_register_operand" "=r")
9464 (match_operand:SI 3 "memory_operand" "m"))
9465 (set (match_operand:SI 1 "s_register_operand" "=r")
9466 (match_operand:SI 4 "memory_operand" "m"))
9467 (set (match_operand:SI 2 "s_register_operand" "=r")
9468 (match_operand:SI 5 "memory_operand" "m"))]
9469 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9471 return emit_ldm_seq (operands, 3);
9476 [(set (match_operand:SI 0 "s_register_operand" "=r")
9477 (match_operand:SI 2 "memory_operand" "m"))
9478 (set (match_operand:SI 1 "s_register_operand" "=r")
9479 (match_operand:SI 3 "memory_operand" "m"))]
9480 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9482 return emit_ldm_seq (operands, 2);
9487 [(set (match_operand:SI 4 "memory_operand" "=m")
9488 (match_operand:SI 0 "s_register_operand" "r"))
9489 (set (match_operand:SI 5 "memory_operand" "=m")
9490 (match_operand:SI 1 "s_register_operand" "r"))
9491 (set (match_operand:SI 6 "memory_operand" "=m")
9492 (match_operand:SI 2 "s_register_operand" "r"))
9493 (set (match_operand:SI 7 "memory_operand" "=m")
9494 (match_operand:SI 3 "s_register_operand" "r"))]
9495 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9497 return emit_stm_seq (operands, 4);
9502 [(set (match_operand:SI 3 "memory_operand" "=m")
9503 (match_operand:SI 0 "s_register_operand" "r"))
9504 (set (match_operand:SI 4 "memory_operand" "=m")
9505 (match_operand:SI 1 "s_register_operand" "r"))
9506 (set (match_operand:SI 5 "memory_operand" "=m")
9507 (match_operand:SI 2 "s_register_operand" "r"))]
9508 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9510 return emit_stm_seq (operands, 3);
9515 [(set (match_operand:SI 2 "memory_operand" "=m")
9516 (match_operand:SI 0 "s_register_operand" "r"))
9517 (set (match_operand:SI 3 "memory_operand" "=m")
9518 (match_operand:SI 1 "s_register_operand" "r"))]
9519 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9521 return emit_stm_seq (operands, 2);
9526 [(set (match_operand:SI 0 "s_register_operand" "")
9527 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9529 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9530 [(match_operand:SI 3 "s_register_operand" "")
9531 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9532 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9534 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9535 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9540 ;; This split can be used because CC_Z mode implies that the following
9541 ;; branch will be an equality, or an unsigned inequality, so the sign
9542 ;; extension is not needed.
9545 [(set (reg:CC_Z CC_REGNUM)
9547 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9549 (match_operand 1 "const_int_operand" "")))
9550 (clobber (match_scratch:SI 2 ""))]
9552 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9553 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9554 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9555 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9557 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9561 (define_expand "prologue"
9562 [(clobber (const_int 0))]
9565 arm_expand_prologue ();
9567 thumb_expand_prologue ();
9572 (define_expand "epilogue"
9573 [(clobber (const_int 0))]
9576 if (current_function_calls_eh_return)
9577 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9579 thumb_expand_epilogue ();
9580 else if (USE_RETURN_INSN (FALSE))
9582 emit_jump_insn (gen_return ());
9585 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9587 gen_rtx_RETURN (VOIDmode)),
9593 ;; Note - although unspec_volatile's USE all hard registers,
9594 ;; USEs are ignored after relaod has completed. Thus we need
9595 ;; to add an unspec of the link register to ensure that flow
9596 ;; does not think that it is unused by the sibcall branch that
9597 ;; will replace the standard function epilogue.
9598 (define_insn "sibcall_epilogue"
9599 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9600 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9603 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9604 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9605 return arm_output_epilogue (next_nonnote_insn (insn));
9607 ;; Length is absolute worst case
9608 [(set_attr "length" "44")
9609 (set_attr "type" "block")
9610 ;; We don't clobber the conditions, but the potential length of this
9611 ;; operation is sufficient to make conditionalizing the sequence
9612 ;; unlikely to be profitable.
9613 (set_attr "conds" "clob")]
9616 (define_insn "*epilogue_insns"
9617 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9621 return arm_output_epilogue (NULL);
9622 else /* TARGET_THUMB */
9623 return thumb_unexpanded_epilogue ();
9625 ; Length is absolute worst case
9626 [(set_attr "length" "44")
9627 (set_attr "type" "block")
9628 ;; We don't clobber the conditions, but the potential length of this
9629 ;; operation is sufficient to make conditionalizing the sequence
9630 ;; unlikely to be profitable.
9631 (set_attr "conds" "clob")]
9634 (define_expand "eh_epilogue"
9635 [(use (match_operand:SI 0 "register_operand" ""))
9636 (use (match_operand:SI 1 "register_operand" ""))
9637 (use (match_operand:SI 2 "register_operand" ""))]
9641 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9642 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9644 rtx ra = gen_rtx_REG (Pmode, 2);
9646 emit_move_insn (ra, operands[2]);
9649 /* This is a hack -- we may have crystalized the function type too
9651 cfun->machine->func_type = 0;
9655 ;; This split is only used during output to reduce the number of patterns
9656 ;; that need assembler instructions adding to them. We allowed the setting
9657 ;; of the conditions to be implicit during rtl generation so that
9658 ;; the conditional compare patterns would work. However this conflicts to
9659 ;; some extent with the conditional data operations, so we have to split them
9663 [(set (match_operand:SI 0 "s_register_operand" "")
9664 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9665 [(match_operand 2 "" "") (match_operand 3 "" "")])
9667 (match_operand 4 "" "")))
9668 (clobber (reg:CC CC_REGNUM))]
9669 "TARGET_ARM && reload_completed"
9670 [(set (match_dup 5) (match_dup 6))
9671 (cond_exec (match_dup 7)
9672 (set (match_dup 0) (match_dup 4)))]
9675 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9676 operands[2], operands[3]);
9677 enum rtx_code rc = GET_CODE (operands[1]);
9679 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9680 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9681 if (mode == CCFPmode || mode == CCFPEmode)
9682 rc = reverse_condition_maybe_unordered (rc);
9684 rc = reverse_condition (rc);
9686 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9691 [(set (match_operand:SI 0 "s_register_operand" "")
9692 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9693 [(match_operand 2 "" "") (match_operand 3 "" "")])
9694 (match_operand 4 "" "")
9696 (clobber (reg:CC CC_REGNUM))]
9697 "TARGET_ARM && reload_completed"
9698 [(set (match_dup 5) (match_dup 6))
9699 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9700 (set (match_dup 0) (match_dup 4)))]
9703 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9704 operands[2], operands[3]);
9706 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9707 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9712 [(set (match_operand:SI 0 "s_register_operand" "")
9713 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9714 [(match_operand 2 "" "") (match_operand 3 "" "")])
9715 (match_operand 4 "" "")
9716 (match_operand 5 "" "")))
9717 (clobber (reg:CC CC_REGNUM))]
9718 "TARGET_ARM && reload_completed"
9719 [(set (match_dup 6) (match_dup 7))
9720 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9721 (set (match_dup 0) (match_dup 4)))
9722 (cond_exec (match_dup 8)
9723 (set (match_dup 0) (match_dup 5)))]
9726 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9727 operands[2], operands[3]);
9728 enum rtx_code rc = GET_CODE (operands[1]);
9730 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9731 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9732 if (mode == CCFPmode || mode == CCFPEmode)
9733 rc = reverse_condition_maybe_unordered (rc);
9735 rc = reverse_condition (rc);
9737 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9742 [(set (match_operand:SI 0 "s_register_operand" "")
9743 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9744 [(match_operand:SI 2 "s_register_operand" "")
9745 (match_operand:SI 3 "arm_add_operand" "")])
9746 (match_operand:SI 4 "arm_rhs_operand" "")
9748 (match_operand:SI 5 "s_register_operand" ""))))
9749 (clobber (reg:CC CC_REGNUM))]
9750 "TARGET_ARM && reload_completed"
9751 [(set (match_dup 6) (match_dup 7))
9752 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9753 (set (match_dup 0) (match_dup 4)))
9754 (cond_exec (match_dup 8)
9755 (set (match_dup 0) (not:SI (match_dup 5))))]
9758 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9759 operands[2], operands[3]);
9760 enum rtx_code rc = GET_CODE (operands[1]);
9762 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9763 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9764 if (mode == CCFPmode || mode == CCFPEmode)
9765 rc = reverse_condition_maybe_unordered (rc);
9767 rc = reverse_condition (rc);
9769 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9773 (define_insn "*cond_move_not"
9774 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9775 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9776 [(match_operand 3 "cc_register" "") (const_int 0)])
9777 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9779 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9783 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9784 [(set_attr "conds" "use")
9785 (set_attr "length" "4,8")]
9788 ;; The next two patterns occur when an AND operation is followed by a
9789 ;; scc insn sequence
9791 (define_insn "*sign_extract_onebit"
9792 [(set (match_operand:SI 0 "s_register_operand" "=r")
9793 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9795 (match_operand:SI 2 "const_int_operand" "n")))
9796 (clobber (reg:CC CC_REGNUM))]
9799 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9800 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9801 return \"mvnne\\t%0, #0\";
9803 [(set_attr "conds" "clob")
9804 (set_attr "length" "8")]
9807 (define_insn "*not_signextract_onebit"
9808 [(set (match_operand:SI 0 "s_register_operand" "=r")
9810 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9812 (match_operand:SI 2 "const_int_operand" "n"))))
9813 (clobber (reg:CC CC_REGNUM))]
9816 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9817 output_asm_insn (\"tst\\t%1, %2\", operands);
9818 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9819 return \"movne\\t%0, #0\";
9821 [(set_attr "conds" "clob")
9822 (set_attr "length" "12")]
9825 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9826 ;; expressions. For simplicity, the first register is also in the unspec
9828 (define_insn "*push_multi"
9829 [(match_parallel 2 "multi_register_push"
9830 [(set (match_operand:BLK 0 "memory_operand" "=m")
9831 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9832 UNSPEC_PUSH_MULT))])]
9836 int num_saves = XVECLEN (operands[2], 0);
9838 /* For the StrongARM at least it is faster to
9839 use STR to store only a single register. */
9841 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9847 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9849 for (i = 1; i < num_saves; i++)
9851 strcat (pattern, \", %|\");
9853 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9856 strcat (pattern, \"}\");
9857 output_asm_insn (pattern, operands);
9862 [(set_attr "type" "store4")]
9865 (define_insn "stack_tie"
9866 [(set (mem:BLK (scratch))
9867 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9868 (match_operand:SI 1 "s_register_operand" "r")]
9872 [(set_attr "length" "0")]
9875 ;; Similarly for the floating point registers
9876 (define_insn "*push_fp_multi"
9877 [(match_parallel 2 "multi_register_push"
9878 [(set (match_operand:BLK 0 "memory_operand" "=m")
9879 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9880 UNSPEC_PUSH_MULT))])]
9881 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9886 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9887 output_asm_insn (pattern, operands);
9890 [(set_attr "type" "f_store")]
9893 ;; Special patterns for dealing with the constant pool
9895 (define_insn "align_4"
9896 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9899 assemble_align (32);
9904 (define_insn "align_8"
9905 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9908 assemble_align (64);
9913 (define_insn "consttable_end"
9914 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9917 making_const_table = FALSE;
9922 (define_insn "consttable_1"
9923 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9926 making_const_table = TRUE;
9927 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9931 [(set_attr "length" "4")]
9934 (define_insn "consttable_2"
9935 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9938 making_const_table = TRUE;
9939 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9943 [(set_attr "length" "4")]
9946 (define_insn "consttable_4"
9947 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9951 making_const_table = TRUE;
9952 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9957 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9958 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9962 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9967 [(set_attr "length" "4")]
9970 (define_insn "consttable_8"
9971 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9975 making_const_table = TRUE;
9976 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9981 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9982 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9986 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9991 [(set_attr "length" "8")]
9994 ;; Miscellaneous Thumb patterns
9996 (define_expand "tablejump"
9997 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9998 (use (label_ref (match_operand 1 "" "")))])]
10003 /* Hopefully, CSE will eliminate this copy. */
10004 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10005 rtx reg2 = gen_reg_rtx (SImode);
10007 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10008 operands[0] = reg2;
10013 ;; NB never uses BX.
10014 (define_insn "*thumb_tablejump"
10015 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10016 (use (label_ref (match_operand 1 "" "")))]
10019 [(set_attr "length" "2")]
10022 ;; V5 Instructions,
10024 (define_insn "clzsi2"
10025 [(set (match_operand:SI 0 "s_register_operand" "=r")
10026 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10027 "TARGET_ARM && arm_arch5"
10029 [(set_attr "predicable" "yes")])
10031 (define_expand "ffssi2"
10032 [(set (match_operand:SI 0 "s_register_operand" "")
10033 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10034 "TARGET_ARM && arm_arch5"
10039 t1 = gen_reg_rtx (SImode);
10040 t2 = gen_reg_rtx (SImode);
10041 t3 = gen_reg_rtx (SImode);
10043 emit_insn (gen_negsi2 (t1, operands[1]));
10044 emit_insn (gen_andsi3 (t2, operands[1], t1));
10045 emit_insn (gen_clzsi2 (t3, t2));
10046 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10051 (define_expand "ctzsi2"
10052 [(set (match_operand:SI 0 "s_register_operand" "")
10053 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10054 "TARGET_ARM && arm_arch5"
10059 t1 = gen_reg_rtx (SImode);
10060 t2 = gen_reg_rtx (SImode);
10061 t3 = gen_reg_rtx (SImode);
10063 emit_insn (gen_negsi2 (t1, operands[1]));
10064 emit_insn (gen_andsi3 (t2, operands[1], t1));
10065 emit_insn (gen_clzsi2 (t3, t2));
10066 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10071 ;; V5E instructions.
10073 (define_insn "prefetch"
10074 [(prefetch (match_operand:SI 0 "address_operand" "p")
10075 (match_operand:SI 1 "" "")
10076 (match_operand:SI 2 "" ""))]
10077 "TARGET_ARM && arm_arch5e"
10080 ;; General predication pattern
10083 [(match_operator 0 "arm_comparison_operator"
10084 [(match_operand 1 "cc_register" "")
10090 (define_insn "prologue_use"
10091 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10093 "%@ %0 needed for prologue"
10097 ;; Patterns for exception handling
10099 (define_expand "eh_return"
10100 [(use (match_operand 0 "general_operand" ""))]
10105 emit_insn (gen_arm_eh_return (operands[0]));
10107 emit_insn (gen_thumb_eh_return (operands[0]));
10112 ;; We can't expand this before we know where the link register is stored.
10113 (define_insn_and_split "arm_eh_return"
10114 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10116 (clobber (match_scratch:SI 1 "=&r"))]
10119 "&& reload_completed"
10123 arm_set_return_address (operands[0], operands[1]);
10128 (define_insn_and_split "thumb_eh_return"
10129 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10131 (clobber (match_scratch:SI 1 "=&l"))]
10134 "&& reload_completed"
10138 thumb_set_return_address (operands[0], operands[1]);
10146 (define_insn "load_tp_hard"
10147 [(set (match_operand:SI 0 "register_operand" "=r")
10148 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10150 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10151 [(set_attr "predicable" "yes")]
10154 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10155 (define_insn "load_tp_soft"
10156 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10157 (clobber (reg:SI LR_REGNUM))
10158 (clobber (reg:SI IP_REGNUM))
10159 (clobber (reg:CC CC_REGNUM))]
10161 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10162 [(set_attr "conds" "clob")]
10165 ;; Load the FPA co-processor patterns
10167 ;; Load the Maverick co-processor patterns
10168 (include "cirrus.md")
10169 ;; Load the Intel Wireless Multimedia Extension patterns
10170 (include "iwmmxt.md")
10171 ;; Load the VFP co-processor patterns