1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(R0_REGNUM 0) ; First CORE register
34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (CC_REGNUM 24) ; Condition code pseudo register
39 (LAST_ARM_REGNUM 15) ;
40 (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
41 (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
44 ;; 3rd operand to select_dominance_cc_mode
53 ;; Note: sin and cos are no-longer used.
56 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
60 ; operand 0 is the result,
61 ; operand 1 the parameter.
62 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63 ; operand 0 is the first register,
64 ; subsequent registers are in parallel (use ...)
66 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
67 ; usage, that is, we will add the pic_register
68 ; value to it before trying to dereference it.
69 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
70 ; GLOBAL_OFFSET_TABLE. The operation is fully
71 ; described by the RTL but must be wrapped to
72 ; prevent combine from trying to rip it apart.
73 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
74 ; being scheduled before the stack adjustment insn.
75 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76 ; this unspec is used to prevent the deletion of
77 ; instructions setting registers for EH handling
78 ; and stack frame generation. Operand 0 is the
80 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
94 (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
99 ;; UNSPEC_VOLATILE Usage:
102 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
104 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105 ; instruction epilogue sequence that isn't expanded
106 ; into normal RTL. Used for both normal and sibcall
108 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
109 ; for inlined constants.
110 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
112 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
114 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
116 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
118 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
120 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
121 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
122 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
123 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
124 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
126 (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
131 ;;---------------------------------------------------------------------------
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code. This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
146 ;; Operand number of an input operand that is shifted. Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
150 ; Floating Point Unit. If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns. (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154 (const (symbol_ref "arm_fpu_attr")))
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed. If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171 [(set_attr "conds" "clob")
172 (set_attr "length" "4")
173 (set_attr "pool_range" "250")])
175 ;; The instruction used to implement a particular pattern. This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
180 "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
181 (const_string "other"))
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
188 ; Classification of each insn
189 ; alu any alu instruction that doesn't hit memory or fp
190 ; regs or have a shifted source operand
191 ; alu_shift any data instruction that doesn't hit memory or fp
192 ; regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ; regs, but has a source operand shifted by a register value
195 ; mult a multiply instruction
196 ; block blockage insn, this blocks all functional units
197 ; float a floating point arithmetic operation (subject to expansion)
198 ; fdivd DFmode floating point division
199 ; fdivs SFmode floating point division
200 ; fmul Floating point multiply
201 ; ffmul Fast floating point multiply
202 ; farith Floating point arithmetic (4 cycle)
203 ; ffarith Fast floating point arithmetic (2 cycle)
204 ; float_em a floating point arithmetic operation that is normally emulated
205 ; even on a machine with an fpa.
206 ; f_load a floating point load from memory
207 ; f_store a floating point store to memory
208 ; f_load[sd] single/double load from memory
209 ; f_store[sd] single/double store to memory
210 ; f_flag a transfer of co-processor flags to the CPSR
211 ; f_mem_r a transfer of a floating point register to a real reg via mem
212 ; r_mem_f the reverse of f_mem_r
213 ; f_2_r fast transfer float to arm (no memory needed)
214 ; r_2_f fast transfer arm to float
215 ; f_cvt convert floating<->integral
217 ; call a subroutine call
218 ; load_byte load byte(s) from memory to arm registers
219 ; load1 load 1 word from memory to arm registers
220 ; load2 load 2 words from memory to arm registers
221 ; load3 load 3 words from memory to arm registers
222 ; load4 load 4 words from memory to arm registers
223 ; store store 1 word to memory from arm registers
224 ; store2 store 2 words
225 ; store3 store 3 words
226 ; store4 store 4 (or more) words
227 ; Additions for Cirrus Maverick co-processor:
228 ; mav_farith Floating point arithmetic (4 cycle)
229 ; mav_dmult Double multiplies (7 cycle)
232 "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
234 (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235 (const_string "mult")
236 (const_string "alu")))
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options()
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions. It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
246 ; USE means that the condition codes are used by the insn in the process of
247 ; outputting code, this means (at present) that we can't use the insn in
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ; well defined manner.
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ; they are altered at all
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ; instruction (UNEQ and LTGT). These cannot be predicated.
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ; output of this insn
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263 (if_then_else (eq_attr "type" "call")
264 (const_string "clob")
265 (const_string "nocond")))
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by
269 ; gen...). We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
273 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
274 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor. Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282 (if_then_else (eq_attr "type"
283 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
285 (const_string "no")))
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290 (if_then_else (eq_attr "type"
291 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292 (const_string "single")
293 (const_string "multi")))
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label. Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
300 ;;---------------------------------------------------------------------------
303 ; A list of modes that are exactly 64 bits in size. We use this to expand
304 ; some splits that are the same for all modes when operating on ARM
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
308 ;;---------------------------------------------------------------------------
311 (include "predicates.md")
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
316 ;; Processor type. This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
319 ;; True if the generic scheduling description should be used.
321 (define_attr "generic_sched" "yes,no"
323 (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
325 (const_string "yes"))))
327 (define_attr "generic_vfp" "yes,no"
329 (and (eq_attr "fpu" "vfp")
330 (eq_attr "tune" "!arm1020e,arm1022e"))
332 (const_string "no"))))
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
341 ;;---------------------------------------------------------------------------
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
352 (define_expand "adddi3"
354 [(set (match_operand:DI 0 "s_register_operand" "")
355 (plus:DI (match_operand:DI 1 "s_register_operand" "")
356 (match_operand:DI 2 "s_register_operand" "")))
357 (clobber (reg:CC CC_REGNUM))])]
360 if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
362 if (!cirrus_fp_register (operands[0], DImode))
363 operands[0] = force_reg (DImode, operands[0]);
364 if (!cirrus_fp_register (operands[1], DImode))
365 operands[1] = force_reg (DImode, operands[1]);
366 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
372 if (GET_CODE (operands[1]) != REG)
373 operands[1] = force_reg (SImode, operands[1]);
374 if (GET_CODE (operands[2]) != REG)
375 operands[2] = force_reg (SImode, operands[2]);
380 (define_insn "*thumb_adddi3"
381 [(set (match_operand:DI 0 "register_operand" "=l")
382 (plus:DI (match_operand:DI 1 "register_operand" "%0")
383 (match_operand:DI 2 "register_operand" "l")))
384 (clobber (reg:CC CC_REGNUM))
387 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388 [(set_attr "length" "4")]
391 (define_insn_and_split "*arm_adddi3"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394 (match_operand:DI 2 "s_register_operand" "r, 0")))
395 (clobber (reg:CC CC_REGNUM))]
396 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398 "TARGET_ARM && reload_completed"
399 [(parallel [(set (reg:CC_C CC_REGNUM)
400 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404 (plus:SI (match_dup 4) (match_dup 5))))]
407 operands[3] = gen_highpart (SImode, operands[0]);
408 operands[0] = gen_lowpart (SImode, operands[0]);
409 operands[4] = gen_highpart (SImode, operands[1]);
410 operands[1] = gen_lowpart (SImode, operands[1]);
411 operands[5] = gen_highpart (SImode, operands[2]);
412 operands[2] = gen_lowpart (SImode, operands[2]);
414 [(set_attr "conds" "clob")
415 (set_attr "length" "8")]
418 (define_insn_and_split "*adddi_sesidi_di"
419 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420 (plus:DI (sign_extend:DI
421 (match_operand:SI 2 "s_register_operand" "r,r"))
422 (match_operand:DI 1 "s_register_operand" "r,0")))
423 (clobber (reg:CC CC_REGNUM))]
424 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
426 "TARGET_ARM && reload_completed"
427 [(parallel [(set (reg:CC_C CC_REGNUM)
428 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
430 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432 (plus:SI (ashiftrt:SI (match_dup 2)
437 operands[3] = gen_highpart (SImode, operands[0]);
438 operands[0] = gen_lowpart (SImode, operands[0]);
439 operands[4] = gen_highpart (SImode, operands[1]);
440 operands[1] = gen_lowpart (SImode, operands[1]);
441 operands[2] = gen_lowpart (SImode, operands[2]);
443 [(set_attr "conds" "clob")
444 (set_attr "length" "8")]
447 (define_insn_and_split "*adddi_zesidi_di"
448 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449 (plus:DI (zero_extend:DI
450 (match_operand:SI 2 "s_register_operand" "r,r"))
451 (match_operand:DI 1 "s_register_operand" "r,0")))
452 (clobber (reg:CC CC_REGNUM))]
453 "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
455 "TARGET_ARM && reload_completed"
456 [(parallel [(set (reg:CC_C CC_REGNUM)
457 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461 (plus:SI (match_dup 4) (const_int 0))))]
464 operands[3] = gen_highpart (SImode, operands[0]);
465 operands[0] = gen_lowpart (SImode, operands[0]);
466 operands[4] = gen_highpart (SImode, operands[1]);
467 operands[1] = gen_lowpart (SImode, operands[1]);
468 operands[2] = gen_lowpart (SImode, operands[2]);
470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")]
474 (define_expand "addsi3"
475 [(set (match_operand:SI 0 "s_register_operand" "")
476 (plus:SI (match_operand:SI 1 "s_register_operand" "")
477 (match_operand:SI 2 "reg_or_int_operand" "")))]
480 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
482 arm_split_constant (PLUS, SImode, NULL_RTX,
483 INTVAL (operands[2]), operands[0], operands[1],
484 optimize && !no_new_pseudos);
490 ; If there is a scratch available, this will be faster than synthesizing the
493 [(match_scratch:SI 3 "r")
494 (set (match_operand:SI 0 "arm_general_register_operand" "")
495 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496 (match_operand:SI 2 "const_int_operand" "")))]
498 !(const_ok_for_arm (INTVAL (operands[2]))
499 || const_ok_for_arm (-INTVAL (operands[2])))
500 && const_ok_for_arm (~INTVAL (operands[2]))"
501 [(set (match_dup 3) (match_dup 2))
502 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
506 (define_insn_and_split "*arm_addsi3"
507 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
508 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
516 GET_CODE (operands[2]) == CONST_INT
517 && !(const_ok_for_arm (INTVAL (operands[2]))
518 || const_ok_for_arm (-INTVAL (operands[2])))"
519 [(clobber (const_int 0))]
521 arm_split_constant (PLUS, SImode, curr_insn,
522 INTVAL (operands[2]), operands[0],
526 [(set_attr "length" "4,4,16")
527 (set_attr "predicable" "yes")]
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register. Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
534 (define_insn "*thumb_addsi3"
535 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
536 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
540 static const char * const asms[] =
542 \"add\\t%0, %0, %2\",
543 \"sub\\t%0, %0, #%n2\",
544 \"add\\t%0, %1, %2\",
545 \"add\\t%0, %0, %2\",
546 \"add\\t%0, %0, %2\",
547 \"add\\t%0, %1, %2\",
550 if ((which_alternative == 2 || which_alternative == 6)
551 && GET_CODE (operands[2]) == CONST_INT
552 && INTVAL (operands[2]) < 0)
553 return \"sub\\t%0, %1, #%n2\";
554 return asms[which_alternative];
556 [(set_attr "length" "2")]
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
562 [(set (match_operand:SI 0 "arm_general_register_operand" "")
563 (match_operand:SI 1 "const_int_operand" ""))
565 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
567 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568 && (INTVAL (operands[1]) & 3) == 0"
569 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
573 (define_insn "*addsi3_compare0"
574 [(set (reg:CC_NOOV CC_REGNUM)
576 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577 (match_operand:SI 2 "arm_add_operand" "rI,L"))
579 (set (match_operand:SI 0 "s_register_operand" "=r,r")
580 (plus:SI (match_dup 1) (match_dup 2)))]
584 sub%?s\\t%0, %1, #%n2"
585 [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch"
589 [(set (reg:CC_NOOV CC_REGNUM)
591 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592 (match_operand:SI 1 "arm_add_operand" "rI,L"))
598 [(set_attr "conds" "set")]
601 (define_insn "*compare_negsi_si"
602 [(set (reg:CC_Z CC_REGNUM)
604 (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605 (match_operand:SI 1 "s_register_operand" "r")))]
608 [(set_attr "conds" "set")]
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614 [(set (reg:CC CC_REGNUM)
616 (match_operand:SI 1 "s_register_operand" "r,r")
617 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618 (set (match_operand:SI 0 "s_register_operand" "=r,r")
619 (plus:SI (match_dup 1)
620 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
624 add%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 ;; Convert the sequence
630 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
634 ;; bcs dest ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
638 [(set (match_operand:SI 0 "arm_general_register_operand" "")
639 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
641 (set (match_operand 2 "cc_register" "")
642 (compare (match_dup 0) (const_int -1)))
644 (if_then_else (match_operator 3 "equality_operator"
645 [(match_dup 2) (const_int 0)])
646 (match_operand 4 "" "")
647 (match_operand 5 "" "")))]
648 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
652 (match_dup 1) (const_int 1)))
653 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
655 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
658 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
662 operands[2], const0_rtx);"
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670 [(set (reg:CC_C CC_REGNUM)
672 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673 (match_operand:SI 2 "arm_add_operand" "rI,L"))
675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
676 (plus:SI (match_dup 1) (match_dup 2)))]
680 sub%?s\\t%0, %1, #%n2"
681 [(set_attr "conds" "set")]
684 (define_insn "*addsi3_compare_op2"
685 [(set (reg:CC_C CC_REGNUM)
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
691 (plus:SI (match_dup 1) (match_dup 2)))]
695 sub%?s\\t%0, %1, #%n2"
696 [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op0"
700 [(set (reg:CC_C CC_REGNUM)
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
709 [(set_attr "conds" "set")]
712 (define_insn "*compare_addsi2_op1"
713 [(set (reg:CC_C CC_REGNUM)
715 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
722 [(set_attr "conds" "set")]
725 (define_insn "*addsi3_carryin"
726 [(set (match_operand:SI 0 "s_register_operand" "=r")
727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
732 [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_shift"
736 [(set (match_operand:SI 0 "s_register_operand" "=r")
737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739 (match_operator:SI 2 "shift_operator"
740 [(match_operand:SI 3 "s_register_operand" "r")
741 (match_operand:SI 4 "reg_or_int_operand" "rM")])
742 (match_operand:SI 1 "s_register_operand" "r"))))]
744 "adc%?\\t%0, %1, %3%S2"
745 [(set_attr "conds" "use")
746 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747 (const_string "alu_shift")
748 (const_string "alu_shift_reg")))]
751 (define_insn "*addsi3_carryin_alt1"
752 [(set (match_operand:SI 0 "s_register_operand" "=r")
753 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754 (match_operand:SI 2 "arm_rhs_operand" "rI"))
755 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
758 [(set_attr "conds" "use")]
761 (define_insn "*addsi3_carryin_alt2"
762 [(set (match_operand:SI 0 "s_register_operand" "=r")
763 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764 (match_operand:SI 1 "s_register_operand" "r"))
765 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
768 [(set_attr "conds" "use")]
771 (define_insn "*addsi3_carryin_alt3"
772 [(set (match_operand:SI 0 "s_register_operand" "=r")
773 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774 (match_operand:SI 2 "arm_rhs_operand" "rI"))
775 (match_operand:SI 1 "s_register_operand" "r")))]
778 [(set_attr "conds" "use")]
781 (define_insn "incscc"
782 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785 (match_operand:SI 1 "s_register_operand" "0,?r")))]
789 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790 [(set_attr "conds" "use")
791 (set_attr "length" "4,8")]
794 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
796 [(set (match_operand:SI 0 "s_register_operand" "")
797 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798 (match_operand:SI 2 "s_register_operand" ""))
800 (clobber (match_operand:SI 3 "s_register_operand" ""))]
802 [(set (match_dup 3) (match_dup 1))
803 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
805 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
808 (define_expand "addsf3"
809 [(set (match_operand:SF 0 "s_register_operand" "")
810 (plus:SF (match_operand:SF 1 "s_register_operand" "")
811 (match_operand:SF 2 "arm_float_add_operand" "")))]
812 "TARGET_ARM && TARGET_HARD_FLOAT"
815 && !cirrus_fp_register (operands[2], SFmode))
816 operands[2] = force_reg (SFmode, operands[2]);
819 (define_expand "adddf3"
820 [(set (match_operand:DF 0 "s_register_operand" "")
821 (plus:DF (match_operand:DF 1 "s_register_operand" "")
822 (match_operand:DF 2 "arm_float_add_operand" "")))]
823 "TARGET_ARM && TARGET_HARD_FLOAT"
826 && !cirrus_fp_register (operands[2], DFmode))
827 operands[2] = force_reg (DFmode, operands[2]);
830 (define_expand "subdi3"
832 [(set (match_operand:DI 0 "s_register_operand" "")
833 (minus:DI (match_operand:DI 1 "s_register_operand" "")
834 (match_operand:DI 2 "s_register_operand" "")))
835 (clobber (reg:CC CC_REGNUM))])]
838 if (TARGET_HARD_FLOAT && TARGET_MAVERICK
840 && cirrus_fp_register (operands[0], DImode)
841 && cirrus_fp_register (operands[1], DImode))
843 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
849 if (GET_CODE (operands[1]) != REG)
850 operands[1] = force_reg (SImode, operands[1]);
851 if (GET_CODE (operands[2]) != REG)
852 operands[2] = force_reg (SImode, operands[2]);
857 (define_insn "*arm_subdi3"
858 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
859 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860 (match_operand:DI 2 "s_register_operand" "r,0,0")))
861 (clobber (reg:CC CC_REGNUM))]
863 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864 [(set_attr "conds" "clob")
865 (set_attr "length" "8")]
868 (define_insn "*thumb_subdi3"
869 [(set (match_operand:DI 0 "register_operand" "=l")
870 (minus:DI (match_operand:DI 1 "register_operand" "0")
871 (match_operand:DI 2 "register_operand" "l")))
872 (clobber (reg:CC CC_REGNUM))]
874 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875 [(set_attr "length" "4")]
878 (define_insn "*subdi_di_zesidi"
879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
882 (match_operand:SI 2 "s_register_operand" "r,r"))))
883 (clobber (reg:CC CC_REGNUM))]
885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
890 (define_insn "*subdi_di_sesidi"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
894 (match_operand:SI 2 "s_register_operand" "r,r"))))
895 (clobber (reg:CC CC_REGNUM))]
897 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
902 (define_insn "*subdi_zesidi_di"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (zero_extend:DI
905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
907 (clobber (reg:CC CC_REGNUM))]
909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
914 (define_insn "*subdi_sesidi_di"
915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
916 (minus:DI (sign_extend:DI
917 (match_operand:SI 2 "s_register_operand" "r,r"))
918 (match_operand:DI 1 "s_register_operand" "?r,0")))
919 (clobber (reg:CC CC_REGNUM))]
921 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
926 (define_insn "*subdi_zesidi_zesidi"
927 [(set (match_operand:DI 0 "s_register_operand" "=r")
928 (minus:DI (zero_extend:DI
929 (match_operand:SI 1 "s_register_operand" "r"))
931 (match_operand:SI 2 "s_register_operand" "r"))))
932 (clobber (reg:CC CC_REGNUM))]
934 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935 [(set_attr "conds" "clob")
936 (set_attr "length" "8")]
939 (define_expand "subsi3"
940 [(set (match_operand:SI 0 "s_register_operand" "")
941 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942 (match_operand:SI 2 "s_register_operand" "")))]
945 if (GET_CODE (operands[1]) == CONST_INT)
949 arm_split_constant (MINUS, SImode, NULL_RTX,
950 INTVAL (operands[1]), operands[0],
951 operands[2], optimize && !no_new_pseudos);
954 else /* TARGET_THUMB */
955 operands[1] = force_reg (SImode, operands[1]);
960 (define_insn "*thumb_subsi3_insn"
961 [(set (match_operand:SI 0 "register_operand" "=l")
962 (minus:SI (match_operand:SI 1 "register_operand" "l")
963 (match_operand:SI 2 "register_operand" "l")))]
966 [(set_attr "length" "2")]
969 (define_insn_and_split "*arm_subsi3_insn"
970 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
971 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972 (match_operand:SI 2 "s_register_operand" "r,r")))]
978 && GET_CODE (operands[1]) == CONST_INT
979 && !const_ok_for_arm (INTVAL (operands[1]))"
980 [(clobber (const_int 0))]
982 arm_split_constant (MINUS, SImode, curr_insn,
983 INTVAL (operands[1]), operands[0], operands[2], 0);
986 [(set_attr "length" "4,16")
987 (set_attr "predicable" "yes")]
991 [(match_scratch:SI 3 "r")
992 (set (match_operand:SI 0 "arm_general_register_operand" "")
993 (minus:SI (match_operand:SI 1 "const_int_operand" "")
994 (match_operand:SI 2 "arm_general_register_operand" "")))]
996 && !const_ok_for_arm (INTVAL (operands[1]))
997 && const_ok_for_arm (~INTVAL (operands[1]))"
998 [(set (match_dup 3) (match_dup 1))
999 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1003 (define_insn "*subsi3_compare0"
1004 [(set (reg:CC_NOOV CC_REGNUM)
1006 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1009 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010 (minus:SI (match_dup 1) (match_dup 2)))]
1014 rsb%?s\\t%0, %2, %1"
1015 [(set_attr "conds" "set")]
1018 (define_insn "decscc"
1019 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1020 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1021 (match_operator:SI 2 "arm_comparison_operator"
1022 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1026 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027 [(set_attr "conds" "use")
1028 (set_attr "length" "*,8")]
1031 (define_expand "subsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "")
1033 (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035 "TARGET_ARM && TARGET_HARD_FLOAT"
1037 if (TARGET_MAVERICK)
1039 if (!cirrus_fp_register (operands[1], SFmode))
1040 operands[1] = force_reg (SFmode, operands[1]);
1041 if (!cirrus_fp_register (operands[2], SFmode))
1042 operands[2] = force_reg (SFmode, operands[2]);
1046 (define_expand "subdf3"
1047 [(set (match_operand:DF 0 "s_register_operand" "")
1048 (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050 "TARGET_ARM && TARGET_HARD_FLOAT"
1052 if (TARGET_MAVERICK)
1054 if (!cirrus_fp_register (operands[1], DFmode))
1055 operands[1] = force_reg (DFmode, operands[1]);
1056 if (!cirrus_fp_register (operands[2], DFmode))
1057 operands[2] = force_reg (DFmode, operands[2]);
1062 ;; Multiplication insns
1064 (define_expand "mulsi3"
1065 [(set (match_operand:SI 0 "s_register_operand" "")
1066 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067 (match_operand:SI 1 "s_register_operand" "")))]
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1075 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1078 "mul%?\\t%0, %2, %1"
1079 [(set_attr "insn" "mul")
1080 (set_attr "predicable" "yes")]
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1084 ; 1 and 2; are the same, because reload will make operand 0 match
1085 ; operand 1 without realizing that this conflicts with operand 2. We fix
1086 ; this by adding another alternative to match this case, and then `reload'
1087 ; it ourselves. This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1090 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091 (match_operand:SI 2 "register_operand" "l,l,l")))]
1094 if (which_alternative < 2)
1095 return \"mov\\t%0, %1\;mul\\t%0, %2\";
1097 return \"mul\\t%0, %2\";
1099 [(set_attr "length" "4,4,2")
1100 (set_attr "insn" "mul")]
1103 (define_insn "*mulsi3_compare0"
1104 [(set (reg:CC_NOOV CC_REGNUM)
1105 (compare:CC_NOOV (mult:SI
1106 (match_operand:SI 2 "s_register_operand" "r,r")
1107 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1109 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110 (mult:SI (match_dup 2) (match_dup 1)))]
1112 "mul%?s\\t%0, %2, %1"
1113 [(set_attr "conds" "set")
1114 (set_attr "insn" "muls")]
1117 (define_insn "*mulsi_compare0_scratch"
1118 [(set (reg:CC_NOOV CC_REGNUM)
1119 (compare:CC_NOOV (mult:SI
1120 (match_operand:SI 2 "s_register_operand" "r,r")
1121 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1123 (clobber (match_scratch:SI 0 "=&r,&r"))]
1125 "mul%?s\\t%0, %2, %1"
1126 [(set_attr "conds" "set")
1127 (set_attr "insn" "muls")]
1130 ;; Unnamed templates to match MLA instruction.
1132 (define_insn "*mulsi3addsi"
1133 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1135 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1139 "mla%?\\t%0, %2, %1, %3"
1140 [(set_attr "insn" "mla")
1141 (set_attr "predicable" "yes")]
1144 (define_insn "*mulsi3addsi_compare0"
1145 [(set (reg:CC_NOOV CC_REGNUM)
1148 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1156 "mla%?s\\t%0, %2, %1, %3"
1157 [(set_attr "conds" "set")
1158 (set_attr "insn" "mlas")]
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162 [(set (reg:CC_NOOV CC_REGNUM)
1165 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1169 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1171 "mla%?s\\t%0, %2, %1, %3"
1172 [(set_attr "conds" "set")
1173 (set_attr "insn" "mlas")]
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1178 (define_insn "*mulsidi3adddi"
1179 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184 (match_operand:DI 1 "s_register_operand" "0")))]
1185 "TARGET_ARM && arm_arch3m"
1186 "smlal%?\\t%Q0, %R0, %3, %2"
1187 [(set_attr "insn" "smlal")
1188 (set_attr "predicable" "yes")]
1191 (define_insn "mulsidi3"
1192 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196 "TARGET_ARM && arm_arch3m"
1197 "smull%?\\t%Q0, %R0, %1, %2"
1198 [(set_attr "insn" "smull")
1199 (set_attr "predicable" "yes")]
1202 (define_insn "umulsidi3"
1203 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1205 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207 "TARGET_ARM && arm_arch3m"
1208 "umull%?\\t%Q0, %R0, %1, %2"
1209 [(set_attr "insn" "umull")
1210 (set_attr "predicable" "yes")]
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1215 (define_insn "*umulsidi3adddi"
1216 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1219 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221 (match_operand:DI 1 "s_register_operand" "0")))]
1222 "TARGET_ARM && arm_arch3m"
1223 "umlal%?\\t%Q0, %R0, %3, %2"
1224 [(set_attr "insn" "umlal")
1225 (set_attr "predicable" "yes")]
1228 (define_insn "smulsi3_highpart"
1229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1233 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1236 (clobber (match_scratch:SI 3 "=&r,&r"))]
1237 "TARGET_ARM && arm_arch3m"
1238 "smull%?\\t%3, %0, %2, %1"
1239 [(set_attr "insn" "smull")
1240 (set_attr "predicable" "yes")]
1243 (define_insn "umulsi3_highpart"
1244 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1251 (clobber (match_scratch:SI 3 "=&r,&r"))]
1252 "TARGET_ARM && arm_arch3m"
1253 "umull%?\\t%3, %0, %2, %1"
1254 [(set_attr "insn" "umull")
1255 (set_attr "predicable" "yes")]
1258 (define_insn "mulhisi3"
1259 [(set (match_operand:SI 0 "s_register_operand" "=r")
1260 (mult:SI (sign_extend:SI
1261 (match_operand:HI 1 "s_register_operand" "%r"))
1263 (match_operand:HI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_arch5e"
1265 "smulbb%?\\t%0, %1, %2"
1266 [(set_attr "insn" "smulxy")
1267 (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3tb"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (mult:SI (ashiftrt:SI
1273 (match_operand:SI 1 "s_register_operand" "r")
1276 (match_operand:HI 2 "s_register_operand" "r"))))]
1277 "TARGET_ARM && arm_arch5e"
1278 "smultb%?\\t%0, %1, %2"
1279 [(set_attr "insn" "smulxy")
1280 (set_attr "predicable" "yes")]
1283 (define_insn "*mulhisi3bt"
1284 [(set (match_operand:SI 0 "s_register_operand" "=r")
1285 (mult:SI (sign_extend:SI
1286 (match_operand:HI 1 "s_register_operand" "r"))
1288 (match_operand:SI 2 "s_register_operand" "r")
1290 "TARGET_ARM && arm_arch5e"
1291 "smulbt%?\\t%0, %1, %2"
1292 [(set_attr "insn" "smulxy")
1293 (set_attr "predicable" "yes")]
1296 (define_insn "*mulhisi3tt"
1297 [(set (match_operand:SI 0 "s_register_operand" "=r")
1298 (mult:SI (ashiftrt:SI
1299 (match_operand:SI 1 "s_register_operand" "r")
1302 (match_operand:SI 2 "s_register_operand" "r")
1304 "TARGET_ARM && arm_arch5e"
1305 "smultt%?\\t%0, %1, %2"
1306 [(set_attr "insn" "smulxy")
1307 (set_attr "predicable" "yes")]
1310 (define_insn "*mulhisi3addsi"
1311 [(set (match_operand:SI 0 "s_register_operand" "=r")
1312 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313 (mult:SI (sign_extend:SI
1314 (match_operand:HI 2 "s_register_operand" "%r"))
1316 (match_operand:HI 3 "s_register_operand" "r")))))]
1317 "TARGET_ARM && arm_arch5e"
1318 "smlabb%?\\t%0, %2, %3, %1"
1319 [(set_attr "insn" "smlaxy")
1320 (set_attr "predicable" "yes")]
1323 (define_insn "*mulhidi3adddi"
1324 [(set (match_operand:DI 0 "s_register_operand" "=r")
1326 (match_operand:DI 1 "s_register_operand" "0")
1327 (mult:DI (sign_extend:DI
1328 (match_operand:HI 2 "s_register_operand" "%r"))
1330 (match_operand:HI 3 "s_register_operand" "r")))))]
1331 "TARGET_ARM && arm_arch5e"
1332 "smlalbb%?\\t%Q0, %R0, %2, %3"
1333 [(set_attr "insn" "smlalxy")
1334 (set_attr "predicable" "yes")])
1336 (define_expand "mulsf3"
1337 [(set (match_operand:SF 0 "s_register_operand" "")
1338 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340 "TARGET_ARM && TARGET_HARD_FLOAT"
1343 && !cirrus_fp_register (operands[2], SFmode))
1344 operands[2] = force_reg (SFmode, operands[2]);
1347 (define_expand "muldf3"
1348 [(set (match_operand:DF 0 "s_register_operand" "")
1349 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351 "TARGET_ARM && TARGET_HARD_FLOAT"
1354 && !cirrus_fp_register (operands[2], DFmode))
1355 operands[2] = force_reg (DFmode, operands[2]);
1360 (define_expand "divsf3"
1361 [(set (match_operand:SF 0 "s_register_operand" "")
1362 (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1367 (define_expand "divdf3"
1368 [(set (match_operand:DF 0 "s_register_operand" "")
1369 (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1376 (define_expand "modsf3"
1377 [(set (match_operand:SF 0 "s_register_operand" "")
1378 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1383 (define_expand "moddf3"
1384 [(set (match_operand:DF 0 "s_register_operand" "")
1385 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1390 ;; Boolean and,ior,xor insns
1392 ;; Split up double word logical operations
1394 ;; Split up simple DImode logical operations. Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1397 [(set (match_operand:DI 0 "s_register_operand" "")
1398 (match_operator:DI 6 "logical_binary_operator"
1399 [(match_operand:DI 1 "s_register_operand" "")
1400 (match_operand:DI 2 "s_register_operand" "")]))]
1401 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1406 operands[3] = gen_highpart (SImode, operands[0]);
1407 operands[0] = gen_lowpart (SImode, operands[0]);
1408 operands[4] = gen_highpart (SImode, operands[1]);
1409 operands[1] = gen_lowpart (SImode, operands[1]);
1410 operands[5] = gen_highpart (SImode, operands[2]);
1411 operands[2] = gen_lowpart (SImode, operands[2]);
1416 [(set (match_operand:DI 0 "s_register_operand" "")
1417 (match_operator:DI 6 "logical_binary_operator"
1418 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419 (match_operand:DI 1 "s_register_operand" "")]))]
1420 "TARGET_ARM && reload_completed"
1421 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422 (set (match_dup 3) (match_op_dup:SI 6
1423 [(ashiftrt:SI (match_dup 2) (const_int 31))
1427 operands[3] = gen_highpart (SImode, operands[0]);
1428 operands[0] = gen_lowpart (SImode, operands[0]);
1429 operands[4] = gen_highpart (SImode, operands[1]);
1430 operands[1] = gen_lowpart (SImode, operands[1]);
1431 operands[5] = gen_highpart (SImode, operands[2]);
1432 operands[2] = gen_lowpart (SImode, operands[2]);
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1439 [(set (match_operand:DI 0 "s_register_operand" "")
1441 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442 (match_operand:DI 1 "s_register_operand" "")))]
1443 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445 (set (match_dup 3) (match_dup 4))]
1448 operands[4] = gen_highpart (SImode, operands[1]);
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[1] = gen_lowpart (SImode, operands[1]);
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1458 [(set (match_operand:DI 0 "s_register_operand" "")
1460 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461 (match_operand:DI 1 "s_register_operand" "")))]
1462 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464 (set (match_dup 3) (match_dup 4))]
1467 operands[4] = gen_highpart (SImode, operands[1]);
1468 operands[3] = gen_highpart (SImode, operands[0]);
1469 operands[0] = gen_lowpart (SImode, operands[0]);
1470 operands[1] = gen_lowpart (SImode, operands[1]);
1474 (define_insn "anddi3"
1475 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1476 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1477 (match_operand:DI 2 "s_register_operand" "r,r")))]
1478 "TARGET_ARM && ! TARGET_IWMMXT"
1480 [(set_attr "length" "8")]
1483 (define_insn_and_split "*anddi_zesidi_di"
1484 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485 (and:DI (zero_extend:DI
1486 (match_operand:SI 2 "s_register_operand" "r,r"))
1487 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1490 "TARGET_ARM && reload_completed"
1491 ; The zero extend of operand 2 clears the high word of the output
1493 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494 (set (match_dup 3) (const_int 0))]
1497 operands[3] = gen_highpart (SImode, operands[0]);
1498 operands[0] = gen_lowpart (SImode, operands[0]);
1499 operands[1] = gen_lowpart (SImode, operands[1]);
1501 [(set_attr "length" "8")]
1504 (define_insn "*anddi_sesdi_di"
1505 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1506 (and:DI (sign_extend:DI
1507 (match_operand:SI 2 "s_register_operand" "r,r"))
1508 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1511 [(set_attr "length" "8")]
1514 (define_expand "andsi3"
1515 [(set (match_operand:SI 0 "s_register_operand" "")
1516 (and:SI (match_operand:SI 1 "s_register_operand" "")
1517 (match_operand:SI 2 "reg_or_int_operand" "")))]
1522 if (GET_CODE (operands[2]) == CONST_INT)
1524 arm_split_constant (AND, SImode, NULL_RTX,
1525 INTVAL (operands[2]), operands[0],
1526 operands[1], optimize && !no_new_pseudos);
1531 else /* TARGET_THUMB */
1533 if (GET_CODE (operands[2]) != CONST_INT)
1534 operands[2] = force_reg (SImode, operands[2]);
1539 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1541 operands[2] = force_reg (SImode,
1542 GEN_INT (~INTVAL (operands[2])));
1544 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1549 for (i = 9; i <= 31; i++)
1551 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1553 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1557 else if ((((HOST_WIDE_INT) 1) << i) - 1
1558 == ~INTVAL (operands[2]))
1560 rtx shift = GEN_INT (i);
1561 rtx reg = gen_reg_rtx (SImode);
1563 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1570 operands[2] = force_reg (SImode, operands[2]);
1576 (define_insn_and_split "*arm_andsi3_insn"
1577 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1578 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1583 bic%?\\t%0, %1, #%B2
1586 && GET_CODE (operands[2]) == CONST_INT
1587 && !(const_ok_for_arm (INTVAL (operands[2]))
1588 || const_ok_for_arm (~INTVAL (operands[2])))"
1589 [(clobber (const_int 0))]
1591 arm_split_constant (AND, SImode, curr_insn,
1592 INTVAL (operands[2]), operands[0], operands[1], 0);
1595 [(set_attr "length" "4,4,16")
1596 (set_attr "predicable" "yes")]
1599 (define_insn "*thumb_andsi3_insn"
1600 [(set (match_operand:SI 0 "register_operand" "=l")
1601 (and:SI (match_operand:SI 1 "register_operand" "%0")
1602 (match_operand:SI 2 "register_operand" "l")))]
1605 [(set_attr "length" "2")]
1608 (define_insn "*andsi3_compare0"
1609 [(set (reg:CC_NOOV CC_REGNUM)
1611 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1614 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1615 (and:SI (match_dup 1) (match_dup 2)))]
1619 bic%?s\\t%0, %1, #%B2"
1620 [(set_attr "conds" "set")]
1623 (define_insn "*andsi3_compare0_scratch"
1624 [(set (reg:CC_NOOV CC_REGNUM)
1626 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1629 (clobber (match_scratch:SI 2 "=X,r"))]
1633 bic%?s\\t%2, %0, #%B1"
1634 [(set_attr "conds" "set")]
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638 [(set (reg:CC_NOOV CC_REGNUM)
1639 (compare:CC_NOOV (zero_extract:SI
1640 (match_operand:SI 0 "s_register_operand" "r")
1641 (match_operand 1 "const_int_operand" "n")
1642 (match_operand 2 "const_int_operand" "n"))
1645 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646 && INTVAL (operands[1]) > 0
1647 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1650 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651 << INTVAL (operands[2]));
1652 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1655 [(set_attr "conds" "set")]
1658 (define_insn_and_split "*ne_zeroextractsi"
1659 [(set (match_operand:SI 0 "s_register_operand" "=r")
1660 (ne:SI (zero_extract:SI
1661 (match_operand:SI 1 "s_register_operand" "r")
1662 (match_operand:SI 2 "const_int_operand" "n")
1663 (match_operand:SI 3 "const_int_operand" "n"))
1665 (clobber (reg:CC CC_REGNUM))]
1667 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668 && INTVAL (operands[2]) > 0
1669 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1673 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674 && INTVAL (operands[2]) > 0
1675 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1680 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1682 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683 (match_dup 0) (const_int 1)))]
1685 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686 << INTVAL (operands[3]));
1688 [(set_attr "conds" "clob")
1689 (set_attr "length" "8")]
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693 [(set (match_operand:SI 0 "s_register_operand" "=r")
1694 (ne:SI (zero_extract:SI
1695 (match_operand:SI 1 "s_register_operand" "r")
1696 (match_operand:SI 2 "const_int_operand" "n")
1699 (clobber (reg:CC CC_REGNUM))]
1703 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1706 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1708 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709 (match_dup 0) (const_int 1)))]
1711 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1713 [(set_attr "conds" "clob")
1714 (set_attr "length" "8")]
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (if_then_else:SI (ne (zero_extract:SI
1720 (match_operand:SI 1 "s_register_operand" "r")
1721 (match_operand:SI 2 "const_int_operand" "n")
1722 (match_operand:SI 3 "const_int_operand" "n"))
1724 (match_operand:SI 4 "arm_not_operand" "rIK")
1726 (clobber (reg:CC CC_REGNUM))]
1728 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729 && INTVAL (operands[2]) > 0
1730 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1735 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736 && INTVAL (operands[2]) > 0
1737 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739 && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1743 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1745 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746 (match_dup 0) (match_dup 4)))]
1748 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749 << INTVAL (operands[3]));
1751 [(set_attr "conds" "clob")
1752 (set_attr "length" "8")]
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756 [(set (match_operand:SI 0 "s_register_operand" "=r")
1757 (if_then_else:SI (ne (zero_extract:SI
1758 (match_operand:SI 1 "s_register_operand" "r")
1759 (match_operand:SI 2 "const_int_operand" "n")
1762 (match_operand:SI 3 "arm_not_operand" "rIK")
1764 (clobber (reg:CC CC_REGNUM))]
1765 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1767 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1771 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1773 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774 (match_dup 0) (match_dup 3)))]
1776 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1778 [(set_attr "conds" "clob")
1779 (set_attr "length" "8")]
1783 [(set (match_operand:SI 0 "s_register_operand" "")
1784 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785 (match_operand:SI 2 "const_int_operand" "")
1786 (match_operand:SI 3 "const_int_operand" "")))
1787 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1789 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1792 HOST_WIDE_INT temp = INTVAL (operands[2]);
1794 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795 operands[3] = GEN_INT (32 - temp);
1800 [(set (match_operand:SI 0 "s_register_operand" "")
1801 (match_operator:SI 1 "shiftable_operator"
1802 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803 (match_operand:SI 3 "const_int_operand" "")
1804 (match_operand:SI 4 "const_int_operand" ""))
1805 (match_operand:SI 5 "s_register_operand" "")]))
1806 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1808 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1811 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1814 HOST_WIDE_INT temp = INTVAL (operands[3]);
1816 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817 operands[4] = GEN_INT (32 - temp);
1822 [(set (match_operand:SI 0 "s_register_operand" "")
1823 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824 (match_operand:SI 2 "const_int_operand" "")
1825 (match_operand:SI 3 "const_int_operand" "")))]
1827 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1830 HOST_WIDE_INT temp = INTVAL (operands[2]);
1832 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833 operands[3] = GEN_INT (32 - temp);
1838 [(set (match_operand:SI 0 "s_register_operand" "")
1839 (match_operator:SI 1 "shiftable_operator"
1840 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841 (match_operand:SI 3 "const_int_operand" "")
1842 (match_operand:SI 4 "const_int_operand" ""))
1843 (match_operand:SI 5 "s_register_operand" "")]))
1844 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1846 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1849 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1852 HOST_WIDE_INT temp = INTVAL (operands[3]);
1854 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855 operands[4] = GEN_INT (32 - temp);
1859 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself. Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert. This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1868 (define_expand "insv"
1869 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870 (match_operand:SI 1 "general_operand" "")
1871 (match_operand:SI 2 "general_operand" ""))
1872 (match_operand:SI 3 "reg_or_int_operand" ""))]
1876 int start_bit = INTVAL (operands[2]);
1877 int width = INTVAL (operands[1]);
1878 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879 rtx target, subtarget;
1881 target = operands[0];
1882 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1883 subreg as the final target. */
1884 if (GET_CODE (target) == SUBREG)
1886 subtarget = gen_reg_rtx (SImode);
1887 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888 < GET_MODE_SIZE (SImode))
1889 target = SUBREG_REG (target);
1894 if (GET_CODE (operands[3]) == CONST_INT)
1896 /* Since we are inserting a known constant, we may be able to
1897 reduce the number of bits that we have to clear so that
1898 the mask becomes simple. */
1899 /* ??? This code does not check to see if the new mask is actually
1900 simpler. It may not be. */
1901 rtx op1 = gen_reg_rtx (SImode);
1902 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1903 start of this pattern. */
1904 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1907 emit_insn (gen_andsi3 (op1, operands[0],
1908 gen_int_mode (~mask2, SImode)));
1909 emit_insn (gen_iorsi3 (subtarget, op1,
1910 gen_int_mode (op3_value << start_bit, SImode)));
1912 else if (start_bit == 0
1913 && !(const_ok_for_arm (mask)
1914 || const_ok_for_arm (~mask)))
1916 /* A Trick, since we are setting the bottom bits in the word,
1917 we can shift operand[3] up, operand[0] down, OR them together
1918 and rotate the result back again. This takes 3 insns, and
1919 the third might be mergeable into another op. */
1920 /* The shift up copes with the possibility that operand[3] is
1921 wider than the bitfield. */
1922 rtx op0 = gen_reg_rtx (SImode);
1923 rtx op1 = gen_reg_rtx (SImode);
1925 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927 emit_insn (gen_iorsi3 (op1, op1, op0));
1928 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1930 else if ((width + start_bit == 32)
1931 && !(const_ok_for_arm (mask)
1932 || const_ok_for_arm (~mask)))
1934 /* Similar trick, but slightly less efficient. */
1936 rtx op0 = gen_reg_rtx (SImode);
1937 rtx op1 = gen_reg_rtx (SImode);
1939 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1946 rtx op0 = gen_int_mode (mask, SImode);
1947 rtx op1 = gen_reg_rtx (SImode);
1948 rtx op2 = gen_reg_rtx (SImode);
1950 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1952 rtx tmp = gen_reg_rtx (SImode);
1954 emit_insn (gen_movsi (tmp, op0));
1958 /* Mask out any bits in operand[3] that are not needed. */
1959 emit_insn (gen_andsi3 (op1, operands[3], op0));
1961 if (GET_CODE (op0) == CONST_INT
1962 && (const_ok_for_arm (mask << start_bit)
1963 || const_ok_for_arm (~(mask << start_bit))))
1965 op0 = gen_int_mode (~(mask << start_bit), SImode);
1966 emit_insn (gen_andsi3 (op2, operands[0], op0));
1970 if (GET_CODE (op0) == CONST_INT)
1972 rtx tmp = gen_reg_rtx (SImode);
1974 emit_insn (gen_movsi (tmp, op0));
1979 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1981 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1985 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1987 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1990 if (subtarget != target)
1992 /* If TARGET is still a SUBREG, then it must be wider than a word,
1993 so we must be careful only to set the subword we were asked to. */
1994 if (GET_CODE (target) == SUBREG)
1995 emit_move_insn (target, subtarget);
1997 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008 (match_operand:DI 2 "s_register_operand" "0,r")))]
2011 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2016 operands[3] = gen_highpart (SImode, operands[0]);
2017 operands[0] = gen_lowpart (SImode, operands[0]);
2018 operands[4] = gen_highpart (SImode, operands[1]);
2019 operands[1] = gen_lowpart (SImode, operands[1]);
2020 operands[5] = gen_highpart (SImode, operands[2]);
2021 operands[2] = gen_lowpart (SImode, operands[2]);
2023 [(set_attr "length" "8")
2024 (set_attr "predicable" "yes")]
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029 (and:DI (not:DI (zero_extend:DI
2030 (match_operand:SI 2 "s_register_operand" "r,r")))
2031 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2034 bic%?\\t%Q0, %Q1, %2
2036 ; (not (zero_extend ...)) allows us to just copy the high word from
2037 ; operand1 to operand0.
2040 && operands[0] != operands[1]"
2041 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042 (set (match_dup 3) (match_dup 4))]
2045 operands[3] = gen_highpart (SImode, operands[0]);
2046 operands[0] = gen_lowpart (SImode, operands[0]);
2047 operands[4] = gen_highpart (SImode, operands[1]);
2048 operands[1] = gen_lowpart (SImode, operands[1]);
2050 [(set_attr "length" "4,8")
2051 (set_attr "predicable" "yes")]
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056 (and:DI (not:DI (sign_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r")))
2058 (match_operand:DI 1 "s_register_operand" "0,r")))]
2061 "TARGET_ARM && reload_completed"
2062 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063 (set (match_dup 3) (and:SI (not:SI
2064 (ashiftrt:SI (match_dup 2) (const_int 31)))
2068 operands[3] = gen_highpart (SImode, operands[0]);
2069 operands[0] = gen_lowpart (SImode, operands[0]);
2070 operands[4] = gen_highpart (SImode, operands[1]);
2071 operands[1] = gen_lowpart (SImode, operands[1]);
2073 [(set_attr "length" "8")
2074 (set_attr "predicable" "yes")]
2077 (define_insn "andsi_notsi_si"
2078 [(set (match_operand:SI 0 "s_register_operand" "=r")
2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080 (match_operand:SI 1 "s_register_operand" "r")))]
2082 "bic%?\\t%0, %1, %2"
2083 [(set_attr "predicable" "yes")]
2086 (define_insn "bicsi3"
2087 [(set (match_operand:SI 0 "register_operand" "=l")
2088 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089 (match_operand:SI 2 "register_operand" "0")))]
2092 [(set_attr "length" "2")]
2095 (define_insn "andsi_not_shiftsi_si"
2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098 [(match_operand:SI 2 "s_register_operand" "r")
2099 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100 (match_operand:SI 1 "s_register_operand" "r")))]
2102 "bic%?\\t%0, %1, %2%S4"
2103 [(set_attr "predicable" "yes")
2104 (set_attr "shift" "2")
2105 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106 (const_string "alu_shift")
2107 (const_string "alu_shift_reg")))]
2110 (define_insn "*andsi_notsi_si_compare0"
2111 [(set (reg:CC_NOOV CC_REGNUM)
2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114 (match_operand:SI 1 "s_register_operand" "r"))
2116 (set (match_operand:SI 0 "s_register_operand" "=r")
2117 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2119 "bic%?s\\t%0, %1, %2"
2120 [(set_attr "conds" "set")]
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124 [(set (reg:CC_NOOV CC_REGNUM)
2126 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127 (match_operand:SI 1 "s_register_operand" "r"))
2129 (clobber (match_scratch:SI 0 "=r"))]
2131 "bic%?s\\t%0, %1, %2"
2132 [(set_attr "conds" "set")]
2135 (define_insn "iordi3"
2136 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2137 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2138 (match_operand:DI 2 "s_register_operand" "r,r")))]
2139 "TARGET_ARM && ! TARGET_IWMMXT"
2141 [(set_attr "length" "8")
2142 (set_attr "predicable" "yes")]
2145 (define_insn "*iordi_zesidi_di"
2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147 (ior:DI (zero_extend:DI
2148 (match_operand:SI 2 "s_register_operand" "r,r"))
2149 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2152 orr%?\\t%Q0, %Q1, %2
2154 [(set_attr "length" "4,8")
2155 (set_attr "predicable" "yes")]
2158 (define_insn "*iordi_sesidi_di"
2159 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160 (ior:DI (sign_extend:DI
2161 (match_operand:SI 2 "s_register_operand" "r,r"))
2162 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2165 [(set_attr "length" "8")
2166 (set_attr "predicable" "yes")]
2169 (define_expand "iorsi3"
2170 [(set (match_operand:SI 0 "s_register_operand" "")
2171 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172 (match_operand:SI 2 "reg_or_int_operand" "")))]
2175 if (GET_CODE (operands[2]) == CONST_INT)
2179 arm_split_constant (IOR, SImode, NULL_RTX,
2180 INTVAL (operands[2]), operands[0], operands[1],
2181 optimize && !no_new_pseudos);
2184 else /* TARGET_THUMB */
2185 operands [2] = force_reg (SImode, operands [2]);
2190 (define_insn_and_split "*arm_iorsi3"
2191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2192 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2199 && GET_CODE (operands[2]) == CONST_INT
2200 && !const_ok_for_arm (INTVAL (operands[2]))"
2201 [(clobber (const_int 0))]
2203 arm_split_constant (IOR, SImode, curr_insn,
2204 INTVAL (operands[2]), operands[0], operands[1], 0);
2207 [(set_attr "length" "4,16")
2208 (set_attr "predicable" "yes")]
2211 (define_insn "*thumb_iorsi3"
2212 [(set (match_operand:SI 0 "register_operand" "=l")
2213 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214 (match_operand:SI 2 "register_operand" "l")))]
2217 [(set_attr "length" "2")]
2221 [(match_scratch:SI 3 "r")
2222 (set (match_operand:SI 0 "arm_general_register_operand" "")
2223 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224 (match_operand:SI 2 "const_int_operand" "")))]
2226 && !const_ok_for_arm (INTVAL (operands[2]))
2227 && const_ok_for_arm (~INTVAL (operands[2]))"
2228 [(set (match_dup 3) (match_dup 2))
2229 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2233 (define_insn "*iorsi3_compare0"
2234 [(set (reg:CC_NOOV CC_REGNUM)
2235 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238 (set (match_operand:SI 0 "s_register_operand" "=r")
2239 (ior:SI (match_dup 1) (match_dup 2)))]
2241 "orr%?s\\t%0, %1, %2"
2242 [(set_attr "conds" "set")]
2245 (define_insn "*iorsi3_compare0_scratch"
2246 [(set (reg:CC_NOOV CC_REGNUM)
2247 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2250 (clobber (match_scratch:SI 0 "=r"))]
2252 "orr%?s\\t%0, %1, %2"
2253 [(set_attr "conds" "set")]
2256 (define_insn "xordi3"
2257 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2258 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2259 (match_operand:DI 2 "s_register_operand" "r,r")))]
2260 "TARGET_ARM && !TARGET_IWMMXT"
2262 [(set_attr "length" "8")
2263 (set_attr "predicable" "yes")]
2266 (define_insn "*xordi_zesidi_di"
2267 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268 (xor:DI (zero_extend:DI
2269 (match_operand:SI 2 "s_register_operand" "r,r"))
2270 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2273 eor%?\\t%Q0, %Q1, %2
2275 [(set_attr "length" "4,8")
2276 (set_attr "predicable" "yes")]
2279 (define_insn "*xordi_sesidi_di"
2280 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281 (xor:DI (sign_extend:DI
2282 (match_operand:SI 2 "s_register_operand" "r,r"))
2283 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2286 [(set_attr "length" "8")
2287 (set_attr "predicable" "yes")]
2290 (define_expand "xorsi3"
2291 [(set (match_operand:SI 0 "s_register_operand" "")
2292 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293 (match_operand:SI 2 "arm_rhs_operand" "")))]
2296 if (GET_CODE (operands[2]) == CONST_INT)
2297 operands[2] = force_reg (SImode, operands[2]);
2301 (define_insn "*arm_xorsi3"
2302 [(set (match_operand:SI 0 "s_register_operand" "=r")
2303 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2306 "eor%?\\t%0, %1, %2"
2307 [(set_attr "predicable" "yes")]
2310 (define_insn "*thumb_xorsi3"
2311 [(set (match_operand:SI 0 "register_operand" "=l")
2312 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313 (match_operand:SI 2 "register_operand" "l")))]
2316 [(set_attr "length" "2")]
2319 (define_insn "*xorsi3_compare0"
2320 [(set (reg:CC_NOOV CC_REGNUM)
2321 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2324 (set (match_operand:SI 0 "s_register_operand" "=r")
2325 (xor:SI (match_dup 1) (match_dup 2)))]
2327 "eor%?s\\t%0, %1, %2"
2328 [(set_attr "conds" "set")]
2331 (define_insn "*xorsi3_compare0_scratch"
2332 [(set (reg:CC_NOOV CC_REGNUM)
2333 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2338 [(set_attr "conds" "set")]
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2346 [(set (match_operand:SI 0 "s_register_operand" "")
2347 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349 (match_operand:SI 3 "arm_rhs_operand" "")))
2350 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2352 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353 (not:SI (match_dup 3))))
2354 (set (match_dup 0) (not:SI (match_dup 4)))]
2358 (define_insn "*andsi_iorsi3_notsi"
2359 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2364 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365 [(set_attr "length" "8")
2366 (set_attr "predicable" "yes")]
2370 [(set (match_operand:SI 0 "s_register_operand" "")
2371 (match_operator:SI 1 "logical_binary_operator"
2372 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373 (match_operand:SI 3 "const_int_operand" "")
2374 (match_operand:SI 4 "const_int_operand" ""))
2375 (match_operator:SI 9 "logical_binary_operator"
2376 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377 (match_operand:SI 6 "const_int_operand" ""))
2378 (match_operand:SI 7 "s_register_operand" "")])]))
2379 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2381 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2385 [(ashift:SI (match_dup 2) (match_dup 4))
2389 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2392 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2396 [(set (match_operand:SI 0 "s_register_operand" "")
2397 (match_operator:SI 1 "logical_binary_operator"
2398 [(match_operator:SI 9 "logical_binary_operator"
2399 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400 (match_operand:SI 6 "const_int_operand" ""))
2401 (match_operand:SI 7 "s_register_operand" "")])
2402 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403 (match_operand:SI 3 "const_int_operand" "")
2404 (match_operand:SI 4 "const_int_operand" ""))]))
2405 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2407 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2411 [(ashift:SI (match_dup 2) (match_dup 4))
2415 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2418 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2422 [(set (match_operand:SI 0 "s_register_operand" "")
2423 (match_operator:SI 1 "logical_binary_operator"
2424 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425 (match_operand:SI 3 "const_int_operand" "")
2426 (match_operand:SI 4 "const_int_operand" ""))
2427 (match_operator:SI 9 "logical_binary_operator"
2428 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429 (match_operand:SI 6 "const_int_operand" ""))
2430 (match_operand:SI 7 "s_register_operand" "")])]))
2431 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2433 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2437 [(ashift:SI (match_dup 2) (match_dup 4))
2441 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2444 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2448 [(set (match_operand:SI 0 "s_register_operand" "")
2449 (match_operator:SI 1 "logical_binary_operator"
2450 [(match_operator:SI 9 "logical_binary_operator"
2451 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452 (match_operand:SI 6 "const_int_operand" ""))
2453 (match_operand:SI 7 "s_register_operand" "")])
2454 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455 (match_operand:SI 3 "const_int_operand" "")
2456 (match_operand:SI 4 "const_int_operand" ""))]))
2457 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2459 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2463 [(ashift:SI (match_dup 2) (match_dup 4))
2467 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2470 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2474 ;; Minimum and maximum insns
2476 (define_insn "smaxsi3"
2477 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2478 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2479 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2480 (clobber (reg:CC CC_REGNUM))]
2483 cmp\\t%1, %2\;movlt\\t%0, %2
2484 cmp\\t%1, %2\;movge\\t%0, %1
2485 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2486 [(set_attr "conds" "clob")
2487 (set_attr "length" "8,8,12")]
2490 (define_insn "sminsi3"
2491 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2494 (clobber (reg:CC CC_REGNUM))]
2497 cmp\\t%1, %2\;movge\\t%0, %2
2498 cmp\\t%1, %2\;movlt\\t%0, %1
2499 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2500 [(set_attr "conds" "clob")
2501 (set_attr "length" "8,8,12")]
2504 (define_insn "umaxsi3"
2505 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2508 (clobber (reg:CC CC_REGNUM))]
2511 cmp\\t%1, %2\;movcc\\t%0, %2
2512 cmp\\t%1, %2\;movcs\\t%0, %1
2513 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2514 [(set_attr "conds" "clob")
2515 (set_attr "length" "8,8,12")]
2518 (define_insn "uminsi3"
2519 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2522 (clobber (reg:CC CC_REGNUM))]
2525 cmp\\t%1, %2\;movcs\\t%0, %2
2526 cmp\\t%1, %2\;movcc\\t%0, %1
2527 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2528 [(set_attr "conds" "clob")
2529 (set_attr "length" "8,8,12")]
2532 (define_insn "*store_minmaxsi"
2533 [(set (match_operand:SI 0 "memory_operand" "=m")
2534 (match_operator:SI 3 "minmax_operator"
2535 [(match_operand:SI 1 "s_register_operand" "r")
2536 (match_operand:SI 2 "s_register_operand" "r")]))
2537 (clobber (reg:CC CC_REGNUM))]
2540 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541 operands[1], operands[2]);
2542 output_asm_insn (\"cmp\\t%1, %2\", operands);
2543 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2547 [(set_attr "conds" "clob")
2548 (set_attr "length" "12")
2549 (set_attr "type" "store1")]
2552 ; Reject the frame pointer in operand[1], since reloading this after
2553 ; it has been eliminated can cause carnage.
2554 (define_insn "*minmax_arithsi"
2555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556 (match_operator:SI 4 "shiftable_operator"
2557 [(match_operator:SI 5 "minmax_operator"
2558 [(match_operand:SI 2 "s_register_operand" "r,r")
2559 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2561 (clobber (reg:CC CC_REGNUM))]
2562 "TARGET_ARM && !arm_eliminable_register (operands[1])"
2565 enum rtx_code code = GET_CODE (operands[4]);
2567 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568 operands[2], operands[3]);
2569 output_asm_insn (\"cmp\\t%2, %3\", operands);
2570 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571 if (which_alternative != 0 || operands[3] != const0_rtx
2572 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2576 [(set_attr "conds" "clob")
2577 (set_attr "length" "12")]
2581 ;; Shift and rotation insns
2583 (define_expand "ashldi3"
2584 [(set (match_operand:DI 0 "s_register_operand" "")
2585 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586 (match_operand:SI 2 "reg_or_int_operand" "")))]
2589 if (GET_CODE (operands[2]) == CONST_INT)
2591 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2593 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2596 /* Ideally we shouldn't fail here if we could know that operands[1]
2597 ends up already living in an iwmmxt register. Otherwise it's
2598 cheaper to have the alternate code being generated than moving
2599 values to iwmmxt regs and back. */
2602 else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2607 (define_insn "arm_ashldi3_1bit"
2608 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2609 (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2611 (clobber (reg:CC CC_REGNUM))]
2613 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614 [(set_attr "conds" "clob")
2615 (set_attr "length" "8")]
2618 (define_expand "ashlsi3"
2619 [(set (match_operand:SI 0 "s_register_operand" "")
2620 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621 (match_operand:SI 2 "arm_rhs_operand" "")))]
2624 if (GET_CODE (operands[2]) == CONST_INT
2625 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2627 emit_insn (gen_movsi (operands[0], const0_rtx));
2633 (define_insn "*thumb_ashlsi3"
2634 [(set (match_operand:SI 0 "register_operand" "=l,l")
2635 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2639 [(set_attr "length" "2")]
2642 (define_expand "ashrdi3"
2643 [(set (match_operand:DI 0 "s_register_operand" "")
2644 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645 (match_operand:SI 2 "reg_or_int_operand" "")))]
2648 if (GET_CODE (operands[2]) == CONST_INT)
2650 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2652 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2655 /* Ideally we shouldn't fail here if we could know that operands[1]
2656 ends up already living in an iwmmxt register. Otherwise it's
2657 cheaper to have the alternate code being generated than moving
2658 values to iwmmxt regs and back. */
2661 else if (!TARGET_REALLY_IWMMXT)
2666 (define_insn "arm_ashrdi3_1bit"
2667 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2668 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2670 (clobber (reg:CC CC_REGNUM))]
2672 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673 [(set_attr "conds" "clob")
2674 (set_attr "length" "8")]
2677 (define_expand "ashrsi3"
2678 [(set (match_operand:SI 0 "s_register_operand" "")
2679 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680 (match_operand:SI 2 "arm_rhs_operand" "")))]
2683 if (GET_CODE (operands[2]) == CONST_INT
2684 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685 operands[2] = GEN_INT (31);
2689 (define_insn "*thumb_ashrsi3"
2690 [(set (match_operand:SI 0 "register_operand" "=l,l")
2691 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2695 [(set_attr "length" "2")]
2698 (define_expand "lshrdi3"
2699 [(set (match_operand:DI 0 "s_register_operand" "")
2700 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701 (match_operand:SI 2 "reg_or_int_operand" "")))]
2704 if (GET_CODE (operands[2]) == CONST_INT)
2706 if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2708 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2711 /* Ideally we shouldn't fail here if we could know that operands[1]
2712 ends up already living in an iwmmxt register. Otherwise it's
2713 cheaper to have the alternate code being generated than moving
2714 values to iwmmxt regs and back. */
2717 else if (!TARGET_REALLY_IWMMXT)
2722 (define_insn "arm_lshrdi3_1bit"
2723 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2724 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2726 (clobber (reg:CC CC_REGNUM))]
2728 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729 [(set_attr "conds" "clob")
2730 (set_attr "length" "8")]
2733 (define_expand "lshrsi3"
2734 [(set (match_operand:SI 0 "s_register_operand" "")
2735 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736 (match_operand:SI 2 "arm_rhs_operand" "")))]
2739 if (GET_CODE (operands[2]) == CONST_INT
2740 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2742 emit_insn (gen_movsi (operands[0], const0_rtx));
2748 (define_insn "*thumb_lshrsi3"
2749 [(set (match_operand:SI 0 "register_operand" "=l,l")
2750 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2754 [(set_attr "length" "2")]
2757 (define_expand "rotlsi3"
2758 [(set (match_operand:SI 0 "s_register_operand" "")
2759 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760 (match_operand:SI 2 "reg_or_int_operand" "")))]
2763 if (GET_CODE (operands[2]) == CONST_INT)
2764 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2767 rtx reg = gen_reg_rtx (SImode);
2768 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2774 (define_expand "rotrsi3"
2775 [(set (match_operand:SI 0 "s_register_operand" "")
2776 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777 (match_operand:SI 2 "arm_rhs_operand" "")))]
2782 if (GET_CODE (operands[2]) == CONST_INT
2783 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2786 else /* TARGET_THUMB */
2788 if (GET_CODE (operands [2]) == CONST_INT)
2789 operands [2] = force_reg (SImode, operands[2]);
2794 (define_insn "*thumb_rotrsi3"
2795 [(set (match_operand:SI 0 "register_operand" "=l")
2796 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797 (match_operand:SI 2 "register_operand" "l")))]
2800 [(set_attr "length" "2")]
2803 (define_insn "*arm_shiftsi3"
2804 [(set (match_operand:SI 0 "s_register_operand" "=r")
2805 (match_operator:SI 3 "shift_operator"
2806 [(match_operand:SI 1 "s_register_operand" "r")
2807 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2810 [(set_attr "predicable" "yes")
2811 (set_attr "shift" "1")
2812 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813 (const_string "alu_shift")
2814 (const_string "alu_shift_reg")))]
2817 (define_insn "*shiftsi3_compare0"
2818 [(set (reg:CC_NOOV CC_REGNUM)
2819 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820 [(match_operand:SI 1 "s_register_operand" "r")
2821 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2823 (set (match_operand:SI 0 "s_register_operand" "=r")
2824 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2826 "mov%?s\\t%0, %1%S3"
2827 [(set_attr "conds" "set")
2828 (set_attr "shift" "1")
2829 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830 (const_string "alu_shift")
2831 (const_string "alu_shift_reg")))]
2834 (define_insn "*shiftsi3_compare0_scratch"
2835 [(set (reg:CC_NOOV CC_REGNUM)
2836 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837 [(match_operand:SI 1 "s_register_operand" "r")
2838 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2840 (clobber (match_scratch:SI 0 "=r"))]
2842 "mov%?s\\t%0, %1%S3"
2843 [(set_attr "conds" "set")
2844 (set_attr "shift" "1")]
2847 (define_insn "*notsi_shiftsi"
2848 [(set (match_operand:SI 0 "s_register_operand" "=r")
2849 (not:SI (match_operator:SI 3 "shift_operator"
2850 [(match_operand:SI 1 "s_register_operand" "r")
2851 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2854 [(set_attr "predicable" "yes")
2855 (set_attr "shift" "1")
2856 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857 (const_string "alu_shift")
2858 (const_string "alu_shift_reg")))]
2861 (define_insn "*notsi_shiftsi_compare0"
2862 [(set (reg:CC_NOOV CC_REGNUM)
2863 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864 [(match_operand:SI 1 "s_register_operand" "r")
2865 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2867 (set (match_operand:SI 0 "s_register_operand" "=r")
2868 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2870 "mvn%?s\\t%0, %1%S3"
2871 [(set_attr "conds" "set")
2872 (set_attr "shift" "1")
2873 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874 (const_string "alu_shift")
2875 (const_string "alu_shift_reg")))]
2878 (define_insn "*not_shiftsi_compare0_scratch"
2879 [(set (reg:CC_NOOV CC_REGNUM)
2880 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2881 [(match_operand:SI 1 "s_register_operand" "r")
2882 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2884 (clobber (match_scratch:SI 0 "=r"))]
2886 "mvn%?s\\t%0, %1%S3"
2887 [(set_attr "conds" "set")
2888 (set_attr "shift" "1")
2889 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890 (const_string "alu_shift")
2891 (const_string "alu_shift_reg")))]
2894 ;; We don't really have extzv, but defining this using shifts helps
2895 ;; to reduce register pressure later on.
2897 (define_expand "extzv"
2899 (ashift:SI (match_operand:SI 1 "register_operand" "")
2900 (match_operand:SI 2 "const_int_operand" "")))
2901 (set (match_operand:SI 0 "register_operand" "")
2902 (lshiftrt:SI (match_dup 4)
2903 (match_operand:SI 3 "const_int_operand" "")))]
2907 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2910 operands[3] = GEN_INT (rshift);
2914 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2918 operands[2] = GEN_INT (lshift);
2919 operands[4] = gen_reg_rtx (SImode);
2924 ;; Unary arithmetic insns
2926 (define_expand "negdi2"
2928 [(set (match_operand:DI 0 "s_register_operand" "")
2929 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2930 (clobber (reg:CC CC_REGNUM))])]
2935 if (GET_CODE (operands[1]) != REG)
2936 operands[1] = force_reg (SImode, operands[1]);
2941 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942 ;; The second alternative is to allow the common case of a *full* overlap.
2943 (define_insn "*arm_negdi2"
2944 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2945 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2946 (clobber (reg:CC CC_REGNUM))]
2948 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2949 [(set_attr "conds" "clob")
2950 (set_attr "length" "8")]
2953 (define_insn "*thumb_negdi2"
2954 [(set (match_operand:DI 0 "register_operand" "=&l")
2955 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2956 (clobber (reg:CC CC_REGNUM))]
2958 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959 [(set_attr "length" "6")]
2962 (define_expand "negsi2"
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2969 (define_insn "*arm_negsi2"
2970 [(set (match_operand:SI 0 "s_register_operand" "=r")
2971 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2973 "rsb%?\\t%0, %1, #0"
2974 [(set_attr "predicable" "yes")]
2977 (define_insn "*thumb_negsi2"
2978 [(set (match_operand:SI 0 "register_operand" "=l")
2979 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2982 [(set_attr "length" "2")]
2985 (define_expand "negsf2"
2986 [(set (match_operand:SF 0 "s_register_operand" "")
2987 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2988 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2992 (define_expand "negdf2"
2993 [(set (match_operand:DF 0 "s_register_operand" "")
2994 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2995 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2998 ;; abssi2 doesn't really clobber the condition codes if a different register
2999 ;; is being set. To keep things simple, assume during rtl manipulations that
3000 ;; it does, but tell the final scan operator the truth. Similarly for
3003 (define_expand "abssi2"
3005 [(set (match_operand:SI 0 "s_register_operand" "")
3006 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007 (clobber (reg:CC CC_REGNUM))])]
3011 (define_insn "*arm_abssi2"
3012 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3013 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3014 (clobber (reg:CC CC_REGNUM))]
3017 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3018 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3019 [(set_attr "conds" "clob,*")
3020 (set_attr "shift" "1")
3021 ;; predicable can't be set based on the variant, so left as no
3022 (set_attr "length" "8")]
3025 (define_insn "*neg_abssi2"
3026 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3028 (clobber (reg:CC CC_REGNUM))]
3031 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3032 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3033 [(set_attr "conds" "clob,*")
3034 (set_attr "shift" "1")
3035 ;; predicable can't be set based on the variant, so left as no
3036 (set_attr "length" "8")]
3039 (define_expand "abssf2"
3040 [(set (match_operand:SF 0 "s_register_operand" "")
3041 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3042 "TARGET_ARM && TARGET_HARD_FLOAT"
3045 (define_expand "absdf2"
3046 [(set (match_operand:DF 0 "s_register_operand" "")
3047 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT"
3051 (define_expand "sqrtsf2"
3052 [(set (match_operand:SF 0 "s_register_operand" "")
3053 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3054 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057 (define_expand "sqrtdf2"
3058 [(set (match_operand:DF 0 "s_register_operand" "")
3059 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3060 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3063 (define_insn_and_split "one_cmpldi2"
3064 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3068 "TARGET_ARM && reload_completed"
3069 [(set (match_dup 0) (not:SI (match_dup 1)))
3070 (set (match_dup 2) (not:SI (match_dup 3)))]
3073 operands[2] = gen_highpart (SImode, operands[0]);
3074 operands[0] = gen_lowpart (SImode, operands[0]);
3075 operands[3] = gen_highpart (SImode, operands[1]);
3076 operands[1] = gen_lowpart (SImode, operands[1]);
3078 [(set_attr "length" "8")
3079 (set_attr "predicable" "yes")]
3082 (define_expand "one_cmplsi2"
3083 [(set (match_operand:SI 0 "s_register_operand" "")
3084 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3089 (define_insn "*arm_one_cmplsi2"
3090 [(set (match_operand:SI 0 "s_register_operand" "=r")
3091 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3094 [(set_attr "predicable" "yes")]
3097 (define_insn "*thumb_one_cmplsi2"
3098 [(set (match_operand:SI 0 "register_operand" "=l")
3099 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3102 [(set_attr "length" "2")]
3105 (define_insn "*notsi_compare0"
3106 [(set (reg:CC_NOOV CC_REGNUM)
3107 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3109 (set (match_operand:SI 0 "s_register_operand" "=r")
3110 (not:SI (match_dup 1)))]
3113 [(set_attr "conds" "set")]
3116 (define_insn "*notsi_compare0_scratch"
3117 [(set (reg:CC_NOOV CC_REGNUM)
3118 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3120 (clobber (match_scratch:SI 0 "=r"))]
3123 [(set_attr "conds" "set")]
3126 ;; Fixed <--> Floating conversion insns
3128 (define_expand "floatsisf2"
3129 [(set (match_operand:SF 0 "s_register_operand" "")
3130 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3131 "TARGET_ARM && TARGET_HARD_FLOAT"
3133 if (TARGET_MAVERICK)
3135 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3140 (define_expand "floatsidf2"
3141 [(set (match_operand:DF 0 "s_register_operand" "")
3142 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3143 "TARGET_ARM && TARGET_HARD_FLOAT"
3145 if (TARGET_MAVERICK)
3147 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3152 (define_expand "fix_truncsfsi2"
3153 [(set (match_operand:SI 0 "s_register_operand" "")
3154 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3155 "TARGET_ARM && TARGET_HARD_FLOAT"
3157 if (TARGET_MAVERICK)
3159 if (!cirrus_fp_register (operands[0], SImode))
3160 operands[0] = force_reg (SImode, operands[0]);
3161 if (!cirrus_fp_register (operands[1], SFmode))
3162 operands[1] = force_reg (SFmode, operands[0]);
3163 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3168 (define_expand "fix_truncdfsi2"
3169 [(set (match_operand:SI 0 "s_register_operand" "")
3170 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3171 "TARGET_ARM && TARGET_HARD_FLOAT"
3173 if (TARGET_MAVERICK)
3175 if (!cirrus_fp_register (operands[1], DFmode))
3176 operands[1] = force_reg (DFmode, operands[0]);
3177 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3184 (define_expand "truncdfsf2"
3185 [(set (match_operand:SF 0 "s_register_operand" "")
3187 (match_operand:DF 1 "s_register_operand" "")))]
3188 "TARGET_ARM && TARGET_HARD_FLOAT"
3192 ;; Zero and sign extension instructions.
3194 (define_insn "zero_extendsidi2"
3195 [(set (match_operand:DI 0 "s_register_operand" "=r")
3196 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3199 if (REGNO (operands[1])
3200 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202 return \"mov%?\\t%R0, #0\";
3204 [(set_attr "length" "8")
3205 (set_attr "predicable" "yes")]
3208 (define_insn "zero_extendqidi2"
3209 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3210 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3213 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3215 [(set_attr "length" "8")
3216 (set_attr "predicable" "yes")
3217 (set_attr "type" "*,load_byte")
3218 (set_attr "pool_range" "*,4092")
3219 (set_attr "neg_pool_range" "*,4084")]
3222 (define_insn "extendsidi2"
3223 [(set (match_operand:DI 0 "s_register_operand" "=r")
3224 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3227 if (REGNO (operands[1])
3228 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230 return \"mov%?\\t%R0, %Q0, asr #31\";
3232 [(set_attr "length" "8")
3233 (set_attr "shift" "1")
3234 (set_attr "predicable" "yes")]
3237 (define_expand "zero_extendhisi2"
3239 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3241 (set (match_operand:SI 0 "s_register_operand" "")
3242 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3246 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3248 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3253 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3255 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3259 if (!s_register_operand (operands[1], HImode))
3260 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3264 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3269 operands[1] = gen_lowpart (SImode, operands[1]);
3270 operands[2] = gen_reg_rtx (SImode);
3274 (define_insn "*thumb_zero_extendhisi2"
3275 [(set (match_operand:SI 0 "register_operand" "=l")
3276 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277 "TARGET_THUMB && !arm_arch6"
3279 rtx mem = XEXP (operands[1], 0);
3281 if (GET_CODE (mem) == CONST)
3282 mem = XEXP (mem, 0);
3284 if (GET_CODE (mem) == LABEL_REF)
3285 return \"ldr\\t%0, %1\";
3287 if (GET_CODE (mem) == PLUS)
3289 rtx a = XEXP (mem, 0);
3290 rtx b = XEXP (mem, 1);
3292 /* This can happen due to bugs in reload. */
3293 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3296 ops[0] = operands[0];
3299 output_asm_insn (\"mov %0, %1\", ops);
3301 XEXP (mem, 0) = operands[0];
3304 else if ( GET_CODE (a) == LABEL_REF
3305 && GET_CODE (b) == CONST_INT)
3306 return \"ldr\\t%0, %1\";
3309 return \"ldrh\\t%0, %1\";
3311 [(set_attr "length" "4")
3312 (set_attr "type" "load_byte")
3313 (set_attr "pool_range" "60")]
3316 (define_insn "*thumb_zero_extendhisi2_v6"
3317 [(set (match_operand:SI 0 "register_operand" "=l,l")
3318 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319 "TARGET_THUMB && arm_arch6"
3323 if (which_alternative == 0)
3324 return \"uxth\\t%0, %1\";
3326 mem = XEXP (operands[1], 0);
3328 if (GET_CODE (mem) == CONST)
3329 mem = XEXP (mem, 0);
3331 if (GET_CODE (mem) == LABEL_REF)
3332 return \"ldr\\t%0, %1\";
3334 if (GET_CODE (mem) == PLUS)
3336 rtx a = XEXP (mem, 0);
3337 rtx b = XEXP (mem, 1);
3339 /* This can happen due to bugs in reload. */
3340 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3343 ops[0] = operands[0];
3346 output_asm_insn (\"mov %0, %1\", ops);
3348 XEXP (mem, 0) = operands[0];
3351 else if ( GET_CODE (a) == LABEL_REF
3352 && GET_CODE (b) == CONST_INT)
3353 return \"ldr\\t%0, %1\";
3356 return \"ldrh\\t%0, %1\";
3358 [(set_attr "length" "2,4")
3359 (set_attr "type" "alu_shift,load_byte")
3360 (set_attr "pool_range" "*,60")]
3363 (define_insn "*arm_zero_extendhisi2"
3364 [(set (match_operand:SI 0 "s_register_operand" "=r")
3365 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366 "TARGET_ARM && arm_arch4 && !arm_arch6"
3368 [(set_attr "type" "load_byte")
3369 (set_attr "predicable" "yes")
3370 (set_attr "pool_range" "256")
3371 (set_attr "neg_pool_range" "244")]
3374 (define_insn "*arm_zero_extendhisi2_v6"
3375 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377 "TARGET_ARM && arm_arch6"
3381 [(set_attr "type" "alu_shift,load_byte")
3382 (set_attr "predicable" "yes")
3383 (set_attr "pool_range" "*,256")
3384 (set_attr "neg_pool_range" "*,244")]
3387 (define_insn "*arm_zero_extendhisi2addsi"
3388 [(set (match_operand:SI 0 "s_register_operand" "=r")
3389 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390 (match_operand:SI 2 "s_register_operand" "r")))]
3391 "TARGET_ARM && arm_arch6"
3392 "uxtah%?\\t%0, %2, %1"
3393 [(set_attr "type" "alu_shift")
3394 (set_attr "predicable" "yes")]
3397 (define_expand "zero_extendqisi2"
3398 [(set (match_operand:SI 0 "s_register_operand" "")
3399 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3402 if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3406 emit_insn (gen_andsi3 (operands[0],
3407 gen_lowpart (SImode, operands[1]),
3410 else /* TARGET_THUMB */
3412 rtx temp = gen_reg_rtx (SImode);
3415 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416 operands[1] = gen_lowpart (SImode, operands[1]);
3419 ops[1] = operands[1];
3420 ops[2] = GEN_INT (24);
3422 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3425 ops[0] = operands[0];
3427 ops[2] = GEN_INT (24);
3429 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3437 (define_insn "*thumb_zero_extendqisi2"
3438 [(set (match_operand:SI 0 "register_operand" "=l")
3439 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440 "TARGET_THUMB && !arm_arch6"
3442 [(set_attr "length" "2")
3443 (set_attr "type" "load_byte")
3444 (set_attr "pool_range" "32")]
3447 (define_insn "*thumb_zero_extendqisi2_v6"
3448 [(set (match_operand:SI 0 "register_operand" "=l,l")
3449 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450 "TARGET_THUMB && arm_arch6"
3454 [(set_attr "length" "2,2")
3455 (set_attr "type" "alu_shift,load_byte")
3456 (set_attr "pool_range" "*,32")]
3459 (define_insn "*arm_zero_extendqisi2"
3460 [(set (match_operand:SI 0 "s_register_operand" "=r")
3461 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462 "TARGET_ARM && !arm_arch6"
3463 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3464 [(set_attr "type" "load_byte")
3465 (set_attr "predicable" "yes")
3466 (set_attr "pool_range" "4096")
3467 (set_attr "neg_pool_range" "4084")]
3470 (define_insn "*arm_zero_extendqisi2_v6"
3471 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473 "TARGET_ARM && arm_arch6"
3476 ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477 [(set_attr "type" "alu_shift,load_byte")
3478 (set_attr "predicable" "yes")
3479 (set_attr "pool_range" "*,4096")
3480 (set_attr "neg_pool_range" "*,4084")]
3483 (define_insn "*arm_zero_extendqisi2addsi"
3484 [(set (match_operand:SI 0 "s_register_operand" "=r")
3485 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486 (match_operand:SI 2 "s_register_operand" "r")))]
3487 "TARGET_ARM && arm_arch6"
3488 "uxtab%?\\t%0, %2, %1"
3489 [(set_attr "predicable" "yes")
3490 (set_attr "type" "alu_shift")]
3494 [(set (match_operand:SI 0 "s_register_operand" "")
3495 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3497 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3498 [(set (match_dup 2) (match_dup 1))
3499 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3504 [(set (match_operand:SI 0 "s_register_operand" "")
3505 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3506 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3507 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3508 [(set (match_dup 2) (match_dup 1))
3509 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3513 (define_insn "*compareqi_eq0"
3514 [(set (reg:CC_Z CC_REGNUM)
3515 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3519 [(set_attr "conds" "set")]
3522 (define_expand "extendhisi2"
3524 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3526 (set (match_operand:SI 0 "s_register_operand" "")
3527 (ashiftrt:SI (match_dup 2)
3532 if (GET_CODE (operands[1]) == MEM)
3536 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3541 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3542 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3547 if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3549 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3553 if (!s_register_operand (operands[1], HImode))
3554 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3559 emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3561 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3562 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3567 operands[1] = gen_lowpart (SImode, operands[1]);
3568 operands[2] = gen_reg_rtx (SImode);
3572 (define_insn "thumb_extendhisi2"
3573 [(set (match_operand:SI 0 "register_operand" "=l")
3574 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3575 (clobber (match_scratch:SI 2 "=&l"))]
3576 "TARGET_THUMB && !arm_arch6"
3580 rtx mem = XEXP (operands[1], 0);
3582 /* This code used to try to use 'V', and fix the address only if it was
3583 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3584 range of QImode offsets, and offsettable_address_p does a QImode
3587 if (GET_CODE (mem) == CONST)
3588 mem = XEXP (mem, 0);
3590 if (GET_CODE (mem) == LABEL_REF)
3591 return \"ldr\\t%0, %1\";
3593 if (GET_CODE (mem) == PLUS)
3595 rtx a = XEXP (mem, 0);
3596 rtx b = XEXP (mem, 1);
3598 if (GET_CODE (a) == LABEL_REF
3599 && GET_CODE (b) == CONST_INT)
3600 return \"ldr\\t%0, %1\";
3602 if (GET_CODE (b) == REG)
3603 return \"ldrsh\\t%0, %1\";
3611 ops[2] = const0_rtx;
3614 gcc_assert (GET_CODE (ops[1]) == REG);
3616 ops[0] = operands[0];
3617 ops[3] = operands[2];
3618 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3621 [(set_attr "length" "4")
3622 (set_attr "type" "load_byte")
3623 (set_attr "pool_range" "1020")]
3626 ;; We used to have an early-clobber on the scratch register here.
3627 ;; However, there's a bug somewhere in reload which means that this
3628 ;; can be partially ignored during spill allocation if the memory
3629 ;; address also needs reloading; this causes us to die later on when
3630 ;; we try to verify the operands. Fortunately, we don't really need
3631 ;; the early-clobber: we can always use operand 0 if operand 2
3632 ;; overlaps the address.
3633 (define_insn "*thumb_extendhisi2_insn_v6"
3634 [(set (match_operand:SI 0 "register_operand" "=l,l")
3635 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3636 (clobber (match_scratch:SI 2 "=X,l"))]
3637 "TARGET_THUMB && arm_arch6"
3643 if (which_alternative == 0)
3644 return \"sxth\\t%0, %1\";
3646 mem = XEXP (operands[1], 0);
3648 /* This code used to try to use 'V', and fix the address only if it was
3649 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3650 range of QImode offsets, and offsettable_address_p does a QImode
3653 if (GET_CODE (mem) == CONST)
3654 mem = XEXP (mem, 0);
3656 if (GET_CODE (mem) == LABEL_REF)
3657 return \"ldr\\t%0, %1\";
3659 if (GET_CODE (mem) == PLUS)
3661 rtx a = XEXP (mem, 0);
3662 rtx b = XEXP (mem, 1);
3664 if (GET_CODE (a) == LABEL_REF
3665 && GET_CODE (b) == CONST_INT)
3666 return \"ldr\\t%0, %1\";
3668 if (GET_CODE (b) == REG)
3669 return \"ldrsh\\t%0, %1\";
3677 ops[2] = const0_rtx;
3680 gcc_assert (GET_CODE (ops[1]) == REG);
3682 ops[0] = operands[0];
3683 if (reg_mentioned_p (operands[2], ops[1]))
3686 ops[3] = operands[2];
3687 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3690 [(set_attr "length" "2,4")
3691 (set_attr "type" "alu_shift,load_byte")
3692 (set_attr "pool_range" "*,1020")]
3695 (define_expand "extendhisi2_mem"
3696 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3698 (zero_extend:SI (match_dup 7)))
3699 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3700 (set (match_operand:SI 0 "" "")
3701 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3706 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3708 mem1 = change_address (operands[1], QImode, addr);
3709 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3710 operands[0] = gen_lowpart (SImode, operands[0]);
3712 operands[2] = gen_reg_rtx (SImode);
3713 operands[3] = gen_reg_rtx (SImode);
3714 operands[6] = gen_reg_rtx (SImode);
3717 if (BYTES_BIG_ENDIAN)
3719 operands[4] = operands[2];
3720 operands[5] = operands[3];
3724 operands[4] = operands[3];
3725 operands[5] = operands[2];
3730 (define_insn "*arm_extendhisi2"
3731 [(set (match_operand:SI 0 "s_register_operand" "=r")
3732 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3733 "TARGET_ARM && arm_arch4 && !arm_arch6"
3735 [(set_attr "type" "load_byte")
3736 (set_attr "predicable" "yes")
3737 (set_attr "pool_range" "256")
3738 (set_attr "neg_pool_range" "244")]
3741 (define_insn "*arm_extendhisi2_v6"
3742 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3743 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3744 "TARGET_ARM && arm_arch6"
3748 [(set_attr "type" "alu_shift,load_byte")
3749 (set_attr "predicable" "yes")
3750 (set_attr "pool_range" "*,256")
3751 (set_attr "neg_pool_range" "*,244")]
3754 (define_insn "*arm_extendhisi2addsi"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3757 (match_operand:SI 2 "s_register_operand" "r")))]
3758 "TARGET_ARM && arm_arch6"
3759 "sxtah%?\\t%0, %2, %1"
3762 (define_expand "extendqihi2"
3764 (ashift:SI (match_operand:QI 1 "general_operand" "")
3766 (set (match_operand:HI 0 "s_register_operand" "")
3767 (ashiftrt:SI (match_dup 2)
3772 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3774 emit_insn (gen_rtx_SET (VOIDmode,
3776 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3779 if (!s_register_operand (operands[1], QImode))
3780 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3781 operands[0] = gen_lowpart (SImode, operands[0]);
3782 operands[1] = gen_lowpart (SImode, operands[1]);
3783 operands[2] = gen_reg_rtx (SImode);
3787 (define_insn "*extendqihi_insn"
3788 [(set (match_operand:HI 0 "s_register_operand" "=r")
3789 (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3790 "TARGET_ARM && arm_arch4"
3792 [(set_attr "type" "load_byte")
3793 (set_attr "predicable" "yes")
3794 (set_attr "pool_range" "256")
3795 (set_attr "neg_pool_range" "244")]
3798 (define_expand "extendqisi2"
3800 (ashift:SI (match_operand:QI 1 "general_operand" "")
3802 (set (match_operand:SI 0 "s_register_operand" "")
3803 (ashiftrt:SI (match_dup 2)
3808 if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3810 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3815 if (!s_register_operand (operands[1], QImode))
3816 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3820 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3821 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3825 operands[1] = gen_lowpart (SImode, operands[1]);
3826 operands[2] = gen_reg_rtx (SImode);
3830 (define_insn "*arm_extendqisi"
3831 [(set (match_operand:SI 0 "s_register_operand" "=r")
3832 (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3833 "TARGET_ARM && arm_arch4 && !arm_arch6"
3835 [(set_attr "type" "load_byte")
3836 (set_attr "predicable" "yes")
3837 (set_attr "pool_range" "256")
3838 (set_attr "neg_pool_range" "244")]
3841 (define_insn "*arm_extendqisi_v6"
3842 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3843 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3844 "TARGET_ARM && arm_arch6"
3848 [(set_attr "type" "alu_shift,load_byte")
3849 (set_attr "predicable" "yes")
3850 (set_attr "pool_range" "*,256")
3851 (set_attr "neg_pool_range" "*,244")]
3854 (define_insn "*arm_extendqisi2addsi"
3855 [(set (match_operand:SI 0 "s_register_operand" "=r")
3856 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3857 (match_operand:SI 2 "s_register_operand" "r")))]
3858 "TARGET_ARM && arm_arch6"
3859 "sxtab%?\\t%0, %2, %1"
3860 [(set_attr "type" "alu_shift")
3861 (set_attr "predicable" "yes")]
3864 (define_insn "*thumb_extendqisi2"
3865 [(set (match_operand:SI 0 "register_operand" "=l,l")
3866 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3867 "TARGET_THUMB && !arm_arch6"
3871 rtx mem = XEXP (operands[1], 0);
3873 if (GET_CODE (mem) == CONST)
3874 mem = XEXP (mem, 0);
3876 if (GET_CODE (mem) == LABEL_REF)
3877 return \"ldr\\t%0, %1\";
3879 if (GET_CODE (mem) == PLUS
3880 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3881 return \"ldr\\t%0, %1\";
3883 if (which_alternative == 0)
3884 return \"ldrsb\\t%0, %1\";
3886 ops[0] = operands[0];
3888 if (GET_CODE (mem) == PLUS)
3890 rtx a = XEXP (mem, 0);
3891 rtx b = XEXP (mem, 1);
3896 if (GET_CODE (a) == REG)
3898 if (GET_CODE (b) == REG)
3899 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3900 else if (REGNO (a) == REGNO (ops[0]))
3902 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", 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);
3911 gcc_assert (GET_CODE (b) == REG);
3912 if (REGNO (b) == REGNO (ops[0]))
3914 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3915 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3919 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3922 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3924 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3925 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3926 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3931 ops[2] = const0_rtx;
3933 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3937 [(set_attr "length" "2,6")
3938 (set_attr "type" "load_byte,load_byte")
3939 (set_attr "pool_range" "32,32")]
3942 (define_insn "*thumb_extendqisi2_v6"
3943 [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3944 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3945 "TARGET_THUMB && arm_arch6"
3951 if (which_alternative == 0)
3952 return \"sxtb\\t%0, %1\";
3954 mem = XEXP (operands[1], 0);
3956 if (GET_CODE (mem) == CONST)
3957 mem = XEXP (mem, 0);
3959 if (GET_CODE (mem) == LABEL_REF)
3960 return \"ldr\\t%0, %1\";
3962 if (GET_CODE (mem) == PLUS
3963 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3964 return \"ldr\\t%0, %1\";
3966 if (which_alternative == 0)
3967 return \"ldrsb\\t%0, %1\";
3969 ops[0] = operands[0];
3971 if (GET_CODE (mem) == PLUS)
3973 rtx a = XEXP (mem, 0);
3974 rtx b = XEXP (mem, 1);
3979 if (GET_CODE (a) == REG)
3981 if (GET_CODE (b) == REG)
3982 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3983 else if (REGNO (a) == REGNO (ops[0]))
3985 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3986 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3989 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3993 gcc_assert (GET_CODE (b) == REG);
3994 if (REGNO (b) == REGNO (ops[0]))
3996 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3997 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4000 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4003 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4005 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4006 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4011 ops[2] = const0_rtx;
4013 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4017 [(set_attr "length" "2,2,4")
4018 (set_attr "type" "alu_shift,load_byte,load_byte")
4019 (set_attr "pool_range" "*,32,32")]
4022 (define_expand "extendsfdf2"
4023 [(set (match_operand:DF 0 "s_register_operand" "")
4024 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
4025 "TARGET_ARM && TARGET_HARD_FLOAT"
4029 ;; Move insns (including loads and stores)
4031 ;; XXX Just some ideas about movti.
4032 ;; I don't think these are a good idea on the arm, there just aren't enough
4034 ;;(define_expand "loadti"
4035 ;; [(set (match_operand:TI 0 "s_register_operand" "")
4036 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
4039 ;;(define_expand "storeti"
4040 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4041 ;; (match_operand:TI 1 "s_register_operand" ""))]
4044 ;;(define_expand "movti"
4045 ;; [(set (match_operand:TI 0 "general_operand" "")
4046 ;; (match_operand:TI 1 "general_operand" ""))]
4052 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4053 ;; operands[1] = copy_to_reg (operands[1]);
4054 ;; if (GET_CODE (operands[0]) == MEM)
4055 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4056 ;; else if (GET_CODE (operands[1]) == MEM)
4057 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4061 ;; emit_insn (insn);
4065 ;; Recognize garbage generated above.
4068 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4069 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4073 ;; register mem = (which_alternative < 3);
4074 ;; register const char *template;
4076 ;; operands[mem] = XEXP (operands[mem], 0);
4077 ;; switch (which_alternative)
4079 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4080 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
4081 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
4082 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
4083 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
4084 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
4086 ;; output_asm_insn (template, operands);
4090 (define_expand "movdi"
4091 [(set (match_operand:DI 0 "general_operand" "")
4092 (match_operand:DI 1 "general_operand" ""))]
4095 if (!no_new_pseudos)
4097 if (GET_CODE (operands[0]) != REG)
4098 operands[1] = force_reg (DImode, operands[1]);
4103 (define_insn "*arm_movdi"
4104 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4105 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
4107 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4109 && ( register_operand (operands[0], DImode)
4110 || register_operand (operands[1], DImode))"
4112 switch (which_alternative)
4119 return output_move_double (operands);
4122 [(set_attr "length" "8,12,16,8,8")
4123 (set_attr "type" "*,*,*,load2,store2")
4124 (set_attr "pool_range" "*,*,*,1020,*")
4125 (set_attr "neg_pool_range" "*,*,*,1008,*")]
4129 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4130 (match_operand:ANY64 1 "const_double_operand" ""))]
4133 && (arm_const_double_inline_cost (operands[1])
4134 <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4137 arm_split_constant (SET, SImode, curr_insn,
4138 INTVAL (gen_lowpart (SImode, operands[1])),
4139 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4140 arm_split_constant (SET, SImode, curr_insn,
4141 INTVAL (gen_highpart_mode (SImode,
4142 GET_MODE (operands[0]),
4144 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4149 ; If optimizing for size, or if we have load delay slots, then
4150 ; we want to split the constant into two separate operations.
4151 ; In both cases this may split a trivial part into a single data op
4152 ; leaving a single complex constant to load. We can also get longer
4153 ; offsets in a LDR which means we get better chances of sharing the pool
4154 ; entries. Finally, we can normally do a better job of scheduling
4155 ; LDR instructions than we can with LDM.
4156 ; This pattern will only match if the one above did not.
4158 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4159 (match_operand:ANY64 1 "const_double_operand" ""))]
4160 "TARGET_ARM && reload_completed
4161 && arm_const_double_by_parts (operands[1])"
4162 [(set (match_dup 0) (match_dup 1))
4163 (set (match_dup 2) (match_dup 3))]
4165 operands[2] = gen_highpart (SImode, operands[0]);
4166 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4168 operands[0] = gen_lowpart (SImode, operands[0]);
4169 operands[1] = gen_lowpart (SImode, operands[1]);
4174 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4175 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4176 "TARGET_EITHER && reload_completed"
4177 [(set (match_dup 0) (match_dup 1))
4178 (set (match_dup 2) (match_dup 3))]
4180 operands[2] = gen_highpart (SImode, operands[0]);
4181 operands[3] = gen_highpart (SImode, operands[1]);
4182 operands[0] = gen_lowpart (SImode, operands[0]);
4183 operands[1] = gen_lowpart (SImode, operands[1]);
4185 /* Handle a partial overlap. */
4186 if (rtx_equal_p (operands[0], operands[3]))
4188 rtx tmp0 = operands[0];
4189 rtx tmp1 = operands[1];
4191 operands[0] = operands[2];
4192 operands[1] = operands[3];
4199 ;; We can't actually do base+index doubleword loads if the index and
4200 ;; destination overlap. Split here so that we at least have chance to
4203 [(set (match_operand:DI 0 "s_register_operand" "")
4204 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4205 (match_operand:SI 2 "s_register_operand" ""))))]
4207 && reg_overlap_mentioned_p (operands[0], operands[1])
4208 && reg_overlap_mentioned_p (operands[0], operands[2])"
4210 (plus:SI (match_dup 1)
4213 (mem:DI (match_dup 4)))]
4215 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4219 ;;; ??? This should have alternatives for constants.
4220 ;;; ??? This was originally identical to the movdf_insn pattern.
4221 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4222 ;;; thumb_reorg with a memory reference.
4223 (define_insn "*thumb_movdi_insn"
4224 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4225 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
4227 && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4228 && ( register_operand (operands[0], DImode)
4229 || register_operand (operands[1], DImode))"
4232 switch (which_alternative)
4236 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4237 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4238 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4240 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4242 operands[1] = GEN_INT (- INTVAL (operands[1]));
4243 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4245 return \"ldmia\\t%1, {%0, %H0}\";
4247 return \"stmia\\t%0, {%1, %H1}\";
4249 return thumb_load_double_from_address (operands);
4251 operands[2] = gen_rtx_MEM (SImode,
4252 plus_constant (XEXP (operands[0], 0), 4));
4253 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4256 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4257 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4258 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4261 [(set_attr "length" "4,4,6,2,2,6,4,4")
4262 (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4263 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4266 (define_expand "movsi"
4267 [(set (match_operand:SI 0 "general_operand" "")
4268 (match_operand:SI 1 "general_operand" ""))]
4273 /* Everything except mem = const or mem = mem can be done easily. */
4274 if (GET_CODE (operands[0]) == MEM)
4275 operands[1] = force_reg (SImode, operands[1]);
4276 if (arm_general_register_operand (operands[0], SImode)
4277 && GET_CODE (operands[1]) == CONST_INT
4278 && !(const_ok_for_arm (INTVAL (operands[1]))
4279 || const_ok_for_arm (~INTVAL (operands[1]))))
4281 arm_split_constant (SET, SImode, NULL_RTX,
4282 INTVAL (operands[1]), operands[0], NULL_RTX,
4283 optimize && !no_new_pseudos);
4287 else /* TARGET_THUMB.... */
4289 if (!no_new_pseudos)
4291 if (GET_CODE (operands[0]) != REG)
4292 operands[1] = force_reg (SImode, operands[1]);
4296 /* Recognize the case where operand[1] is a reference to thread-local
4297 data and load its address to a register. */
4298 if (arm_tls_referenced_p (operands[1]))
4300 rtx tmp = operands[1];
4303 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4305 addend = XEXP (XEXP (tmp, 0), 1);
4306 tmp = XEXP (XEXP (tmp, 0), 0);
4309 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4310 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4312 tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4315 tmp = gen_rtx_PLUS (SImode, tmp, addend);
4316 tmp = force_operand (tmp, operands[0]);
4321 && (CONSTANT_P (operands[1])
4322 || symbol_mentioned_p (operands[1])
4323 || label_mentioned_p (operands[1])))
4324 operands[1] = legitimize_pic_address (operands[1], SImode,
4325 (no_new_pseudos ? operands[0] : 0));
4329 (define_insn "*arm_movsi_insn"
4330 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4331 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4332 "TARGET_ARM && ! TARGET_IWMMXT
4333 && !(TARGET_HARD_FLOAT && TARGET_VFP)
4334 && ( register_operand (operands[0], SImode)
4335 || register_operand (operands[1], SImode))"
4341 [(set_attr "type" "*,*,load1,store1")
4342 (set_attr "predicable" "yes")
4343 (set_attr "pool_range" "*,*,4096,*")
4344 (set_attr "neg_pool_range" "*,*,4084,*")]
4348 [(set (match_operand:SI 0 "arm_general_register_operand" "")
4349 (match_operand:SI 1 "const_int_operand" ""))]
4351 && (!(const_ok_for_arm (INTVAL (operands[1]))
4352 || const_ok_for_arm (~INTVAL (operands[1]))))"
4353 [(clobber (const_int 0))]
4355 arm_split_constant (SET, SImode, NULL_RTX,
4356 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4361 (define_insn "*thumb_movsi_insn"
4362 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4363 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4365 && ( register_operand (operands[0], SImode)
4366 || register_operand (operands[1], SImode))"
4377 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4378 (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4379 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4383 [(set (match_operand:SI 0 "register_operand" "")
4384 (match_operand:SI 1 "const_int_operand" ""))]
4385 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4386 [(set (match_dup 0) (match_dup 1))
4387 (set (match_dup 0) (neg:SI (match_dup 0)))]
4388 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4392 [(set (match_operand:SI 0 "register_operand" "")
4393 (match_operand:SI 1 "const_int_operand" ""))]
4394 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4395 [(set (match_dup 0) (match_dup 1))
4396 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4399 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4400 unsigned HOST_WIDE_INT mask = 0xff;
4403 for (i = 0; i < 25; i++)
4404 if ((val & (mask << i)) == val)
4407 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4411 operands[1] = GEN_INT (val >> i);
4412 operands[2] = GEN_INT (i);
4416 ;; When generating pic, we need to load the symbol offset into a register.
4417 ;; So that the optimizer does not confuse this with a normal symbol load
4418 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4419 ;; since that is the only type of relocation we can use.
4421 ;; The rather odd constraints on the following are to force reload to leave
4422 ;; the insn alone, and to force the minipool generation pass to then move
4423 ;; the GOT symbol to memory.
4425 (define_insn "pic_load_addr_arm"
4426 [(set (match_operand:SI 0 "s_register_operand" "=r")
4427 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4428 "TARGET_ARM && flag_pic"
4430 [(set_attr "type" "load1")
4431 (set (attr "pool_range") (const_int 4096))
4432 (set (attr "neg_pool_range") (const_int 4084))]
4435 (define_insn "pic_load_addr_thumb"
4436 [(set (match_operand:SI 0 "s_register_operand" "=l")
4437 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4438 "TARGET_THUMB && flag_pic"
4440 [(set_attr "type" "load1")
4441 (set (attr "pool_range") (const_int 1024))]
4444 ;; This variant is used for AOF assembly, since it needs to mention the
4445 ;; pic register in the rtl.
4446 (define_expand "pic_load_addr_based"
4447 [(set (match_operand:SI 0 "s_register_operand" "")
4448 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4449 "TARGET_ARM && flag_pic"
4450 "operands[2] = cfun->machine->pic_reg;"
4453 (define_insn "*pic_load_addr_based_insn"
4454 [(set (match_operand:SI 0 "s_register_operand" "=r")
4455 (unspec:SI [(match_operand 1 "" "")
4456 (match_operand 2 "s_register_operand" "r")]
4458 "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4460 #ifdef AOF_ASSEMBLER
4461 operands[1] = aof_pic_entry (operands[1]);
4463 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4466 [(set_attr "type" "load1")
4467 (set (attr "pool_range")
4468 (if_then_else (eq_attr "is_thumb" "yes")
4471 (set (attr "neg_pool_range")
4472 (if_then_else (eq_attr "is_thumb" "yes")
4477 (define_insn "pic_add_dot_plus_four"
4478 [(set (match_operand:SI 0 "register_operand" "=r")
4479 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4480 (const (plus:SI (pc) (const_int 4))))]
4482 (use (match_operand 2 "" ""))]
4485 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4486 INTVAL (operands[2]));
4487 return \"add\\t%0, %|pc\";
4489 [(set_attr "length" "2")]
4492 (define_insn "pic_add_dot_plus_eight"
4493 [(set (match_operand:SI 0 "register_operand" "=r")
4494 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4495 (const (plus:SI (pc) (const_int 8))))]
4497 (use (match_operand 2 "" ""))]
4500 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4501 INTVAL (operands[2]));
4502 return \"add%?\\t%0, %|pc, %1\";
4504 [(set_attr "predicable" "yes")]
4507 (define_insn "tls_load_dot_plus_eight"
4508 [(set (match_operand:SI 0 "register_operand" "+r")
4509 (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4510 (const (plus:SI (pc) (const_int 8))))]
4512 (use (match_operand 2 "" ""))]
4515 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4516 INTVAL (operands[2]));
4517 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4519 [(set_attr "predicable" "yes")]
4522 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4523 ;; followed by a load. These sequences can be crunched down to
4524 ;; tls_load_dot_plus_eight by a peephole.
4527 [(parallel [(set (match_operand:SI 0 "register_operand" "")
4528 (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4529 (const (plus:SI (pc) (const_int 8))))]
4531 (use (label_ref (match_operand 1 "" "")))])
4532 (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4533 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4534 [(parallel [(set (match_dup 2)
4535 (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4536 (const (plus:SI (pc) (const_int 8))))]
4538 (use (label_ref (match_dup 1)))])]
4542 (define_expand "builtin_setjmp_receiver"
4543 [(label_ref (match_operand 0 "" ""))]
4547 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4549 if (arm_pic_register != INVALID_REGNUM)
4550 arm_load_pic_register (1UL << 3);
4554 ;; If copying one reg to another we can set the condition codes according to
4555 ;; its value. Such a move is common after a return from subroutine and the
4556 ;; result is being tested against zero.
4558 (define_insn "*movsi_compare0"
4559 [(set (reg:CC CC_REGNUM)
4560 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4562 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4567 sub%?s\\t%0, %1, #0"
4568 [(set_attr "conds" "set")]
4571 ;; Subroutine to store a half word from a register into memory.
4572 ;; Operand 0 is the source register (HImode)
4573 ;; Operand 1 is the destination address in a register (SImode)
4575 ;; In both this routine and the next, we must be careful not to spill
4576 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4577 ;; can generate unrecognizable rtl.
4579 (define_expand "storehi"
4580 [;; store the low byte
4581 (set (match_operand 1 "" "") (match_dup 3))
4582 ;; extract the high byte
4584 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4585 ;; store the high byte
4586 (set (match_dup 4) (match_dup 5))]
4590 rtx op1 = operands[1];
4591 rtx addr = XEXP (op1, 0);
4592 enum rtx_code code = GET_CODE (addr);
4594 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4596 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4598 operands[4] = adjust_address (op1, QImode, 1);
4599 operands[1] = adjust_address (operands[1], QImode, 0);
4600 operands[3] = gen_lowpart (QImode, operands[0]);
4601 operands[0] = gen_lowpart (SImode, operands[0]);
4602 operands[2] = gen_reg_rtx (SImode);
4603 operands[5] = gen_lowpart (QImode, operands[2]);
4607 (define_expand "storehi_bigend"
4608 [(set (match_dup 4) (match_dup 3))
4610 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4611 (set (match_operand 1 "" "") (match_dup 5))]
4615 rtx op1 = operands[1];
4616 rtx addr = XEXP (op1, 0);
4617 enum rtx_code code = GET_CODE (addr);
4619 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4621 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4623 operands[4] = adjust_address (op1, QImode, 1);
4624 operands[1] = adjust_address (operands[1], QImode, 0);
4625 operands[3] = gen_lowpart (QImode, operands[0]);
4626 operands[0] = gen_lowpart (SImode, operands[0]);
4627 operands[2] = gen_reg_rtx (SImode);
4628 operands[5] = gen_lowpart (QImode, operands[2]);
4632 ;; Subroutine to store a half word integer constant into memory.
4633 (define_expand "storeinthi"
4634 [(set (match_operand 0 "" "")
4635 (match_operand 1 "" ""))
4636 (set (match_dup 3) (match_dup 2))]
4640 HOST_WIDE_INT value = INTVAL (operands[1]);
4641 rtx addr = XEXP (operands[0], 0);
4642 rtx op0 = operands[0];
4643 enum rtx_code code = GET_CODE (addr);
4645 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4647 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4649 operands[1] = gen_reg_rtx (SImode);
4650 if (BYTES_BIG_ENDIAN)
4652 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4653 if ((value & 255) == ((value >> 8) & 255))
4654 operands[2] = operands[1];
4657 operands[2] = gen_reg_rtx (SImode);
4658 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4663 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4664 if ((value & 255) == ((value >> 8) & 255))
4665 operands[2] = operands[1];
4668 operands[2] = gen_reg_rtx (SImode);
4669 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4673 operands[3] = adjust_address (op0, QImode, 1);
4674 operands[0] = adjust_address (operands[0], QImode, 0);
4675 operands[2] = gen_lowpart (QImode, operands[2]);
4676 operands[1] = gen_lowpart (QImode, operands[1]);
4680 (define_expand "storehi_single_op"
4681 [(set (match_operand:HI 0 "memory_operand" "")
4682 (match_operand:HI 1 "general_operand" ""))]
4683 "TARGET_ARM && arm_arch4"
4685 if (!s_register_operand (operands[1], HImode))
4686 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4690 (define_expand "movhi"
4691 [(set (match_operand:HI 0 "general_operand" "")
4692 (match_operand:HI 1 "general_operand" ""))]
4697 if (!no_new_pseudos)
4699 if (GET_CODE (operands[0]) == MEM)
4703 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4706 if (GET_CODE (operands[1]) == CONST_INT)
4707 emit_insn (gen_storeinthi (operands[0], operands[1]));
4710 if (GET_CODE (operands[1]) == MEM)
4711 operands[1] = force_reg (HImode, operands[1]);
4712 if (BYTES_BIG_ENDIAN)
4713 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4715 emit_insn (gen_storehi (operands[1], operands[0]));
4719 /* Sign extend a constant, and keep it in an SImode reg. */
4720 else if (GET_CODE (operands[1]) == CONST_INT)
4722 rtx reg = gen_reg_rtx (SImode);
4723 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4725 /* If the constant is already valid, leave it alone. */
4726 if (!const_ok_for_arm (val))
4728 /* If setting all the top bits will make the constant
4729 loadable in a single instruction, then set them.
4730 Otherwise, sign extend the number. */
4732 if (const_ok_for_arm (~(val | ~0xffff)))
4734 else if (val & 0x8000)
4738 emit_insn (gen_movsi (reg, GEN_INT (val)));
4739 operands[1] = gen_lowpart (HImode, reg);
4741 else if (arm_arch4 && optimize && !no_new_pseudos
4742 && GET_CODE (operands[1]) == MEM)
4744 rtx reg = gen_reg_rtx (SImode);
4746 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4747 operands[1] = gen_lowpart (HImode, reg);
4749 else if (!arm_arch4)
4751 if (GET_CODE (operands[1]) == MEM)
4754 rtx offset = const0_rtx;
4755 rtx reg = gen_reg_rtx (SImode);
4757 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4758 || (GET_CODE (base) == PLUS
4759 && (GET_CODE (offset = XEXP (base, 1))
4761 && ((INTVAL(offset) & 1) != 1)
4762 && GET_CODE (base = XEXP (base, 0)) == REG))
4763 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4767 new = widen_memory_access (operands[1], SImode,
4768 ((INTVAL (offset) & ~3)
4769 - INTVAL (offset)));
4770 emit_insn (gen_movsi (reg, new));
4771 if (((INTVAL (offset) & 2) != 0)
4772 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4774 rtx reg2 = gen_reg_rtx (SImode);
4776 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4781 emit_insn (gen_movhi_bytes (reg, operands[1]));
4783 operands[1] = gen_lowpart (HImode, reg);
4787 /* Handle loading a large integer during reload. */
4788 else if (GET_CODE (operands[1]) == CONST_INT
4789 && !const_ok_for_arm (INTVAL (operands[1]))
4790 && !const_ok_for_arm (~INTVAL (operands[1])))
4792 /* Writing a constant to memory needs a scratch, which should
4793 be handled with SECONDARY_RELOADs. */
4794 gcc_assert (GET_CODE (operands[0]) == REG);
4796 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4797 emit_insn (gen_movsi (operands[0], operands[1]));
4801 else /* TARGET_THUMB */
4803 if (!no_new_pseudos)
4805 if (GET_CODE (operands[1]) == CONST_INT)
4807 rtx reg = gen_reg_rtx (SImode);
4809 emit_insn (gen_movsi (reg, operands[1]));
4810 operands[1] = gen_lowpart (HImode, reg);
4813 /* ??? We shouldn't really get invalid addresses here, but this can
4814 happen if we are passed a SP (never OK for HImode/QImode) or
4815 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4816 HImode/QImode) relative address. */
4817 /* ??? This should perhaps be fixed elsewhere, for instance, in
4818 fixup_stack_1, by checking for other kinds of invalid addresses,
4819 e.g. a bare reference to a virtual register. This may confuse the
4820 alpha though, which must handle this case differently. */
4821 if (GET_CODE (operands[0]) == MEM
4822 && !memory_address_p (GET_MODE (operands[0]),
4823 XEXP (operands[0], 0)))
4825 = replace_equiv_address (operands[0],
4826 copy_to_reg (XEXP (operands[0], 0)));
4828 if (GET_CODE (operands[1]) == MEM
4829 && !memory_address_p (GET_MODE (operands[1]),
4830 XEXP (operands[1], 0)))
4832 = replace_equiv_address (operands[1],
4833 copy_to_reg (XEXP (operands[1], 0)));
4835 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4837 rtx reg = gen_reg_rtx (SImode);
4839 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4840 operands[1] = gen_lowpart (HImode, reg);
4843 if (GET_CODE (operands[0]) == MEM)
4844 operands[1] = force_reg (HImode, operands[1]);
4846 else if (GET_CODE (operands[1]) == CONST_INT
4847 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4849 /* Handle loading a large integer during reload. */
4851 /* Writing a constant to memory needs a scratch, which should
4852 be handled with SECONDARY_RELOADs. */
4853 gcc_assert (GET_CODE (operands[0]) == REG);
4855 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4856 emit_insn (gen_movsi (operands[0], operands[1]));
4863 (define_insn "*thumb_movhi_insn"
4864 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4865 (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
4867 && ( register_operand (operands[0], HImode)
4868 || register_operand (operands[1], HImode))"
4870 switch (which_alternative)
4872 case 0: return \"add %0, %1, #0\";
4873 case 2: return \"strh %1, %0\";
4874 case 3: return \"mov %0, %1\";
4875 case 4: return \"mov %0, %1\";
4876 case 5: return \"mov %0, %1\";
4877 default: gcc_unreachable ();
4879 /* The stack pointer can end up being taken as an index register.
4880 Catch this case here and deal with it. */
4881 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4882 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4883 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4886 ops[0] = operands[0];
4887 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4889 output_asm_insn (\"mov %0, %1\", ops);
4891 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4894 return \"ldrh %0, %1\";
4896 [(set_attr "length" "2,4,2,2,2,2")
4897 (set_attr "type" "*,load1,store1,*,*,*")]
4901 (define_expand "movhi_bytes"
4902 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4904 (zero_extend:SI (match_dup 6)))
4905 (set (match_operand:SI 0 "" "")
4906 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4911 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4913 mem1 = change_address (operands[1], QImode, addr);
4914 mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4915 operands[0] = gen_lowpart (SImode, operands[0]);
4917 operands[2] = gen_reg_rtx (SImode);
4918 operands[3] = gen_reg_rtx (SImode);
4921 if (BYTES_BIG_ENDIAN)
4923 operands[4] = operands[2];
4924 operands[5] = operands[3];
4928 operands[4] = operands[3];
4929 operands[5] = operands[2];
4934 (define_expand "movhi_bigend"
4936 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4939 (ashiftrt:SI (match_dup 2) (const_int 16)))
4940 (set (match_operand:HI 0 "s_register_operand" "")
4944 operands[2] = gen_reg_rtx (SImode);
4945 operands[3] = gen_reg_rtx (SImode);
4946 operands[4] = gen_lowpart (HImode, operands[3]);
4950 ;; Pattern to recognize insn generated default case above
4951 (define_insn "*movhi_insn_arch4"
4952 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4953 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4956 && (GET_CODE (operands[1]) != CONST_INT
4957 || const_ok_for_arm (INTVAL (operands[1]))
4958 || const_ok_for_arm (~INTVAL (operands[1])))"
4960 mov%?\\t%0, %1\\t%@ movhi
4961 mvn%?\\t%0, #%B1\\t%@ movhi
4962 str%?h\\t%1, %0\\t%@ movhi
4963 ldr%?h\\t%0, %1\\t%@ movhi"
4964 [(set_attr "type" "*,*,store1,load1")
4965 (set_attr "predicable" "yes")
4966 (set_attr "pool_range" "*,*,*,256")
4967 (set_attr "neg_pool_range" "*,*,*,244")]
4970 (define_insn "*movhi_bytes"
4971 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4972 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4975 mov%?\\t%0, %1\\t%@ movhi
4976 mvn%?\\t%0, #%B1\\t%@ movhi"
4977 [(set_attr "predicable" "yes")]
4980 (define_expand "thumb_movhi_clobber"
4981 [(set (match_operand:HI 0 "memory_operand" "")
4982 (match_operand:HI 1 "register_operand" ""))
4983 (clobber (match_operand:DI 2 "register_operand" ""))]
4986 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4987 && REGNO (operands[1]) <= LAST_LO_REGNUM)
4989 emit_insn (gen_movhi (operands[0], operands[1]));
4992 /* XXX Fixme, need to handle other cases here as well. */
4997 ;; We use a DImode scratch because we may occasionally need an additional
4998 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4999 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5000 (define_expand "reload_outhi"
5001 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5002 (match_operand:HI 1 "s_register_operand" "r")
5003 (match_operand:DI 2 "s_register_operand" "=&l")])]
5006 arm_reload_out_hi (operands);
5008 thumb_reload_out_hi (operands);
5013 (define_expand "reload_inhi"
5014 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5015 (match_operand:HI 1 "arm_reload_memory_operand" "o")
5016 (match_operand:DI 2 "s_register_operand" "=&r")])]
5020 arm_reload_in_hi (operands);
5022 thumb_reload_out_hi (operands);
5026 (define_expand "movqi"
5027 [(set (match_operand:QI 0 "general_operand" "")
5028 (match_operand:QI 1 "general_operand" ""))]
5031 /* Everything except mem = const or mem = mem can be done easily */
5033 if (!no_new_pseudos)
5035 if (GET_CODE (operands[1]) == CONST_INT)
5037 rtx reg = gen_reg_rtx (SImode);
5039 emit_insn (gen_movsi (reg, operands[1]));
5040 operands[1] = gen_lowpart (QImode, reg);
5045 /* ??? We shouldn't really get invalid addresses here, but this can
5046 happen if we are passed a SP (never OK for HImode/QImode) or
5047 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5048 HImode/QImode) relative address. */
5049 /* ??? This should perhaps be fixed elsewhere, for instance, in
5050 fixup_stack_1, by checking for other kinds of invalid addresses,
5051 e.g. a bare reference to a virtual register. This may confuse the
5052 alpha though, which must handle this case differently. */
5053 if (GET_CODE (operands[0]) == MEM
5054 && !memory_address_p (GET_MODE (operands[0]),
5055 XEXP (operands[0], 0)))
5057 = replace_equiv_address (operands[0],
5058 copy_to_reg (XEXP (operands[0], 0)));
5059 if (GET_CODE (operands[1]) == MEM
5060 && !memory_address_p (GET_MODE (operands[1]),
5061 XEXP (operands[1], 0)))
5063 = replace_equiv_address (operands[1],
5064 copy_to_reg (XEXP (operands[1], 0)));
5067 if (GET_CODE (operands[1]) == MEM && optimize > 0)
5069 rtx reg = gen_reg_rtx (SImode);
5071 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5072 operands[1] = gen_lowpart (QImode, reg);
5075 if (GET_CODE (operands[0]) == MEM)
5076 operands[1] = force_reg (QImode, operands[1]);
5078 else if (TARGET_THUMB
5079 && GET_CODE (operands[1]) == CONST_INT
5080 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5082 /* Handle loading a large integer during reload. */
5084 /* Writing a constant to memory needs a scratch, which should
5085 be handled with SECONDARY_RELOADs. */
5086 gcc_assert (GET_CODE (operands[0]) == REG);
5088 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5089 emit_insn (gen_movsi (operands[0], operands[1]));
5096 (define_insn "*arm_movqi_insn"
5097 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5098 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5100 && ( register_operand (operands[0], QImode)
5101 || register_operand (operands[1], QImode))"
5107 [(set_attr "type" "*,*,load1,store1")
5108 (set_attr "predicable" "yes")]
5111 (define_insn "*thumb_movqi_insn"
5112 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5113 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
5115 && ( register_operand (operands[0], QImode)
5116 || register_operand (operands[1], QImode))"
5124 [(set_attr "length" "2")
5125 (set_attr "type" "*,load1,store1,*,*,*")
5126 (set_attr "pool_range" "*,32,*,*,*,*")]
5129 (define_expand "movsf"
5130 [(set (match_operand:SF 0 "general_operand" "")
5131 (match_operand:SF 1 "general_operand" ""))]
5136 if (GET_CODE (operands[0]) == MEM)
5137 operands[1] = force_reg (SFmode, operands[1]);
5139 else /* TARGET_THUMB */
5141 if (!no_new_pseudos)
5143 if (GET_CODE (operands[0]) != REG)
5144 operands[1] = force_reg (SFmode, operands[1]);
5150 ;; Transform a floating-point move of a constant into a core register into
5151 ;; an SImode operation.
5153 [(set (match_operand:SF 0 "arm_general_register_operand" "")
5154 (match_operand:SF 1 "immediate_operand" ""))]
5157 && GET_CODE (operands[1]) == CONST_DOUBLE"
5158 [(set (match_dup 2) (match_dup 3))]
5160 operands[2] = gen_lowpart (SImode, operands[0]);
5161 operands[3] = gen_lowpart (SImode, operands[1]);
5162 if (operands[2] == 0 || operands[3] == 0)
5167 (define_insn "*arm_movsf_soft_insn"
5168 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5169 (match_operand:SF 1 "general_operand" "r,mE,r"))]
5171 && TARGET_SOFT_FLOAT
5172 && (GET_CODE (operands[0]) != MEM
5173 || register_operand (operands[1], SFmode))"
5176 ldr%?\\t%0, %1\\t%@ float
5177 str%?\\t%1, %0\\t%@ float"
5178 [(set_attr "length" "4,4,4")
5179 (set_attr "predicable" "yes")
5180 (set_attr "type" "*,load1,store1")
5181 (set_attr "pool_range" "*,4096,*")
5182 (set_attr "neg_pool_range" "*,4084,*")]
5185 ;;; ??? This should have alternatives for constants.
5186 (define_insn "*thumb_movsf_insn"
5187 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5188 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5190 && ( register_operand (operands[0], SFmode)
5191 || register_operand (operands[1], SFmode))"
5200 [(set_attr "length" "2")
5201 (set_attr "type" "*,load1,store1,load1,store1,*,*")
5202 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5205 (define_expand "movdf"
5206 [(set (match_operand:DF 0 "general_operand" "")
5207 (match_operand:DF 1 "general_operand" ""))]
5212 if (GET_CODE (operands[0]) == MEM)
5213 operands[1] = force_reg (DFmode, operands[1]);
5215 else /* TARGET_THUMB */
5217 if (!no_new_pseudos)
5219 if (GET_CODE (operands[0]) != REG)
5220 operands[1] = force_reg (DFmode, operands[1]);
5226 ;; Reloading a df mode value stored in integer regs to memory can require a
5228 (define_expand "reload_outdf"
5229 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5230 (match_operand:DF 1 "s_register_operand" "r")
5231 (match_operand:SI 2 "s_register_operand" "=&r")]
5235 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5238 operands[2] = XEXP (operands[0], 0);
5239 else if (code == POST_INC || code == PRE_DEC)
5241 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5242 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5243 emit_insn (gen_movdi (operands[0], operands[1]));
5246 else if (code == PRE_INC)
5248 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5250 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5253 else if (code == POST_DEC)
5254 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5256 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5257 XEXP (XEXP (operands[0], 0), 1)));
5259 emit_insn (gen_rtx_SET (VOIDmode,
5260 replace_equiv_address (operands[0], operands[2]),
5263 if (code == POST_DEC)
5264 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5270 (define_insn "*movdf_soft_insn"
5271 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5272 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5273 "TARGET_ARM && TARGET_SOFT_FLOAT
5274 && ( register_operand (operands[0], DFmode)
5275 || register_operand (operands[1], DFmode))"
5277 switch (which_alternative)
5284 return output_move_double (operands);
5287 [(set_attr "length" "8,12,16,8,8")
5288 (set_attr "type" "*,*,*,load2,store2")
5289 (set_attr "pool_range" "1020")
5290 (set_attr "neg_pool_range" "1008")]
5293 ;;; ??? This should have alternatives for constants.
5294 ;;; ??? This was originally identical to the movdi_insn pattern.
5295 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5296 ;;; thumb_reorg with a memory reference.
5297 (define_insn "*thumb_movdf_insn"
5298 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5299 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5301 && ( register_operand (operands[0], DFmode)
5302 || register_operand (operands[1], DFmode))"
5304 switch (which_alternative)
5308 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5309 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5310 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5312 return \"ldmia\\t%1, {%0, %H0}\";
5314 return \"stmia\\t%0, {%1, %H1}\";
5316 return thumb_load_double_from_address (operands);
5318 operands[2] = gen_rtx_MEM (SImode,
5319 plus_constant (XEXP (operands[0], 0), 4));
5320 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5323 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5324 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5325 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5328 [(set_attr "length" "4,2,2,6,4,4")
5329 (set_attr "type" "*,load2,store2,load2,store2,*")
5330 (set_attr "pool_range" "*,*,*,1020,*,*")]
5333 (define_expand "movxf"
5334 [(set (match_operand:XF 0 "general_operand" "")
5335 (match_operand:XF 1 "general_operand" ""))]
5336 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5338 if (GET_CODE (operands[0]) == MEM)
5339 operands[1] = force_reg (XFmode, operands[1]);
5344 (define_expand "movv2si"
5345 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5346 (match_operand:V2SI 1 "general_operand" ""))]
5347 "TARGET_REALLY_IWMMXT"
5351 (define_expand "movv4hi"
5352 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5353 (match_operand:V4HI 1 "general_operand" ""))]
5354 "TARGET_REALLY_IWMMXT"
5358 (define_expand "movv8qi"
5359 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5360 (match_operand:V8QI 1 "general_operand" ""))]
5361 "TARGET_REALLY_IWMMXT"
5366 ;; load- and store-multiple insns
5367 ;; The arm can load/store any set of registers, provided that they are in
5368 ;; ascending order; but that is beyond GCC so stick with what it knows.
5370 (define_expand "load_multiple"
5371 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372 (match_operand:SI 1 "" ""))
5373 (use (match_operand:SI 2 "" ""))])]
5376 HOST_WIDE_INT offset = 0;
5378 /* Support only fixed point registers. */
5379 if (GET_CODE (operands[2]) != CONST_INT
5380 || INTVAL (operands[2]) > 14
5381 || INTVAL (operands[2]) < 2
5382 || GET_CODE (operands[1]) != MEM
5383 || GET_CODE (operands[0]) != REG
5384 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5385 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5389 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5390 force_reg (SImode, XEXP (operands[1], 0)),
5391 TRUE, FALSE, operands[1], &offset);
5394 ;; Load multiple with write-back
5396 (define_insn "*ldmsi_postinc4"
5397 [(match_parallel 0 "load_multiple_operation"
5398 [(set (match_operand:SI 1 "s_register_operand" "=r")
5399 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5402 (mem:SI (match_dup 2)))
5403 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5404 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5405 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5406 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5407 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5408 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5409 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5410 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5411 [(set_attr "type" "load4")
5412 (set_attr "predicable" "yes")]
5415 (define_insn "*ldmsi_postinc4_thumb"
5416 [(match_parallel 0 "load_multiple_operation"
5417 [(set (match_operand:SI 1 "s_register_operand" "=l")
5418 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5420 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5421 (mem:SI (match_dup 2)))
5422 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5423 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5424 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5425 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5426 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5427 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5428 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5429 "ldmia\\t%1!, {%3, %4, %5, %6}"
5430 [(set_attr "type" "load4")]
5433 (define_insn "*ldmsi_postinc3"
5434 [(match_parallel 0 "load_multiple_operation"
5435 [(set (match_operand:SI 1 "s_register_operand" "=r")
5436 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5438 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439 (mem:SI (match_dup 2)))
5440 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5442 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5444 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445 "ldm%?ia\\t%1!, {%3, %4, %5}"
5446 [(set_attr "type" "load3")
5447 (set_attr "predicable" "yes")]
5450 (define_insn "*ldmsi_postinc2"
5451 [(match_parallel 0 "load_multiple_operation"
5452 [(set (match_operand:SI 1 "s_register_operand" "=r")
5453 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5455 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456 (mem:SI (match_dup 2)))
5457 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5459 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460 "ldm%?ia\\t%1!, {%3, %4}"
5461 [(set_attr "type" "load2")
5462 (set_attr "predicable" "yes")]
5465 ;; Ordinary load multiple
5467 (define_insn "*ldmsi4"
5468 [(match_parallel 0 "load_multiple_operation"
5469 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5470 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5471 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5472 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5473 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5474 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5475 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5476 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5477 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5478 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5479 [(set_attr "type" "load4")
5480 (set_attr "predicable" "yes")]
5483 (define_insn "*ldmsi3"
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 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5490 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5491 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5492 "ldm%?ia\\t%1, {%2, %3, %4}"
5493 [(set_attr "type" "load3")
5494 (set_attr "predicable" "yes")]
5497 (define_insn "*ldmsi2"
5498 [(match_parallel 0 "load_multiple_operation"
5499 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5500 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5501 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5502 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5503 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5504 "ldm%?ia\\t%1, {%2, %3}"
5505 [(set_attr "type" "load2")
5506 (set_attr "predicable" "yes")]
5509 (define_expand "store_multiple"
5510 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5511 (match_operand:SI 1 "" ""))
5512 (use (match_operand:SI 2 "" ""))])]
5515 HOST_WIDE_INT offset = 0;
5517 /* Support only fixed point registers. */
5518 if (GET_CODE (operands[2]) != CONST_INT
5519 || INTVAL (operands[2]) > 14
5520 || INTVAL (operands[2]) < 2
5521 || GET_CODE (operands[1]) != REG
5522 || GET_CODE (operands[0]) != MEM
5523 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5524 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5528 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5529 force_reg (SImode, XEXP (operands[0], 0)),
5530 TRUE, FALSE, operands[0], &offset);
5533 ;; Store multiple with write-back
5535 (define_insn "*stmsi_postinc4"
5536 [(match_parallel 0 "store_multiple_operation"
5537 [(set (match_operand:SI 1 "s_register_operand" "=r")
5538 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5540 (set (mem:SI (match_dup 2))
5541 (match_operand:SI 3 "arm_hard_register_operand" ""))
5542 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543 (match_operand:SI 4 "arm_hard_register_operand" ""))
5544 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5545 (match_operand:SI 5 "arm_hard_register_operand" ""))
5546 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5547 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5548 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5549 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5550 [(set_attr "predicable" "yes")
5551 (set_attr "type" "store4")]
5554 (define_insn "*stmsi_postinc4_thumb"
5555 [(match_parallel 0 "store_multiple_operation"
5556 [(set (match_operand:SI 1 "s_register_operand" "=l")
5557 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5559 (set (mem:SI (match_dup 2))
5560 (match_operand:SI 3 "arm_hard_register_operand" ""))
5561 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5562 (match_operand:SI 4 "arm_hard_register_operand" ""))
5563 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5564 (match_operand:SI 5 "arm_hard_register_operand" ""))
5565 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5566 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5567 "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5568 "stmia\\t%1!, {%3, %4, %5, %6}"
5569 [(set_attr "type" "store4")]
5572 (define_insn "*stmsi_postinc3"
5573 [(match_parallel 0 "store_multiple_operation"
5574 [(set (match_operand:SI 1 "s_register_operand" "=r")
5575 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5577 (set (mem:SI (match_dup 2))
5578 (match_operand:SI 3 "arm_hard_register_operand" ""))
5579 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5580 (match_operand:SI 4 "arm_hard_register_operand" ""))
5581 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5582 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584 "stm%?ia\\t%1!, {%3, %4, %5}"
5585 [(set_attr "predicable" "yes")
5586 (set_attr "type" "store3")]
5589 (define_insn "*stmsi_postinc2"
5590 [(match_parallel 0 "store_multiple_operation"
5591 [(set (match_operand:SI 1 "s_register_operand" "=r")
5592 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5594 (set (mem:SI (match_dup 2))
5595 (match_operand:SI 3 "arm_hard_register_operand" ""))
5596 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5597 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599 "stm%?ia\\t%1!, {%3, %4}"
5600 [(set_attr "predicable" "yes")
5601 (set_attr "type" "store2")]
5604 ;; Ordinary store multiple
5606 (define_insn "*stmsi4"
5607 [(match_parallel 0 "store_multiple_operation"
5608 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5609 (match_operand:SI 2 "arm_hard_register_operand" ""))
5610 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5611 (match_operand:SI 3 "arm_hard_register_operand" ""))
5612 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5613 (match_operand:SI 4 "arm_hard_register_operand" ""))
5614 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5615 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5616 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5617 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5618 [(set_attr "predicable" "yes")
5619 (set_attr "type" "store4")]
5622 (define_insn "*stmsi3"
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 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5629 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5630 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5631 "stm%?ia\\t%1, {%2, %3, %4}"
5632 [(set_attr "predicable" "yes")
5633 (set_attr "type" "store3")]
5636 (define_insn "*stmsi2"
5637 [(match_parallel 0 "store_multiple_operation"
5638 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5639 (match_operand:SI 2 "arm_hard_register_operand" ""))
5640 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5641 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5642 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5643 "stm%?ia\\t%1, {%2, %3}"
5644 [(set_attr "predicable" "yes")
5645 (set_attr "type" "store2")]
5648 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5649 ;; We could let this apply for blocks of less than this, but it clobbers so
5650 ;; many registers that there is then probably a better way.
5652 (define_expand "movmemqi"
5653 [(match_operand:BLK 0 "general_operand" "")
5654 (match_operand:BLK 1 "general_operand" "")
5655 (match_operand:SI 2 "const_int_operand" "")
5656 (match_operand:SI 3 "const_int_operand" "")]
5661 if (arm_gen_movmemqi (operands))
5665 else /* TARGET_THUMB */
5667 if ( INTVAL (operands[3]) != 4
5668 || INTVAL (operands[2]) > 48)
5671 thumb_expand_movmemqi (operands);
5677 ;; Thumb block-move insns
5679 (define_insn "movmem12b"
5680 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5681 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5682 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5683 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5684 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5685 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5686 (set (match_operand:SI 0 "register_operand" "=l")
5687 (plus:SI (match_dup 2) (const_int 12)))
5688 (set (match_operand:SI 1 "register_operand" "=l")
5689 (plus:SI (match_dup 3) (const_int 12)))
5690 (clobber (match_scratch:SI 4 "=&l"))
5691 (clobber (match_scratch:SI 5 "=&l"))
5692 (clobber (match_scratch:SI 6 "=&l"))]
5694 "* return thumb_output_move_mem_multiple (3, operands);"
5695 [(set_attr "length" "4")
5696 ; This isn't entirely accurate... It loads as well, but in terms of
5697 ; scheduling the following insn it is better to consider it as a store
5698 (set_attr "type" "store3")]
5701 (define_insn "movmem8b"
5702 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5703 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5704 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5705 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5706 (set (match_operand:SI 0 "register_operand" "=l")
5707 (plus:SI (match_dup 2) (const_int 8)))
5708 (set (match_operand:SI 1 "register_operand" "=l")
5709 (plus:SI (match_dup 3) (const_int 8)))
5710 (clobber (match_scratch:SI 4 "=&l"))
5711 (clobber (match_scratch:SI 5 "=&l"))]
5713 "* return thumb_output_move_mem_multiple (2, operands);"
5714 [(set_attr "length" "4")
5715 ; This isn't entirely accurate... It loads as well, but in terms of
5716 ; scheduling the following insn it is better to consider it as a store
5717 (set_attr "type" "store2")]
5722 ;; Compare & branch insns
5723 ;; The range calculations are based as follows:
5724 ;; For forward branches, the address calculation returns the address of
5725 ;; the next instruction. This is 2 beyond the branch instruction.
5726 ;; For backward branches, the address calculation returns the address of
5727 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5728 ;; instruction for the shortest sequence, and 4 before the branch instruction
5729 ;; if we have to jump around an unconditional branch.
5730 ;; To the basic branch range the PC offset must be added (this is +4).
5731 ;; So for forward branches we have
5732 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5733 ;; And for backward branches we have
5734 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5736 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5737 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5739 (define_expand "cbranchsi4"
5740 [(set (pc) (if_then_else
5741 (match_operator 0 "arm_comparison_operator"
5742 [(match_operand:SI 1 "s_register_operand" "")
5743 (match_operand:SI 2 "nonmemory_operand" "")])
5744 (label_ref (match_operand 3 "" ""))
5748 if (thumb_cmpneg_operand (operands[2], SImode))
5750 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5751 operands[3], operands[0]));
5754 if (!thumb_cmp_operand (operands[2], SImode))
5755 operands[2] = force_reg (SImode, operands[2]);
5758 (define_insn "*cbranchsi4_insn"
5759 [(set (pc) (if_then_else
5760 (match_operator 0 "arm_comparison_operator"
5761 [(match_operand:SI 1 "s_register_operand" "l,*h")
5762 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5763 (label_ref (match_operand 3 "" ""))
5767 output_asm_insn (\"cmp\\t%1, %2\", operands);
5769 switch (get_attr_length (insn))
5771 case 4: return \"b%d0\\t%l3\";
5772 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5773 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5776 [(set (attr "far_jump")
5778 (eq_attr "length" "8")
5779 (const_string "yes")
5780 (const_string "no")))
5781 (set (attr "length")
5783 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5784 (le (minus (match_dup 3) (pc)) (const_int 256)))
5787 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5788 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5793 (define_insn "cbranchsi4_scratch"
5794 [(set (pc) (if_then_else
5795 (match_operator 4 "arm_comparison_operator"
5796 [(match_operand:SI 1 "s_register_operand" "l,0")
5797 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5798 (label_ref (match_operand 3 "" ""))
5800 (clobber (match_scratch:SI 0 "=l,l"))]
5803 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5805 switch (get_attr_length (insn))
5807 case 4: return \"b%d4\\t%l3\";
5808 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5809 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5812 [(set (attr "far_jump")
5814 (eq_attr "length" "8")
5815 (const_string "yes")
5816 (const_string "no")))
5817 (set (attr "length")
5819 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5820 (le (minus (match_dup 3) (pc)) (const_int 256)))
5823 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5824 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5828 (define_insn "*movsi_cbranchsi4"
5831 (match_operator 3 "arm_comparison_operator"
5832 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5834 (label_ref (match_operand 2 "" ""))
5836 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5840 if (which_alternative == 0)
5841 output_asm_insn (\"cmp\t%0, #0\", operands);
5842 else if (which_alternative == 1)
5843 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5846 output_asm_insn (\"cmp\t%1, #0\", operands);
5847 if (which_alternative == 2)
5848 output_asm_insn (\"mov\t%0, %1\", operands);
5850 output_asm_insn (\"str\t%1, %0\", operands);
5852 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5854 case 4: return \"b%d3\\t%l2\";
5855 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5856 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5859 [(set (attr "far_jump")
5861 (ior (and (gt (symbol_ref ("which_alternative"))
5863 (eq_attr "length" "8"))
5864 (eq_attr "length" "10"))
5865 (const_string "yes")
5866 (const_string "no")))
5867 (set (attr "length")
5869 (le (symbol_ref ("which_alternative"))
5872 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5873 (le (minus (match_dup 2) (pc)) (const_int 256)))
5876 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5877 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5881 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5882 (le (minus (match_dup 2) (pc)) (const_int 256)))
5885 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5886 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5891 (define_insn "*negated_cbranchsi4"
5894 (match_operator 0 "equality_operator"
5895 [(match_operand:SI 1 "s_register_operand" "l")
5896 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5897 (label_ref (match_operand 3 "" ""))
5901 output_asm_insn (\"cmn\\t%1, %2\", operands);
5902 switch (get_attr_length (insn))
5904 case 4: return \"b%d0\\t%l3\";
5905 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5906 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5909 [(set (attr "far_jump")
5911 (eq_attr "length" "8")
5912 (const_string "yes")
5913 (const_string "no")))
5914 (set (attr "length")
5916 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5917 (le (minus (match_dup 3) (pc)) (const_int 256)))
5920 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5921 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5926 (define_insn "*tbit_cbranch"
5929 (match_operator 0 "equality_operator"
5930 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5932 (match_operand:SI 2 "const_int_operand" "i"))
5934 (label_ref (match_operand 3 "" ""))
5936 (clobber (match_scratch:SI 4 "=l"))]
5941 op[0] = operands[4];
5942 op[1] = operands[1];
5943 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5945 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5946 switch (get_attr_length (insn))
5948 case 4: return \"b%d0\\t%l3\";
5949 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5950 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5953 [(set (attr "far_jump")
5955 (eq_attr "length" "8")
5956 (const_string "yes")
5957 (const_string "no")))
5958 (set (attr "length")
5960 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5961 (le (minus (match_dup 3) (pc)) (const_int 256)))
5964 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5965 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5970 (define_insn "*tstsi3_cbranch"
5973 (match_operator 3 "equality_operator"
5974 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5975 (match_operand:SI 1 "s_register_operand" "l"))
5977 (label_ref (match_operand 2 "" ""))
5982 output_asm_insn (\"tst\\t%0, %1\", operands);
5983 switch (get_attr_length (insn))
5985 case 4: return \"b%d3\\t%l2\";
5986 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5987 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5990 [(set (attr "far_jump")
5992 (eq_attr "length" "8")
5993 (const_string "yes")
5994 (const_string "no")))
5995 (set (attr "length")
5997 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5998 (le (minus (match_dup 2) (pc)) (const_int 256)))
6001 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6002 (le (minus (match_dup 2) (pc)) (const_int 2048)))
6007 (define_insn "*andsi3_cbranch"
6010 (match_operator 5 "equality_operator"
6011 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6012 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6014 (label_ref (match_operand 4 "" ""))
6016 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6017 (and:SI (match_dup 2) (match_dup 3)))
6018 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6022 if (which_alternative == 0)
6023 output_asm_insn (\"and\\t%0, %3\", operands);
6024 else if (which_alternative == 1)
6026 output_asm_insn (\"and\\t%1, %3\", operands);
6027 output_asm_insn (\"mov\\t%0, %1\", operands);
6031 output_asm_insn (\"and\\t%1, %3\", operands);
6032 output_asm_insn (\"str\\t%1, %0\", operands);
6035 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6037 case 4: return \"b%d5\\t%l4\";
6038 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6039 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6042 [(set (attr "far_jump")
6044 (ior (and (eq (symbol_ref ("which_alternative"))
6046 (eq_attr "length" "8"))
6047 (eq_attr "length" "10"))
6048 (const_string "yes")
6049 (const_string "no")))
6050 (set (attr "length")
6052 (eq (symbol_ref ("which_alternative"))
6055 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6056 (le (minus (match_dup 4) (pc)) (const_int 256)))
6059 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6060 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6064 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6065 (le (minus (match_dup 4) (pc)) (const_int 256)))
6068 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6069 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6074 (define_insn "*orrsi3_cbranch_scratch"
6077 (match_operator 4 "equality_operator"
6078 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6079 (match_operand:SI 2 "s_register_operand" "l"))
6081 (label_ref (match_operand 3 "" ""))
6083 (clobber (match_scratch:SI 0 "=l"))]
6087 output_asm_insn (\"orr\\t%0, %2\", operands);
6088 switch (get_attr_length (insn))
6090 case 4: return \"b%d4\\t%l3\";
6091 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6092 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6095 [(set (attr "far_jump")
6097 (eq_attr "length" "8")
6098 (const_string "yes")
6099 (const_string "no")))
6100 (set (attr "length")
6102 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6103 (le (minus (match_dup 3) (pc)) (const_int 256)))
6106 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6107 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6112 (define_insn "*orrsi3_cbranch"
6115 (match_operator 5 "equality_operator"
6116 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6119 (label_ref (match_operand 4 "" ""))
6121 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6122 (ior:SI (match_dup 2) (match_dup 3)))
6123 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6127 if (which_alternative == 0)
6128 output_asm_insn (\"orr\\t%0, %3\", operands);
6129 else if (which_alternative == 1)
6131 output_asm_insn (\"orr\\t%1, %3\", operands);
6132 output_asm_insn (\"mov\\t%0, %1\", operands);
6136 output_asm_insn (\"orr\\t%1, %3\", operands);
6137 output_asm_insn (\"str\\t%1, %0\", operands);
6140 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6142 case 4: return \"b%d5\\t%l4\";
6143 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6147 [(set (attr "far_jump")
6149 (ior (and (eq (symbol_ref ("which_alternative"))
6151 (eq_attr "length" "8"))
6152 (eq_attr "length" "10"))
6153 (const_string "yes")
6154 (const_string "no")))
6155 (set (attr "length")
6157 (eq (symbol_ref ("which_alternative"))
6160 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161 (le (minus (match_dup 4) (pc)) (const_int 256)))
6164 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6169 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170 (le (minus (match_dup 4) (pc)) (const_int 256)))
6173 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6179 (define_insn "*xorsi3_cbranch_scratch"
6182 (match_operator 4 "equality_operator"
6183 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6184 (match_operand:SI 2 "s_register_operand" "l"))
6186 (label_ref (match_operand 3 "" ""))
6188 (clobber (match_scratch:SI 0 "=l"))]
6192 output_asm_insn (\"eor\\t%0, %2\", operands);
6193 switch (get_attr_length (insn))
6195 case 4: return \"b%d4\\t%l3\";
6196 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6200 [(set (attr "far_jump")
6202 (eq_attr "length" "8")
6203 (const_string "yes")
6204 (const_string "no")))
6205 (set (attr "length")
6207 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208 (le (minus (match_dup 3) (pc)) (const_int 256)))
6211 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6217 (define_insn "*xorsi3_cbranch"
6220 (match_operator 5 "equality_operator"
6221 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6224 (label_ref (match_operand 4 "" ""))
6226 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6227 (xor:SI (match_dup 2) (match_dup 3)))
6228 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6232 if (which_alternative == 0)
6233 output_asm_insn (\"eor\\t%0, %3\", operands);
6234 else if (which_alternative == 1)
6236 output_asm_insn (\"eor\\t%1, %3\", operands);
6237 output_asm_insn (\"mov\\t%0, %1\", operands);
6241 output_asm_insn (\"eor\\t%1, %3\", operands);
6242 output_asm_insn (\"str\\t%1, %0\", operands);
6245 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6247 case 4: return \"b%d5\\t%l4\";
6248 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6252 [(set (attr "far_jump")
6254 (ior (and (eq (symbol_ref ("which_alternative"))
6256 (eq_attr "length" "8"))
6257 (eq_attr "length" "10"))
6258 (const_string "yes")
6259 (const_string "no")))
6260 (set (attr "length")
6262 (eq (symbol_ref ("which_alternative"))
6265 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266 (le (minus (match_dup 4) (pc)) (const_int 256)))
6269 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6274 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275 (le (minus (match_dup 4) (pc)) (const_int 256)))
6278 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6284 (define_insn "*bicsi3_cbranch_scratch"
6287 (match_operator 4 "equality_operator"
6288 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6289 (match_operand:SI 1 "s_register_operand" "0"))
6291 (label_ref (match_operand 3 "" ""))
6293 (clobber (match_scratch:SI 0 "=l"))]
6297 output_asm_insn (\"bic\\t%0, %2\", operands);
6298 switch (get_attr_length (insn))
6300 case 4: return \"b%d4\\t%l3\";
6301 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6305 [(set (attr "far_jump")
6307 (eq_attr "length" "8")
6308 (const_string "yes")
6309 (const_string "no")))
6310 (set (attr "length")
6312 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313 (le (minus (match_dup 3) (pc)) (const_int 256)))
6316 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6322 (define_insn "*bicsi3_cbranch"
6325 (match_operator 5 "equality_operator"
6326 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6327 (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6329 (label_ref (match_operand 4 "" ""))
6331 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6332 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6333 (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6337 if (which_alternative == 0)
6338 output_asm_insn (\"bic\\t%0, %3\", operands);
6339 else if (which_alternative <= 2)
6341 output_asm_insn (\"bic\\t%1, %3\", operands);
6342 /* It's ok if OP0 is a lo-reg, even though the mov will set the
6343 conditions again, since we're only testing for equality. */
6344 output_asm_insn (\"mov\\t%0, %1\", operands);
6348 output_asm_insn (\"bic\\t%1, %3\", operands);
6349 output_asm_insn (\"str\\t%1, %0\", operands);
6352 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6354 case 4: return \"b%d5\\t%l4\";
6355 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6356 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6359 [(set (attr "far_jump")
6361 (ior (and (eq (symbol_ref ("which_alternative"))
6363 (eq_attr "length" "8"))
6364 (eq_attr "length" "10"))
6365 (const_string "yes")
6366 (const_string "no")))
6367 (set (attr "length")
6369 (eq (symbol_ref ("which_alternative"))
6372 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6373 (le (minus (match_dup 4) (pc)) (const_int 256)))
6376 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6377 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6381 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6382 (le (minus (match_dup 4) (pc)) (const_int 256)))
6385 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6386 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6391 (define_insn "*cbranchne_decr1"
6393 (if_then_else (match_operator 3 "equality_operator"
6394 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6396 (label_ref (match_operand 4 "" ""))
6398 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6399 (plus:SI (match_dup 2) (const_int -1)))
6400 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6405 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6407 VOIDmode, operands[2], const1_rtx);
6408 cond[1] = operands[4];
6410 if (which_alternative == 0)
6411 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6412 else if (which_alternative == 1)
6414 /* We must provide an alternative for a hi reg because reload
6415 cannot handle output reloads on a jump instruction, but we
6416 can't subtract into that. Fortunately a mov from lo to hi
6417 does not clobber the condition codes. */
6418 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6419 output_asm_insn (\"mov\\t%0, %1\", operands);
6423 /* Similarly, but the target is memory. */
6424 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6425 output_asm_insn (\"str\\t%1, %0\", operands);
6428 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6431 output_asm_insn (\"b%d0\\t%l1\", cond);
6434 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6435 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6437 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6438 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6442 [(set (attr "far_jump")
6444 (ior (and (eq (symbol_ref ("which_alternative"))
6446 (eq_attr "length" "8"))
6447 (eq_attr "length" "10"))
6448 (const_string "yes")
6449 (const_string "no")))
6450 (set_attr_alternative "length"
6454 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6455 (le (minus (match_dup 4) (pc)) (const_int 256)))
6458 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6459 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6464 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6465 (le (minus (match_dup 4) (pc)) (const_int 256)))
6468 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6469 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6474 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6475 (le (minus (match_dup 4) (pc)) (const_int 256)))
6478 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6479 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6484 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6485 (le (minus (match_dup 4) (pc)) (const_int 256)))
6488 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6489 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6494 (define_insn "*addsi3_cbranch"
6497 (match_operator 4 "comparison_operator"
6499 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6500 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6502 (label_ref (match_operand 5 "" ""))
6505 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6506 (plus:SI (match_dup 2) (match_dup 3)))
6507 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6509 && (GET_CODE (operands[4]) == EQ
6510 || GET_CODE (operands[4]) == NE
6511 || GET_CODE (operands[4]) == GE
6512 || GET_CODE (operands[4]) == LT)"
6518 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6519 cond[1] = operands[2];
6520 cond[2] = operands[3];
6522 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6523 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6525 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6527 if (which_alternative >= 3
6528 && which_alternative < 4)
6529 output_asm_insn (\"mov\\t%0, %1\", operands);
6530 else if (which_alternative >= 4)
6531 output_asm_insn (\"str\\t%1, %0\", operands);
6533 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6536 return \"b%d4\\t%l5\";
6538 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6540 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6544 [(set (attr "far_jump")
6546 (ior (and (lt (symbol_ref ("which_alternative"))
6548 (eq_attr "length" "8"))
6549 (eq_attr "length" "10"))
6550 (const_string "yes")
6551 (const_string "no")))
6552 (set (attr "length")
6554 (lt (symbol_ref ("which_alternative"))
6557 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6558 (le (minus (match_dup 5) (pc)) (const_int 256)))
6561 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6562 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6566 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6567 (le (minus (match_dup 5) (pc)) (const_int 256)))
6570 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6571 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6576 (define_insn "*addsi3_cbranch_scratch"
6579 (match_operator 3 "comparison_operator"
6581 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6582 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6584 (label_ref (match_operand 4 "" ""))
6586 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6588 && (GET_CODE (operands[3]) == EQ
6589 || GET_CODE (operands[3]) == NE
6590 || GET_CODE (operands[3]) == GE
6591 || GET_CODE (operands[3]) == LT)"
6594 switch (which_alternative)
6597 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6600 output_asm_insn (\"cmn\t%1, %2\", operands);
6603 if (INTVAL (operands[2]) < 0)
6604 output_asm_insn (\"sub\t%0, %1, %2\", operands);
6606 output_asm_insn (\"add\t%0, %1, %2\", operands);
6609 if (INTVAL (operands[2]) < 0)
6610 output_asm_insn (\"sub\t%0, %0, %2\", operands);
6612 output_asm_insn (\"add\t%0, %0, %2\", operands);
6616 switch (get_attr_length (insn))
6619 return \"b%d3\\t%l4\";
6621 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6623 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6627 [(set (attr "far_jump")
6629 (eq_attr "length" "8")
6630 (const_string "yes")
6631 (const_string "no")))
6632 (set (attr "length")
6634 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6635 (le (minus (match_dup 4) (pc)) (const_int 256)))
6638 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6639 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6644 (define_insn "*subsi3_cbranch"
6647 (match_operator 4 "comparison_operator"
6649 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6650 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6652 (label_ref (match_operand 5 "" ""))
6654 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6655 (minus:SI (match_dup 2) (match_dup 3)))
6656 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6658 && (GET_CODE (operands[4]) == EQ
6659 || GET_CODE (operands[4]) == NE
6660 || GET_CODE (operands[4]) == GE
6661 || GET_CODE (operands[4]) == LT)"
6664 if (which_alternative == 0)
6665 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6666 else if (which_alternative == 1)
6668 /* We must provide an alternative for a hi reg because reload
6669 cannot handle output reloads on a jump instruction, but we
6670 can't subtract into that. Fortunately a mov from lo to hi
6671 does not clobber the condition codes. */
6672 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6673 output_asm_insn (\"mov\\t%0, %1\", operands);
6677 /* Similarly, but the target is memory. */
6678 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6679 output_asm_insn (\"str\\t%1, %0\", operands);
6682 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6685 return \"b%d4\\t%l5\";
6687 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6689 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6693 [(set (attr "far_jump")
6695 (ior (and (eq (symbol_ref ("which_alternative"))
6697 (eq_attr "length" "8"))
6698 (eq_attr "length" "10"))
6699 (const_string "yes")
6700 (const_string "no")))
6701 (set (attr "length")
6703 (eq (symbol_ref ("which_alternative"))
6706 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6707 (le (minus (match_dup 5) (pc)) (const_int 256)))
6710 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6711 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6715 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6716 (le (minus (match_dup 5) (pc)) (const_int 256)))
6719 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6720 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6725 (define_insn "*subsi3_cbranch_scratch"
6728 (match_operator 0 "arm_comparison_operator"
6729 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6730 (match_operand:SI 2 "nonmemory_operand" "l"))
6732 (label_ref (match_operand 3 "" ""))
6735 && (GET_CODE (operands[0]) == EQ
6736 || GET_CODE (operands[0]) == NE
6737 || GET_CODE (operands[0]) == GE
6738 || GET_CODE (operands[0]) == LT)"
6740 output_asm_insn (\"cmp\\t%1, %2\", operands);
6741 switch (get_attr_length (insn))
6743 case 4: return \"b%d0\\t%l3\";
6744 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6748 [(set (attr "far_jump")
6750 (eq_attr "length" "8")
6751 (const_string "yes")
6752 (const_string "no")))
6753 (set (attr "length")
6755 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756 (le (minus (match_dup 3) (pc)) (const_int 256)))
6759 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6765 ;; Comparison and test insns
6767 (define_expand "cmpsi"
6768 [(match_operand:SI 0 "s_register_operand" "")
6769 (match_operand:SI 1 "arm_add_operand" "")]
6772 arm_compare_op0 = operands[0];
6773 arm_compare_op1 = operands[1];
6778 (define_expand "cmpsf"
6779 [(match_operand:SF 0 "s_register_operand" "")
6780 (match_operand:SF 1 "arm_float_compare_operand" "")]
6781 "TARGET_ARM && TARGET_HARD_FLOAT"
6783 arm_compare_op0 = operands[0];
6784 arm_compare_op1 = operands[1];
6789 (define_expand "cmpdf"
6790 [(match_operand:DF 0 "s_register_operand" "")
6791 (match_operand:DF 1 "arm_float_compare_operand" "")]
6792 "TARGET_ARM && TARGET_HARD_FLOAT"
6794 arm_compare_op0 = operands[0];
6795 arm_compare_op1 = operands[1];
6800 (define_insn "*arm_cmpsi_insn"
6801 [(set (reg:CC CC_REGNUM)
6802 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6803 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6808 [(set_attr "conds" "set")]
6811 (define_insn "*cmpsi_shiftsi"
6812 [(set (reg:CC CC_REGNUM)
6813 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6814 (match_operator:SI 3 "shift_operator"
6815 [(match_operand:SI 1 "s_register_operand" "r")
6816 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6819 [(set_attr "conds" "set")
6820 (set_attr "shift" "1")
6821 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6822 (const_string "alu_shift")
6823 (const_string "alu_shift_reg")))]
6826 (define_insn "*cmpsi_shiftsi_swp"
6827 [(set (reg:CC_SWP CC_REGNUM)
6828 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6829 [(match_operand:SI 1 "s_register_operand" "r")
6830 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6831 (match_operand:SI 0 "s_register_operand" "r")))]
6834 [(set_attr "conds" "set")
6835 (set_attr "shift" "1")
6836 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6837 (const_string "alu_shift")
6838 (const_string "alu_shift_reg")))]
6841 (define_insn "*cmpsi_negshiftsi_si"
6842 [(set (reg:CC_Z CC_REGNUM)
6844 (neg:SI (match_operator:SI 1 "shift_operator"
6845 [(match_operand:SI 2 "s_register_operand" "r")
6846 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6847 (match_operand:SI 0 "s_register_operand" "r")))]
6850 [(set_attr "conds" "set")
6851 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6852 (const_string "alu_shift")
6853 (const_string "alu_shift_reg")))]
6856 ;; Cirrus SF compare instruction
6857 (define_insn "*cirrus_cmpsf"
6858 [(set (reg:CCFP CC_REGNUM)
6859 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6860 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6861 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862 "cfcmps%?\\tr15, %V0, %V1"
6863 [(set_attr "type" "mav_farith")
6864 (set_attr "cirrus" "compare")]
6867 ;; Cirrus DF compare instruction
6868 (define_insn "*cirrus_cmpdf"
6869 [(set (reg:CCFP CC_REGNUM)
6870 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6871 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6872 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6873 "cfcmpd%?\\tr15, %V0, %V1"
6874 [(set_attr "type" "mav_farith")
6875 (set_attr "cirrus" "compare")]
6878 ;; Cirrus DI compare instruction
6879 (define_expand "cmpdi"
6880 [(match_operand:DI 0 "cirrus_fp_register" "")
6881 (match_operand:DI 1 "cirrus_fp_register" "")]
6882 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6884 arm_compare_op0 = operands[0];
6885 arm_compare_op1 = operands[1];
6889 (define_insn "*cirrus_cmpdi"
6890 [(set (reg:CC CC_REGNUM)
6891 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6892 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6893 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6894 "cfcmp64%?\\tr15, %V0, %V1"
6895 [(set_attr "type" "mav_farith")
6896 (set_attr "cirrus" "compare")]
6899 ; This insn allows redundant compares to be removed by cse, nothing should
6900 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6901 ; is deleted later on. The match_dup will match the mode here, so that
6902 ; mode changes of the condition codes aren't lost by this even though we don't
6903 ; specify what they are.
6905 (define_insn "*deleted_compare"
6906 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6908 "\\t%@ deleted compare"
6909 [(set_attr "conds" "set")
6910 (set_attr "length" "0")]
6914 ;; Conditional branch insns
6916 (define_expand "beq"
6918 (if_then_else (eq (match_dup 1) (const_int 0))
6919 (label_ref (match_operand 0 "" ""))
6922 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6925 (define_expand "bne"
6927 (if_then_else (ne (match_dup 1) (const_int 0))
6928 (label_ref (match_operand 0 "" ""))
6931 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6934 (define_expand "bgt"
6936 (if_then_else (gt (match_dup 1) (const_int 0))
6937 (label_ref (match_operand 0 "" ""))
6940 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6943 (define_expand "ble"
6945 (if_then_else (le (match_dup 1) (const_int 0))
6946 (label_ref (match_operand 0 "" ""))
6949 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6952 (define_expand "bge"
6954 (if_then_else (ge (match_dup 1) (const_int 0))
6955 (label_ref (match_operand 0 "" ""))
6958 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6961 (define_expand "blt"
6963 (if_then_else (lt (match_dup 1) (const_int 0))
6964 (label_ref (match_operand 0 "" ""))
6967 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6970 (define_expand "bgtu"
6972 (if_then_else (gtu (match_dup 1) (const_int 0))
6973 (label_ref (match_operand 0 "" ""))
6976 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6979 (define_expand "bleu"
6981 (if_then_else (leu (match_dup 1) (const_int 0))
6982 (label_ref (match_operand 0 "" ""))
6985 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6988 (define_expand "bgeu"
6990 (if_then_else (geu (match_dup 1) (const_int 0))
6991 (label_ref (match_operand 0 "" ""))
6994 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6997 (define_expand "bltu"
6999 (if_then_else (ltu (match_dup 1) (const_int 0))
7000 (label_ref (match_operand 0 "" ""))
7003 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7006 (define_expand "bunordered"
7008 (if_then_else (unordered (match_dup 1) (const_int 0))
7009 (label_ref (match_operand 0 "" ""))
7011 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7012 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7016 (define_expand "bordered"
7018 (if_then_else (ordered (match_dup 1) (const_int 0))
7019 (label_ref (match_operand 0 "" ""))
7021 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7022 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7026 (define_expand "bungt"
7028 (if_then_else (ungt (match_dup 1) (const_int 0))
7029 (label_ref (match_operand 0 "" ""))
7031 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7032 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7035 (define_expand "bunlt"
7037 (if_then_else (unlt (match_dup 1) (const_int 0))
7038 (label_ref (match_operand 0 "" ""))
7040 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7041 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7044 (define_expand "bunge"
7046 (if_then_else (unge (match_dup 1) (const_int 0))
7047 (label_ref (match_operand 0 "" ""))
7049 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7050 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7053 (define_expand "bunle"
7055 (if_then_else (unle (match_dup 1) (const_int 0))
7056 (label_ref (match_operand 0 "" ""))
7058 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7059 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7062 ;; The following two patterns need two branch instructions, since there is
7063 ;; no single instruction that will handle all cases.
7064 (define_expand "buneq"
7066 (if_then_else (uneq (match_dup 1) (const_int 0))
7067 (label_ref (match_operand 0 "" ""))
7069 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7070 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7073 (define_expand "bltgt"
7075 (if_then_else (ltgt (match_dup 1) (const_int 0))
7076 (label_ref (match_operand 0 "" ""))
7078 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7079 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7083 ;; Patterns to match conditional branch insns.
7086 ; Special pattern to match UNEQ.
7087 (define_insn "*arm_buneq"
7089 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7090 (label_ref (match_operand 0 "" ""))
7092 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7094 gcc_assert (!arm_ccfsm_state);
7096 return \"bvs\\t%l0\;beq\\t%l0\";
7098 [(set_attr "conds" "jump_clob")
7099 (set_attr "length" "8")]
7102 ; Special pattern to match LTGT.
7103 (define_insn "*arm_bltgt"
7105 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7106 (label_ref (match_operand 0 "" ""))
7108 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7110 gcc_assert (!arm_ccfsm_state);
7112 return \"bmi\\t%l0\;bgt\\t%l0\";
7114 [(set_attr "conds" "jump_clob")
7115 (set_attr "length" "8")]
7118 (define_insn "*arm_cond_branch"
7120 (if_then_else (match_operator 1 "arm_comparison_operator"
7121 [(match_operand 2 "cc_register" "") (const_int 0)])
7122 (label_ref (match_operand 0 "" ""))
7126 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7128 arm_ccfsm_state += 2;
7131 return \"b%d1\\t%l0\";
7133 [(set_attr "conds" "use")
7134 (set_attr "type" "branch")]
7137 ; Special pattern to match reversed UNEQ.
7138 (define_insn "*arm_buneq_reversed"
7140 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7142 (label_ref (match_operand 0 "" ""))))]
7143 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7145 gcc_assert (!arm_ccfsm_state);
7147 return \"bmi\\t%l0\;bgt\\t%l0\";
7149 [(set_attr "conds" "jump_clob")
7150 (set_attr "length" "8")]
7153 ; Special pattern to match reversed LTGT.
7154 (define_insn "*arm_bltgt_reversed"
7156 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7158 (label_ref (match_operand 0 "" ""))))]
7159 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7161 gcc_assert (!arm_ccfsm_state);
7163 return \"bvs\\t%l0\;beq\\t%l0\";
7165 [(set_attr "conds" "jump_clob")
7166 (set_attr "length" "8")]
7169 (define_insn "*arm_cond_branch_reversed"
7171 (if_then_else (match_operator 1 "arm_comparison_operator"
7172 [(match_operand 2 "cc_register" "") (const_int 0)])
7174 (label_ref (match_operand 0 "" ""))))]
7177 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7179 arm_ccfsm_state += 2;
7182 return \"b%D1\\t%l0\";
7184 [(set_attr "conds" "use")
7185 (set_attr "type" "branch")]
7192 (define_expand "seq"
7193 [(set (match_operand:SI 0 "s_register_operand" "")
7194 (eq:SI (match_dup 1) (const_int 0)))]
7196 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7199 (define_expand "sne"
7200 [(set (match_operand:SI 0 "s_register_operand" "")
7201 (ne:SI (match_dup 1) (const_int 0)))]
7203 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7206 (define_expand "sgt"
7207 [(set (match_operand:SI 0 "s_register_operand" "")
7208 (gt:SI (match_dup 1) (const_int 0)))]
7210 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7213 (define_expand "sle"
7214 [(set (match_operand:SI 0 "s_register_operand" "")
7215 (le:SI (match_dup 1) (const_int 0)))]
7217 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7220 (define_expand "sge"
7221 [(set (match_operand:SI 0 "s_register_operand" "")
7222 (ge:SI (match_dup 1) (const_int 0)))]
7224 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7227 (define_expand "slt"
7228 [(set (match_operand:SI 0 "s_register_operand" "")
7229 (lt:SI (match_dup 1) (const_int 0)))]
7231 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7234 (define_expand "sgtu"
7235 [(set (match_operand:SI 0 "s_register_operand" "")
7236 (gtu:SI (match_dup 1) (const_int 0)))]
7238 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7241 (define_expand "sleu"
7242 [(set (match_operand:SI 0 "s_register_operand" "")
7243 (leu:SI (match_dup 1) (const_int 0)))]
7245 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7248 (define_expand "sgeu"
7249 [(set (match_operand:SI 0 "s_register_operand" "")
7250 (geu:SI (match_dup 1) (const_int 0)))]
7252 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7255 (define_expand "sltu"
7256 [(set (match_operand:SI 0 "s_register_operand" "")
7257 (ltu:SI (match_dup 1) (const_int 0)))]
7259 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7262 (define_expand "sunordered"
7263 [(set (match_operand:SI 0 "s_register_operand" "")
7264 (unordered:SI (match_dup 1) (const_int 0)))]
7265 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7270 (define_expand "sordered"
7271 [(set (match_operand:SI 0 "s_register_operand" "")
7272 (ordered:SI (match_dup 1) (const_int 0)))]
7273 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7274 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7278 (define_expand "sungt"
7279 [(set (match_operand:SI 0 "s_register_operand" "")
7280 (ungt:SI (match_dup 1) (const_int 0)))]
7281 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7282 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7286 (define_expand "sunge"
7287 [(set (match_operand:SI 0 "s_register_operand" "")
7288 (unge:SI (match_dup 1) (const_int 0)))]
7289 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7290 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7294 (define_expand "sunlt"
7295 [(set (match_operand:SI 0 "s_register_operand" "")
7296 (unlt:SI (match_dup 1) (const_int 0)))]
7297 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7298 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7302 (define_expand "sunle"
7303 [(set (match_operand:SI 0 "s_register_operand" "")
7304 (unle:SI (match_dup 1) (const_int 0)))]
7305 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7306 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7310 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7311 ;;; simple ARM instructions.
7313 ; (define_expand "suneq"
7314 ; [(set (match_operand:SI 0 "s_register_operand" "")
7315 ; (uneq:SI (match_dup 1) (const_int 0)))]
7316 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7317 ; "gcc_unreachable ();"
7320 ; (define_expand "sltgt"
7321 ; [(set (match_operand:SI 0 "s_register_operand" "")
7322 ; (ltgt:SI (match_dup 1) (const_int 0)))]
7323 ; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7324 ; "gcc_unreachable ();"
7327 (define_insn "*mov_scc"
7328 [(set (match_operand:SI 0 "s_register_operand" "=r")
7329 (match_operator:SI 1 "arm_comparison_operator"
7330 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7332 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7333 [(set_attr "conds" "use")
7334 (set_attr "length" "8")]
7337 (define_insn "*mov_negscc"
7338 [(set (match_operand:SI 0 "s_register_operand" "=r")
7339 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7340 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7342 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7343 [(set_attr "conds" "use")
7344 (set_attr "length" "8")]
7347 (define_insn "*mov_notscc"
7348 [(set (match_operand:SI 0 "s_register_operand" "=r")
7349 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7350 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7352 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7353 [(set_attr "conds" "use")
7354 (set_attr "length" "8")]
7358 ;; Conditional move insns
7360 (define_expand "movsicc"
7361 [(set (match_operand:SI 0 "s_register_operand" "")
7362 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7363 (match_operand:SI 2 "arm_not_operand" "")
7364 (match_operand:SI 3 "arm_not_operand" "")))]
7368 enum rtx_code code = GET_CODE (operands[1]);
7371 if (code == UNEQ || code == LTGT)
7374 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7375 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7379 (define_expand "movsfcc"
7380 [(set (match_operand:SF 0 "s_register_operand" "")
7381 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7382 (match_operand:SF 2 "s_register_operand" "")
7383 (match_operand:SF 3 "nonmemory_operand" "")))]
7387 enum rtx_code code = GET_CODE (operands[1]);
7390 if (code == UNEQ || code == LTGT)
7393 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7394 Otherwise, ensure it is a valid FP add operand */
7395 if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7396 || (!arm_float_add_operand (operands[3], SFmode)))
7397 operands[3] = force_reg (SFmode, operands[3]);
7399 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7400 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7404 (define_expand "movdfcc"
7405 [(set (match_operand:DF 0 "s_register_operand" "")
7406 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7407 (match_operand:DF 2 "s_register_operand" "")
7408 (match_operand:DF 3 "arm_float_add_operand" "")))]
7409 "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7412 enum rtx_code code = GET_CODE (operands[1]);
7415 if (code == UNEQ || code == LTGT)
7418 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7419 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7423 (define_insn "*movsicc_insn"
7424 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7426 (match_operator 3 "arm_comparison_operator"
7427 [(match_operand 4 "cc_register" "") (const_int 0)])
7428 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7429 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7436 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7437 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7438 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7439 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7440 [(set_attr "length" "4,4,4,4,8,8,8,8")
7441 (set_attr "conds" "use")]
7444 (define_insn "*movsfcc_soft_insn"
7445 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7446 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7447 [(match_operand 4 "cc_register" "") (const_int 0)])
7448 (match_operand:SF 1 "s_register_operand" "0,r")
7449 (match_operand:SF 2 "s_register_operand" "r,0")))]
7450 "TARGET_ARM && TARGET_SOFT_FLOAT"
7454 [(set_attr "conds" "use")]
7458 ;; Jump and linkage insns
7460 (define_expand "jump"
7462 (label_ref (match_operand 0 "" "")))]
7467 (define_insn "*arm_jump"
7469 (label_ref (match_operand 0 "" "")))]
7473 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7475 arm_ccfsm_state += 2;
7478 return \"b%?\\t%l0\";
7481 [(set_attr "predicable" "yes")]
7484 (define_insn "*thumb_jump"
7486 (label_ref (match_operand 0 "" "")))]
7489 if (get_attr_length (insn) == 2)
7491 return \"bl\\t%l0\\t%@ far jump\";
7493 [(set (attr "far_jump")
7495 (eq_attr "length" "4")
7496 (const_string "yes")
7497 (const_string "no")))
7498 (set (attr "length")
7500 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7501 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7506 (define_expand "call"
7507 [(parallel [(call (match_operand 0 "memory_operand" "")
7508 (match_operand 1 "general_operand" ""))
7509 (use (match_operand 2 "" ""))
7510 (clobber (reg:SI LR_REGNUM))])]
7516 /* In an untyped call, we can get NULL for operand 2. */
7517 if (operands[2] == NULL_RTX)
7518 operands[2] = const0_rtx;
7520 /* This is to decide if we should generate indirect calls by loading the
7521 32 bit address of the callee into a register before performing the
7522 branch and link. operand[2] encodes the long_call/short_call
7523 attribute of the function being called. This attribute is set whenever
7524 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7525 is used, and the short_call attribute can also be set if function is
7526 declared as static or if it has already been defined in the current
7527 compilation unit. See arm.c and arm.h for info about this. The third
7528 parameter to arm_is_longcall_p is used to tell it which pattern
7530 callee = XEXP (operands[0], 0);
7532 if ((GET_CODE (callee) == SYMBOL_REF
7533 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7534 || (GET_CODE (callee) != SYMBOL_REF
7535 && GET_CODE (callee) != REG))
7536 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7540 (define_insn "*call_reg_armv5"
7541 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7542 (match_operand 1 "" ""))
7543 (use (match_operand 2 "" ""))
7544 (clobber (reg:SI LR_REGNUM))]
7545 "TARGET_ARM && arm_arch5"
7547 [(set_attr "type" "call")]
7550 (define_insn "*call_reg_arm"
7551 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7552 (match_operand 1 "" ""))
7553 (use (match_operand 2 "" ""))
7554 (clobber (reg:SI LR_REGNUM))]
7555 "TARGET_ARM && !arm_arch5"
7557 return output_call (operands);
7559 ;; length is worst case, normally it is only two
7560 [(set_attr "length" "12")
7561 (set_attr "type" "call")]
7564 (define_insn "*call_mem"
7565 [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7566 (match_operand 1 "" ""))
7567 (use (match_operand 2 "" ""))
7568 (clobber (reg:SI LR_REGNUM))]
7571 return output_call_mem (operands);
7573 [(set_attr "length" "12")
7574 (set_attr "type" "call")]
7577 (define_insn "*call_reg_thumb_v5"
7578 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7579 (match_operand 1 "" ""))
7580 (use (match_operand 2 "" ""))
7581 (clobber (reg:SI LR_REGNUM))]
7582 "TARGET_THUMB && arm_arch5"
7584 [(set_attr "length" "2")
7585 (set_attr "type" "call")]
7588 (define_insn "*call_reg_thumb"
7589 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7590 (match_operand 1 "" ""))
7591 (use (match_operand 2 "" ""))
7592 (clobber (reg:SI LR_REGNUM))]
7593 "TARGET_THUMB && !arm_arch5"
7596 if (!TARGET_CALLER_INTERWORKING)
7597 return thumb_call_via_reg (operands[0]);
7598 else if (operands[1] == const0_rtx)
7599 return \"bl\\t%__interwork_call_via_%0\";
7600 else if (frame_pointer_needed)
7601 return \"bl\\t%__interwork_r7_call_via_%0\";
7603 return \"bl\\t%__interwork_r11_call_via_%0\";
7605 [(set_attr "type" "call")]
7608 (define_expand "call_value"
7609 [(parallel [(set (match_operand 0 "" "")
7610 (call (match_operand 1 "memory_operand" "")
7611 (match_operand 2 "general_operand" "")))
7612 (use (match_operand 3 "" ""))
7613 (clobber (reg:SI LR_REGNUM))])]
7617 rtx callee = XEXP (operands[1], 0);
7619 /* In an untyped call, we can get NULL for operand 2. */
7620 if (operands[3] == 0)
7621 operands[3] = const0_rtx;
7623 /* See the comment in define_expand \"call\". */
7624 if ((GET_CODE (callee) == SYMBOL_REF
7625 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7626 || (GET_CODE (callee) != SYMBOL_REF
7627 && GET_CODE (callee) != REG))
7628 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7632 (define_insn "*call_value_reg_armv5"
7633 [(set (match_operand 0 "" "")
7634 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7635 (match_operand 2 "" "")))
7636 (use (match_operand 3 "" ""))
7637 (clobber (reg:SI LR_REGNUM))]
7638 "TARGET_ARM && arm_arch5"
7640 [(set_attr "type" "call")]
7643 (define_insn "*call_value_reg_arm"
7644 [(set (match_operand 0 "" "")
7645 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7646 (match_operand 2 "" "")))
7647 (use (match_operand 3 "" ""))
7648 (clobber (reg:SI LR_REGNUM))]
7649 "TARGET_ARM && !arm_arch5"
7651 return output_call (&operands[1]);
7653 [(set_attr "length" "12")
7654 (set_attr "type" "call")]
7657 (define_insn "*call_value_mem"
7658 [(set (match_operand 0 "" "")
7659 (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7660 (match_operand 2 "" "")))
7661 (use (match_operand 3 "" ""))
7662 (clobber (reg:SI LR_REGNUM))]
7663 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7665 return output_call_mem (&operands[1]);
7667 [(set_attr "length" "12")
7668 (set_attr "type" "call")]
7671 (define_insn "*call_value_reg_thumb_v5"
7672 [(set (match_operand 0 "" "")
7673 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674 (match_operand 2 "" "")))
7675 (use (match_operand 3 "" ""))
7676 (clobber (reg:SI LR_REGNUM))]
7677 "TARGET_THUMB && arm_arch5"
7679 [(set_attr "length" "2")
7680 (set_attr "type" "call")]
7683 (define_insn "*call_value_reg_thumb"
7684 [(set (match_operand 0 "" "")
7685 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7686 (match_operand 2 "" "")))
7687 (use (match_operand 3 "" ""))
7688 (clobber (reg:SI LR_REGNUM))]
7689 "TARGET_THUMB && !arm_arch5"
7692 if (!TARGET_CALLER_INTERWORKING)
7693 return thumb_call_via_reg (operands[1]);
7694 else if (operands[2] == const0_rtx)
7695 return \"bl\\t%__interwork_call_via_%1\";
7696 else if (frame_pointer_needed)
7697 return \"bl\\t%__interwork_r7_call_via_%1\";
7699 return \"bl\\t%__interwork_r11_call_via_%1\";
7701 [(set_attr "type" "call")]
7704 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7705 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7707 (define_insn "*call_symbol"
7708 [(call (mem:SI (match_operand:SI 0 "" ""))
7709 (match_operand 1 "" ""))
7710 (use (match_operand 2 "" ""))
7711 (clobber (reg:SI LR_REGNUM))]
7713 && (GET_CODE (operands[0]) == SYMBOL_REF)
7714 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7717 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7719 [(set_attr "type" "call")]
7722 (define_insn "*call_value_symbol"
7723 [(set (match_operand 0 "" "")
7724 (call (mem:SI (match_operand:SI 1 "" ""))
7725 (match_operand:SI 2 "" "")))
7726 (use (match_operand 3 "" ""))
7727 (clobber (reg:SI LR_REGNUM))]
7729 && (GET_CODE (operands[1]) == SYMBOL_REF)
7730 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7733 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7735 [(set_attr "type" "call")]
7738 (define_insn "*call_insn"
7739 [(call (mem:SI (match_operand:SI 0 "" ""))
7740 (match_operand:SI 1 "" ""))
7741 (use (match_operand 2 "" ""))
7742 (clobber (reg:SI LR_REGNUM))]
7744 && GET_CODE (operands[0]) == SYMBOL_REF
7745 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7747 [(set_attr "length" "4")
7748 (set_attr "type" "call")]
7751 (define_insn "*call_value_insn"
7752 [(set (match_operand 0 "" "")
7753 (call (mem:SI (match_operand 1 "" ""))
7754 (match_operand 2 "" "")))
7755 (use (match_operand 3 "" ""))
7756 (clobber (reg:SI LR_REGNUM))]
7758 && GET_CODE (operands[1]) == SYMBOL_REF
7759 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7761 [(set_attr "length" "4")
7762 (set_attr "type" "call")]
7765 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7766 (define_expand "sibcall"
7767 [(parallel [(call (match_operand 0 "memory_operand" "")
7768 (match_operand 1 "general_operand" ""))
7770 (use (match_operand 2 "" ""))])]
7774 if (operands[2] == NULL_RTX)
7775 operands[2] = const0_rtx;
7779 (define_expand "sibcall_value"
7780 [(parallel [(set (match_operand 0 "" "")
7781 (call (match_operand 1 "memory_operand" "")
7782 (match_operand 2 "general_operand" "")))
7784 (use (match_operand 3 "" ""))])]
7788 if (operands[3] == NULL_RTX)
7789 operands[3] = const0_rtx;
7793 (define_insn "*sibcall_insn"
7794 [(call (mem:SI (match_operand:SI 0 "" "X"))
7795 (match_operand 1 "" ""))
7797 (use (match_operand 2 "" ""))]
7798 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7800 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7802 [(set_attr "type" "call")]
7805 (define_insn "*sibcall_value_insn"
7806 [(set (match_operand 0 "" "")
7807 (call (mem:SI (match_operand:SI 1 "" "X"))
7808 (match_operand 2 "" "")))
7810 (use (match_operand 3 "" ""))]
7811 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7813 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7815 [(set_attr "type" "call")]
7818 ;; Often the return insn will be the same as loading from memory, so set attr
7819 (define_insn "return"
7821 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7824 if (arm_ccfsm_state == 2)
7826 arm_ccfsm_state += 2;
7829 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7831 [(set_attr "type" "load1")
7832 (set_attr "length" "12")
7833 (set_attr "predicable" "yes")]
7836 (define_insn "*cond_return"
7838 (if_then_else (match_operator 0 "arm_comparison_operator"
7839 [(match_operand 1 "cc_register" "") (const_int 0)])
7842 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7845 if (arm_ccfsm_state == 2)
7847 arm_ccfsm_state += 2;
7850 return output_return_instruction (operands[0], TRUE, FALSE);
7852 [(set_attr "conds" "use")
7853 (set_attr "length" "12")
7854 (set_attr "type" "load1")]
7857 (define_insn "*cond_return_inverted"
7859 (if_then_else (match_operator 0 "arm_comparison_operator"
7860 [(match_operand 1 "cc_register" "") (const_int 0)])
7863 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7866 if (arm_ccfsm_state == 2)
7868 arm_ccfsm_state += 2;
7871 return output_return_instruction (operands[0], TRUE, TRUE);
7873 [(set_attr "conds" "use")
7874 (set_attr "length" "12")
7875 (set_attr "type" "load1")]
7878 ;; Generate a sequence of instructions to determine if the processor is
7879 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7882 (define_expand "return_addr_mask"
7884 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7886 (set (match_operand:SI 0 "s_register_operand" "")
7887 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7889 (const_int 67108860)))] ; 0x03fffffc
7892 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7895 (define_insn "*check_arch2"
7896 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7897 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7900 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7901 [(set_attr "length" "8")
7902 (set_attr "conds" "set")]
7905 ;; Call subroutine returning any type.
7907 (define_expand "untyped_call"
7908 [(parallel [(call (match_operand 0 "" "")
7910 (match_operand 1 "" "")
7911 (match_operand 2 "" "")])]
7916 rtx par = gen_rtx_PARALLEL (VOIDmode,
7917 rtvec_alloc (XVECLEN (operands[2], 0)));
7918 rtx addr = gen_reg_rtx (Pmode);
7922 emit_move_insn (addr, XEXP (operands[1], 0));
7923 mem = change_address (operands[1], BLKmode, addr);
7925 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7927 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7929 /* Default code only uses r0 as a return value, but we could
7930 be using anything up to 4 registers. */
7931 if (REGNO (src) == R0_REGNUM)
7932 src = gen_rtx_REG (TImode, R0_REGNUM);
7934 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7936 size += GET_MODE_SIZE (GET_MODE (src));
7939 emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7944 for (i = 0; i < XVECLEN (par, 0); i++)
7946 HOST_WIDE_INT offset = 0;
7947 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7950 emit_move_insn (addr, plus_constant (addr, size));
7952 mem = change_address (mem, GET_MODE (reg), NULL);
7953 if (REGNO (reg) == R0_REGNUM)
7955 /* On thumb we have to use a write-back instruction. */
7956 emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7957 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7958 size = TARGET_ARM ? 16 : 0;
7962 emit_move_insn (mem, reg);
7963 size = GET_MODE_SIZE (GET_MODE (reg));
7967 /* The optimizer does not know that the call sets the function value
7968 registers we stored in the result block. We avoid problems by
7969 claiming that all hard registers are used and clobbered at this
7971 emit_insn (gen_blockage ());
7977 (define_expand "untyped_return"
7978 [(match_operand:BLK 0 "memory_operand" "")
7979 (match_operand 1 "" "")]
7984 rtx addr = gen_reg_rtx (Pmode);
7988 emit_move_insn (addr, XEXP (operands[0], 0));
7989 mem = change_address (operands[0], BLKmode, addr);
7991 for (i = 0; i < XVECLEN (operands[1], 0); i++)
7993 HOST_WIDE_INT offset = 0;
7994 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7997 emit_move_insn (addr, plus_constant (addr, size));
7999 mem = change_address (mem, GET_MODE (reg), NULL);
8000 if (REGNO (reg) == R0_REGNUM)
8002 /* On thumb we have to use a write-back instruction. */
8003 emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8004 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8005 size = TARGET_ARM ? 16 : 0;
8009 emit_move_insn (reg, mem);
8010 size = GET_MODE_SIZE (GET_MODE (reg));
8014 /* Emit USE insns before the return. */
8015 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8016 emit_insn (gen_rtx_USE (VOIDmode,
8017 SET_DEST (XVECEXP (operands[1], 0, i))));
8019 /* Construct the return. */
8020 expand_naked_return ();
8026 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8027 ;; all of memory. This blocks insns from being moved across this point.
8029 (define_insn "blockage"
8030 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8033 [(set_attr "length" "0")
8034 (set_attr "type" "block")]
8037 (define_expand "casesi"
8038 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8039 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8040 (match_operand:SI 2 "const_int_operand" "") ; total range
8041 (match_operand:SI 3 "" "") ; table label
8042 (match_operand:SI 4 "" "")] ; Out of range label
8047 if (operands[1] != const0_rtx)
8049 reg = gen_reg_rtx (SImode);
8051 emit_insn (gen_addsi3 (reg, operands[0],
8052 GEN_INT (-INTVAL (operands[1]))));
8056 if (!const_ok_for_arm (INTVAL (operands[2])))
8057 operands[2] = force_reg (SImode, operands[2]);
8059 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8065 ;; The USE in this pattern is needed to tell flow analysis that this is
8066 ;; a CASESI insn. It has no other purpose.
8067 (define_insn "casesi_internal"
8068 [(parallel [(set (pc)
8070 (leu (match_operand:SI 0 "s_register_operand" "r")
8071 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8072 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8073 (label_ref (match_operand 2 "" ""))))
8074 (label_ref (match_operand 3 "" ""))))
8075 (clobber (reg:CC CC_REGNUM))
8076 (use (label_ref (match_dup 2)))])]
8080 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8081 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8083 [(set_attr "conds" "clob")
8084 (set_attr "length" "12")]
8087 (define_expand "indirect_jump"
8089 (match_operand:SI 0 "s_register_operand" ""))]
8094 ;; NB Never uses BX.
8095 (define_insn "*arm_indirect_jump"
8097 (match_operand:SI 0 "s_register_operand" "r"))]
8099 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8100 [(set_attr "predicable" "yes")]
8103 (define_insn "*load_indirect_jump"
8105 (match_operand:SI 0 "memory_operand" "m"))]
8107 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8108 [(set_attr "type" "load1")
8109 (set_attr "pool_range" "4096")
8110 (set_attr "neg_pool_range" "4084")
8111 (set_attr "predicable" "yes")]
8114 ;; NB Never uses BX.
8115 (define_insn "*thumb_indirect_jump"
8117 (match_operand:SI 0 "register_operand" "l*r"))]
8120 [(set_attr "conds" "clob")
8121 (set_attr "length" "2")]
8132 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8133 return \"mov\\tr8, r8\";
8135 [(set (attr "length")
8136 (if_then_else (eq_attr "is_thumb" "yes")
8142 ;; Patterns to allow combination of arithmetic, cond code and shifts
8144 (define_insn "*arith_shiftsi"
8145 [(set (match_operand:SI 0 "s_register_operand" "=r")
8146 (match_operator:SI 1 "shiftable_operator"
8147 [(match_operator:SI 3 "shift_operator"
8148 [(match_operand:SI 4 "s_register_operand" "r")
8149 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8150 (match_operand:SI 2 "s_register_operand" "r")]))]
8152 "%i1%?\\t%0, %2, %4%S3"
8153 [(set_attr "predicable" "yes")
8154 (set_attr "shift" "4")
8155 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8156 (const_string "alu_shift")
8157 (const_string "alu_shift_reg")))]
8161 [(set (match_operand:SI 0 "s_register_operand" "")
8162 (match_operator:SI 1 "shiftable_operator"
8163 [(match_operator:SI 2 "shiftable_operator"
8164 [(match_operator:SI 3 "shift_operator"
8165 [(match_operand:SI 4 "s_register_operand" "")
8166 (match_operand:SI 5 "reg_or_int_operand" "")])
8167 (match_operand:SI 6 "s_register_operand" "")])
8168 (match_operand:SI 7 "arm_rhs_operand" "")]))
8169 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8172 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8175 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8178 (define_insn "*arith_shiftsi_compare0"
8179 [(set (reg:CC_NOOV CC_REGNUM)
8180 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8181 [(match_operator:SI 3 "shift_operator"
8182 [(match_operand:SI 4 "s_register_operand" "r")
8183 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8184 (match_operand:SI 2 "s_register_operand" "r")])
8186 (set (match_operand:SI 0 "s_register_operand" "=r")
8187 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8190 "%i1%?s\\t%0, %2, %4%S3"
8191 [(set_attr "conds" "set")
8192 (set_attr "shift" "4")
8193 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8194 (const_string "alu_shift")
8195 (const_string "alu_shift_reg")))]
8198 (define_insn "*arith_shiftsi_compare0_scratch"
8199 [(set (reg:CC_NOOV CC_REGNUM)
8200 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8201 [(match_operator:SI 3 "shift_operator"
8202 [(match_operand:SI 4 "s_register_operand" "r")
8203 (match_operand:SI 5 "reg_or_int_operand" "rI")])
8204 (match_operand:SI 2 "s_register_operand" "r")])
8206 (clobber (match_scratch:SI 0 "=r"))]
8208 "%i1%?s\\t%0, %2, %4%S3"
8209 [(set_attr "conds" "set")
8210 (set_attr "shift" "4")
8211 (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8212 (const_string "alu_shift")
8213 (const_string "alu_shift_reg")))]
8216 (define_insn "*sub_shiftsi"
8217 [(set (match_operand:SI 0 "s_register_operand" "=r")
8218 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8219 (match_operator:SI 2 "shift_operator"
8220 [(match_operand:SI 3 "s_register_operand" "r")
8221 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8223 "sub%?\\t%0, %1, %3%S2"
8224 [(set_attr "predicable" "yes")
8225 (set_attr "shift" "3")
8226 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8227 (const_string "alu_shift")
8228 (const_string "alu_shift_reg")))]
8231 (define_insn "*sub_shiftsi_compare0"
8232 [(set (reg:CC_NOOV CC_REGNUM)
8234 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8235 (match_operator:SI 2 "shift_operator"
8236 [(match_operand:SI 3 "s_register_operand" "r")
8237 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8239 (set (match_operand:SI 0 "s_register_operand" "=r")
8240 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8243 "sub%?s\\t%0, %1, %3%S2"
8244 [(set_attr "conds" "set")
8245 (set_attr "shift" "3")
8246 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8247 (const_string "alu_shift")
8248 (const_string "alu_shift_reg")))]
8251 (define_insn "*sub_shiftsi_compare0_scratch"
8252 [(set (reg:CC_NOOV CC_REGNUM)
8254 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8255 (match_operator:SI 2 "shift_operator"
8256 [(match_operand:SI 3 "s_register_operand" "r")
8257 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8259 (clobber (match_scratch:SI 0 "=r"))]
8261 "sub%?s\\t%0, %1, %3%S2"
8262 [(set_attr "conds" "set")
8263 (set_attr "shift" "3")
8264 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8265 (const_string "alu_shift")
8266 (const_string "alu_shift_reg")))]
8271 (define_insn "*and_scc"
8272 [(set (match_operand:SI 0 "s_register_operand" "=r")
8273 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8274 [(match_operand 3 "cc_register" "") (const_int 0)])
8275 (match_operand:SI 2 "s_register_operand" "r")))]
8277 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8278 [(set_attr "conds" "use")
8279 (set_attr "length" "8")]
8282 (define_insn "*ior_scc"
8283 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8284 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8285 [(match_operand 3 "cc_register" "") (const_int 0)])
8286 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8290 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8291 [(set_attr "conds" "use")
8292 (set_attr "length" "4,8")]
8295 (define_insn "*compare_scc"
8296 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8297 (match_operator:SI 1 "arm_comparison_operator"
8298 [(match_operand:SI 2 "s_register_operand" "r,r")
8299 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8300 (clobber (reg:CC CC_REGNUM))]
8303 if (operands[3] == const0_rtx)
8305 if (GET_CODE (operands[1]) == LT)
8306 return \"mov\\t%0, %2, lsr #31\";
8308 if (GET_CODE (operands[1]) == GE)
8309 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8311 if (GET_CODE (operands[1]) == EQ)
8312 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8315 if (GET_CODE (operands[1]) == NE)
8317 if (which_alternative == 1)
8318 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8319 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8321 if (which_alternative == 1)
8322 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8324 output_asm_insn (\"cmp\\t%2, %3\", operands);
8325 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8327 [(set_attr "conds" "clob")
8328 (set_attr "length" "12")]
8331 (define_insn "*cond_move"
8332 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8333 (if_then_else:SI (match_operator 3 "equality_operator"
8334 [(match_operator 4 "arm_comparison_operator"
8335 [(match_operand 5 "cc_register" "") (const_int 0)])
8337 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8338 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8341 if (GET_CODE (operands[3]) == NE)
8343 if (which_alternative != 1)
8344 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8345 if (which_alternative != 0)
8346 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8349 if (which_alternative != 0)
8350 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8351 if (which_alternative != 1)
8352 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8355 [(set_attr "conds" "use")
8356 (set_attr "length" "4,4,8")]
8359 (define_insn "*cond_arith"
8360 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8361 (match_operator:SI 5 "shiftable_operator"
8362 [(match_operator:SI 4 "arm_comparison_operator"
8363 [(match_operand:SI 2 "s_register_operand" "r,r")
8364 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8365 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8366 (clobber (reg:CC CC_REGNUM))]
8369 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8370 return \"%i5\\t%0, %1, %2, lsr #31\";
8372 output_asm_insn (\"cmp\\t%2, %3\", operands);
8373 if (GET_CODE (operands[5]) == AND)
8374 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8375 else if (GET_CODE (operands[5]) == MINUS)
8376 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8377 else if (which_alternative != 0)
8378 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8379 return \"%i5%d4\\t%0, %1, #1\";
8381 [(set_attr "conds" "clob")
8382 (set_attr "length" "12")]
8385 (define_insn "*cond_sub"
8386 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8387 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8388 (match_operator:SI 4 "arm_comparison_operator"
8389 [(match_operand:SI 2 "s_register_operand" "r,r")
8390 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8391 (clobber (reg:CC CC_REGNUM))]
8394 output_asm_insn (\"cmp\\t%2, %3\", operands);
8395 if (which_alternative != 0)
8396 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8397 return \"sub%d4\\t%0, %1, #1\";
8399 [(set_attr "conds" "clob")
8400 (set_attr "length" "8,12")]
8403 (define_insn "*cmp_ite0"
8404 [(set (match_operand 6 "dominant_cc_register" "")
8407 (match_operator 4 "arm_comparison_operator"
8408 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8409 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8410 (match_operator:SI 5 "arm_comparison_operator"
8411 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8412 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8418 static const char * const opcodes[4][2] =
8420 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8421 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8422 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8423 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8424 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8425 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8426 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8427 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8430 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8432 return opcodes[which_alternative][swap];
8434 [(set_attr "conds" "set")
8435 (set_attr "length" "8")]
8438 (define_insn "*cmp_ite1"
8439 [(set (match_operand 6 "dominant_cc_register" "")
8442 (match_operator 4 "arm_comparison_operator"
8443 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8444 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8445 (match_operator:SI 5 "arm_comparison_operator"
8446 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8447 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8453 static const char * const opcodes[4][2] =
8455 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8456 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8457 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8458 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8459 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8460 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8461 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8462 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8465 comparison_dominates_p (GET_CODE (operands[5]),
8466 reverse_condition (GET_CODE (operands[4])));
8468 return opcodes[which_alternative][swap];
8470 [(set_attr "conds" "set")
8471 (set_attr "length" "8")]
8474 (define_insn "*cmp_and"
8475 [(set (match_operand 6 "dominant_cc_register" "")
8478 (match_operator 4 "arm_comparison_operator"
8479 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8480 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8481 (match_operator:SI 5 "arm_comparison_operator"
8482 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8483 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8488 static const char *const opcodes[4][2] =
8490 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8491 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8492 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8493 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8494 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8495 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8496 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8497 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8500 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8502 return opcodes[which_alternative][swap];
8504 [(set_attr "conds" "set")
8505 (set_attr "predicable" "no")
8506 (set_attr "length" "8")]
8509 (define_insn "*cmp_ior"
8510 [(set (match_operand 6 "dominant_cc_register" "")
8513 (match_operator 4 "arm_comparison_operator"
8514 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8515 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8516 (match_operator:SI 5 "arm_comparison_operator"
8517 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8518 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8523 static const char *const opcodes[4][2] =
8525 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8526 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8527 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8528 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8529 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8530 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8531 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8532 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8535 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8537 return opcodes[which_alternative][swap];
8540 [(set_attr "conds" "set")
8541 (set_attr "length" "8")]
8544 (define_insn_and_split "*ior_scc_scc"
8545 [(set (match_operand:SI 0 "s_register_operand" "=r")
8546 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8547 [(match_operand:SI 1 "s_register_operand" "r")
8548 (match_operand:SI 2 "arm_add_operand" "rIL")])
8549 (match_operator:SI 6 "arm_comparison_operator"
8550 [(match_operand:SI 4 "s_register_operand" "r")
8551 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8552 (clobber (reg:CC CC_REGNUM))]
8554 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8557 "TARGET_ARM && reload_completed"
8561 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8562 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8564 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8566 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8569 [(set_attr "conds" "clob")
8570 (set_attr "length" "16")])
8572 ; If the above pattern is followed by a CMP insn, then the compare is
8573 ; redundant, since we can rework the conditional instruction that follows.
8574 (define_insn_and_split "*ior_scc_scc_cmp"
8575 [(set (match_operand 0 "dominant_cc_register" "")
8576 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8577 [(match_operand:SI 1 "s_register_operand" "r")
8578 (match_operand:SI 2 "arm_add_operand" "rIL")])
8579 (match_operator:SI 6 "arm_comparison_operator"
8580 [(match_operand:SI 4 "s_register_operand" "r")
8581 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8583 (set (match_operand:SI 7 "s_register_operand" "=r")
8584 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8585 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8588 "TARGET_ARM && reload_completed"
8592 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8593 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8595 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8597 [(set_attr "conds" "set")
8598 (set_attr "length" "16")])
8600 (define_insn_and_split "*and_scc_scc"
8601 [(set (match_operand:SI 0 "s_register_operand" "=r")
8602 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603 [(match_operand:SI 1 "s_register_operand" "r")
8604 (match_operand:SI 2 "arm_add_operand" "rIL")])
8605 (match_operator:SI 6 "arm_comparison_operator"
8606 [(match_operand:SI 4 "s_register_operand" "r")
8607 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8608 (clobber (reg:CC CC_REGNUM))]
8610 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8613 "TARGET_ARM && reload_completed
8614 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8619 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8620 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8622 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8624 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8627 [(set_attr "conds" "clob")
8628 (set_attr "length" "16")])
8630 ; If the above pattern is followed by a CMP insn, then the compare is
8631 ; redundant, since we can rework the conditional instruction that follows.
8632 (define_insn_and_split "*and_scc_scc_cmp"
8633 [(set (match_operand 0 "dominant_cc_register" "")
8634 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8635 [(match_operand:SI 1 "s_register_operand" "r")
8636 (match_operand:SI 2 "arm_add_operand" "rIL")])
8637 (match_operator:SI 6 "arm_comparison_operator"
8638 [(match_operand:SI 4 "s_register_operand" "r")
8639 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8641 (set (match_operand:SI 7 "s_register_operand" "=r")
8642 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8643 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8646 "TARGET_ARM && reload_completed"
8650 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8651 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8653 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8655 [(set_attr "conds" "set")
8656 (set_attr "length" "16")])
8658 ;; If there is no dominance in the comparison, then we can still save an
8659 ;; instruction in the AND case, since we can know that the second compare
8660 ;; need only zero the value if false (if true, then the value is already
8662 (define_insn_and_split "*and_scc_scc_nodom"
8663 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8664 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8665 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8666 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8667 (match_operator:SI 6 "arm_comparison_operator"
8668 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8669 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8670 (clobber (reg:CC CC_REGNUM))]
8672 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8675 "TARGET_ARM && reload_completed"
8676 [(parallel [(set (match_dup 0)
8677 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8678 (clobber (reg:CC CC_REGNUM))])
8679 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8681 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8684 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8685 operands[4], operands[5]),
8687 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8689 [(set_attr "conds" "clob")
8690 (set_attr "length" "20")])
8693 [(set (reg:CC_NOOV CC_REGNUM)
8694 (compare:CC_NOOV (ior:SI
8695 (and:SI (match_operand:SI 0 "s_register_operand" "")
8697 (match_operator:SI 1 "comparison_operator"
8698 [(match_operand:SI 2 "s_register_operand" "")
8699 (match_operand:SI 3 "arm_add_operand" "")]))
8701 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8704 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8706 (set (reg:CC_NOOV CC_REGNUM)
8707 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8712 [(set (reg:CC_NOOV CC_REGNUM)
8713 (compare:CC_NOOV (ior:SI
8714 (match_operator:SI 1 "comparison_operator"
8715 [(match_operand:SI 2 "s_register_operand" "")
8716 (match_operand:SI 3 "arm_add_operand" "")])
8717 (and:SI (match_operand:SI 0 "s_register_operand" "")
8720 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8723 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8725 (set (reg:CC_NOOV CC_REGNUM)
8726 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8730 (define_insn "*negscc"
8731 [(set (match_operand:SI 0 "s_register_operand" "=r")
8732 (neg:SI (match_operator 3 "arm_comparison_operator"
8733 [(match_operand:SI 1 "s_register_operand" "r")
8734 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8735 (clobber (reg:CC CC_REGNUM))]
8738 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8739 return \"mov\\t%0, %1, asr #31\";
8741 if (GET_CODE (operands[3]) == NE)
8742 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8744 if (GET_CODE (operands[3]) == GT)
8745 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8747 output_asm_insn (\"cmp\\t%1, %2\", operands);
8748 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8749 return \"mvn%d3\\t%0, #0\";
8751 [(set_attr "conds" "clob")
8752 (set_attr "length" "12")]
8755 (define_insn "movcond"
8756 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8758 (match_operator 5 "arm_comparison_operator"
8759 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8760 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8761 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8762 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8763 (clobber (reg:CC CC_REGNUM))]
8766 if (GET_CODE (operands[5]) == LT
8767 && (operands[4] == const0_rtx))
8769 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8771 if (operands[2] == const0_rtx)
8772 return \"and\\t%0, %1, %3, asr #31\";
8773 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8775 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8777 if (operands[1] == const0_rtx)
8778 return \"bic\\t%0, %2, %3, asr #31\";
8779 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8781 /* The only case that falls through to here is when both ops 1 & 2
8785 if (GET_CODE (operands[5]) == GE
8786 && (operands[4] == const0_rtx))
8788 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8790 if (operands[2] == const0_rtx)
8791 return \"bic\\t%0, %1, %3, asr #31\";
8792 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8794 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8796 if (operands[1] == const0_rtx)
8797 return \"and\\t%0, %2, %3, asr #31\";
8798 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8800 /* The only case that falls through to here is when both ops 1 & 2
8803 if (GET_CODE (operands[4]) == CONST_INT
8804 && !const_ok_for_arm (INTVAL (operands[4])))
8805 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8807 output_asm_insn (\"cmp\\t%3, %4\", operands);
8808 if (which_alternative != 0)
8809 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8810 if (which_alternative != 1)
8811 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8814 [(set_attr "conds" "clob")
8815 (set_attr "length" "8,8,12")]
8818 (define_insn "*ifcompare_plus_move"
8819 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8820 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8821 [(match_operand:SI 4 "s_register_operand" "r,r")
8822 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8824 (match_operand:SI 2 "s_register_operand" "r,r")
8825 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8826 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8827 (clobber (reg:CC CC_REGNUM))]
8830 [(set_attr "conds" "clob")
8831 (set_attr "length" "8,12")]
8834 (define_insn "*if_plus_move"
8835 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8837 (match_operator 4 "arm_comparison_operator"
8838 [(match_operand 5 "cc_register" "") (const_int 0)])
8840 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8842 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8846 sub%d4\\t%0, %2, #%n3
8847 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8848 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8849 [(set_attr "conds" "use")
8850 (set_attr "length" "4,4,8,8")
8851 (set_attr "type" "*,*,*,*")]
8854 (define_insn "*ifcompare_move_plus"
8855 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8857 [(match_operand:SI 4 "s_register_operand" "r,r")
8858 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8859 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8861 (match_operand:SI 2 "s_register_operand" "r,r")
8862 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8863 (clobber (reg:CC CC_REGNUM))]
8866 [(set_attr "conds" "clob")
8867 (set_attr "length" "8,12")]
8870 (define_insn "*if_move_plus"
8871 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8873 (match_operator 4 "arm_comparison_operator"
8874 [(match_operand 5 "cc_register" "") (const_int 0)])
8875 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8877 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8878 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8882 sub%D4\\t%0, %2, #%n3
8883 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8884 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8885 [(set_attr "conds" "use")
8886 (set_attr "length" "4,4,8,8")
8887 (set_attr "type" "*,*,*,*")]
8890 (define_insn "*ifcompare_arith_arith"
8891 [(set (match_operand:SI 0 "s_register_operand" "=r")
8892 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8893 [(match_operand:SI 5 "s_register_operand" "r")
8894 (match_operand:SI 6 "arm_add_operand" "rIL")])
8895 (match_operator:SI 8 "shiftable_operator"
8896 [(match_operand:SI 1 "s_register_operand" "r")
8897 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8898 (match_operator:SI 7 "shiftable_operator"
8899 [(match_operand:SI 3 "s_register_operand" "r")
8900 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8901 (clobber (reg:CC CC_REGNUM))]
8904 [(set_attr "conds" "clob")
8905 (set_attr "length" "12")]
8908 (define_insn "*if_arith_arith"
8909 [(set (match_operand:SI 0 "s_register_operand" "=r")
8910 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8911 [(match_operand 8 "cc_register" "") (const_int 0)])
8912 (match_operator:SI 6 "shiftable_operator"
8913 [(match_operand:SI 1 "s_register_operand" "r")
8914 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8915 (match_operator:SI 7 "shiftable_operator"
8916 [(match_operand:SI 3 "s_register_operand" "r")
8917 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8919 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8920 [(set_attr "conds" "use")
8921 (set_attr "length" "8")]
8924 (define_insn "*ifcompare_arith_move"
8925 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8926 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8927 [(match_operand:SI 2 "s_register_operand" "r,r")
8928 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8929 (match_operator:SI 7 "shiftable_operator"
8930 [(match_operand:SI 4 "s_register_operand" "r,r")
8931 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8932 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8933 (clobber (reg:CC CC_REGNUM))]
8936 /* If we have an operation where (op x 0) is the identity operation and
8937 the conditional operator is LT or GE and we are comparing against zero and
8938 everything is in registers then we can do this in two instructions. */
8939 if (operands[3] == const0_rtx
8940 && GET_CODE (operands[7]) != AND
8941 && GET_CODE (operands[5]) == REG
8942 && GET_CODE (operands[1]) == REG
8943 && REGNO (operands[1]) == REGNO (operands[4])
8944 && REGNO (operands[4]) != REGNO (operands[0]))
8946 if (GET_CODE (operands[6]) == LT)
8947 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8948 else if (GET_CODE (operands[6]) == GE)
8949 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8951 if (GET_CODE (operands[3]) == CONST_INT
8952 && !const_ok_for_arm (INTVAL (operands[3])))
8953 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8955 output_asm_insn (\"cmp\\t%2, %3\", operands);
8956 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8957 if (which_alternative != 0)
8958 return \"mov%D6\\t%0, %1\";
8961 [(set_attr "conds" "clob")
8962 (set_attr "length" "8,12")]
8965 (define_insn "*if_arith_move"
8966 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8967 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8968 [(match_operand 6 "cc_register" "") (const_int 0)])
8969 (match_operator:SI 5 "shiftable_operator"
8970 [(match_operand:SI 2 "s_register_operand" "r,r")
8971 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8972 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8976 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8977 [(set_attr "conds" "use")
8978 (set_attr "length" "4,8")
8979 (set_attr "type" "*,*")]
8982 (define_insn "*ifcompare_move_arith"
8983 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8984 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8985 [(match_operand:SI 4 "s_register_operand" "r,r")
8986 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8987 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8988 (match_operator:SI 7 "shiftable_operator"
8989 [(match_operand:SI 2 "s_register_operand" "r,r")
8990 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8991 (clobber (reg:CC CC_REGNUM))]
8994 /* If we have an operation where (op x 0) is the identity operation and
8995 the conditional operator is LT or GE and we are comparing against zero and
8996 everything is in registers then we can do this in two instructions */
8997 if (operands[5] == const0_rtx
8998 && GET_CODE (operands[7]) != AND
8999 && GET_CODE (operands[3]) == REG
9000 && GET_CODE (operands[1]) == REG
9001 && REGNO (operands[1]) == REGNO (operands[2])
9002 && REGNO (operands[2]) != REGNO (operands[0]))
9004 if (GET_CODE (operands[6]) == GE)
9005 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9006 else if (GET_CODE (operands[6]) == LT)
9007 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9010 if (GET_CODE (operands[5]) == CONST_INT
9011 && !const_ok_for_arm (INTVAL (operands[5])))
9012 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9014 output_asm_insn (\"cmp\\t%4, %5\", operands);
9016 if (which_alternative != 0)
9017 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9018 return \"%I7%D6\\t%0, %2, %3\";
9020 [(set_attr "conds" "clob")
9021 (set_attr "length" "8,12")]
9024 (define_insn "*if_move_arith"
9025 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9027 (match_operator 4 "arm_comparison_operator"
9028 [(match_operand 6 "cc_register" "") (const_int 0)])
9029 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9030 (match_operator:SI 5 "shiftable_operator"
9031 [(match_operand:SI 2 "s_register_operand" "r,r")
9032 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9036 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9037 [(set_attr "conds" "use")
9038 (set_attr "length" "4,8")
9039 (set_attr "type" "*,*")]
9042 (define_insn "*ifcompare_move_not"
9043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9045 (match_operator 5 "arm_comparison_operator"
9046 [(match_operand:SI 3 "s_register_operand" "r,r")
9047 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9050 (match_operand:SI 2 "s_register_operand" "r,r"))))
9051 (clobber (reg:CC CC_REGNUM))]
9054 [(set_attr "conds" "clob")
9055 (set_attr "length" "8,12")]
9058 (define_insn "*if_move_not"
9059 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9061 (match_operator 4 "arm_comparison_operator"
9062 [(match_operand 3 "cc_register" "") (const_int 0)])
9063 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9064 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9068 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9069 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9070 [(set_attr "conds" "use")
9071 (set_attr "length" "4,8,8")]
9074 (define_insn "*ifcompare_not_move"
9075 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9077 (match_operator 5 "arm_comparison_operator"
9078 [(match_operand:SI 3 "s_register_operand" "r,r")
9079 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9081 (match_operand:SI 2 "s_register_operand" "r,r"))
9082 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9083 (clobber (reg:CC CC_REGNUM))]
9086 [(set_attr "conds" "clob")
9087 (set_attr "length" "8,12")]
9090 (define_insn "*if_not_move"
9091 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9093 (match_operator 4 "arm_comparison_operator"
9094 [(match_operand 3 "cc_register" "") (const_int 0)])
9095 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9096 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9100 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9101 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9102 [(set_attr "conds" "use")
9103 (set_attr "length" "4,8,8")]
9106 (define_insn "*ifcompare_shift_move"
9107 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9109 (match_operator 6 "arm_comparison_operator"
9110 [(match_operand:SI 4 "s_register_operand" "r,r")
9111 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9112 (match_operator:SI 7 "shift_operator"
9113 [(match_operand:SI 2 "s_register_operand" "r,r")
9114 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9115 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9116 (clobber (reg:CC CC_REGNUM))]
9119 [(set_attr "conds" "clob")
9120 (set_attr "length" "8,12")]
9123 (define_insn "*if_shift_move"
9124 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9126 (match_operator 5 "arm_comparison_operator"
9127 [(match_operand 6 "cc_register" "") (const_int 0)])
9128 (match_operator:SI 4 "shift_operator"
9129 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9130 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9131 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9135 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9136 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9137 [(set_attr "conds" "use")
9138 (set_attr "shift" "2")
9139 (set_attr "length" "4,8,8")
9140 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9141 (const_string "alu_shift")
9142 (const_string "alu_shift_reg")))]
9145 (define_insn "*ifcompare_move_shift"
9146 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9148 (match_operator 6 "arm_comparison_operator"
9149 [(match_operand:SI 4 "s_register_operand" "r,r")
9150 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9151 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9152 (match_operator:SI 7 "shift_operator"
9153 [(match_operand:SI 2 "s_register_operand" "r,r")
9154 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9155 (clobber (reg:CC CC_REGNUM))]
9158 [(set_attr "conds" "clob")
9159 (set_attr "length" "8,12")]
9162 (define_insn "*if_move_shift"
9163 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9165 (match_operator 5 "arm_comparison_operator"
9166 [(match_operand 6 "cc_register" "") (const_int 0)])
9167 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9168 (match_operator:SI 4 "shift_operator"
9169 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9170 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9174 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9175 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9176 [(set_attr "conds" "use")
9177 (set_attr "shift" "2")
9178 (set_attr "length" "4,8,8")
9179 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9180 (const_string "alu_shift")
9181 (const_string "alu_shift_reg")))]
9184 (define_insn "*ifcompare_shift_shift"
9185 [(set (match_operand:SI 0 "s_register_operand" "=r")
9187 (match_operator 7 "arm_comparison_operator"
9188 [(match_operand:SI 5 "s_register_operand" "r")
9189 (match_operand:SI 6 "arm_add_operand" "rIL")])
9190 (match_operator:SI 8 "shift_operator"
9191 [(match_operand:SI 1 "s_register_operand" "r")
9192 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9193 (match_operator:SI 9 "shift_operator"
9194 [(match_operand:SI 3 "s_register_operand" "r")
9195 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9196 (clobber (reg:CC CC_REGNUM))]
9199 [(set_attr "conds" "clob")
9200 (set_attr "length" "12")]
9203 (define_insn "*if_shift_shift"
9204 [(set (match_operand:SI 0 "s_register_operand" "=r")
9206 (match_operator 5 "arm_comparison_operator"
9207 [(match_operand 8 "cc_register" "") (const_int 0)])
9208 (match_operator:SI 6 "shift_operator"
9209 [(match_operand:SI 1 "s_register_operand" "r")
9210 (match_operand:SI 2 "arm_rhs_operand" "rM")])
9211 (match_operator:SI 7 "shift_operator"
9212 [(match_operand:SI 3 "s_register_operand" "r")
9213 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9215 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9216 [(set_attr "conds" "use")
9217 (set_attr "shift" "1")
9218 (set_attr "length" "8")
9219 (set (attr "type") (if_then_else
9220 (and (match_operand 2 "const_int_operand" "")
9221 (match_operand 4 "const_int_operand" ""))
9222 (const_string "alu_shift")
9223 (const_string "alu_shift_reg")))]
9226 (define_insn "*ifcompare_not_arith"
9227 [(set (match_operand:SI 0 "s_register_operand" "=r")
9229 (match_operator 6 "arm_comparison_operator"
9230 [(match_operand:SI 4 "s_register_operand" "r")
9231 (match_operand:SI 5 "arm_add_operand" "rIL")])
9232 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9233 (match_operator:SI 7 "shiftable_operator"
9234 [(match_operand:SI 2 "s_register_operand" "r")
9235 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9236 (clobber (reg:CC CC_REGNUM))]
9239 [(set_attr "conds" "clob")
9240 (set_attr "length" "12")]
9243 (define_insn "*if_not_arith"
9244 [(set (match_operand:SI 0 "s_register_operand" "=r")
9246 (match_operator 5 "arm_comparison_operator"
9247 [(match_operand 4 "cc_register" "") (const_int 0)])
9248 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9249 (match_operator:SI 6 "shiftable_operator"
9250 [(match_operand:SI 2 "s_register_operand" "r")
9251 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9253 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9254 [(set_attr "conds" "use")
9255 (set_attr "length" "8")]
9258 (define_insn "*ifcompare_arith_not"
9259 [(set (match_operand:SI 0 "s_register_operand" "=r")
9261 (match_operator 6 "arm_comparison_operator"
9262 [(match_operand:SI 4 "s_register_operand" "r")
9263 (match_operand:SI 5 "arm_add_operand" "rIL")])
9264 (match_operator:SI 7 "shiftable_operator"
9265 [(match_operand:SI 2 "s_register_operand" "r")
9266 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9267 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9268 (clobber (reg:CC CC_REGNUM))]
9271 [(set_attr "conds" "clob")
9272 (set_attr "length" "12")]
9275 (define_insn "*if_arith_not"
9276 [(set (match_operand:SI 0 "s_register_operand" "=r")
9278 (match_operator 5 "arm_comparison_operator"
9279 [(match_operand 4 "cc_register" "") (const_int 0)])
9280 (match_operator:SI 6 "shiftable_operator"
9281 [(match_operand:SI 2 "s_register_operand" "r")
9282 (match_operand:SI 3 "arm_rhs_operand" "rI")])
9283 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9285 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9286 [(set_attr "conds" "use")
9287 (set_attr "length" "8")]
9290 (define_insn "*ifcompare_neg_move"
9291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9293 (match_operator 5 "arm_comparison_operator"
9294 [(match_operand:SI 3 "s_register_operand" "r,r")
9295 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9296 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9297 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9298 (clobber (reg:CC CC_REGNUM))]
9301 [(set_attr "conds" "clob")
9302 (set_attr "length" "8,12")]
9305 (define_insn "*if_neg_move"
9306 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9308 (match_operator 4 "arm_comparison_operator"
9309 [(match_operand 3 "cc_register" "") (const_int 0)])
9310 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9311 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9315 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9316 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9317 [(set_attr "conds" "use")
9318 (set_attr "length" "4,8,8")]
9321 (define_insn "*ifcompare_move_neg"
9322 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9324 (match_operator 5 "arm_comparison_operator"
9325 [(match_operand:SI 3 "s_register_operand" "r,r")
9326 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9327 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9328 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9329 (clobber (reg:CC CC_REGNUM))]
9332 [(set_attr "conds" "clob")
9333 (set_attr "length" "8,12")]
9336 (define_insn "*if_move_neg"
9337 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9339 (match_operator 4 "arm_comparison_operator"
9340 [(match_operand 3 "cc_register" "") (const_int 0)])
9341 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9342 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9346 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9347 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9348 [(set_attr "conds" "use")
9349 (set_attr "length" "4,8,8")]
9352 (define_insn "*arith_adjacentmem"
9353 [(set (match_operand:SI 0 "s_register_operand" "=r")
9354 (match_operator:SI 1 "shiftable_operator"
9355 [(match_operand:SI 2 "memory_operand" "m")
9356 (match_operand:SI 3 "memory_operand" "m")]))
9357 (clobber (match_scratch:SI 4 "=r"))]
9358 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9364 HOST_WIDE_INT val1 = 0, val2 = 0;
9366 if (REGNO (operands[0]) > REGNO (operands[4]))
9368 ldm[1] = operands[4];
9369 ldm[2] = operands[0];
9373 ldm[1] = operands[0];
9374 ldm[2] = operands[4];
9377 base_reg = XEXP (operands[2], 0);
9379 if (!REG_P (base_reg))
9381 val1 = INTVAL (XEXP (base_reg, 1));
9382 base_reg = XEXP (base_reg, 0);
9385 if (!REG_P (XEXP (operands[3], 0)))
9386 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9388 arith[0] = operands[0];
9389 arith[3] = operands[1];
9403 if (val1 !=0 && val2 != 0)
9405 if (val1 == 4 || val2 == 4)
9406 /* Other val must be 8, since we know they are adjacent and neither
9408 output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9413 ldm[0] = ops[0] = operands[4];
9415 ops[2] = GEN_INT (val1);
9416 output_add_immediate (ops);
9418 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9420 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9426 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9428 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9433 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9435 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9437 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9440 [(set_attr "length" "12")
9441 (set_attr "predicable" "yes")
9442 (set_attr "type" "load1")]
9445 ; This pattern is never tried by combine, so do it as a peephole
9448 [(set (match_operand:SI 0 "arm_general_register_operand" "")
9449 (match_operand:SI 1 "arm_general_register_operand" ""))
9450 (set (reg:CC CC_REGNUM)
9451 (compare:CC (match_dup 1) (const_int 0)))]
9453 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9454 (set (match_dup 0) (match_dup 1))])]
9458 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9459 ; reversed, check that the memory references aren't volatile.
9462 [(set (match_operand:SI 0 "s_register_operand" "=r")
9463 (match_operand:SI 4 "memory_operand" "m"))
9464 (set (match_operand:SI 1 "s_register_operand" "=r")
9465 (match_operand:SI 5 "memory_operand" "m"))
9466 (set (match_operand:SI 2 "s_register_operand" "=r")
9467 (match_operand:SI 6 "memory_operand" "m"))
9468 (set (match_operand:SI 3 "s_register_operand" "=r")
9469 (match_operand:SI 7 "memory_operand" "m"))]
9470 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9472 return emit_ldm_seq (operands, 4);
9477 [(set (match_operand:SI 0 "s_register_operand" "=r")
9478 (match_operand:SI 3 "memory_operand" "m"))
9479 (set (match_operand:SI 1 "s_register_operand" "=r")
9480 (match_operand:SI 4 "memory_operand" "m"))
9481 (set (match_operand:SI 2 "s_register_operand" "=r")
9482 (match_operand:SI 5 "memory_operand" "m"))]
9483 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9485 return emit_ldm_seq (operands, 3);
9490 [(set (match_operand:SI 0 "s_register_operand" "=r")
9491 (match_operand:SI 2 "memory_operand" "m"))
9492 (set (match_operand:SI 1 "s_register_operand" "=r")
9493 (match_operand:SI 3 "memory_operand" "m"))]
9494 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9496 return emit_ldm_seq (operands, 2);
9501 [(set (match_operand:SI 4 "memory_operand" "=m")
9502 (match_operand:SI 0 "s_register_operand" "r"))
9503 (set (match_operand:SI 5 "memory_operand" "=m")
9504 (match_operand:SI 1 "s_register_operand" "r"))
9505 (set (match_operand:SI 6 "memory_operand" "=m")
9506 (match_operand:SI 2 "s_register_operand" "r"))
9507 (set (match_operand:SI 7 "memory_operand" "=m")
9508 (match_operand:SI 3 "s_register_operand" "r"))]
9509 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9511 return emit_stm_seq (operands, 4);
9516 [(set (match_operand:SI 3 "memory_operand" "=m")
9517 (match_operand:SI 0 "s_register_operand" "r"))
9518 (set (match_operand:SI 4 "memory_operand" "=m")
9519 (match_operand:SI 1 "s_register_operand" "r"))
9520 (set (match_operand:SI 5 "memory_operand" "=m")
9521 (match_operand:SI 2 "s_register_operand" "r"))]
9522 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9524 return emit_stm_seq (operands, 3);
9529 [(set (match_operand:SI 2 "memory_operand" "=m")
9530 (match_operand:SI 0 "s_register_operand" "r"))
9531 (set (match_operand:SI 3 "memory_operand" "=m")
9532 (match_operand:SI 1 "s_register_operand" "r"))]
9533 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9535 return emit_stm_seq (operands, 2);
9540 [(set (match_operand:SI 0 "s_register_operand" "")
9541 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9543 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9544 [(match_operand:SI 3 "s_register_operand" "")
9545 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9546 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9548 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9549 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9554 ;; This split can be used because CC_Z mode implies that the following
9555 ;; branch will be an equality, or an unsigned inequality, so the sign
9556 ;; extension is not needed.
9559 [(set (reg:CC_Z CC_REGNUM)
9561 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9563 (match_operand 1 "const_int_operand" "")))
9564 (clobber (match_scratch:SI 2 ""))]
9566 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9567 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9568 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9569 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9571 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9575 (define_expand "prologue"
9576 [(clobber (const_int 0))]
9579 arm_expand_prologue ();
9581 thumb_expand_prologue ();
9586 (define_expand "epilogue"
9587 [(clobber (const_int 0))]
9590 if (current_function_calls_eh_return)
9591 emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9593 thumb_expand_epilogue ();
9594 else if (USE_RETURN_INSN (FALSE))
9596 emit_jump_insn (gen_return ());
9599 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9601 gen_rtx_RETURN (VOIDmode)),
9607 ;; Note - although unspec_volatile's USE all hard registers,
9608 ;; USEs are ignored after relaod has completed. Thus we need
9609 ;; to add an unspec of the link register to ensure that flow
9610 ;; does not think that it is unused by the sibcall branch that
9611 ;; will replace the standard function epilogue.
9612 (define_insn "sibcall_epilogue"
9613 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9614 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9617 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9618 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9619 return arm_output_epilogue (next_nonnote_insn (insn));
9621 ;; Length is absolute worst case
9622 [(set_attr "length" "44")
9623 (set_attr "type" "block")
9624 ;; We don't clobber the conditions, but the potential length of this
9625 ;; operation is sufficient to make conditionalizing the sequence
9626 ;; unlikely to be profitable.
9627 (set_attr "conds" "clob")]
9630 (define_insn "*epilogue_insns"
9631 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9635 return arm_output_epilogue (NULL);
9636 else /* TARGET_THUMB */
9637 return thumb_unexpanded_epilogue ();
9639 ; Length is absolute worst case
9640 [(set_attr "length" "44")
9641 (set_attr "type" "block")
9642 ;; We don't clobber the conditions, but the potential length of this
9643 ;; operation is sufficient to make conditionalizing the sequence
9644 ;; unlikely to be profitable.
9645 (set_attr "conds" "clob")]
9648 (define_expand "eh_epilogue"
9649 [(use (match_operand:SI 0 "register_operand" ""))
9650 (use (match_operand:SI 1 "register_operand" ""))
9651 (use (match_operand:SI 2 "register_operand" ""))]
9655 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9656 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9658 rtx ra = gen_rtx_REG (Pmode, 2);
9660 emit_move_insn (ra, operands[2]);
9663 /* This is a hack -- we may have crystalized the function type too
9665 cfun->machine->func_type = 0;
9669 ;; This split is only used during output to reduce the number of patterns
9670 ;; that need assembler instructions adding to them. We allowed the setting
9671 ;; of the conditions to be implicit during rtl generation so that
9672 ;; the conditional compare patterns would work. However this conflicts to
9673 ;; some extent with the conditional data operations, so we have to split them
9677 [(set (match_operand:SI 0 "s_register_operand" "")
9678 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679 [(match_operand 2 "" "") (match_operand 3 "" "")])
9681 (match_operand 4 "" "")))
9682 (clobber (reg:CC CC_REGNUM))]
9683 "TARGET_ARM && reload_completed"
9684 [(set (match_dup 5) (match_dup 6))
9685 (cond_exec (match_dup 7)
9686 (set (match_dup 0) (match_dup 4)))]
9689 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690 operands[2], operands[3]);
9691 enum rtx_code rc = GET_CODE (operands[1]);
9693 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9694 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9695 if (mode == CCFPmode || mode == CCFPEmode)
9696 rc = reverse_condition_maybe_unordered (rc);
9698 rc = reverse_condition (rc);
9700 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9705 [(set (match_operand:SI 0 "s_register_operand" "")
9706 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9707 [(match_operand 2 "" "") (match_operand 3 "" "")])
9708 (match_operand 4 "" "")
9710 (clobber (reg:CC CC_REGNUM))]
9711 "TARGET_ARM && reload_completed"
9712 [(set (match_dup 5) (match_dup 6))
9713 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9714 (set (match_dup 0) (match_dup 4)))]
9717 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9718 operands[2], operands[3]);
9720 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9721 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9726 [(set (match_operand:SI 0 "s_register_operand" "")
9727 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9728 [(match_operand 2 "" "") (match_operand 3 "" "")])
9729 (match_operand 4 "" "")
9730 (match_operand 5 "" "")))
9731 (clobber (reg:CC CC_REGNUM))]
9732 "TARGET_ARM && reload_completed"
9733 [(set (match_dup 6) (match_dup 7))
9734 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9735 (set (match_dup 0) (match_dup 4)))
9736 (cond_exec (match_dup 8)
9737 (set (match_dup 0) (match_dup 5)))]
9740 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9741 operands[2], operands[3]);
9742 enum rtx_code rc = GET_CODE (operands[1]);
9744 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9745 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9746 if (mode == CCFPmode || mode == CCFPEmode)
9747 rc = reverse_condition_maybe_unordered (rc);
9749 rc = reverse_condition (rc);
9751 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9756 [(set (match_operand:SI 0 "s_register_operand" "")
9757 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9758 [(match_operand:SI 2 "s_register_operand" "")
9759 (match_operand:SI 3 "arm_add_operand" "")])
9760 (match_operand:SI 4 "arm_rhs_operand" "")
9762 (match_operand:SI 5 "s_register_operand" ""))))
9763 (clobber (reg:CC CC_REGNUM))]
9764 "TARGET_ARM && reload_completed"
9765 [(set (match_dup 6) (match_dup 7))
9766 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9767 (set (match_dup 0) (match_dup 4)))
9768 (cond_exec (match_dup 8)
9769 (set (match_dup 0) (not:SI (match_dup 5))))]
9772 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9773 operands[2], operands[3]);
9774 enum rtx_code rc = GET_CODE (operands[1]);
9776 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9777 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9778 if (mode == CCFPmode || mode == CCFPEmode)
9779 rc = reverse_condition_maybe_unordered (rc);
9781 rc = reverse_condition (rc);
9783 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9787 (define_insn "*cond_move_not"
9788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9789 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9790 [(match_operand 3 "cc_register" "") (const_int 0)])
9791 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9793 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9797 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9798 [(set_attr "conds" "use")
9799 (set_attr "length" "4,8")]
9802 ;; The next two patterns occur when an AND operation is followed by a
9803 ;; scc insn sequence
9805 (define_insn "*sign_extract_onebit"
9806 [(set (match_operand:SI 0 "s_register_operand" "=r")
9807 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9809 (match_operand:SI 2 "const_int_operand" "n")))
9810 (clobber (reg:CC CC_REGNUM))]
9813 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9814 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9815 return \"mvnne\\t%0, #0\";
9817 [(set_attr "conds" "clob")
9818 (set_attr "length" "8")]
9821 (define_insn "*not_signextract_onebit"
9822 [(set (match_operand:SI 0 "s_register_operand" "=r")
9824 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9826 (match_operand:SI 2 "const_int_operand" "n"))))
9827 (clobber (reg:CC CC_REGNUM))]
9830 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9831 output_asm_insn (\"tst\\t%1, %2\", operands);
9832 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9833 return \"movne\\t%0, #0\";
9835 [(set_attr "conds" "clob")
9836 (set_attr "length" "12")]
9839 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9840 ;; expressions. For simplicity, the first register is also in the unspec
9842 (define_insn "*push_multi"
9843 [(match_parallel 2 "multi_register_push"
9844 [(set (match_operand:BLK 0 "memory_operand" "=m")
9845 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9846 UNSPEC_PUSH_MULT))])]
9850 int num_saves = XVECLEN (operands[2], 0);
9852 /* For the StrongARM at least it is faster to
9853 use STR to store only a single register. */
9855 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9861 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9863 for (i = 1; i < num_saves; i++)
9865 strcat (pattern, \", %|\");
9867 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9870 strcat (pattern, \"}\");
9871 output_asm_insn (pattern, operands);
9876 [(set_attr "type" "store4")]
9879 (define_insn "stack_tie"
9880 [(set (mem:BLK (scratch))
9881 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9882 (match_operand:SI 1 "s_register_operand" "r")]
9886 [(set_attr "length" "0")]
9889 ;; Similarly for the floating point registers
9890 (define_insn "*push_fp_multi"
9891 [(match_parallel 2 "multi_register_push"
9892 [(set (match_operand:BLK 0 "memory_operand" "=m")
9893 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9894 UNSPEC_PUSH_MULT))])]
9895 "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9900 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9901 output_asm_insn (pattern, operands);
9904 [(set_attr "type" "f_store")]
9907 ;; Special patterns for dealing with the constant pool
9909 (define_insn "align_4"
9910 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9913 assemble_align (32);
9918 (define_insn "align_8"
9919 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9922 assemble_align (64);
9927 (define_insn "consttable_end"
9928 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9931 making_const_table = FALSE;
9936 (define_insn "consttable_1"
9937 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9940 making_const_table = TRUE;
9941 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9945 [(set_attr "length" "4")]
9948 (define_insn "consttable_2"
9949 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9952 making_const_table = TRUE;
9953 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9957 [(set_attr "length" "4")]
9960 (define_insn "consttable_4"
9961 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9965 making_const_table = TRUE;
9966 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9971 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9972 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9976 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9981 [(set_attr "length" "4")]
9984 (define_insn "consttable_8"
9985 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9989 making_const_table = TRUE;
9990 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9995 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9996 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10000 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10005 [(set_attr "length" "8")]
10008 ;; Miscellaneous Thumb patterns
10010 (define_expand "tablejump"
10011 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10012 (use (label_ref (match_operand 1 "" "")))])]
10017 /* Hopefully, CSE will eliminate this copy. */
10018 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10019 rtx reg2 = gen_reg_rtx (SImode);
10021 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10022 operands[0] = reg2;
10027 ;; NB never uses BX.
10028 (define_insn "*thumb_tablejump"
10029 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10030 (use (label_ref (match_operand 1 "" "")))]
10033 [(set_attr "length" "2")]
10036 ;; V5 Instructions,
10038 (define_insn "clzsi2"
10039 [(set (match_operand:SI 0 "s_register_operand" "=r")
10040 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10041 "TARGET_ARM && arm_arch5"
10043 [(set_attr "predicable" "yes")])
10045 (define_expand "ffssi2"
10046 [(set (match_operand:SI 0 "s_register_operand" "")
10047 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10048 "TARGET_ARM && arm_arch5"
10053 t1 = gen_reg_rtx (SImode);
10054 t2 = gen_reg_rtx (SImode);
10055 t3 = gen_reg_rtx (SImode);
10057 emit_insn (gen_negsi2 (t1, operands[1]));
10058 emit_insn (gen_andsi3 (t2, operands[1], t1));
10059 emit_insn (gen_clzsi2 (t3, t2));
10060 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10065 (define_expand "ctzsi2"
10066 [(set (match_operand:SI 0 "s_register_operand" "")
10067 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10068 "TARGET_ARM && arm_arch5"
10073 t1 = gen_reg_rtx (SImode);
10074 t2 = gen_reg_rtx (SImode);
10075 t3 = gen_reg_rtx (SImode);
10077 emit_insn (gen_negsi2 (t1, operands[1]));
10078 emit_insn (gen_andsi3 (t2, operands[1], t1));
10079 emit_insn (gen_clzsi2 (t3, t2));
10080 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10085 ;; V5E instructions.
10087 (define_insn "prefetch"
10088 [(prefetch (match_operand:SI 0 "address_operand" "p")
10089 (match_operand:SI 1 "" "")
10090 (match_operand:SI 2 "" ""))]
10091 "TARGET_ARM && arm_arch5e"
10094 ;; General predication pattern
10097 [(match_operator 0 "arm_comparison_operator"
10098 [(match_operand 1 "cc_register" "")
10104 (define_insn "prologue_use"
10105 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10107 "%@ %0 needed for prologue"
10111 ;; Patterns for exception handling
10113 (define_expand "eh_return"
10114 [(use (match_operand 0 "general_operand" ""))]
10119 emit_insn (gen_arm_eh_return (operands[0]));
10121 emit_insn (gen_thumb_eh_return (operands[0]));
10126 ;; We can't expand this before we know where the link register is stored.
10127 (define_insn_and_split "arm_eh_return"
10128 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10130 (clobber (match_scratch:SI 1 "=&r"))]
10133 "&& reload_completed"
10137 arm_set_return_address (operands[0], operands[1]);
10142 (define_insn_and_split "thumb_eh_return"
10143 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10145 (clobber (match_scratch:SI 1 "=&l"))]
10148 "&& reload_completed"
10152 thumb_set_return_address (operands[0], operands[1]);
10160 (define_insn "load_tp_hard"
10161 [(set (match_operand:SI 0 "register_operand" "=r")
10162 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10164 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10165 [(set_attr "predicable" "yes")]
10168 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10169 (define_insn "load_tp_soft"
10170 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10171 (clobber (reg:SI LR_REGNUM))
10172 (clobber (reg:SI IP_REGNUM))
10173 (clobber (reg:CC CC_REGNUM))]
10175 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10176 [(set_attr "conds" "clob")]
10179 ;; Load the FPA co-processor patterns
10181 ;; Load the Maverick co-processor patterns
10182 (include "cirrus.md")
10183 ;; Load the Intel Wireless Multimedia Extension patterns
10184 (include "iwmmxt.md")
10185 ;; Load the VFP co-processor patterns